2017-09-11 1 views
0

Lorsque la connexion Internet est fournie, mon application peut se connecter à un serveur via une socket Web à l'aide de OkHttp (v 3.9.0). Je veux gérer une tentative ratée de se connecter à une socket Web avec élégance (c'est-à-dire lorsqu'aucune connexion Internet n'est disponible).Comment faire pour attraper UnknownHostException lors de la connexion à websocket via OkHttp sur Android?

Je construis une connexion à mon serveur en utilisant le code présenté ci-dessous:

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

client.newWebSocket(request, webSocketListener); 

Mon auditeur poignées UnknownHostException de défaillance et les journaux.

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

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

Le résultat est

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 

Et les application se bloque.

J'ai essayé d'entourer le premier bloc de code avec try-catch, en attrapant toutes les exceptions levées, mais plus tard, j'ai compris que UnknownHostException doit avoir déjà été géré en interne par OkHttpClient. OkHttpClient a ensuite appelé la méthode onFailure de mon écouteur. Cependant, UnknownHostException reste toujours non capturé. Y a-t-il un moyen d'attraper cette exception? Je ne veux pas utiliser Thread.setDefaultUncaughtExceptionHandler(). Y a-t-il un autre moyen de gérer cette situation?

+0

Pourquoi vous essayez de ne pas utiliser Retrofit2 au lieu de OkHttp? Habituellement, Retrofit fonctionne pour Android et OkHttp est utilisé pour "Java Standard". –

+0

UnknownHostException n'est jamais lancé à l'intérieur de la méthode onFailure(). – canihazurcode

Répondre

-1

UnknownHostException est sous-classe de IOException afin que vous puissiez attraper le IOException et cela corrigera pour vous

+0

J'ai essayé d'entourer le bloc de code responsable de la connexion avec try {...} catch (Exception e) {...}, mais il ne lance aucune exception – canihazurcode

+0

catch (IOException e) –

+1

IOException est une sous-classe d'exception. – canihazurcode

1

J'ai essayé d'utiliser OkHttp d'Android pour communiquer avec un serveur WebSockets un mois il y a, et il n » Je ne veux pas travailler. Donc à la place, j'ai utilisé un moyen de communication de bas niveau et cela a fonctionné comme un charme, avec juste un Java basique.

Voilà comment le code semble (pour envoyer des informations au serveur, dans mon cas):

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

En utilisant cette approche de bas niveau, j'ai pu contourner en utilisant OkHttp et fait mon travail avec juste norme Java. Maintenant, je sais que vous voulez obtenir des données du serveur et ne pas les publier, comme dans mon cas, mais peut-être que cela vous donne une idée d'une solution de contournement avec seulement Java.

De même, vous pourriez écrire une méthode isOnline() comme je l'ai fait. Seulement si c'est en ligne, il va essayer de communiquer avec le serveur. Peut-être que de cette façon, vous contourner votre problème et garder votre code actuel. Voici ma méthode 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; 
     } 
    } 

Vous pouvez même faire l'application tente de se connecter à une certaine Wi-Fi en utilisant ceci:

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