Obtenir le chemin réel à partir de L'URI du fichier dans sdcard marshmallow

je veux choisir le fichier qui existe dans sdcard pas dans le stockage interne et télécharger le serveur mais je ne suis pas en mesure d'obtenir son chemin pour obtenir sa taille. J'ai lancé une intention pour choisir un fichier en utilisant le code ci-dessous:

 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);

pour obtenir le chemin de dossier j'utilise cette réponse et son fonctionnement à moins que l'utilisateur ne sélectionne n'importe quel dossier de sdcard(amovible). Quand je debug le code et ai trouvé que type est pas primaire de sorte qu'il ne va pas à l'intérieur de cette condition:

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

ma question est donc: qu'est-ce que ce sera d'autre? c'est à dire que si le type n'est pas première? comment obtenir le chemin à suivre dans cette affaire? j'ai cherché beaucoup de questions et tutoriel il n'y en a pas d'autre dans aucun d'eux. J'ai également essayé autre partie de cette réponse mais son ne fonctionne pas parce que System.getenv() retour null pour " SECONDARY_STORAGE " et sdcard pour " EXTERNAL_STORAGE ". J'obtiens un fichier non trouvé exception lorsque j'essaie:

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

Uri et doc Id de fichier ressembler à:

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

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

de l'aide ??

5
demandé sur Community 2017-02-08 13:41:23

3 réponses

après avoir passé du temps sur Android Device Manager, j'ai trouvé la solution, voici:

si l'id de type doc n'est pas primaire alors je crée le chemin en utilisant:

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

modifier: dans le cas de DocumentUri sélectionner contentUri sur la base du type de fichier

Voici la fonction complète:

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;
}
8
répondu Jaiprakash Soni 2018-01-10 06:10:02

changez votre code de téléchargement. Quelque part vous aurez

FileInputStream fis = new FileInputStream(path);

changer à

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

utilisez donc l'uri directement. Pas besoin d'un chemin d'accès au fichier.

3
répondu greenapps 2017-02-08 11:27:17

il est assez facile d'implémenter FileProvider sur votre application. Tout d'abord, vous devez ajouter une étiquette FileProvider dans AndroidManifest.xml sous la balise comme ci-dessous: 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>

et ensuite créer un provider_paths.fichier xml dans le dossier xml sous le dossier res. Dossier peut être nécessaire pour créer si elle n'existe pas.

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>

fait! FileProvider est maintenant déclaré et être prêt utiliser.

la dernière étape consiste à modifier la ligne de code ci-dessous dans MainActivity.java

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



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

et.... fait ! Votre application doit maintenant fonctionner parfaitement sur N'importe quelle version Android y compris Nougat Android. Yah !

-1
répondu g7pro 2017-02-08 11:10:12