Skip to content
This repository was archived by the owner on Mar 24, 2020. It is now read-only.

Commit 015019c

Browse files
author
Miłosz Lewandowski
committed
Fix for onRequestPermissionsResult() not called for child fragments.
The solution is very similar to the one for onActivityResult. Instead of iterating over fragments in FragmentActivity, pass the execution of onRequestPermissionsResult() to FragmentManager, which maintains list of permissions requests. Either fragment is found and its onRequestPermissionsResult() callback is called, or child FragmentManager is asked to process the result.
1 parent 46935c3 commit 015019c

2 files changed

Lines changed: 147 additions & 17 deletions

File tree

src/java/android/support/v4/app/FragmentActivity.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -804,22 +804,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
804804
@NonNull int[] grantResults) {
805805
int index = (requestCode>>8)&0xff;
806806
if (index != 0) {
807-
index--;
808-
final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
809-
if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
810-
Log.w(TAG, "Activity result fragment index out of range: 0x"
811-
+ Integer.toHexString(requestCode));
812-
return;
813-
}
814-
final List<Fragment> activeFragments =
815-
mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
816-
Fragment frag = activeFragments.get(index);
817-
if (frag == null) {
818-
Log.w(TAG, "Activity result no fragment exists for index: 0x"
819-
+ Integer.toHexString(requestCode));
820-
} else {
821-
frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
822-
}
807+
getSupportFragmentManager().onRequestPermissionsResult(requestCode, permissions, grantResults);
823808
}
824809
}
825810

@@ -852,7 +837,7 @@ private void requestPermissionsFromFragment(Fragment fragment, String[] permissi
852837
}
853838
mRequestedPermissionsFromFragment = true;
854839
ActivityCompat.requestPermissions(this, permissions,
855-
((fragment.mIndex + 1) << 8) + (requestCode & 0xff));
840+
(fragment.getFragmentManager().getPermissionsRequestCode(fragment)<<8) + (requestCode&0xff));
856841
}
857842

858843
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {

src/java/android/support/v4/app/FragmentManager.java

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import android.os.Parcelable;
2929
import android.support.annotation.CallSuper;
3030
import android.support.annotation.IdRes;
31+
import android.support.annotation.NonNull;
3132
import android.support.annotation.StringRes;
3233
import android.support.v4.util.DebugUtils;
3334
import android.support.v4.util.LogWriter;
@@ -366,13 +367,18 @@ public static void enableDebugLogging(boolean enabled) {
366367

367368
abstract int getActivityRequestCode(Fragment fragment);
368369
abstract void onActivityResult(int requestCode, int resultCode, Intent data);
370+
371+
abstract int getPermissionsRequestCode(Fragment fragment);
372+
abstract void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
373+
@NonNull int[] grantResults);
369374
}
370375

