Android M权限:onRequestPermissionsResult()未被调用

312
我正在更新我们的应用程序以使用新的 M 运行时权限系统。除了onRequestPermissionsResult()之外,一切正常。我需要在按钮按下时检查权限,如果成功,发送短信。当我授予权限来执行此操作时,对话框关闭,但它直到我再次按下按钮才触发“发送短信”操作。
我已经进行了调试并在onRequestPermissionsResult()方法中设置了断点,但它从未进入该方法。
首先调用此方法:
    private void askForPermission() {
    String[] permissions = new String[]{Manifest.permission.SEND_SMS};
    ActivityCompat.requestPermissions(getActivity(), permissions, PERMISSIONS_CODE);
}

然后我的回调函数看起来像这样:

    @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == PERMISSIONS_CODE) {
        for (int i = 0; i < permissions.length; i++) {
            String permission = permissions[i];
            int grantResult = grantResults[i];

            if (permission.equals(Manifest.permission.SEND_SMS)) {
                if (grantResult == PackageManager.PERMISSION_GRANTED) {
                    onPPSButtonPress();
                } else {
                    requestPermissions(new String[]{Manifest.permission.SEND_SMS}, PERMISSIONS_CODE);
                }
            }
        }
    }
}

有人遇到类似的问题吗? 感谢任何关于此问题的帮助。 谢谢

25个回答

589

我遇到了同样的问题,现在我找到了解决方法。在使用Support库时,你需要使用正确的方法调用。例如:

  • AppCompatActivity中,你应该使用ActivityCompat.requestPermissions;
  • android.support.v4.app.Fragment中,你可以简单地使用requestPermissions(这是android.support.v4.app.Fragment的一个实例方法)

如果你在Fragment中调用ActivityCompat.requestPermissions,onRequestPermissionsResult回调函数将被调用在Activity而不是Fragment上。


15
它也会出现在没有历史记录的活动中: https://code.google.com/p/android-developer-preview/issues/detail?id=2915 - Anthony Bobenrieth
11
当在android.support.v4.app.Fragment中时,你应该简单地使用requestPermissions。- 谢谢! - Tigran Sarkisian
5
那么对于 noHistory 的活动,解决方案是什么?我们无法从它们那里请求权限吗? - Dean Wild
2
链接已经失效 @AnthonyBobenrieth。是否有任何解决方案来避免历史记录问题? - fersarr
3
在使用 Fragment.requestPermissions() 时,实际上是父 Activity 接收到了 onRequestPermissionsResult() 回调。(这是在支持库版本23.3.0中的情况) - Someone Somewhere
显示剩余8条评论

106

你可以尝试这个:

requestPermissions(permissions, PERMISSIONS_CODE);

如果您从片段中调用此代码,则它具有自己的requestPermissions()方法。我认为问题在于您正在调用静态方法。

专业提示:如果您想在片段中使用onRequestPermissionsResult(),请使用以下方法:FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)


感谢你的帮助。我注意到如果在片段中,有一个requestPermission方法。我现在正处于一个片段中,我尝试只调用requestPermissions,但不幸的是它没有起作用。我也尝试了你提到的方法,但还是没成功。 - Ayohaych
这在我的Android M设备上有效。但我想知道它是否会在Pre-M设备上引起任何问题? - Bala Vishnu
4
请确保您不在activity的onRequestPermissionsResult方法中使用请求代码。如果您的activity还使用了onRequestPermissionsResult回调,您应该提供默认值: super.onRequestPermissionsResult(requestCode,permissions,grantResults); - Timmy Simons

69

我希望它能正常工作

针对活动:

 ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);

对于片段:

 requestPermissions(permissionsList,REQUEST_CODE);

SDK 15及以下的怎么处理? - zulkarnain shah
4
您无需获得 SDK 15 的许可,只有 Marshmallow 及以上版本需要。 - Sanjay Mangaroliya

51
我也遇到了这个问题。如果你希望处理权限的活动不会出现在历史/最近列表中,那么你可能会尝试更改你的AndroidManifest.xml条目。
如果你将调用requestPermissionsAppCompatActivity.requestPermissions的活动设置为......
android:noHistory="true"
android:excludeFromRecents="true"

