我有一个带有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)
在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
嵌套片段中的onRequestPermissionsResult永远不会被调用(在我的情况下,它会返回HomeActivity)但是我没关系,我会手动通知片段结果。
但问题是,当我在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
但是在 FragmetnA 或 NestedFragmentA 中,当我从嵌套片段请求时,返回HomeActivity的requestCode已更改
FragmentA
// 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
NestedFragmentA
// 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
您是否知道会导致此问题的原因?
答案 0 :(得分:14)
我不会否认"Nested Fragments do not receive request permissions (onRequestPermissionsResult()) callback"
。
但我在这里要做的是解释你所观察到的关于不同的&#34;怪异的&#34;在片段和嵌套片段的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)
仅在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 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)
<强> BUT 强>
使用转换后的请求代码 -
fragment.mIndex
因此更改的请求代码为 -
FragmentA
其中 (((0 + 1) << 8) + (102 & 0xff)) which computes to 358
是片段级别。因此,对于立即片段(直接意味着容器活动的子代),它将是&#34; 0&#34;
对于直接嵌套的片段(意味着片段内的片段),它将是&#34; 1&#34;并且它会根据你的片段嵌套的深度而增加。
在我们的案例中,对于NestedFragmentA
,请求代码更改为
(((1 + 1) << 8) + (102 & 0xff)) which computes to 614
对于ActivityCompat.requestPermissions()
,请求代码更改为
ActivityCompat.requestPermissions()
现在我们知道请求代码的更改位置。让我们从onRequestPermissionsResult()
继续。因此我们知道onRequestPermissionsResult()
因为我们使用此方法来请求活动的权限。
此外,我们知道这将执行一些操作,并且将向用户显示权限弹出窗口以接受/拒绝所请求的权限。
现在我们来ActivityCompat.requestPermissions()
。当用户接受/拒绝时,将调用容器活动的FragmentA
,因为最终调用了 req code ::358
。
我们假设您接受/拒绝super.onRequestPermissionsResult(requestCode, permissions, grantResults);
的许可,以便您获取日志 -
FragmentActivity's onRequestPermissionsResult()
之后
frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
将调用frag.onRequestPermissionsResult()
,然后执行一些验证并调用
requestCode
Bow,您可以看到358
中传递的请求代码不同。 &0xff
为102
,358
之后又为HomeActivity's onRequestPermissionsResult()
。
瞧!!
这意味着虽然我们在FragmentA's onRequestPermissionsResult()
中获得了不同的请求代码(102
),但我们使用原始请求代码(FragmentA
)调用 req code ::358
因此,我们将从NestedFragmentA
-
NestedFragmentA
现在来HomeActivity
。我们假设您接受/拒绝 req code ::614
的许可,这样您就可以登录onRequestPermissionsResult()
-
NestedFragmentA's onRequestPermissionsResult()
但我们知道不会为嵌套片段调用requestPermissions()
,因此我们无法在requestPermissions()
我想我已经解释了为什么我们在片段和嵌套片段所做的onRequestPermissionsResult()
的容器活动中获得不同的请求代码的原因。
所以我要说的是,对于那些没有从片段嵌套requestPermissions()
的片段,只在那里实现STRSPLIT(string, regex, limit)
而不是在容器活动中。
对于嵌套片段,只有[\s,]+
才能获得来自父片段的嵌套片段所需的权限。这似乎是唯一的解决方法。