【问题标题】:Save image from internal storage to gallery through ACTION_VIEW intent通过 ACTION_VIEW 意图将图像从内部存储保存到图库
【发布时间】:2020-05-30 08:04:21
【问题描述】:

我有一个聊天应用程序。如果用户发送图像,我会将该图像保存到应用程序的内部存储中

data/data/package_name/....

因此,如果用户单击该图像,我会向系统发送意图以打开它

val uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(it.localUri))
       val intent = Intent(Intent.ACTION_VIEW).apply {
       flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
       setDataAndType(uri, "image/*")
    }
    startActivity(intent)

问题在于,在图像查看器中,没有选择将文件保存在手机的公共存储中,在这种情况下保存在图库中。 有没有办法在不更改我的应用中图像的内部存储默认保存位置的情况下做到这一点?

【问题讨论】:

    标签: android kotlin android-fileprovider android-internal-storage


    【解决方案1】:

    如果您对此感兴趣,可以使用MediaStore 以编程方式将您内部存储中的图片保存到图库中。

    代码

    您可以使用以下代码,我在我的应用程序中成功使用了该代码。

    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "MyPicture.jpg");
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
       contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
    }
    
    ContentResolver resolver = myContext.getContentResolver();
    Bitmap bitmap;
    Uri uri;
    try {
       // Requires permission WRITE_EXTERNAL_STORAGE
       bitmap = BitmapFactory.decodeFile(currentPhotoPath);
       uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
    } catch (Exception e) {
       Log.e(LOG_TAG, "Error inserting picture in MediaStore: " + e.getMessage());
       return;
    }
    
    try (OutputStream stream = resolver.openOutputStream(uri)) {
       if (!bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream) {
          throw new IOException("Error compressing the picture.");
       }
    } catch (Exception e) {
       if (uri != null) {
          resolver.delete(uri, null, null);
       }
       Log.e(LOG_TAG, "Error adding picture to gallery: " + e.getMessage());       
    }
    
    

    感谢this answerFile 转换为Bitmapthis answer for 使用 MediaStore

    注意事项

    • BitmapFactory.decodeFile() 需要运行时权限 WRITE_EXTERNAL_STORAGE
    • 随着在 Android 10 中引入作用域内存(这将在 Android 11 中成为强制要求,请参阅 this articleMediaStore 可能是将图片保存到图库的唯一可靠方法
    • 范围存储的结果是,是的,您应该继续使用内部存储来存储图片的缓存副本。

    测试

    我已在以下设备/操作系统组合上使用 targetSdkVersion 29 测试了此代码

    • 三星 Galaxy S10 / API 29
    • 三星 Galaxy S9 / API 29
    • 华为 Nexus 6P / API 27

    【讨论】:

    • 嗯,这是一个很好的答案。但是我认为你没有理解我的问题。在我的情况下,当我单击照片时,我不使用 ImageViewer 的自定义活动。相反,我使用 Android 手机的默认图像查看器打开照片。那么我想在哪里写上面的代码..?
    • @james04 谢谢!我明白这一点,这就是为什么我说“如果这是你感兴趣的东西”。如果您可以在聊天like this 中的每张图片旁边放一个小按钮,那么我的回答可能会有用。不幸的是,如果您必须坚持使用默认图像查看器,我无法为您提供帮助。
    • @james04 AFAIK,因为系统决定了哪个应用程序将处理Intent.ACTION_VIEW(或者如果有更多,您可以选择一个),您不能期望在每个平台上都有相同的行为。你可以使用Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 如果你想将图片保存到画廊而不查看它(虽然在 Android Q 中已弃用)。但我认为没有Intent 可以保证启动一个在所有平台上始终执行这两种操作的应用程序。
    猜你喜欢
    • 2016-08-06
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多