Android 7 nougat, how to get the file path from uri of incoming intent?

£可爱£侵袭症+ 提交于 2019-12-03 16:06:51

You cannot get a "file path" for a Uri, for the simple reason that there is no requirement that a Uri point to a file. Use ContentResolver and methods like openInputStream() to access the content represented by the Uri.

To share a file with another app using a content URI, your app has to generate the content URI. To generate the content URI, create a new File for the file, then pass the File to getUriForFile(). You can send the content URI returned by getUriForFile() to another app in an Intent. The client app that receives the content URI can open the file and access its contents by calling ContentResolver.openFileDescriptor to get a ParcelFileDescriptor. Source: Android developers

// Use Below Method Working fine for Android N.
private static String getFilePathForN(Uri uri, Context context) {
    Uri returnUri = uri;
    Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
    /*
     * Get the column indexes of the data in the Cursor,
     *     * move to the first row in the Cursor, get the data,
     *     * and display it.
     * */
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
    returnCursor.moveToFirst();
    String name = (returnCursor.getString(nameIndex));
    String size = (Long.toString(returnCursor.getLong(sizeIndex)));
    File file = new File(context.getFilesDir(), name);
    try {
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        FileOutputStream outputStream = new FileOutputStream(file);
        int read = 0;
        int maxBufferSize = 1 * 1024 * 1024;
        int bytesAvailable = inputStream.available();

        //int bufferSize = 1024;
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);

        final byte[] buffers = new byte[bufferSize];
        while ((read = inputStream.read(buffers)) != -1) {
            outputStream.write(buffers, 0, read);
        }
        Log.e("File Size", "Size " + file.length());
        inputStream.close();
        outputStream.close();
        Log.e("File Path", "Path " + file.getPath());

    } catch (Exception e) {
        Log.e("Exception", e.getMessage());
    }
    return file.getPath();
}

I had the similar requirement in our app and got confused earlier. I solved this way.

In Android N, only the file uri exposed to 3rd party app is changed. (Not the way we were using it before).

In our app we were sending uri to Camera app, in that location we are expecting the camera app to store the captured image.

  1. For android N, we generate new Content:// uri based url pointing to file.
  2. We generate usual File api based path for the same (using older method).

Now we have 2 different uri for same file. #1 is shared with Camera app. If the camera intent is success, we can access the image from #2.

Hope this helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!