英文:
READ_EXTERNAL_STORAGE Permission request not showing on emulator
问题
I'm trying to set up a way to register permission result handlers after the activity is initialized, by creating a Map<Integer, Runnable>
to hold the handlers, when I request permission I use a randomly generated code and save a runnable to the Map of codes/handlers.
Here's what I have so far in my activity class
private final HashMap<Integer, Runnable> onPermission = new HashMap<>();
// I call this from other classes to ask for a permission and register a handler
public void requestPermission(Runnable onGranted, String... permissions) {
int code = Permissions.permissionRequestCode();
onPermission.put(code, onGranted);
requestPermissions(permissions, code);
}
// Overriding this method to check if the Map has a handler for the granted request
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Runnable handler = onPermission.get(requestCode);
if (handler != null && isGranted(grantResults)) {
handler.run();
onPermission.remove(requestCode);
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
// Utility method to check if all the requested permissions are granted
private boolean isGranted(int[] results) {
for (int i : results) {
if (i != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
And here is an example of how this can be used, where owner
is my Activity instance:
private void readImages() {
if (ContextCompat.checkSelfPermission(owner, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
loadImages();
} else {
owner.requestPermission(this::loadImages, Manifest.permission.READ_EXTERNAL_STORAGE);
}
}
Now running this on an actual device (Android 12, API 31), works exactly like I would expect (the request shows, and the handler is executed when the permission is granted), however on the emulator (Android 13, API 33), nothing shows when the permission is requested, and it remains "not granted", the permission doesn't even show in the "App info" even though it's included in the manifest.
My manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="Mesa"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.Mesa.NoActionBar"
android:usesCleartextTraffic="true">
<activity
android:name=".app.Mesa"
android:configChanges="uiMode|screenSize|colorMode"
android:exported="true"
android:theme="@style/Theme.Mesa.NoActionBar"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
My build.gradle:
android {
compileSdk 33
defaultConfig {
applicationId "org.luke.mesa"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
proguardFiles 'proguard-rules.pro'
}
buildTypes {
release {
minifyEnabled true
}
debug {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
allprojects {
tasks.withType(JavaCompile){
options.compilerArgs << "-Xlint:deprecation"
}
}
}
buildFeatures {
viewBinding true
dataBinding true
}
packagingOptions {
resources {
merges += ['META-INF/DEPENDENCIES']
}
}
namespace 'org.luke.mesa'
dependenciesInfo {
includeInApk true
includeInBundle true
}
buildToolsVersion '33.0.0'
}
Possible duplicates which didn't solve my problem:
英文:
I'm trying to set up a way to register permission result handlers after the activity is initialized, by creating a Map<Integer, Runnable>
to hold the handlers, when I request permission I use a randomly generated code and save a runnable to the Map of codes/handlers.
Here's what I have so far in my activity class
private final HashMap<Integer, Runnable> onPermission = new HashMap<>();
//i call this from other classes to ask for a permission and register a handler
public void requestPermission(Runnable onGranted, String...permissions) {
int code = Permissions.permissionRequestCode();
onPermission.put(code, onGranted);
requestPermissions(permissions, code);
}
//overriding this method to check if the Map has a handler for the granted request
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Runnable handler = onPermission.get(requestCode);
if (handler != null && isGranted(grantResults)) {
handler.run();
onPermission.remove(requestCode);
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
//utility method to check if all the requested permissions are granted
private boolean isGranted(int[] results) {
for (int i : results) {
if (i != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
And here is an example of how this can be used, where owner
is an my Activity instance :
private void readImages() {
if (ContextCompat.checkSelfPermission(owner, Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
loadImages();
} else {
owner.requestPermission(this::loadImages, Manifest.permission.READ_EXTERNAL_STORAGE);
}
}
Now running this on an actual device (Android 12, API 31), works exactly like I would expect (the request shows, and the handler is executed when the permission is granted), however on the emulator (Android 13, API 33), nothing shows when the permission is requested, and it remains "not granted", the permission doesn't even show in the "App info" even though it's included in the manifest.
Real device :
Emulator :
My manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="Mesa"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.Mesa.NoActionBar"
android:usesCleartextTraffic="true">
<activity
android:name=".app.Mesa"
android:configChanges="uiMode|screenSize|colorMode"
android:exported="true"
android:theme="@style/Theme.Mesa.NoActionBar"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
My build.gradle :
android {
compileSdk 33
defaultConfig {
applicationId "org.luke.mesa"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
proguardFiles 'proguard-rules.pro'
}
buildTypes {
release {
minifyEnabled true
}
debug {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
allprojects {
tasks.withType(JavaCompile){
options.compilerArgs <<"-Xlint:deprecation"
}
}
}
buildFeatures {
viewBinding true
dataBinding true
}
packagingOptions {
resources {
merges += ['META-INF/DEPENDENCIES']
}
}
namespace 'org.luke.mesa'
dependenciesInfo {
includeInApk true
includeInBundle true
}
buildToolsVersion '33.0.0'
}
possible duplicates which didn't solve my problem :
答案1
得分: 3
Android 13及更高版本,请求READ_EXTERNAL_STORAGE
权限的应用必须改为请求以下一个或多个更细粒度的权限:
READ_MEDIA_IMAGES
(读取媒体图像)READ_MEDIA_VIDEO
(读取媒体视频)READ_MEDIA_AUDIO
(读取媒体音频)
参考链接:https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions
英文:
As of Android 13 and above, apps that request READ_EXTERNAL_STORAGE
must instead request one or more of the following more granular permissions:
READ_MEDIA_IMAGES
READ_MEDIA_VIDEO
READ_MEDIA_AUDIO
Reference: https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论