简体   繁体   English

用于 Android 11+ 的可移动 micro-sd 卡上的文件的 ContentProvider

[英]ContentProvider for files on removable micro-sd card for Android 11+

As FileProvider cannot serve from micro-sd card one has to make its own extending ContentProvider.由于 FileProvider 无法从 micro-sd 卡提供服务,因此必须制作自己的扩展 ContentProvider。

So i did time ago.所以我前段时间做过。 And was working fine for all Android versions below 11.并且适用于所有低于 11 的 Android 版本。

It can serve files from the whole device including micro sd card.它可以提供来自整个设备的文件,包括 micro sd 卡。

So also from private getExternalFilesDirs()[0] and getExternalFilesDirs()[1].同样来自私有 getExternalFilesDirs()[0] 和 getExternalFilesDirs()[1]。

Now see these two paths both on same micro-sd:现在在同一个 micro-sd 上看到这两条路径:

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

They could be served.他们可以服务。

But on an Android 11+ devices HTMLViewer and Chrome can only handle the first path.但是在 Android 11+ 设备上,HTMLViewer 和 Chrome 只能处理第一个路径。 The app itself can always handle its own files using path or own provider.应用程序本身始终可以使用路径或自己的提供程序处理自己的文件。

On Android 11+ own apps that were choosen with ACTON_VIEW and used.readLine() to read from uri could handle first path and failed for second path.在 Android 11+ 上,使用 ACTON_VIEW 选择并使用.readLine() 从 uri 读取的应用程序可以处理第一个路径,而第二个路径失败。 I could finally solve it for my own apps by not using.readLine() but looking at.available() and doing a direct.read() from inputstream.我终于可以通过不使用.readLine() 而是查看.available() 并从输入流执行direct.read() 来为我自己的应用程序解决它。

This is the provider class i use:这是我使用的提供商 class:

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
}

In AndroidManifest.xml:在 AndroidManifest.xml 中:

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

Use following uries for an ACTIEN_VIEW intent.对 ACTIEN_VIEW 意图使用以下 uri。 (Change 1234-5678 accordingly to used micro sd card) (将 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");

Test the uries in the providing app first.首先在提供的应用程序中测试 uris。

Following intent is used to start an external app.以下意图用于启动外部应用程序。

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

My question is: Why, on Android 11 and 12, is ContentProvider for files on a micro sd card acting different for files from different locations?我的问题是:为什么在 Android 11 和 12 上,用于 micro sd 卡上的文件的 ContentProvider 对来自不同位置的文件的作用不同?

I could solve the read problem for.txt files but if my external app wants to save edits it fails.我可以解决.txt 文件的读取问题,但如果我的外部应用程序想要保存编辑,它会失败。

Update (Nov 5):更新(11 月 5 日):

Following only with MANAGE_EXTERNAL_STORAGE.仅使用 MANAGE_EXTERNAL_STORAGE。 The idea came to mind that files deep in the directory tree would suffer from this behavior.想到目录树深处的文件会受到这种行为的影响。 So i copied所以我复制了

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

to

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

No problems with the latter for viewing and editing by external app.后者通过外部应用程序查看和编辑没有问题。 The problem is only for files in app specific directory on micro sd card.问题仅适用于 micro sd 卡上应用程序特定目录中的文件。

Apparenyly Google read my post.显然谷歌阅读了我的帖子。

But said nothing;-)但什么也没说;-)

The problem is solved.问题已经解决了。

At least on my device that just received the Android 12 update.至少在我刚刚收到 Android 12 更新的设备上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM