使用ActivityResultLauncher拍照后未返回调用页面,直接回到主页面
在Activity中调用相机拍照,图片拍摄成功,但点击确认后未回到启动相机的页面,直接跳转至主页面。
代码实现
public void captureImage(){ ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, "Cust-" + customerName+ newCustomerID); values.put(MediaStore.Images.Media.DESCRIPTION, "From the Camera"); image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); cameraActivityResultLauncher.launch(image_uri); } ActivityResultLauncher<Uri> cameraActivityResultLauncher = registerForActivityResult( new ActivityResultContracts.TakePicture(), new ActivityResultCallback<Boolean>() { @Override public void onActivityResult(Boolean result) { if(result) { Bitmap inputImage = uriToBitmap(image_uri); Bitmap rotated = rotateBitmap(inputImage); imageView.setImageBitmap(rotated); } } }); //TODO takes URI of the image and returns bitmap private Bitmap uriToBitmap(Uri selectedFileUri) { try { ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(selectedFileUri, "r"); FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor); parcelFileDescriptor.close(); return image; } catch (IOException e) { e.printStackTrace(); } return null; } //TODO rotate image if image captured on samsung devices //TODO Most phone cameras are landscape, meaning if you take the photo in portrait, the resulting photos will be rotated 90 degrees. @SuppressLint("Range") public Bitmap rotateBitmap(Bitmap input){ String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION}; Cursor cur = getContentResolver().query(image_uri, orientationColumn, null, null, null); int orientation = -1; if (cur != null && cur.moveToFirst()) { orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0])); } Log.d("tryOrientation",orientation+""); Matrix rotationMatrix = new Matrix(); rotationMatrix.setRotate(orientation); Bitmap cropped = Bitmap.createBitmap(input,0,0, input.getWidth(), input.getHeight(), rotationMatrix, true); return cropped; }
Logcat日志
Handler (com.samsung.android.camera.core2.device.CamDeviceHandlerManager$ExecTimeLoggingHandler) {8f36486} 向已销毁线程的Handler发送消息
java.lang.IllegalStateException: Handler (com.samsung.android.camera.core2.device.CamDeviceHandlerManager$ExecTimeLoggingHandler) {8f36486} 向已销毁线程的Handler发送消息
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:560)
at android.os.Handler.enqueueMessage(Handler.java:778)
at android.os.Handler.sendMessageAtTime(Handler.java:727)
at android.os.Handler.sendMessageDelayed(Handler.java:697)
at android.os.Handler.post(Handler.java:427)
at com.samsung.android.camera.core2.device.CamDeviceImpl.lambda$createCaptureSessionInternal$2(CamDeviceImpl.java:634)
at com.samsung.android.camera.core2.device.-$$Lambda$CamDeviceImpl$5X5wiAbd03qI4TTgkJV3Zs0XzuA.accept(Unknown Source:4)
at java.util.Optional.ifPresent(Optional.java:179)
at com.samsung.android.camera.core2.device.CamDeviceImpl.lambda$createCaptureSessionInternal$3$CamDeviceImpl(CamDeviceImpl.java:634)
at com.samsung.android.camera.core2.device.-$$Lambda$CamDeviceImpl$ckQoqhLVTrOTDJwKo66Y0V6AUsk.execute(Unknown Source:2)
at android.hardware.camera2.impl.CallbackProxies$SessionStateCallbackProxy.onReady(CallbackProxies.java:74)
at android.hardware.camera2.impl.CameraCaptureSessionImpl$2.onIdle(CameraCaptureSessionImpl.java:843)
at android.hardware.camera2.impl.CameraDeviceImpl$6.run(CameraDeviceImpl.java:244)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.os.HandlerThread.run(HandlerThread.java:67)
解决方案
1. 处理Activity被回收的情况
拍照过程中原Activity可能因系统内存不足被销毁,返回时会重新启动任务栈的主Activity。需保存和恢复关键状态:
- 保存状态:
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (image_uri != null) { outState.putParcelable("image_uri", image_uri); } }
- 恢复状态:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); if (savedInstanceState != null) { image_uri = savedInstanceState.getParcelable("image_uri"); } // 初始化ActivityResultLauncher等组件 }
2. 检查Activity启动模式
确保当前Activity的launchMode为默认的standard,避免singleTask/singleInstance导致的任务栈异常:
<activity android:name=".YourCameraCallingActivity" android:launchMode="standard"/>
3. 优化图片存储方式(解决Samsung相机兼容性)
Log中的报错是Samsung相机内部问题,但改用私有目录存储可避免媒体库写入的潜在异常:
- 配置FileProvider(在Manifest中):
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider>
- 创建res/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="camera_photos" path="Pictures"/> </paths>
- 修改拍照方法:
public void captureImage(){ try { File imageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File imageFile = new File(imageDir, "Cust-" + customerName + newCustomerID + ".jpg"); image_uri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", imageFile); cameraActivityResultLauncher.launch(image_uri); } catch (Exception e) { e.printStackTrace(); } }
4. 修复代码中的资源泄漏与异常
- 关闭Cursor避免内存泄漏:
@SuppressLint("Range") public Bitmap rotateBitmap(Bitmap input){ String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION}; Cursor cur = getContentResolver().query(image_uri, orientationColumn, null, null, null); int orientation = -1; if (cur != null) { if (cur.moveToFirst()) { orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0])); } cur.close(); // 必须关闭Cursor } Log.d("tryOrientation", orientation + ""); Matrix rotationMatrix = new Matrix(); rotationMatrix.setRotate(orientation); return Bitmap.createBitmap(input, 0, 0, input.getWidth(), input.getHeight(), rotationMatrix, true); }
- 增加空值判断防止崩溃:
@Override public void onActivityResult(Boolean result) { if(result && image_uri != null) { Bitmap inputImage = uriToBitmap(image_uri); if (inputImage != null) { Bitmap rotated = rotateBitmap(inputImage); imageView.setImageBitmap(rotated); } } }
内容的提问来源于stack exchange,提问作者youssef SULTAN

