Android SecurityException: getDataNetworkTypeForSubscriber问题修复
前不久,在开发Android视频播放器的时候,使用手机的4G播放时出现了getDataNetworkTypeForSubscriber
错误,详细的报错信息如下:
php
Process: com.avatar.buyer.client, PID: 27217
java.lang.SecurityException: getDataNetworkTypeForSubscriber
at android.os.Parcel.createExceptionOrNull(Parcel.java:2437)
at android.os.Parcel.createException(Parcel.java:2421)
at android.os.Parcel.readException(Parcel.java:2404)
at android.os.Parcel.readException(Parcel.java:2346)
at com.android.internal.telephony.ITelephony$Stub$Proxy.getNetworkTypeForSubscriber(ITelephony.java:9300)
at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:3550)
at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:3514)
at com.kk.taurus.playerbase.utils.NetworkUtils.getNetworkState(NetworkUtils.java:76)
at com.avatar.video.cover.ErrorCover.onCoverAttachedToWindow(ErrorCover.java:54)
at com.kk.taurus.playerbase.receiver.BaseCover.onViewAttachedToWindow(BaseCover.java:118)
at android.view.View.dispatchAttachedToWindow(View.java:21982)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4293)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4302)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4302)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4302)
at android.view.ViewGroup.addViewInner(ViewGroup.java:6127)
at android.view.ViewGroup.addView(ViewGroup.java:5903)
at android.view.ViewGroup.addView(ViewGroup.java:5875)
at com.kk.taurus.playerbase.assist.RelationAssist.attachContainer(RelationAssist.java:367)
at com.avatar.video.base.BSPlayer.attachContainer(BSPlayer.java:194)
at com.avatar.video.base.BSPlayer.attachContainer(BSPlayer.java:190)
at com.avatar.module.shop.ui.GoodsDetailActivity.setVideoConfig(GoodsDetailActivity.kt:224)
at com.avatar.module.shop.ui.GoodsDetailActivity.access$setVideoConfig(GoodsDetailActivity.kt:64)
at com.avatar.module.shop.ui.GoodsDetailActivity$updateTopBanner$2.onPlay(GoodsDetailActivity.kt:187)
at com.avatar.common.widget.banner.CommonBannerAdapter.onBindViewHolder$lambda-2$lambda-1(CommonBannerAdapter.kt:55)
at com.avatar.common.widget.banner.CommonBannerAdapter.lambda$TurXnrorY1dSzOfKtnh8x0HRywc(Unknown Source:0)
at com.avatar.common.widget.banner.-$$Lambda$CommonBannerAdapter$TurXnrorY1dSzOfKtnh8x0HRywc.onClick(Unknown Source:11)
上述错误通常出现在,用户切换改变网络的过程中。根据资料查找,出现这种错误的场景为:
- 根据 SecurityException: getDataNetworkTypeForSubscriber 可以看到,这是一个安全性异常,所以猜测应用在 Android11 的权限有关,由于缺少该权限导致无法访问接口而异常。
- 找到网络状态检测方法,可以看到调用了 TelephonyManager.getNetworkType()接口获取网络类型,该方法是需要 READ_PHONE_STATE 权限的,该方法上面也有 RequiresPermission 注解声明。
下面是我们检查网络状态的代码,可以看到,最后调用了telephonyManager.getNetworkType();
,报错的地方就在那,如下:
ini
@RequiresPermission(value = "android.permission.READ_PHONE_STATE")
public int getNetworkState(Context context) {
if (null == mConnectivityManager) { // 为空则认为无网络
return NETWORK_NONE;
}
// 获取网络类型,如果为空,返回无网络
NetworkInfo activeNetInfo = mConnectivityManager.getActiveNetworkInfo();
if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
return NETWORK_NONE;
}
// 判断是否为WIFI
NetworkInfo wifiInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (null != wifiInfo) {
NetworkInfo.State state = wifiInfo.getState();
if (null != state) {
if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
return NETWORK_WIFI;
}
}
}
// 若不是WIFI,则去判断是2G、3G、4G网
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
int networkType = telephonyManager.getNetworkType();
...
}
解决的方式也是很简单,就是在调用前判断网络状态权限,如果没有权限跳转授权权限。
typescript
private void requestPermission() {
LogUtil.printE(HomeActivity.class, ">>> etrunc requestPermission SDK-VERSION= " + Build.VERSION.SDK_INT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { //Android 11 授权读写权限
XXPermissions.with(this)
.permission(Permission.READ_PHONE_STATE)
.request(new OnPermissionCallback() {
@Override
public void onGranted(List<String> permissions, boolean all) {
if (all) {
ToastUtil.showToast(getApplication(), R.string.permission_success_tip);
}
}
@Override
public void onDenied(List<String> permissions, boolean never) {
if (never) {
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(this, permissions);
} else {
ToastUtil.showToast(getApplication(), R.string.permissions_error);
}
}
});
}
}