Как обновить MediaStore на Android?
это началось как общий вопрос пользователя на форумах Android. Однако это стало, по необходимости, вопросом программирования. Вот в чем моя проблема.
Android имеет сервис-MediaScanner - который работает в фоновом режиме в любое время (я считаю) SD-карта не монтируется и повторно монтируется. Эта служба собирает данные обо всех медиафайлах на карте и предоставляет базу данных SQLite, которую могут запрашивать музыкальные приложения. Большинство музыкальных приложений используют эту услугу, так как она экономит батарея-слив, связанный со сканированием SD-карты.
С тех пор, как я начал использовать android, у меня постоянно была проблема, при которой плейлисты m3u, синхронизированные с устройством, остаются в этой БД SQLite даже после удаления с SD-карты. Это дошло до того, что теперь у меня есть коллекция из 40 плейлистов, отображаемых в любом музыкальном приложении, которое я использую, несмотря на то, что на карте есть только около 10 файлов m3u. Остальные списки воспроизведения не воспроизводятся и пусты. Я могу удалить их вручную удалив их из музыкального приложения,но я устал от этого. Должен быть лучший способ удалить эти списки воспроизведения ghost.
на 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())));
}
}
3 ответов
здесь просто один файл решения':
всякий раз, когда вы добавить файл, пусть Поставщик контента MediaStore знает об этом, используя
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageAdded)));
на удаление: просто используйте getContentResolver ().удалить (uri, null, null) (кредит переходит в DDSports)
хорошо, я сделал это.
вместо повторного сканирования карты приложение выполняет итерацию по всем плейлистам в mediastore и проверяет длину поля _data. Я обнаружил, что для всех списков без связанного файла M3U это поле всегда было пустым. Тогда это был просто случай поиска исходного кода для оригинального музыкального приложения android, поиска метода удаления и использования его для удаления любых плейлистов длиной 0. Я переименовал приложение PlaylistPurge (так как это не так 'rescan' больше) и публикую код ниже.
Я, вероятно, также опубликую это где-нибудь, либо на рынке, либо на своем собственном сайте,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 будет годом, когда я это сделаю.
вы можете запросить повторное сканирование конкретных файлов, используя следующий код.
Примечание: переданный тип MIME важен. Я заметил, что изменения, внесенные в теги 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)
{
}
});