Android Studio中基于ActivityResultLauncher的图片上传实现问题求助
排查ActivityResultLauncher实现图片选择功能的问题
我在Android Studio中实现图片上传功能,由于StartActivityForResult已被弃用,改用ActivityResultLauncher的新方式实现,但功能无法正常运行,以下是我的Java类代码,恳请帮忙排查问题:
package com.example.gas4u; // 注:代码缺少常量定义(如STORAGE_REQUEST_CODE、CAMERA_REQUEST_CODE)、权限数组定义(storagePermission、cameraPermissions) // 以及productIconIv、image_uri等变量声明 private void showImagePickDialog() { //options to display in dialog String[] options = {"Camera","Gallery"}; //dialog AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Pick Image") .setItems(options, new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which){ //handle items clicks if (which == 0){ //camera clicked if (checkCameraPermission()){ //permission granted pickFromCamera(); } else{ //permission not granted, request requestCameraPermission(); } } else{ //gallery clicked if (checkStoragePermission()){ //permission granted pickFromGallery(); } else{ //permission not granted requestStoragePermission(); } } } }).show(); } // You can do the assignment inside onAttach or onCreate, i.e, before the activity is displayed ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result ) { if (result.getResultCode() == Activity.RESULT_OK) { // There are no request codes Intent data = result.getData(); if (result.getResultCode() == IMAGE_PICK_GALLERY_CODE){ //image picked from gallery //save picked image uri image_uri = data.getData(); //set image productIconIv.setImageURI(image_uri); } else if (result.getResultCode() == IMAGE_PICK_CAMERA_CODE){ //image picked from camera productIconIv.setImageURI(image_uri); } } } }); private void pickFromGallery(){ //intent to pick image from gallery Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); someActivityResultLauncher.launch(intent); //(intent, IMAGE_PICK_GALLERY_CODE); } private void pickFromCamera(){ //intent to pick image from camera //using media store to pick high/original quality image ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.TITLE, "Temp_Image_Title"); contentValues.put(MediaStore.Images.Media.DESCRIPTION, "Temp_Image_Description"); image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); Intent intent= new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri); someActivityResultLauncher.launch(intent); //startActivityForResult(intent, IMAGE_PICK_CAMERA_CODE); } private boolean checkStoragePermission(){ boolean result = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED); return result; //returns true or false } private void requestStoragePermission(){ ActivityCompat.requestPermissions(this, storagePermission, STORAGE_REQUEST_CODE); } private boolean checkCameraPermission(){ boolean result = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == (PackageManager.PERMISSION_GRANTED); boolean result1 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED); return result && result1; } private void requestCameraPermission(){ ActivityCompat.requestPermissions(this, cameraPermissions, CAMERA_REQUEST_CODE); } //handle permission results public void onRequestPermissionResult(int requestCode, @NonNull String[] permission, @NonNull int[] grantResults){ switch (requestCode){ case CAMERA_REQUEST_CODE:{ if (grantResults.length>0){ boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; boolean storageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED; if (cameraAccepted && storageAccepted){ //both permission granted pickFromCamera(); } else{ //both or one permissions denied Toast.makeText(this, "Camera & Storage permissions are required...", Toast.LENGTH_SHORT).show(); } } } case STORAGE_REQUEST_CODE:{ if (grantResults.length>0){ boolean storageAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; if (storageAccepted){ //permission granted pickFromGallery(); }else{ //permission denied Toast.makeText(this, "Storage permissions is required...", Toast.LENGTH_SHORT).show(); } } } } super.onRequestPermissionsResult(requestCode, permission, grantResults); }
问题排查与修复方案
1. 核心错误:ActivityResult回调无法区分相机/图库来源
新的ActivityResultLauncher没有请求码,回调中的result.getResultCode()只能是RESULT_OK或RESULT_CANCELED,无法通过它判断是相机还是图库返回的结果。
修复方式:创建两个独立的ActivityResultLauncher,分别处理相机和图库的结果:
// 处理图库选择 ActivityResultLauncher<Intent> galleryLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { image_uri = result.getData().getData(); productIconIv.setImageURI(image_uri); } }); // 处理相机拍摄 ActivityResultLauncher<Intent> cameraLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { // 相机拍摄的图片已通过image_uri保存,直接设置即可 productIconIv.setImageURI(image_uri); } }); // 修改pickFromGallery方法 private void pickFromGallery(){ Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); galleryLauncher.launch(intent); } // 修改pickFromCamera方法 private void pickFromCamera(){ ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.TITLE, "Temp_Image_Title"); contentValues.put(MediaStore.Images.Media.DESCRIPTION, "Temp_Image_Description"); image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); Intent intent= new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri); cameraLauncher.launch(intent); }
2. 权限回调方法名拼写错误
原代码中的onRequestPermissionResult少了一个s,正确方法名是onRequestPermissionsResult,这个错误会导致权限申请后的回调逻辑完全不执行,必须修正:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){ switch (requestCode){ case CAMERA_REQUEST_CODE:{ if (grantResults.length>0){ boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; boolean storageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED; if (cameraAccepted && storageAccepted){ pickFromCamera(); } else{ Toast.makeText(this, "Camera & Storage permissions are required...", Toast.LENGTH_SHORT).show(); } } break; // 添加break,避免执行后续case } case STORAGE_REQUEST_CODE:{ if (grantResults.length>0){ boolean storageAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED; if (storageAccepted){ pickFromGallery(); }else{ Toast.makeText(this, "Storage permission is required...", Toast.LENGTH_SHORT).show(); } } break; // 添加break } } super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
3. Android 13+权限适配
Android 13及以上版本,WRITE_EXTERNAL_STORAGE权限已被废弃,图库选择需使用READ_MEDIA_IMAGES权限,更新权限判断逻辑:
private boolean checkStoragePermission(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED; } else { return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } } private boolean checkCameraPermission(){ boolean cameraGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { return cameraGranted; // Android13+不需要存储权限 } else { boolean storageGranted = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; return cameraGranted && storageGranted; } }
同时更新权限数组定义(示例):
private String[] storagePermission; private String[] cameraPermissions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { storagePermission = new String[]{Manifest.permission.READ_MEDIA_IMAGES}; cameraPermissions = new String[]{Manifest.permission.CAMERA}; } else { storagePermission = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}; cameraPermissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}; } }
4. 补充缺失的常量定义
确保代码中定义了所需常量:
private static final int STORAGE_REQUEST_CODE = 100; private static final int CAMERA_REQUEST_CODE = 200; // 原代码中的IMAGE_PICK_*_CODE已不再需要,因为使用了独立的Launcher
内容的提问来源于stack exchange,提问作者Osborne
相关产品推荐
相关产品推荐

