web-dev-qa-db-ja.com

ヌガーでのみTransactionTooLargeException

AndroidバージョンがNougatより前のデバイスでうまく機能するアプリを使用しました。

Nougatを搭載したデバイスでアプリを起動し、ホームボタンを押すと、アプリがクラッシュし、logcatに次のように表示されます。

!!! FAILED BINDER TRANSACTION !!!  (parcel size = 1819712)
Unhandled exception
Java.lang.RuntimeException: Android.os.TransactionTooLargeException: data parcel size 1819712 bytes
    at Android.app.ActivityThread$StopInfo.run(ActivityThread.Java:3781)
    at Android.os.Handler.handleCallback(Handler.Java:751)
    at Android.os.Handler.dispatchMessage(Handler.Java:95)
    at Android.os.Looper.loop(Looper.Java:154)
    at Android.app.ActivityThread.main(ActivityThread.Java:6119)
    at Java.lang.reflect.Method.invoke(Native Method)
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:886)
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:776)
 Caused by: Android.os.TransactionTooLargeException: data parcel size 1819712 bytes
    at Android.os.BinderProxy.transactNative(Native Method)
    at Android.os.BinderProxy.transact(Binder.Java:615)
    at Android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.Java:3636)
    at Android.app.ActivityThread$StopInfo.run(ActivityThread.Java:3773)
    at Android.os.Handler.handleCallback(Handler.Java:751) 
    at Android.os.Handler.dispatchMessage(Handler.Java:95) 
    at Android.os.Looper.loop(Looper.Java:154) 
    at Android.app.ActivityThread.main(ActivityThread.Java:6119) 
    at Java.lang.reflect.Method.invoke(Native Method) 
    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:886) 
    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:776) 

簡単な解決策はありますか?この問題はヌガーでのみ発生します。

6
Marcin Bortel

私も同じ問題を抱えてる。これはグーグルフォーラムの多くの開発者によって不平を言われています。彼らの答えは、州内にあまり多くのデータを保存することを推奨していないため、WAI(意図したとおりに機能する)です。したがって、アドバイスは、非常に基本的な引数のみをインテントに追加することです。アクティビティまたはフラグメント間でデータを送信する場合は、

  • データを(一時)ファイルに保存し、ファイルURIを渡します。大量のデータをまったく別のアプリに転送する場合は、このオプションがおそらく唯一のオプションです。アプリケーションインスタンスにデータを保存します。
  • 渡すデータを保持するシングルトンコンテナを作成します。
  • FragmentStatePageAdapterを使用している場合は、状態データが保存されないように、次のコードを追加してください。

    @Override    
    public Parcelable saveState() {
            Bundle bundle = (Bundle) super.saveState();
            bundle.putParcelableArray("states", null); // Never maintain any states from the base class to avoid TransactionTooLargeException
            return bundle;
    }
    

参照:

https://issuetracker.google.com/issues/3710338

https://www.neotechsoftware.com/blog/Android-intent-size-limit

6
flame3

TransactionTooLargeExceptionクラスのドキュメントから

バインダートランザクションバッファーの固定サイズは制限されており、現在は1Mbであり、プロセスで進行中のすべてのトランザクションで共有されます。したがって、個々のトランザクションのほとんどが中程度のサイズであっても、進行中のトランザクションが多い場合、この例外がスローされる可能性があります。

下のAndroid APIに渡すデータのサイズを確認しましたか?

Android 7.0 /7.1などでデータを転送する前にこのサイズをログに記録することをお勧めします。おそらく異なるAndroidバージョンでは、データが異なる量のメモリを占有します。

1
Volodymyr

アクティビティにいくつかのフラグメントがあり、それぞれがonSaveInstanceを実行している場合は、さらに発生します。フラグメントonCreateViewが常にビューを再起動する場合(ビューステートを復元するためにOSは必要ありません)、rootview.setSaveFromParentEnabled(false);ビューのonSaveInstanceState()を防ぐため。これは役立つかもしれません。

0
lannyf

こっちも一緒。この問題の迅速な解決策はありません。

私の解決策は、データを一時的にデータベースまたはファイルに保存することでした。また、アクティビティとフラグメントの間で必要なデータのみを送信するだけです。

これは、膨大なデータを使用するほとんどのユースケースにとっても優れたデザインパターンだと思います。

0

データをファイルに保存することでこの問題を解決しました。ご回答ありがとうございます。

0
Marcin Bortel