You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Studio无代码报错但应用强制关闭问题求助

解决Android拍照显示到ImageView的RuntimeException问题

嘿,我来帮你排查这个问题!既然代码语法没问题、Activity也注册了,那大概率是权限、拍照Intent处理、文件路径或者ImageView加载环节出了问题,咱们一步步拆解:

1. 先检查权限配置(最常见的坑)

Android 6.0(API 23)及以上,只在AndroidManifest.xml加静态权限是不够的,必须动态申请相机权限

  • 先补全Manifest里的静态权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<!-- 如果要把照片存到外部存储,还要加这个权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • 然后在Activity里添加权限判断逻辑,点击拍照按钮前先确认权限:
private static final int REQUEST_CAMERA_PERMISSION = 100;

// 拍照按钮的点击事件
public void takePhoto(View view) {
    // 检查相机权限是否已授予
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
        // 未授权,发起权限申请
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.CAMERA},
                REQUEST_CAMERA_PERMISSION);
        return;
    }
    // 权限通过,启动相机
    launchCamera();
}

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CAMERA_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            launchCamera();
        } else {
            Toast.makeText(this, "需要相机权限才能拍照哦", Toast.LENGTH_SHORT).show();
        }
    }
}

2. 检查相机Intent的正确写法(避免FileUriExposedException)

Android 7.0及以上不能直接用Uri.fromFile()传递文件路径,必须用FileProvider,否则会抛出RuntimeException:

  • 先在Manifest里注册FileProvider:
<application>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.your.package.name.fileprovider" <!-- 替换成你的应用包名+fileprovider -->
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>
  • res/xml目录下创建file_paths.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_images" path="Pictures" />
</paths>
  • 然后编写启动相机的逻辑:
private static final int REQUEST_IMAGE_CAPTURE = 200;
private Uri photoUri;

private void launchCamera() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // 先确认有相机应用能处理这个Intent
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        File photoFile = null;
        try {
            photoFile = createImageFile(); // 创建保存照片的临时文件
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        if (photoFile != null) {
            // 通过FileProvider获取文件Uri
            photoUri = FileProvider.getUriForFile(this,
                    "com.your.package.name.fileprovider",
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    } else {
        Toast.makeText(this, "没找到可用的相机应用", Toast.LENGTH_SHORT).show();
    }
}

// 创建临时照片文件
private File createImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(imageFileName, ".jpg", storageDir);
}

3. 检查拍照结果的处理(避免OOM或Uri错误)

拍完照后要正确加载照片到ImageView,注意压缩Bitmap防止内存溢出:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        try {
            // 从photoUri加载Bitmap
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), photoUri);
            // 压缩Bitmap,避免OOM
            bitmap = Bitmap.createScaledBitmap(bitmap, 800, 600, true);
            ImageView imageView = findViewById(R.id.photo_preview); // 替换成你的ImageView ID
            imageView.setImageBitmap(bitmap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 最后检查XML布局的ImageView

确保你的ImageView ID和代码里的对应,没有设置错误属性:
比如你的LinearLayout布局示例:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/take_photo_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="拍照"
        android:onClick="takePhoto"/>

    <ImageView
        android:id="@+id/photo_preview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"/>

</LinearLayout>

你可以先从权限和FileProvider这两个点入手排查,这是触发RuntimeException的高频原因!如果还是有问题,把LogCat里的具体异常信息贴出来,能更精准定位~

内容的提问来源于stack exchange,提问作者Shiv Mistry

火山引擎 最新活动