Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android R migration #336

Closed
courville opened this issue Apr 26, 2020 · 33 comments
Closed

Android R migration #336

courville opened this issue Apr 26, 2020 · 33 comments
Assignees
Labels
blocker Bug severity task TODO
Milestone

Comments

@courville
Copy link
Contributor

In order to target SDK 30 you need:

diff --git a/build.gradle b/build.gradle
index ea5d6de..bd9c633 100644
--- a/build.gradle
+++ b/build.gradle
@@ -115,7 +115,7 @@ android {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
-    compileSdkVersion 29
+    compileSdkVersion 'android-R'
     buildToolsVersion '29.0.3'
     sourceSets {
         main {
@@ -130,7 +130,7 @@ android {
     defaultConfig {
         generatedDensities = []
         minSdkVersion 21
-        targetSdkVersion 29
+        targetSdkVersion 'R'
         multiDexEnabled true
         versionCode getDate()
         version = '4.48.1'

When launching the app you get this obvious introspection not allowed anymore to solve:

2020-04-26 13:56:05.111 7491-7550/org.courville.nova W/.courville.nov: Accessing hidden method Landroid/os/storage/StorageVolume;->getPath()Ljava/lang/String; (greylist-max-q,test-api, reflection, denied)
2020-04-26 13:56:05.111 7491-7550/org.courville.nova W/System.err: java.lang.NoSuchMethodException: android.os.storage.StorageVolume.getPath []
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at java.lang.Class.getMethod(Class.java:2072)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at java.lang.Class.getMethod(Class.java:1693)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.filecorelibrary.ExtStorageManager.updateAllVolumes(ExtStorageManager.java:127)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.filecorelibrary.ExtStorageManager.getExtStorageManager(ExtStorageManager.java:51)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.Blacklist.isBlacklisted(Blacklist.java:84)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.VideoStoreImportImpl$Job.<init>(VideoStoreImportImpl.java:246)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.VideoStoreImportImpl.handleScanCursor(VideoStoreImportImpl.java:171)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.VideoStoreImportImpl.doScan(VideoStoreImportImpl.java:331)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.VideoStoreImportImpl.doFullImport(VideoStoreImportImpl.java:105)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.VideoStoreImportService.doImport(VideoStoreImportService.java:417)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at com.archos.mediaprovider.video.VideoStoreImportService.handleMessage(VideoStoreImportService.java:364)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at android.os.Looper.loop(Looper.java:216)
2020-04-26 13:56:05.112 7491-7550/org.courville.nova W/System.err:     at android.os.HandlerThread.run(HandlerThread.java:67)
@courville courville added the task TODO label Apr 26, 2020
@courville courville self-assigned this Apr 26, 2020
@courville
Copy link
Contributor Author

androidR branch created for Video/MediaLib/FileCoreLibrary

courville added a commit to nova-video-player/aos-FileCoreLibrary that referenced this issue May 9, 2020
@courville
Copy link
Contributor Author

getPath is greylisted reflection denied on API30:
See nova-video-player/aos-FileCoreLibrary@e81467b
See nova-video-player/aos-FileCoreLibrary@04839ca

@courville
Copy link
Contributor Author

Pending google play to be ready to manage properly android.permission.MANAGE_EXTERNAL_STORAGE and request exemption.

See nova-video-player/aos-Video@fa42e91

@courville
Copy link
Contributor Author

@courville
Copy link
Contributor Author

Exemption requested and denied.
For the record here are the elements sent.
App functionality requiring the permission (limit 500 chars):

Nova is a video player/manager that catalogs (though MediaStore.Files import)  and presents all videos as a structured medialibrary (Movie/TVshow/Anime) after media information scraping (themoviedb/thetvdb cloud services).
It needs to:
- access all videos already present on the device wherever located (internal, SDcard, USB)
- act as a file manager (import/delete/download) for all media files even those not recognized as such by Android: e.g. NFO metadata, SUB/SSA subtitles, XML resume points

Why can't your app follow good confidentiality practices (i.e. Storage Access Framework or Media Store API or Scoped Storage) (limit 500 chars):

Without loss of functionality, scoped storage cannot be used since Nova needs to index all preexisting videos & related files at any location (internal/SDcard/USB)
MediaStoreAPI does not allow managing (read/download/delete) all media files processed today by Nova: e.g. NFO metadata, SUB/SSA subtitle, XML resume points
Storage Access Framework is not compatible with Nova full device media persistent library design capturing overall device content
Nova is open-source and can be audited on github

Less than 30s video explaining the claim: https://home.courville.org/nova_video_player-faq/nova-MANAGE_EXTERNAL_STORAGE-permission.mp4

Generic reject email received from Google without any specific information.

Overall this is a very frustrating experience.

@courville
Copy link
Contributor Author

Note that Google failed to implement on Android TV (at least API30 emulator) the required dialog to manage properly android.permission.MANAGE_EXTERNAL_STORAGE:

2021-07-10 15:25:25.798 4151-4151/org.courville.nova E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.courville.nova, PID: 4151
    android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION (has extras) }
        at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2067)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1727)
        at android.app.Activity.startActivityForResult(Activity.java:5320)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:574)
        at android.app.Activity.startActivityForResult(Activity.java:5278)
        at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:560)
        at android.app.Activity.startActivity(Activity.java:5664)
        at android.app.Activity.startActivity(Activity.java:5617)
        at com.archos.mediacenter.video.browser.PermissionChecker$4.onClick(PermissionChecker.java:161)
        at androidx.appcompat.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

