Android 在活动'中接收不正确的结果代码;s OnRequestPermissions从片段请求权限时的结果

Android 在活动'中接收不正确的结果代码;s OnRequestPermissions从片段请求权限时的结果,android,android-fragments,android-permissions,android-6.0-marshmallow,Android,Android Fragments,Android Permissions,Android 6.0 Marshmallow,我有一个targetSdkVersion=23的应用程序,compileSdkVersion=23的主要活动设置如下 - HomeActivity (AppCompatActivity) - FragmentA (V4 Fragment) - ViewPager - NestedFragmentA (V4 Fragment) - NestedFragmentB (v4 Fragment) - NestedFragmentC (v4 Fragment

我有一个targetSdkVersion=23的应用程序,compileSdkVersion=23的主要活动设置如下

- HomeActivity (AppCompatActivity)
  - FragmentA (V4 Fragment)
    - ViewPager
      - NestedFragmentA (V4 Fragment)
      - NestedFragmentB (v4 Fragment)
      - NestedFragmentC (v4 Fragment)
      - NestedFragmentD (v4 Fragment)
  - Fragment B (V4 Fragment)
  - Fragment C (V4 Fragment)
在家庭活动中

public static final String PERMISSION = Manifest.permission.WRITE_EXTERNAL_STORAGE

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    Log.i("Logger", "Request Code: " + String.valueOf(requestCode));

    // Handle permission request result
}
我从@commonware上读到了这个答案

嵌套片段中的onRequestPermissionsResult永远不会被调用(在我的例子中,它的结果将返回到HomeActivity),但我可以接受,我将手动通知片段结果

但问题是,当我在HomeActivity中请求许可时,一切正常

家庭活动

// Request permission from HomeActivity
// Supply 101 as request code, get 101 back

@Override
public void clickSomething(View v) {
    requestPermissions(new String[]{PERMISSION}, 101);
}

// Logcat
Logger: Request Code: 101 <<< CORRECT
//从HomeActivity请求权限
//提供101作为请求代码,返回101
@凌驾
公共空间单击某物(视图v){
requestPermissions(新字符串[]{PERMISSION},101);
}
//Logcat

Logger:Request Code:101我不会否认这样一个事实,“嵌套片段不接收请求权限(onRequestPermissionsResult())回调”

但我在这里要做的是解释您观察到的关于容器活动中收到的不同“奇怪”请求代码的行为,这些代码是由片段和嵌套片段生成的
requestPermissions()

为了解释这一点,让我们考虑一下你的例子-

- HomeActivity (AppCompatActivity)
  - FragmentA (V4 Fragment)
    - ViewPager
      - NestedFragmentA (V4 Fragment)
      - NestedFragmentB (v4 Fragment)
      - NestedFragmentC (v4 Fragment)
      - NestedFragmentD (v4 Fragment)
  - Fragment B (V4 Fragment)
  - Fragment C (V4 Fragment)
仅在
HomeActivity、FragmentA和NestedFragmentA中实现
onRequestPermissionsResult()
,以便更好地了解打印收到的请求代码的日志

    @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            Log.d("debug", "req code :: " + requestCode);     
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
还可以从
FragmentA
NestedFragmentA
请求某些权限。让我们看一下位置权限的exmaple

 requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 102); 
现在,每当我们从片段或嵌套片段中调用
requestPermissions()
时,它就会调用
Fragment类的requestPermissions()
,后者依次调用
FragmentHostCallback的onRequestPermissionsFromFragment()
,后者又调用
FragmentActivity的requestPermissionsFromFragment()
。现在这里是请求代码的转换。 验证您的请求代码后,它将调用

ActivityCompat's requestPermissions()
但是

使用转换后的请求代码-

ActivityCompat.requestPermissions(this, permissions,((fragment.mIndex + 1) << 8) + (requestCode & 0xff));
对于
NestedFragmentA
,请求将代码更改为

 (((0 + 1) << 8) + (102 & 0xff)) which computes to 358
(((1 + 1) << 8) + (102 & 0xff)) which computes to 614
之后

super.onRequestPermissionsResult(requestCode, permissions, grantResults);
将调用FragmentActivity的onRequestPermissionsResult()
,然后执行一些验证和调用

frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
您可以看到在
frag中传递的请求代码。onRequestPermissionsResult()
不同
requestCode
358
,在
&0xff
之后,它再次变成
102
。 瞧!! 这意味着,尽管我们在
HomeActivity的onRequestPermissionsResult()
中获得了不同的请求代码(
358
),但我们正在使用原始请求代码(
102
)调用
FragmentA的onRequestPermissionsResult()
) 因此,我们将从
FragmentA
-

 req code ::358
现在来看
NestedFragmentA
。假设您接受/拒绝来自
NestedFragmentA
的权限,这样您就可以登录
HomeActivity
-

 req code ::614
但是我们知道嵌套片段不会调用
onRequestPermissionsResult()
,因此我们不会在
NestedFragmentA的onRequestPermissionsResult()中获得任何日志

我想我已经解释了为什么我们在容器活动中为片段和嵌套片段生成的
requestPermissions()
获取不同的请求代码

因此,我要说的是,对于没有嵌套的片段
requestPermissions()
,只从片段中执行
onRequestPermissionsResult()
,而不是在容器活动中。
对于嵌套片段,应该
requestPermissions()
仅从父片段获取嵌套片段所需的权限。这似乎是唯一的解决办法。

您不能从嵌套的frgament调用requestpermission…请访问此进一步的问题,1。)我可以说,如果我不重写onRequestPermissionsResult,或者如果我调用超级容器内活动,碎片将收到正确的代码吗?2.)Activity和ActivityCompat的行为是否相同?1。是的。ActivityCompat.requestPermissions()最终调用activity.requestPermissions()
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
 req code ::358
 req code ::614