In diesem Artikel wird der Quellcode des Systems analysiert und erklärt, wie man vom Programm erstellte Multimediadateien zur Medienbibliothek des Systems hinzufügt, wie man sie aus der Medienbibliothek löscht und welche Probleme bei den meisten Programmentwicklern häufig auftreten, z um sie zur Medienbibliothek hinzuzufügen. Ich werde diese Probleme einzeln durch Analyse des Quellcodes erläutern.
Multimediadatei-Scanmechanismus in Android
Android bietet ein großartiges Programm zum Hinzufügen von Multimediadateien zur Medienbibliothek. Dieses Programm ist MediaProvider. Schauen wir uns nun kurz das folgende Programm an. Werfen Sie zunächst einen Blick auf seinen Receiver
<receiver android:name="MediaScannerReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MEDIA_MOUNTED" /> <data android:scheme="file" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MEDIA_UNMOUNTED" /> <data android:scheme="file" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.MEDIA_SCANNER_SCAN_FILE" /> <data android:scheme="file" /> </intent-filter> </receiver>
MediaScannerReceiver empfängt nur die richtige Absicht, die den Aktions- und Datenregeln entspricht.
Wie MediaScannerReciever mit Intent umgeht
1. Scannen Sie den internen Speicher (nicht integrierte und externe SD-Karte) genau dann, wenn die Aktion android.intent.action.BOOT_COMPLETED empfangen wird
2. Außer bei anderen Intents als der Aktion android.intent.action.BOOT_COMPLETED müssen Daten weitergegeben werden.
3. Wenn Sie die Absicht Intent.ACTION_MEDIA_MOUNTED erhalten, scannen Sie die SD-Karte.
4. Beim Empfang der Absicht Intent.ACTION_MEDIA_SCANNER_SCAN_FILE gibt es kein Problem mit der Erkennung und eine einzelne Datei wird gescannt.
So funktioniert MediaScannerService
Tatsächlich übernimmt MediaScannerReceiver nicht wirklich die Scanarbeit, sondern startet einen Dienst namens MediaScannerService. Schauen wir uns weiterhin den Serviceteil des MediaProvider-Manifests an.
<service android:name="MediaScannerService" android:exported="true"> <intent-filter> <action android:name="android.media.IMediaScannerService" /> </intent-filter> </service>
scanFile-Methode in MediaScannerService
private Uri scanFile(String path, String mimeType) { String volumeName = MediaProvider.EXTERNAL_VOLUME; openDatabase(volumeName); MediaScanner scanner = createMediaScanner(); return scanner.scanSingleFile(path, volumeName, mimeType); }
Scan-Methode in MediaScannerService
private void scan(String[] directories, String volumeName) { // don't sleep while scanning mWakeLock.acquire(); ContentValues values = new ContentValues(); values.put(MediaStore.MEDIA_SCANNER_VOLUME, volumeName); Uri scanUri = getContentResolver().insert(MediaStore.getMediaScannerUri(), values); Uri uri = Uri.parse("file://" + directories[0]); sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_STARTED, uri)); try { if (volumeName.equals(MediaProvider.EXTERNAL_VOLUME)) { openDatabase(volumeName); } MediaScanner scanner = createMediaScanner(); scanner.scanDirectories(directories, volumeName); } catch (Exception e) { Log.e(TAG, "exception in MediaScanner.scan()", e); } getContentResolver().delete(scanUri, null, null); sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_FINISHED, uri)); mWakeLock.release(); }
createMediaScanner-Methode in MediaScannerService
private MediaScanner createMediaScanner() { MediaScanner scanner = new MediaScanner(this); Locale locale = getResources().getConfiguration().locale; if (locale != null) { String language = locale.getLanguage(); String country = locale.getCountry(); String localeString = null; if (language != null) { if (country != null) { scanner.setLocale(language + "_" + country); } else { scanner.setLocale(language); } } } return scanner; }
Anleitung Eine neu erstellte Datei scannen
Hier gibt es zwei Möglichkeiten, neu erstellte Dateien zur Medienbibliothek hinzuzufügen.
Der einfachste Weg
Senden Sie einfach eine korrekte Intent-Übertragung an den MediaScannerReceiver.
String saveAs = "Your_Created_File_Path" Uri contentUri = Uri.fromFile(new File(saveAs)); Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,contentUri); getContext().sendBroadcast(mediaScanIntent);
Die oben beschriebene minimalistische Methode funktioniert in den meisten Fällen normal, funktioniert jedoch in einigen Fällen nicht, was in einem späteren Abschnitt vorgestellt wird. Selbst wenn Sie mit der oben genannten Methode Erfolg haben, wird empfohlen, den späteren Abschnitt über die Gründe für das Scheitern der Übertragung bei der Übertragung weiterzulesen.
MediaScannerConnection verwenden
public void mediaScan(File file) { MediaScannerConnection.scanFile(getActivity(), new String[] { file.getAbsolutePath() }, null, new OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { Log.v("MediaScanWork", "file " + path + " was scanned seccessfully: " + uri); } }); }
Die scanFile-Methode von MediaScannerConnection wurde ab 2.2 (API 8) eingeführt.
Erstellen Sie ein MediaScannerConnection-Objekt und rufen Sie dann die scanFile-Methode auf
Es ist ganz einfach, siehe http://developer.android.com/reference/android/media/MediaScannerConnection.html
So scannen Sie mehrere Dateien
1. Senden Sie mehrere Intent.ACTION_MEDIA_SCANNER_SCAN_FILE-Broadcasts
2. Verwenden Sie MediaScannerConnection und übergeben Sie das Array der hinzuzufügenden Pfade.
Warum das Senden von MEDIA_SCANNER_SCAN_FILE nicht wirksam wird
Was den Grund betrifft, warum es auf einigen Geräten nicht wirksam wird, denken viele Leute, dass es an der API liegt. Dies ist jedoch nicht der Fall hängt tatsächlich mit dem Dateipfad zusammen, den Sie eingegeben haben. Schauen Sie sich den onReceive-Code des Empfängers an.
public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Uri uri = intent.getData(); if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { // scan internal storage scan(context, MediaProvider.INTERNAL_VOLUME); } else { if (uri.getScheme().equals("file")) { // handle intents related to external storage String path = uri.getPath(); String externalStoragePath = Environment.getExternalStorageDirectory().getPath(); Log.d(TAG, "action: " + action + " path: " + path); if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { // scan whenever any volume is mounted scan(context, MediaProvider.EXTERNAL_VOLUME); } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) && path != null && path.startsWith(externalStoragePath + "/")) { scanFile(context, path); } } } }
Alles ist korrekt, bis auf den eingehenden Pfad. Weil Sie möglicherweise den Dateipfad fest codiert haben. Da es ein solches Urteil path.startsWith(externalStoragePath + „/“) gibt, werde ich hier ein einfaches Beispiel geben.
final String saveAs = "/sdcard/" + System.currentTimeMillis() + "_add.png"; Uri contentUri = Uri.fromFile(new File(saveAs)); Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,contentUri); getContext().sendBroadcast(mediaScanIntent); Uri uri = mediaScanIntent.getData(); String path = uri.getPath(); String externalStoragePath = Environment.getExternalStorageDirectory().getPath(); Log.i("LOGTAG", "Androidyue onReceive intent= " + mediaScanIntent + ";path=" + path + ";externalStoragePath=" + externalStoragePath);
Werfen wir einen Blick auf das Ausgabeprotokoll und analysieren den Grund.
LOGTAG Androidyue onReceive intent= Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/1390136305831_add.png };path=/sdcard/1390136305831_add.png;externalStoragePath=/mnt/sdcard
Die obige Ausgabeanalyse zeigt, dass die von Ihnen gesendete Übertragung und Aktion korrekt sind, die Datenregeln ebenfalls korrekt sind und Ihr Dateipfad ebenfalls vorhanden ist, der Dateipfad /sdcard/1390136305831_add.png jedoch nicht Beginnt nicht mit dem Stammpfad des externen Speichers /mnt/sdcard/. Daher wurde der Scanvorgang nicht gestartet, was dazu führte, dass die Datei nicht zur Medienbibliothek hinzugefügt wurde. Bitte überprüfen Sie daher den Pfad der Datei.
So entfernen Sie sie aus der Medienbibliothek
Wenn wir eine Multimediadatei löschen, bedeutet das, dass wir die Datei auch aus der Medienbibliothek löschen müssen.
Können Sie einfach eine Sendung senden?
Kann das Senden einer Übertragung das Problem lösen? Ich wünschte, es könnte, aber es funktioniert nicht wirklich. Sie können es sehen, indem Sie sich den folgenden Code ansehen.
// this function is used to scan a single file public Uri scanSingleFile(String path, String volumeName, String mimeType) { try { initialize(volumeName); prescan(path, true); File file = new File(path); if (!file.exists()) { return null; } // lastModified is in milliseconds on Files. long lastModifiedSeconds = file.lastModified() / 1000; // always scan the file, so we can return the content://media Uri for existing files return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(), false, true, MediaScanner.isNoMediaPath(path)); } catch (RemoteException e) { Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e); return null; } }
Genau wie beim obigen Code wird geprüft, ob die Datei vorhanden ist. Wenn die Datei nicht vorhanden ist, wird die Abwärtsausführung direkt gestoppt. Das wird also nicht funktionieren. Was zu tun?
public void testDeleteFile() { String existingFilePath = "/mnt/sdcard/1390116362913_add.png"; File existingFile = new File(existingFilePath); existingFile.delete(); ContentResolver resolver = getActivity().getContentResolver(); resolver.delete(Images.Media.EXTERNAL_CONTENT_URI, Images.Media.DATA + "=?", new String[]{existingFilePath}); }
Der obige Code kann funktionieren, löschen Sie ihn einfach direkt vom MediaProvider. Spezifische Löschcodes finden Sie im Code-Snippet für Medien auf Android
One More Thing
Ausführlichere Erläuterungen zum Scannen von Multimediadateien in Android finden Sie auf der chinesischen PHP-Website für Verwandte Artikel!