API 29 Доступ к медиастору

Мое приложение создает списки воспроизведения в медиа-магазине Android. Все хорошо для API, включая 28, однако API 29, похоже, требует дополнительных разрешений. Вставка нового имени и идентификатора плейлиста работает без проблем. Когда дело доходит до вставки идентификатора дорожки и порядка воспроизведения, возникает исключение разрешения на доступ. При проверке Uri я обнаружил, что когда resolver.insert для API 29, ошибка исключения:

java.lang.SecurityException: myapp_name has no access to content://media/external_primary/audio/media/146

Код:

Uri exturi = MediaStore.Audio.Playlists.Members.getContentUri("external", playlist_id);
// exturi : content://media/external/audio/playlists/227/members

// values : audio_id=146 play_order=0
values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, play_order);
values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audio_id);

try {
    resolver.insert(exturi, values);
} catch (Exception e) {
    e.printStackTrace();
}

Странно то, что вставка нового списка воспроизведения в Mediastore работает, но добавление дорожек (track_id, порядок воспроизведения) выдает ошибку разрешения доступа

Как устранить эту ошибку исключения для API 29?

Обновление от февраля 2021 г.: небольшой шаг вперед, я почти уверен, что мне нужно получить Documenturi для исходного uri, но все равно выдает ошибку доступа. Таким образом, проблема заключается не в доступе к дорожкам, а в самом uri.

doc_uri = MediaStore.getDocumentUri(context,playlist_members_uri);
java.lang.SecurityException: com.flyingdutchman.newplaylistmanager has no access to content://media/external/audio/playlists/130/members

person Theo    schedule 07.08.2019    source источник
comment
не используйте только внешний жестко закодированный, используйте основной внешний том.   -  person greywolf82    schedule 07.08.2019
comment
developer.android.com/training/data-storage/shared/media Попробуйте использовать MediaStore.VOLUME_EXTERNAL_PRIMARY (в API ‹= 28 вместо этого используйте VOLUME_EXTERNAL)   -  person Khoa Nguyễn    schedule 09.01.2020
comment
@Khoa Nguyễn пробовал это безрезультатно   -  person Theo    schedule 09.01.2020
comment
@ Тео Удачи? В вашем телефоне есть SD-карта? (У меня есть отчеты об этом, но я не могу воспроизвести)   -  person now    schedule 13.01.2020
comment
У меня такая же проблема. Я могу удалить треки из плейлиста, но при добавлении получаю такое же исключение на API 29. Вы уже нашли решение? Буду очень рад помощи в этом.   -  person morja    schedule 14.01.2020
comment
Это происходит и со мной при создании нового плейлиста. Плейлист создается, хотя!   -  person Prince Ali    schedule 12.07.2020
comment
Привет @morja, у меня точно такая же проблема. Вы нашли решение? Я могу удалить песни, но когда я пытаюсь добавить, я получаю SecurityException. Спасибо!   -  person EvanBlack    schedule 10.01.2021
comment
@EvanBlack Привет. На данный момент я делаю обходной путь с плейлистами m3u на основе файлов. Система сканирует их и создает списки воспроизведения. Недостатком мэра является то, что идентификаторы меняются каждый раз при воссоздании плейлистов. Таким образом, некоторые приложения, использующие плейлисты, необходимо обновлять каждый раз, когда они меняются.   -  person morja    schedule 11.01.2021


Ответы (6)


Я думаю, что это ошибка Android 10, поэтому я подал отчет здесь: https://issuetracker.google.com/issues/147619577 (содержит инструкции для тестового примера эмулятора, чтобы воспроизвести его, если это вас интересует). Пожалуйста, подумайте о том, чтобы отметить его, чтобы команда Android знала, что это влияет на вас.

Насколько я могу судить, это влияет только на файлы во «внешнем» хранилище, например, на SD-карты, смонтированные на /storage/XXXX-XXXX.

Тем временем, единственное исправление, которое некоторые из моих пользователей смогли успешно применить, — это переместить свои музыкальные файлы во внутреннюю память (перезагрузите компьютер и дождитесь завершения сканирования носителя, чтобы убедиться, что MediaStore обновлен).