This is a mess.

@courville courville added the blocker Bug severity label Jul 13, 2021
@courville
Copy link
Contributor Author

@courville
Copy link
Contributor Author

Found old issue on issuetracker somehow related https://issuetracker.google.com/issues/136774034
And precious command:

adb shell content query --uri "content://media/external/file" --projection name:_data.

@courville
Copy link
Contributor Author

courville commented Jul 14, 2021

API30debacle plan of record:

  • rely on Media API to import storage content (valid for video&srt, no ssa/nfo --> request to google?)
  • use storage access framework for video delete/subs download? (groupped actions possible?), check if there is no annoying directory picker
  • possible use scoped storage to replicate external/local storage tree for NFO/cover/(no XML on internal storage) with /sdcard/Android/org.courville.nova prefix (lifecycle question for external drive)

@courville
Copy link
Contributor Author

In terms of deadline 2021/11/1 for nova cf. https://support.google.com/googleplay/android-developer/answer/9859152#zippy=%2Ctarget-api-level-requirements-for-play-console

API level requirement Starting date
Android 8.0 (API level 26) August 1, 2018: Required for new appsNovember 1, 2018: Required for app updates
Android 9 (API level 28) August 1, 2019: Required for new appsNovember 1, 2019: Required for app updates
Android 10 (API level 29)* August 3, 2020: Required for new appsNovember 2, 2020: Required for app updates
Android 11 (API level 30)* August 2, 2021: Required for new appsNovember 1, 2021: Required for app updates

@moneytoo
Copy link

As mentioned here, it is still possible to use the classic File API, though it is limited to media files only (just like the MediaStore API). The greylisted methods could be possibly replaced by MediaStore.getExternalVolumeNames() (?).

@courville
Copy link
Contributor Author

Reading https://stackoverflow.com/questions/56468539/getexternalstoragepublicdirectory-deprecated-in-android-q
leads to the conclusion that nova needs to use MediaStore API.

Code sample to implement create/delete/etc... classes compatible with Android Q/R (FileUtilsQ.java) are available here https://gist.github.com/fiftyonemoon/433b563f652039e32c07d1d629f913fb and mentioned here https://stackoverflow.com/questions/64582269/how-can-i-delete-file-on-android-11-api-30-without-system-confirmation-dialog

This requires however to have proper content:// uri and https://stackoverflow.com/questions/7305504/convert-file-uri-to-content-uri provides some more or less working methods.

@courville
Copy link
Contributor Author

courville commented Oct 23, 2021

Experimenting a bit:

  • when srt files are created by nova, nova can delete them without a securityException handling using directly content://media/external_primary/file/## uri
  • video files can be delete only using content://media/external_primary/video/media/### uri
  • nova is unable to create NFO (no XML resume point files on local storage) anywhere (SRT ok) --> use scoped storage for this (will eat local storage space with external USB drives) and treat covers the same way (or deprecate external nfo/cover)

Some useful query methods via adb:

  • for videos adb shell content query --uri "content://media/external_primary/video/media" --projection _data
  • for files adb shell content query --uri "content://media/external/file" --projection _data

To get the content uri, this asynchronous way works:

