How should I handle "No Internet Connection" using Retrofit on Android

I would like to handle situations where there is no internet connection. I usually ran:

ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting(); 

(from here ) before sending requests to the network and notify the user if there was no Internet connection.

From what I saw, Retrofit does not deal with this situation specifically. If there is no internet connection, I just get a RetrofitError with a timeout as the reason.

If I would like to include this kind of validation in every HTTP request using Retrofit, how do I do this? Or should I do it at all.

thank

Alex

+75
android retrofit
Dec 26 '13 at 14:36
source share
6 answers

As a result, I create a custom Retrofit client that checks the connection before executing the request and throws an exception.

 public class ConnectivityAwareUrlClient implements Client { Logger log = LoggerFactory.getLogger(ConnectivityAwareUrlClient.class); public ConnectivityAwareUrlClient(Client wrappedClient, NetworkConnectivityManager ncm) { this.wrappedClient = wrappedClient; this.ncm = ncm; } Client wrappedClient; private NetworkConnectivityManager ncm; @Override public Response execute(Request request) throws IOException { if (!ncm.isConnected()) { log.debug("No connectivity %s ", request); throw new NoConnectivityException("No connectivity"); } return wrappedClient.execute(request); } } 

and then use it when setting up the RestAdapter

 RestAdapter.Builder().setEndpoint(serverHost) .setClient(new ConnectivityAwareUrlClient(new OkHttpClient(), ...)) 
+46
Mar 23 '14 at 19:22
source share

Since retrofit 1.8.0 it is deprecated

 retrofitError.isNetworkError() 

you should use

 if (retrofitError.getKind() == RetrofitError.Kind.NETWORK) { } 

There are several types of errors that you can handle:

NETWORK An error occurred while communicating with the server. IOException. Timeout, No connection, etc.

CONVERSION An exception was thrown while (de) serialized the body.

HTTP Non-200 HTTP status code was received from the server, for example. 502, 503, etc.

UNEXPECTED An internal error occurred while trying to execute the query. It is recommended that this exception be thrown so that your application crashes.

+33
Mar 15 '15 at 6:51
source share

@AlexV sure RetrofitError contains a timeout as the reason (SocketTimeOutException when calling getCause ()) when there is no Internet connection?

As far as I know, when there is no Internet connection, RetrofitError contains ConnectionException as the reason.

If you implement ErrorHandler , you can do something like this:

 public class RetrofitErrorHandler implements ErrorHandler { @Override public Throwable handleError(RetrofitError cause) { if (cause.isNetworkError()) { if (cause.getCause() instanceof SocketTimeoutException) { return new MyConnectionTimeoutException(); } else { return new MyNoConnectionException(); } } else { [... do whatever you want if it not a network error ...] } } } 
+32
Jan 10 '14 at
source share

Using Retrofit 2, we use the OkHttp interceptor implementation to test network connectivity before sending a request. If there is no network, select an exception.

This allows you to specifically handle network connectivity issues before clicking "Retrofit."

 import java.io.IOException; import okhttp3.Interceptor; import okhttp3.Response; import rx.Observable; public class ConnectivityInterceptor implements Interceptor { private boolean isNetworkActive; public ConnectivityInterceptor(Observable<Boolean> isNetworkActive) { isNetworkActive.subscribe( _isNetworkActive -> this.isNetworkActive = _isNetworkActive, _error -> Log.e("NetworkActive error " + _error.getMessage())); } @Override public Response intercept(Interceptor.Chain chain) throws IOException { if (!isNetworkActive) { throw new NoConnectivityException(); } else { Response response = chain.proceed(chain.request()); return response; } } } public class NoConnectivityException extends IOException { @Override public String getMessage() { return "No network available, please check your WiFi or Data connection"; } } 
+12
Nov 17 '16 at 23:59
source share

When you get a Throwable error Throwable from your HTTP request, you can determine if this is a network error using a method like this:

 String getErrorMessage(Throwable e) { RetrofitError retrofitError; if (e instanceof RetrofitError) { retrofitError = ((RetrofitError) e); if (retrofitError.getKind() == RetrofitError.Kind.NETWORK) { return "Network is down!"; } } } 

UPDATE I have to say that this only works with Retrofit 1, not Retrofit 2.

+4
Sep 10 '15 at 15:11
source share

you can use this code

Response.java

 import com.google.gson.annotations.SerializedName; /** * Created by hackro on 19/01/17. */ public class Response { @SerializedName("status") public String status; public void setStatus(String status) { this.status = status; } public String getStatus() { return status; } @SuppressWarnings({"unused", "used by Retrofit"}) public Response() { } public Response(String status) { this.status = status; } } 

NetworkError.java

 import android.text.TextUtils; import com.google.gson.Gson; import java.io.IOException; import java.util.List; import java.util.Map; import retrofit2.adapter.rxjava.HttpException; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; /** * Created by hackro on 19/01/17. */ public class NetworkError extends Throwable { public static final String DEFAULT_ERROR_MESSAGE = "Please try again."; public static final String NETWORK_ERROR_MESSAGE = "No Internet Connection!"; private static final String ERROR_MESSAGE_HEADER = "Error Message"; private final Throwable error; public NetworkError(Throwable e) { super(e); this.error = e; } public String getMessage() { return error.getMessage(); } public boolean isAuthFailure() { return error instanceof HttpException && ((HttpException) error).code() == HTTP_UNAUTHORIZED; } public boolean isResponseNull() { return error instanceof HttpException && ((HttpException) error).response() == null; } public String getAppErrorMessage() { if (this.error instanceof IOException) return NETWORK_ERROR_MESSAGE; if (!(this.error instanceof HttpException)) return DEFAULT_ERROR_MESSAGE; retrofit2.Response<?> response = ((HttpException) this.error).response(); if (response != null) { String status = getJsonStringFromResponse(response); if (!TextUtils.isEmpty(status)) return status; Map<String, List<String>> headers = response.headers().toMultimap(); if (headers.containsKey(ERROR_MESSAGE_HEADER)) return headers.get(ERROR_MESSAGE_HEADER).get(0); } return DEFAULT_ERROR_MESSAGE; } protected String getJsonStringFromResponse(final retrofit2.Response<?> response) { try { String jsonString = response.errorBody().string(); Response errorResponse = new Gson().fromJson(jsonString, Response.class); return errorResponse.status; } catch (Exception e) { return null; } } public Throwable getError() { return error; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NetworkError that = (NetworkError) o; return error != null ? error.equals(that.error) : that.error == null; } @Override public int hashCode() { return error != null ? error.hashCode() : 0; } } 

Implementation in your methods

  @Override public void onCompleted() { super.onCompleted(); } @Override public void onError(Throwable e) { super.onError(e); networkError.setError(e); Log.e("Error:",networkError.getAppErrorMessage()); } @Override public void onNext(Object obj) { super.onNext(obj); } 
+1
Apr 02 '17 at 21:21
source share



All Articles