简体   繁体   English

我如何修复致命异常:main android.os.NetworkOnMainThreadException

[英]how do i fix FATAL EXCEPTION:main android.os.NetworkOnMainThreadException

I'm sorry if it's not proper English because I'm using a translator.如果它不是正确的英语,我很抱歉,因为我正在使用翻译器。

I downloaded a program from github that can control the mouse over the Android phone.我从github下载了一个程序,可以在Android手机上控制鼠标。 There is no problem connecting to the server, But an error occurs when touching the textview to control the mouse.连接服务器没有问题,但是触摸textview控制鼠标时出现错误。

Uniquely, when running a program with a virtual device, no error occurs and works well.独特的是,当使用虚拟设备运行程序时,不会发生错误并且运行良好。

I've seen many examples and answers, but I can't solve them, so I'm re-posting.我看过很多例子和答案,但我无法解决它们,所以我重新发布。 ;_; ;_; I'd really appreciate it if you could tell me which parts to modify.如果您能告诉我要修改哪些部分,我将不胜感激。

public class MainActivity extends ActionBarActivity implements View.OnClickListener {

Context context;
Button playPauseButton;
Button nextButton;
Button previousButton;
TextView mousePad;

private boolean isConnected=false;
private boolean mouseMoved=false;
private Socket socket;
private PrintWriter out;

private float initX =0;
private float initY =0;
private float disX =0;
private float disY =0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    context = this;

    playPauseButton = (Button)findViewById(R.id.playPauseButton);
    nextButton = (Button)findViewById(R.id.nextButton);
    previousButton = (Button)findViewById(R.id.previousButton);


    playPauseButton.setOnClickListener(this);
    nextButton.setOnClickListener(this);
    previousButton.setOnClickListener(this);

    mousePad = (TextView)findViewById(R.id.mousePad);


    mousePad.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(isConnected && out!=null){
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        initX =event.getX();
                        initY =event.getY();
                        mouseMoved=false;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        disX = event.getX()- initX;
                        disY = event.getY()- initY;

                        initX = event.getX();
                        initY = event.getY();
                        if(disX !=0|| disY !=0){
                            out.println(disX +","+ disY);
                        }
                        mouseMoved=true;
                        break;
                    case MotionEvent.ACTION_UP:
                        if(!mouseMoved){
                            out.println(Constants.MOUSE_LEFT_CLICK);
                        }
                }
            }
            return true;
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    if(id == R.id.action_connect) {
        ConnectPhoneTask connectPhoneTask = new ConnectPhoneTask();
        connectPhoneTask.execute(Constants.SERVER_IP); //try to connect to server in another thread
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.playPauseButton:
            if (isConnected && out!=null) {
                out.println(Constants.PLAY);//send "play" to server
            }
            break;
        case R.id.nextButton:
            if (isConnected && out!=null) {
                out.println(Constants.NEXT); //send "next" to server
            }
            break;
        case R.id.previousButton:
            if (isConnected && out!=null) {
                out.println(Constants.PREVIOUS); //send "previous"
            }
            break;
    }

}

@Override
public void onDestroy()
{
    super.onDestroy();
    if(isConnected && out!=null) {
        try {
            out.println("exit"); //tell server to exit
            socket.close(); //close socket
        } catch (IOException e) {
            Log.e("remotedroid", "Error in closing socket", e);
        }
    }
}

public class ConnectPhoneTask extends AsyncTask<String,Void,Boolean> {

    @Override
    protected Boolean doInBackground(String... params) {
        boolean result = true;
        try {
            InetAddress serverAddr = InetAddress.getByName(params[0]);
            socket = new Socket(serverAddr, Constants.SERVER_PORT);//Open socket on server IP and port
        } catch (IOException e) {
            Log.e("remotedroid", "Error while connecting", e);
            result = false;
        }
        return result;
    }

