(Android)使用RxJava2连接多个DNS以检测网络是否真正连通

最近遇到一个问题,在APP发起HTTPS请求之前,想判断一下手机网络是否已连通。查了一轮资料后,发现以前用的好几种方式(这里暂时省略)都过时和失效,特别是在Android10之后,所以萌生了写这个工具类的想法。

这里有几个要求:

  • 任何一个DNS连通后,无须等待其他DNS是否连通,马上回调;
  • 所有DNS都无法连通,才能认为是检测失败,所以在此过程中即使任何一个DNS连接出错,也不能打断其他DNS的连接请求和回调;
  • 需要并发请求,即几个请求同时发出,而不能为串行请求(一个等一个)
  • 取消订阅后,抛出的异常无法捕获,将导致程序崩溃,需要在Application设置RxJavaPlugin的ErrorHandler,以接收这类异常
  • 取消订阅后,不要再发射事件

所以,考虑使用RxJava2的mergeDelayError操作符和take操作符。

  • mergeDelayError:并发去请求,过程出错也不会立即onError打断其他请求
  • take:只接受n个事件

使用方法:

首先要在Application的onCreate()中调用

ConnectionCheckUtil.initRxJavaDisposeErrorHandler()

然后,在需要的地方调用:

ConnectionCheckUtil.connectionCheck(object : OnConnectionCheckListener {
            override fun onConnected() {
                //connected
            }
            override fun onDisconnected() {
                //not connected
            }
        })

最后附上源码和GitHub Demo

import com.orhanobut.logger.Logger;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;

public class ConnectionCheckUtil {

    private static final String TAG = "ConnectionCheckUtil";
    private static final int timeout = 1000;
    private static final String dns1 = "8.8.8.8";
    private static final String dns2 = "8.8.4.4";

    public interface OnConnectionCheckListener{
        void onConnected();
        void onDisconnected();
    }

    public static void connectionCheck(OnConnectionCheckListener callBack) {
        Observable check1 = getConnectionCheckObservable(dns1);
        Observable check2 = getConnectionCheckObservable(dns2);
        Observable.mergeDelayError(check1, check2)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .take(1)
                .subscribe(getResultCheckObserver(callBack));
    }

    private static Observable getConnectionCheckObservable(String ip) {
        return Observable.create((ObservableOnSubscribe<String>) e -> {
            try {
                Socket s;
                s = new Socket();
                InetAddress host = InetAddress.getByName(ip);
                s.connect(new InetSocketAddress(host, 53), timeout);
                s.close();
                if(!e.isDisposed()) {
                    Logger.t(TAG).d("onNext" + ip);
                    e.onNext(ip);
                }
            } catch (Exception ex) {
                if(!e.isDisposed()) {
                    Logger.t(TAG).d("onError" + ex.getMessage());
                    e.onError(ex);
                }
            }
        });
    }
    private static Observer<String> getResultCheckObserver(OnConnectionCheckListener callBack) {
        return new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                Logger.t(TAG).d("onSubscribe : " + d.isDisposed() + "\n");
            }

            @Override
            public void onNext(@NonNull String ip) {
                Logger.t(TAG).d("onNext : value : " + ip + "\n");
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Logger.t(TAG).d("onError : value : " + e.getMessage() + "\n");
                callBack.onDisconnected();
            }

            @Override
            public void onComplete() {
                Logger.t(TAG).d( "onComplete" + "\n");
                callBack.onConnected();
            }
        };
    }

    public static void initRxJavaDisposeErrorHandler() {
        RxJavaPlugins.setErrorHandler(throwable -> {
        });
    }
}

参考资料:

RxJava2使用过程中遇到的坑

FATAL EXCEPTION: RxCachedThreadScheduler-4 or -1 or -2 or -3

Android 判断网络连接是否可用

Android RxJava:组合 / 合并操作符 详细教程

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值