it-swarm.com.de

Android: Abrufen einer Datei-URI von einer Inhalts-URI?

In meiner App muss der Benutzer eine Audiodatei auswählen, die die App dann verarbeitet. Das Problem ist, dass die URI im Dateiformat vorliegen muss, damit die App das tut, was ich von ihr möchte. Wenn ich den nativen Musik-Player von Android verwende, um in der App nach der Audiodatei zu suchen, ist der URI ein Inhalts-URI, der folgendermaßen aussieht:

content://media/external/audio/media/710

Unter Verwendung der beliebten Datei-Manager-Anwendung Astro erhalte ich jedoch Folgendes:

file:///sdcard/media/audio/ringtones/GetupGetOut.mp3

Letzteres ist für mich viel zugänglicher, aber ich möchte natürlich, dass die App mit der Audiodatei funktioniert, die der Benutzer auswählt, unabhängig davon, mit welchem ​​Programm er seine Sammlung durchsucht. Also meine Frage ist, gibt es eine Möglichkeit, die content:// style URI in einen file:// URI? Ansonsten, was würden Sie mir empfehlen, um dieses Problem zu lösen? Hier ist der Code, der die Auswahl als Referenz aufruft:

Intent ringIntent = new Intent();
ringIntent.setType("audio/mp3");
ringIntent.setAction(Intent.ACTION_GET_CONTENT);
ringIntent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(ringIntent, "Select Ringtone"), SELECT_RINGTONE);

Ich mache folgendes mit der Inhalts-URI:

m_ringerPath = m_ringtoneUri.getPath();
File file = new File(m_ringerPath);

Dann mache ein paar FileInputStream-Sachen mit dieser Datei.

105
JMRboosties

Verwenden Sie einfach getContentResolver().openInputStream(uri), um InputStream von einer URI abzurufen.

http://developer.Android.com/reference/Android/content/ContentResolver.html#openInputStream (Android.net.Uri)

132
Jason LeBrun

Sie können den Content Resolver verwenden, um ein file:// Pfad vom content:// URI:

String filePath = null;
Uri _uri = data.getData();
Log.d("","URI = "+ _uri);                                       
if (_uri != null && "content".equals(_uri.getScheme())) {
    Cursor cursor = this.getContentResolver().query(_uri, new String[] { Android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null);
    cursor.moveToFirst();   
    filePath = cursor.getString(0);
    cursor.close();
} else {
    filePath = _uri.getPath();
}
Log.d("","Chosen path = "+ filePath);
40
Rafael Nobre

Wenn Sie einen Inhalts-Uri mit content://com.externalstorage... Haben, können Sie diese Methode verwenden, um den absoluten Pfad eines Ordners oder einer Datei abzurufen on Android 19 oder höher.

public static String getPath(final Context context, final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat;

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        System.out.println("getPath() uri: " + uri.toString());
        System.out.println("getPath() uri authority: " + uri.getAuthority());
        System.out.println("getPath() uri path: " + uri.getPath());

        // ExternalStorageProvider
        if ("com.Android.externalstorage.documents".equals(uri.getAuthority())) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);

            // This is for checking Main Memory
            if ("primary".equalsIgnoreCase(type)) {
                if (split.length > 1) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1] + "/";
                } else {
                    return Environment.getExternalStorageDirectory() + "/";
                }
                // This is for checking SD Card
            } else {
                return "storage" + "/" + docId.replace(":", "/");
            }

        }
    }
    return null;
}

Sie können überprüfen, ob jeder Teil von Uri println verwendet. Die zurückgegebenen Werte für meine SD-Karte und den Hauptspeicher des Geräts sind unten aufgeführt. Sie können zugreifen und löschen, wenn sich die Datei im Speicher befindet, aber ich konnte Datei von SD-Karte löschen mit dieser Methode nur das Bild lesen oder öffnen, das diesen absoluten Pfad verwendet. Wenn Sie eine Lösung zum Löschen mit dieser Methode gefunden haben, teilen Sie uns dies bitte mit. SD-KARTE

getPath() uri: content://com.Android.externalstorage.documents/tree/612E-B7BF%3A/document/612E-B7BF%3A
getPath() uri authority: com.Android.externalstorage.documents
getPath() uri path: /tree/612E-B7BF:/document/612E-B7BF:
getPath() docId: 612E-B7BF:, split: 1, type: 612E-B7BF

HAUPTERINNERUNG

getPath() uri: content://com.Android.externalstorage.documents/tree/primary%3A/document/primary%3A
getPath() uri authority: com.Android.externalstorage.documents
getPath() uri path: /tree/primary:/document/primary:
getPath() docId: primary:, split: 1, type: primary

Wenn Sie Uri mit file:/// Erhalten möchten, nachdem Sie den Pfad erhalten haben, verwenden Sie

DocumentFile documentFile = DocumentFile.fromFile(new File(path));
documentFile.getUri() // will return a Uri with file Uri
6
Thracian

Der Versuch, den URI mit dem Schema content: // durch Aufrufen von ContentResolver.query() zu behandeln, ist keine gute Lösung. Auf dem HTC Desire, auf dem 4.2.2 ausgeführt wird, könnte NULL als Abfrageergebnis angezeigt werden.

Warum nicht stattdessen ContentResolver verwenden? https://stackoverflow.com/a/29141800/3205334

6
Darth Raven

Nun, ich bin etwas spät dran zu antworten, aber mein Code ist getestet

überprüfe Schema von uri:

 byte[] videoBytes;

if (uri.getScheme().equals("content")){
        InputStream iStream =   context.getContentResolver().openInputStream(uri);
            videoBytes = getBytes(iStream);
        }else{
            File file = new File(uri.getPath());
            FileInputStream fileInputStream = new FileInputStream(file);     
            videoBytes = getBytes(fileInputStream);
        }

In der obigen Antwort habe ich das Video-URI in ein Byte-Array konvertiert, aber das hat nichts mit Frage zu tun. Ich habe nur meinen vollständigen Code kopiert, um die Verwendung von FileInputStream und InputStream zu zeigen, da beide gleich funktionieren mein Code.

Ich habe den variablen Kontext getActivity () in meinem Fragment verwendet und in Activity ist es einfach ActivityName.this

context=getActivity(); // in Fragment

context=ActivityName.this; // in Aktivität

3
Umar Ata