Android Run time permission api "requestPermission()" design - android

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.

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.

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.

Related

Is it safe to use the ApplicationContext for a Dialog?

I'm running an application that generates a dialog alert from within a Fragment as a network callback. This requires you to pass in an available Context reference; since I'm using Fragments, I use getActivity(). Due to the network-dependent nature of the callback, getActivity() can sometimes return null. This crashes my code.
To work around this error, I was hoping to supply the ApplicationContext to the dialog instead. It is a singleton that persists for the lifetime of the application, so I know it won't be withdrawn. In addition, the Dialog's content is with regards to payment confirmation, so I believe there's reasonable scope for it to be displayed without a strict relationship to a certain Window.
Is this a safe implementation? Am I avoiding the inevitable, and should move to a more robust pattern altogether?
Is this a safe implementation?
IMHO, no.
Tactically, I would expect your app to crash in some situations (e.g., your app is in the background at the time the network I/O completes), and I would expect your dialog to not necessarily honor the appropriate theme. Since it seems like your "dialog" is not tied to an activity, it should be an activity, in the form of a dialog-themed activity. That solves your reliability problem and your theme problem, though there is still the possibility that you display a dialog(-themed activity) while the user is in some other app, if your network I/O takes longer than you anticipate.
Strategically, it seems like you care about the results of your network I/O regardless of what happens in the UI layer of your app. In that case, your UI layer of your app should not be the one directly receiving the results of the network I/O, and it feels like your fragment is doing that right now. Use something that is decoupled from your UI (IntentService, JobService, bare thread, ThreadPoolExecutor) for managing the network I/O. Have it use an event bus (LocalBroadcastManager, greenrobot's EventBus) to tell the UI layer that the network I/O completed, and if the UI layer does not respond to the event (because it is in the background and you only pay attention to events when the UI is visible), raise a Notification or do something else subtle to let the user know about the results.
You have to use an Activity as Context for your Dialog, because Dialog is a component, that expects the UI context. So before showing the dialog, you can check if the current fragment is currently added to its activity using the isAdded() method:
if (isAdded()) {
showDialog();
}

Recommended design approach for web service downloading/importing within app

My app needs to initially download data from two different web services (JSON) and import them into it's local database (Realm). I have two activities that need to display data from these web services. The first one (HomeActivity) is the initial activity that the app loads. The second one (LineupActivity) is created when navigating to it from the HomeActivity.
Currently, I've created an Application class (extending Application) in order to handle the web service downloading and importing. In it's onCreate(), it calls two methods, which are AsyncTasks that download and import each web service.
The reason I've added this download/import process into the Application class is for 2 reasons:
I want all the app data to be downloaded as soon as possible, so
when navigating to the second activity it doesn't need to initiate
another download.
Both these activities have swipe to refresh. They call each respective method in the Application class to re-download/import the
web service data.
Have I approached this incorrectly? Should I move the web service download/import logic out of the Application class? Also, does the onCreate() of the Application class get called more than once? Meaning, I know that it only gets called only once in the application's lifecycle, but does the Android OS eventually kill an app and have it call the onCreate() in the Application class when starting it again? I want the app to download fresh data upon startup, but not every time the user brings the app into focus.
Have I approached this incorrectly?
"Incorrectly" is a very relative term in this context.
Metaphorically, its like the context is never null but that doesn't determine boolean incorrect is true or false.
Should I move the web service download/import logic out of the Application class?
I would say Yes, as the download logic would not be related to the O.S. and the app being alive in its memory. Your requirement does not seem complex. Service would be necessary if the downloads are huge chunks of data, and if its not necessary, don't do it.
Also, does the onCreate() of the Application class get called more than once? Meaning, I know that it only gets called only once in the application's lifecycle...Application class when starting it again?
No, it won't be called more than once without app being killed and restarted. And what your are saying is correct, but for your requirement, there are probably more efficient and lighter ways to do it rather than combining it with an Application class.
For the rest of the logic, you could implement Asynctasks as a separate class and implement interfaces which are the callbacks of the result of your task. This would help in Swipe-to-refresh functionality.
In terms of documentation reference, Application class
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way.
Your case seems exactly that.
One thing you need to decide is When, how often do you need to refresh/download the data. For only start-up of the app or once daily, you can store date/day in SharedPreferences and check the value in onResume() of your Activity.
You can also implement inheritance with a Base Activity with the necessary download check logic in it and extend your classes. A Splash Screen would always help to initiate the downloads.
I suppose you could approach this anyway you want, though I like to implement one of the three options mentioned here: https://dl.google.com/googleio/2010/android-developing-RESTful-android-apps.pdf.
The presentation itself can be found here: https://www.youtube.com/watch?v=xHXn3Kg2IQE.
This does however not mention how you should sync on startup. But you could just set a SharedPreference in the application class and then use one of the patterns to sync in the background.
I'd recommend you instead of using Application to download your stuff to use a Service. If by any reason your app gets killed by the OS your dl's will never complete. Using a Service it will.
Also, you can use a Broadcast to your activity to signalize that the service has completed downloading and taking the necessary following steps.
first: I think it's bad to place the download at appliaction onCreate
as stated in documentation
Called when the application is starting, before any activity, service,
or receiver objects (excluding content providers) have been created.
Implementations should be as quick as possible (for example using lazy
initialization of state) since the time spent in this function
directly impacts the performance of starting the first activity,
service, or receiver in a process. If you override this method, be
sure to call super.onCreate().
pay attention to this part
Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity
so any delay in download or import may cause the first activity to be delayed.
and the behavior is not clear, a black screen maybe?
Second suggestions for download/import:
1- use an AsyncTask in the first activity, where you display a small progress bar indicating the download/import process or even block the whole UI until completed (based on your business)
2- add a splash screen while downloading the data
regarding fresh data, you can store a timestamp, last_updated
and before starting the download/import process, check that value, if less than your accepted value (say 1 hour) don't start the download/import.
finally, regarding onCreate() call, i think it's not called everytime, only when app is re-created, like 1st run after reboot, or after being killed or forced close.

Is there a way to create a controlling instance that controls several activities of my app?

I work on a project that has several developers.
We work on one rather large app.
Every developer has several activities that can be seen as sub-apps of the whole main-app.
I do realize, that this may not be the best design, but it exists and we have to handle it somehow.
Now the main issue is, that we need a master, that is always active and checks I/Os etc and that can give out status changes to every sub-app/activity. Something like "we just lost internet connection" etc.
Right now, that master is a singleton, that is first instantiated by the launcher activity and that every activity/sub-app can register to by passing the appropriate interfaces depending on what updates the activity would like to receive.
This is working, however it doesn’t feel right, because the singleton needs context to access system resources to determine system stati like internet or gps. Should the singleton be killed by OS, than a simple "getInstance" wouldn’t do much good, because the singleton would somehow need to acquire a context. I've read about extending the Application class and creating a static member context there, but this variable had to be volatile AND its possible that it returns null if the entire app is in some restart-after-crash/kill state. It doesn’t feel safe.
In addition, there should also be a possibility that the master somehow opens a user-dialog to display warnings etc to the user. Those warnings should look the same across the entire app and no dev should have to worry about when or why it suddenly pops up. Right now, those messages appear as custom toasts that overlay everything. Of course they require context and if the app is about to close there could be a problem.
All in all, that’s the mess we are in and I’m looking for a solution.
So how do I create a safe master object or activity (or even service ?!) that can pass info to different activities and post warnings etc (and Maybe even has the ability to close activities or at least order them to close themselves without the need to register a can_close interface).
It should be that safe, that if after a crash android only restarts the activity that was active it somehow manages to also be restarted or at least have/give the same info as before.
Every idea is welcome but total overhauls of the app are just not possible (lack of time and manpower)
Here are a few ideas:
Create a Service component for all the monitoring you need to do.
If I understand correctly, this service will be required only if
some of the activities are running. So you can make it a bound
service. Let all activities bind to this service when they start
and unbind when they close. The service will be started when the
first activity binds.
Create a base class for all your activities. You can write all the common code here. e.g. the code to bind to and exchange messages
with the master service. This class can also contain utility methods
for notifying user etc. So all activities will use the same method
for notification.
For user notifications, you could either use Status Bar Notification or create a Fragment which can capture, aggregate
and display the notifications. You can have a common menu item
implemented in the base Activity class to show/hide this Fragment.
If you use Status Bar Notification, make sure you use one aggregated
notification for your app. Otherwise, the different activities might
create a clutter in the status bar.
I guess that one solution would be to create a service that serve as the master.
You will have to make it run independently of the different activities (but don't forget to manage own to shut it down neatly if the app is no longer used, you don't want to kill your clients battery).
A service can't act on the interface though, so you will probably need to broadcast messages to the activities to order them to open a dialog.
A final thought : Toasts are ok but popup that block the interface are very bad, especially on a mobile device.

Handle screen orientation changes when there are AsyncTasks running

I've been bugged by this for a while. How do I properly handle screen orientation changes while I have a separate Thread / AsyncTask running? Currently, I have
android:configChanges="orientation|keyboard|keyboardHidden"
in my AndroidManifest.xml, but that is not really encouraged:
Note: Using this attribute should be avoided and used only as a last-resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.
Also, in the 2.3 emulator, it works when switching to landscape, but switching back to portrait fails.
Now, the reason why I use configChanges is because when the user switches orientation, I might have an AsyncTask running, doing some network traffic, and I don't want it stopped.
Is there any other way of doing this, or is there a way of fixing 2.3 to switch back to portrait?
I know about onRetainNonConfigurationInstance, but I'm not sure it would be a good idea to "save" the AsyncTask instance, mainly because the class that extends AsyncTask is not static (so it is tied to the Activity) -- and it needs to be, because in onPostExecute() it calls methods from the Activity instance.
I had a similar problem to your and worked around it by implementing the AsyncTask as part of a class which inherits from Application class. An Application class is available all the life time of the application So you don't have to worry about your AsyncTask getting interrupted unless the whole application will be killed.
To get notified when the task has finished the Activity has to implement a interface which it uses to register itself to the Application class.
When your application is destroyed because of the screen rotation you can unregister your Activity from the Application class and re-register it when it is recreated. If the task finishes between destruction and recreation the result of the operation can be stored in the Application class meanwhile so the Activity can check whether the task is still running or whether the result is already available when it is recreated.
Another advantage is that you have direct access to the applications context because the Application class is a sub class of the Context class.
Take a look the droid-fu library BetterAsyncTask. It is meant to handle this exact case.
http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/
I already popped up similar question here.
Basically there is an example of how to pause/resume an AsynTask on device rotation. However it still does not fit for all cases (sometimes it is not possible to safely suspend the action, such as a new user creation on a remote server). For those "unsafe" cases you need to code somewhat I'd call a tricky "framework". You will see CommonsWare gives github links to the one.

Android Application class being called twice

In my Android application, I overload the Application class, and I updated the tag in my manifest. This application also creates an Android Service.
I have put some logs in the onCreate of my Application class, and I see it being called twice.
The first time is when my application gets launched (this is expected) and then, it's usually right after the Service is being created.
the log also shows that a second instance of the Application is being created.
(I print the "this" value and they are different).
I thought the Application would be created as a singleton.
Is that happening because I create a Service?
Yes, if you used android:process then you have it running in a separate process, so when the service starts a new process is started for it and thus a new Application object for that process needs to be created.
But there is a more fundamental problem - it is just not right for an Application object to start one of its services. It is important that you don't confuse Application with how you may think of an "application" in another OS. The Application object does not drive the app. It is just a global of state for the app in that process. In fact, the Application object is completely superfluous -- you never need one to write an Android application. Generally I actually recommend that people don't use it. It is more likely to cause trouble than anything else.
Another way to put this: what really defines an application is its collection of activity, service, receiver, and provider tags. Those are what are "launched." All an Application is, is something that is created as part of initializing an application's process. It has no lifecycle of its own, it is just there to serve the other real components in the app.
So just ignore Application when designing your app; it will reduce confusion. (In its place, I prefer to use global singletons for such state.)
Also as a general rule, I recommend not using android:process. There are certainly some uses for it, but the vast majority of the time it is not needed and just makes an application use more RAM, less efficient, and harder to write (since you can't take advantage of globals in a single process). It should be obvious to you if you reach a place where there is actually a good reason to use android:process.
A Service should not really be thought of as an Activity, and you're bound to have problems later on if you think this way. Services and Activities can belong to the same application, if you defined them that way in your AndroidManifest.xml, but they behave differently and have different lifecycles. If you want your Service in a different process, then you set android:process="string" in the <service> section to give it a name different from your application name. You won't have access to global variables when it's in a separate process, and you should communicate to your service through Intents. If your service is more complex, you might want to look at making it remotely callable through AIDL. If you want a singleton activity, then set that Activity's launchMode to either singleInstance or singleTask. singleInstance means it will be the first and only instance of this Activity in it's task stack and no new instances will be created for any new Intents. Since it's the only instance of this Activity, it will always be at the top of the task stack, and always in a position to handle new Intents directed at this Activity. If the Activity is declared as singleTask it will also be a singleton but may have other Activities in the same task stack, and may even have Activities at the top of the task stack above it. This is an important distinction to note. Remember this: singleton Activities that are NOT at the top of the task stack cannot handle new Intents, and the Intent will be dropped. If you want your Activity to always be able to handle all new Intents destined for it, then you most likely want to use singleInstance
The problem is that a Service is a component too, with its own lifecycle, just it hasn't got an user interface.
You should check the developer application fundamentals for the alternatives.
I just had this issue and after reading all this, nothing helped. Here is what helped me.
Add the attribute MainLauncher = true to your MainActivity.cs class.

Categories

Resources