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

Posted

技术标签:

【中文标题】如果在片段和活动中都定义了 onRequestPermissionsResult,则不会在片段中调用【英文标题】:onRequestPermissionsResult not being called in fragment if defined in both fragment and activity 【发布时间】:2016-06-29 14:16:17 【问题描述】:

我有一个片段,其中我有 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 方法,并且它被调用了。

我无法移除 Activity 的 onRequestPermissionsResult 方法,但想在我向 Fragment 请求权限时调用 Fragment 的 onRequestPermissionsResult 方法。 我怎样才能做到这一点?我在这里做错了什么吗,如果有人在这里有想法,请帮助我。

【问题讨论】:

参考这个链接run time permissions in fragment这是确切的解决方案 【参考方案1】:

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

我认为您混淆了片段和活动的方法。上个月我的项目也有类似的问题。请检查您是否最终有以下内容:

    在 AppCompatActivity 中使用方法 ActivityCompat.requestpermissions 在 v4 支持片段中,您应该使用 requestpermissions 关键是如果您在片段中调用 AppcompatActivity.requestpermissions 则回调将进入活动而不是片段 确保从活动的onRequestPermissionsResult 调用super.onRequestPermissionsResult

看看有没有帮助。

【讨论】:

只是仔细检查确保您的活动中设置了 super.onrequestpermissionresult 当我使用requestpermissions请求权限时,在活动的onrequestpermissionresult中添加super.onrequestpermissionresult会调用片段的onrequestpermissionresult。现在工作正常,非常感谢.. :) 活动回调中缺少 super.onrequestpermissionresult,导致我的片段回调没有被调用 requestPermissions() 需要 API 级别 23。是否有其他解决方案向后兼容 API 级别 21? @msc87 1.在onRequestPermissionsResult的activity和fragment中,第一行应该是:super.onRequestPermissionsResult(requestCode, permissions, grantResults); 2.in你所在的fragment识别未授予的权限,只需像这样调用 requestPermission 方法:requestPermissions(new String[]Manifest.permission.CALL_PHONE, MY_PERMISSIONS_REQUEST_CALL_PHONE);【参考方案2】:

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

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

【讨论】:

您可以提供一个链接,而不是复制答案 - ***.com/a/33081173/630833【参考方案3】:
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();
 
 

更改权限

【讨论】:

您好 user2002721;您的代码可能是正确的,但在某些上下文中它会做出更好的答案;例如,您可以解释这个提议的更改如何以及为什么会解决提问者的问题,可能包括指向相关文档的链接。这将使它对他们更有用,对正在寻找类似问题的解决方案的其他网站读者也更有用。 如果您尝试访问 grantResults 的索引 0 而不先检查长度,程序可能会抛出数组越界异常。它发生在我的程序中。我将 grantResults 的 if 语句分隔为内部 if 语句以防止这种情况发生,现在它工作正常。【参考方案4】:

验证PERMISSION_REQUEST_CODE inonRequestPermissionsResult 和 yourFragment 内部是否包含相同的值。

【讨论】:

【参考方案5】:

片段上的方法 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"

【讨论】:

FragmentCompat 已从 27.1.0 版本中弃用【参考方案6】:

我向片段请求位置许可,在片段中,我需要更改:

            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。

【讨论】:

像魅力一样工作:) 它不能与 kotlin 一起工作,你能帮我吗?这里也使用了这个 requestPermissions(context as Activity ,permissionList.toTypedArray(), MY_PERMISSIONS_REQUEST) 谢谢 :),你节省了我的时间【参考方案7】:

对于 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”块或在不需要时避免请求调用【参考方案8】:

这个接受的答案对我不起作用,所以我找到了自己的解决方案,解释如下:

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);
    

它正在工作......

【讨论】:

【参考方案9】:

如果您使用 Kotlin,您应该明确指定您正在调用片段方法,而不是活动

 fragment.requestPermissions(permissions, PERMISSIONS_CODE);

Android M Permissions: onRequestPermissionsResult() not being called

Request runtime permissions from v4.Fragment and have callback go to Fragment?

【讨论】:

【参考方案10】:

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

