web-dev-qa-db-ja.com

AndroidパッケージマネージャーがTransactionTooLargeExceptionで死亡しました

私のアプリは、インストールされているすべてのAPKファイルのリストを読み取り、リストをループしてAPK情報を読み取りますが、TransactionTooLargeException例外をスローします。

私がここで読んだことから http://developer.Android.com/reference/Android/os/TransactionTooLargeException.html 、グーグルは大きなトランザクションを小さなトランザクションに分割することをお勧めします。ただし、APKリストをループするときにこれが途中で発生するようです。例外をキャッチして続行すると、残りはすべて正常に機能します。 getPackageInfoの呼び出し中にメモリ使用量を減らす方法はありますか?その呼び出しは、すでに戻った後でも何かを保持しますか?.

これが起こったときの痕跡です:

at Android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.Java:89)
at com.myapp.appreader.getAppDetails(Appreader.Java:207)
at com.myapp.appreader.collectData(Appreader.Java:99)
at com.myapp.appreader.AppDataCollectionTask.run(AppDataCollectionTask.Java:26)
at com.myapp.appreader.service.AppDataTaskExecutor$AppDataAsyncTask.executeTask(AppDataTaskExecutor.Java:439) 
at com.myapp.appreader.service.AppDataTaskExecutor$AppDataAsyncTask.doInBackground(AppDataTaskExecutor.Java:327)
at com.myapp.appreader.service.AppDataTaskExecutor$AppDataAsyncTask.doInBackground(AppDataTaskExecutor.Java:1)
at Android.os.AsyncTask$2.call(AsyncTask.Java:287)
at Java.util.concurrent.FutureTask.run(FutureTask.Java:234)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1080)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:573)
at Java.lang.Thread.run(Thread.Java:856)\nCaused by: Android.os.TransactionTooLargeExceptionat Android.os.BinderProxy.transact(Native Method)
at Android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.Java:1538)
at Android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.Java:84)
11
Ray

バインダートランザクションには1MBの制限があります。つまり、ほとんどのIPC呼び出しは適度なサイズである必要があります。

TransactionTooLargeExceptionからデータを取得するときにPackageManagerまたは同様のバインダーエラーが発生した場合(例:getPackageInfo())、フラグを少なくしてリクエストを複数の呼び出しに分割してみてください(例:呼び出しごとに_GET_META_DATA_)。うまくいけば、これにより、個々のトランザクションのサイズが1MBの制限を下回るように削減されます。

また、複数の結果を返すPackageManagerの呼び出しを使用している場合(たとえば、getInstalledPackages()の場合は、その呼び出しでnoフラグを要求してから、の値を取得してください。一度に多数のエントリに関する大量のデータを取得しないように、各パッケージを個別に。

そしてもちろん、特に呼び出しにフラグが含まれている可能性がある場合は、必要なフラグのみを使用してください。 _GET_META_DATA_はその典型的な例です。多くのアプリがそれを使用していますが(Play開発者サービスなど)、メタデータ情報を知る必要がない場合は、リクエストしないでください。

26
CommonsWare

私はこの問題を解決する方法を見つけ、それについて投稿しました ここ

つまり、インストールされているアプリのパッケージ名を(ADBを使用して)見つけて、それぞれの情報を次々に取得します。

0