Android应用点击拍照按钮崩溃,相机权限相关问题求助
问题解决方案
1. 修正Manifest权限拼写错误
你的Manifest中READ_EXTERNAL_STORAGE权限的包名是大写的,Android权限名区分大小写,必须改为小写,否则权限声明无效:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
2. 添加动态权限申请(Android 6.0+ 强制要求)
仅在Manifest中声明危险权限(如相机、存储)不够,Android 6.0及以上系统需要在运行时向用户主动申请。在TrackFragment中添加权限检查与申请逻辑:
private final int CAMERA_REQ_CODE = 100; private ImageView imgCamera; // 定义需要申请的权限列表 private final String[] REQUIRED_PERMISSIONS = { Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); imgCamera = view.findViewById(R.id.imgCamera); Button btnCamera = view.findViewById(R.id.btnCamera); btnCamera.setOnClickListener(v -> { // 先检查权限是否已授予 if (hasAllPermissions()) { startCamera(); } else { // 请求权限 requestPermissions(REQUIRED_PERMISSIONS, CAMERA_REQ_CODE); } }); } // 检查所有必需权限是否已授予 private boolean hasAllPermissions() { for (String permission : REQUIRED_PERMISSIONS) { if (ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } // 处理权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == CAMERA_REQ_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { startCamera(); } else { Toast.makeText(requireContext(), "需要相机和存储权限才能使用此功能", Toast.LENGTH_SHORT).show(); } } } // 启动相机Intent,增加相机应用可用性检查 private void startCamera() { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 确保有应用能处理这个Intent,避免崩溃 if (cameraIntent.resolveActivity(requireContext().getPackageManager()) != null) { startActivityForResult(cameraIntent, CAMERA_REQ_CODE); } else { Toast.makeText(requireContext(), "未找到可用的相机应用", Toast.LENGTH_SHORT).show(); } }
3. 替换过时的startActivityForResult(推荐)
如果希望使用最新API替代已过时的方法,用registerForActivityResult重构相机结果回调:
private ActivityResultLauncher<Intent> cameraLauncher; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注册相机结果回调 cameraLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { Intent data = result.getData(); if (data != null && data.getExtras() != null) { Bitmap img = (Bitmap) data.getExtras().get("data"); imgCamera.setImageBitmap(img); } } } ); } // 修改startCamera方法 private void startCamera() { Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (cameraIntent.resolveActivity(requireContext().getPackageManager()) != null) { cameraLauncher.launch(cameraIntent); } else { Toast.makeText(requireContext(), "未找到可用的相机应用", Toast.LENGTH_SHORT).show(); } }
同时删除原有的onActivityResult方法。
4. 修复潜在空指针问题
你代码中private final Context trackFragmentContext = this.getContext();存在初始化时机问题:Fragment创建阶段getContext()尚未赋值,会导致空指针异常。直接删除该变量,在需要Context的地方使用requireContext()(确保Fragment已关联Activity)或getContext()(需判空)。
额外注意事项
- 若App目标SDK为33+,
WRITE_EXTERNAL_STORAGE权限已被废弃,无需申请,改用MediaStore API存储图片。 - 测试时确保设备安装了可用的相机应用,避免因无相机应用导致崩溃。
内容的提问来源于stack exchange,提问作者J_R
相关产品推荐
相关产品推荐

