为什么Images.Media.insertImage返回null

21

我有一段代码,其中我运行了方法MediaStore.Images.Media.insertImage(不是从文件名插入),此代码将图像保存到MediaStore并返回图像的uri。 我知道如果出现任何错误,它会返回null而不是uri。 这张图片已经被许多人多次下载,但偶尔会从该方法返回null。 这种情况从未发生在我的设备上,因此我不知道发生了什么。 有什么原因可能会导致这种情况? 另外一个帖子也有同样的问题,但答案是指向MediaStore源代码的链接,但该链接指向一个页面,显示该链接不可用。 感谢您的帮助。

当我移除SD卡后,我遇到了这个错误,所以我知道这可能是一个原因,但我不确定,感觉如果卡已满也会出现类似的问题。 仍然想知道是否还有其他原因。

8个回答

20

在某些版本的Android中,当您没有/sdcard/DCIM/Camera目录时似乎会发生这种情况。对我来说,创建此目录(并具有权限)解决了问题。


4
我也曾经在设备重置后遇到过这种情况。在使用默认的Android相机应用程序拍照后,将创建该文件夹,之后我可以从我的代码中将图片插入其中。 - Mark Beaton

9

MediaStore.Images.Media.insertImage实际上是访问外部存储器以保存图像。

以下是可能导致您的应用失败的一些重要提醒:

  1. 如果处于大容量存储模式,则USB连接将阻止SD卡使用。

  2. 可能有其他因素导致SD卡不可访问,因此请确保您可以使用文件浏览器访问SD卡。

  3. 确保您的权限已正确配置为android.permission.WRITE_EXTERNAL_STORAGE

将此发布在此处以完整性,因为我从insertImage获取了null,并且原因是1。


6

我曾经遇到过相同的问题,但是什么都没用。但最后在3个小时后它终于起作用了。

解决方案:我发现只要我们不从图片库中删除该图像,它就可以正常工作,否则它就会返回null。但突然间我尝试更改标题和描述名称,它就像魔法一样奏效了。

因此,我已经添加了一个日期与位图的标题和描述。以防用户从文件管理器手动删除位图。即使这样,它还是可以正常工作的。

  private fun insertImage(cr: ContentResolver,
        source: Bitmap?,
        title: String,
        description: String
    ): String? {

        val sdf = SimpleDateFormat("MM-dd-yyyy-hh.mm.ss.SSS.a", Locale.US)
        val date=sdf.format(Date())

        val values = ContentValues()
        values.put(Images.Media.TITLE, title)
        values.put(Images.Media.DISPLAY_NAME, title+date)
        values.put(Images.Media.DESCRIPTION, description+date)
        values.put(Images.Media.MIME_TYPE, "image/jpeg")
        // Add the date meta data to ensure the image is added at the front of the gallery
        values.put(Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000)
        values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis())

        var url: Uri? = null
        var stringUrl: String? = null    /* value to be returned */

        try {
            url = cr.insert(Images.Media.EXTERNAL_CONTENT_URI, values)

            if (source != null) {
                val imageOut = cr.openOutputStream(url!!)
                try {
                    source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut)
                } finally {
                    imageOut!!.close()
                }


            } else {
                cr.delete(url!!, null, null)
                url = null
            }
        } catch (e: Exception) {
            if (url != null) {
                cr.delete(url, null, null)
                url = null
            }
        }

        if (url != null) {
            stringUrl = url.toString()
        }

        return stringUrl
    }

我在这个应用中实现了分享新闻位图功能,并且它正常运行。享受吧!

在安卓10上,我遇到了这个问题。通过给标题和描述添加日期对我有用。你能解释原因吗?谢谢你节省了我的时间@MAyank - Asif Ullah

5
请确保您在清单文件中添加了权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在调用
MediaStore.Images.Media.insertImage
之前,请添加以下代码:
File sdcard = Environment.getExternalStorageDirectory();
    if (sdcard != null) {
        File mediaDir = new File(sdcard, "DCIM/Camera");
        if (!mediaDir.exists()) {
            mediaDir.mkdirs();
        }
    }

1
那第二个权限没有任何作用 - 它应该用大写字母 READ_EXTERNAL_STORAGE - Richard Le Mesurier

5
当我在模拟器上使用全新的sdcard镜像进行测试时,遇到了这个问题。通过创建/sdcard/Pictures文件夹并使用new File("/sdcard/Pictures").mkdirs();解决了该问题。

1
当我遇到这样的问题时,我通过添加权限来解决它:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

1
第二个权限没有起作用 - 它应该用大写字母 READ_EXTERNAL_STORAGE - Richard Le Mesurier

1
我在获取用户允许WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE权限之前执行了MediaStore.Images.Media.insertImage,导致路径为空。因此,请确保用户已允许权限,然后再存储图像。

0

试试这个:

MediaStore.Images.Media.insertImage(context.getContentResolver(), bitmap, "filename", null);

Android 10需要在insertImage()方法的第三个参数中提供实际文件名。


你能告诉我源代码吗? - Sumit Shukla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接