person now    schedule 14.01.2020
comment
Спасибо попробую музыку на внутренней памяти - person Theo; 14.01.2020
comment
Android 10 представляет новую концепцию хранилища: Хранилище с заданной областью. Если вам не нравится хранилище с заданной областью, добавьте этот флаг в свой файл манифеста (но это не рекомендуется, поскольку это будет обязательным в следующем выпуске). Android): ‹application android:requestLegacyExternalStorage=true›‹/application› - person toumir; 28.01.2020
comment
@toumir Ошибка также затрагивает приложения, ориентированные на API 28 или использующие requestLegacyExternalStorage=true, так что это не помогает. - person now; 28.01.2020
comment
@now не ошибка, но это поведение влияет на приложения, ориентированные на API 29 или +, API 28 и ниже у меня работает нормально. - person toumir; 29.01.2020
comment
Мне было бы любопытно увидеть это. Не могли бы вы поделиться проектом, который работает? - person now; 30.01.2020
comment
На уровне API 29 пользователь должен разрешить любые действия в отношении файлов, созданных другими приложениями. developer.android.com/training/data-storage/shared/media - person laim2003; 20.11.2020

в моих дальнейших поисках ответа я наткнулся на это;

Все о базе данных мультимедиа (Mediastore ) с Android 11

person Theo    schedule 16.03.2021

  1. Создайте список воспроизведения с uri MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI и строкой даты в external.db для списка воспроизведения:
_id _display_name volume_name
308 New playlist.m3u external_primary

Имя тома списка воспроизведения — external_primary.

2.

  • Музыкальный файл находится на флешке
  • Идентификатор музыкального файла во external.db — 278.
  • Имя тома флэш-карты: 1EDD-DDE0

При добавлении этого музыкального файла в плейлист появилось следующее исключение:
Сообщение об исключении: java.lang.SecurityException: нет доступа к контенту://media/external_primary/audio/media/278

Если я создам плейлист с uri MediaStore.Audio.Playlists.getContentUri("1edd-dde0"), то музыка будет успешно добавлена ​​в плейлист.

Судя по всему, причина в несоответствии имени тома в плейлисте и добавляемом музыкальном файле. Только когда имя тома списка воспроизведения совпадает с именем музыкального файла, операция вставки может быть завершена.

person wanted    schedule 08.04.2021
comment
Я применил предложение, но .... Uri uri_to_use = MediaStore.Audio.Playlists.getContentUri(0F16-2701); -дает: content://media/0F16-2701/audio/playlists и приводит к java.lang.IllegalArgumentException: том 0F16-2701 не найден - person Theo; 09.04.2021
comment
Я имею в виду, что вы должны сделать плейлист на той же громкости, что и песня, которую вы хотите добавить. В вашем случае вы должны создать свой список воспроизведения на 0F16-2701, затем вы можете добавить в список воспроизведения песни, расположенные на 0F16-2701. - person wanted; 14.04.2021
comment
Я ценю ваш интерес. Я думаю, что сделал так, как вы предложили, как показано в моем примере uri_to_use. Чего я не понимаю, так это того, зачем вам вообще нужно имя тома, поскольку список воспроизведения Android — это просто запись с entry_id и именем в таблице файлов с media_type = 4. Я начал с чистого эмулятора, создал 1 плейлист для Android, проверил базу данных. Результат 1 запись в файлах, но к детали _DATA добавлен .m3u, а в папке «Музыка» есть пустой файл .m3u. Если вы заставили это работать, возможно, у вас есть рабочий пример? - person Theo; 15.04.2021

Обновление для андроид 11. Стоит отметить, что база данных мультимедиа переехала из

/data/data/com.android.providers.media

to

/data/data/com.google.android.providers.media.module

также в структурах произошли существенные изменения

до Android 10/11 и android 11

