AsyncTask 和 getInstalledPackages() 失败

发布于 2024-12-14 10:40:57 字数 1397 浏览 1 评论 0原文

我真的不明白发生了什么,也许你可以给我一个想法。我使用 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);

有时 packages 包含所有已安装的应用程序,有时为 EMPTY。比如说,有 3 次,第 3 次是空的。从 AsyncTask 中取出这段代码并将其放在 getListData() 上,每次都可以正常工作,没有任何问题。问题是我有点冻结,因为操作不在后台线程上。 那么 AsyncTask 是怎么回事?我做错了什么吗?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

长梦不多时 2024-12-21 10:40:57

基本上,这个异常在 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;
    }

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;
    }
°如果伤别离去 2024-12-21 10:40:57

查看类似的SO问题此处,CommonsWare认为此方法需要参与UI线程,据我所知,这是唯一合理的解释。

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.

泅渡 2024-12-21 10:40:57

我提出了一个不同的解释:

IPC 缓冲区已满,并且在早期的 Android 版本(子 API15)上仅返回一个空列表,而在较新的 Android 版本上则会抛出 TransactionTooLargeException。

另请参阅:
PackageManager.getInstalledPackages() 返回空列表

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文