【问题标题】:Make image File visible in Android Gallery on Lollipop使图像文件在 Lollipop 上的 Android 图库中可见
【发布时间】:2015-07-01 15:44:42
【问题描述】:

我正在尝试使应用程序中拍摄的一些图片在图库中可见(以便可以在应用程序外部共享和查看),但我想将图像本身保存在应用程序的数据目录中因此,当应用被删除时,它们会被删除(因此它们存储在 "{sdcard}/Android/data/{appID}/Pictures/{subfolder}/" 中)。

我查看了很多答案,对于旧版本的 Android,以下两种解决方案都可以工作,但它们似乎不适用于 Lollipop:

MediaScannerConnection.scanFile(this,
    new String[]{file.toString()}, new String[] { "image/jpeg" },
    new MediaScannerConnection.OnScanCompletedListener() {
        public void onScanCompleted(String path, Uri uri) {
            Log.i("ExternalStorage", "Scanned " + path + ":");
            Log.i("ExternalStorage", "-> uri=" + uri);
        }
    });

Uri contentUri = Uri.fromFile(file);
Intent mediaScanIntent = new 
    Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,contentUri);
sendBroadcast(mediaScanIntent);

我已经在 Nexus 4 (Android 5.0.1) 和 Nexus 6 (Android 5.1) 上对此进行了测试,但它不起作用。在 Nexus 7 (Android 4.2.2) 中它确实有效。所有 3 台设备在 {sdcard}/Android/data/ 文件夹中都有一个“.onmedia”文件,因此没有正常的媒体扫描应该拾取它们...

有没有人知道如何解决这个问题以使其适用于所有设备/Android 版本?这是否应该因为 noMedia 文件首先无法正常工作,而 Lollipop 是唯一可以正确执行此操作的版本吗?

编辑:请注意,即使重新启动手机(这也应该触发重新扫描文件)也不起作用。并且有充分的理由,因为文件位于“.nomedia”目录的子文件夹中......所以我认为任何包含 MEDIA_MOUNTED 广播的解决方案都是无用的。

【问题讨论】:

  • 请看我的回答,我认为它对你有用。

标签: android android-5.0-lollipop android-gallery android-file android-mediascanner


【解决方案1】:

我建议你看看my answer here。它总结了我围绕MediaScanner 所做的所有发现。

旁注:所有KitKat 问题似乎也都在Lollipop 上。

【讨论】:

  • 谢谢。但它们似乎都不是解决方案。即使是通过 shell 发送“挂载”广播的 hack 也行不通……
  • 正确。正如我所说,KitKat 没有有效的解决方案,Lollipop 也没有。
【解决方案2】:

我不确定媒体内容提供商是否会获得对包含图像的本地数据目录的读取权限。如果没有权限,您的画廊方法将无法运行。

要了解是否有可能,您可以尝试通过自己将本地图像的引用放入 androids 媒体数据库

    mMediaProvider = mContext.getContentResolver().acquireProvider("media");
    mImagesUri = Images.Media.getContentUri(volumeName);
    result = mMediaProvider.insert(mImagesUri, values);

这里是媒体扫描器的源代码,它应该包含所有必要的代码片段,如何从 jpg 中填充值

【讨论】:

    【解决方案3】:

    图片保存后调用scan方法扫描图库,会显示图库中的图片。

      scanFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/appfolder/imgname"+imagenumber+".png");
    
    
     private void scanFile(String file) {
    
    
          MediaScannerConnection.scanFile(this,
                    new String[] { file.toString() }, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.i("ExternalStorage", "Scanned " + path + ":");
                            Log.i("ExternalStorage", "-> uri=" + uri);
                        }
                    });
    
    
        }
    

    【讨论】:

    • 你必须刷新那个指定的文件,然后只有它的作品,在 Nexus 5、5.0.2 中测试......它的作品,
    • 我想了一秒钟可能是您使用绝对路径而不是 file.toString() 的区别,但仍然使用 file.getAbsolutePath() 它在我的 Nexus 4 上不起作用, 5.0.1 虽然日志说它确实被扫描:I/ExternalStorage:扫描/storage/emulated/0/Android/data/com.something/files/Pictures/10141/7657/RZ-1430906494186.jpg:I/ExternalStorage: -> uri=content://media/external/file/43992 您使用什么应用程序来查看图库?我尝试了 Google 的“照片”和 Telegram(分享图片)。
    • 仅谷歌照片并在后期保存照片后执行调用扫描方法 scanFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "/dd/dddd"+imagenumber+".p​​ng");
    • 啊.. 但是您使用的是 PUBLIC 外部存储目录?因为造成这个问题的原因是文件存储在私有应用程序目录“externalStorage/Android/data/APP-ID/files/Pictures/...”中。我希望在删除应用程序时删除文件,但只要应用程序在那里,我希望它们在其他应用程序/图库中可见/可共享。
    【解决方案4】:

    正如您所说,{sdcard}/Android/data/ 文件夹包含一个 .nomedia 文件,那么我们可以为MediaScanner 发送广播以扫描文件夹的子文件夹,其中包含.nomedia 文件,通过使用以下代码指定该子文件夹路径。

    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file:// "+"Directory path")));
    

    【讨论】:

      【解决方案5】:

      试试下面的代码。它在 Lollipop 中对我有用,希望对你也有用

      ContentValues values = new ContentValues();
      values.put(MediaStore.Images.Media.DATA,"file path");
      values.put(MediaStore.Images.Media.MIME_TYPE,"image/jpeg");
      mContext.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);
      

      编辑:不要忘记将其添加到您的清单中(尽管在 Lollipop 中不再需要它):

      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      

      【讨论】:

      • 谢谢。我担心这个答案对我不起作用,但这是因为我只有 SDK 18 及更低版本的“写入外部存储”权限。现在有了所有 SDK 的许可,它就可以工作了。仍然需要在较低版本的 Android 中进行测试,但这至少是一个完美的开始!
      • 我获得了 100 个更多的声誉,因为我昨天经常浏览 stackoverflow 网络,只是为了寻找这个令人敬畏的答案。谢谢@Lokesh
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-02-07
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      相关资源
      最近更新 更多