13

作为我的应用程序的一部分,我使用 ApplicationPackageManager.getInstalledApplications 获取设备上安装的应用程序列表,但对于某些用户,我收到崩溃报告说

android.osBinderProxy.tranasact 的 TransactionTooLargeException(本机方法)

谁能想到我为什么会得到这个?

4

2 回答 2

17

我发现这已在 Android 5.1 上解决(证明在这里,搜索“修复包管理器 TransactionTooLargeExceptions”),因为它在多个地方被报告:

但是,我想为 pre-5.1 解决这个问题,所以我想出了一个解决方案(并建议谷歌将它放在支持库中,here)。这是我建议的简短代码版本:

  public static List<PackageInfo> getInstalledPackages(Context context,int flags)
    {
    final PackageManager pm=context.getPackageManager();
    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;
    }

它的作用是先尝试使用官方的方式,然后如果失败,它会使用ADB命令获取包名,并依次获取每个应用程序的信息。

它比官方慢得多,但对我来说并没有崩溃。我已经在 Android 模拟器(包括 2.3.x 到 5.0.x)以及真实设备上对其进行了测试。

在我的设备(带有 Android 5.1 自定义 ROM 的 Galaxy S3)上花费的时间是 1375-2012 毫秒(总共 197 个应用程序),而使用官方方式则为 37-65 毫秒。


编辑:人们在这里声称它没有固定在 Android 5.1 上。我希望它在 Android 6 上得到修复。

于 2015-05-05T20:26:36.380 回答
5

在正常情况下,这种异常很难重现。当传输数据时 IPC 内存耗尽时,您将收到此异常。这可能发生在两种情况下,服务试图将数据放置到客户端或客户端正在将数据发送到服务。很可能您的一些用户可能已经安装了大量的应用程序,这导致数据大小大于 1MB(这是 IPC 缓冲区的大小)。

恐怕在这种情况下,你不会做得更好。但是,如果您正在执行类似 applyBatch 的操作,您可以将一个大事务拆分为多个较小的事务。

也看看这个线程What to do on TransactionTooLargeException

于 2012-11-05T17:32:35.933 回答