【问题标题】:android : Copying an .jpg image after deleting the same gives errorandroid:删除后复制.jpg图像会出错
【发布时间】:2019-07-28 05:14:27
【问题描述】:

从应用程序 Java 端,使用 file.mkdir 创建目录并复制 文件夹中存在的 JPG 文件(jpg_3) 使用 java API 从 USB 大容量存储设备。

然后使用 File.delete() 方法从内存中删除相同的文件和目录。

当尝试将这些相同的文件添加到内存时,文件没有被复制,而是出现以下异常:

02-20 16:11:56.727 17471 17964 E XXXXXX:java.io.FileNotFoundException:/storage/emulated/0/XXX/jpg_3/galaxy-wallpaper-4.jpg:打开失败:ENOENT(没有这样的文件或目录)

后来我们发现下面提到的进程仍在访问那些被删除的文件。

shell@ABC:/storage/emulated/legacy/XXX # lsof | grep jpg_3

sdcard 1819 media_rw 5 ??? ??? ??? ??? /data/media/0/XXX/jpg_3/galaxy-wallpaper-4.jpg(已删除)

android.p 3205 u0_a4 67 ??? ??? ??? ??? /storage/emulated/0/XXX/jpg_3/galaxy-wallpaper-4.jpg(已删除)

shell@ABC:/storage/emulated/legacy/XXX #ps 3205

用户 PID PPID VSIZE RSS WCHAN PC NAME

u0_a4 3168 1830 1022984 58080 ffffffff 76e7f868 S android.process.media

如果我们尝试使用 mkdir(在 ADB Shell 中)创建具有相同名称的目录,我们会得到以下错误:

shell@ABC:/storage/emulated/legacy/XXX # mkdir jpg_3 jpg_3 的 mkdir 失败,设备或资源忙

我们怀疑这些 .jpg 文件的软链接即使在删除后仍然存在,从而导致上述错误。

我们尝试了 File.delete() 以及下面提到的代码 参考:android : deleting an image

public static void deleteFileFromMediaStore(final ContentResolver contentResolver, final File file) {
String canonicalPath;
try {
    canonicalPath = file.getCanonicalPath();
} catch (IOException e) {
    canonicalPath = file.getAbsolutePath();
}
final Uri uri = MediaStore.Files.getContentUri("external");
final int result = contentResolver.delete(uri,
        MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
if (result == 0) {
    final String absolutePath = file.getAbsolutePath();
    if (!absolutePath.equals(canonicalPath)) {
        contentResolver.delete(uri,
                MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
    }
}

}

如何解决 .jpg 文件的软链接问题?

注意:我们还尝试重新扫描设备

MediaScannerConnection.scanFile(mService.getApplicationContext(), new String[]{
            oDeleteFile.getAbsolutePath().toString()
    }, null, null);

但这并没有帮助。

提前致谢

【问题讨论】:

标签: android jpeg delete-file file-copying


【解决方案1】:

在 Android Nougat 版本中,有一个文件 ExifInterface.java(/frameworks/base/media/java/android/media/) 有一个函数 'getJpegAttributes' 从 JPEG 输入流中加载 EXIF 属性。下面是文件的链接—— http://androidxref.com/7.0.0_r1/xref/frameworks/base/media/java/android/media/ExifInterface.java

在这个函数中,DataInputStream已经通过以下代码创建——

DataInputStream dataInputStream = new DataInputStream(inputStream);

但是在函数结束时,同一个文件流并没有被关闭。因此,Android Media Provider 进程甚至不需要访问该文件 尽管 MediaScannerService.java 完成了对复制文件的扫描。所以当我们在函数末尾通过如下代码关闭文件流时——

if (null != dataInputStream) {
    Log.d(TAG, "dataInputStream.close()" );
    dataInputStream.close();
}

问题得到解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多