在 AppCompatActivity 中,应该使用 ActivityCompat.requestPermissions; 在 android.support.v4.app.Fragment 中,你应该简单地使用 requestPermissions(这是 android.support.v4.app.Fragment 的一个实例方法) 如果你在片段中调用 ActivityCompat.requestPermissions,onRequestPermissionsResult 回调会在 Activity 而不是片段上调用。

requestPermissions(permissions, PERMISSIONS_CODE);

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

所以基本概念是,如果你在一个 Activity 中,那么调用

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

如果在 Fragment 中,只需调用

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

作为参考,我已经从这个链接https://www.coderzheaven.com/2016/10/12/onrequestpermissionsresult-not-called-on-fragments/得到了答案

【讨论】:

【参考方案11】:

我有同样的问题。您的片段可以从活动布局初始化。 像这样:

main_activty.xml

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

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

【讨论】:

【参考方案12】:

在低于 23 的 API 中,您可以在 Activity 中创建一个接口,然后在子 Fragment 中实现它,当您获得权限请求结果时,Activity 将其传递给 Fragment 中实现的接口。 就这么简单:)

【讨论】:

【参考方案13】:

改变这个:

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

到这个:

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

【讨论】:

下一个是在fragment中使用(onRequestPermissionsResult在fragment中调用),ActivityCompat版本是在onRequestPermissionsResult在Activity中时使用的。【参考方案14】:

你可以调用下面的 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.


【讨论】:

【参考方案15】:

在片段中,您不应将 ActivityCompat 用于 requestPermissions,您只需使用 requestPermissions 并在方法中传递两个参数。

    权限字符串 请求代码。

对于经验:

 requestPermissions(new String[]android.Manifest.permission.READ_EXTERNAL_STORAGE, STORAGE_PERMISSION_CODE);

【讨论】:

【参考方案16】:

当我们从片段中请求权限时,android会更改我们的requestCode

requestPermissionsFromFragment

这是来自 FragmetActivity 的代码:

 void requestPermissionsFromFragment(@NonNull Fragment fragment, @NonNull String[] permissions,
        int requestCode) 
    if (requestCode == -1) 
        ActivityCompat.requestPermissions(this, permissions, requestCode);
        return;
    
    checkForValidRequestCode(requestCode);
    try 
        mRequestedPermissionsFromFragment = true;
        int requestIndex = allocateRequestIndex(fragment);
        ActivityCompat.requestPermissions(this, permissions,
                ((requestIndex + 1) << 16) + (requestCode & 0xffff));
     finally 
        mRequestedPermissionsFromFragment = false;
    

你可以看到 (requestIndex + 1) 以及何时

onRequestPermissionsResult

android 检查请求代码是否是从 Fragment 发送的,它将结果传递给 Fragment 否则它不会将它传递给 Fragment 这是来自 FragmentActivity 的代码:

enter code here@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
        @NonNull int[] grantResults) 
    mFragments.noteStateNotSaved();
    int index = (requestCode >> 16) & 0xffff;
    if (index != 0) 
        index--;

        String who = mPendingFragmentActivityResults.get(index);
        mPendingFragmentActivityResults.remove(index);
        if (who == null) 
            Log.w(TAG, "Activity result delivered for unknown Fragment.");
            return;
        
        Fragment frag = mFragments.findFragmentByWho(who);
        if (frag == null) 
            Log.w(TAG, "Activity result no fragment exists for who: " + who);
         else 
            frag.onRequestPermissionsResult(requestCode & 0xffff, permissions, grantResults);
        
    

总结

因此,如果您调用 activity.requestPermission() 或 ActivityCompat.requestPermission,它会将结果传递给您的 Activity,如果您调用 fragment.requestPermission(),它会将结果传递给您的 Activity AND片段

【讨论】:

【参考方案17】:

如果你想进入你的 Fragment 的onPermissionResult,你必须调用Fragment.requestPermission()

【讨论】:

以上是关于如果在片段和活动中都定义了 onRequestPermissionsResult,则不会在片段中调用的主要内容,如果未能解决你的问题,请参考以下文章

关于其活动的片段生命周期

实现一个可以从每个片段和活动中访问的按钮

多次调用片段 onCreateView

从活动更新视图页面中片段中的列表视图

在片段活动中显示自定义对话框

在片段和活动之间导航