Android 7.0 Nougat,如何从传入意图的URI获取文件路径?

6

文件提供者:设置文件共享

我知道在 Android Nougat 中更改了文件策略。 希望将文件共享给其他应用的应用程序通过 FileProvider 生成 URI。 URI 格式为 content://com.example.myapp.fileprovider/myimages/default_image.jpg

我想知道如何从由 FileProvider.getUriForFile() 生成的 URI 中获取文件路径。 因为我的应用程序需要知道物理文件路径才能保存、加载、读取信息等。 这是否可能?

[简而言之]

  1. 我的应用程序在 Android 7 Nougat 上收到其他应用程序的意图 URI。
  2. URI 格式为 content://com.example.myapp.fileprovider/myimages/default_image.jpg
  3. 也许是由 FileProvider.getUriForFile 生成的。
  4. 我想知道从 URI 获取文件路径的方法。
  5. 我只能使用 getContentResolver().openFileDescriptor() 获取 MIME 类型、显示名称、文件大小和二进制读取内容。 但我想知道文件路径。

1
如果您可以从流中进行二进制读取,那么您可以从流中读取。使用它。不需要文件路径。只有文件提供者应该能够告诉您文件路径,但它不会这样做。重新思考。重新设计。您不需要文件路径。 - greenapps
1
我的应用程序需要知道物理文件路径才能保存、加载、读取信息等。但是,通过使用ContentResolver和openInputStream(),您可以创建自己的副本。不仅您无法确定路径,即使您能够确定路径,也很可能无法访问该文件系统。 - CommonsWare
你找到解决方案了吗? - user25
3个回答

4
您无法获取Uri的“文件路径”,这是因为没有要求Uri指向文件。使用ContentResolver和像openInputStream()这样的方法来访问由Uri表示的内容。

要使用内容URI与另一个应用程序共享文件,您的应用程序必须生成内容URI。要生成内容URI,请为文件创建新文件,然后将文件传递给getUriForFile()。您可以将getUriForFile()返回的内容URI发送到意图中的另一个应用程序。接收内容URI的客户端应用程序可以通过调用ContentResolver.openFileDescriptor来打开文件并访问其内容以获取ParcelFileDescriptor。 来源:Android developers


1
要使用内容URI与另一个应用程序共享文件,您的应用程序必须实现FileProvider。 - greenapps
如果我想使用本地库播放视频文件(C++对内容URI一无所知,它需要绝对路径),该怎么办?我从某个资源管理器应用程序中选择一个视频文件,并尝试在我的视频播放器应用程序中打开它。 - user25

1
// 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();
}

以上方法适用于Android N。您将获得文件路径ContentResolver()并在Android Manifest文件中使用文件提供程序,同时使用读写外部存储权限。以上方法只需在OnActivityResult中调用,其中Data uri被获取,然后简单地调用String strPath=getFilePathForN(uri,this)。 - Satyawan Hajare
请在回答问题时,始终将其放在上下文中,而不仅仅是粘贴代码。有关更多详细信息,请参见此处 - gehbiszumeis

0

我在我们的应用程序中有类似的需求,之前感到困惑。我是这样解决的。

在Android N中,仅向第三方应用程序公开的文件URI已更改。(不是我们以前使用的方式)。

在我们的应用程序中,我们将uri发送到相机应用程序,在那个位置,我们期望相机应用程序存储捕获的图像。

  1. 对于Android N,我们基于URL生成新的Content:// uri指向文件。
  2. 我们为相同的内容生成通常的基于文件API的路径(使用旧方法)。

现在我们有了两个不同的URI,用于相同的文件。#1与相机应用程序共享。如果相机意图成功,则可以从#2访问图像。

希望这可以帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接