Как я могу обновить MediaStore на Android?

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

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

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

На 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())));    
    }
}

4 ответа

Решение

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

Вместо повторного сканирования карты, приложение просматривает все списки воспроизведения в mediastore и проверяет длину поля _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 год будет годом, когда я это сделаю.

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

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

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

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

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

ПРИМЕЧАНИЕ: переданный MIME TYPE важен. Я заметил, что изменения, внесенные в теги 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)
        {
        }
    });

просто добавьте это в свою деятельность:

      Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

 MediaScannerConnection.scanFile(
            this, new String[]{"/storage/emulated/0"}, null,
            new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    Log.i("231","onScanCompleted");
                }
            });
Другие вопросы по тегам