我真的不明白发生了什么,也许你可以给我一个想法。我使用getInstalledPackages()来获取所有用户安装的应用程序及其权限的列表。我是这样做的:
private PackageManager pm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pm = getPackageManager();
getListData();
}
private void getListData()
{
backTask = new BackTask();
backTask.execute();
}
protected class BackTask extends AsyncTask<Context, String, ArrayList<App>>
{
....
@Override
protected ArrayList<App> doInBackground(Context... param)
{
try {
//get a list of installed apps.
List<PackageInfo> packages = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS);
for (PackageInfo packageInfo : packages) {
ApplicationInfo application = packageInfo.applicationInfo;
....
}
我需要刷新基于用户交互显示的列表。问题出现在AsyncTask的这一行:
List<PackageInfo> packages = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS);
有时包包含所有已安装的应用有时是EMPTY。比如说3次,第3次是空的。将此代码从AsyncTask中取出并放在getListData()上,每次都可以正常工作而不会出现任何问题。问题是我得到一点冻结,因为操作不在后台线程上。 那么与AsyncTask的交易是什么?我做错了吗?
答案 0 :(得分:1)
基本上,这个例外是在Android 5.1上修复的(或者至少是我在某处读过的),但是对于5.1之前的版本,你需要自己做一些事情。
您可以避免此异常崩溃,并使用shell获取已安装应用的完整列表,如我在此处所示:
https://code.google.com/p/android/issues/detail?id=172058
以下是代码:
public static List<PackageInfo> getInstalledPackages(Context context,int flags)
{
final PackageManager pm=context.getPackageManager();
//if it's Android 5.1, no need to do any special work
if(VERSION.SDK_INT>=VERSION_CODES.LOLLIPOP_MR1)
return pm.getInstalledPackages(flags);
//else, protect against exception, and use a fallback if needed:
try
{
return pm.getInstalledPackages(flags);
}
catch(Exception ignored)
{
//we don't care why it didn't succeed. We'll do it using an alternative way instead
}
// use fallback:
Process process;
List<PackageInfo> result=new ArrayList<>();
BufferedReader bufferedReader=null;
try
{
process=Runtime.getRuntime().exec("pm list packages");
bufferedReader=new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while((line=bufferedReader.readLine())!=null)
{
final String packageName=line.substring(line.indexOf(':')+1);
final PackageInfo packageInfo=pm.getPackageInfo(packageName,flags);
result.add(packageInfo);
}
process.waitFor();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
if(bufferedReader!=null)
try
{
bufferedReader.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
return result;
}
答案 1 :(得分:0)
检查一个类似的SO问题here,CommonsWare认为这个方法需要涉及UI线程,据我所知,这是唯一合理的解释。
答案 2 :(得分:0)
我提出了不同的解释:
IPC缓冲区运行完全,在早期的Android版本(子API15)上只返回一个空列表,而在较新的Android版本上会抛出TransactionTooLargeException。
另见: PackageManager.getInstalledPackages() returns empty list