371376
final class FragmentManagerState implements Parcelable {
372377
FragmentState[] mActive;
373378
int[] mAdded;
374379
BackStackState[] mBackStack;
375380
ActivityRequest[] mPendingActivityRequests;
381+
PermissionsRequest[] mPendingPermissionsRequests;
376382

377383
public FragmentManagerState() {
378384
}
@@ -382,6 +388,7 @@ public FragmentManagerState(Parcel in) {
382388
mAdded = in.createIntArray();
383389
mBackStack = in.createTypedArray(BackStackState.CREATOR);
384390
mPendingActivityRequests = in.createTypedArray(ActivityRequest.CREATOR);
391+
mPendingPermissionsRequests = in.createTypedArray(PermissionsRequest.CREATOR);
385392
}
386393

387394
public int describeContents() {
@@ -393,6 +400,7 @@ public void writeToParcel(Parcel dest, int flags) {
393400
dest.writeIntArray(mAdded);
394401
dest.writeTypedArray(mBackStack, flags);
395402
dest.writeTypedArray(mPendingActivityRequests, flags);
403+
dest.writeTypedArray(mPendingPermissionsRequests, flags);
396404
}
397405

398406
public static final Parcelable.Creator<FragmentManagerState> CREATOR
@@ -448,6 +456,47 @@ public ActivityRequest[] newArray(int size) {
448456
};
449457
}
450458

459+
final class PermissionsRequest implements Parcelable {
460+
final int mFragmentIndex;
461+
final int mRequestIndex;
462+
final int mChildRequestIndex;
463+
464+
PermissionsRequest(int fragmentIndex, int requestIndex, int childRequestIndex) {
465+
mFragmentIndex = fragmentIndex;
466+
mRequestIndex = requestIndex;
467+
mChildRequestIndex = childRequestIndex;
468+
}
469+
470+
PermissionsRequest(Parcel in) {
471+
mFragmentIndex = in.readInt();
472+
mRequestIndex = in.readInt();
473+
mChildRequestIndex = in.readInt();
474+
}
475+
476+
@Override
477+
public int describeContents() {
478+
return 0;
479+
}
480+
481+
@Override
482+
public void writeToParcel(Parcel dest, int flags) {
483+
dest.writeInt(mFragmentIndex);
484+
dest.writeInt(mRequestIndex);
485+
dest.writeInt(mChildRequestIndex);
486+
}
487+
488+
public static final Parcelable.Creator<PermissionsRequest> CREATOR
489+
= new Parcelable.Creator<PermissionsRequest>() {
490+
public PermissionsRequest createFromParcel(Parcel in) {
491+
return new PermissionsRequest(in);
492+
}
493+
494+
public PermissionsRequest[] newArray(int size) {
495+
return new PermissionsRequest[size];
496+
}
497+
};
498+
}
499+
451500
/**
452501
* Container for fragments associated with an activity.
453502
*/
@@ -537,6 +586,8 @@ public void onAnimationRepeat(Animation animation) {
537586
ArrayList<Fragment> mCreatedMenus;
538587
ArrayList<ActivityRequest> mPendingActivityRequests;
539588
ArrayList<Integer> mAvailRequestIndices;
589+
ArrayList<PermissionsRequest> mPendingPermissionsRequests;
590+
ArrayList<Integer> mAvailPermissionsRequestIndices;
540591

541592
// Must be accessed while locked.
542593
ArrayList<BackStackRecord> mBackStackIndices;
@@ -945,6 +996,77 @@ private boolean dispatchOnActivityResult(int requestIndex, int requestCode, int
945996
}
946997
}
947998

999+
@Override
1000+
int getPermissionsRequestCode(Fragment fragment) {
1001+
return getPermissionsRequestIndex(fragment, -1) + 1;
1002+
}
1003+
1004+
private int getPermissionsRequestIndex(Fragment fragment, int childRequestIndex) {
1005+
final PermissionsRequest request;
1006+
1007+
if (mAvailPermissionsRequestIndices == null || mAvailPermissionsRequestIndices.isEmpty()) {
1008+
if (mPendingPermissionsRequests == null) {
1009+
mPendingPermissionsRequests = new ArrayList<PermissionsRequest>();
1010+
}
1011+
1012+
if (mPendingPermissionsRequests.size() > 0xff) {
1013+
throw new IllegalStateException("Over 0xff pending permissions requests in " + fragment);
1014+
}
1015+
1016+
request = new PermissionsRequest(fragment.mIndex, mPendingPermissionsRequests.size(), childRequestIndex);
1017+
mPendingPermissionsRequests.add(request);
1018+
} else {
1019+
request = new PermissionsRequest(fragment.mIndex, mAvailPermissionsRequestIndices.remove(mAvailPermissionsRequestIndices.size() - 1), childRequestIndex);
1020+
mPendingPermissionsRequests.set(request.mRequestIndex, request);
1021+
}
1022+
1023+
Fragment parent = fragment.getParentFragment();
1024+
if (parent != null) {
1025+
return parent.mFragmentManager.getPermissionsRequestIndex(parent, request.mRequestIndex);
1026+
} else {
1027+
return request.mRequestIndex;
1028+
}
1029+
}
1030+
1031+
@Override
1032+
void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
1033+
@NonNull int[] grantResults) {
1034+
if (!dispatchOnRequestPermissionsResult((requestCode>>8) - 1, requestCode&0xff,
1035+
permissions, grantResults)) {
1036+
Log.w(TAG, "No fragment exists for requestCode: 0x" + Integer.toHexString(requestCode));
1037+
}
1038+
}
1039+
1040+
private boolean dispatchOnRequestPermissionsResult(int requestIndex, int requestCode,
1041+
@NonNull String[] permissions,
1042+
@NonNull int[] grantResults) {
1043+
if (!checkElement(mPendingPermissionsRequests, requestIndex)) {
1044+
return false;
1045+
}
1046+
1047+
PermissionsRequest resultRequest = mPendingPermissionsRequests.get(requestIndex);
1048+
if (!checkElement(mActive, resultRequest.mFragmentIndex)) {
1049+
return false;
1050+
}
1051+
1052+
Fragment fragment = mActive.get(resultRequest.mFragmentIndex);
1053+
if (resultRequest.mChildRequestIndex != -1) {
1054+
mPendingPermissionsRequests.set(requestIndex, null);
1055+
if (mAvailPermissionsRequestIndices == null) {
1056+
mAvailPermissionsRequestIndices = new ArrayList<Integer>();
1057+
}
1058+
mAvailPermissionsRequestIndices.add(requestIndex);
1059+
1060+
return fragment.mChildFragmentManager.dispatchOnRequestPermissionsResult(
1061+
resultRequest.mChildRequestIndex,
1062+
requestCode, permissions, grantResults
1063+
);
1064+
} else {
1065+
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
1066+
return true;
1067+
}
1068+
}
1069+
9481070
private boolean checkElement(ArrayList<?> list, int index) {
9491071
return list != null && index < list.size() && list.get(index) != null;
9501072
}
@@ -2028,11 +2150,18 @@ Parcelable saveAllState() {
20282150
pendingActivityRequests = mPendingActivityRequests.toArray(new ActivityRequest[mPendingActivityRequests.size()]);
20292151
}
20302152

