Android 如何从第二Activity调用首个Activity的Camera扫描功能
核心问题说明
你之前尝试直接new MainActivity()实例调用方法的方式不可行,Android Activity由系统统一管理生命周期,手动创建的实例不具备正常运行所需的上下文环境,无法调用相机等系统能力。
可行实现方案
通过startActivityForResult(或更高版本的Activity Result API)启动第一个Activity,携带扫描类型标记,第一个Activity完成扫描后根据标记将结果返回给第二个Activity,第二个Activity根据返回的扫描类型更新对应ImageView即可。
修改后第一个Activity(MainActivity)代码
public class MainActivity extends HasCameraOpenerActivity { // 全局参数键定义 public static final String EXTRA_SCAN_TYPE = "scan_type"; public static final int SCAN_TYPE_FIRST_LAUNCH = 0; // 首次启动扫描 public static final int SCAN_TYPE_CASH_CARD = 1; // 扫描现金卡 public static final int SCAN_TYPE_OTHER_CARD = 2; // 扫描另一张卡片 public static final String EXTRA_SCANNED_URI = "scanned_uri"; private Button button; private int currentScanType; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = findViewById(R.id.scan_btn); // 接收启动参数判断扫描类型 currentScanType = getIntent().getIntExtra(EXTRA_SCAN_TYPE, SCAN_TYPE_FIRST_LAUNCH); // 如果是从第二个Activity来的重扫请求,直接调起相机 if (currentScanType != SCAN_TYPE_FIRST_LAUNCH) { pickCamera(); } button.setOnClickListener(v -> pickCamera()); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode == RESULT_OK && requestCode == 1){ if (currentScanType == SCAN_TYPE_FIRST_LAUNCH) { // 首次启动扫描,跳转第二个Activity Intent intent = new Intent(MainActivity.this, MainActivity2.class); intent.putExtra(EXTRA_SCANNED_URI, image_uri.toString()); startActivity(intent); finish(); } else { // 重扫请求,把结果返回给第二个Activity Intent resultIntent = new Intent(); resultIntent.putExtra(EXTRA_SCAN_TYPE, currentScanType); resultIntent.putExtra(EXTRA_SCANNED_URI, image_uri.toString()); setResult(RESULT_OK, resultIntent); finish(); } } } } // 相机基类无需修改 public abstract class HasCameraOpenerActivity extends Activity { protected Uri image_uri; public void pickCamera() { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, "NewPic"); values.put(MediaStore.Images.Media.DESCRIPTION, "Image to Text"); image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); Intent cameraIntent = new Intent (MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri); startActivityForResult(cameraIntent, 1); } }
修改后第二个Activity(MainActivity2)代码
public class MainActivity2 extends AppCompatActivity { // 请求码区分两个ImageView的重扫请求 private static final int REQUEST_RESCAN_CASH_CARD = 1001; private static final int REQUEST_RESCAN_OTHER_CARD = 1002; private ImageView mPreviewCashCard; private ImageView mPreviewOtherCard; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Button btnrescanCashCard = findViewById(R.id.rescanCashcard); Button btnrescanOtherCard = findViewById(R.id.rescanOtherCard); mPreviewCashCard = findViewById(R.id.imageView); mPreviewOtherCard = findViewById(R.id.imageView2); // 加载首次扫描的现金卡图片 Bundle extras = getIntent().getExtras(); if (extras != null) { String resultUri = extras.getString(MainActivity.EXTRA_SCANNED_URI); loadImageToView(resultUri, mPreviewCashCard); } // 现金卡重扫点击事件 btnrescanCashCard.setOnClickListener(v -> { Intent rescanIntent = new Intent(MainActivity2.this, MainActivity.class); rescanIntent.putExtra(MainActivity.EXTRA_SCAN_TYPE, MainActivity.SCAN_TYPE_CASH_CARD); startActivityForResult(rescanIntent, REQUEST_RESCAN_CASH_CARD); }); // 另一张卡片重扫点击事件 btnrescanOtherCard.setOnClickListener(v -> { Intent rescanIntent = new Intent(MainActivity2.this, MainActivity.class); rescanIntent.putExtra(MainActivity.EXTRA_SCAN_TYPE, MainActivity.SCAN_TYPE_OTHER_CARD); startActivityForResult(rescanIntent, REQUEST_RESCAN_OTHER_CARD); }); } // 接收重扫结果更新对应ImageView @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && data != null) { String scannedUri = data.getStringExtra(MainActivity.EXTRA_SCANNED_URI); int scanType = data.getIntExtra(MainActivity.EXTRA_SCAN_TYPE, -1); if (scanType == MainActivity.SCAN_TYPE_CASH_CARD) { loadImageToView(scannedUri, mPreviewCashCard); } else if (scanType == MainActivity.SCAN_TYPE_OTHER_CARD) { loadImageToView(scannedUri, mPreviewOtherCard); } } } // 公共图片加载方法 private void loadImageToView(String uriStr, ImageView imageView) { if (uriStr == null || imageView == null) return; Uri myUri = Uri.parse(uriStr); try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),myUri); imageView.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } }
注意事项
- Android 6.0及以上版本需要提前动态申请相机、存储读写权限
- Android 7.0及以上版本传递文件Uri需要配置FileProvider,否则会触发Uri暴露异常
- 如果项目适配了AndroidX,建议使用Activity Result API替代已废弃的
startActivityForResult方法,逻辑会更简洁
内容的提问来源于stack exchange,提问作者BootCamp
相关产品推荐
相关产品推荐

