写点什么

修复 SecurityException: getDataNetworkTypeForSubscriber 问题

作者:Changing Lin
  • 2021 年 11 月 22 日
  • 本文字数:3879 字

    阅读完需:约 13 分钟

1.问题

  • 用户切换改变网络的过程中,应用概率会出现崩溃,日志如下


API level: '30'OS version: '11'ABI list: 'arm64-v8a,armeabi-v7a,armeabi'Manufacturer: 'OnePlus'Brand: 'OnePlus'Model: 'GM1900'Build fingerprint: 'OnePlus/OnePlus7_CH/OnePlus7:11/RKQ1.201022.002/2108161921:user/release-keys'pid: 29126, tid: 29126, name: main  >>> package name <<<
java stacktrace:java.lang.SecurityException: getDataNetworkTypeForSubscriber at android.os.Parcel.createExceptionOrNull(Parcel.java:2373) at android.os.Parcel.createException(Parcel.java:2357) at android.os.Parcel.readException(Parcel.java:2340) at android.os.Parcel.readException(Parcel.java:2282) at com.android.internal.telephony.ITelephony$Stub$Proxy.getNetworkTypeForSubscriber(ITelephony.java:8803) at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:3070) at android.telephony.TelephonyManager.getNetworkType(TelephonyManager.java:3034) at j.k.b0.a.e.b.c(Unknown Source:51) at j.k.b.q.c.w.onCreateView(:14) at androidx.fragment.app.Fragment.performCreateView(Unknown Source:15) at h.l.d.q.V(:18) at h.l.d.q.T(:1) at h.l.d.q.U(Unknown Source:47) at h.l.d.a.n(Unknown Source:182) at h.l.d.q.E(:7) at h.l.d.q.b0(Unknown Source:84) at h.l.d.q.D(Unknown Source:31) at h.l.d.a.e(:2) at h.l.d.v.finishUpdate(Unknown Source:12) at androidx.viewpager.widget.ViewPager.r(:2) at androidx.viewpager.widget.ViewPager.onMeasure(:1) at android.view.View.measure(View.java:25671) at androidx.constraintlayout.widget.ConstraintLayout.e(:2) at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(:70) at android.view.View.measure(View.java:25671) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6987) at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) at androidx.appcompat.widget.ContentFrameLayout.onMeasure(Unknown Source:154) at android.view.View.measure(View.java:25671) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6987) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552) at android.widget.LinearLayout.measureVertical(LinearLayout.java:842) at android.widget.LinearLayout.onMeasure(LinearLayout.java:721) at android.view.View.measure(View.java:25671) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6987) at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) at android.view.View.measure(View.java:25671) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6987) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552) at android.widget.LinearLayout.measureVertical(LinearLayout.java:842) at android.widget.LinearLayout.onMeasure(LinearLayout.java:721) at android.view.View.measure(View.java:25671) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6987) at android.widget.FrameLayout.onMeasure(FrameLayout.java:194) at com.android.internal.policy.DecorView.onMeasure(DecorView.java:776) at android.view.View.measure(View.java:25671) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3713) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2496) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2771) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2182) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8730) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1352) at android.view.Choreographer.doCallbacks(Choreographer.java:1149) at android.view.Choreographer.doFrame(Choreographer.java:1049) at android.view.Choreographer$FrameHandler.handleMessage(Choreographer.java:1275) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:233) at android.app.ActivityThread.main(ActivityThread.java:8010) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
复制代码

2.分析

  • 根据 SecurityException: getDataNetworkTypeForSubscriber 可以看到,这是一个安全性异常,所以猜测应用在 Android11 的权限有关,由于缺少该权限导致无法访问接口而异常。

  • 找到网络状态检测方法,可以看到调用了 TelephonyManager.getNetworkType()接口获取网络类型,该方法是需要 READ_PHONE_STATE 权限的,该方法上面也有 RequiresPermission 注解声明


    @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();        ...    }
复制代码
  • 进一步分析,接口的调用堆栈为:

TelephonyManager.getNetworkType ->PhoneInterfaceManager.getNetworkTypeForSubscriber->TelephonyPermissions.checkCallingOrSelfReadPhoneState->TelephonyPermissions.checkReadPhoneState->ContextImpl.enforcePermission->ContextImpl.checkPermission->PermissionManager.checkPermission->PermissionManager.checkPermissionUncached->ActivityManager.getService->IActivityManager.checkPermission->
复制代码

3.解决方法

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(HomeActivity.this)                    // 不适配 Android 11 可以这样写                    //.permission(Permission.Group.STORAGE)                    // 适配 Android 11 需要这样写,这里无需再写 Permission.Group.STORAGE                    .permission(Permission.MANAGE_EXTERNAL_STORAGE, 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) { ToastUtil.showToast(getApplication(), R.string.permissions_refuse_authorization); // 如果是被永久拒绝就跳转到应用权限系统设置页面 XXPermissions.startPermissionActivity(HomeActivity.this, permissions); } else { ToastUtil.showToast(getApplication(), R.string.permissions_error); } } }); } }
复制代码


发布于: 55 分钟前阅读数: 4
用户头像

Changing Lin

关注

获得机遇的手段远超于固有常规之上~ 2020.04.29 加入

我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。

评论

发布
暂无评论
修复SecurityException: getDataNetworkTypeForSubscriber问题