如果您的Activity是从Activity或者AppCompatActivity派生而来,那么在您的AndroidManifest.xml中设置了noHistory=trueexcludeFromRecents=true这两个标记,那么onRequestPermissionsResult()将不会被调用。

解决方法是从'AndroidManifest.xml'中删除这两个标记,并使用finishAndRemoveTask()来结束您的Activity。


我宁愿不删除noHistory属性,但这是适合我的解决方案。谢谢! - Eric Schlenz
1
我在Marshmallow上遇到了这个问题,但在Nougat上没有,谢谢,它对我有用。 - Yohan Dahmani

38
如果您在活动和片段中都有onRequestPermissionsResult,请确保在活动中调用super.onRequestPermissionsResult。在片段中不是必须的,但在活动中是必须的。

另外,请注意,如果您针对一个API(例如19)进行目标设置,则仍将处于旧的权限模型系统下,因此不会收到请求权限相关的函数调用。 - Bonatti
如果您扩展了另一个未调用super的活动,请查看我的答案。 - TouchBoarder
3
发现这个方法:FragmentActivity.onRequestPermissionsResult(..) 是将调用片段的 onRequestPermissionsResult(..) 的方法转发到那里。 - JanPl
@Bonatti 那么如果我在Android 4.4.2中尝试请求权限,我将不会得到结果吗?因此我只能查看权限而无法更改它们? - Alex Fragotsis
@AlexanderFragotsis 你会得到一个结果。唯一的区别是你不需要被要求授权,而是系统会自动授权给你。 - Dusan Zivkovic
哇,这里有些不一致的东西。我有两个应用程序,一个需要它,而另一个则不需要。 - guness

32

2
涉及到 android.support.v13.app.FragmentCompat。 - Udi Oshi
1
FragmentCompat在API 27.1.0中已被弃用。 - Big McLargeHuge
我的答案已经过时,请参考:https://developer.android.com/training/permissions/requesting - Ben.Slama.Jihed

15

如果您在片段中使用requestPermissions,它只接受2个参数而不是3个。

您应该使用requestPermissions(permissions, PERMISSIONS_CODE);


1
实际上它确实提供了一个问题的答案。调用片段的实例方法requestPermissions而不是ActivityCompat.requestPermissions,会触发result方法。这就是主要问题所在。谢谢Don。 - Waclock

15

如果出于某种原因您扩展了位于某个外部库中的自定义Activity,而该库未调用super关键字,那么您需要在Activity onRequestPermissionsResult中手动调用Fragment super.onRequestPermissionsResult。

YourActivity extends SomeActivityNotCallingSuperOnRequestPermissionsResult{
Fragment requestingFragment;//the fragment requesting the permission
...
@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestingFragment!=null)
            requestingFragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
...

我有一个普通的活动,它扩展了 AppCompatActivity,我是否仍然需要使用 super() - Vivek Thummar

12

我已经发现,在哪里调用android.support.v4.app.Fragment.requestPermissions非常重要。

如果您在onCreate()中调用它,onRequestPermissionsResult()将永远不会被调用。

解决方案:在onActivityCreated()中调用它;

@Override
public void onActivityCreated(Bundle savedInstanceState) {

    super.onActivityCreated(savedInstanceState);

    if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED) 
        requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0);

}

1
我遇到了同样的问题,但是在我的代码中我无法获得 onActivityCreated()。SDK 23. - kAmol
请参见http://developer.android.com/reference/android/app/Fragment.html#onActivityCreated%28android.os.Bundle%29,或参见http://www.mysamplecode.com/2012/08/android-fragment-example.html中的示例。 - almisoft
我不在片段中,我正在尝试在活动的onCreate中完成它。 - kAmol
使用 onPause() 还是怎么样? - almisoft

12

FragmentCompat中,对于Marshmallow以前的设备,您可以使用checkPermissions函数。

我像这样使用:

FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

2
只有在 android.app.fragment 中请求权限并导入 support-v13 库才能使其正常工作! - Rez
4
FragmentCompat.requestPermissions() 在 android.support.v4.app.Fragment 中无法使用。有人知道如何处理吗? - Jutikorn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接