我有一个 targetSdkVersion = 23, compileSdkVersion = 23 的应用程序,主要 Activity 设置如下
- 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 中
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
}
我从@CommonsWare 阅读了这个答案,
https://stackoverflow.com/a/33170531/760363
嵌套 fragment 中的 onRequestPermissionsResult 永远不会被调用(在我的情况下,它的结果将返回到 HomeActivity)但我很好,我会手动通知 fragment 结果。
但问题是,当我在 HomeActivity 中请求许可时,一切正常。
首页 Activity
// 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
但在 fragment nA 或 嵌套 fragment A ,当我从嵌套 fragment 请求时,返回 HomeActivity 的 requestCode 发生了变化
fragment A
// Request permission from FragmentA
// Supply 102 as request code, get 358 back
@Override
public void clickAnotherThing(View v) {
requestPermissions(new String[]{HomeActivity.PERMISSION}, 102);
}
// Logcat
Logger: Request Code: 358 <<< INCORRECT
嵌套 fragment A
// Request permission from NestedFragmentA
// Supply 103 as request code, get 615 back
@Override
public void clickDifferentThing(View v) {
requestPermissions(new String[]{HomeActivity.PERMISSION}, 103);
}
// Logcat
Logger: Request Code: 615 <<< INCORRECT
你知道什么会导致这个问题吗?
最佳答案
我不会否定 "Nested Fragments do not receive request permissions (onRequestPermissionsResult()) callback"
的事实。 .
但我在这里要做的是解释您观察到的关于 requestPermissions()
的容器 Activity 中收到的不同“奇怪”请求代码的行为。由 fragment 和嵌套 fragment 组成。
为了解释这一点,让我们考虑你的例子 -
- 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)
实现
onRequestPermissionsResult()
仅在 HomeActivity, FragmentA and NestedFragmentA
为了更好地理解打印收到的请求代码的日志 @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
.让我们以位置权限为例 requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 102);
现在每当我们
requestPermissions()
从 fragment 或嵌套 fragment ,它调用Fragment class's requestPermissions()
进而调用 FragmentHostCallback's onRequestPermissionsFromFragment()
进而调用 FragmentActivity's requestPermissionsFromFragment()
.现在这里是您的请求代码的转换。验证您的请求代码后,它会调用
ActivityCompat's requestPermissions()
但是
使用转换后的请求代码 -
ActivityCompat.requestPermissions(this, permissions,((fragment.mIndex + 1) << 8) + (requestCode & 0xff));
所以更改后的请求代码是 -
((fragment.mIndex + 1) << 8) + (requestCode & 0xff)
在哪里
fragment.mIndex
是 fragment 级别。所以对于直接 fragment (直接表示容器 Activity 的子项),它将是“0”对于直接嵌套的 fragment (意味着 fragment 中的 fragment ),它将为“1”,并且它会根据 fragment 嵌套的深度而增加。
在我们的例子中,对于
FragmentA
, 请求代码更改为 (((0 + 1) << 8) + (102 & 0xff)) which computes to 358
对于
NestedFragmentA
, 请求代码更改为(((1 + 1) << 8) + (102 & 0xff)) which computes to 614
现在我们知道请求代码在哪里改变了。让我们从
ActivityCompat.requestPermissions()
继续.所以我们知道ActivityCompat.requestPermissions()
因为我们使用这种方法来请求 Activity 的权限。此外,我们知道这将执行一些操作,并且将向用户显示权限弹出窗口以接受/拒绝请求的权限。
现在我们来
onRequestPermissionsResult()
.当用户接受/拒绝时,onRequestPermissionsResult()
的容器 Activity 将被调用,因为最终 ActivityCompat.requestPermissions()
被称为。假设您接受/拒绝来自
FragmentA
的许可所以你会得到日志- req code ::358
在那之后
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
将调用
FragmentActivity's onRequestPermissionsResult()
依次执行一些验证和调用frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
低头可以看到
frag.onRequestPermissionsResult()
中传入的请求码是不同的。 requestCode
是 358
及之后 &0xff
它变成 102
再次。瞧!
这意味着尽管我们在
358
中获得了不同的请求代码 ( HomeActivity's onRequestPermissionsResult()
) ,但我们正在调用 FragmentA's onRequestPermissionsResult()
使用原始请求代码 (102
)所以我们将从
FragmentA
获取这些日志- req code ::358
现在来到
NestedFragmentA
.假设您接受/拒绝来自 NestedFragmentA
的许可所以你会得到HomeActivity
的登录- req code ::614
但我们知道
onRequestPermissionsResult()
不会为嵌套 fragment 调用,因此我们不会在 NestedFragmentA's onRequestPermissionsResult()
中获得任何日志我想我已经解释了我们在
requestPermissions()
的容器 Activity 中获得不同请求代码的原因。由 fragment 和嵌套 fragment 组成。所以我会说对于没有嵌套的 fragment
requestPermissions()
仅从 fragment 中执行 onRequestPermissionsResult()
仅存在于容器 Activity 中,而不存在于容器 Activity 中。对于嵌套 fragment ,应该
requestPermissions()
仅适用于来自父 fragment 的嵌套 fragment 所需的权限。看来这是唯一的解决方法。
关于android - 从 Fragment 请求权限时,在 Activity 的 onRequestPermissionsResult 中收到不正确的 resultCode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36170324/