I have a simple activity which binds a connection to a IntnetService. The service just plays a MediaPlayer. I have implemented onDestroy inside the service. However after pressing back in main activity, I was expecting the service to run as usual as IntentService supposes to run in background in separated thread, but after debugging I realized that onDestory activity calls in IntentService class and destroys the Media Player in it. Where I am wrong probably?
This is my Activity
public class MainActivity extends AppCompatActivity{
private void startAudio() {
Intent intent = new Intent(Intent.ACTION_SYNC, null, this, PlayerService.class);
bound = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
This is my Service:
public class PlayerService extends IntentService{
#Override
public void onDestroy() {
mediaPlayer.pause();
mediaPlayer.reset();
mediaPlayer.release();
}
}
bindService is used to bind to service and service stops itself when it has no clients/connections left.Here,as activity is destroyed,service is also getting destroyed
IntentService is supposed to run in background in separated thread until and unless it has work.But here,it is not getting work and hence getting destroyed.
Intent service has a queue which queues the incoming intents and performs the actions requested by these intents one by one. Once, the queue of this service is empty i.e. it has completed all of the actions requested by the intents it stops and starts again when it receives another intent.
Since, your service does not have any intent to be processed it ceases to exist. What you need here is a Sticky Service which continues even if it does not have any action to perform.
Related
First question here, but I've been around for a while.
What do I have:
I'm building an Android app which plays audio streams and online playlists. Everything is working fine now, but I'm having issues in communicating with my service.
The music is playing in a Service, started with startForeground, so it doesn't gets killed.
I need to communicate from my activity with the service, for getting the track name, image, and a couple of things more.
Whats my issue:
I think I need to start my service with bindService (instead of my current startService) so the activity can talk to it.
However, when I do that, my service gets killed after closing the Activity.
How can I get both? Binding and foreground service?
Thanks!
No. bindService will not start a service . It will just bind to the Service with a service connection, so that you will have the instance of the service to access/control it.
As per your requirement I hope you will have the instance of MediaPlayer in service . You can also start the service from Activity and then bind it. If the service is already running onStartCommand() will be called, and you can check if MediaPlayer instance is not null then simply return START_STICKY.
Change you Activity like this..
public class MainActivity extends ActionBarActivity {
CustomService customService = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// start the service, even if already running no problem.
startService(new Intent(this, CustomService.class));
// bind to the service.
bindService(new Intent(this,
CustomService.class), mConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
customService = ((CustomService.LocalBinder) iBinder).getInstance();
// now you have the instance of service.
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
customService = null;
}
};
#Override
protected void onDestroy() {
super.onDestroy();
if (customService != null) {
// Detach the service connection.
unbindService(mConnection);
}
}
}
I have similar application with MediaPlayer service. let me know if this approach doesn't help you.
Quoting Android documentation:
A bound service is destroyed once all clients unbind, unless the service was also started
And about the difference between started and bound just take a look to https://developer.android.com/guide/components/services.html
So, you have to create the Service using startService and then bindService, like #Libin does in his/her example. Then, the service will run until you use stopService or stopSelf or until Android decides that it needs resources and kills you.
On receiving a certain event in my Android service, I want to terminate the app from within the service. I know I can call finish in an activity to end it.
Also I understand that service will call stopSelf() on itself to end itself. But I need to terminate the entire app including any particular activity of the app that was visible at that time.
Any ideas?
Try this:
Process.killProcess(Process.myPid());
You can create an BaseActivity with BroadcastReceiver to close all Activities by registering it in onCreate() of BaseActivity and extending all your Activities with BaseActivity.
public static final String EXIT_APP_ACTION = "EXIT_APP_ACTION";
BroadcastReceiver ExitAppBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
Register it in onCreate() for the BaseActivity in your Application using,
registerReceiver(ExitAppBroadcastReceiver, new IntentFilter(EXIT_APP_ACTION));
Then you can fire this BroadcastReceiver from your Service using the Context to close all Activites including Service by calling stofSelf(),
stopSelf()
context.sendBroadcast(new Intent(BaseActivity.EXIT_APP_ACTION));
I have a trouble with screen orientation when using AsyncTask even it's inside Service.
My service look like:
public class RequestService extends Service {
private MyBinder binder;
public RequestService(){
binder = new MyBinder(RequestService.this);
}
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public class MyBinder extends Binder{
private final RequestService service;
public MyBinder(RequestService service){
this.service = service;
}
public RequestService getService(){
return this.service;
}
}
public <T> void sendRequest(Request<T> task, INotifyRequest<T> notify){
// Call excute the asynctask and notify result in onPostExcute
new TaskExecutor<T>(task, notify).execute();
}
}
Update: I use my Service like this:
// start the service
final Intent intent = new Intent(context, serviceClass);
context.startService(intent);
// then bound the service:
final Intent intentService = new Intent(context, serviceClass);
// Implement the Service Connection
serviceConnection = new RequestServiceConnection();
context.getApplicationContext().bindService(intentService, serviceConnection,
Context.BIND_AUTO_CREATE);
When orientation changing, the service is unbound then re-bound, the AsyncTask doesn't notify to update UI. I wonder why it could happen even AsyncTask inside the Service?
I have read this post, but I don't want to lock the screen orientation or something like that. I prefer the Service than IntentService as Service 's flexible, I can use it with the Binder to get Service instance.
So, the question is, is there any way to do thread safe inside the Service rather than AsyncTask?
If you use a bound service keep in mind, that the Service will be destroyed if no Activity is bound. I don't know if you unbind in onPause(), but this would destroy your Service at an orientation change.
Because of this you will loose the Service and the reference to the AsyncTask. Furthermore there is no onRetainInstanceState() available for a Service, to save the AsyncTask and grab it again.
Think about an IntentService in this case it would be the proper way. Or if you wanna keep the Service use startService(), to keep it alive while no Activity is bound. Then you can still bind and unbind from the service the way you want.
The next point is to keep a reference of the AsyncTask. Because you have to set your callback again if the Activity was destroyed. Because the callback reference will still be set to the old Activity.
Hope this helps.
Edit:
Well if you read that maybe you consider using a IntentService or something..
Keep a instance of the AsyncTask in the Service and define a setter in your Task for your callback.
If your Activity binds to the service after the orientation change check, whether the AsyncTask is running. If it's running update the callback. You can use your Binder for that.
i have created one intent service. Now I want to stop that service from activity how to stop that service? My code is:
MyActivity.java
#Override
public void onCreate(Bundle savedInstanceState) {
Intent intent = new Intent(this, myService.class);
intent.putExtra("myHand", new Messenger(this.myHand));
startService(intent);
}
myService.java
public class myService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
String signal = intent.getAction();
if (signal != null && signal.equals("stop")) {
stopSelf();
} else {
t.schedule(new TimerTask() {System.out.println("print")}, 0, 10000);
}
}
}
to stop service on click of button
Intent in = new Intent(this, myService.class);
in.setAction("stop");
stopService(in);
can anybody help me to stop service?
From the docs for IntentService
IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
In other words, you don't have to stop an IntentService - it will terminate itself when it has no more work to do.
EDIT:
Looking back at your code, it seems you don't wan't to stop the IntentService you want to stop the TimerTask???
t.schedule(new TimerTask() {System.out.println("print")}, 0, 10000);
I don't know what t is but I'm guessing it's a Timer. If that's the case it will be running with its own Thread and attempting to terminate the IntentService is pointless - kill the Timer instead.
Also, why are you using an IntentService to create any type of object which maintains its own thread of execution?
Now I want to stop that service from activity how to stop that
service?
IntentService stops itself, you shouldn't, you can't call stopSelf().
When all requests have been handled, the IntentService stops itself.
From what I know, IntentHandler creates a separate new thread, does its work, and kills itself.
So I don't think you need to explicitly stop it from an activity.
I have been looking for some way to get the ServiceConnection when I start my Service using startService(...).
I haven't found a way, so I have been searching a bit and found this:
Does each Activity need to Bind to a Service & What happens when it was created with startService()
There, Commonsware says that it doesn't matter if I call bindService after the startService call.
So I thought that I first run startService(...) and then directly after do a bindService(...) (so that onServiceConnected is called). But then the Service.onCreate is executed twice. Probably because startService isn't "finished" yet...?
Question is: How do I get a reference to my Service (the IBinder), ie. how do I get the onServiceConnected to fire if I start my Service with startService?
--- EDIT ---
I still do want to know any answers and ideas you might have. I made a "hack" to get around this:
I simply made a static reference (in SRef.java I have public static IBinder myBinder = null), and in my Service.onCreate I simple do
SRef.myBinder = myBinder;
This doesn't seem right to me, so any other ideas on how it is supposed to work would be appreciated.
I use the exact same technique (a samba client service), onCreate is never called twice for me and I get the binder (by connection callback) as I would expect. A new start of activity doesn't fire a onCreate either because previous startService performed the startup of the service already.
Here is my code (might be trivial, but maybe it helps):
Activity (onCreate):
startService(new Intent(this, SambaService.class));
bindService(new Intent(this, SambaService.class), sambaServiceConnection,
Context.BIND_AUTO_CREATE);
Service:
private ServiceBinder mServiceBinder = new ServiceBinder();
public class ServiceBinder extends Binder {
public SambaService getService() {
return SambaService.this;
}
}
public IBinder onBind(Intent intent) {
return mServiceBinder;
}