updating an activity from an asynchronous service - android

I've implemented a service that does an asynchronous sync between my application and google docs. I want to update the top level activity of my application when the sync is complete. However because of the service it's possible that the app could be be in a unknown state. Is there a way to make the top level activity, whatever that may be, recreate itself from an asynchtask in a service.

In your Service, just call startActivity(new Intent(this, TopLevelActivity.class)). This will launch your TopLevelActivity if it's not already running, or call your TopLevelActivity's onNewIntent() method if it is already running, and bring it to the top. You can override onNewIntent() and capture the Intent if you want to be notified.

You should broadcast an Intent from the service and then have the Activity be a broadcast receiver.
Here is a write up on BroadcastReceiver.
Hope this helps.

The correct way to do this, I believe, is to use a Remote Interface using AIDL:
https://developer.android.com/guide/components/aidl.html
You make a simple *.aidl file with the interface in it, and the Android tools will generate the Interface class for you. It will allow you to register Callback methods. Much cleaner than tossing startActivity intents back and forth.

Related

How to detect user activity/inactivity in Android service/background application?

How to detect user activity/inactivity in android service/background application - from same or other applications?
I want to know that user stop touching screen and not busy with another activity to show notifiation popup. Not sure is there no other method than use AccessibilityService.
One of the ways is to know that from reading the Android logs
Use a boot receiver to setup the AlarmManager (and of course also check to start the polling from your main Activity too, for the case when your app is installed and the system is not booted) and have the AlarmManager send an Intent for another receiver.
I think they answered it in this question to do what you are looking for:
android: running a background task using AlarmManager
Define a interface in activity and service.
in oncreate of activity set reference to activity in service method.
Now you have activity reference for entire service lifetime.
another way to do this is, application class, same application class is shared by activity and service, so you can both of these from each other using application class.
If you want see from applications then use broadcastreceivers that is the only wau

How to implement the communication between a Service and an Activity in different processes?

I read some similar questions (for example at this link), but the problem I'm asking is a bit different. In fact, in my case the service is started manually by the startService method, then as a consequence it can not be started using the bindService method.
Suppose we have a package that contains the MainService service and MainServiceActivity activity. In the file "AndroidManifest.xml" this activity is declared with action MAIN and category LAUNCHER. This activity is used to configure the service via the SharedPreferences and start the service by invoking startService method. In other words, typically the user launches the MainServiceActivity and configures/starts the MainService.
Now consider another activity (Let's call it SecondActivity) that is part of another package. Depending on the configuration, the service starts this activity using the startActivity method, so this other activity is running on a separate process than the MainService. As soon as the activity is running, it should inform the service.
At this point, a communication request/reply begins between the MainService and the SecondActivity: the service sends a request and the activity sends a reply.
The communication via messaging might fit, but the MainService is started through startService method, so the bindService method can not be invoked by activities that want to bind to the service.
Then I had an idea that makes use of an additional service (Let's call it UtilityService), which is part of the same package of MainService: the UtilityService could be started using the bindService method. As a consequence:
as soon as the MainService is running, it might perform the bind to the UtilityService;
when the MainService launches an external activity (for example the above SecondActivity), this activity bind to the UtilityService.
In this way, both the MainService and the SecondActivity are connected to the UtilityService, where the latter acts as an intermediary for communication.
Are there alternatives to this idea?
In fact, in my case the service is started manually by the startService method, then as a consequence it can not be started using the bindService method.
You can both bind and start a service, if you wish. It's a bit unusual, but it can be done.
Are there alternatives to this idea?
Binding has nothing in particular to do with services being able to communicate with activities. Using some sort of callback or listener object via binding is a possibility, but it is far from the only one.
You can:
Have the service send a broadcast Intent, to be picked up by the activity
Have the activity send a PendingIntent (e.g., via createPendingResult()) to the service in an Intent extra on the command sent via startService(), to be used by the service to send information back to the activity (or wherever the activity wants it to go, such as a broadcast)
Have the activity pass a Messenger tied to its Handler to the service in an Intent extra on the command sent via startService(), to be used by the service to send information back to the activity
All of those work perfectly well between processes, as well as within a process.
You can use Android Interface Definition Language (AIDL).
You can find an easy to use guide here

Notify activity from service

I'm trying to start a Service from my Activity to look out for changes on a web page, it's a private app so I don't bother the battery life...
But I'd like to pass data from my Service to my Activity... I can't seem to find a way to call the Activity from my Service. How can I achieve this?
As Alex indicated, you can bind to the service and pass some sort of listener or callback to the service to use on events.
Or, you can use a broadcast Intent, perhaps using methods like setPackage() on the Intent to limit the scope of the broadcast.
Or, you can use createPendingResult() to create a PendingIntent that you pass as an Intent extra to the service -- the service can then use that PendingIntent to trigger onActivityResult() in your activity.
Or, you can use a ResultReceiver.
Or, you can use a Messenger.
(admittedly, I have not tried those latter two approaches, but I think they will work here)
One more alternative: if your service updates content provider, activity can be notified via ContentObserver. This would be enough if your service downloads some data from server and you simply want to display fresh contents in the activity.
Some ugly ways:
1.) If the activity has not started yet, then use intent and startActivity, but remember intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2.) Otherwise if the activity has started already, you can write your own callback method in the activity and register the method in the service, then direct call the method in the service.
Hope to find some smart way.
I think broadcast also work well, you can write a static inner class for receive broadcast and start activity. But it is also ugly in my opinion.
The ResultReceiver mechanism has been explained in another post :-
Restful API service
However it would not work in all cases. Please refer to my comment on that post. The limited scope broadcast or PendingIntent mechanism seem more suitable.

