你好,伙计们,
我想为我的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):线程启动
此外,当我尝试调用“connection.doInBackground()”而不是“connection.execute()”时(我知道这根本没有任何意义),我得到一个“networkonmainthreadexception” - 但我以为我已经用AsyncTask解决了这个问题。嗯,我是Android的新手,但我已经搜索了很多,不知道我是不是那么傻但现在我放弃了,所以我在这里注册了我。也许有人可以告诉我,我做错了什么..
(不确定我是否需要发布我的MainActivity类......)
谢谢! :)
编辑:谢谢大家的所有这些答案,知道我有点过度扩张,只是给我一些时间来尝试/了解你的所有提示,谢谢!
答案 0 :(得分:1)
在AsyncTask的实现上有很多概念上的错误,甚至很难弄清楚为什么或可能出错的地方,所以我会在这里写一个食谱和一个关于如何写一个AsyncTask然后你应用它们,如果你仍然遇到错误,那么你再问:
<强>提示:强>
NullPointerException
doInBackground()
,execute()
调用将创建一个新线程并为您调用(这就是AsyncTask用于的原因)<强>配方强>
// 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?
}
}
}
答案 1 :(得分:0)
您是否在清单中添加了所需的权限?
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
答案 2 :(得分:0)
您正试图使用MainActivity
doInBackground()
中的onPostExecute()
,这需要位于UI
线程和doInBackground()
线程上运行的{{1}}方法中}方法没有。
4个步骤
执行异步任务时,任务将经历4个步骤:
onPreExecute(),在执行任务之前在UI线程上调用。 此步骤通常用于设置任务,例如通过显示 用户界面中的进度条。
doInBackground(Params ...),在后台线程上调用 在onPreExecute()完成执行后立即执行。使用此步骤 执行可能需要很长时间的后台计算。该 异步任务的参数传递给此步骤。该 计算结果必须由此步骤返回并且将是 回到最后一步。这一步也可以使用 publishProgress(Progress ...)发布一个或多个进度单元。 这些值发布在UI线程中 onProgressUpdate(Progress ...)步骤。
onProgressUpdate(Progress ...),在调用后在UI线程上调用 发布进度(进度......)。执行的时间是 未定义。此方法用于显示任何形式的进度 后台计算仍在执行时的用户界面。 例如,它可用于为进度条设置动画或显示登录 文本字段。
onPostExecute(Result),在后台后的UI线程上调用 计算结束。背景计算的结果是 作为参数传递给此步骤。
答案 3 :(得分:0)
如果您需要在主线程(即UI)上运行某些内容,而不是尝试使用AsynTask
在主线程上运行某些内容,则可以从publishProgess()
调用doInBackground(...)
onProgressUpdate(...)
,后者又调用doInBackground
。不要直接致电execute()
,AsyncTask
是启动doInBackground()
的正确方法。返回onPostExecute()
后,将在主线程上自动调用{{1}}。
Android docs on AsyncTask
非常好,并有一个很好的用法示例。
答案 4 :(得分:0)
Exception表示您需要在后台线程上运行网络操作。直接调用doInBackground()只会使所有内容在调用的同一个线程中运行,显然是主调用。因此,您必须使用connection.excute()
生成新的。
但是,您无法从后台线程更新UI元素。要在主线程上执行此操作,您需要为AsyncTask实现onProgressUpdate()
,如下所示:
@Override
protected void onProgressUpdate(String... arg) {
main.addText(arg[0]);
}
现在,将addText()
中doInBackground()
的所有来电替换为publishProgress("whatever");
。不要忘记将异步任务声明更改为AsyncTask<Void, String, Void>
。
当你完成上面的所有内容时,你不需要在doInBackground()
内生成另一个线程,它将在后台线程中执行。
虽然,您当前的代码大致相同,但这将解决混乱(不再是thrd = new Thread(new Runnable() {...
和main.runOnUiThread...
)并可能解决您的问题。