How to invoke Android media scanner for vendor provided external SD card, not the one obtained via getExternalStorage()

前端 未结 2 1960
面向向阳花
面向向阳花 2020-12-21 07:23

My app allows user to save files on an external SD card besides the getExternalStorage() path. I understand that Android does not have notion of external SD cardas such but

相关标签:
2条回答
  • 2020-12-21 08:03

    I took a look in Android open source code (Android 4.1)

    There is file called /packages/providers/MediaProvider/src/com/android/providers/media/MediaScannerReceiver.java

    It has following code:

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

    As you can see it will check for ACTION_MEDIA_MOUNT (which you use) and it will call scan(). However, it will use hardcoded MediaProvier.EXTERNAL_VOLUME (instead of passed file URI).

    Answering your question, it doesn't make sense for you to change your code. Any URI with file schema will work the same.

    However, there is a chance that vendor will modify this code.

    And one more thing. Android 4.2 introduced multiuser notion and each user has his/her own external storage. Based on this, shown code may have changed.

    Update 1

    It's interesting. Initially, I just looked through part of MediaScannerReceiver and was under impression that it will scan only one external volume. However, after you told me that you looked through the code and asked whether it will work. I investigate a little bit further and found that it will search all mountable volumes (as you said).

    As I understand it goes through following execution path (it in kind of pseudo-java code to disregard all instantiations and so on)

    • MediaScannerReceiver.onReceive calls scan(context, MediaProvider.EXTERNAL_VOLUME);
    • MediaScannerReceiver.scan calls context.startService( new Intent(context, MediaScannerService.class).putExtras(args)); where args contain key/value pair "volume"=MediaProvider.EXTERNAL_VOLUME)
    • MediaScannerService.onStartCommand calls mServicehandler.sendMessage
    • MediaScannerService.ServiceHandler.handleMessage receives a message and calls equivalent of scan(StorageManager.getVolumePaths(),MediaProvider.EXTERNAL_VOLUME)
    • MediaScannerService.scan calls MediaScanner.scanDirectories
    • MediaScanner goes through each directory one by one

    Taking into account that "StorageManager.getVolumePaths()" should return all mountable volumes, I think you should be fine with your current code (it will scan all volumes).

    0 讨论(0)
  • 2020-12-21 08:13

    For Api 8 and above you can use this

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

    This scans only an individual file and you can give any path here, including alternative external storage.

    0 讨论(0)
提交回复
热议问题