如果在片段和活动中都定义了onRequestPermissionsResult,则不会在片段中调用


167

我有一个片段,其中有recyclerview并使用recyclerview适配器在此recyclerview中设置数据。

现在,我在适配器的列表项中有一个按钮,单击该按钮后,我需要检查android中的READ_EXTERNAL_STORAGE权限以获取android中的新权限模型。

我在此适配器的片段中创建了一个新函数,以检查是否已授予许可,如果尚未授予许可,则请求许可。

我已将MyFragment.this作为适配器中的参数传递,并在按钮中单击适配器中的调用片段的方法。

我已使用以下代码在片段中调用requestPermission。

if(ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED){
       requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                ConstantVariables.READ_EXTERNAL_STORAGE);
    }

onRequestPermissionsResult通过使用以下代码覆盖了片段中的方法:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case ConstantVariables.READ_EXTERNAL_STORAGE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, proceed to the normal flow.
                startImageUploading();
            } else {}

但是不会被调用,而是会调用此Activity的onRequestPermissionsResult方法。

我在片段的父活动中也定义了相同的onRequestPermissionsResult方法,并且该方法被调用。

我无法删除活动的onRequestPermissionsResult方法,但是想在请求片段的权限时调用片段的onRequestPermissionsResult方法。我怎样才能做到这一点?我在这里做错什么,如果有人在这里有想法请帮助我。


1
在片段中引用此链接的运行时权限。这是确切的解决方案
Antony jackson

Answers:


371

编辑答案以涵盖更广泛的问题

我认为您混淆了片段和活动的方法。我的项目上个月遇到了类似的问题。请检查您是否最终具备以下条件:

  1. 在AppCompatActivity中使用方法ActivityCompat.requestpermissions
  2. 在v4支持片段中,您应该使用requestpermissions
  3. 捕获是,如果您在片段中调用AppcompatActivity.requestpermissions,则回调将进入活动状态而不是片段
  4. 确保super.onRequestPermissionsResult从活动的致电onRequestPermissionsResult

看看是否有帮助。


9
只要仔细检查确保您有super.onrequestpermissionresult集的活动
VarunJoshi129

27
super.onrequestpermissionresult当我使用来请求权限时,添加活动的onrequestpermissionresult会调用该片段的onrequestpermissionresult requestpermissions。现在一切正常,非常感谢.. :)
Prithniraj Nicyone

1
super.onrequestpermissionresult结果从活动回调中丢失,导致我的片段回调没有被调用
sakis kaliakoudas'Aug 8'16

4
requestPermissions()需要API级别23。是否存在与API级别21向后兼容的其他解决方案?
亚当·赫维兹

2
@ msc87 1.在活动和片段的onRequestPermissionsResult中,第一行应为:super.onRequestPermissionsResult(requestCode,权限,grantResults); 2.在识别出未授予权限的片段中,只需调用requestPermission方法,如下所示:requestPermissions(new String [] {Manifest.permission.CALL_PHONE},MY_PERMISSIONS_REQUEST_CALL_PHONE);
AREF

122

我从一个片段中请求了位置许可,在这个片段中,我需要更改它:

            ActivityCompat.requestPermissions(getActivity(), new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQ_CODE);

对此:

            requestPermissions(new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQ_CODE);

然后在片段中调用onRequestPermissionsResult。


2
像魅力一样工作:)
Antonio Vlasic '18

1
它不能与kotlin一起使用,请您帮我帮忙,因为这里使用了requestRequests(上下文为Activity,permissionList.toTypedArray(),MY_PERMISSIONS_REQUEST)
Arbaz.in

谢谢:),您节省了我的时间
Axrorxo'ja Yodgorov '19

19

这是人们在编写棉花糖时常犯的错误。

在AppCompatActivity中时,应使用ActivityCompat.requestPermissions; 在android.support.v4.app.Fragment中时,您应仅使用requestPermissions(这是android.support.v4.app.Fragment的实例方法)如果您在一个片段中调用ActivityCompat.requestPermissions,则会在onRequestPermissionsResult回调上进行调用活动而不是片段。

requestPermissions(permissions, PERMISSIONS_CODE);

如果您从片段中调用此代码,则它具有自己的requestPermissions方法。

所以基本概念是,如果您处于活动状态,则调用

ActivityCompat.requestPermissions(this,
                            new String[]{Manifest.permission.CAMERA},
                            MY_PERMISSIONS_REQUEST_CAMERA);

如果是片段,只需调用

requestPermissions(new String[]{Manifest.permission.CAMERA},
                            MY_PERMISSIONS_REQUEST_CAMERA);

