wake-up-neo.net

Holen Sie sich den realen Pfad von der URI der Datei in sdcard Marshmallow

Ich möchte eine Datei auswählen, die in sdcard nicht im internen Speicher vorhanden ist, und den Server hochladen, aber ich kann den Pfad für dessen Größe nicht abrufen. Ich habe eine Absicht für die Auswahl einer Datei mit folgendem Code gestartet:

 intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
 intent.addCategory(Intent.CATEGORY_OPENABLE);
 intent.setType("*/*");
 String[] mimetypes = {"application/*"};
 intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
 startActivityForResult(
      Intent.createChooser(intent, "Select a File to Upload"), FILE_SELECT_CODE);

Um den Pfad zur Datei zu erhalten, verwende ich diese Antwort und ihre Funktion, es sei denn, der Benutzer wählt eine Datei aus der SD-Karte (entfernbar) aus. Wenn ich den Code debugge und herausgefunden habe, dass type nicht primary ist, geht es nicht in diese Bedingung:

if("primary".equalsIgnoreCase(type)){
     return Environment.getExternalStorageDirectory() + "/" + split[1];
} 

Meine Frage ist also, was wird es sonst sein? Was ist, wenn der Typ nicht primär ist? Wie können wir in diesem Fall den Pfad zur Datei erhalten? Ich habe viele Fragen und Anleitungen gesucht, in keinem davon ist etwas anderes. Ich habe auch einen anderen Teil von diese Antwort ausprobiert - aber es funktioniert nicht, weil System.getenv() return null für " SECONDARY_STORAGE " und sdcard für " EXTERNAL_STORAGE ". Ich bekomme keine Ausnahme, wenn ich versuche:

if ("primary".equalsIgnoreCase(type)) {
    return Environment.getExternalStorageDirectory() + "/" + split[1];
}else{
    return System.getenv("EXTERNAL_STORAGE") + "/" + split[1];
}

Uri und Dokument ID für Datei sehen so aus: 

Uri : content: //com.Android.externalstorage.documents/document/0EF9-3110%3Adevice-2016-12-02-130553.png

docId : 0EF9-3110: device-2016-12-02-130553.png

Irgendeine Hilfe ??

6
Jaiprakash Soni

Nachdem ich einige Zeit mit dem Android Device Manager verbracht habe, habe ich eine Lösung gefunden, hier ist es:

Wenn die Dokumenttyp-ID nicht primär ist, erstelle ich den Pfad mit:

filePath = "/storage/" + type + "/" + split[1];

EDIT: Bei DocumentUri wählen Sie contentUri anhand des Dateityps aus

Hier ist vollständige Funktion:

public static String getRealPathFromURI_API19(Context context, Uri uri) {
    String filePath = "";

    // ExternalStorageProvider
    if (isExternalStorageDocument(uri)) {
        final String docId = DocumentsContract.getDocumentId(uri);
        final String[] split = docId.split(":");
        final String type = split[0];

        if ("primary".equalsIgnoreCase(type)) {
            return Environment.getExternalStorageDirectory() + "/" + split[1];
        } else {

            if (Build.VERSION.SDK_INT > 20) {
                    //getExternalMediaDirs() added in API 21
                    File extenal[] = context.getExternalMediaDirs();
                    if (extenal.length > 1) {
                        filePath = extenal[1].getAbsolutePath();
                        filePath = filePath.substring(0, filePath.indexOf("Android")) + split[1];
                    }
             }else{
                    filePath = "/storage/" + type + "/" + split[1];
             }
            return filePath;
        }

    } else if (isDownloadsDocument(uri)) {
        // DownloadsProvider
        final String id = DocumentsContract.getDocumentId(uri);
        //final Uri contentUri = ContentUris.withAppendedId(
        // Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                String result = cursor.getString(index);
                cursor.close();
                return result;
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
    } else if (DocumentsContract.isDocumentUri(context, uri)) {
        // MediaProvider
        String wholeID = DocumentsContract.getDocumentId(uri);

        // Split at colon, use second item in the array
        String[] ids = wholeID.split(":");
        String id;
        String type;
        if (ids.length > 1) {
            id = ids[1];
            type = ids[0];
        } else {
            id = ids[0];
            type = ids[0];
        }

        Uri contentUri = null;
        if ("image".equals(type)) {
            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        } else if ("video".equals(type)) {
            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        } else if ("audio".equals(type)) {
            contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        }

        final String selection = "_id=?";
        final String[] selectionArgs = new String[]{id};
        final String column = "_data";
        final String[] projection = {column};
        Cursor cursor = context.getContentResolver().query(contentUri, 
            projection, selection, selectionArgs, null);

        if (cursor != null) {
            int columnIndex = cursor.getColumnIndex(column);

            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
            }
            cursor.close();
        }
        return filePath;
    } else {
        String[] proj = {MediaStore.Audio.Media.DATA};
        Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
        if (cursor != null) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
            if (cursor.moveToFirst())
                filePath = cursor.getString(column_index);
            cursor.close();
        }


        return filePath;
    }
    return null;
}
9
Jaiprakash Soni

Ändern Sie Ihren Upload-Code. Irgendwo wirst du haben

FileInputStream fis = new FileInputStream(path);

Ändern

InputStream is = getContentResolver().openInputStream(uri);

Verwenden Sie den URI also direkt. Kein Dateipfad erforderlich.

3
greenapps

Es ist ziemlich einfach, FileProvider in Ihrer Anwendung zu implementieren. Zuerst müssen Sie ein FileProvider-Tag in AndroidManifest.xml unter folgendem Tag hinzufügen: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    ...
    <application
        ...
        <provider
            Android:name="Android.support.v4.content.FileProvider"
            Android:authorities="${applicationId}.provider"
            Android:exported="false"
            Android:grantUriPermissions="true">
            <meta-data
                Android:name="Android.support.FILE_PROVIDER_PATHS"
                Android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>

Erstellen Sie dann eine Datei provider_paths.xml im Ordner xml unter dem Ordner res. Möglicherweise wird ein Ordner zum Erstellen benötigt, wenn er nicht vorhanden ist.

res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path name="external_files" path="."/>
</paths>

Erledigt! FileProvider ist jetzt deklariert und einsatzbereit.

Der letzte Schritt besteht darin, die folgende Codezeile in MainActivity.Java zu ändern

Uri photoURI = Uri.fromFile(createImageFile());
to



 Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
            BuildConfig.APPLICATION_ID + ".provider",
            createImageFile());

Und fertig ! Ihre Anwendung sollte jetzt auf jeder Android-Version, einschließlich Android Nougat, einwandfrei funktionieren. Yah!

0
g7pro