person Theo    schedule 23.03.2021
comment
Я пробовал все, и это все равно не будет работать выше API 28. Я сдался и просто создал свою собственную базу данных, используя комнату с плейлистом и таблицей песен. ScopedStorage все испортил. - person Vince VD; 26.03.2021

Я внедрил SAF, поэтому не используйте scopedStorage и получите доступ, как только пользователь примет его. Тот факт, что я могу вставлять новые записи в список воспроизведения, ясно показывает доступ к MediaStore, я также могу их удалить. Однако попытка добавить треки в эти плейлисты не работает для api29. Вставка/удаление нового списка воспроизведения не включает файлы, расположенные на внутренних или внешних SD-картах, поскольку это просто добавление значений.

разрешения как для внутренней, так и для внешней SD-карты:

2020-07-12 14:39:04.435 11858-11858/com.flyingdutchman.newplaylistmanager E/onCreate:: uriPermission: UriPermission {uri=content://com.android.externalstorage.documents/tree/17F5-240A%3A, modeFlags=3, persistedTime=1594551961263}
2020-07-12 14:39:04.435 11858-11858/com.flyingdutchman.newplaylistmanager E/onCreate:: uriPermission: UriPermission {uri=content://com.android.externalstorage.documents/tree/primary%3A, modeFlags=3, persistedTime=1594551926876}

Теперь вопрос становится

Как убедиться, что разрешения saf распознаются методом resolver.insert при вставке/изменении дорожек в базу данных мультимедиа

person Theo    schedule 18.02.2020
comment
У меня также реализован SAF, но когда я вызываю обновление для ContentResolver, например. contentResolver.update(mediaFileUri, values, null, null); он по-прежнему выдает RecoverableSecurityException вы нашли способ, чтобы нам не нужно было перехватывать это исключение и запрашивать разрешение для каждого файла отдельно? Это то, что я делаю прямо сейчас, но я действительно ненавижу это, и это настоящая проблема. - person Vince VD; 27.05.2020
comment
@Vince VD, не дальше вперед. Невероятно, что никто не создает списки воспроизведения в Android 10. Тем временем android11 ​​не за горами, и многие вещи устаревают. Заманчиво просто сдаться - person Theo; 27.05.2020
comment
Создание списков воспроизведения, кажется, работает во многих приложениях mp3-плееров в Play Store, но я заметил, что они не вставляют новый список воспроизведения в MediaStore. Так что я думаю, что они управляют своей собственной базой данных со списками воспроизведения, и похоже, что это наш единственный вариант прямо сейчас. - person Vince VD; 31.05.2020

Обновление май 2020 г.

Пошаговое выполнение кода преобразователя с помощью отладки F7

Сценарий 1 приводит к ошибке разрешения (неверный MediaStore.VOLUME_EXTERNAL).

 playlist_uri = MediaStore.Audio.Playlists.getContentUri(MediaStore.VOLUME_EXTERNAL);
 playlist_members_uri  = MediaStore.Audio.Playlists.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
                    .buildUpon()
                    .appendEncodedPath(Long.toString(playlist_id))
                    .appendEncodedPath("members")
                    .build();

AcquireProvider(mContext, авторизация); = СМИ

Uri createdRow = provider.insert(mPackageName, mAttributionTag, url, values, extras); = ноль

mPackageName=com.flyingdutchman.newplaylistmanager

mAttributionTag = ноль

значения[0] = 206 значений[1]=69 значений[2]=1

экстра = ноль

База данныхUtils.java

   public static final void readExceptionFromParcel(Parcel reply) {
        int code = reply.readExceptionCode();
        if (code == 0) return;
        String msg = reply.readString();
        DatabaseUtils.readExceptionFromParcel(reply, msg, code);
    }

msg = com.flyingdutchman.newplaylistmanager не имеет доступа к контенту://media/external_primary/audio/playlists/206

Сценарий 2 приводит к НЕТ ошибке разрешения, НО треки не добавляются в таблицу audio_playlists_map.

 playlist_uri = MediaStore.Audio.Playlists.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
url=content://media/external_primary/audio/playlists/206/members
person Theo    schedule 12.05.2021