80

我试图简单地将一个简单的 XML 文件写入 SD 卡,我注意到我的 Nexus 4 确实写入了该文件,但它无法通过使用 Windows 7 的 MTP 协议查看。

代码:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    CustomerQueryRqType customerQueryRequest = new CustomerQueryRqType();
    Serializer serializer = new Persister();
    File myFile = new File(Environment.getExternalStorageDirectory() + "/customerQueryRequest.xml");

    try {
        boolean created = myFile.createNewFile();
        serializer.write(customerQueryRequest, myFile);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我可以使用 Astro 文件管理器查看手机本身的文件:

截屏

但 Windows 看不到它...:

截屏

adb shell目录上显示:

ls -l
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Alarms
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Android
drwxrwxr-x root     sdcard_rw          2012-11-21 19:30 DCIM
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Download
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Movies
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Music
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Notifications
drwxrwxr-x root     sdcard_rw          2012-11-19 12:06 Pictures
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Podcasts
drwxrwxr-x root     sdcard_rw          2012-11-19 13:22 Ringtones
drwxrwxr-x root     sdcard_rw          2012-11-19 14:33 bluetooth
-rw-rw-r-- root     sdcard_rw       79 2012-12-05 22:26 customerQueryRequest.xml
drwxrwxr-x root     sdcard_rw          2012-11-20 02:50 data
-rw-rw-r-- root     sdcard_rw    11394 2012-11-19 13:54 eightpen_custom_gestures
drwxrwxr-x root     sdcard_rw          2012-11-19 13:17 media

我的 Nexus 4 怎么了?为什么它对 Windows 隐藏我的东西?

4

12 回答 12

72

似乎是影响通过 MTP 访问 Android USB 文件的已知问题。MTP 缓存会过期,直到手机重新启动。

一种解决方法是:

  • 清除“媒体存储”应用程序的数据
  • 使用SDrescanSD Scanner(也适用于 Android 4.4/5,在F-Droid上可用)应用程序强制更新

或者根本避免使用 USB。该问题不会影响访问文件的其他方法。例如,尝试使用 AirDroid传输文件。


注意:这不适用于 Android 5.0.2:清除“媒体存储”并使用 SD Rescanner 后,这些文件夹在 Windows 7 中显示为无法打开的 4K 文件。此时唯一的解决方案是再次清除媒体存储并重新启动设备

于 2012-12-28T19:02:43.277 回答
44

您可以在文件关闭后使用以下代码

MediaScannerConnection.scanFile(this, new String[] { file.getAbsolutePath() }, null, null);

来源: https ://code.google.com/p/android/issues/detail?id=38282

于 2013-12-06T00:47:06.447 回答
5

在这个问题上花了几个小时后,我解决了这样的问题:

private void rescanFolder(String dest) {
    // Scan files only (not folders);
    File[] files = new File(dest).listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isFile();
        }
    });

    String[] paths = new String[files.length];
    for (int co=0; co< files.length; co++)
        paths[co] = files[co].getAbsolutePath();

    MediaScannerConnection.scanFile(activity, paths, null, null);

    // and now recursively scan subfolders
    files = new File(dest).listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isDirectory();
        }
    });

    for (int co=0; co<files.length; co++)
        rescanFolder(files[co].getAbsolutePath());
} 

问题是您必须只扫描文件(而不是文件夹),然后为每个 fubfolder 递归重复

编辑 此外,如果您不希望将图片添加到您的相册(但只是您的内容通过 mtp 协议显示),请记住.nomedia在重新扫描之前在您的文件夹中放置一个空文件,如下所示:

new File(myFolder + File.separator + ".nomedia").createNewFile();
rescanFolder(myFolder);
于 2014-12-05T17:32:36.203 回答
4

对于已接受答案中提到的错误,我发现的最佳解决方法是使用 SSH 将数据从 Android 操作系统复制到另一台机器/服务器(Linux、MacOS、Windows)。

  • 确保设备 (Android) 和机器(您要复制数据的位置)可以通过 IP 或主机名访问,例如通过将它们连接到同一个 wifi 网络。

可选和推荐

  • 使用 USB 网络共享连接 android 设备。由于有线连接,这确保了快速的速度,并保证了两个 IP 地址对彼此可见,因为它们都在同一个网络中。

在安卓设备中

  • 安装 SSH 服务器。SSHelper的工作就像一个魅力
  • 运行 SSHelper 并转到配置选项卡以获取 IP 地址、端口和密码。在下面的示例中,它们是 192.168.1.5、2222 和 'admin'。
  • 默认密码是 admin 但如果您决定更改它,请在更改后点击“使用新值重新启动服务器”按钮

在机器里

  • 安装 rsync。如果碰巧使用 Ubuntu,它已经默认安装。
  • 打开 shell 并键入以下命令。将 IP 地址和端口更改为您的值

