假如没有存储权限,如何实现相机拍照并存储图片呢?
1. 去除读、写存储权限,保留相机权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
2. AndroidManifest.xml 定义provider
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.oo">
<application
android:requestLegacyExternalStorage="true">
<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>
<!-- Android 11 -->
<meta-data
android:name="ScopedStorage"
android:value="true" />
</application>
</manifest>
3. 定义file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path
name="root_path"
path="." />
<!--Environment.getExternalStorageDirectory()-->
<external-path
name="external_path"
path="/" />
<!--context.getExternalCacheDir()-->
<external-cache-path
name="external_cache_path"
path="/" />
<!--context.getCacheDir()-->
<cache-path
name="cache_path"
path="cache_path"/>
<!--context.getFilesDir()-->
<files-path
name="root"
path="." />
<!--context.getExternalFilesDir()-->
<external-files-path
name="external_files"
path="." />
</paths>
4. 具体代码逻辑
4.1 检查相机权限 省略 ...
这个代码没啥特别的,请自己实现。
4.2 定义ActivityResultContract接收对象
open class TakeCameraBackPhoto : ActivityResultContract<Uri, Boolean>() {
@CallSuper
override fun createIntent(context: Context, input: Uri): Intent {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT, input)
intent.putExtra("android.intent.extras.LENS_FACING_BACK", 1)
intent.putExtra("android.intent.extras.CAMERA_FACING", 0)
intent.putExtra("android.intent.extra.USE_FRONT_CAMERA", false)
return intent
}
final override fun getSynchronousResult(
context: Context,
input: Uri
): SynchronousResult<Boolean>? = null
@Suppress("AutoBoxing")
final override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
return resultCode == Activity.RESULT_OK
}
}
4.3 具体实现
class MainActivity : AppCompatActivity() {
var file: File? = null
private val takeCameraPhoto = registerForActivityResult(TakeCameraBackPhoto()) {
if (it) {
file?.let { file ->
// file.absolutePath 即文件的完整路径
}
return@registerForActivityResult
}
}
// 调用此方法即可
private fun openCamera(context:Context) {
file = File(
context.externalCacheDir, "${System.currentTimeMillis()}.jpg"
)
val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file.apply {
parentFile?.mkdirs()
createNewFile()
})
takeCameraPhoto.launch(uri)
}
}