Package manager has died异常PackageInfo 引发 Crash
Android 获取 PackageInfo 引发 Crash 填坑
一般 Android 通过PackageInfo这个类来获取应用安装包信息,比如应用内包含的所有Activity名称、应用版本号之类的。PackageInfo通过PackageManager来获取,代码如下:
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
比如我们要获取应用版本号时:
public static int getVersionCode(Context context) {
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return info.versionCode;
}
Tip: 获取应用自身版本号,推荐使用BuildConfig.VERSION_CODE 方式,这里只是为了方便举例说明问题。
一般情况下,上面的方法是可以正常拿到数据的,但是在某些情况下这也可能会引发 java.lang.RuntimeException: Package manager has died 异常。
java.lang.RuntimeException: Package manager has died
at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:82)
为了分析引发 Package manager has died 这个问题的具体原因,我们先来看看 getPackageInfo 这个方法:
frameworks/base/core/java/android/app/ApplicationPackageManager.java:
@Override
public PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException {
try {
PackageInfo pi = mPM.getPackageInfo(packageName, flags, mContext.getUserId());
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
} throw new NameNotFoundException(packageName);
}
从上面可以看出,getPackageInfo 具体实现是一个 Binder 调用,造成这个的原因是因为发生了 RemoteException 。
Binder 调用为什么会造成 Exception,下面再来看看 Binder 代码frameworks/base/core/jni/android_util_Binder.cpp:
case FAILED_TRANSACTION:
ALOGE("!!! FAILED BINDER TRANSACTION !!!");
// TransactionTooLargeException is a checked exception, only throw from certain methods.
// FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
// but it is not the only one. The Binder driver can return BR_FAILED_REPLY
// for other reasons also, such as if the transaction is malformed or
// refers to an FD that has been closed. We should change the driver
// to enable us to distinguish these cases in the future.
jniThrowException(env, canThrowRemoteException
? "android/os/TransactionTooLargeException"
: "java/lang/RuntimeException", NULL);
break;
可以看出造成 Binder crash 抛出 RuntimeException 是因为获取应用 PackageInfo 中数据量太大了,超出了 Binder 可传递的最大容量,进而导致 PackageManager 崩溃。
对于上面这种情况,考虑如果只获取versionName和versionCode两个信息,不需要Activity等信息,设法让PackageInfo的信息量小点,避免超出了 Binder 可传递的最大容量。
我们可以利用 getPackageInfo(String packageName, @PackageInfoFlags int flags) 它的第二个参数 flag ,使得该方法返回的对象容量减小,比如使用 PackageManager.GET_CONFIGURATIONS
此外,如果对与Binder的同时调用超出了限制就会抛出 TransactionTooLargeException这个异常,虽然这种场景比较少见,但是我们还是有比较避免多个线程同时来调用Binder就可以了。
优化后代码如下:
public static int getVersionCode(Context context) {
synchronized(Hold.class){
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_CONFIGURATIONS);
return info.versionCode;
}
}
Package manager has died异常PackageInfo 引发 Crash的更多相关文章
- [Android Pro] 分析 Package manager has died
reference to : http://blog.csdn.net/xxooyc/article/details/50162523 这是今天遇到的一个issue,由于Binder造成的.虽然比较简 ...
- Visual Studio 2015 新建MVC项目 Package Manager Console不能使用 (HRESULT: 0x80131500)
Visual studio 2015 突然新建不了MVC项目,报出错误: HRESULT: 0x80131500 在折腾了很长时间,最后在Github上看到这样一个贴 地址:https://githu ...
- 你需要知道的包管理器(Package Manager)
最近我花了一点时间关注了在不同系统之中所用到的包管理器(Package Manager) .最开始的时候,我是在使用Linux操作系统时,对这种工具以及它背后的想法深深迷恋住了:这真是自由的软件世界. ...
- 解决VS2015启动时Package manager console崩溃的问题 - Windows PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope
安装VS2015,启动以后,Package manager console崩溃,错误信息如下: Windows PowerShell updated your execution policy suc ...
- Error: Could not access the Package Manager. Is the system running?
最近在搭建cordova,android 开发环境,安装android studio之后创建一个demo之后,运行想看一下效果,在运行过程中创建一个虚拟机(arm)的,等了有1分钟左右,再次运行程序, ...
- Visual Studio 2010 更新NuGet Package Manager出错解决办法
在Visual Studio 2010的扩展管理器中发现NuGet Package Manger有最新版本更新提示,选择更新安装提示以下错误信息: 2013/4/25 1:11:48 - Micros ...
- Getting and installing the PEAR package manager
Windows After you have downloaded and installed PHP, you have to manually execute the batch file loc ...
- RPM是RedHat Package Manager(RedHat软件包管理工具)
RPM是RedHat Package Manager(RedHat软件包管理工具)类似Windows里面的“添加/删除程序” rpm 执行安装包二进制包(Binary)以及源代码包(Source)两种 ...
- installation - How to install Synaptic Package Manager? - Ask Ubuntu
installation - How to install Synaptic Package Manager? - Ask Ubuntu How to install Synaptic Package ...
随机推荐
- CSP-J&S 游记以及总结
前言 以前的比赛没有写什么总结,都只注重结果,没有注重过程,不知道如何才能在比赛中拿到高分,因此这次CSP才会考得一塌糊涂. 从此吸取教训,每场比赛都要总结经验,每场比赛都要尽全力考,每个题目都要尽全 ...
- Mongodb的几条命令
最近.... #设置用户名密码db.createUser({user: 'root', pwd: '123456', roles: ['root']}) #开启认证nohup mongod --aut ...
- 【leetcode】313. Super Ugly Number
题目如下: 解题思路:总结一下这么几点,一出一进,优先级队列排序,保证每次输出的都是当前的最小值.解法大致如图: 代码如下: #include<map> #include<queue ...
- LeetCode--617--合并二叉树(python)
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新的二叉树.合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 ...
- github上.md的编写
# algs4 一:大标题 =========== 二:中标题 ------------ 三:1~6级标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 # ...
- mysql IN操作符 语法
mysql IN操作符 语法 作用:在 WHERE 子句中规定多个值.深圳大理石平台 语法:SELECT column_name(s) FROM table_name WHERE column_nam ...
- [USACO17JAN]Promotion Counting 题解
前言 巨佬说:要有线段树,结果蒟蒻打了一棵树状数组... 想想啊,奶牛都开公司当老板了,我还在这里码代码,太失败了. 话说奶牛开个公司老板不应该是FarmerJohn吗? 题解 刚看到这道题的时候竟然 ...
- nginx 静态资源WEB服务
1.静态资源类型 非服务器动态运行生成的文件 类型种类 浏览器端渲染 HTML.CSS.JS 图片 JPEG.GIF.PNG 视频 FLV.MPEG ...
- RabbitMQ 工作图解
(转网上的图) (原文地址 ,http://www.cnblogs.com/knowledgesea/p/5296008.html)
- permutation 2
permutation 2 猜了发结论过了== $N$个数的全排列,$p_{1}=x,p_{2}=y$要求$|p_{i+1}-p_{i}|<=2|$求满足条件的排列个数. 首先考虑$x=1,y= ...