Android跨Activity调用相机方法并展示到ImageView空指针问题求助
问题根因
你直接通过new MainActivity()实例化Activity的写法完全不符合Android组件规范:
- Android的Activity生命周期、上下文绑定均由系统负责,手动new出来的实例没有经过系统初始化,
getContentResolver()、BaseContext等核心成员都是空值,所以调用pickCamera()必然触发空指针。 - 跨Activity直接调用方法本身就是错误设计,Android的不同Activity之间是独立组件,不允许直接持有对方实例调用方法。
解决方案
方案1:抽离相机逻辑为公共工具类(最优,彻底消除重复代码)
把拍图、回传的通用逻辑封装成独立的工具类,两个Activity都直接调用工具类的方法即可,不需要互相调用。
步骤:
- 新建
CameraUtils工具类,封装拍图Intent创建、Uri生成逻辑:
public class CameraUtils { public static final int IMAGE_PICK_CAMERA_CODE = 1001; // 生成拍照所需的Uri,返回给调用方保存 public static Uri createImageUri(Context context) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, "NewPic"); values.put(MediaStore.Images.Media.DESCRIPTION, "Image to Text"); return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values); } // 获取拍照Intent public static Intent getCameraIntent(Uri imageUri) { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); return cameraIntent; } // 统一处理拍图完成后跳转SecondActivity的逻辑 public static void handleImageResult(Context context, Uri imageUri) { Intent i = new Intent(context, MainActivity2.class); i.putExtra("CashCardImage", imageUri.toString()); context.startActivity(i); } }
- FirstActivity修改调用逻辑:
// 成员变量保存拍照uri private Uri image_uri; btnrescanBeneId.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { image_uri = CameraUtils.createImageUri(FirstActivity.this); startActivityForResult(CameraUtils.getCameraIntent(image_uri), CameraUtils.IMAGE_PICK_CAMERA_CODE); } }); @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK && requestCode == CameraUtils.IMAGE_PICK_CAMERA_CODE){ CameraUtils.handleImageResult(FirstActivity.this, image_uri); } }
- SecondActivity直接调用工具类,不需要再调FirstActivity的方法:
// 成员变量保存拍照uri private Uri image_uri; btnrescanBeneId.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { image_uri = CameraUtils.createImageUri(SecondActivity.this); startActivityForResult(CameraUtils.getCameraIntent(image_uri), CameraUtils.IMAGE_PICK_CAMERA_CODE); } }); @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK && requestCode == CameraUtils.IMAGE_PICK_CAMERA_CODE){ // 拍图完成直接在当前页面展示,不需要跳转 try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),image_uri); mPreviewCashCard.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } }
方案2:通过Intent跳转复用FirstActivity逻辑(仅做参考)
如果不想改动FirstActivity原有逻辑,可以给FirstActivity加一个跳转参数,标记是从SecondActivity跳转过来请求拍照的,拍完成后直接返回结果给SecondActivity:
- SecondActivity点击按钮时跳转到FirstActivity,携带请求拍照的标记:
btnrescanBeneId.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(SecondActivity.this, FirstActivity.class); intent.putExtra("trigger_camera_directly", true); startActivityForResult(intent, 1002); } }); // 接收FirstActivity返回的拍照结果 @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK && requestCode == 1002 && data != null){ String resultUri = data.getStringExtra("CashCardImage"); Uri myUri = Uri.parse(resultUri); try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),myUri); mPreviewCashCard.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } }
- FirstActivity的onCreate里判断参数,自动触发拍照:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ...原有逻辑不变 if(getIntent().getBooleanExtra("trigger_camera_directly", false)){ pickCamera(); } }
- FirstActivity的onActivityResult里判断来源,是SecondActivity请求的就直接返回结果,否则跳转SecondActivity:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode ==RESULT_OK && requestCode == IMAGE_PICK_CAMERA_CODE){ if(getIntent().getBooleanExtra("trigger_camera_directly", false)){ // 是SecondActivity请求拍照,直接返回结果 Intent resultIntent = new Intent(); resultIntent.putExtra("CashCardImage", image_uri.toString()); setResult(RESULT_OK, resultIntent); finish(); } else { // 原有逻辑,跳转SecondActivity Intent i = new Intent(MainActivity.this, MainActivity2.class); i.putExtra("CashCardImage",image_uri.toString()); startActivity(i); } } }
内容的提问来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

