我如何修复FATAL EXCEPTION:主要android.os.NetworkOnMainThreadException

问题描述 投票:-1回答:2

如果不是英语,我很抱歉,因为我正在使用翻译。

我从github下载了一个可以通过Android手机控制鼠标的程序。连接到服务器没有问题,但是当触摸textview来控制鼠标时会发生错误。

独特的是,当使用虚拟设备运行程序时,不会发生错误并且运行良好。

我见过很多例子和答案,但我无法解决,所以我重新发帖。 ; _;如果你能告诉我哪些部分需要修改,我真的很感激。

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:

<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" />

错误:

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)

我是编程的初学者,所以请原谅我的错误

android exception android-asynctask fatal-error
2个回答
0
投票

问题是在AsyncTask的onPostExecute中调用以下内容:

socket.getOutputStream() 

这发生在MainThread上,因此抛出异常。将它移动到doInBackground内的try catch block所以它看起来像这样:

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();
    }
}

0
投票

我建议当你遇到错误时你不确定是什么原因引起的,你应该将复杂的指令分解成简单的指令并设置一个断点,这样你就可以浏览它们并确切地看到导致运行时错误的指令。因此,在上面的代码中,您可以简化如下:

 OutputStream os = socket.getOutputStream();
 OutputStreamWriter ow = new OutputStreamWriter(os);
 out = new PrintWriter(ow, true); //create output stream to send data to server
© www.soinside.com 2019 - 2024. All rights reserved.