如何使用 MediaStore 在 Android Q 中保存图像?

这是新的 Android Q Scoped Storage的链接。


根据这个 Android Developers Best Practices Blog,storing shared media files(我的情况)应该使用MediaStore API 来完成。


深入研究文档,我找不到相关的功能。


这是我在 Kotlin 中的试用:


val bitmap = getImageBitmap() // I have a bitmap from a function or callback or whatever

val name = "example.png" // I have a name


val picturesDirectory = getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!


// Make sure the directory "Android/data/com.mypackage.etc/files/Pictures" exists

if (!picturesDirectory.exists()) {

    picturesDirectory.mkdirs()

}


try {

    val out = FileOutputStream(File(picturesDirectory, name))

    bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)


    out.flush()

    out.close()


} catch(e: Exception) {

    // handle the error

}

结果是我的图像Android/data/com.mypackage.etc/files/Pictures/example.png按照最佳实践博客中的描述保存在这里Storing app-internal files


我的问题是:


如何使用 MediaStore API 保存图像?Java 中的答案同样可以接受。


烙印99
浏览 182回答 5
5回答

Cats萌萌

尝试下一个方法。如果文件夹不存在,Android Q(及更高版本)已经负责创建文件夹。该示例被硬编码为输出到DCIM文件夹中。如果您需要一个子文件夹,则将子文件夹名称附加为下一个:final String relativeLocation = Environment.DIRECTORY_DCIM + File.separator + “YourSubforderName”;考虑压缩格式应该与mime-type参数有关。例如,对于 JPEG 压缩格式,mime 类型将是“image/jpeg”,等等。可能您还想将压缩质量作为参数传递,在此示例中硬编码为 95。爪哇:@NonNullpublic Uri saveBitmap(@NonNull final Context context, @NonNull final Bitmap bitmap,                      @NonNull final Bitmap.CompressFormat format,                      @NonNull final String mimeType,                      @NonNull final String displayName) throws IOException {    final ContentValues values = new ContentValues();    values.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName);    values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);    values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);    final ContentResolver resolver = context.getContentResolver();    Uri uri = null;    try {        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;        uri = resolver.insert(contentUri, values);        if (uri == null)            throw new IOException("Failed to create new MediaStore record.");        try (final OutputStream stream = resolver.openOutputStream(uri)) {            if (stream == null)                throw new IOException("Failed to open output stream.");                     if (!bitmap.compress(format, 95, stream))                throw new IOException("Failed to save bitmap.");        }        return uri;    }    catch (IOException e) {        if (uri != null) {            // Don't leave an orphan entry in the MediaStore            resolver.delete(uri, null, null);        }        throw e;    }}科特林:@Throws(IOException::class)fun saveBitmap(    context: Context, bitmap: Bitmap, format: Bitmap.CompressFormat,    mimeType: String, displayName: String): Uri {    val values = ContentValues().apply {        put(MediaStore.MediaColumns.DISPLAY_NAME, displayName)        put(MediaStore.MediaColumns.MIME_TYPE, mimeType)        put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM)    }    val resolver = context.contentResolver    var uri: Uri? = null    try {        uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)            ?: throw IOException("Failed to create new MediaStore record.")        resolver.openOutputStream(uri)?.use {            if (!bitmap.compress(format, 95, it))                throw IOException("Failed to save bitmap.")        } ?: throw IOException("Failed to open output stream.")        return uri    } catch (e: IOException) {        uri?.let { orphanUri ->            // Don't leave an orphan entry in the MediaStore            resolver.delete(orphanUri, null, null)        }        throw e    }}Kotlin 变体,具有更实用的风格:@Throws(IOException::class)fun saveBitmap(    context: Context, bitmap: Bitmap, format: Bitmap.CompressFormat,    mimeType: String, displayName: String): Uri {    val values = ContentValues().apply {        put(MediaStore.MediaColumns.DISPLAY_NAME, displayName)        put(MediaStore.MediaColumns.MIME_TYPE, mimeType)        put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM)    }    var uri: Uri? = null    return runCatching {        with(context.contentResolver) {            insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)?.also {                uri = it // Keep uri reference so it can be removed on failure                openOutputStream(it)?.use { stream ->                    if (!bitmap.compress(format, 95, stream))                        throw IOException("Failed to save bitmap.")                } ?: throw IOException("Failed to open output stream.")            } ?: throw IOException("Failed to create new MediaStore record.")        }    }.getOrElse {        uri?.let { orphanUri ->            // Don't leave an orphan entry in the MediaStore            context.contentResolver.delete(orphanUri, null, null)        }        throw it    }}

慕虎7371278

private void saveImage(Bitmap bitmap, @NonNull String name) throws IOException {    OutputStream fos;    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {        ContentResolver resolver = getContentResolver();        ContentValues contentValues = new ContentValues();        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name + ".jpg");        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);        Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);        fos = resolver.openOutputStream(Objects.requireNonNull(imageUri));    } else {        String imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();        File image = new File(imagesDir, name + ".jpg");        fos = new FileOutputStream(image);    }    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);    Objects.requireNonNull(fos).close();}图像将存储在图片文件夹@根级别在直播中查看https://youtu.be/695HqaiwzQ0我创建了教程

