ActivityCompat.requestPermissions 未显示对话框
Posted
技术标签:
【中文标题】ActivityCompat.requestPermissions 未显示对话框【英文标题】:ActivityCompat.requestPermissions not showing dialog box 【发布时间】:2016-05-30 19:32:00 【问题描述】:if (ContextCompat.checkSelfPermission(RegisterActivity.this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED)
ActivityCompat.requestPermissions(this,
new String[]Manifest.permission.READ_PHONE_STATE, REQUEST_READ_PHONE_STATE_PERMISSION);
我正在尝试在 nexus 5 api 23 上使用此功能,但它只是没有像它应该做的那样向我显示对话框,它只是没有做任何事情。 什么可能导致问题? (此代码在 java 活动中) 我尝试将我的最小 api 更改为 23 并使用没有 ActivityCompat 的 requestPermissions() 但仍然无法正常工作。
apply plugin: 'com.android.application'
android
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig
applicationId "com.example.idanayzen.photomap"
minSdkVersion 23
targetSdkVersion 23
versionCode 1
versionName "1.0"
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
dependencies
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.google.android.gms:play-services:8.4.0'
compile 'com.android.support:design:23.1.1'
和清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.idanayzen.photomap">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps" />
<activity android:name=".RegisterActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".WrongPhoneNum"></activity>
</application>
</manifest>
【问题讨论】:
顺便说一句,我已经尝试将字符串更改为“android.permission.READ_PHONE_STATE”仍然相同 权限被屏蔽了吗? 【参考方案1】:这里是一个使用requestPermissions()
的例子:
首先,在清单中定义权限(就像您在帖子中所做的那样),否则您的请求将自动被拒绝:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
接下来,在onRequestPermissionsResult()中定义一个值来处理权限回调:
private final int REQUEST_PERMISSION_PHONE_STATE=1;
这是调用 requestPermissions() 的代码:
private void showPhoneStatePermission()
int permissionCheck = ContextCompat.checkSelfPermission(
this, Manifest.permission.READ_PHONE_STATE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED)
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE))
showExplanation("Permission Needed", "Rationale", Manifest.permission.READ_PHONE_STATE, REQUEST_PERMISSION_PHONE_STATE);
else
requestPermission(Manifest.permission.READ_PHONE_STATE, REQUEST_PERMISSION_PHONE_STATE);
else
Toast.makeText(MainActivity.this, "Permission (already) Granted!", Toast.LENGTH_SHORT).show();
首先,您检查您是否已经拥有权限(请记住,即使在被授予权限后,用户也可以稍后在应用设置中撤销权限。)
最后,这是您检查是否获得许可的方式:
@Override
public void onRequestPermissionsResult(
int requestCode,
String permissions[],
int[] grantResults)
switch (requestCode)
case REQUEST_PERMISSION_PHONE_STATE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
Toast.makeText(MainActivity.this, "Permission Granted!", Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "Permission Denied!", Toast.LENGTH_SHORT).show();
private void showExplanation(String title,
String message,
final String permission,
final int permissionRequestCode)
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(title)
.setMessage(message)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog, int id)
requestPermission(permission, permissionRequestCode);
);
builder.create().show();
private void requestPermission(String permissionName, int permissionRequestCode)
ActivityCompat.requestPermissions(this,
new String[]permissionName, permissionRequestCode);
【讨论】:
如果 requestPermissions 不起作用,做所有这些检查不是没用吗?在我的代码中,我只是检查我是否有权限,如果没有,我会调用 requestPermissions。后来我想我会改变这一点。我完全按照你说的做了 requestPermissions 语法,但它对我不起作用。 由于您没有发布实际的 requestPermissions() 代码,因此我发布了一个完整的工作示例。对我来说很好。 我刚刚发布了我的实际 requestPermissions() 代码。谢谢你的帮助:) @Phil - 将两者都添加到示例中。如您所见,直接调用 requestPermission 一样容易,如果您请求多个权限,则需要这样做,因为此方法只是调用一个权限的包装器。 感谢您突出显示“首先,在清单中定义权限(就像您在帖子中所做的那样),否则您的请求将被自动拒绝”。我的是这样我遇到了同样的问题,结果证明是由于 manifest merger tool 从依赖项中提取了 android:maxSdkVersion
属性。
要查看您在 APK 中请求的实际权限,您可以使用 aapt
工具,如下所示:
/path/to/android-sdk/build-tools/version/aapt d permissions /path/to/your-apk.apk
在我的情况下,它打印:
uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE' maxSdkVersion='18'
即使我没有在清单中指定maxSdkVersion
。我通过将清单中的 <uses-permission>
更改为:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
(其中工具命名空间是http://schemas.android.com/tools
)
【讨论】:
你拯救了我的一天!谢谢 @usman 它不一定适用于所有人,可能是您的情况不同。请发表您的问题,肯定有人会解决您的问题:) 至少到目前为止,要查看实际的权限(合并)清单,您可以在没有任何其他工具(如aapt
)的情况下查看它。当您从 Android Studio 中看到您的 AndroidManifest.xml 时,请查看底部选项卡,只需单击 Merged Manifest
选项卡。
你是个矮胖的巫师。你是个巫师!!【参考方案3】:
我需要请求WRITE_EXTERNAL_STORAGE
的许可,但尽管尝试了提到的所有不同建议,但没有得到弹出窗口。
最终的罪魁祸首是 HockeyApp。它使用清单合并来包含自己对WRITE_EXTERNAL_STORAGE
的权限,但它会对其应用最大 sdk 版本。
解决此问题的方法是将其包含在您的清单文件中,但对其进行替换,以覆盖 HockeyApp 的版本并成功!
4.7.2 其他请求外部存储权限的依赖(SDK版本5.0.0及更高版本)为Android O做好准备, HockeySDK-Android 5.0.0 及更高版本限制
WRITE_EXTERNAL_STORAGE
使用 maxSdkVersion 过滤器的权限。在某些用例中,例如 如果应用程序包含需要此权限的依赖项, maxSdkVersion 使这些依赖项无法授予或 请求许可。这些情况的解决方案如下:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/>
它会导致其他属性从低 优先清单将被替换而不是被合并。
https://support.hockeyapp.net/kb/client-integration-android/hockeyapp-for-android-sdk#permissions-advanced
【讨论】:
谢谢,这都是我的问题。 这解决了我的问题。非常感谢!【参考方案4】:替换:
ActivityCompat.requestPermissions(this, new String[]"Manifest.permission.READ_PHONE_STATE", 225);
与:
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.READ_PHONE_STATE, 225);
The actual string for that permission 不是"Manifest.permission.READ_PHONE_STATE"
。使用符号Manifest.permission.READ_PHONE_STATE
。
【讨论】:
不适合我。我的应用程序配置为从 16 到 23 sdk 版本运行 你应该使用 android.Manifest.permission.READ_PHONE_STATE【参考方案5】:单行代码可能不是问题。
在某些设备上(我不记得它是否有现货 Android),权限对话框包含一个标有“不再询问”的复选框。如果您在选中该框的情况下单击拒绝,则不会再次提示您获得该权限,应用程序将自动拒绝该权限。要恢复此设置,您必须进入设置 -> 应用程序 -> 权限并重新启用该应用程序的权限。然后将其关闭以再次拒绝它。您可能需要在再次关闭之前打开应用程序,不确定。
我不知道你的 Nexus 有没有。也许值得一试。
【讨论】:
我遇到过这种情况。我能想到的最好办法是在onRequestPermissionsResult()
中检查PackageManager.PERMISSION_DENIED
并调整UI 以向用户解释必须手动设置权限并打开Settings.ACTION_APPLICATION_DETAILS_SETTINGS
。【参考方案6】:
我将目标 SDK 版本从 22 更新到了 23,它运行良好。
【讨论】:
是的,但这不是偶然的运气。原因是 23 是 Android 开始将<uses-permission>
解释为未来的代码操作而不是安装时的需求。【参考方案7】:
这是我想与大家分享的另一个经验。在我实现以下代码来检查 BLE 访问权限后,问题就出现了:
final String requiredPermission = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && targetSdkVersion >= Build.VERSION_CODES.Q) ?
android.Manifest.permission.ACCESS_FINE_LOCATION :
android.Manifest.permission.ACCESS_COARSE_LOCATION;
我的意思是区分 FINE 和 COARSE 位置权限请求,两者都已在清单中定义。检查 ACCESS_COARSE_LOCATION 权限时,从未弹出“请求权限”对话框,但始终使用 PERMISSION_DENIED 调用onRequestPermissionsResult
(以防应用设置中未启用权限)。所以我删除了对 BUILD.SDK 的检查,只检查了ACCESS_FINE_LOCATION
,瞧,丢失的对话框出现了。
final String requiredPermission = android.Manifest.permission.ACCESS_FINE_LOCATION;
成功了。
Manifest 源包含:
<uses-permission android:name="android.permission.COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
但 apk 仅包含 android.permission.ACCESS_FINE_LOCATION
。在构建过程中的某个时候,COARSE_LOCATION
已被删除。
我希望这可以帮助遇到同样问题的人。
【讨论】:
【参考方案8】:对我来说,问题是错误地请求了一个组而不是实际权限。
【讨论】:
【参考方案9】:以上信息很好,但是将targetSdkVersion
设置为23(或更高)对于Android 将清单中的<uses-permission>
标记解释为“我将在代码中询问”是关键 “我要求安装”。很多消息来源会告诉您您需要 <uses-permission>
标签,但没有人说明原因,如果您没有设置该值,您将像我一样连续数小时感到困惑。
【讨论】:
【参考方案10】:这只是发生在我身上。事实证明,当我需要过滤到 DANGEROUS 权限时,我正在请求所有权限,它突然开始工作了。
fun requestPermissions()
val missingDangerPermissions = PERMISSIONS
.filter ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
.filter this.getPackageManager().getPermissionInfo(it, PackageManager.GET_META_DATA).protectionLevel == PermissionInfo.PROTECTION_DANGEROUS // THIS FILTER HERE!
if (missingDangerPermissions.isNotEmpty())
Log.i(TAG, "Requesting dangerous permission to $missingDangerPermissions.")
ActivityCompat.requestPermissions(this,
missingDangerPermissions.toTypedArray(),
REQUEST_CODE_REQUIRED_PERMISSIONS);
return
else
Log.i(TAG, "We had all the permissions we needed (yay!)")
【讨论】:
从哪里得到 ContextCompat 的变量?我试过了,但变量没有找到结果?【参考方案11】:我在三星 S8 和 N8 中遇到过这个问题(其他都没有发现)
所以问题在于清单文件使用权限
<uses-permission android:name="android.permission.CAMERA"
android:requiredFeature="true" />
由于某种原因,android:requiredFeature
属性是罪魁祸首。我还没有找到原因的解释。
要解决,只需删除它,
<uses-permission android:name="android.permission.CAMERA" />
【讨论】:
【参考方案12】:不要忘记在清单中写上没有多余空格的权限。就我而言,我有:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE " />
但是看,最后,有一个额外的空间。写对了就行了
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
它现在正在工作
【讨论】:
【参考方案13】:无论你做什么,检查你是否在 Manifest 文件中声明了你需要的权限。
<!--Declaring the required permissions-->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.CAMERA" />
然后进行下一步..
【讨论】:
【参考方案14】:我也遇到了同样的问题。我更新到 buildToolsVersion "23.0.3" 一下子就奏效了。希望这对遇到此问题的人有所帮助。
【讨论】:
【参考方案15】:我遇到了同样的问题,并通过将 Manifest.permission.READ_PHONE_STATE 替换为 android.Manifest.permission.READ_PHONE_STATE 来解决它。
【讨论】:
【参考方案16】:对我来说,问题是我的请求代码无效。我选择 0xDEADBEEF 作为请求代码,但它默默地失败了(也许它在内部某个地方被转换为小于 32 位的东西?)如果我选择 255,一切都像上面描述的 NightSkyDev 一样正常工作。
【讨论】:
docs 状态,requestCode
应≥ 0。0xDEADBEEF 为
【参考方案17】:
对我来说,错误出现在清单中:权限是大写的。 Android Studio 建议我使用大写的权限。我不在乎,我花了两个小时才解决这个问题。
权限的正确语法是
【讨论】:
【参考方案18】:对我来说,问题是在提出请求后,我的主要活动启动了另一个活动。这取代了对话框,因此它从未被看到。
【讨论】:
【参考方案19】:它发生在我身上,我在 API 23 上运行它,我不得不使用代码来请求权限,如下面的代码将它放在 create 方法上。请注意,MY_PERMISSIONS_REQUEST_READ_LOCATION 是一个整数,等于 1 example int MY_PERMISSIONS_REQUEST_READ_LOCATION = 1:
如果 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) requestPermissions(new String[] Manifest.permission.ACCESS_COARSE_LOCATION,MY_PERMISSIONS_REQUEST_READ_LOCATION);
【讨论】:
【参考方案20】:也许这个解决方案可以帮助任何人 而不是:
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
使用:
ActivityCompat.requestPermissions(this, new String[]android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
所以我们将android.
添加到Manifest.permission.WRITE_EXTERNAL_STORAGE
【讨论】:
以上是关于ActivityCompat.requestPermissions 未显示对话框的主要内容,如果未能解决你的问题,请参考以下文章