Started and Bound service is mysteriously stopped and restarted - android

My activity attempts to start and then bind a service that's supposed to run independently of it. This service turns the GPS on.
onCreate calls getApplicationContext.StartService, and onResume calls getApplicationContext.BindService. OnPause calls getApplicationContext.unbindService, although it never appears to run properly (the service connection never logs an unbind, although binds are logged when I treat it similarly).
Unfortunately, when I open up my Recents list, and slide the activity away, the Service stops and then re-starts itself almost immediately, dropping the GPS connection. What would cause this sort of behavior?
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
// Start up the service
Intent intent = new Intent(getApplicationContext(), LockService.class);
getApplicationContext().bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onPause() {
super.onPause();
Log.i(tag, "onPause");
if (isBound) {
getApplicationContext().unbindService(myConnection);
}
}
...
// Bound service stuff
LockService myService;
boolean isBound = false;
private ServiceConnection myConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LockBinder binder = (LockBinder) service;
myService = binder.getService();
isBound = true;
final boolean status = myService.getStatus();
Log.i(tag, "service bound");
}
#Override
public void onServiceDisconnected(ComponentName className) {
isBound = false;
Log.i(tag, "service unbound");
}
};
Edit: I checked into this answer, but this just prevents the service from restarting immediately (it still gets hung up, and re-opening the activity re-initializes it):
Android onCreate Service called when Activity onDestroy called
Edit 2: I had gotten my hopes up a bit too far with this answer. It doesn't seem to fix anything either.
How to force the onServiceDisconnected() get called?
Edit 3: This might be a KitKat thing.
In android 4.4, swiping app out of recent tasks permanently kills application with its service . Any idea why?

Because swiping an app out of the Recents list kills it in Android version 4.4 (KK), I have opted to simply not show my app in the Recents list at all.
Oh well, it didn't really need to live there anyway. It exists quite happily inside the notification bar. I pity anyone who isn't so lucky, and needs to forcibly restart the service via a timer and some hackneyed code.

Related

Service freezing activity before UI has inflated

I have a long-running service that is bound to a loading screen. I know this is suboptimal, but an AsyncTask did not work for me as it keeps running (data leaks) even after the Activity is ended forcefully. Regardless, want to understand what is happening here. The basic layout never shows up (black screen), but the service runs as intended. A (bound) service lives and runs on the activity thread, of course. But why does it not inflate the UI first? onCreate gets called before bindService afaik and as the Log confirmed.
ServiceConnection _connection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
_service = myService.Stub.asInterface(iBinder);
runStuff();
}
public void onServiceDisconnected(ComponentName componentName) {
_service = null;
}
#Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent();
serviceIntent.setPackage(myService.class.getPackage().getName());
serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loadingscreen);
findViewsById();
setDefaultVisibility();
[...]
Edit: As additional info, it actually takes a long time to display the (very simple) loading screen even with the AsyncTask. But even that weird delay should still not matter, because the service should not bind before then. What am I missing?
Edit2: I added timestamps. The service starts immediately. If the service is in an AsyncTask, the UI still takes the same time to load. From the button tap on the previous activity to onPostCreate it takes about 400ms, not the 3-4 s I see looking at the UI. The AsyncTask does update the UI as expected, but apart from onProgressUpdate, there is nothing pertaining to UI after onCreate or before any service calls. What could cause such a delay? I don't even have that on activities in the same app that are heavy on DB and GUI.
Put your code in a seperate method, I dont know if this will work but i have had success like this
private void start(){
Intent serviceIntent = new Intent();
serviceIntent.setPackage(myService.class.getPackage().getName());
serviceIntent.setAction(myService.class.getName() + ".ACTION_BIND");
bindService(serviceIntent, _connection, BIND_AUTO_CREATE);
}
and then start that method in your oncreate the service will then start after creation like
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loadingscreen);
findViewsById();
setDefaultVisibility();
start();
[...]

Android Service with MediaPlayer gets recreated or destroyed

