Android 包管理器因 TransactionTooLargeException 而死亡

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24253976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:55:56  来源:igfitidea点击:

Android Package manager has died with TransactionTooLargeException

androidexceptiontransactionsandroid-package-managers

提问by Ray

My app reads the list of all installed APK files, and then loop through the list to read the APK info, however it throws a TransactionTooLargeException exception.

我的应用程序读取所有已安装 APK 文件的列表,然后遍历列表以读取 APK 信息,但是它会引发 TransactionTooLargeException 异常。

From what I have read here http://developer.android.com/reference/android/os/TransactionTooLargeException.html, google recommends to break large transactions into smaller transactions. However it seems this happens in the middle when looping through the APK list. If I catch the exception and continue it, the rest all works fine. Is there a way to reduce the memory usage while calling the getPackageInfo? Does that call hold some thing even after it already returned.

从我在这里读到的http://developer.android.com/reference/android/os/TransactionTooLargeException.html,谷歌建议将大交易分解为小交易。然而,当循环遍历 APK 列表时,这似乎发生在中间。如果我捕获异常并继续它,其余的一切正常。有没有办法在调用 getPackageInfo 时减少内存使用量?即使在它已经返回之后,该调用是否仍然保留某些内容。

Here is the trace when it happened:

这是它发生时的踪迹:

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.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)

回答by CommonsWare

There is a 1MB limit on a Binder transaction, which means most IPC invocations have to be modest in size.

Binder 事务有 1MB 的限制,这意味着大多数 IPC 调用的大小必须适中。

If you hit a TransactionTooLargeExceptionor similar Binder failures when retrieving data from PackageManager(e.g., getPackageInfo()), try splitting your request over multiple calls, with fewer flags (e.g., GET_META_DATA) per call. Hopefully this will reduce the size of any individual transaction to be under the 1MB limit.

如果您TransactionTooLargeException在从PackageManager(例如getPackageInfo())检索数据时遇到或类似的 Binder 故障,请尝试将您的请求拆分为多个调用,GET_META_DATA每个调用使用较少的标志(例如)。希望这会将任何单个事务的大小减少到 1MB 限制以下。

Also, if you are using calls on PackageManagerthat return multiple results (e.g., getInstalledPackages(), try asking for noflags on that call, then retrieving the values for each package individually, to avoid getting a lot of data on a lot of entries at once.

此外,如果您正在使用PackageManager返回多个结果的调用(例如,getInstalledPackages()尝试在该调用上要求任何标志,然后分别检索每个包的值,以避免一次获取大量条目的大量数据。

And, of course, only use flags that you need, particularly if your call might contain some. GET_META_DATAis a classic example of that: many apps use it (e.g., for Play Services), but if you do not need to know the metadata information, don't request it.

而且,当然,只使用您需要的标志,特别是如果您的呼叫可能包含一些标志。GET_META_DATA这是一个典型的例子:许多应用程序都使用它(例如,用于 Play 服务),但如果您不需要知道元数据信息,请不要请求它。

回答by android developer

I've found a way to solve this issue, and posted about it here.

我找到了解决此问题的方法,并在此处发布了相关信息

In short, it finds the installed apps' pacakges names (using ADB) and then get the information about each of them, one after another.

简而言之,它会查找已安装应用程序的包名称(使用 ADB),然后一个接一个地获取有关每个应用程序的信息。