Как обращаться с «Нет подключения к Интернету» с помощью Retrofit на Android?

Я хотел бы обрабатывать ситуации, когда нет подключения к Интернету. Обычно я запускаю:

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

( Отсюда ) перед отправкой запросов в сеть и уведомлять пользователя, если не было интернет-соединения.

Из того, что я видел, Retrofit не справляется с этой ситуацией конкретно. Если нет подключения к Интернету, я просто получаю RetrofitError с таймаутом в качестве причины.

Если я хотел бы включить этот вид проверки в каждый HTTP-запрос с помощью Retrofit, как мне это сделать? Или я должен делать это вообще.

благодаря

Alex

Solutions Collecting From Web of "Как обращаться с «Нет подключения к Интернету» с помощью Retrofit на Android?"

То, что я закончил, – это создание настраиваемого клиента Retrofit, который проверяет подключение до выполнения запроса и генерирует исключение.

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

А затем использовать его при настройке RestAdapter

 RestAdapter.Builder().setEndpoint(serverHost) .setClient(new ConnectivityAwareUrlClient(new OkHttpClient(), ...)) 

@AlexV вы уверены, что RetrofitError содержит тайм-аут в качестве причины (SocketTimeOutException при вызове getCause ()), когда нет подключения к Интернету?

Насколько я знаю, когда нет подключения к Интернету, RetrofitError содержит ConnectionException в качестве причины.

Если вы реализуете ErrorHandler, вы можете сделать что-то вроде этого:

 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's not a network error ...] } } } 

Начиная с версии 1.8.0 это устарело

 retrofitError.isNetworkError() 

Вы должны использовать

 retrofitError.getKind().equals(RetrofitError.Kind.NETWORK) 

А затем сделайте свой материал внутри оператора if

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

Существует несколько типов ошибок, с которыми вы можете справиться:

NETWORK IOException произошло при общении с сервером, например, Timeout, No connection и т. Д.

CONVERSION Исключение было выбрано, когда (de) сериализовало тело.

HTTP От сервера был получен код статуса HTTP не-200, например 502, 503 и т. Д. …

UNEXPECTED Внутренняя ошибка при попытке выполнить запрос. Лучше всего перебросить это исключение, чтобы ваше приложение вышло из строя.

С помощью Retrofit 2 мы используем реализацию перехватчика OkHttp для проверки сетевого подключения перед отправкой запроса. Если нет сети, выберите исключение.

Это позволяет специально обрабатывать проблемы с подключением к сети, прежде чем нажать 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"; } } 

Когда вы получаете сообщение Throwable из вашего HTTP-запроса, вы можете определить, является ли это сетевой ошибкой с помощью такого метода:

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

UPDATE : Я должен сказать, что это работает только с Retrofit 1, а не с Retrofit 2.

Вы можете использовать этот код

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

Реализация в ваших методах

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