Как обновить 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()))); } } 

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

    Всякий раз, когда вы добавляете файл, пусть MediaStore Content Provider знает об этом, используя

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

    Для удаления : просто используйте getContentResolver (). Delete (uri, null, null) (кредит отправляется в DDSports )

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

    Вместо повторной проверки карты приложение выполняет итерацию через все плейлисты в медиасторе и проверяет длину поля _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 list = new ArrayList(); 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; r0){ // 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(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 год станет годом, когда я это сделаю.

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

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

     MediaScannerConnection.scanFile( context, new String[]{ pathToFile1, pathToFile2 }, new String[]{ "audio/mp3", "*/*" }, new MediaScannerConnectionClient() { public void onMediaScannerConnected() { } public void onScanCompleted(String path, Uri uri) { } }); 
    Давайте будем гением компьютера.