Heim  >  Artikel  >  Java  >  Ausführliche Erklärung zum Scannen von Multimediadateien in Android

Ausführliche Erklärung zum Scannen von Multimediadateien in Android

高洛峰
高洛峰Original
2017-01-16 17:26:201595Durchsuche

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&#39;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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn