我正在参加「掘金·启航计划」
最近遇到一个需求,对接运营商的一键登录功能,但是 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;
}
}