浮云间

这是我经常使用的。你可以尝试一下。 private void saveImageToStorage() throws IOException {    OutputStream imageOutStream;    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {        ContentValues values = new ContentValues();        values.put(MediaStore.Images.Media.DISPLAY_NAME, "image_screenshot.jpg");        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");        values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);        Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);        imageOutStream = getContentResolver().openOutputStream(uri);    } else {        String imagePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();        File image = new File(imagePath, "image_screenshotjpg");        imageOutStream = new FileOutputStream(image);    }    try {        bitmapObject.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream);    } finally {        imageOutStream.close();    }}

守候你守候我

如果有人正在寻找如何将照片保存到 DCIM 文件夹中,以一种稍后将出现在 Google Photos 中的方式:(基于:https: //github.com/yasirkula/UnityNativeGallery/blob/670d9e2b8328f7796dd95d29dd80fadd8935b804/JAR%20Source/NativeGallery .java#L73-L96 )ContentValue values = new ContentValues();values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);values.put(MediaStore.MediaColumns.DATE_TAKEN, System.currentTimeMillis());values.put(MediaStore.MediaColumns.IS_PENDING, true);Uri uri = context.getContentResolver().insert(externalContentUri, values);if (uri != null) {    try {        if (WriteFileToStream(originalFile, context.getContentResolver().openOutputStream(uri))) {            values.put(MediaStore.MediaColumns.IS_PENDING, false);            context.getContentResolver().update(uri, values, null, null);        }    } catch (Exception e) {        context.getContentResolver().delete( uri, null, null );    }}WriteFileToStream从文件复制到流的标准方法在哪里。

慕森王

这是我的 2022 版本,此版本也在 Samsung S22 Phone 上的 Emulator SDK 27 和 30 中进行了测试。长:博士对于 SDK < 29 你需要按照这里的代码,并且在成功拍照后几乎不需要添加代码。您可以在savePictureQ(...)下面的我的功能中看到否则,如果您是 SDK >= 29,只需从函数的MediaStore.EXTRA_OUTPUTextras处传递 URIcontentResolver.insert(...)因为startActivityForResult(Intent)已经弃用了我的版本registerForActivityResult(...)private val cameraLauncher =&nbsp; &nbsp; registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {&nbsp; &nbsp; &nbsp; &nbsp; if (it.resultCode == Activity.RESULT_OK) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val name: String = viewModel.savePictureQ()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (name != "") requireActivity().applicationContext.deleteFile(name)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val cr = requireContext().contentResolver&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val uri = viewModel.getTargetUri()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (uri != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val source = ImageDecoder.createSource(cr, uri)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ImageDecoder.decodeBitmap(source)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else MediaStore.Images.Media.getBitmap(cr, uri)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val resized = Bitmap.createScaledBitmap(bitmap, 512, 512, true)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }我在另一个名为 Repository.kt 的文件中调用 Intent,我还使用假 viewModel 来调用 Repository 代码。这是我调用 viewModel 代码的方式private lateinit var viewModel: MenuViewModeloverride fun onCreateView(&nbsp; &nbsp; inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {&nbsp; &nbsp; viewModel = MenuViewModel(Injection.provideRepository(requireContext()))&nbsp; &nbsp; ...}private fun permissionCheck() {&nbsp; &nbsp; val granted = PackageManager.PERMISSION_GRANTED&nbsp; &nbsp; val permissions = arrayOf(&nbsp; &nbsp; &nbsp; &nbsp; Manifest.permission.WRITE_EXTERNAL_STORAGE,&nbsp; &nbsp; &nbsp; &nbsp; Manifest.permission.READ_EXTERNAL_STORAGE,&nbsp; &nbsp; &nbsp; &nbsp; Manifest.permission.CAMERA&nbsp; &nbsp; )&nbsp; &nbsp; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; if (ActivityCompat.checkSelfPermission(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireContext(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; permissions[0]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) != granted && ActivityCompat.checkSelfPermission(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireContext(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; permissions[1]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) != granted && ActivityCompat.checkSelfPermission(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireContext(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; permissions[2]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) != granted&nbsp; &nbsp; &nbsp; &nbsp; ) ActivityCompat.requestPermissions(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireActivity(), permissions, MainActivity.REQUEST_CODE_PERMISSION&nbsp; &nbsp; &nbsp; &nbsp; ) else MainActivity.accepted = true&nbsp; &nbsp; } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; if (ActivityCompat.checkSelfPermission(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireContext(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; permissions[2]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) != granted && ActivityCompat.checkSelfPermission(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireContext(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Manifest.permission.ACCESS_MEDIA_LOCATION&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) != granted&nbsp; &nbsp; &nbsp; &nbsp; ) ActivityCompat.requestPermissions(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requireActivity(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; arrayOf(permissions[2], Manifest.permission.ACCESS_MEDIA_LOCATION),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MainActivity.REQUEST_CODE_PERMISSION&nbsp; &nbsp; &nbsp; &nbsp; ) else MainActivity.accepted = true&nbsp; &nbsp; }}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {&nbsp; &nbsp; ...&nbsp; &nbsp; bind.fromCamera.setOnClickListener {&nbsp; &nbsp; &nbsp; &nbsp; permissionCheck()&nbsp; &nbsp; &nbsp; &nbsp; if (`permission granted check`) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; viewModel.getCameraIntent(cameraLauncher)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; ...}在我的假 viewModel 中:class MenuViewModel(private val repository: IRepository) {&nbsp; &nbsp; fun getTargetUri() = repository.getTargetUri()&nbsp; &nbsp; fun getCameraIntent(launcher: ActivityResultLauncher<Intent>) =&nbsp; &nbsp; &nbsp; &nbsp; repository.createTakePictureIntent(launcher)&nbsp; &nbsp; fun savePictureQ(): String = repository.savePictureQ()}在我的存储库代码中:class Repository private constructor(private val context: Context) : IRepository {&nbsp; &nbsp; companion object {&nbsp; &nbsp; &nbsp; &nbsp; @Volatile&nbsp; &nbsp; &nbsp; &nbsp; private var INSTANCE: IRepository? = null&nbsp; &nbsp; &nbsp; &nbsp; fun getInstance(context: Context) = INSTANCE ?: synchronized(this) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; INSTANCE ?: Repository(context).apply { INSTANCE = this }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; private var currentPath = ""&nbsp; &nbsp; private var targetUri: Uri? = null&nbsp; &nbsp; private fun createImageFile(): File {&nbsp; // create temporary file for SDK < 29&nbsp; &nbsp; &nbsp; &nbsp; val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())&nbsp; &nbsp; &nbsp; &nbsp; val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)&nbsp; &nbsp; &nbsp; &nbsp; return File.createTempFile(timestamp, ".jpg", storageDir)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .apply { currentPath = absolutePath }&nbsp; &nbsp; }&nbsp; &nbsp; override fun savePictureQ() : String {&nbsp; // Saving picture and added to Gallery for SDK < 29&nbsp; &nbsp; &nbsp; &nbsp; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val f = File(currentPath)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val cr = context.contentResolver&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val bitmap = BitmapFactory.decodeFile(currentPath)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val path = "${Environment.DIRECTORY_PICTURES}${File.separator}PoCkDetection"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val values = createContentValues(f.name, path)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var uri: Uri? = null&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)!!&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val os = cr.openOutputStream(uri)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val result = bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!result) throw Exception()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (e: Exception) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw e&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; os?.close()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; targetUri = uri&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.delete()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (f.exists()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.canonicalFile.delete()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (f.exists()) return f.name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (e: Exception) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uri?.let {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cr.delete(it, null, null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return ""&nbsp; &nbsp; }&nbsp; &nbsp; override fun getTargetUri(): Uri? = targetUri&nbsp; &nbsp; private fun createContentValues(title: String, path: String): ContentValues =&nbsp; &nbsp; &nbsp; &nbsp; ContentValues().apply {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.MediaColumns.TITLE, "$title.jpg")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.MediaColumns.DISPLAY_NAME, "$title.jpg")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.MediaColumns.DATE_TAKEN, System.currentTimeMillis())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.MediaColumns.RELATIVE_PATH, path)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.Images.Media.TITLE, "$title.jpg")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.Images.Media.DISPLAY_NAME, "$title.jpg")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.Images.Media.MIME_TYPE, "image/jpg")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; override fun createTakePictureIntent(launcher: ActivityResultLauncher<Intent>) {&nbsp; &nbsp; &nbsp; &nbsp; Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; takePictureIntent.resolveActivity(context.packageManager).also {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val photoFile: File? = try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; createImageFile()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (e: IOException) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; null&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; photoFile?.also {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val photoURI =&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FileProvider.getUriForFile(context, "com.your.package.name", it)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; launcher.launch(takePictureIntent)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val timestamp =&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val path = "${Environment.DIRECTORY_PICTURES}${File.separator}PoCkDetection"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val values = createContentValues(timestamp, path)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val photoURI = context.contentResolver.insert(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; targetUri = photoURI&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; launcher.launch(takePictureIntent)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}对于 SDK < 29,我遵循Google Developer的这段代码这是我的清单在遵循代码后的样子:<application ...>&nbsp; &nbsp; <provider&nbsp; &nbsp; &nbsp; &nbsp; android:name="androidx.core.content.FileProvider"&nbsp; &nbsp; &nbsp; &nbsp; android:authorities="com.your.package.name"&nbsp; &nbsp; &nbsp; &nbsp; android:exported="false"&nbsp; &nbsp; &nbsp; &nbsp; android:grantUriPermissions="true">&nbsp; &nbsp; &nbsp; &nbsp; <meta-data&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android:name="android.support.FILE_PROVIDER_PATHS"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; android:resource="@xml/camera_paths" />&nbsp; &nbsp; </provider></application>创建名为 xml 的新 res 文件夹,然后创建新的 xml 文件,确保名称与您放置在该文件<meta-data>中<provider>和内部的名称相同:<?xml version="1.0" encoding="utf-8"?><paths>&nbsp; &nbsp; <external-files-path&nbsp; &nbsp; &nbsp; &nbsp; name="camera_take"&nbsp; &nbsp; &nbsp; &nbsp; path="Pictures" /></paths>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java