3

我的应用程序允许用户在 getExternalStorage() 路径之外的外部 SD 卡上保存文件。我知道 Android 没有外部 SD 卡的概念,但我们知道许多设备制造商为平板电脑/手机提供额外的 SD 卡插槽。并且此特定 SD 卡的路径可能取决于供应商。

我的应用程序为用户提供了一个首选项,他/她可以提供与 getExternalStorage() 返回的路径不同的 SD 卡供应商路径。

以前我会使用以下代码来调用媒体扫描仪,

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

但现在我想知道以下代码是否可行:

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

它会起作用吗?我没有这种带有额外 SD 卡插槽的设备来测试它,您的意见对我很有用。

4

2 回答 2

1

我看了一下Android开源代码(Android 4.1)

有一个名为 /packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerReceiver.java 的文件

它有以下代码:

 @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Uri uri = intent.getData();
        if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
            // scan internal storage
            scan(context, MediaProvider.INTERNAL_VOLUME);
        } else {
            if (uri.getScheme().equals("file")) {
                // handle intents related to external storage
                String path = uri.getPath();
                String externalStoragePath = Environment.getExternalStorageDirectory().getPath();

                Log.d(TAG, "action: " + action + " path: " + path);
                if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
                    // scan whenever any volume is mounted
                    scan(context, MediaProvider.EXTERNAL_VOLUME);
                } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) &&
                        path != null && path.startsWith(externalStoragePath + "/")) {
                    scanFile(context, path);
                }
            }
        }
    }

如您所见,它将检查 ACTION_MEDIA_MOUNT(您使用的)并调用 scan()。但是,它将使用硬编码的 MediaProvier.EXTERNAL_VOLUME(而不是传递的文件 URI)。

回答您的问题,您更改代码没有意义。任何带有文件模式的 URI 都可以正常工作。

但是,供应商有可能会修改此代码。

还有一件事情。Android 4.2 引入了多用户概念,每个用户都有自己的外部存储。基于此,显示的代码可能已更改。

更新 1

这真有趣。最初,我只是浏览了 MediaScannerReceiver 的一部分,并认为它只会扫描一个外部卷。但是,在您告诉我您查看了代码并询问它是否可以工作之后。我进一步调查,发现它会搜索所有可挂载的卷(如你所说)。

据我了解,它通过以下执行路径(它以伪Java代码的形式忽略所有实例化等等)

  • MediaScannerReceiver.onReceive 调用 scan(context, MediaProvider.EXTERNAL_VOLUME);
  • MediaScannerReceiver.scan 调用 context.startService(new Intent(context, MediaScannerService.class).putExtras(args)); 其中 args 包含键/值对 "volume"=MediaProvider.EXTERNAL_VOLUME)
  • MediaScannerService.onStartCommand 调用 mServicehandler.sendMessage
  • MediaScannerService.ServiceHandler.handleMessage 接收消息并调用等效于 scan(StorageManager.getVolumePaths(),MediaProvider.EXTERNAL_VOLUME)
  • MediaScannerService.scan 调用 MediaScanner.scanDirectories
  • MediaScanner 一个一个地遍历每个目录

考虑到“StorageManager.getVolumePaths()”应该返回所有可挂载的卷,我认为你应该对你当前的代码没问题(它将扫描所有卷)。

于 2013-01-31T02:56:17.987 回答
0

对于 Api 8 及更高版本,您可以使用它

 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);
  }
 });

这仅扫描单个文件,您可以在此处提供任何路径,包括替代外部存储。

于 2013-01-31T17:04:03.353 回答