Im still a bit new to the Android Service Class. I know you need to start the service from your application with startService(intent), however my problem is my service has methods inside it. I need to start the service with an intent and then create an object of that class in my Activity so I can call methods of the service. The problem is when I do this I create one instance of the service when I start it with an intent and another instance of the service when I create an object of the class in my activity. This means any data passed to the service from startService(intent) is not there when I create the object of the service. Any ways around this or am I just totally misusing the service class? I can give some code but its basically this:
//Create Object of ControlPanel service class.
ControlPanel cPanel = new ControlPanel();
//Create intent for starting ControlPanel service class
Intent controlPanel = new Intent(this, cPanel.getClass());
//Start Service
startService(controlPanel);
I'd say you are misusing the class :-).
Calling startService() multiple times does not result in starting multiple service.
From the doc:
Request that a given application service be started. The Intent can either contain the complete class name of a specific service implementation to start, or an abstract definition through the action and other fields of the kind of service to start. If this service is not already running, it will be instantiated and started (creating a process for it if needed); if it is running then it remains running.
You should override onStartCommand() as well. The first startService call starts the service if it has not been started yet. In any case onStartCommand will intercept any further startService calls and the intent you want to send to it.
Any ways around this or am I just totally misusing the service class?
You are totally misusing the Service class.
A Service is used via two basic patterns:
Sending commands to it, via startService().
Binding to it, to call an API exposed by that Service, via bindService().
Binding more accurately depicts what you are trying to do ("so I can call methods of the service"), however binding is tricky to get right, particularly when it comes to configuration changes.
Hence, I would recommend first that you sit back and determine completely and precisely why you are using a Service in the first place. ControlPanel, for example, is a name I would associate with a UI, not UI-less ("background") operations. Then and only then can you determine if the command or the binding pattern is appropriate for your use case.
You can do this with one service class.
public static int myStaticMethod(){
return 1;
}
Simply make the methods you need to access static.
Related
I have an app where I need to establish and maintain a bluetooth connection with another phone. However, this connection needs to remain alive even if the screen turns off.
So the way I've done this is 1) make it a service so the connection can exist in the background and 2) make an explicit call to start/stop the service instead of binding it to the activity (I believe if the screen goes off, the activity goes away, thus the service will stop)
This has now made things more complicated because my service has methods that I need to be able to manually invoke. For example, I want to start bluetooth discovery when the user clicks a button. So on button click, I need to tell this service to call my startDiscovery method. There are many situations like this (e.g. open a socket, pair to a device etc) where I need to manually call service methods
A lot of what I've read on this topic solves this by binding the service, but this I cannot do as explained earlier
Without binding, others suggest to use some sort of event bus, where on button click I send a message to the service. When it receives the message, it checks what type of message it is and then invokes the appropriate method.
OK, this works, but what if my method requires me to pass something into it? For example, lets say I have a list or something that I need to send over bluetooth. So I have a method in my Service that takes a list object, serializes it and sends it over BT to the other phone. But this doesn't seem possible with a basic messaging/event bus system
In sum, how do I pass an object through to a method in a service that is not bound to an activity, but instead has been manually started with startService?
I have seen this question here, but that method only seems to allow me to send objects when I start the service. In my case, the service is already started and sits in the background handling bluetooth traffic. I need to be able to invoke methods and pass objects while the service is already running
I have done something similar in my service. Sometimes i need to manually hide the notification that the service created. So i made the method public and static so it can be called anywhere like this:
public static void hideNotification(){
notificationManager.cancel(0);
}
Then call it in your activity like this: MyService.hideNotification()
EDIT
If you do not want a static method, you can create an empty constructor for your service and then when you need to call the method, create a new instance of your service and call it from that. For example:
In the service:
public class MyService extends Service{
public MyService(){}
public void hideNotification(){
notificationManager.cancel(0);
}
}
When you need to call a method:
MyService service = new Myservice();
service.hideNotification();
I'm facing a strange problem with my app. I have a LocationService that runs in the background. The way I manage its lifecycle is:
In onResume, every activity uses bindService(intent,serviceConnection, BIND_AUTO_CREATE) like that the service is automatically created when needed.
In onStop, every activity uses unbindService(serviceConnection)
This works because when switching activities, the new Activity onResume is called before the old Activity onStop method
The problem I have is, lets say I start from the home screen and I launch the app with an Activity that has a fragment in it. The order of the function call is as follows
Activity onCreate --> setContentView is called here
Activity onResume --> here bindService is called and should create the Service
Fragment onResume
Service onBind method is called
My question is why is there a something else between my bindServiceand onBind calls?? I have a feeling this has something to do with threading issues.
Well, this isn't a very good answer, but why wouldn't there be something else between your bindService() and onBind() calls? You seem to be assuming that when you call bind the system will immediately create and start your service, and no such guarantee is provided.
You haven't indicated whether yours is an IntentService, or just a regular Service, and this might affect the speed with which your service is launched, but my answer would be the same.
Also, I'm assuming that your ServiceConnection object is called, as expected, sometime after your service's onBind() returns.
I say this not based on having read anything definitive, but because I had a similar experience: I was surprised and annoyed at how long it took before my service was created and my ServiceConnection was called, even though I returned from the service's onBind very quickly. (My fragments needed data from the service to create the initial UI so any delay in the creation of the service meant a delay in displaying the initial UI to the user.)
In the end I settled upon launching my service using an Intent rather then a bind, e.g.
Intent si = new Intent( this, com.company.MyService.class );
si.setAction( MyService.SVC_BIND );
startService( si );
I then sent MyService.SVC_UNBIND in place of calling unbind. When I received the UNBIND intent in my service I cleanup and then call stopSelf(). These are user actions - I just named them for how I'm using them.
I believe this was faster, but looking back upon my comments from that code I don't have any specifics. Note that this meant no ServiceConnection, but I'm making some direct calls from the activities into the service, and using LocalBroadcastManager a fair bit.
Another option to consider (in order that your service be started more quickly, if that is your goal here??) is to launch it in Appliction.onCreate(), rather then waiting for Activity.onResume(). All of these options make it necessary to do some extra work to determine when to stop the service, compared to your current, normal, scheme where that is taken care of for you.
In my case, my issue was using android:process attribute for <service> element within Android Manifest, which is supposed to improve performance, but in reallity, maybe it does once the service is running, but it takes a very long while to reach onCreate() (and so also to reach onBind()). For me it was taking minutes. Now Apps and services run smooth and as expected.
More info:
https://developer.android.com/guide/topics/manifest/service-element
Usually when I create an Android service I implement the onCreate method, but in my last project this does not work. I tried implementing onStartCommand, and this seems to work.
The question is: when I have to implement a service which method is required? Which methods I have to implement? onCreate, onStartCommand, or both? And what is the role of each?
onCreate() is called when the Service object is instantiated (ie: when the service is created). You should do things in this method that you need to do only once (ie: initialize some variables, etc.). onCreate() will only ever be called once per instantiated object.
You only need to implement onCreate() if you actually want/need to initialize something only once.
onStartCommand() is called every time a client starts the service using startService(Intent intent). This means that onStartCommand() can get called multiple times. You should do the things in this method that are needed each time a client requests something from your service. This depends a lot on what your service does and how it communicates with the clients (and vice-versa).
If you don't implement onStartCommand() then you won't be able to get any information from the Intent that the client passes to onStartCommand() and your service might not be able to do any useful work.
Service behave same like Activity Whatever you want to associate once with a service will go in onCreate like initialization
and whenever the service is called using startService. onStartCommand will be called. and you can pass any action to perform . like for a music player , You can play ,pause,stop using action
And you do any operation in service by sending an action and receiving it on onStartCommand
onCreate work like a Constructor.
Edit in Short
onCreate() calls only for the first time you start a Service Whereas onStartCommand() calls everytime you call the startService again. It let you set an action like play,stop,pause music.
public void onStartCommand()
{
if(intent.getAction.equals("any.play")
{
//play song
}
else if(intent.getAction.equals("any.stop")
{}
}
I've inherited a project and I don't understand how to either get a response, or set a callback from the following code:
startService(new Intent(this, VenueUpdateService.class));
At the moment the application continues even if the VenueUpdateService fails. I want to change it so that the application waits for a success/fail from VenueUpdateService.
I get a response within the VenueUpdateService class about success/fail. But how do I pass this back to the activity that started the service?
Thanks,
James.
What you're asking to do seems kind of strange to me. A Service will always succeed in being started if you call startService. It's not as if startService is some risky behavior that needs be wrapped in a try/call block.
But I suppose your Activity could register a BroadcastReceiver that receives a broadcast sent from the service in onStartCommand.
Or maybe you're looking to bind to the service, in which case you'll know when you're bound. see here
What I did was change the IntentService to an AsyncTask.
I basically wanted to stop the user interacting with the app while the VenueUpdateService did it's thing as it had to succeed at least once before the user could continue using the app.
So now I have:
VenueUpdateTask task = new VenueUpdateTask();
task.execute(response);
Within that class I show a progress dialog, do update venues.
I Need some help here, I have a service which I can start or stop whenever I want and using the onStart() command to pass some extras using putExtras() from my activity
But I need some serious basic instructions on how to interact with the already created service.
Please don't refer me to another webpage which already have some implementations, just give me the needed code to interact from my UI activity to the service:
something like this:
public class myActivity extends Activity {
Object ReceivedObjectFromService;
onCreate()
{
some stuff here
myMethod()
}
public class myMethod()
{
//do some stuff with the ReceivedObjectFromService
//Don't know how to call this method from the service btw
}
please some help, I don't understand the tutorials on how to interact service to activity or viceversa
Interaction with already created service is no different to starting a brand new service. You just simply call startService() so your client code is no different.
Now, the part which is different is the service itself. In your service, onCreate() must start a background thread or a timer to carry on doing a work. onStart() will receive all startService cases and must in fact add the data it receives in the Intent to an internal list or queue and then in the timer's callback start processing from this queue.
Now you can pass any messages or data you want (even closing the service) using startService and passing data in the Intent that your service understands.
Hope this helps.