web-dev-qa-db-fra.com

Le gestionnaire de paquets Android est mort avec TransactionTooLargeException

Mon application lit la liste de tous les fichiers APK installés, puis parcourt la liste pour lire les informations sur l'APK. Cependant, une exception TransactionTooLargeException est levée.

D'après ce que j'ai lu ici http://developer.Android.com/reference/Android/os/TransactionTooLargeException.html , Google recommande de décomposer les transactions volumineuses en transactions plus petites. Cependant, il semble que cela se produise au milieu lorsque vous parcourez la liste des APK. Si j'attrape l'exception et la continue, le reste fonctionne parfaitement. Existe-t-il un moyen de réduire l'utilisation de la mémoire lors de l'appel de getPackageInfo? Est-ce que cet appel contient quelque chose même après son retour?.

Voici la trace quand c'est arrivé:

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)
10
Ray

Il existe une limite de 1 Mo pour une transaction de classeur, ce qui signifie que la plupart des invocations IPC doivent être de taille modeste.

Si vous rencontrez un échec du classeur TransactionTooLargeException ou similaire lorsque vous récupérez des données de PackageManager (par exemple, getPackageInfo()), essayez de fractionner votre demande en plusieurs appels, avec moins d'indicateurs (par exemple, GET_META_DATA) par appel. Espérons que cela réduira la taille de chaque transaction individuelle en dessous de la limite de 1 Mo.

De même, si vous utilisez des appels sur PackageManager qui renvoient plusieurs résultats (par exemple, getInstalledPackages(), essayez de demander no flags sur cet appel, puis récupérez les valeurs de chaque paquet individuellement, afin d'éviter de récupérer beaucoup de données sur beaucoup des entrées à la fois.

Et bien sûr, n'utilisez que les drapeaux dont vous avez besoin, en particulier si votre appel peut en contenir. GET_META_DATA en est un exemple classique: de nombreuses applications l’utilisent (par exemple, pour Play Services), mais si vous n’avez pas besoin de connaître les métadonnées, n’en demandez pas.

23
CommonsWare

J'ai trouvé un moyen de résoudre ce problème, et posté à ce sujet ici .

En bref, il trouve le nom des paquets des applications installées (à l’aide de ADB), puis obtient les informations les concernant, l’un après l’autre.

0