如何为供应商提供的外部SD卡调用Android媒体扫描程序,而不是通过getExternalStorage()获取的SD卡

时间:2013-01-22 00:15:52

标签: android

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

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

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

  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卡插槽的设备来测试它,你的意见对我有用。

2 个答案:

答案 0 :(得分: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接收消息并调用相当于的消息 扫描(StorageManager.getVolumePaths(),MediaProvider.EXTERNAL_VOLUME)
  • MediaScannerService.scan调用MediaScanner.scanDirectories
  • MediaScanner逐个浏览每个目录

考虑到“StorageManager.getVolumePaths()”应该返回所有可安装的卷,我认为您应该可以使用当前代码(它将扫描所有卷)。

答案 1 :(得分: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);
  }
 });

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