Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TransactionTooLargeEception when trying to get a list of applications installed

Tags:

android

As part of my app I get a list of apps installed on the device by using ApplicationPackageManager.getInstalledApplications but for some users I get crash reports saying that

TransactionTooLargeException at android.osBinderProxy.tranasact(Native Method)

Can anyone think why I'd get this?

like image 690
Andrew Avatar asked Nov 05 '12 16:11

Andrew


2 Answers

I've found that this was solved on Android 5.1 (proof here, search for "Fix package manager TransactionTooLargeExceptions") as it was reported on multiple places:

  • https://code.google.com/p/android/issues/detail?id=95749
  • https://code.google.com/p/android/issues/detail?id=93717
  • https://code.google.com/p/android/issues/detail?id=69276

However, I wanted to solve this for pre-5.1, so I've come up with a solution (and suggested Google to put it on the support library, here) . Here's a short code version of what I've suggested:

  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;
    }

What it does it to try using the official way first, and then, if failed, it fetches the package names using ADB command, and get the information of each of the apps, one after another.

It is much slower than the official one, but it didn't crash for me. I've tested it on Android emulators (2.3.x till 5.0.x, including), and on real devices too.

The time it took on my device (Galaxy S3 with custom rom of Android 5.1) is 1375-2012 ms (on 197 apps total) compared to 37-65 ms using the official way .


EDIT: people claim here that it's not fixed on Android 5.1 . I hope that it got fixed on Android 6 .

like image 125
android developer Avatar answered Oct 18 '22 05:10

android developer


This exception is kind of difficult to reproduce under normal circumstances. You will get this exception when there IPC memory is exhausted when transferring data. This can occur in both cases, where a service is trying to place data to client or a client is sending data to service. Most probably some of your users might have installed huge number of application, which results in a data size greater than 1MB (which is the size of IPC buffer).

I am afraid in this case, you will not be do anything better. But if you are doing something like, applyBatch, you can separate one large transaction to multiple smaller transactions.

Also have a look at this thread What to do on TransactionTooLargeException

like image 5
Durairaj Packirisamy Avatar answered Oct 18 '22 06:10

Durairaj Packirisamy