Подтвердить что ты не робот

Как обновить MediaStore на Android?

Это началось как общий пользовательский вопрос на форумах Android. Однако он стал, по необходимости, вопросом программирования. Вот моя проблема.

Android имеет сервис - MediaScanner - который работает в фоновом режиме в любое время (я считаю), SD-карта не смонтирована и снова установлена. Эта служба собирает данные обо всех медиафайлах на карте и предоставляет SQLite DB, которые могут быть запрошены музыкальными приложениями. Большинство музыкальных приложений используют эту услугу, поскольку она экономит заряд батареи, связанный с сканированием SD-карты.

Поскольку я начал использовать android, у меня постоянно возникала проблема, при которой плейлисты M3U, синхронизированные с устройством, остаются в этой SQLite DB даже после удаления с SD-карты. Это дошло до того, что теперь у меня есть коллекция из примерно 40 списков воспроизведения, которые появляются в любом музыкальном приложении, которое я использую, несмотря на то, что на карте есть только около 10 м3u файлов. Остальные плейлисты не играют, и они пусты. Я могу удалить их вручную, удалив их из музыкального приложения, но мне это надоело. Должен быть лучший способ удалить эти плейлисты с призраками.

На Android Market есть два приложения - SDRescan и Music Scanner, которые, предположительно, делают именно это, но ни один из них не работает.

Я начал писать собственное приложение, чтобы обновить или удалить базу данных MediaStore и начать с нуля, но я не очень далеко. У меня есть приложение для Android, которое запускает следующий код:

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

Я нашел несколько примеров этого кода онлайн как способ сканирования SD-карты, но мне не повезло с этим. Какие-нибудь советы?

ПОЛНЫЙ КОД:

package com.roryok.MediaRescan;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;

public class MediaRescan extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 
        setContentView(R.layout.main);
    }

    //Rescan the sdcard after copy the file
    private void rescanSdcard() throws Exception{     
      Intent scanIntent = new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                Uri.parse("file://" + Environment.getExternalStorageDirectory()));   
      IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
      intentFilter.addDataScheme("file");     
      sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                Uri.parse("file://" + Environment.getExternalStorageDirectory())));    
    }
}
4b9b3361

Ответ 1

Хорошо, я сделал это.

Вместо повторной проверки карты приложение выполняет итерацию через все плейлисты в медиазвезде и проверяет длину поля _data. Я обнаружил, что для всех списков без связанного файла M3U это поле всегда было пустым. Тогда это был всего лишь случай поиска исходного кода для оригинального приложения для Android-андроида, поиска метода удаления и использования этого для удаления любых плейлистов с длиной 0. Я переименовал приложение PlaylistPurge (так как он не "повторно сканирует" ') и я отправляю код ниже.

Я, вероятно, также опубликую это где-нибудь на рынке или на моем собственном сайте, http://roryok.com

package com.roryok.PlaylistPurge;

import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;

public class PlaylistPurge extends ListActivity {

    private List<String> list = new ArrayList<String>();
    private final String [] STAR= {"*"};

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ListAdapter adapter = createAdapter();
        setListAdapter(adapter);
    }

    /**
     * Creates and returns a list adapter for the current list activity
     * @return
     */
    protected ListAdapter createAdapter()
    {
        // return play-lists
        Uri playlist_uri= MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;    
        Cursor cursor= managedQuery(playlist_uri, STAR, null,null,null);
        cursor.moveToFirst();
        for(int r= 0; r<cursor.getCount(); r++, cursor.moveToNext()){
            int i = cursor.getInt(0);
            int l = cursor.getString(1).length();
            if(l>0){
                // keep any playlists with a valid data field, and let me know
                list.add("Keeping : " + cursor.getString(2) + " : id(" + i + ")");
            }else{
                // delete any play-lists with a data length of '0'
                Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, i);
                getContentResolver().delete(uri, null, null);
                list.add("Deleted : " + cursor.getString(2) + " : id(" + i + ")");
            }
        }       
        cursor.close();
        // publish list of retained / deleted playlists
        ListAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);

        return adapter;
    }
}

ОБНОВЛЕНИЕ:

Здесь ссылка на сообщение в моем блоге о приложении http://roryok.com/blog/index.php/2010/07/23/clearing-out-deleted-playlists-in-android/

ОБНОВЛЕНИЕ 2: Вторник, 9 апреля 2013 г.

Я получил большой трафик в своем блоге с этого поста и огромное количество писем от людей, поблагодаривших меня за это. Рад, что это помогло! Любые потенциальные пользователи должны знать, что мое дерьмовое приложение в настоящее время падает, как только вы его запускаете, но на самом деле делает то, что оно должно делать! Я всегда собирался вернуться и исправить это разрушительное поведение и поставить его на рынок, надеюсь, 2013 год станет годом, когда я это сделаю.

Ответ 2

Вот простое в использовании решение на основе одного файла:

Добавление файла:

Всякий раз, когда вы добавляете файл, сообщите MediaStoreконтент-провайдеру, используя:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(newMediaFile)));

Удаление файла:

Аналогичным образом, когда вы удаляете файл, сообщите MediaStoreконтент-провайдеру, используя:

getContentResolver().delete(uri, null, null) (Credit goes to [DDSports][1])

Ответ 3

Вы можете запросить повторное сканирование определенных файлов с помощью следующего кода.

ПРИМЕЧАНИЕ. Переданный MIME TYPE важен. Я заметил, что изменения, сделанные в тегах MP3 ID3, не обновились должным образом в SQLite, если я использовал "*/*", однако используя "аудио/mp3" работал

MediaScannerConnection.scanFile(
    context, 
    new String[]{ pathToFile1, pathToFile2 }, 
    new String[]{ "audio/mp3", "*/*" }, 
    new MediaScannerConnectionClient()
    {
        public void onMediaScannerConnected()
        {
        }
        public void onScanCompleted(String path, Uri uri)
        {
        }
    });