Как я могу вызвать MediaScannerConnection.scanFile() асинхронно, получая при этом уведомление о его завершении?
Я хочу собрать некоторую информацию из 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 ответ
Я использую это
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();
}
}