Mahendra Chhimwal
Mahendra Chhimwal

Reputation: 1818

Android Run time permission api "requestPermission()" design

As Android added last year , Run time permission thing in Android API version 23 and above, I have a query regarding

ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

And

   ActivityCompat.requestPermissions(new String[]Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

api for requesting permission. In above library either we have to provide Activity instance which should have implemented ActivityCompat.OnRequestPermissionsResultCallback interface. Support version of fragment and AppcompatActivity, FragmentActivity have implemented this by default.

Why we need to provide the callback refrence in form of Activity or Fragment only? We could have design this API as

ActivityCompat.requestPermissions(context,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS,ActivityCompat.OnRequestPermissionsResultCallback callback);

I mean we have bound to provide a Activity or support version of Fragment. What if we want to check outside activity in any other simple class? Just a case I have a GeofenceManager class which needs Location permission and many Activities or classes need some information from this GeofenceManager singleton class.

Should I have to implement OnRequestPermissionsResultCallback in each of activities? I think it would be much better if the Api is in suggested design above. There must be some big reason in designing the API in that way. My little experience does not able to get it.

Upvotes: 2

Views: 708

Answers (2)

Mahendra Chhimwal
Mahendra Chhimwal

Reputation: 1818

I know it is a bit late to answer my own question, but I still think my answer will help this thread.

In Android, there are 5 types of process, based on priority in general. These are foreground processes, followed by any visible processes, service processes, background processes, and finally ‘empty’ processes.

The foreground process has the highest priority as in most cases the user is directly playing with these process's components, like Activity or foreground services. But our case falls in the second kind of process. A Visible process.

Note: The permission dialogs are not shown in the activity which requested permission. It is, in fact, an Activity!

There are situations where your activity can be visible but not in the foreground. A simple example is when the foreground activity starts a new activity with Dialog theme or a translucent activity. But Keep in mind though, just because you are visible does not mean you can’t be killed. If there is enough memory pressure from foreground processes, it is still possible that your visible process will be killed. From a user perspective, this means the visible activity behind the current activity is replaced with a black screen. Of course, if you’re properly recreating your activity, your process and Activity will be restored as soon as the foreground Activity is closed without any loss of data.

The fact that your activity and process can be killed even if visible is one of the reasons the startActivityForResult()+onActivityResult() and the requestPermissions()+onRequestPermissionsResult() flows don’t take callback class instances — if your whole process dies, so does every callback class instance. If you see libraries using a callback approach, realize that it will not be resilient to low memory pressure cases.

Note: Android only kills processes, not components. Always remember this.

That is one of the main reason why requestPermission() API in Android is designed the way it is, instead of the one mentioned in question by me.

Upvotes: 0

Budius
Budius

Reputation: 39836

All the AppCompat APIs are meant to be as easily as possible replaced by their native counterpart.

Said that the native android.app.Activity on API 23 implementation is a public final void requestPermissions method and a public void onRequestPermissionsResult callback.

So that how those gets translated to AppCompat. Having them as separate entities would certainly lead to a more flexible approach, but it would also lead to being unable on the future to deprecated the AppCompat as devices get updated.

You could argue why the API23 activity doesn't do the same, but that's just in general how Android always being and is their approach to everything, example onActivityResult

Furthermore those must be attached to the activity because an should only ever ask for permissions when it's in foreground.

edit:

Further thinking, there's another reason for it. Rotation! With the activity being destroyed and re-built during rotation, having a callback based on an interface can be very tricky.

The callback method need some type of context or carry further actions (go to the next activity, or load/read something from the newly granted permission). So if the coder pass the interface as an anonymous inner class or make its activity extend that interface and a rotation happen, it will leak the activity. Or the callback method would need to receive a context parameter, but then the framework would have to keep track on which activity is the current context to send back to the callback. All this would get very convoluted very fast. So a simply straight forward way of doing it is by making it an actual method of the activity.

Upvotes: 2

Related Questions