    @Override
    protected void onPostExecute(Boolean result)
    {
        isConnected = result;
        Toast.makeText(context,isConnected?"Connected to server!":"Error while connecting",Toast.LENGTH_LONG).show();
        try {
            if(isConnected) {
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                        .getOutputStream())), true); //create output stream to send data to server
            }
        }catch (IOException e){
            Log.e("remotedroid", "Error while creating OutWriter", e);
            Toast.makeText(context,"Error while connecting",Toast.LENGTH_LONG).show();
        }
    }
}

} }

layout xml :布局xml:

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/playPauseButton"
    android:clickable="true"
    android:background="@android:color/holo_blue_dark"
    android:id="@+id/mousePad"/>

<Button
    android:id="@+id/playPauseButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:text="Button3" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Left"
    android:id="@+id/previousButton"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Right"
    android:id="@+id/nextButton"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

error :错误 :

05-01 03:53:09.768 8768-8768/samcox.remotedroid E/InputEventReceiver: Exception dispatching input event.
05-01 03:53:09.775 8768-8768/samcox.remotedroid E/AndroidRuntime: FATAL EXCEPTION: main
    Process: samcox.remotedroid, PID: 8768
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:116)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:161)
        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 samcox.remotedroid.MainActivity$1.onTouch(MainActivity.java:77)
        at android.view.View.dispatchTouchEvent(View.java:13468)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3222)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2904)
        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:731)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1869)
        at android.app.Activity.dispatchTouchEvent(Activity.java:3487)
        at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:689)
        at android.view.View.dispatchPointerEvent(View.java:13720)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6125)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5903)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5352)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5405)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5371)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5530)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5379)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5587)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5352)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5405)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5371)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5379)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5352)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8412)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8345)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8298)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8527)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:198)
        at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
        at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:187)
        at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:8486)
05-01 03:53:09.776 8768-8768/samcox.remotedroid E/AndroidRuntime:     at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:8554)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
        at android.view.Choreographer.doCallbacks(Choreographer.java:761)
        at android.view.Choreographer.doFrame(Choreographer.java:690)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7073)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

I am a beginner in programming, so please excuse my errors我是编程初学者,所以请原谅我的错误

The issue is that inside the AsyncTask's onPostExecute you call the following:问题是在 AsyncTask 的 onPostExecute 中,您调用以下内容:

socket.getOutputStream() 

This happens on the MainThread and therefore the exception is thrown.这发生在 MainThread 上,因此抛出异常。 Move it to the doInBackground inside the try catch block so it looks like this:将它移动到try catch block内的doInBackground使其看起来像这样:

public class ConnectPhoneTask extends AsyncTask<String,Void,Boolean> {

    @Override
    protected Boolean doInBackground(String... params) {
        boolean result = true;
        try {
            InetAddress serverAddr = InetAddress.getByName(params[0]);
            socket = new Socket(serverAddr, Constants.SERVER_PORT);//Open socket on server IP and port
            if(isConnected) {
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
                        .getOutputStream())), true); //create output stream to send data to server
            }
        } catch (IOException e) {
            Log.e("remotedroid", "Error while connecting", e);
            result = false;
        }
        return result;
    }

    @Override
    protected void onPostExecute(Boolean result)
    {
        isConnected = result;
        Toast.makeText(context,isConnected?"Connected to server!":"Error while connecting",Toast.LENGTH_LONG).show();
    }
}

I recommend that when you get errors you are unsure of what is causing it, you should break down complex instructions into simple instructions and set a breakpoint so you can walk through them and see exactly which instruction is resulting in the runtime error.我建议,当您遇到错误并不确定是什么导致错误时,您应该将复杂的指令分解为简单的指令并设置一个断点,以便您可以遍历它们并确切地查看导致运行时错误的指令。 So, in the code above, you could maybe simplify as so:所以,在上面的代码中,你可以这样简化:

 OutputStream os = socket.getOutputStream();
 OutputStreamWriter ow = new OutputStreamWriter(os);
 out = new PrintWriter(ow, true); //create output stream to send data to server

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM