问题描述
高德地图,在我的小米4(Android 6.0)上出现bug,日志如下:
06-07 17:58:52.761 31095-32257/com.freetek.deepsea W/System.err: java.lang.SecurityException: getCellLocation: Neither user 10549 nor current process has android.permission.ACCESS_COARSE_LOCATION.
06-07 17:58:52.762 31095-32257/com.freetek.deepsea W/System.err: at android.os.Parcel.readException(Parcel.java:1620)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at android.os.Parcel.readException(Parcel.java:1573)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.android.internal.telephony.ITelephony$Stub$Proxy.getCellLocation(ITelephony.java:2428)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at android.telephony.TelephonyManager.getCellLocation(TelephonyManager.java:831)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.m(CgiManager.java)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.l(CgiManager.java)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.f(CgiManager.java)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.loc.bv.G(APS.java)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.loc.bv.a(APS.java)
06-07 17:58:52.763 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d.a(APSServiceCore.java)
06-07 17:58:52.764 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d.c(APSServiceCore.java)
06-07 17:58:52.764 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d$a.run(APSServiceCore.java)
06-07 17:58:52.772 31095-32257/com.freetek.deepsea W/System.err: java.lang.reflect.InvocationTargetException
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at java.lang.reflect.Method.invoke(Native Method)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.cu.a(Reflect.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.m(CgiManager.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.l(CgiManager.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.f(CgiManager.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.bv.G(APS.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.bv.a(APS.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d.a(APSServiceCore.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d.c(APSServiceCore.java)
06-07 17:58:52.773 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d$a.run(APSServiceCore.java)
06-07 17:58:52.774 31095-32257/com.freetek.deepsea W/System.err: Caused by: java.lang.SecurityException: getAllCellInfo: Neither user 10549 nor current process has android.permission.ACCESS_COARSE_LOCATION.
06-07 17:58:52.774 31095-32257/com.freetek.deepsea W/System.err: at android.os.Parcel.readException(Parcel.java:1620)
06-07 17:58:52.774 31095-32257/com.freetek.deepsea W/System.err: at android.os.Parcel.readException(Parcel.java:1573)
06-07 17:58:52.774 31095-32257/com.freetek.deepsea W/System.err: at com.android.internal.telephony.ITelephony$Stub$Proxy.getAllCellInfo(ITelephony.java:3060)
06-07 17:58:52.774 31095-32257/com.freetek.deepsea W/System.err: at android.telephony.TelephonyManager.getAllCellInfo(TelephonyManager.java:2899)
06-07 17:58:52.774 31095-32257/com.freetek.deepsea W/System.err: ... 10 more
06-07 17:58:52.783 31095-32257/com.freetek.deepsea W/System.err: java.lang.SecurityException: getCellLocation: Neither user 10549 nor current process has android.permission.ACCESS_COARSE_LOCATION.
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at android.os.Parcel.readException(Parcel.java:1620)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at android.os.Parcel.readException(Parcel.java:1573)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.android.internal.telephony.ITelephony$Stub$Proxy.getCellLocation(ITelephony.java:2428)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at android.telephony.TelephonyManager.getCellLocation(TelephonyManager.java:831)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.loc.ce.d(CgiManager.java)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.loc.bv.G(APS.java)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.loc.bv.a(APS.java)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d.a(APSServiceCore.java)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d.c(APSServiceCore.java)
06-07 17:58:52.784 31095-32257/com.freetek.deepsea W/System.err: at com.loc.d$a.run(APSServiceCore.java)
问题原因
Android M(版本号6.0 api:23)对原来的权限系统做了升级。在6.0之前,Android系统的app的权限是在安装的时候申请的,用户同意安装后,无需再次申请。
这样的的设计系统有明显的弊端。用户安装时被app的功能吸引,不会仔细阅读权限,一般都直接点击安装了,甚至有些应用基本上申请了app级别的所有权限。这样由权限来保障的安全系统几乎就不起作用了。
所以在很多第三方开发的Android系统里面,会对一些敏感权限,如 地理位置获取、打电话、发短信 进行限制,当app执行相关api时,会弹出提醒,让用户确认是否可行。
6.0上Google也试图来解决这个问题,但是它的解决方案比第三方要粗暴——开发者必须在调用接口前再次确定权限,否则直接拒绝。所以就出现了一开始的那个错误
java.lang.SecurityException: getCellLocation: Neither user 10549 nor current process has android.permission.ACCESS_COARSE_LOCATION.
吐槽一下:这个解决方式太坑爹了,原生系统应该向miui它们学学,对开发者友好一点。
问题解决
解决方案有两种:
不要用23的sdk编译,即 targetSdkVersion和compileSdkVersion不要等于23。基于兼容性原则,Android对用23已下sdk编译的app依然使用旧的权限模型。
自己在需要用到权限前进行权限判断,提醒用户打开相应的权限。相关代码参考github的开源工程PermissionsChecker。
Panda
2016-06-07