13

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?

Andrew
  • 7,548
  • 7
  • 50
  • 72

2 Answers2

18

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:

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 .

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Your solution uses getInstalledPackages() instead of getInstalledApplications. Is there a reason? Is it work only with first version? – greywolf82 Jun 13 '15 at 16:36
  • @greywolf82 I'm pretty sure they both can get the same issue. It could be that "getInstalledApplications" holds a bit smaller objects (since PacakgeInfo has more thing you can do with it), which might have this issue on a larger number of apps compared to getInstalledPackages. Anyway, both of those functions will return you the list of installed apps. – android developer Jun 13 '15 at 21:30
  • I just got the TransactionTooLarge exception on a Sony Experia Z3 running 5.1.1 – guy.gc Oct 18 '15 at 07:16
  • @androiddeveloper yes I have and I've implemented your solution in my app. So far works good - the only down side to it, is that it's considerably slower than calling queryIntentActivities. – guy.gc Oct 18 '15 at 14:54
  • @guy.gc So my code saved your app from crashing, no? Sadly, it is very slow, but at least it works. – android developer Oct 18 '15 at 18:08
  • The fix you cite is only a fix within one of the android applications. It does not fix the package manager itself. This is the fix: https://android.googlesource.com/platform/packages/apps/ContactsCommon/+/4e3a17e%5E!/ – David Liu Nov 09 '15 at 19:51
  • @DavidLiu Sure it's not a fix. It's a workaround that allows to still avoid a crash while getting the result. I don't see the fix on the link you've provided. – android developer Nov 09 '15 at 20:31
  • 1
    I'm not referring to your code's workaround. I'm talking about your first sentence, where you said it was fixed in 5.1. It's not fixed in 5.1, or at least the fix you're pointing at doesn't do what you think it does. – David Liu Nov 09 '15 at 20:45
  • @DavidLiu Oh. Ok. Is it fixed then on Android 6, perhaps? And, how come Google said it's fixed (here: https://code.google.com/p/android/issues/detail?id=93717#c11 ) ? – android developer Nov 10 '15 at 08:30
  • 1
    Like they said, they fixed the problem. However, their definition of the problem is not the IPC binder size limit, but rather specifically the ContactsProvider crashing. As I quote from them: "Yes, we switched to a safer version of PackageManager method in 5.1, which knows how to circumvent the binder size limit." He makes no mention of actually fixing the problem in PackageManager. This is his actual fix: https://github.com/android/platform_packages_providers_contactsprovider/commit/6522ca9 – David Liu Nov 11 '15 at 20:48
  • Whether getInstalledPackages (which he switched to) actually circumvents the IPC size limit or he's just completely mistaken, I have no idea. – David Liu Nov 11 '15 at 20:49
  • @DavidLiu Do you see this issue occur on Android 6 ? Do you know of a better workaround? Can you please post a new issue there, too? I will star it of course. – android developer Nov 12 '15 at 08:47
  • I don't have access to an Android 6 device yet. I'll let you know when I do. – David Liu Nov 12 '15 at 19:47
  • @DavidLiu It's quite a rare issue, and I think it occurs only when there are a lot of apps, no? – android developer Nov 13 '15 at 08:07
  • This problem is NOT fixed at all on Android 5.1, it's still there. Google doesn't fix the problem, it has implemented workaround just to bypass the size problem. I don't know if this problem is applicable to Android 6 too. – greywolf82 Jan 17 '16 at 08:24
  • @OmervanKloeten Why? what happens instead? Also, it's not a hack. It's a workaround. calling adb commands should be fine. Is it possible the output format is different? In the loop, try to use the log to write what the output is. – android developer Mar 02 '16 at 07:44
  • @androiddeveloper We get an empty list. No error, no warning, just an empty list. Trust me, we'd have loved for this to work but it just doesn't :/ – Omer van Kloeten Mar 02 '16 at 12:08
  • @OmervanKloeten Please try to write to the log the lines that loop handles. Also, try to connect to PC, and run the command. – android developer Mar 02 '16 at 13:44
  • NOT FIXED IN 6.0.1 – Dhaval Parmar Feb 07 '19 at 07:05
  • @DhawalSodhaParmar Does it happen on newer devices though? – android developer Feb 09 '19 at 22:12
5

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

Community
  • 1
  • 1
Durairaj Packirisamy
  • 4,635
  • 1
  • 21
  • 27
  • Thanks for that. Do you know if there's a way to get the Application Info in a different way? I don't necessarily need every app with all it's info in one go. It would probably be better if I could just get a list of the apps and then query for individual ones to get the required ApplicationInfo object back so the transaction wasn't as large. – Andrew Nov 06 '12 at 10:07
  • I can see PackageManager getApplicationInfo (String packageName, int flags) which looks like it can do this. I guess I can combine this with: getInstalledPackages to possibly get the data without hitting this problem. – Andrew Nov 06 '12 at 10:18
  • 2
    Instead of: List packages = pm.getInstalledApplications(PackageManager.GET_META_DATA); I'm now using:List packs = pm.getInstalledPackages(0); List packages = new ArrayList(); for(int i=0;i – Andrew Nov 06 '12 at 21:55
  • This looks good. In the first place, were you able to reproduce this issue? – Durairaj Packirisamy Nov 07 '12 at 00:26
  • I've never been able to reproduce it, but I certainly know quite a few users report it. The new code is working, but whether it'll fix the issue is hard to tell until I get the reports through. – Andrew Nov 07 '12 at 13:06
  • Well it seems to have fixed the issue as I'm not getting reports of this anymore. Thanks – Andrew Nov 22 '12 at 12:04
  • 3
    @Andrew, I've just got new crash report, stating that "Package manager has died" at `getInstalledPackages(0)` call. So this seems to be not a panacea. I'm still looking for a solution/workaround. – Stan Jun 01 '14 at 10:40
  • Does anyone know perhaps what's the expected number of apps that can trigger this issue? Also, it seems to be fixed only on Android 5.1 : https://code.google.com/p/android/issues/detail?id=93717 – android developer May 05 '15 at 17:11
  • Never mind. Found a solution. I've put the answer here. – android developer May 05 '15 at 20:20