I'm using bound service so that I am able to communicate between an activity and a service.
I'm binding to a service in onStart:
#Override
protected void onStart() {
super.onStart();
Intent bindIntent = new Intent(this, MusicService.class);
bindService(bindIntent, this, BIND_AUTO_CREATE);
}
waiting for service to bind:
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMusicService = ((MusicService.LocalBinder) service).getService();
mMusicService.setCallback(this);
}
handling disconnect from service:
#Override
public void onServiceDisconnected(ComponentName name) {
mMusicService = null;
}
unbinding from service in onDestroy:
#Override
protected void onDestroy() {
super.onDestroy();
if (mMusicService != null && isFinishing()) {
mMusicService.setCallback(null);
unbindService(this);
}
}
My problem is that when app is minimized, onDestroy gets called immediately and then onUnbind in Service gets called and music is stopped.
Here is onUnbind method (where mPlayer is MediaPlayer):
#Override
public boolean onUnbind(Intent intent) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
return super.onUnbind(intent);
}
If I don't implement onUnbind music continues to play (sometimes and sometimes it stops after some time) and when I open the app again (from minimized applications) I am able to play another song and then those two song play at same time.
I've red couple articles about music players and services on android and I thought that this was correct approach (thinking that onDestroy will be called when OS is out of memory).
Any ideas how I can re-implement my app workflow so that I will work as expected?
EDIT
At first I thought that "Don't keep activities" under developer options is a problem, but problem is still there even if I uncheck it.
And if some code from my service is needed please say I will edit my question (there's a lot of code and I'm not sure which part is important for this issue)
SOLUTION:
startForeground(<notification id>, <notification>);
to run service even if app gets killed. And when user dismisses the notification:
stopForeground(true);
stopSelf();
More about startForeground here.
It's not obvious, but you should start a Thread that runs in background and use the service to control it's state.
A service isn't a thread that hold some run state like a thread. Unless it's an IntentService. (Correct me if I'm wrong)
While activity can (and probably will) get destroyed, your app will keep running.
Activity:
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, BackgroundService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
finishOnPause = true;
}
#Override
protected void onStop() {
super.onStop();
unbindService(mServiceConnection);
}
Service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
ensureServiceThread();
if (intent != null) {
}
return START_NOT_STICKY;
}
private void ensureServiceThread() {
if (service_thread == null) {
service_thread = new ServiceThread(this);
service_thread.start();
}
}
#Override
public void onDestroy() {
stopServiceThread();
super.onDestroy();
}
private void stopServiceThread() {
if (service_thread != null) {
service_thread.interrupt();
service_thread = null;
}
}
And you should do your work inside the Thread.
If you need context, it's your Service.
If you need to do something on Main thread - create a Handler in Service.OnCreate and do a handler.postRunnable inside a worker thread safely.
What I would do is:
- Create a service
- Create a thread
- Create a media player inside a thread (if possible, otherwise on Service creation and pass it to thread)
- Inside a thread - continuously poll media player state
- On song finished send an intent to service that change track
- stop thread/service if needed.

Dismiss notification on low memory?

As you can see from the picture, this is what happens to my fancy media player notification when the system goes low on memory. This notification is issued from a service and when the system goes low on memory, the service is stopped, too, automatically by the system.
From the behavior, it seems that the Service's onDestroy() is not called because it is implemented to get rid of the notification. So, i decided to implement onTrimMemory() as follows:
#Override
public void onTrimMemory(int memory){
Log.d("TRIM", "Please, Trim Memory");
String stop = getResources().getString(R.string.stopping_playback);
if(MusicService.status == 1){
stopService(PodcastrApplication.newInstance().getMusicServiceIntent());
}
Toast.makeText(PodcastrApplication.this, stop, Toast.LENGTH_SHORT).show();
}
But that did not work. I didn't even see the Toast or the Log.
So, how do I remove the notification when the system goes low on memory?
PS: At the point when this happens, it is certain that the MediaPlayer has stopped playing (automatically). It is only a matter of removing the notification.
When the service terminates, it notifies all its clients about this event. Therefore, the corresponding ServiceConnection object in the client activity receives a onServiceDisconnected() callback. You can remove the notification from within this method.
EDIT:
private ServiceConnection connection = new ServiceConnection(){
public void onServiceDisconnected(ComponentName name){
ClientActivity.this.runOnUiThread(new Runnable({
public void run(){
getSystemService("notification").cancelAll();
}
}));
}
public void onServiceConnected(...){...}//do something if you need to
};
public void onPause(){
Intent i = getIntentForService();
bindService(i, connection, Context.BIND_AUTO_CREATE);
}
public void onStop(){//or onDestroy()
unBindService(connection);
}

Communicate with foreground service android

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.

Android, unbind service and onServiceDisconnected problem

I'm not good in English, but I would try to explain my problem in good way.
So, the problem is:
1) I have a local service
2) I start it and then bound to it.
3) Problem appears when I am about to close that service. onServiceDisconnected method from my implementation of class ServiceConnection is never called. If I close it manually (from settings), or by unbindService, or by stopService, or by combination of unbindService and stopService - onServiceDisconnected still doesn't to be called.
What am I doing wrong?
Short code is below:
protected ServiceConnection mServerConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(LOG_TAG, "onServiceConnected");
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d(LOG_TAG, "onServiceDisconnected");
}
}
public void start() {
// mContext is defined upper in code, I think it is not necessary to explain what is it
mContext.bindService(i, mServerConn, Context.BIND_AUTO_CREATE);
mContext.startService(i);
}
public void stop() {
mContext.stopService(new Intent(mContext, ServiceRemote.class));
mContext.unbindService(mServerConn);
}
I'm testing this code under emulator of Android 2.2
onServiceDisconnected is only called in extreme situations (crashed / killed).
which is very unlikely to happen for a local service since all your application components normally run in the same process... meaning, unless you intentionnaly unbind or destroy the service, it should remain connected, or die with the component using it.
Android developer documentation says...
public abstract void onServiceDisconnected (ComponentName name)
Called when a connection to the Service has been lost. This typically happens when the process hosting the service has crashed or been killed. This does not remove the ServiceConnection itself -- this binding to the service will remain active, and you will receive a call to onServiceConnected(ComponentName, IBinder) when the Service is next running.
For more: https://developer.android.com/reference/android/content/ServiceConnection#onServiceDisconnected(android.content.ComponentName)
I used Context.BIND_AUTO_CREATE in bindService. I have fetch same issue after apply its working perfect for me.
bindService(new Intent(this,XMPPService.class),mConnection, Context.BIND_AUTO_CREATE);

Categories

Resources