作为参考,我从此链接获得了答案https://www.coderzheaven.com/2016/10/12/onrequestpermissionsresult-not-所谓的片段/


6

requestPermissions片段方法需要API级别23或更高。
如果您的应用定位到较低版本,则可以使用

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

首先,您需要添加support-v13依赖项:

implementation "com.android.support:support-v13:$supportLibVersion"

从版本27.1.0中弃用FragmentCompat
Raj kannan Iyyappan '18

6

改变这个:

ActivityCompat.requestPermissions(
    activity,
    arrayOf(Manifest.permission.READ_CONTACTS),
    PERMISSIONS_REQUEST_READ_CONTACTS
)

对此:

requestPermissions(
     arrayOf(Manifest.permission.READ_CONTACTS),
     PERMISSIONS_REQUEST_READ_CONTACTS
)

下一个用于片段(onRequestPermissionsResult在片段中调用),ActivityCompat版本用于在活动中放置onRequestPermissionsResult时使用。
咆哮Grønmo

1
private void showContacts() {
 if (getActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
         != PackageManager.PERMISSION_GRANTED) {
     requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
             PERMISSIONS_REQUEST_READ_STORAGE);
 } else {
     doShowContacts();
 }
}

 @Override
 public void onRequestPermissionsResult(int requestCode, String[] permissions,
     int[] grantResults) {
 if (requestCode == PERMISSIONS_REQUEST_READ_STORAGE
         && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
     doShowContacts();
 }
 }

变更许可


2
嗨user2002721; 您的代码可能是正确的,但在某些情况下,它将提供更好的答案;例如,您可以解释此提议的更改将如何以及为什么解决发问者的问题,可能包括相关文档的链接。这将使其对他们更有用,对正在寻找类似问题的解决方案的其他站点读者也将更有用。
文斯·鲍德伦

如果您尝试访问GrantResults的索引0而没有先检查长度,则程序可能会抛出数组超出范围的异常。它发生在我的程序上。我将GrantResults的if语句分隔为内部的if语句,以防止这种情况发生,现在它可以正常工作。
彼得·格里芬

1

这个公认的答案对我不起作用,因此我找到了自己的解决方案,如下所述:

1.首先,我创建了一个方法,分段:

public static void MyOnRequestPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
        if (requestCode == 1 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Log.d(TAG, "Permission: true");
        } else {
            Log.d(TAG, "permission: false");
        }
}

2.然后从其基础活动中调用它:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(requestCode ==1){
        SignupFragment.MyOnRequestPermissionResult(requestCode, permissions, grantResults);
    }
}

它正在工作...


0

验证两个PERMISSION_REQUEST_CODEonRequestPermissionsResult和里面的Fragment包含相同的值。


0

对于tragetSDK 28,SDK检查(> 23)和来自片段的请求权限将起作用。ActivityCompat.requestPermissions失败(如果将请求代码设置为65536以下,则会出现权限对话框,并且如果用户允许该权限,则会提供该权限,但不会发生回调。但是,如果设置为65536以上,则ActivityCompat.requestPermissions将立即失败。我不知道此逻辑背后的原因。可能是错误或故意的。

工作代码:

  if (Build.VERSION.SDK_INT >= 23) {
                        requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_ACCESS_REQUEST);
                    }

您不需要进行版本检查。在低于23的版本中,它将仅返回“已授予权限”值。开发人员的选择:为简单起见,避免使用“ if”块,或者在不需要时避免请求调用
Psest328 '18


0

我遇到过同样的问题。您的片段可以从活动布局中初始化。像那样:

main_activty.xml

<fragment
    android:id="@+id/fragment"
    android:name="com.exampe.SomeFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

当我FragmentTransaction改用时,这个问题已为我解决


0

在23以下的API中,您可以在活动中创建一个接口,然后在子片段中实现该接口,当活动中获得权限请求结果时,将其传递到片段中已实现的接口。这很简单:)


0

您可以调用下面的Fragment方法

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
                doActionBecauseNowYouCanBro();
            } else {
                // Explain to the user that the feature is unavailable because
                // the features requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
                showWhyRequestPermissionsAndDontBlockUserItsCalledManners();
            }
            return;
    }
    // Other 'case' lines to check for other
    // permissions this app might request.

}

-5

此问题实际上是由NestedFragments引起的。基本上,大多数片段我们都扩展了HostedFragment,而HostedFragment又扩展了CompatFragment。拥有这些嵌套片段会导致问题,最终由项目中的另一个开发人员解决。

他正在做一些低级的工作,例如位切换以使它工作,所以我不太确定实际的最终解决方案


3
而不是复制一个答案,你可以只提供一个链接- stackoverflow.com/a/33081173/630833
jayeffkay
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.