Android:Wi-Fi下使用蜂窝网络请求数据

1,518 阅读1分钟

我正在参加「掘金·启航计划」

最近遇到一个需求,对接运营商的一键登录功能,但是 SDK 要求首次调用必须在移动网络下才可以,那么当 Wi-Fi 和移动网络同时打开的情况下,系统的默认请求都是通过 WI-FI 的,那么怎么做到,指定 SDK 接口方法通过移动网络进行请求呢?

Android 提供绑定网络类型接口,可以将网络请求指定网络。

一、权限

需要添加以下权限

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

二、蜂窝网络是否打开

1、判断是否安装SIM卡;

2、调用反射方法,判断移动网络是否打开,至少要打开移动网络,才可以进行网络请求

//是否有SIM卡
public static boolean hasSimCard(Context context) {
    TelephonyManager telMgr = (TelephonyManager)
            context.getSystemService(Context.TELEPHONY_SERVICE);
    int simState = telMgr.getSimState();
    boolean result = true;
    switch (simState) {
        case TelephonyManager.SIM_STATE_ABSENT:
            result = false; // 没有SIM卡
            break;
        case TelephonyManager.SIM_STATE_UNKNOWN:
            result = false;
            break;
    }
    Log.d("try", result ? "有SIM卡" : "无SIM卡");
    return result;
}
//蜂窝网络是否打开
public boolean isMobileEnableReflex(Context context) {
    try {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        Method getMobileDataEnabledMethod = ConnectivityManager.class.getDeclaredMethod("getMobileDataEnabled");
        getMobileDataEnabledMethod.setAccessible(true);
        return (Boolean) getMobileDataEnabledMethod.invoke(connectivityManager);
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
    
    

三、设置绑定蜂窝网络

addTransportType:指定网络传输类型,NetworkCapabilities.TRANSPORT_CELLULAR为蜂窝网络;

addCapability:指定能力,NetworkCapabilities.NET_CAPABILITY_INTERNET添加联网网络能力;

ConnectivityManager connMgr =(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder=new NetworkRequest.Builder();
builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
NetworkRequest request=builder.build();
ConnectivityManager.NetworkCallback networkCallback =new ConnectivityManager.NetworkCallback(){
    @Override
    public void onAvailable(@NonNull Network network) {
        super.onAvailable(network);
        try {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                connMgr.setProcessDefaultNetwork(network);
            } else {
                connMgr.bindProcessToNetwork(network);
            }
        } catch (IllegalStateException e) {
            Log.e(TAG, "ConnectivityManager.NetworkCallback.onAvailable: ", e);
        }
    }
    @Override
    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
        Log.e(TAG, "onCapabilitiesChanged: " + networkCapabilities);
    }
    @Override
    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
        Log.e(TAG, "onLinkPropertiesChanged: " + linkProperties);
        //此处进行蜂窝网络请求
    }
    @Override
    public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {
        super.onBlockedStatusChanged(network, blocked);
        Log.e(TAG, "onBlockedStatusChanged");
        //指定网络取消或者阻塞,会进入此方法,可以做错误处理
    }

}
connMgr.registerNetworkCallback(request, networkCallback);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    connMgr.requestNetwork(request,networkCallback,5000);
}else {
    connMgr.requestNetwork(request,networkCallback);
}

四、取消绑定蜂窝网络

可以在回调方法onLinkPropertiesChanged里面进行网络请求,再请求的回调方法里,一定要记得取消绑定,不然后续的请求也只会通过移动网络进行,这就不行了。

if (connMgr!=null) {
    Log.d(TAG,"unregisterNetworkCallback");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        connMgr.bindProcessToNetwork(null);
    }
    if (networkCallback!=null){
        try {
            connMgr.unregisterNetworkCallback(networkCallback);
        }catch (IllegalArgumentException e){
            e.printStackTrace();
        }
        networkCallback=null;
    }

}