尝试获取安装的应用程序列表时的TransactionTooLargeEception

And*_*rew 12 android

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

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

谁能想到我为什么会这样?

and*_*per 14

我发现这是在Android 5.1上解决的(在此证明,搜索"修复包管理器TransactionTooLargeExceptions"),因为它在多个地方报告:

但是,我想在5.1之前解决这个问题,所以我想出了一个解决方案(建议谷歌把它放在支持库上,这里).这是我建议的简短代码版本:

  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;
    }
Run Code Online (Sandbox Code Playgroud)

它首先尝试使用官方方式,然后,如果失败,它使用ADB命令获取包名称,并一个接一个地获取每个应用程序的信息.

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

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


编辑:人们声称它在Android 5.1上没有修复.我希望它在Android 6上得到修复.


Dur*_*amy 5

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

我担心在这种情况下,你不会做更好的事情.但是如果您正在执行类似applyBatch的操作,则可以将一个大事务分成多个较小的事务.

另外看一下这个线程在TransactionTooLargeException上做什么

  • @Andrew,我刚刚收到新的崩溃报告,在`getInstalledPackages(0)`调用中声明"程序包管理器已经死了".所以这似乎不是灵丹妙药.我还在寻找解决方案/解决方法. (3认同)
  • 而不是:List <ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA); 我现在正在使用:List <PackageInfo> packs = pm.getInstalledPackages(0); List <ApplicationInfo> packages = new ArrayList <ApplicationInfo>(); for(int i = 0; i <packs.size(); i ++){PackageInfo p = packs.get(i); if(p.versionName == null){continue; } try {packages.add(pm.getApplicationInfo(p.packageName,0)); } catch(NameNotFoundException e){Log.d(LOGTAG,"Package not found:"+ p.packageName); }} (2认同)