错误:使用asynctask时android.os.NetworkOnMainThreadException

时间:2016-10-31 01:39:34

标签: java android sockets networkonmainthread

我遇到创建套接字和从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)

2 个答案:

答案 0 :(得分:0)

您从在UI线程上运行的点击侦听器调用您的txMsg()方法。这种方法似乎是写入连接到套接字的Writer

如果你想在后台线程和UI线程之间来回交换消息,可能更好的想法AsyncTaskThreadLooper和处理程序一起传递消息从一个线程到另一个线程。

答案 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.
}

谢谢希望这对你有所帮助。