我遇到创建套接字和从Android应用程序发送消息到覆盆子pi的问题。我在以下站点中使用了这个示例:http://android-er.blogspot.nl/2016/05/android-client-example-2-communicate.html,这是为了理解套接字是如何工作的。但是当我使用AsyncTask时,我仍然得到一个android.os.NetworkOnMainThreadException。这是我的MainActivity:
public class MainActivity extends AppCompatActivity {
EditText editTextAddress, editTextPort, editTextMsg;
Button buttonConnect, buttonDisconnect, buttonSend;
TextView textViewState, textViewRx;
ClientHandler clientHandler;
ClientThread clientThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextAddress = (EditText) findViewById(R.id.address);
editTextPort = (EditText) findViewById(R.id.port);
editTextMsg = (EditText) findViewById(R.id.msgtosend);
buttonConnect = (Button) findViewById(R.id.connect);
buttonDisconnect = (Button) findViewById(R.id.disconnect);
buttonSend = (Button)findViewById(R.id.send);
textViewState = (TextView)findViewById(R.id.state);
textViewRx = (TextView)findViewById(R.id.received);
buttonDisconnect.setEnabled(false);
buttonSend.setEnabled(false);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonDisconnect.setOnClickListener(buttonDisConnectOnClickListener);
buttonSend.setOnClickListener(buttonSendOnClickListener);
clientHandler = new ClientHandler(this);
}
View.OnClickListener buttonConnectOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View arg0) {
MainActivity.this.startService(new Intent(MainActivity.this,
ClientThread.class));
clientThread = new ClientThread(
editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()),
clientHandler);
clientThread.execute();
buttonConnect.setEnabled(false);
buttonDisconnect.setEnabled(true);
buttonSend.setEnabled(true);
}
};
View.OnClickListener buttonDisConnectOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(clientThread != null){
clientThread.setRunning(false);
}
}
};
String msgToSend;
View.OnClickListener buttonSendOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(clientThread != null){
msgToSend = editTextMsg.getText().toString();
clientThread.txMsg(msgToSend);
}
}
};
private void updateState(String state){
textViewState.setText(state);
}
private void updateRxMsg(String rxmsg){
textViewRx.append(rxmsg + "\n");
}
private void clientEnd(){
clientThread = null;
textViewState.setText("clientEnd()");
buttonConnect.setEnabled(true);
buttonDisconnect.setEnabled(false);
buttonSend.setEnabled(false);
}
public static class ClientHandler extends Handler {
public static final int UPDATE_STATE = 0;
public static final int UPDATE_MSG = 1;
public static final int UPDATE_END = 2;
private MainActivity parent;
public ClientHandler(MainActivity parent) {
super();
this.parent = parent;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_STATE:
parent.updateState((String)msg.obj);
break;
case UPDATE_MSG:
parent.updateRxMsg((String)msg.obj);
break;
case UPDATE_END:
parent.clientEnd();
break;
default:
super.handleMessage(msg);
}
}
}
}
这是ClientThread.java代码:
public class ClientThread extends AsyncTask<Void, Void, Void>{
String dstAddress;
int dstPort;
private boolean running;
MainActivity.ClientHandler handler;
Socket socket;
PrintWriter printWriter;
BufferedReader bufferedReader;
public ClientThread(String addr, int port, MainActivity.ClientHandler handler) {
super();
dstAddress = addr;
dstPort = port;
this.handler = handler;
}
public void setRunning(boolean running){
this.running = running;
}
private void sendState(String state){
handler.sendMessage(
Message.obtain(handler,
MainActivity.ClientHandler.UPDATE_STATE, state));
}
public void txMsg(String msgToSend){
if(printWriter != null){
printWriter.println(msgToSend);
}
}
@Override
protected Void doInBackground(Void... arg0) {
System.out.println("In doinbackground");
sendState("connecting...");
running = true;
try {
socket = new Socket(dstAddress, dstPort);
sendState("connected");
OutputStream outputStream = socket.getOutputStream();
printWriter = new PrintWriter(outputStream, true);
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
while (running) {
//bufferedReader block the code
String line = bufferedReader.readLine();
if (line != null) {
handler.sendMessage(
Message.obtain(handler,
MainActivity.ClientHandler.UPDATE_MSG, line));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (printWriter != null) {
printWriter.close();
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
handler.sendEmptyMessage(MainActivity.ClientHandler.UPDATE_END);
return null;
}
}
这是我得到的错误:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.zerocj.projectsocked, PID: 2415
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:157)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at java.io.PrintWriter.newLine(PrintWriter.java:482)
at java.io.PrintWriter.println(PrintWriter.java:629)
at java.io.PrintWriter.println(PrintWriter.java:740)
at com.example.zerocj.projectsocked.ClientThread.txMsg(ClientThread.java:47)
at com.example.zerocj.projectsocked.MainActivity$3.onClick(MainActivity.java:85)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22260)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
答案 0 :(得分:0)
您从在UI线程上运行的点击侦听器调用您的txMsg()
方法。这种方法似乎是写入连接到套接字的Writer
。
如果你想在后台线程和UI线程之间来回交换消息,可能更好的想法AsyncTask
将Thread
与Looper
和处理程序一起传递消息从一个线程到另一个线程。
答案 1 :(得分:-1)
请检查堆栈跟踪。它表示在代码中使用严格模式
int SDK_INT = android.os.Build.VERSION.SDK_INT;
if (SDK_INT > 8)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
// Where you get exception write that code inside this.
}
谢谢希望这对你有所帮助。