অ্যান্ড্রয়েডে রেট্রোফিটের সাথে কীভাবে আমার "ইন্টারনেট সংযোগ নেই" পরিচালনা করা উচিত?


119

কোনও ইন্টারনেট সংযোগ না থাকলে আমি পরিস্থিতিগুলি পরিচালনা করতে চাই। সাধারণত আমি চালাতাম:

ConnectivityManager cm =
    (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
                  activeNetwork.isConnectedOrConnecting();

(থেকে এখানে ) নেটওয়ার্কে অনুরোধ পাঠানোর এবং ব্যবহারকারী অবহিত যদি কোন ইন্টারনেট সংযোগ ছিল আগে।

আমি যা দেখেছি সেখান থেকে এই পরিস্থিতিটি বিশেষভাবে পরিচালনা করে না। যদি কোনও ইন্টারনেট সংযোগ না থাকে তবে আমি কেবল RetrofitErrorকারণ হিসাবে টাইমআউট নিয়ে যাব ।

যদি আমি রেট্রোফিটের সাথে প্রতিটি এইচটিটিপি অনুরোধের মধ্যে এই ধরণের চেকটি অন্তর্ভুক্ত করতে চাই তবে আমার কীভাবে এটি করা উচিত? বা আমি এটা আদৌ করা উচিত।

ধন্যবাদ

অ্যালেক্স


আপনি HTTP সংযোগের সময়সীমা বাদ দিতে ট্রাই-ক্যাচ ব্লক ব্যবহার করতে পারেন। তারপরে, ব্যবহারকারীদের ইন্টারনেট সংযোগের স্থিতি সম্পর্কে বলুন। সুন্দর নয় তবে বিকল্প সমাধান।
Tugrul

8
হ্যাঁ, তবে অ্যান্ড্রয়েডের সাথে সকেট থেকে সংযোগের সময়সীমাটি অপেক্ষা করার পরিবর্তে ইন্টারনেট সংযোগ রয়েছে কিনা তা পরীক্ষা করা আরও দ্রুত
অ্যালেক্সভি

অ্যান্ড্রয়েড ক্যোয়ারী "ইন্টারনেট নেই" পরিচালনা করে এবং শীঘ্রই পর্যাপ্ত ত্রুটি কোডটি প্রদান করে। এটি কি aQuery সঙ্গে প্রতিস্থাপন মূল্য? আরেকটি সমাধান হ'ল নেটওয়ার্ক পরিবর্তন সম্পর্কে শ্রোতা তৈরি করা এবং এইভাবে অ্যাপ্লিকেশনটি অনুরোধ প্রেরণের আগে ইন্টারনেট উপলব্ধতার বিষয়ে জানতে পারবে।
স্ট্যান

retrofit 2 এর জন্য দেখুন github.com/square/retrofit/issues/1260
ghanbari

উত্তর:


63

আমি যা করে শেষ করেছি তা হল একটি কাস্টম রেট্রোফিট ক্লায়েন্ট তৈরি করা যা কোনও অনুরোধ কার্যকর করার আগে সংযোগের জন্য পরীক্ষা করে এবং একটি ব্যতিক্রম ছুঁড়ে।

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(), ...))

1
আপনার নেটওয়ার্ক সংযোগ ব্যবস্থাপনার ক্লাসটি কোথা থেকে এসেছে? কাস্টম?
এনপাইক 17

হ্যাঁ, প্রথা এটি মূলত প্রশ্নটির কোড
অ্যালেক্সভি

2
OkHttpClient OkClient () ব্যবহারের পরিবর্তে কাজ করে না B BDW সুন্দর উত্তর। ধন্যবাদ.
হর্ষবর্ধন ত্রিবেদী

ধন্যবাদ :-) OkHttp এর সঠিক ব্যবহারের সাথে আপনার উত্তর সম্পাদনা করেছে।
ব্যবহারকারী 1007522

1
@ মোমিনআল আজিজ আপনি কীভাবে সংজ্ঞা দেন তার উপর নির্ভর করে আপনি NoConnectivityExceptionহয় এটি প্রসারিত IOExceptionবা প্রসারিত করতে পারবেনRuntimeException
আলেক্সভি

45

পুনঃনির্মাণের পরে 1.8.0এটি অবহেলা করা হয়েছে

retrofitError.isNetworkError()

আপনি ব্যবহার করতে হবে

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

}

আপনি পরিচালনা করতে পারেন এমন একাধিক ধরণের ত্রুটি রয়েছে:

NETWORK সার্ভারের সাথে যোগাযোগ করার সময় একটি আইওএক্সেপশন ঘটেছিল, যেমন টাইমআউট, কোনও সংযোগ নেই ... ইত্যাদি

CONVERSION (ডি) একটি বডি সিরিয়াল করার সময় একটি ব্যতিক্রম ছুঁড়ে ফেলা হয়েছিল।

HTTP সার্ভারের থেকে একটি অ -200 এইচটিটিপি স্থিতি কোড পাওয়া গেছে যেমন 502, 503 ইত্যাদি ...

UNEXPECTEDএকটি অনুরোধ কার্যকর করার চেষ্টা করার সময় একটি অভ্যন্তরীণ ত্রুটি ঘটেছে। আপনার অ্যাপ্লিকেশন ক্র্যাশ হয়ে যায় তাই এই ব্যতিক্রমটিকে আবার ছুঁড়ে ফেলা ভাল অনুশীলন।


