0

由于 FileProvider 无法从 micro-sd 卡提供服务,因此必须制作自己的扩展 ContentProvider。

所以我前段时间做过。并且适用于 11 以下的所有 Android 版本。

它可以提供来自整个设备的文件,包括 micro sd 卡。

同样来自私有 getExternalFilesDirs()[0] 和 getExternalFilesDirs()[1]。

现在在同一个 micro-sd 上看到这两条路径:

/storage/1234-5678/Documents/mytext.txt
/storage/1234-5678/Android/data/<package>/files/mytext.txt

他们可以服务。

但在 Android 11+ 设备上,HTMLViewer 和 Chrome 只能处理第一条路径。应用程序本身始终可以使用路径或自己的提供程序处理自己的文件。

在 Android 11+ 上,使用 ACTON_VIEW 选择并使用 .readLine() 从 uri 读取的应用程序可以处理第一个路径,而第二个路径失败。我终于可以通过不使用 .readLine() 而是查看 .available() 并从输入流直接执行 .read() 来为我自己的应用程序解决它。

这是我使用的提供者类:

public class ABCContentProvider extends ContentProvider {
String TAG = "abccontentprovider";

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException
{
    Log.d(TAG, "open-File() mode: " + mode );  // "r" | "w"
    Log.d(TAG, "open-File() uri.getEncodedPath(): " + uri.getEncodedPath() );

    String path = uri.getEncodedPath();

    File f = new File(path);

    if ( ! f.exists() )
    {
        Log.d(TAG, "path does not exist" );
        throw new FileNotFoundException(
                "in ABCProvider\n"
                        + path
                        + "\nmode: " + mode
        );
    }

    if ( mode.equals("r") )
        return (ParcelFileDescriptor.open(f,ParcelFileDescriptor.MODE_READ_ONLY));

    return (ParcelFileDescriptor.open(f,ParcelFileDescriptor.MODE_READ_WRITE));
}

// Omitted all other methods as they are not used.
// Android Studio will add them for you
}

在 AndroidManifest.xml 中:

    <provider
        android:name=".ABCContentProvider"
        android:authorities="aaa.bbb.ccc.provider"
        android:enabled="true"
        android:exported="true" />

对 ACTIEN_VIEW 意图使用以下 uri。(将 1234-5678 相应地更改为使用的 micro sd 卡)

Uri uri1 = Uri.parse("content://aaa.bbb.ccc.provider/storage/1234-5678/Documents/mytext.txt");
Uri uri2 = Uri.parse("content://aaa.bbb.ccc.provider/storage/1234-5678/Android/data/<package>/files/mytext.txt");

首先在提供的应用程序中测试 uris。

以下意图用于启动外部应用程序。

 Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.setDataAndType(uri, "text/plain");
 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 startActivity(intent);

我的问题是:为什么在 Android 11 和 12 上,用于 micro sd 卡上的文件的 ContentProvider 对来自不同位置的文件的作用不同?

我可以解决 .txt 文件的读取问题,但如果我的外部应用程序想要保存编辑,它会失败。

更新(11 月 5 日):

仅使用 MANAGE_EXTERNAL_STORAGE。想到目录树深处的文件会受到这种行为的影响。所以我复制了

/storage/1234-5678/Android/data/<package>/files/mytext.txt

/storage/1234-5678/Endroid/data/<package>/files/mytext.txt

后者通过外部应用程序查看和编辑没有问题。问题仅适用于 micro sd 卡上应用程序特定目录中的文件。

4

0 回答 0