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 一样容易,如果您请求多个权限,则需要这样做,因为此方法只是调用一个权限的包装器。 感谢您突出显示“首先,在清单中定义权限(就像您在帖子中所做的那样),否则您的请求将被自动拒绝”。我的是这样 我把“22”改成了“23”【参考方案2】:

我遇到了同样的问题,结果证明是由于 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。我通过将清单中的 &lt;uses-permission&gt; 更改为:

<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 开始将 &lt;uses-permission&gt; 解释为未来的代码操作而不是安装时的需求。【参考方案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 将清单中的&lt;uses-permission&gt; 标记解释为“我将在代码中询问”是关键 “我要求安装”。很多消息来源会告诉您您需要 &lt;uses-permission&gt; 标签,但没有人说明原因,如果您没有设置该值,您将像我一样连续数小时感到困惑。

【讨论】:

【参考方案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 未显示对话框的主要内容,如果未能解决你的问题,请参考以下文章