2010-07-21 13 views
44

Dies begann als eine allgemeine Benutzerfrage in Android-Foren. Es ist jedoch notwendigerweise eine Programmierfrage geworden. Hier ist mein Problem.Wie kann ich MediaStore auf Android aktualisieren?

Android hat einen Dienst - MediaScanner - der im Hintergrund läuft (ich glaube) die SD-Karte ist unmounted und re-mounted. Dieser Dienst sammelt Daten zu allen Mediendateien auf der Karte und stellt eine SQLite-DB zur Verfügung, die von Musikanwendungen abgefragt werden kann. Die meisten Musikanwendungen nutzen diesen Dienst, da sie beim Scannen der SD-Karte Batteriestrom sparen.

Seit ich Android benutze, hatte ich immer ein Problem, dass M3U-Playlists, die mit dem Gerät synchronisiert wurden, in dieser SQLite-DB bleiben, auch wenn sie von der SD-Karte gelöscht wurden. Es ist soweit gekommen, dass ich jetzt eine Sammlung von ungefähr 40 Playlists in jeder Musik-App habe, die ich benutze, obwohl nur 10 m3u Dateien auf der Karte sind. Die verbleibenden Wiedergabelisten werden nicht abgespielt und sind leer. Ich kann sie manuell entfernen, indem ich sie aus der Musik-App lösche, aber ich habe es satt, das zu tun. Es muss einen besseren Weg geben, diese Geister-Playlists zu entfernen.

Es gibt zwei Apps im Android Market - SDRescan und Music Scanner, die angeblich genau das tun, aber keiner von beiden funktioniert.

Ich habe angefangen, meine eigene App zu schreiben, um die MediaStore-Datenbank zu aktualisieren oder zu löschen und von vorne anzufangen, aber ich komme nicht sehr weit. Ich habe eine Android-App bekam, die den folgenden Code ausgeführt wird:

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

ich ein paar Beispiele dieser Code online als eine Möglichkeit gefunden haben, die SD-Karte zu scannen, aber ich habe kein Glück mit ihm überhaupt . Irgendwelche Tipps?

FULL CODE:

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())));  
    } 
} 
+0

Hallo, Wissen Sie, ob sendBroadcast (neu Intent (Intent.ACTION_MEDIA_MOUNTED, Uri.parse ("file: //" + Environment.getExternalStorageDirectory()))); funktioniert für SD-Karte, die extra Slot-Karten sind? Mit anderen Worten: getExternalStorageDirectory() gibt einen Pfad zur SD-Karte zurück, der intern ist, aber möglicherweise eine vom Hersteller bereitgestellte externe Karte? Wie kann man Medienscanner für solche Karten aufrufen? – Ahmed

+0

scheint es im Moment keine Möglichkeit zu geben, dies zu tun. Sieh diesen Thread: http://StackOverflow.com/Questions/5453708/android-how-to-use-environment-getexternalstorageverzeichnis – roryok

Antwort

18

Ok, ich habe es getan.

Anstatt die Karte erneut zu scannen, durchläuft die App alle Mediathek-Wiedergabelisten und prüft die Länge des Feldes _data. Ich entdeckte, dass für alle Listen ohne zugehörige M3U-Datei dieses Feld immer leer war. Dann ging es nur darum, den Quellcode für die originale android Musik App zu finden, die delete Methode zu finden und damit Playlisten mit einer Länge von 0 zu löschen. Ich habe die App PlaylistPurge umbenannt (da sie nicht erneut scannt) (mehr) und poste den Code unten.

Ich werde wahrscheinlich auch diese irgendwo veröffentlichen, entweder auf dem Markt oder auf meiner eigenen Website, 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; 
    } 
} 

UPDATE:

Hier ist ein Link zu einem Beitrag auf meinem Blog über die App http://roryok.com/blog/index.php/2010/07/23/clearing-out-deleted-playlists-in-android/

UPDATE 2: Freitag, 9. April 2013

ich habe eine Menge Verkehr zu meinem Blog von diesem Posten bekommen, und einem eine riesige Anzahl von E-Mails von Leuten, die mir dafür danken. Froh, dass es geholfen hat! Alle potenziellen Nutzer sollten wissen, dass meine beschissene App momentan abstürzt, sobald sie ausgeführt wird, aber tatsächlich tut, was sie tun soll! Ich wollte immer zurückgehen und dieses krachende Verhalten beheben und es auf den Markt bringen, hoffentlich wird 2013 das Jahr sein, in dem ich das mache.

+0

löscht das die Playlisten, die nicht gelöscht wurden, aber keine Lieder haben? –

+0

Hallo Vinay. Nein, es werden nur Einträge für Playlists gelöscht, die gelöscht wurden. Playlists mit 0 Einträgen sind davon nicht betroffen – roryok

+0

Danke! Gute Lösung –

10

Sie können eine erneute Überprüfung bestimmter Dateien mit dem folgenden Code anfordern.

HINWEIS: Der übergebene MIME TYPE ist wichtig. Ich bemerkte zu MP3 ID3-Tags vorgenommenen Änderungen nicht richtig in der SQLite hatte zu aktualisieren, wenn ich „*/*“ verwendet, jedoch mit „audio/mp3“ arbeitete

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

Sie müssen den Mime-Typ überhaupt nicht bestehen. Wenn die Datei korrekt benannt ist (* .mp3, * .m4a usw.), ermittelt der Scanner den Mime-Typ aus der Erweiterung. Also, statt der neuen String [] {** Mime-Typen **}, übergeben Sie einfach null. – Baron

+0

Das hat mir geholfen, das Entfernen gelöschter und verschobener Dateien zu erkennen. Für meinen Fall kommuniziere ich über MTP (Media Transfer Protocol) und ohne die Dateien erneut zu scannen, scheinen sie immer noch dort zu sein, bis sie neu gestartet werden. – egfconnor

+0

soweit ich weiß, wird das immer noch _playlists_ betreffen, die auf gelöschte Medien verweisen, nur die Bibliotheksreferenzen – roryok

42

Hier ist eine einfache ‚einzige Datei-basierte Lösung‘ :

Wenn Sie eine Datei, lassen Mediastore Content Provider

mit Add es kennt
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageAdded))); 

Für löschen. nur verwenden getContentResolver() löschen (uri , Null, null) (Kredit geht an DDSports)

+0

vermutlich ist das eine Lösung für das Problem verwaister Dateien, die zuerst auftauchen. Meine App war, das Durcheinander zu bereinigen, das von _anderen_ Apps übrig geblieben ist, die das NICHT tun – roryok

+1

Ich gab diesem eine Aufzählung, weil, während es das genaue Problem nicht löst, es eine sehr wertvolle Information ist, die ich denke, relevant ist. – Matt

+2

Dies funktioniert nur beim Hinzufügen einer Datei. Es funktioniert nicht, wenn eine Datei gelöscht werden soll. Sie benötigen den getContentResolver(). Delete (uri, null, null); Methode dafür. – DDSports

Verwandte Themen