Как я могу вызвать MediaScannerConnection.scanFile () асинхронно, получая при этом уведомление о его завершении? - PullRequest
3 голосов
/ 27 ноября 2011

Я хочу собрать некоторую информацию из MediaStore.Иногда файл .nomedia приводит к тому, что файл не сканируется, и поэтому я использую явный вызов, чтобы убедиться, что файл был проверен!

Итак, я звоню

MediaScannerConnection.scanFile(Context activity, String[] path, 
   String[] mimeTypes, OnScanCompletedListener oscl);

..., чтобы запустить сканирование.Однако это может занять некоторое время, поэтому я хотел бы запустить его в фоновом режиме ...

Я столкнулся с парой проблем, пытаясь это сделать:

  • Сначала я попытался вызвать MediaScannerConnection из нового потока, но это не сработало, потому что сканер запускался раньше всего после завершения действия.Я думаю, что параметр «Контекстная активность» вызовет запуск после завершения этой активности.

  • Секундное ожидание результата внутри другого потока не всегда нормально, поскольку от результата зависит, как продолжить.

Поэтому обаспособы не работают.: - (

Итак, мой вопрос: Как запустить MediaScannerConnection.scanFile() в потоке, отличном от потока действия? Если это невозможно, какова лучшая практика для выполнения асинхронной обработки?ИМХО, ожидание должно происходить внутри нового потока, но тогда уже слишком поздно использовать результат для принятия решения о том, как продолжить.


Пример для первой попытки - результат не возвращается:

Log.d(TAG, "MAIN: ID of the main thread ... " 
      + Thread.currentThread().getId());
final Object o = new Object();

Thread scannerThread = new Thread() {
  public void run() {
    Log.d(TAG, "SCAN: scanner thread is started ... (thread id: " 
      + Thread.currentThread().getId() + ")");
    MediaScannerConnection.scanFile(ActivityPlayer.this, new String[] { 
         mp3File.getAbsolutePath() }, null,
         new MediaScannerConnection.OnScanCompletedListener() {
           @Override
           public void onScanCompleted(String path, Uri uri) {
             Log.d(TAG, "SCAN: the onScanCompleted is called! (" + path + ")");
             synchronized (o) {
               o.notifyAll();
               Log.d(TAG, "SCAN: notify is successful executed!");
             }
           }
         });
         Log.d(TAG, "SCAN: MediaScanner is called");
       }
     };         
     Log.d(TAG, "MAIN: start scanning thread");
     scannerThread.start();

     synchronized (o) {
       try {
         Log.d(TAG, 
               "WAITER: Start: Waiting - for the notify of this object o!");
         o.wait();
         Log.d(TAG, "WAITER: End: Waiting - the notify happened!");
       } catch (Exception e) { // InterruptedException
         e.printStackTrace();
       }
     }  

Пример для второй попытки:

Log.d(TAG, "MAIN: ID of the main thread ... " 
      + Thread.currentThread().getId());
final Object o = new Object();

// call scanner ...
Log.d(TAG, "scanning of file started ...");
MediaScannerConnection.scanFile(ActivityPlayer.this, 
        new String[] {mp3File.getAbsolutePath() }, 
        null,   
        new MediaScannerConnection.OnScanCompletedListener() {
          @Override
          public void onScanCompleted(String path, Uri uri) {
            Log.d(TAG, "the onScanCompleted is called! (" + path + ")");
            synchronized (o) {
              o.notifyAll();
              Log.d(TAG, "notify is successful executed!");
            }
          }
        });
// Start thread for waiting ...
Thread waiterThread = new Thread() {
  public void run() {
    Log.d(TAG, "WAITER: waiter thread is started!");
    synchronized (o) {
      try {
        Log.d(TAG, 
              "WAITER: Start: Waiting - for the notify of this object o!");
        o.wait();
        Log.d(TAG, "WAITER: End: Waiting - the notify happened!");
      } catch (Exception e) { // InterruptedException
        e.printStackTrace();
      }
    }
  }
};
waiterThread.start();
Log.d(TAG, "MAIN: ended things ... ");

Заранее спасибо всем, у кого есть хорошая идея для решения этой проблемы!

1 Ответ

0 голосов
/ 07 ноября 2015

Я использую это

public class MediaLibraryHelper {
    public interface OnMediaScanListener{
        void onError();
        void onSuccess(Uri uri);
    }

    private MediaScannerConnection conn;
    private Context context;
    public MediaLibraryHelper(Context context){
        this.context=context;
    }

    public void scanFile(final File file,final OnMediaScanListener lis){
        if(conn!=null)
            conn.disconnect();

        if(!file.isFile()){
            lis.onError();
            return;
        }

        conn=new MediaScannerConnection(context,new MediaScannerConnectionClient(){


            public void onMediaScannerConnected() {
                conn.scanFile(file.getAbsolutePath(),null);
            }


            public void onScanCompleted(String arg0, Uri arg1) {
                conn.disconnect();
                if(arg1==null){
                    lis.onError();
                }
                lis.onSuccess(arg1);

            }});
        conn.connect();
    }


}
...