尝试在 Android 中选取图像时出现 TransactionTooLargeException 和 FAILED BINDER TRANSACTION
TransactionTooLargeException and FAILED BINDER TRANSACTION when trying to pick images in Android
我使用 3 个片段在选项卡布局中显示,下一个问题涉及其中一个片段。
我试图在我的应用程序中选择单个或多个图像,我使用按钮和下一个代码打开图像选择器:
btn_galeria.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, 10);
}
else {
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select picture"), PICK_IMAGE_MULTIPLE);
}
}
});
但是一旦图像选择器打开,应用就会出现以下结果之一:
- 使用 Android 模拟器 API 23: logcat 显示
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2572096)
`图像选择器出现并且应用程序保持 运行,我能够 select 图像和应用程序按预期工作。
- 使用物理设备 Huawei P30 Lite API 29:同样的错误
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 6639520)
,但这一次,即使图像选择器出现,应用程序在后台崩溃,原因如下:
2020-07-07 02:02:51.311 31240-31240/com.ssp.atencionvictimas E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ssp.atencionvictimas, PID: 31240
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 6639520 bytes
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: android.os.TransactionTooLargeException: data parcel size 6639520 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:526)
at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4561)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
2020-07-07 02:02:51.317 31240-31240/com.ssp.atencionvictimas I/Process: Sending signal. PID: 31240 SIG: 9
基本上我想要做的是让用户选择一个或多个图像(如果可能最多 6 个)并使用已经制作的视图适配器显示 selected 图像。
这是在用户 select 编辑图像后执行的代码:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Esta sección de código se ejecuta cuando se termina un Intent, y se regresa al Activity anterior
if(requestCode == 1 && resultCode == RESULT_OK) {
List<Bitmap> bitmaps = new ArrayList<>();
ClipData clipdata = data.getClipData();
ArrayList<Uri> mArrayUri = new ArrayList<>();
ArrayList<String> ListaUris = new ArrayList<>();
if(clipdata != null) {
for(int i=0; i<clipdata.getItemCount(); i++) {
Uri imageUri = clipdata.getItemAt(i).getUri();
mArrayUri.add(imageUri);
try {
InputStream is = getActivity().getApplicationContext().getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
bitmaps.add(bitmap);
Log.v("LOG_TAG", "URI DE IMAGEN: " + imageUri);
// Will return "image:x*"
String wholeID = DocumentsContract.getDocumentId(imageUri);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = getActivity().getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
String filePath = "";
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
ListaUris.add(filePath);
Log.v("LOG_TAG", "FILEPATH: " + filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
else {
Uri imageUri = data.getData();
mArrayUri.add(imageUri);
try {
InputStream is = getActivity().getApplicationContext().getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
bitmaps.add(bitmap);
Log.v("LOG_TAG", "URI DE IMAGEN: " + imageUri);
// Will return "image:x*"
String wholeID = DocumentsContract.getDocumentId(imageUri);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = getActivity().getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
String filePath = "";
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
ListaUris.add(filePath);
Log.v("LOG_TAG", "FILEPATH: " + filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
galleryAdapter = new GalleryAdapter(getActivity().getApplicationContext(),mArrayUri);
gvGallery.setAdapter(galleryAdapter);
gvGallery.setVerticalSpacing(gvGallery.getHorizontalSpacing());
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) gvGallery
.getLayoutParams();
mlp.setMargins(0, gvGallery.getHorizontalSpacing(), 0, 0);
Log.v("LOG_TAG", "CANTIDAD DE FOTOS: " + ListaUris.size());
Log.v("LOG_TAG", "LISTA DE URIS: " + ListaUris);
}
}
但即使我注释掉之前的代码,同样的行为也会发生,所以我相信这与意图 returns 或处理图库数据的方式有关。
我通过在片段 class:
上添加下一个方法覆盖来解决
@Override
public void onSaveInstanceState(Bundle outState) {
if (outState != null)
outState.clear();
}
我使用 3 个片段在选项卡布局中显示,下一个问题涉及其中一个片段。
我试图在我的应用程序中选择单个或多个图像,我使用按钮和下一个代码打开图像选择器:
btn_galeria.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, 10);
}
else {
Intent intent = new Intent();
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select picture"), PICK_IMAGE_MULTIPLE);
}
}
});
但是一旦图像选择器打开,应用就会出现以下结果之一:
- 使用 Android 模拟器 API 23: logcat 显示
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 2572096)
`图像选择器出现并且应用程序保持 运行,我能够 select 图像和应用程序按预期工作。 - 使用物理设备 Huawei P30 Lite API 29:同样的错误
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 6639520)
,但这一次,即使图像选择器出现,应用程序在后台崩溃,原因如下:
2020-07-07 02:02:51.311 31240-31240/com.ssp.atencionvictimas E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ssp.atencionvictimas, PID: 31240
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 6639520 bytes
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:161)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: android.os.TransactionTooLargeException: data parcel size 6639520 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(BinderProxy.java:526)
at android.app.IActivityTaskManager$Stub$Proxy.activityStopped(IActivityTaskManager.java:4561)
at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:145)
at android.os.Handler.handleCallback(Handler.java:888)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
2020-07-07 02:02:51.317 31240-31240/com.ssp.atencionvictimas I/Process: Sending signal. PID: 31240 SIG: 9
基本上我想要做的是让用户选择一个或多个图像(如果可能最多 6 个)并使用已经制作的视图适配器显示 selected 图像。
这是在用户 select 编辑图像后执行的代码:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Esta sección de código se ejecuta cuando se termina un Intent, y se regresa al Activity anterior
if(requestCode == 1 && resultCode == RESULT_OK) {
List<Bitmap> bitmaps = new ArrayList<>();
ClipData clipdata = data.getClipData();
ArrayList<Uri> mArrayUri = new ArrayList<>();
ArrayList<String> ListaUris = new ArrayList<>();
if(clipdata != null) {
for(int i=0; i<clipdata.getItemCount(); i++) {
Uri imageUri = clipdata.getItemAt(i).getUri();
mArrayUri.add(imageUri);
try {
InputStream is = getActivity().getApplicationContext().getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
bitmaps.add(bitmap);
Log.v("LOG_TAG", "URI DE IMAGEN: " + imageUri);
// Will return "image:x*"
String wholeID = DocumentsContract.getDocumentId(imageUri);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = getActivity().getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
String filePath = "";
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
ListaUris.add(filePath);
Log.v("LOG_TAG", "FILEPATH: " + filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
else {
Uri imageUri = data.getData();
mArrayUri.add(imageUri);
try {
InputStream is = getActivity().getApplicationContext().getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
bitmaps.add(bitmap);
Log.v("LOG_TAG", "URI DE IMAGEN: " + imageUri);
// Will return "image:x*"
String wholeID = DocumentsContract.getDocumentId(imageUri);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = getActivity().getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
String filePath = "";
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
ListaUris.add(filePath);
Log.v("LOG_TAG", "FILEPATH: " + filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
galleryAdapter = new GalleryAdapter(getActivity().getApplicationContext(),mArrayUri);
gvGallery.setAdapter(galleryAdapter);
gvGallery.setVerticalSpacing(gvGallery.getHorizontalSpacing());
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) gvGallery
.getLayoutParams();
mlp.setMargins(0, gvGallery.getHorizontalSpacing(), 0, 0);
Log.v("LOG_TAG", "CANTIDAD DE FOTOS: " + ListaUris.size());
Log.v("LOG_TAG", "LISTA DE URIS: " + ListaUris);
}
}
但即使我注释掉之前的代码,同样的行为也会发生,所以我相信这与意图 returns 或处理图库数据的方式有关。
我通过在片段 class:
上添加下一个方法覆盖来解决@Override
public void onSaveInstanceState(Bundle outState) {
if (outState != null)
outState.clear();
}