最近,收到两家大客户反馈的bug,都是咱们android版本sdk报的bug。既然大客户给咱们报bug了,那必须十分重视对待。java

第一个bug,SecurityException: Permission denied (missing INTERNET permission?)
初看一下觉得是网络权限的问题,难道客户没有添加网络的权限,这显然不可能。android
从stackoverflow上搜到这篇文章颇有帮助。大体了解出现这个bug的缘由。缓存
首先,android.permission.INTERNET并非惟一的网络相关权限,还须要声明一下android.permission.ACCESS_NETWORK_STATE这个权限。这个权限对于sdk而言,我仍是很纠结地,由于不少客户不必定会使用到这个权限。若是我多添加了这个权限的判断会致使一些客户没法使用sdk。网络
其次,在root过的设备上,用户能够经过工具来修改在运行时授予已安装应用的权限。同时,在某些定制的rom上也能够这么作的。app
再次,Android 6.0之后引入了全新的权限管理机制,称为运行时权限。它容许用户更多地控制授予的权限(也容许选择性授予),或容许一个撤销已授予的权限,无需应用程序删除。框架
知道这个bug产生的缘由以后,那咱们来解决问题吧。svg
解决方案:
在调用网络框架以前,把请求网络的request放入框架中http请求的队列以前,先判断一下权限是否已经添加:
<uses-permission android:name="android.permission.INTERNET" />工具
public void addToRequestQueue(Request req) { if (!Util.checkPermission(MWConfiguration.getContext(), "android.permission.INTERNET")) { return; } getRequestQueue().addRequest(req); }
添加了完权限的判断以后,能够把影响降到最低。spa
第两个bug,java.lang.RuntimeException: Package manager has died
这个bug也很奇葩,是这段代码形成的.net
/** * 得到当前应用的版本号 * * @param context context * @return App Version */ public static String getAppVersion(Context context) { String result = "1.0"; PackageInfo info = null; try { info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); } catch (NameNotFoundException ignored) { } if (info != null) { result = info.versionName; } return result; }
初看一下,没有任何问题。但为什么会引发了异常呢?
它是一个Binder调用,形成这个的缘由是由于发生了RemoteException。
若是Binder的使用超出了一个进程的限制就会抛TransactionTooLargeException这个异常。
经过查看源码发现,在一个进程中Binder的大小大约是1M。若是这时候恰巧在用getPackageManager()作其余事情,就会提示Package manager has died。
解决方案:
第一种办法,在getAppVersion()方法前加上synchronized。其余用到context.getPackageManager()的地方也尽可能加上synchronized
第二种办法,第一次获取完appVersion这种数据后放在一个地方缓存起来。之后每次直接读取缓存中的数据。
总结
写sdk的上辈子都是折翼天使,但愿之后不再要写sdk了,让我先去哭一下子去。固然这些是不可能的,写代码仍是必须严谨再严谨啊。
本文同步分享在 博客“fengzhizi715”(JianShu)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。