【问题标题】:Android - NetworkOnMainThreadException with okhttp websocketAndroid - 带有 okhttp websocket 的 NetworkOnMainThreadException
【发布时间】:2017-01-21 16:52:18
【问题描述】:

我在使用 Android okhttp Websockets 时遇到了线程问题。我正在做一个聊天应用程序,我需要使用 websocket 从我们的服务器写入和读取。

我在其他帖子中读到,使用 Okhttp,我应该使用 StrictMode.ThreadPolicy.Builder().permitAll(),因为它存在一些问题等。我添加了它。

但是当我尝试发送消息时,我不断收到此错误:

W/System.err: android.os.NetworkOnMainThreadException 09-13 17:13:32.198 22766-22766/com.microsoft.translator

请注意,我是在不同的线程上发送消息,而不是在主线程上。

这是我的代码。感谢任何帮助。

创建网络套接字:

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

   StrictMode.ThreadPolicy policy = new   StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

    // lot other init stuff 
    createWebSocket();
}

private void createWebSocket() {
    okHttpClient = new OkHttpClient();
    Request request = new Request.Builder()
            .url(WSS_URL + token)
            .build();
    webSocketCall = WebSocketCall.create(okHttpClient, request);
    webSocketCall.enqueue(this);
}

@Override
public void onOpen(WebSocket webSocket, Response response) {
    try {
        Log.d(TAG, "onOpen: " + response.message());
        String message = createJsonMessage("Hello");
        byte[] messageBytes = message.getBytes();
        showToastOnUIThread("OnOpen sending message");

        webSocket.sendMessage(WebSocket.PayloadType.TEXT, new Buffer().write(messageBytes));
        this.webSocket = webSocket;
        //startRepeatingTask();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

    private void sendMessage(final String msgString) {

    Runnable postMessageThread = new Runnable() {
        @Override
        public void run() {
            String message = createJsonMessage(msgString);
            byte[] messageBytes = message.getBytes();

            try {
                if (webSocket != null) {
                    try {
                        webSocket.sendMessage(WebSocket.PayloadType.TEXT, new Buffer().write(messageBytes));
                    } catch (IOException e) {
                        e.printStackTrace();
                        Toast.makeText(ChatActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        Toast.makeText(ChatActivity.this, ex.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    postMessageThread.run();
}

【问题讨论】:

  • I should use StrictMode.ThreadPolicy.Builder().permitAll() 。不。你最好不要那样做。

标签: android websocket okhttp


【解决方案1】:

我认为你的代码应该是这样的:

new Thread(new Runnable() {
        public void run() {
            // call send message here
        }
    }).start();

或者你可以使用Asyntask

【讨论】:

  • 这不是我已经拥有的吗? Runnable postMessageThread = new Runnable() { @Override public void run() { ... } 你是想说使用 Thread 而不是 Runnable 类型的变量?
  • 我认为您使用 Runnable 的代码在 UI 线程上运行,而不是创建新线程,因此您将收到错误 NetworkOnMainThreadException。所以 new Thread 将创建另一个线程。但我建议使用 Asyntask 来做网络请求。
【解决方案2】:

我认为这段代码是一个简单的例子。如果不使用token进行鉴权,可以去掉addHeader。

OkHttpClient client = new OkHttpClient();

RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("your_name_input", "your_value")
        .build();

Request request = new Request.Builder()
        .url("your_url")
        .post(requestBody)
        .addHeader("name_your_token", "your_token")
        .build();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        e.printStackTrace();
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        final String yourResponse = response.body().string();
        if(response.isSuccessful()){

            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "Ok: "+yourResponse,Toast.LENGTH_SHORT).show();
                }
            });
        }else{
            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "Ok: "+yourResponse,Toast.LENGTH_SHORT).show();
                }
            });
        }


    }
});

你还在清单中添加权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

【讨论】:

    猜你喜欢
    • 2017-09-15
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2012-11-16
    相关资源
    最近更新 更多