Get real path from URI of file in sdcard marshmallow

前端 未结 3 639
情深已故
情深已故 2020-12-01 17:33

I want to pick file that exist in sdcard not in internal storage and upload it server but I am not able to get its path for getting its size. I have start a

相关标签:
3条回答
  • 2020-12-01 17:45

    After spending time on Android Device Manager I have found solution, here it is:

    If doc type id is not primary then I create path using :

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

    EDIT1: in case of DocumentUri select contentUri on basis of file type

    Here is complete function:

    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();
                       for (File f : extenal) {
                        filePath = f.getAbsolutePath();
                        if (filePath.contains(type)) {
                            int endIndex = filePath.indexOf("Android");
                            filePath = filePath.substring(0, endIndex) + 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;
    }
    

    EDIT2 For handling host like content://com.adobe.scan.android.documents/document/ check code here

    0 讨论(0)
  • 2020-12-01 17:53

    Change your upload code. Somewhere you will have

    FileInputStream fis = new FileInputStream(path);
    

    Change to

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

    So use the uri directly. No need for a file path.

    0 讨论(0)
  • 2020-12-01 17:54

    ​It is quite easy to implement FileProvider on your application. First you need to add a FileProvider tag in AndroidManifest.xml under tag like below: 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>
    

    And then create a provider_paths.xml file in xml folder under res folder. Folder may be needed to create if it doesn't exist.

    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>
    

    Done! FileProvider is now declared and be ready to use.

    The final step is to change the line of code below in MainActivity.java

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

    And .... done ! Your application should now work perfectly fine on any Android version including Android Nougat. Yah !

    0 讨论(0)
提交回复
热议问题