I am working on providing Android 11 support on my audio/video player app. My main concern is actually with not provoking the Google tribe with their no All files access
permission allowed for player apps. I do not want my app to be rejected on publishing on the Google store.
In previous APIs, I am using WRITE_EXTERNAL_STORAGE
permission including Android 10 (where I opt out off Scoped Storage). Though, I do not know how to handle Android 11 without having my app rejected on publishing on Google store. I have learned that READ_EXTERNAL_STORAGE
permission is needed for querying MediaStore
records and I have the following questions:
- Will asking for
READ_EXTERNAL_STORAGE
on runtime on Android 11 be acceptable with Google (when I publish my app on their store)? - Can I ask for
WRITE_EXTERNAL_STORAGE
permission on runtime instead ofREAD_EXTERNAL_STORAGE
for all APIs and the system on Android 11 devices would substitute that forREAD_EXTERNAL_STORAGE
or will I need to add conditions where I ask forREAD_EXTERNAL_STORAGE
on Android 11 devices. - Will asking for
WRITE_EXTERNAL_STORAGE
on runtime on Android 11 be acceptable with Google (when I publish my app on their store)?
CodePudding user response:
you may use all these permissions without any ban from Google. you can't/shouldn't use MANAGE_EXTERNAL_STORAGE
, new perm dedicated for Scoped Storage and file managing apps, antivirs and other "privileged" soft
CodePudding user response:
Here is function for getting list of all video
fun getVideo():ArrayList {
val marrayList = ArrayList<Video>() val contentResolver =context?.contentResolver val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI val selection = "${MediaStore.Video.Media.DURATION} >= ?" val selectionArgs = arrayOf( TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS).toString() ) val sortOrder = "${MediaStore.Video.Media.DISPLAY_NAME} ASC" val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { MediaStore.Video.Media.getContentUri( MediaStore.VOLUME_EXTERNAL ) } else { MediaStore.Video.Media.EXTERNAL_CONTENT_URI } val cursor = contentResolver?.query(collection, null, selection, selectionArgs, sortOrder) if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) { val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID) val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME) val titleCol =cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE) val date=cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATE_ADDED) val durationColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION) val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE) while (cursor.moveToNext()) { val videoPath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)) val id = cursor.getLong(idColumn) val title=cursor.getString(titleCol) val name = cursor.getString(nameColumn) val duration = cursor.getInt(durationColumn) val mdate=cursor.getString(date) val size = cursor.getString(sizeColumn) val thumb = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id) var duration_formatted: String val sec: Int = duration / 1000 % 60 val min: Int = duration / (1000 * 60) % 60 val hrs: Int = duration / (1000 * 60 * 60) duration_formatted = if (hrs == 0) { min.toString() ":" String.format(Locale.UK, "d", sec) } else { hrs.toString() ":" String.format( Locale.UK, "d", min ) ":" String.format( Locale.UK, "d", sec ) } val folder = Video(thumb.toString(),id,title,name,size, duration_formatted, videoPath, mdate) marrayList.add(folder) } cursor.close() } return marrayList
}
2.Here is all [source code]1 for video player project