How to communicate back to a service from a broadcast receiver?

Hope someone can help me out here. I will try to be concise!
I have a widget which starts a service. The service registers two broadcast receivers. I would like to send back intents from the receivers to the service, so that the service can react.
I believe I read somewhere that 'starting' the service multiple times works, e.g. do the following in the receivers:
serviceIntent.setAction("me.SERVICE");
intent.putExtra("me.SERVICE", somedata);
context.startService(serviceIntent);
I remember reading (on some blog) that this won't start a new service, but will simply pass the intent to the already running service. Is this correct? Is it a bad way of doing it? Is there a better way?
Thanks very much!
Jack
Yes, I've used that approach in a pre-2.0 app.
I accomplished this using a singleton. I set a private variable (pointing to 'this') in the service's onCreate, and then used a static method called getInstance() which would return it. So later on, I simply call MyService.getInstance() to get hold of the service.

Stop All Started Services on App Close / Exit

Is it possible to stop all started services when the user hits the Home Button?
I use:
startService(new Intent(ClassName.this, ClassName2.class));
stopService(new Intent(ClassName.this, ClassName2.class));
This means I will have to somehow add the 'stopService()' for 7+ of my app classes
I've researched this topic and I think there's 'onTerminate' but still not sure how this should be implemented.
Any help or hints would be appreciated!
Thanks!
Is it possible to stop all started
services when the user hits the Home
Button?
Not directly. For starters, you have no way of knowing they pressed HOME.
If you only want the service running while activities are using it, consider getting rid of startService(). Instead, use bindService() in the onStart() methods of the activities that need the service, and call unbindService() in their corresponding onStop() methods. You can use BIND_AUTO_CREATE to have the service be lazy-started when needed, and Android will automatically stop the service after all connections have been unbound.
If you want services to stop when the user leaves your app, I would ask if you want to use services at all. You may just be making your application way more complicated than it needs to be.
Also, this line is really questionable:
startService(new Intent(ClassName.this, ClassName2.class));
You are making an Intent whose action is the class name of one class, and data URI is the class name of another class...! Maybe you mean something like "new Intent(context, MyService.class)"?

Categories

Resources