Android Kotlin拍照后无法保存至相册问题求助
解决Android拍照后图片无法显示在系统相册的问题
你的代码里图片存在了应用私有外部存储目录(getExternalFilesDir),这个目录的文件不会被系统媒体扫描器自动索引,所以相册看不到。另外你也没有主动通知媒体库更新文件。下面是具体的修复方案:
核心问题分析
getExternalFilesDir(Environment.DIRECTORY_PICTURES)是应用私有目录,系统媒体库不会自动扫描这里的文件- Android 10及以上启用了Scoped Storage,直接操作公共目录的File会有兼容问题
修复步骤
- 适配存储目录:将图片存到公共图片目录,Android 10+推荐用MediaStore插入
- 通知媒体库扫描:Android 9及以下需要主动发送广播让相册识别新文件
- 权限适配:动态申请存储权限(仅Android 9及以下需要)
修改后的完整代码
class TomarFotos : AppCompatActivity() { val REQUEST_IMAGE_CAPTURE = 1 private var photoUri: Uri? = null // 替换原photoPath,适配Android 10+ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_tomar_fotos) val foto = findViewById<Button>(R.id.tomarfotos) foto.setOnClickListener { checkPermissionAndTakePhoto() } } private fun checkPermissionAndTakePhoto() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 100) return } } tomarFoto() } fun tomarFoto() { val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) if (intent.resolveActivity(packageManager) != null) { photoUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10+ 使用MediaStore创建公共目录Uri,自动加入媒体库 val contentValues = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "foto_${System.currentTimeMillis()}.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) } contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) } else { // Android 9及以下用FileProvider获取Uri val photoFile = createImageFile() photoFile?.let { FileProvider.getUriForFile(this, "com.example.android.fileprovider", it) } } photoUri?.let { intent.putExtra(MediaStore.EXTRA_OUTPUT, it) startActivityForResult(intent, REQUEST_IMAGE_CAPTURE) } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) val fotoTomada = findViewById<ImageView>(R.id.fotopreview) if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { fotoTomada.rotation = 90f fotoTomada.setImageURI(photoUri) // Android 9及以下需要通知媒体库扫描文件 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { photoUri?.let { uri -> val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) mediaScanIntent.data = uri sendBroadcast(mediaScanIntent) } } } } private fun createImageFile(): File? { val fileName = "foto_${System.currentTimeMillis()}" val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) if (!storageDir.exists()) storageDir.mkdirs() return File(storageDir, "$fileName.jpg") } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == 100 && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { tomarFoto() } } }
额外配置
在AndroidManifest.xml中添加权限和FileProvider配置:
<!-- 权限配置 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" /> <uses-feature android:name="android.hardware.camera" android:required="true" /> <!-- FileProvider配置(Android 9及以下需要) --> <application ...> <provider android:name="androidx.core.content.FileProvider" android:authorities="com.example.android.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-path name="my_images" path="Pictures" /> </paths>
这样修改后,拍照的图片会保存到系统公共图片目录,并且能直接在相册中看到。
内容的提问来源于stack exchange,提问作者leadapp
相关产品推荐
相关产品推荐