2153+
// Save pending permissions requests
2154+
PermissionsRequest[] pendingPermissionsRequests = null;
2155+
if (mPendingPermissionsRequests != null) {
2156+
pendingPermissionsRequests = mPendingPermissionsRequests.toArray(new PermissionsRequest[mPendingPermissionsRequests.size()]);
2157+
}
2158+
20312159
FragmentManagerState fms = new FragmentManagerState();
20322160
fms.mActive = active;
20332161
fms.mAdded = added;
20342162
fms.mBackStack = backStack;
20352163
fms.mPendingActivityRequests = pendingActivityRequests;
2164+
fms.mPendingPermissionsRequests = pendingPermissionsRequests;
20362165
return fms;
20372166
}
20382167

@@ -2163,6 +2292,22 @@ void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
21632292
}
21642293
mPendingActivityRequests = new ArrayList<ActivityRequest>(Arrays.asList(fms.mPendingActivityRequests));
21652294
}
2295+
2296+
// Restore pending permissions requests
2297+
if (fms.mPendingPermissionsRequests != null) {
2298+
mPendingPermissionsRequests = new ArrayList<PermissionsRequest>();
2299+
if (mAvailPermissionsRequestIndices != null) {
2300+
mAvailPermissionsRequestIndices.clear();
2301+
} else {
2302+
mAvailPermissionsRequestIndices = new ArrayList<Integer>();
2303+
}
2304+
for (int i=0; i<fms.mPendingPermissionsRequests.length; i++) {
2305+
if (fms.mPendingPermissionsRequests[i] == null) {
2306+
mAvailPermissionsRequestIndices.add(i);
2307+
}
2308+
}
2309+
mPendingPermissionsRequests = new ArrayList<PermissionsRequest>(Arrays.asList(fms.mPendingPermissionsRequests));
2310+
}
21662311
}
21672312

21682313
public void attachController(FragmentHostCallback host,

0 commit comments

Comments
 (0)