簡體   English   中英

用於 Android 11+ 的可移動 micro-sd 卡上的文件的 ContentProvider

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

由於 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() 並從輸入流執行direct.read() 來為我自己的應用程序解決它。

這是我使用的提供商 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
}

在 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 卡上應用程序特定目錄中的文件。

顯然谷歌閱讀了我的帖子。

但什么也沒說;-)

問題已經解決了。

至少在我剛剛收到 Android 12 更新的設備上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM