Activity 中啟動系統圖片選擇器:
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PHOTO_REQUEST_HEADER);
現象:打開相冊、點擊圖片後閃退回原 Activity。初期正常,代碼量增加後出現,懷疑生命周期或內存問題。
「這個要看代碼或 LOG 來分析,只從描述的現象很難找到原因。原因肯定是代碼的問題。實在找不到,就將代碼一步步重建、或者還原,看看是哪一步出了問題。」
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Android 10+ 可能需要 -->
<application android:requestLegacyExternalStorage="true" ... >
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHOTO_REQUEST_HEADER && resultCode == RESULT_OK && data != null) {
Uri selectedImage = data.getData();
// 關鍵:在單獨線程中處理耗時操作 (獲取路徑、壓縮、上傳等)
// 不要在主線程做 I/O 或複雜計算!
new Thread(() -> processImage(selectedImage)).start();
}
}
onCreate 中未正確恢復狀態,或 onActivityResult 邏輯有誤,會導致閃退/異常。onSaveInstanceState 保存必要狀態,onCreate / onRestoreInstanceState 恢復。相冊返回的圖片可能很大(如 4000×3000),直接 `BitmapFactory.decodeStream` 會爆內存。
private Bitmap decodeSampledBitmap(Uri uri, int reqWidth, int reqHeight) {
// 1. 先只解碼邊緣獲取尺寸
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
// 2. 計算采樣率
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 3. 真正解碼
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
}
Android 7.0+ (API 24) 禁止 `file://` Uri 跨應用傳遞,必須用 `FileProvider` 生成 `content://` Uri。若你的代碼中有拍照/裁剪/保存臨時文件邏輯,檢查 Uri 生成方式。
最直接的方法:連接設備/模擬器,過濾標籤 `Error` 或你的包名,捕獲閃退時的紅色異常信息:
// 在 Activity/Fragment 中註冊
private ActivityResultLauncher<Intent> pickImageLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
Uri uri = result.getData().getData();
// 處理圖片
}
}
);
// 啟動
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickImageLauncher.launch(intent);
優勢:生命周期感知、類型安全、避免 requestCode 衝突、自動處理 Activity 重建。