Поставщик содержимого для файлов на съемной карте micro-sd для Android 11

#android #android-contentprovider #android-11 #fileprovider

Вопрос:

Поскольку файлообменник не может работать с карты micro-sd, необходимо создать свой собственный расширяющий контент-провайдер.

Так я и сделал некоторое время назад. И отлично работал для всех версий Android ниже 11.

Он может обслуживать файлы со всего устройства, включая карту 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() из inputstream.

Это класс провайдера, который я использую:

 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 ABCProvidern"
                          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:

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

Use following uries for an ACTIEN_VIEW intent. (Change 1234-5678 accordingly to used micro sd card)

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

Сначала проверьте uries в приложении для предоставления.

Следующее намерение используется для запуска внешнего приложения.

  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 действует по-разному для файлов из разных мест?

Я мог бы решить проблему чтения файлов .txt, но если мое внешнее приложение хочет сохранить изменения, это не удается.

Обновление (5 ноября):

Следуйте только с помощью MANAGE_EXTERNAL_STORAGE. В голову пришла идея, что файлы в глубине дерева каталогов будут страдать от такого поведения. Поэтому я скопировал

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

Для

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

С последним нет проблем для просмотра и редактирования внешним приложением.
Проблема возникает только для файлов в каталоге приложения на карте micro sd.

Комментарии:

1. Android 11 сделал так, что все файлы в разделе /Android/Данные недоступны. Они не могут быть общими и доступны только для приложений, которые обращаются к своим собственным каталогам, поэтому они ведут себя по-другому. Короче говоря, вы больше не можете обмениваться файлами в /android/data/*.

2. @Dan Baruch, это очень коротко, так как я могу идеально обмениваться всеми файлами с основного Android/данными, когда файлы принадлежат моему приложению. И обмен данными со съемного Android/данных происходит таким же образом. Только есть одна причуда, которую я описал. Пожалуйста, прочтите еще раз. .. i can share any file the app can read itself ..