Android相机拍照后无法在ImageView显示问题求助
问题根源与修复方案
你这代码里有几个关键问题导致拍的照片显示不出来:
- 直接用
ACTION_IMAGE_CAPTURE时,相机不会通过data?.data返回图片Uri,默认只给个小缩略图在data.getParcelableExtra("data")里,而且你没处理这种情况;要拿全尺寸照片,必须提前指定输出文件的Uri。 - 没申请相机权限——拍照必须要
CAMERA权限,你只加了存储权限,高版本Android(13+)还得适配新的权限规则。 onActivityResult里没判断请求码和结果码,比如没确认是不是相机的请求、拍照有没有成功(RESULT_OK)。- Android 7.0+不能直接用
file://Uri传文件给相机,得用FileProvider生成content://格式的Uri。
下面一步步改:
1. 先改Manifest配置
加相机权限,配好FileProvider:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!-- 拍照必须的相机权限 --> <uses-permission android:name="android.permission.CAMERA" /> <!-- Android 12及以下需要的存储权限,13+不用了 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- 声明依赖相机硬件 --> <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.LightningsDetection" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 配置FileProvider,用于Android 7.0+的文件共享 --> <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application> </manifest>
2. 建FileProvider的路径配置文件
在res目录下新建xml文件夹,再创建file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 把照片存在应用私有目录的Pictures文件夹,不用申请存储权限也能访问 --> <external-files-path name="my_images" path="Pictures" /> </paths>
3. 重写MainActivity代码
补全权限申请、相机调用、照片显示的逻辑:
package com.example.lightningsdetection import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.Manifest import android.content.Intent import android.content.pm.PackageManager import android.graphics.BitmapFactory import android.net.Uri import android.os.Environment import android.provider.MediaStore import android.widget.Button import android.widget.ImageView import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import java.io.File import java.text.SimpleDateFormat import java.util.Date import java.util.Locale class MainActivity : AppCompatActivity() { private lateinit var capturedImageView: ImageView private var photoUri: Uri? = null private val REQUEST_CAMERA_PERMISSION = 100 private val REQUEST_IMAGE_CAPTURE = 200 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) capturedImageView = findViewById(R.id.capturedImageView) val openCameraButton = findViewById<Button>(R.id.openCameraButton) openCameraButton.setOnClickListener { // 先检查权限再开相机 checkCameraPermission() } } // 检查相机权限,没有就申请 private fun checkCameraPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.CAMERA), REQUEST_CAMERA_PERMISSION ) } else { openCamera() } } // 处理权限申请结果 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_CAMERA_PERMISSION) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { openCamera() } } } // 打开相机,指定照片存储的Uri private fun openCamera() { val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) // 创建存储照片的文件 val photoFile = try { createImageFile() } catch (e: Exception) { null } photoFile?.also { // 用FileProvider生成合法的Uri photoUri = FileProvider.getUriForFile( this, "${packageName}.fileprovider", it ) // 告诉相机把照片存在这个Uri里 intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri) if (intent.resolveActivity(packageManager) != null) { startActivityForResult(intent, REQUEST_IMAGE_CAPTURE) } } } // 创建唯一命名的图片文件,存在应用私有目录 private fun createImageFile(): File { val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES) return File.createTempFile( "JPEG_${timeStamp}_", ".jpg", storageDir ) } // 处理相机返回的结果 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // 只处理相机请求且拍照成功的情况 if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { photoUri?.let { uri -> // 加载图片时缩小尺寸,避免内存溢出 val options = BitmapFactory.Options() options.inSampleSize = 4 // 缩小4倍,可根据需求调整 val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(uri), null, options) capturedImageView.setImageBitmap(bitmap) } } } }
关于Logcat日志的说明
你看到的那个日志不是错误,只是系统记录的Activity窗口销毁信息,和照片不显示没关系,修复上面的代码后就能正常显示照片了。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