8
ব্যবহার করবেন না equalsভেরিয়েবল উপর, সবসময় ব্যবহার CONSTANT.equals(variable)পরিবর্তে সম্ভব নালপয়েন্টারএক্সেপশন এড়ানো। বা এই ক্ষেত্রে আরও ভাল, এনামগুলি গ্রহণ করে == তুলনা তাই error.getKind() == RetrofitError.Kind.NETWORKআরও ভাল পদ্ধতির হতে পারে
মারিউসউডিন

1
আপনি এনপিই এবং অন্যান্য বাক্য গঠন সীমাবদ্ধতা / ব্যথার কারণে ক্লান্ত হয়ে থাকলে জাভা কোটলিনের সাথে প্রতিস্থাপন করুন
লুই সিএডি

42

Retrofit 2 দিয়ে, আমরা অনুরোধ প্রেরণের আগে নেটওয়ার্ক সংযোগের জন্য যাচাই করার জন্য একটি OkHttp ইন্টারসেপ্টার বাস্তবায়ন ব্যবহার করি। যদি কোনও নেটওয়ার্ক না থাকে তবে উপযুক্ত হিসাবে একটি ব্যতিক্রম ছুঁড়ে দিন।

এটির সাহায্যে রেট্রোফিট হিট করার আগে নেটওয়ার্ক সংযোগ সমস্যাগুলি বিশেষত পরিচালনা করতে দেয়।

import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.Response;
import io.reactivex.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";
    }
}

3
এটি ত্রুটিযুক্ত যদি আপনি বিমান মোড চালু করেন তবে এটি বন্ধ করুন কারণ আপনি কেবল পর্যবেক্ষণযোগ্যকে অকেজো করে তুলতে কেবল একবার ভার সেট করে চলেছেন।
অলিভার ডিকসন

3
সুতরাং আপনি এখানে OkHttpClient.Builder.addInterceptor(new ConnectivityInterceptor(HERE))যা করা উচিত তা তৈরি করছেন?
রুমীদ

3
দয়া করে আপনি কি কোডটি অন্তর্ভুক্ত করতে পারেন যাতে লোকেরা একটি পুরো ছবি পায়?
অলিভার ডিকসন

1
@ কেভিনি কীভাবে নিশ্চিত হয়ে উঠতে পারি যে এটি সংযোগ উপলব্ধ হওয়ার পরে তা আপডেট হবে?
রুমীড

3
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। এর আরও উদাহরণ এখানে: migapro.com/detect-offline-error-in-retrofit-2
j2emanue

35

@ অ্যালেক্সভি আপনি কি নিশ্চিত যে ইন্টারনেট সংযোগ না থাকায় রেট্রোফিটআরআর একটি কারণ হিসাবে টাইমআউট (সকেটটাইমআউটঅ্যাক্সেপশন যখন গেটকজ () বলা হয়) রয়েছে?

যতদূর আমি জানি যখন ইন্টারনেট সংযোগ নেই তখন কারণ হিসাবে retrofitError এ একটি সংযোগপ্রকাশ রয়েছে।

আপনি যদি একটি ত্রুটিহ্যান্ডলার বাস্তবায়ন করেন তবে আপনি এরকম কিছু করতে পারেন:

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
আপনি ব্যবহার করতে পারেন এমন রেট্রোফিট উত্সটিতে একটি প্রদত্ত ত্রুটিহ্যান্ডলার রয়েছে। যদি আপনি নিজেই ত্রুটিটি পরিচালনা করেন না, তবে রিট্রোফিট আপনাকে [java.net.Unজ্ঞানহোস্টএক্সেপশন: হোস্ট "উদাহরণ
ডটকম

1
@ কোডভার্সড তাই isNetworkErrorহোস্টের ত্রুটি সমাধান করতে অক্ষম থেকে মুক্তি পেয়েছে ?
সর্বব্যাপী

2
আপনি কীভাবে এটি আপনার ইন্টারফেস, ক্লায়েন্টে প্রয়োগ করবেন? মানে, আপনি এই শ্রেণীর সাথে কি সংযোগ স্থাপন করবেন?
এফআরআর

23
কারণ.is নেটওয়াকের ত্রুটি () অবচিত : ব্যবহারerror.getKind() == RetrofitError.Kind.NETWORK
হুগো গ্রেস

6

রেট্রোফিট 1 এর জন্য

আপনি যখন 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!";
        }
    }
}

5

শুধু এটি করুন আপনি এমনকি মত সমস্যার জন্যও অবহিত করা হবে

UnknownHostException

,

SocketTimeoutException

এবং অন্যদের.

 @Override public void onFailure(Call<List<BrokenGitHubRepo>> call, Throwable t) {  
if (t instanceof IOException) {
    Toast.makeText(ErrorHandlingActivity.this, "this is an actual network failure :( inform the user and possibly retry", Toast.LENGTH_SHORT).show();
    // logging probably not necessary
}
else {
    Toast.makeText(ErrorHandlingActivity.this, "conversion issue! big problems :(", Toast.LENGTH_SHORT).show();
    // todo log to some central bug tracking service
} }

1

আপনি এই কোড ব্যবহার করতে পারেন

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);        
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.