I'm writing an Android app with 3 Activity()s: A, B and C; and one Service: S. The user can start the service using activity A. The service runs for a long time, in 7 steps. Each step takes a few seconds (or minutes). Once a step has completed, I want the service to notify Activity()s B and C about its progress if they are visible. That is, I want to notify an Activity different from which has started the Service. There is no need the show an Activity if it's not visible.
How do I do that? What is the cleanest and/or simplest solution?
Register a receiver at runtime and listen/publish the events. This answer provides an example
Related
How i should implement a countdown timer if i need the following usage:
User starts activity A;
In activity A he starts the timer;
User leaves activity A, timer runs in background;
User comes back to activity A;
User see current (updated) values of the timer;
I tried to use a Countdown Timer but it fails at step 5 - after returning to ativity A i cant see values in TextView (in LogCat i do) and system starts another timer (this way, every activity re-open starts one more timer). Should I use service instead or ... show me the way, please.
You can't be sure that after you leave your activity it will be still alive. System could kill it at any time.
The solutions for this use case could be:
Start timer in foreground Service. Such types of services have better chances to be alive.
When you leave your activity you could save last timer value and last timestamp and restore timer with this info after activity is recreated.
PS. If you also want to fire the alarm when timer is finished you should use AlarmManager but keep in mind restrictions from android 6+ (M).
I have the following flow in my code:
Activity1 : startActivity(Activity2) --->
Activity2: startActivity(Activity3) --->
Activity3: startService(MyService) --->
MyService: startActivity(Activity4)
Each Activity above shows a single view and represents a step in a 4-step setup. The final Activity - Activity 4 - is started after some setup work is done inside MyService, which basically tells the user,
"The service has started, you can close the application by pressing Back or Home button"
When the user presses Back or Home, I want to destroy Activities 1-4 , and only have MyService running. Also, after stopping the Application as above, when the user navigates back to the Application via the menu and starts it, I'll be checking if MyService is already running. If it is already running, I don't want to show Activities 1-3, I want to show another Control Panel View (Another Activity), which says,
"Dude, the service is already running, do you want to Stop or Restart it?"
This view will have a Stop and Restart button, to do the appropriate tasks.
My Questions:
How do I stop Activities 1-4 from inside Activity 4 when Back or Home is pressed,safely? My thought was to add a static stopActivity() method to each Activity, and calling Activity[1-3].stopActivity() from onBackPressed() or onPause() of Activity4. Then inside each stopActivity(), I'll call finish(), thus ending each Activity. But is it safe and efficient to do it this way?
The flow I have illustrated above, is it the optimal way of doing things, or is there a cleaner way? I have BroadcastReceivers registered in these Activities, so I need to perform clean exits for each Activity, without leaked receivers, or worse, crashing the App or affect the User's phone due to unclean exit strategies.
Thanks for your suggestions.
You don't need to stop activities, Android will do it for you. Start your activities using intents with the flag FLAG_ACTIVITY_NO_HISTORY so they won't appear when the user presses back. Those activities will be stopped as soon as the user leaves them.
In the onStop method of each of your activities, write any code you want to deallocate memory if there is something you want to deallocate manually, although that wouldn't be necessary because Android will deallocate it for yourself when the device is short on memory. In those onStop methods unregister any BroadcastReceiverpreviously registered.
Let's assume I have 2 activities: Activity 1, Activity 2. I am starting Activity 2 from Activity 1. Activity 2 - is activity with image and progress bar to display the progress of executing some background task in it which is started in service.
When I try to press hardware Back button from Activity 2 it brings me back to Activity 1, so I can start Activity 2 again even if there is service still running.
So the question is such: How can I prevent such behaviour. I need to start Activity 2 only 1 time and not exit from it while the work is not finished?? And another case is that I can stop my application from Task manager, but service will be working and after that I can run application again - with new service, while old will be still running? What mechanisms are there to prevent such behaviour? Thanks.
You can bind to a local service from your Activity class when it is starting up. Once bound, your Activity can call any public methods declared by that service. This would allow your Activity to bind to the service, then check to see if the service is currently doing any work. You might make a method like isRunning() or similar. If the service is not currently doing any work, you might want to start a new job. If it is already executing some task, you could then display the current progress of that task.
You should read the Local Service Sample article on the Android developer site to get an idea how to do this.
I am writing an Android app (ICS) for a tablet. The user moves from Activity A to Activity B to Activity C with the touch of a button. I want to return from Activity C to Activity A after 10 seconds. Is there some way to count to 10 without locking up Activity C?
I've succeeded with an asyncTask but if I startActivity(A) in the onPostExecute() it feels like I'm violating the guideline that an asyncTask should not mess with the UI. I've tried get() but that does lock up Activity C while it's waiting for the 10 seconds to pass.
Thanks in advance!
Assuming you have any View instance in your activity, you can use View.postDelayed() to post runnable with a given delay. In this runnable you can call Activity.finish(). You should also use View.removeCallbacks() to remove your callback in onDestroy(), to avoid your callback being called after user already navigated back from your activity.
Using AsyncTask just to count some time is just an overkill (unless you want to use AsyncTask to actually do some useful, background work). The Looper and Handler classes provide everything you need to execute any code on UI thread after a given delay. The View methods mentioned above are just convenience methods exposing the Handler functionality.
Using AsyncTask works fine as you describe. From Android Documentation:
onPostExecute(Result), invoked on the UI thread after the background computation finishes.
Since it is invoked on UI thread you should be fine.
Documentation
You can use a alarm manager for that. Set it to send a broadcast 10 seconds starting from activity a and implement a base activity for activity a b and c to receive the broadcast, after receiving the broadcast just end the current activity and start activity a with a new flag. If the current instance is activity a then ignore if not start activity a. Something like that.
As for the idle part you can update the alarm manager on every action, upon entering activity etc.
The advantage of this implementation is that you dont have to go through the hassle of having to worry about context leaks, persisting timers across activities and such. and can make use of what is already there. You can also consider using a service though.
If not you can just use the shared preference store the time to time out and check or update against it for the actions.. A simpler implementation.
Good luck.
I am working on an android application, where there are 4 activities. Activity1 is main activity and there are different buttons on that activity which can open other activities. Other 3 activities can also open each other. There is a thread running in Activity1 which returns some counter. I need to show that counter on all activities.
At an specific time, the thread doesn't know which activity is at top. What is the right way to control this scenario, such that thread output should update on all activities, no matter which one is at top?
I would have that counter on a Service and I would send updates through broadcast intent.
Each Activity will register a listener to that intent on the onStart method and unregister it on onPause. This way the update will reach only the Activity that is on screen.