如何在Android上通过OkHttp连接到websocket时捕获UnknownHostException?

时间:2017-09-11 13:53:26

标签: java android exception websocket okhttp

当提供互联网连接时,我的应用程序可以使用OkHttp(v 3.9.0)通过websocket连接到服务器。我想处理一个失败的尝试连接到websocket优雅(即没有互联网连接可用)。

我使用下面的代码建立了与服务器的连接:

Request request = new Request.Builder()
        .url(BuildConfig.WS_URL)
        .build();

client.newWebSocket(request, webSocketListener);

我的侦听器处理失败并记录UnknownHostException。

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {

    if(t instanceof UnknownHostException) {
        Log.v("LISTENER", "UNKNOWN HOST EXCEPTION");
    }
}

结果是

09-11 15:16:32.773 18384-18473/com.example.app V/LISTENER: UNKNOWN HOST EXCEPTION

09-11 15:16:32.775 18384-18473/com.example.app E/AndroidRuntime: FATAL EXCEPTION: OkHttp https://my.server.url/...
                                                                     Process: com.example.app, PID: 18384

应用程序崩溃。

我试图用try-catch包围第一个代码块,捕获任何抛出的异常,但后来我发现UnknownHostException必须已经由OkHttpClient内部处理。然后OkHttpClient调用了我的监听器的onFailure方法。但是,UnknownHostException仍然没有被捕获。有没有办法抓住这个例外?我不想使用Thread.setDefaultUncaughtExceptionHandler()。有没有其他方法来处理这种情况?

2 个答案:

答案 0 :(得分:1)

我已经尝试使用Android的OkHttp大约一个月前与WebSockets服务器进行通信,但它不想工作。所以我使用了一种低级的沟通方式,它就像一个魅力,只有基本的Java。

以下是代码的外观(在我的例子中,用于向服务器发送信息):

//this is the method that sends the String passed as the parameter to the Sockets server
    private void sendMessage(final String stringToSend) throws IOException {

    if(isOnline()){
        new Thread(new Runnable() {
            @Override
            public void run() {

                Socket socket = null;
                try {
                    socket = new Socket("192.168.0.1",1001);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                DataOutputStream DOS = null;
                try {
                    DOS = new DataOutputStream(socket.getOutputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    DOS.writeUTF(stringToSend);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

使用这种低级方法,我能够绕过使用OkHttp并使用标准Java完成我的工作。现在,我知道你想要从服务器获取数据而不是发布它,就像我的情况一样,但也许它让你知道只有Java的解决方法。

另外,您可以像我一样编写isOnline()方法。只有当它在线时它才会尝试与服务器通信。也许这样,你就可以解决问题并保留当前的代码。这是我的isOnline()方法:

protected boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            //if you're not connected through Wi-Fi...
            if(netInfo.getType() != ConnectivityManager.TYPE_WIFI){
                Toast.makeText(this,"This app doesn't work without Wi-Fi",Toast.LENGTH_LONG).show();
                return false;
            }
            return true;
        } else {
            return false;
        }
    }

您甚至可以使应用程序尝试连接到某个Wi-Fi:

    private void connectToWifi() {
        String networkSSID = "YourWiFiSSID";

        WifiConfiguration wifiConfig = new WifiConfiguration();
        wifiConfig.SSID = "\"" + networkSSID + "\"";
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);

        WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        wifiManager.addNetwork(wifiConfig);

        //enable the WiFi if it's disabled
        if (!wifiManager.isWifiEnabled()){
            wifiManager.setWifiEnabled(true);
        }

        //get the list of Wi-Fi configurations
        List<WifiConfiguration> wifiConfigurationList = wifiManager.getConfiguredNetworks();
        for(WifiConfiguration configuration : wifiConfigurationList){
            //if the configuration is the right one, connect to it
            if(configuration.SSID != null && configuration.SSID.equals("\"" + networkSSID + "\"")){
                wifiManager.disconnect();
                wifiManager.enableNetwork(configuration.networkId,true);
//                wifiManager.reconnect();

                break;
            }
        }
    }

答案 1 :(得分:-1)

UnknownHostException是IOException的子类,因此您可以捕获IOException,这将为您修复它