rsync -avzhP --inplace --info=progress2 -e 'ssh -p 2222' 192.168.1.5:/storage/emulated/0/DCIM/Camera/ /home/username/path/to/pics/

  • 您将收到以下提示,请输入您的密码

SSHelper Version 8.5 Copyright 2014, P. Lutus Default password is "admin" (recommend: change it) username@192.168.1.5's password: admin receiving incremental file list

其他建议对我不起作用:

  • 设备不支持使用 USB 存储模式而不是 MTP(与许多其他较新的设备一样)。
  • 我的操作系统(Android 6.0.1)中没有清除“媒体存储”应用数据的选项。
  • 通过网络共享文件的其他方法也有其缺点。FTP 不保证文件的完整性。如果断开连接,它会覆盖或跳过所有文件,因此其中一个文件可能不完整。其他协议可能难以安装,其他应用程序可能使用专有协议。
于 2016-12-25T12:35:43.923 回答
3

在 Xperia Z 上,以下代码运行良好:

  String screenShotFile = "....";
  activity.sendBroadcast(new Intent(
        Intent.ACTION_MEDIA_MOUNTED, Uri
                .fromFile(screenShotFile)));

对于 4.4+ 使用:

activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                                Uri.fromFile(screenShotFile)));

(不幸的是,我不记得我是否已经测试得足够好)

http://commonsware.com/blog/2013/11/06/android-4p4-permission-regressions.html

于 2013-07-29T17:24:17.877 回答
2

注意/存储/模拟。Android 4.2 有一些时髦的模拟每个应用程序/用户访问的东西,例如每个用户都有一个单独的 /sdcard/。尝试将文件移动到 /sdcard/ 而不是显示的模拟 sdcard。

于 2012-12-07T02:43:49.407 回答
2

提出质疑的简单代码如何在 Android 上刷新 MediaStore?如果在我将文件放在外部存储上后调用,则对 MediaStore 进行必要的更新。我的 Nexus 4 上的内容会在 Window 7 文件资源管理器中立即刷新。

于 2013-07-03T12:13:24.317 回答
1

我需要为我的应用创建一个目录并复制一些示例文件。经过大量的实验和研究,以下程序对我来说完美无缺:

1) 使用 File.mkdir() 创建目录。

2) 复制目录中的文件并在每个文件上运行 MediaScanner。

MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, null, null);

3) 在目录上运行 MediaScanner。

MediaScannerConnection.scanFile(context, new String[]{directory.getAbsolutePath()}, null, null);

结果:文件和目录通过 MTP 立即出现在 PC 上。

于 2015-07-19T04:22:50.090 回答
1

我的 OneplusOne 也有类似的问题:

软件更新(到 6.0.1)后,我在连接到计算机(PTP 和 MTP)时看不到我的相机照片。应用程序的 SDRescan 和 SDscanner 均无效。

我的解决方案是使用终端或手机上的任何文件资源管理器应用程序将所有图片从 DCIM 复制到另一个文件夹。连接到计算机时,我能够看到复制的文件..我将它们移动到我的计算机并清除了我的相机文件夹。没有永久的解决方案,但至少在我进行下一次备份之前,它为我解决了这个问题。=D

于 2016-08-16T12:05:06.133 回答
0

以上答案适用于创建文件。如果您稍后删除该文件并希望也反映该更改,您可以执行以下操作之一;让我们首先介绍两种看似可行但会在某些设备上引起问题的解决方案。第一个是扫描删除的文件:

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

这适用于许多设备以删除文件,但在某些设备上,它实际上会导致创建一个新的 0 字节文件,这可能不是您想要的。在这种情况下,如果你在 < 4.4 KitKat 上运行,你可以这样做:

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(folder)));

其中文件夹等于 file.getParentFile()。不幸的是,在 KitKat 4.4 及更高版本上,这将导致抛出 SecurityException,因此对于这些设备,您可以尝试直接从 Media Store 中删除:

final Uri externalFilesUri = Files.getContentUri("external");
context.getContentResolver().delete(externalFilesUri, Files.FileColumns.DATA + "=?", new String[] {file.getAbsolutePath()});

我已经测试了这个作为 ACTION_MEDIA_MOUNTED 在 KitKat 上不起作用的解决方法,它适用于我在 Nexus 5 上的测试。

于 2014-02-20T19:52:39.427 回答
0

最近我遇到了同样的问题,但一些额外的研究有助于找到隐藏文件。谷歌似乎在存储结构上做了一些改变。所有这些文件都被移动到另一个文件夹This Computer\HTC One\Internal Storage\storage\emulated\0。但奇怪的是,并非所有文件都被移动了。

安卓 4.4.2

于 2014-05-30T05:23:54.883 回答
0

此处的文档中,您需要调用 MediaScannerConnection.scanFile :

// Tell the media scanner about the new file so that it is
// immediately available to the user.
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);
    }
});
于 2017-12-29T22:18:54.120 回答