问题
I don't really understand what is happening and maybe you can give me an idea. I use getInstalledPackages() in order to get a list of all user installed applications and their permissions. Here is how I do it:
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;
....
}
I need to refresh the list displayed based on user interaction. The problem appears at this line in AsyncTask:
List<PackageInfo> packages = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS);
Sometimes packages contains all the installed apps sometimes is EMPTY. Let's say for example out of 3 times, the 3rd time is empty. Taking this code out of AsyncTask and put it on getListData() works every single time without any problems. The issue is that I get a little freeze because operation is not on a back thread. So what's the deal with AsyncTask ? Am I doing something wrong ?
回答1:
Check out a similar SO question here, CommonsWare argues that this method need to be involved in UI thread, As far as I can see, this is the only reasonable explanation.
回答2:
Basically, this exception was fixed on Android 5.1 (or at least that's what I've read somewhere), but for pre-5.1, you need to do something on your own.
You can avoid having a crash of this exception and get a full list of the installed apps by using the shell, as I've shown here:
https://code.google.com/p/android/issues/detail?id=172058
Here's the code:
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;
}
回答3:
I'm proposing a different explanation:
The IPC buffer runs full and on earlier Android versions (sub API15) just an empty list is returned while on newer Android versions a TransactionTooLargeException is thrown.
Also see: PackageManager.getInstalledPackages() returns empty list
来源:https://stackoverflow.com/questions/8079832/asynctask-and-getinstalledpackages-fail