0

大家好,
我想为我的 Android 制作一个聊天客户端。但我就是无法获得任何联系。
好吧,也许你可以帮我一点..
在我的 MainActivity.java 我打电话:

//connect to the server
SocketTask connection = new SocketTask(this); 
connection.execute();

我的 SocketTask.java 如下所示:

package chat.client;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

import android.os.AsyncTask;

public class SocketTask extends AsyncTask<Void, Void, Void>{
    private Socket socket;
    private DataInputStream input;
    protected PrintStream output;
    private MainActivity main;
    private Thread thrd;

    public SocketTask(MainActivity main){
        this.main = main;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            socket = new Socket("192.168.178.23", 1338);
            input = new DataInputStream(socket.getInputStream());
            output = new PrintStream(socket.getOutputStream());

            // submittes the name of the client
            output.println("Mobile");
            output.flush();
            thrd = new Thread(new Runnable() {
                public void run() {
                    while (!Thread.interrupted()) {
                        try {
                            final String data = input.readLine();
                            if (data != null)
                                main.runOnUiThread(new Runnable() {
                                    //new Runnable(){
                                    @Override
                                    public void run() {
                                        if(!data.equals("")){
                                            //main.chatHistory.append(data+"\n");
                                            main.addText(data);
                                        }else{
                                            //chatHistory.append("\n");
                                            main.addText("");
                                        }

                                    }
                                });
                            //};
                        } catch (IOException e) {
                            //chatHistory.append("Verbindung zum Server abgebrochen!");
                            main.addText("Verbindung zum Server abgebrochen!");
                        }
                    }
                }
            });
            thrd.start();
        } catch (Exception e) {
            //chatHistory.append("Es konnte keine Verbindung zum Server aufgebaut werden!");
            main.addText("Es konnte keine Verbindung zum Server aufgebaut werden!"+e);
        }
        return null;
    }
}

但是当我启动它时,我只得到:
02-27 16:32:05.875: E/SensorManager(26146): thread start

此外,当我尝试调用“connection.doInBackground()”而不是“connection.execute()”时(我知道这根本没有任何意义),我得到一个“networkonmainthreadexception” - 但我想我'已经用 AsyncTask 解决了这个问题。好吧,我是 Android 新手,但我已经用谷歌搜索了很多,不知道我是不是那么愚蠢,但现在我放弃了,所以我在这里注册了我。也许你们中的某个人可以告诉我,我做错了什么..

(不确定我是否需要发布我的 MainActivity 类..)
谢谢!:)

编辑:谢谢大家的所有这些答案,知道我有点过分了,给我一些时间来尝试/理解你所有的提示,谢谢!

4

5 回答 5

1

在 AsyncTask 的实现上有很多概念性错误,甚至很难弄清楚为什么会出错,所以我将在这里写一个关于如何编写 AsyncTask 的秘诀和感觉提示然后应用它们,如果仍然出现错误,请再次询问:

尖端:

  • 不要在 AsyncTask 中创建新线程,doInBackground() 已经在后台线程中被调用
  • 不要在 AsyncTask 上调用 runOnUiThread,在 UI 线程上已经调用了 onPostExecute()
  • 如果您的活动暂停(调用 onPause())在您的 AsyncTask 上调用 .pause() ,否则您可能会有一些NullPointerException
  • 不要doInBackground()按照您的建议直接调用,该execute()调用将创建一个新线程并为您调用它(这就是 AsyncTask 的用途)
  • 不要持有活动对象或任何其他持有 AsyncTask 上下文的对象。只需将 AsyncTask 类声明放在 Activity 本身中,出于组织目的,让 doInbackground() 调用不同类中的一个方法进行实际处理。这样,您的 onPostExecute 可以调用 UI 来更新它,但您将数据收集/处理与活动分开

食谱:

// put this class inside your Activity and
// just call a separate class (for organisation),
// or just put the code all in there (for no organisation)
private class SocketTask extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
    // Whatever you do inside here
    // DO NOT create a new thread!
    return APIConnection.callAPI();
}

@Override
protected void onPostExecute(String result) {
    if(result!=null){
    //Update your UI here
    }else{
    // Some error happen?
    }
}
}
于 2013-02-27T16:24:58.100 回答
0

您是否在清单中添加了所需的权限?

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
于 2013-02-27T16:07:50.563 回答
0

您正在尝试与您一起工作,MainActivitydoInBackground()需要在线程onPostExecute()上运行的方法中,而该方法没有。UIdoInBackground()

异步任务

4个步骤

当一个异步任务被执行时,任务会经过 4 个步骤:

onPreExecute(),在任务执行之前在 UI 线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。

doInBackground(Params...),在 onPreExecute() 完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数传递到这一步。计算的结果必须由这一步返回,并将传递回最后一步。此步骤还可以使用 publishProgress(Progress...) 来发布一个或多个进度单位。这些值在 UI 线程上的 onProgressUpdate(Progress...) 步骤中发布。

onProgressUpdate(Progress...),在调用 publishProgress(Progress...) 后在 UI 线程上调用。执行的时间是不确定的。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。例如,它可用于动画进度条或在文本字段中显示日志。

onPostExecute(Result),在后台计算完成后在 UI 线程上调用。后台计算的结果作为参数传递给该步骤。

于 2013-02-27T16:14:40.587 回答
0

AsynTask如果您需要在主线程(即 UI)上运行某些东西,而不是尝试以您的方式在主线程上运行某些东西,您将调用publishProgess()from doInBackground(...),而后者又调用onProgressUpdate(...). 不要doInBackground直接调用,execute()是正确的启动方式AsyncTask。当doInBackground()返回时,onPostExecute()将在主线程上自动调用。

上的Android 文档AsyncTask非常好,并且有一个很好的使用示例。

于 2013-02-27T16:16:19.093 回答
0

异常表示您需要在后台线程上运行网络操作。直接调用 doInBackground() 只会使所有内容都在调用的同一线程中运行,显然是主线程。所以,你必须用connection.excute(). 但是,您不能从后台线程更新 UI 元素。要在主线程上执行此操作,您需要onProgressUpdate()像这样为您的 AsyncTask 实现:

    @Override
    protected void onProgressUpdate(String... arg) {            
        main.addText(arg[0]);
    }

addText()现在,将in的所有调用替换doInBackground()publishProgress("whatever");. 不要忘记将异步任务声明更改为AsyncTask<Void, String, Void>. 完成上述所有操作后,您无需在其中生成另一个线程doInBackground(),它无论如何都会在后台线程中执行。虽然,您当前的代码所做的大致相同,但这将解决混乱(不再是thrd = new Thread(new Runnable() {...and main.runOnUiThread...)并可能解决您的问题。

于 2013-02-27T16:18:01.390 回答