I'm developing an android app (if you want more info http://www.txty.mobi) and I am having some problems with dialogs management. I'm quite new to Android so the way I'm doing things completely wrong. If the case please just say so pointing me to the right documentation to follow.
Background:
The main blocks of the app so far are one activity and one Service (which derives from IntentService).
The actvity needs to interact with the service in just two occasions: start/stop the service. The intent service will self regulate its lifetime using the AlarmManager.
A typical flow when clicking on start/stop:
1) the activity on its onResume registers a broadcast receiver to events sent by the service (unregisters it in the onPause)
2) the activity starts a indeterminate progress dialog
3) the activty sends a single shot alarm event (either start or stop) which will be send **straight away to the service
4) the service does what it needs to do to start
5) the service emits a broadcast event basically saying "done"
6) the activity receive this event and gets rid of the dialog.
The Problem:
The activity can lose its foreground status let's say if the user switches focus or a call is received, so the onPause method is called (at this point the activity could even be killed by the system to claim memory). obviously if this is the case the activity will never receive its broadcast event because the receiver has been unregistered. This will leave the app in the awkward situation, when the activity is brought again to the front, of having a dialog that you can't kill nor will never get rid of.
The (possible??) solution:
The way I am handling this now (apart for keeping the broadcast receiver in place) is by creating a utility class that uses preferences to keep track of which operations are being executed and their status:
Activity
- in the onResume using my utility class gets the list of operations the activity is waiting for
- check their status
- if they are completed perform some actions accordingly (in my case get rid of dialog!)
- delete the operation from the preferences.
- just before asking for a operation to the service it saves it to the preference using my utility class.
Service
perform operation and save state of the operation to the preference using my utility class.
emit broadcast.
Disasters happen!
Now this saves me in a normal situation, but if a disaster happens (i.e. with the task killer app you kill everything) the service might be killed before it can save the status of the operation I am stuck as before (the activity will think the operation is still going on so it won't touch the dialog). So as for now I add a Dismiss button to very dialog just in case :)
Now all of this looks too complicated for what I think should be a fairly common thing to do. That's why, as said at the beginning of the post, I might (very likely!) be completely wrong.
Any ideas? Apologies if this question has been asked already, I looked around but didn't find anything. Please point me to any resource online explaining this.
Thanks and sorry for the lenghty post :P
Luca
Have you tried using a StickyBroadcast? This caches the latest broadcast, so it can be received onResume. Please see this post.
Related
I have a background service doing some work - retrieving user location by interval (launched with startService). As soon special condition reached I'd like to do the following:
If application is in foreground then start specific activity.
If application is not in foreground or closed then show the notification that will start required activity on tap.
I know how to show notification and how handle intent from server with broadcast receiver for example. But how can I determint if my application is in foreground? Or may be you can suggest complete better solution?
I determint if my application is in foreground
There's couple of ways to find out what is in front, but I actually prefer to track this myself (as this helps me apply additional logic if needed). Plus it's pretty simple task. To make this happen you need static int based counter somewhere (you can use your Application object if you have one, or have it elsewhere, does not really matter). In each Activity's onResume() you increment the counter by one, and in onPause() you decrement it by one. If counter equals 0 then none of your activities is in foreground so from your perspective you are in background and you post notification. For simplicity I always do that in my ActivityBase class all my activities extend.
If you do not want to track it yourself, you can use ActivityManager to see what's currently in foreground:
public boolean isAppInForeground() {
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = am.getRunningTasks(Integer.MAX_VALUE);
return (services.get(0).topActivity.getPackageName().toString()
.equalsIgnoreCase(getPackageName().toString()));
}
but this requires <uses-permission android:name="android.permission.GET_TASKS" /> entry in your Manifest, so not always welcome.
An alternative to Marcin's answers is to bind and unbind your Activities to the Service. This will allow communication between the Service and Activity whilst that binding exists, and the Service will know if an Activity that is capable of handling the scenario is currently available - e.g. you may not want to launch the Activity directly if the user is in the middle of some important process (like accepting the T&Cs / EULA or something), so the Service can tell the Activity that an event has happened, but the Activity can respond to the event correctly.
I am currently building an android application that will be used as an anti theft sort of application. Basically, once the alarm has bee launched, the application will monitor the accelerometer to detect movement. If it does, the user will have 15 seconds to enter a set password to deactivate the alarm, otherwise : BIIIIIP!
My problem is the following: how do I manage to keep the monitoring and counter process running after the activity is destroyed (if for example the user presses back) in a way that I can access it again from a notification.
I was thinking of using a thread to run the monitoring and counting process and when the notification was pressed, for example, the class could, in it's onCreate method, be aware whether an already existing thread is running and if so, get the handle to it?
Thanks.
What you are looking for is a Service. They are meant for this exact purpose; to run on the background (this does not mean a background Thread ) even if there are no Activities running.
You should consider using services for this purpose. Here is one of the example: http://blog.kozaxinan.com/2012/08/using-accelerometer-when-screen-off_16.html
I am writing an android application. In the application there are 4 activities.All the activities are mutually independent.
In my application i want to use a socket communication and a service. Both of them starts when the first activity is launched and should be stopped when the last activity exits. The starting activity is preset, so no problem in the starting. But the last activity is random. In this situation how should i stop the service and close the socket?? Is there any callback when the "Application" exits? I have seen the android activity life cycle, But it doesn't says anything about the whole process....
How about using AIDL-interface to a service and let each activity register/unregister. Then let the service count number of activities active and when the counter reaches zero close the socket and exit.
onCreate and onDestroy - bracket the entire life of the app. This pair is called when the app is loaded into memory or unloaded from memory. These two bracket the entire lifetime of an activity. When it is first loaded the onCreate is triggered and when the app is disposed of onDestroy is triggered. You clearly have to use these two to setup and destroy and resources which are needed for the entire lifetime of the app - although in practice things can be more subtle. The system can stop the app without calling the onDestroy and can restart the app triggering an onCreate event.
onStart and onStop - bracket any period that the app is visible. It could be that the app is behind say a modal dialog box. The app is visible but not interacting with the user. This pair of events can be triggered multiple times during the entire lifetime of the app. Simple apps can mostly ignore the onStart and onStop events because the app is still in memory and doesn't loose any resources or state. The main use of onStart and onStop is to give the app an opportunity to monitor any changes that might affect it while not interacting with the user. To confuse the issue even more there is also on onRestart event which occurs before the onStart event but only if this isn't the first time the app has fired the onStart - that is this is a true restart.
onResume and onPause - bracket the period that the app is in the foreground and interacting with the user. Again this pair of events can happen multiple times during the entire lifetime. The onResume event occurs when the app is in the foreground and doing its usual job. The onPause event occurs when the user switches away to another app for example.
You can learn a lot about lifecycles in this Adventure: Have a look at it: http://www.i-programmer.info/programming/android/5966-android-adventures-lifecycle-and-state.html
Edit:
Maybe this will help you: How to handle activity life cycle involving sockets in Android?
And here is a good guide on how to use them:
http://tacticalnuclearstrike.com/2011/03/a-way-of-using-sockets-in-android/
I have a problem trying to figure out the best way to complete a simple app following the Android best practises. Here is the scenario:
1) I have an activity where the user enters something, its then send to a background Service
2) The background service performs some checks on the input and spawns a new AsyncTask to process the input.
3) The asynctask updates a Status Hashmap in the service with its progress and status
4) There is an second activity that binds to the Service to display a list of currently running tasks from the service and their progresses. The idea is that even if this activity is closed the service will continue to run the tasks and when the activity is reopened the refreshed stats will be shown.
I have problems in 3 and 4. What is the best way to communicate to the Service from within the AsyncTask's onProgressUpdate method and at the same time update the listing activity if its opened, if its not opened its simpler, just update the service tracking maps and when the activity is opened it will read them and update.
Im not sure what is the standart approach to handle "Events" of that sort. Do you have to use a Broadcast listener and subscriber or its too much for this simple purpose?
If you want to communicate between the service and an activity, you could broadcast updates from the service within the AsyncTask.onProgressUpdate method (alternatively within the AsyncTask.onPostExecute(Result) method) and listen for the updates using a broadcast receiver within your activity.
Instead of me copying and pasting a lotta code, check out Vogella's tutorial on services, especially the exercise (7. Exercise: Using services and service communication), found here
www.vogella.com/tutorials/AndroidServices/article.html#tutorial_intentservice
Within the exercise, you're looking for the DownloadService.publishResults(...) method which sends out a broadcast from the service to whichever broadcastreceiver is listening for updates, and the use of the BroadcastReceiver in MainActivity, which handles the updates from the service.
Is there some sort of onTerminate() method where I can do some cleanup (I want to clear some SharedPreferences) when my Android app is terminating?
I have an Activity that is keeping a running average of a few numbers, that I'm storing in a SharedPreference. I want this average to last while the app is running (the user can move between different activities) so I can't clear it on onDestroy() for that particular activity. I need to be able to clear it once the app is about to quit.
How can I do this?
I've not tried this, but here's what I would do:
As Alex mentioned in the comment to original question, use a Service to share the app-wide state between Activities.
Whenever you move between Activities, bind to the service from the "new" activity, and unbind from the "old" one. Check this to understand how to coordinate activities.
If you follow this properly, you can ensure that at least one Activity is always bound to the Service as long as your app is running; and that all Activities are unbound when the app is no longer running - at which point your service's onDestroy() is called. This is where you perform your cleanup.
So android doesn't really have a concept of an app being "finished". Unfortunently there is nothing synonymous to "onTerminate()". Is there some criteria by which you can decide when to clear your running average?
Use SharedPreference.Editor to remove the preferences, and commit. Here's a link for you: http://developer.android.com/reference/android/content/SharedPreferences.Editor.html