MediaScannerConnection.scanFile(mContext, new String[]{ uri.getPath() },
                null, // mimetypes
                new MediaScannerConnection.OnScanCompletedListener() {
                    @Override
                    public void onScanCompleted(String path, Uri uri) {
                        contentUri = uri;
                        log.debug("scanFile: contentUri " + contentUri + " for path " + path);
                    }
                });

Note that the hack in ExternalSDFileWriter make Android believe that the file is an image via insertion in the MediaStore.Images.Media does not work anymore and will need to be removed from the code.

courville added a commit to nova-video-player/aos-FileCoreLibrary that referenced this issue Oct 23, 2021
Note that this is a PoC. it works with video files.
SRT files created by nova can be deleted.
Every other format is ko.
Should add jpg file handling the same way.

Launcher pending intent should be wired back to UI logic and not global.

See nova-video-player/aos-AVP#336
courville added a commit to nova-video-player/aos-FileCoreLibrary that referenced this issue Oct 23, 2021
@courville
Copy link
Contributor Author

courville commented Oct 24, 2021

TODO:

  • check why srt can be created and not nfo reading Video/src/main/java/com/archos/mediacenter/video/utils/SubtitlesDownloaderActivity.java:953 and MediaLib/src/com/archos/mediascraper/NfoWriter.java:326. For this use nova setting "Export all descriptions" to see the FileNotFoundException errors (open failed: EPERM). Perhaps use new FileUtilsQ create method?
  • verify that video delete works with hdd attached to shield (i.e. using correct MediaStore.VOLUME_EXTERNAL or MediaStore.Video.Media.EXTERNAL_CONTENT_URI in getContentUri from FileCoreLibrary/src/com/archos/filecorelibrary/FileUtilsQ.java. Could be done first doing adb content query on box after indexing.

@courville
Copy link
Contributor Author

NFO files (text/plain mime type only https://cs.android.com/android/platform/superproject/+/master:packages/providers/MediaProvider/src/com/android/providers/media/util/MimeUtils.java?q=MimeUtils.java) can only be created in Documents/Download folders. It does not make sense to prefix them in app private directory getFilesDir() since nobody would access them. See https://developer.android.com/training/data-storage
Alternative is to use getExternalFilesDir(null) /storage/emulated/0/Android/data/org.courville.nova/files visible from users and where nova can write.
Links to refresh crash courses on directories: https://gist.github.com/granoeste/5574148 https://medium.com/microsoft-mobile-engineering/scoped-storage-in-android-10-android-11-28d58d989f3c

@courville
Copy link
Contributor Author

Some TODO (for me):

  • check nfo/jpg relocate in AutoScrapeService (should be abstracted from nfoParser)
  • wire back the UI notif of the delete for browser refresh
  • bug (not a regression): when removing folder it does the associatedFiles on folder name (not a video)

@courville
Copy link
Contributor Author

API31 targeted for v6.0.30 onward.

@courville courville added this to the nova v6 milestone Dec 20, 2021
@moneytoo
Copy link

VLC 3.4.3 beta 6 available from the public testing channel on Google Play uses the MANAGE_EXTERNAL_STORAGE permission.

@courville
Copy link
Contributor Author

@moneytoo thanks for sharing this news.
It hurts since I have been denied this privilege by Google.
I am glad for vlc to have managed to lobby for it.
At least nova complies with the security requirements of Android...
/me cries into a pillow

@courville
Copy link
Contributor Author

@courville
Copy link
Contributor Author

@moneytoo, I just made the connection with just video player (I am slow sorry).
FYI nova relies on the old Archos Video Player AVOS C based multimedia engine that used to be the software basis for all Archos multimedia PMPs.

@courville
Copy link
Contributor Author

From the VLC folks and for track record https://issuetracker.google.com/issues/143549606

@courville
Copy link
Contributor Author

courville commented Sep 21, 2022

OK just noticed on Google Play console that I have been awarded the android.permission.MANAGE_EXTERNAL_STORAGE sensitive permission (after it has been denied). It appeared out of the blue somehow.

@moneytoo you should check too (finger crossed).

EDIT: I also checked that I can deploy an internal release with the perm.

@moneytoo
Copy link

Knowing Google, something like that usually sounds too good to be true. But if it sticks, it's great. Could it be because you left a version of an app with such permission in some release channel untouched and they eventually approved it? At least for me, I only see my declaration for this permission in App content section and nothing more.

courville added a commit to nova-video-player/aos-Video that referenced this issue Sep 22, 2022
And disable it by default since it afterall foogle does not allow it despite the google play console cryptic status message.

See nova-video-player/aos-AVP#336
@courville
Copy link
Contributor Author

courville commented Sep 22, 2022

OK this was indeed too good to be true. After granted deployment it has been cancelled.
FTR this is what was indicated on the google play console:
Capture d’écran 2022-09-22 à 19 01 18

@moneytoo
Copy link

BTW, it's not only VLC possessing such permission, but a "few more" other players at least:

MX Player (com.mxtech.videoplayer.ad)
MX Player Pro (com.mxtech.videoplayer.pro)
VLC (org.videolan.vlc)
OPlayer Lite (com.olimsoft.android.oplayer)
OPlayer (com.olimsoft.android.oplayer.pro)
KMPlayer (com.kmplayer)
XPlayer (video.player.videoplayer)
PLAYit (com.playit.videoplayer)
HD Video Player by iJoysoft (free.online.hd.video.player)
Video Player by Leopard V7 (com.mine.videoplayer)

@courville
Copy link
Contributor Author

@moneytoo indeed list is expanding... Not quite sure what is the magic for requesting permission since it has been denied twice.
I hate to resort to this, but I might ping some google folks to understand better the process.
Please let me know if you find more.

@moneytoo
Copy link

My opinion is that the magic is either support of some not normally indexed file format (.iso, .wmv, .rm, possibly some other subtitle or audio formats) or some advanced file functionality (local p2p file sharing, folder encryption or lockings etc.).

@moneytoo
Copy link

moneytoo commented Jun 8, 2023

https://www.reddit.com/r/androiddev/comments/rmgdis/comment/jnddkp8/?context=3

@courville
Copy link
Contributor Author

@moneytoo thanks for sharing, have you requested on play console the right?

@courville
Copy link
Contributor Author

courville commented Jul 18, 2023

FTR after downloading a couple (not being exhaustive there) of video players on apkpure (I know...), a simple for i in *apk; do aapt d permissions "$i" | grep '(package|MANAGE)'; done provides:

package: com.kmplayer
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'
package: org.xbmc.kodi
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'
package: com.mxtech.videoplayer.ad
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'
package: video.player.videoplayer
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'
package: com.kmp.video
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'
package: com.mine.videoplayer
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'
package: org.videolan.vlc
uses-permission: name='android.permission.MANAGE_EXTERNAL_STORAGE'

@courville
Copy link
Contributor Author

courville commented Aug 26, 2023

OK after discussing with Google Developper Support, I was not able to get someone that could help on MANAGE_EXTERNAL_STORAGE permission.
However, declaration on Play Console "application content section", the "access to all files" is marked treated and seems enabled. I gave another shot at publishing the nova on internal track and it has not been removed by Google for a week.
I reworked the code to grant the permission to be "universally compatible" with Android ecosystem.
What I learned is:

  • MANAGE_EXTERNAL_STORAGE is supported for API>=30, needs to be granted by user on API>=31 via android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION that does not exist on Android TV until API>=34
  • WRITE_EXTERNAL_STORAGE is maxSdkVersion 29, auto-granted API<=22, requires explicit user permission 23<=API<=32, i.e. not required to be in manifest 30<=API<=32 but programmatically requested
  • READ_EXTERNAL_STORAGE is maxSdkVersion 32, auto-granted API<=22, requires explicit user permission 23<=API<=32
  • for API>=33 instead of using WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE, more granularity is required and READ_MEDIA_(VIDEO|AUDIO|IMAGE) need to be requested when MANAGE_EXTERNAL_STORAGE is not used
  • for API>=33, POST_NOTIFICATIONS permission is also required

What is "fun" is this special case for Android TV.

No wonder that boxes supporting USB storage does not want to migrate to Android 12. Staying on Android 11 waiting for Android 14 is the only way to get apps such as file managers working without fiddling with Android framework introducing some "customizations" forking from a vanilla base.

courville added a commit to nova-video-player/aos-Video that referenced this issue Aug 26, 2023
note: android tv 12&14 cannot grant this permission...

See nova-video-player/aos-AVP#336
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocker Bug severity task TODO
Projects
None yet
Development

No branches or pull requests

2 participants