I want to perform some operation when my application gets killed.
Which method can be used for this? I am working on Android 5.0.
The key of this question is that:
you must understand your application whether can receive any
additional callbacks when your application being killed in any kinds of situation.
The following answer is answered by Devunwired in this question:
Android app doens't call "onDestroy()" when killed (ICS)
This will help you more to understand this.
Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.
finish() is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.
onDestroy() only gets called on an Activity as a result of a call to finish(), so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes through onPause() and onStop().
This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a whole has been brought forward or moved backward.
Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound Service inside of your application that every Activity binds to while active (i.e. between onStart() and onStop()). What this provides you is the ability to leverage the fact that a bound Service only lives as long as clients are bound to it, so you can monitor the onCreate() and onDestroy() methods of the Service to know when the current foreground task is not part of your application.
You might also find this article written by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.
You have to use Service Class for it like -
public class Myservice extends Service { #Nullable #Override public IBinder onBind(Intent intent) { return null; }
#Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(Constants.TAG, "Service Started"); return START_NOT_STICKY; }
#Override public void onDestroy() { super.onDestroy(); Log.d(Constants.TAG, "Service Destroyed"); }
#Override public void onTaskRemoved(Intent rootIntent) { Log.e(Constants.TAG, "END"); //Perfome here want you want to do when app gets kill stopSelf(); } }
In Manifest -
<service android:name="Myservice"
android:stopWithTask="false" />
In Oncreate of your launcher activity or Application Class to start service -
startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
You can use your activity's onDestroy() method.
Related
I am confused right now , about service concept of running and stopping:
what i want to do:
Start Location service at the very start of application.
Keep getting location updates and store them to shared preference
Stop the service in onDestroy of Application scope!
So far i have searched and studied we can only do following things with service(correct me if i'm wrong):
Stop the service automatically by binding it to related activities/fragments/views , when all of them destroyed service unbind itself automatically so we can call stopself method in unbind
return START_NOT_STICKY in onStartCommand to tell OS , don't recreate it , and create intent local service , after completion of some work it will destroy itself.
Stopping the service manually , by declaring it's intent in some kind of static scope and stopping the service in on onActivityDestroyed of Application class [I am not sure what will happen? , maybe service will destroy each time any activity will be destroyed ? or it will be destroyed only when overall application get's destroyed?]
Either way , i am bit confused and beat , been trying to adjust my Location service with given details for 2 days
If you start your Service using START_NOT_STICKY, then your app will kill your service once your entire application is closed from background i.e. you cleaned your app from home screen.
Here START_NOT_STICKY states that you need not recreate service in case it is been killed.
If this is not the case then you have to manually kill it by your self.
Like
Intent lintent = new Intent(context, LocationService.class);
context.stopService(lintent);
You can use this code at point where your application kills.
That's it. You are good to go with this.
First of all, launch the "LocationService" on your app start:
public class MyApp extends Application {
private static final String TAG = "MyApp";
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "App started up");
startService(new Intent(this, MyLocationService.class));
}
}
Second :
As you said, the Service should better run with the "START_NOT_STICKY" flag
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Thrid:
Once the system kills your app, the Service will automatically be killed, so no problems at all.
There is no onDestroy() method on the Application object, the only similar event is onTerminated() and it is not being launched on production devices.
onTerminate
Added in API level 1 void onTerminate () This method is for use in
emulated process environments. It will never be called on a production
Android device, where processes are removed by simply killing them; no
user code (including this callback) is executed when doing so.
More information:
https://developer.android.com/reference/android/app/Application.html#onTerminate()
Btw, If you want the MyLocationService to send updates of the location to your app (when it is open), you should consider to use Otto or EventBus (I recommend you this last one because of the simplicity to use it). You can even configure the #Suscriber to receive updates of old retrieved locations if you want.
I will try to explain in a easiest way :)
There are two type of service
IntentService and Service
IntentService when started will kill itself once it treated the content of it onHandleIntent method
as for Service well this one will not end until you give it the command to do so even if your start it using the context of an activity. It will also stop when the application is stopped in an extreme case (by system (Settings/application/YourApp/stop app OR an app crash)
Easiest way is First of all start IntentService with AlarmManager at some repeating time (10 mintutes), then in onHandleIntent() get Location and store into preference.
No Need bind to your activity, the IntentService automatically stops itself after saved in preferences.
Yes you can stop the service in onDestroy() of the activity:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
service.stop();
super.onDestroy();
}
I have built an app for running. It runs an Activity with a timer shown in the user interface, a gps listener that collects coordinates and a lot of other things (the activity does a lot of work).
Now the request of my client is to move all the activity logic in a Service. In this way, when you start a running session, the Service would start and the notification (very simple, just with a static text) would appear. The activity should keep track of the work made in the Service (timer should go on, speed should be shown, ecc...). Tapping on the notification should bring up the activity. If the activity is closed or crashes the Service should keep going on and when you tap on the notification a new Activity should be brought up without the user noticing any difference (the timer should keep showing the right time, the average speed should comprehend the speeds relevated before the activity crash, ecc...).
I know there are a lot of ways to do that.
What I am asking is: what is the best way? Are there examples of such behavior from where to start? What are the common errors I should avoid? Are there best practices to follow?
Thank you
I developed an app with similar service behaviour. It also requires a service which collects data and some activities for showing the data.
For these kind of applications you want to keep the service alive until the user stopps it manualy but it is still possible for android that it kills the service if the device is low on memory.
For the service - activity interaction you need to bind to a service. A good documentation is available here: http://developer.android.com/guide/components/bound-services.html
Be sure to return START_STICKY in the onStartCommand function of the service. This will make sure the intent will be null when the service was restored by the system and tell android that you start and stop your service explicit.
When binding to the service from the activity you need to check if the service is ready (was not restored by the system). This can be done by adding a "ready" field inside the service that is false by default and is set to true if the onStartCommand intent is not null. Therefore you can react properly to a restored service and start the app from the beginning.
To keep the service alive with a high priority you need to call startForeground inside the service. This also requires to show a notification so the users knows a service is running in the background.
Inside service you can use local broadcastmanager.
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
broadcaster = LocalBroadcastManager.getInstance(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000);
return START_STICKY;
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DisplayLoggingInfo(); //do watever you want to push
handler.postDelayed(this, 1000); // 10 seconds
}
};
My application has an activity and a service running in the same process. When the user terminates the activity by clicking the STOP button, the activity causes the service to terminate.
From the Android documentation I understand that the system can kill a process to reclaim resources:
"Once your activity is stopped, the system might destroy the instance if it needs to recover system memory. In extreme cases, the system might simply kill your app process without calling the activity's final onDestroy() callback, ..."
Question 1: Is it possible for my activity to be killed but not the service? I would prefer my service remain alive.
If the answer is 'yes' then
Question 2: Is there a mechanism where the service can be notified that the activity has been killed?
IBinder.linkToDeath has the functionality I need but seems to apply to a process, not an activity.
I've thought of an indirect method like having the activity take ownership of semaphore and having the service use a thread to wait on it. Then when the activity gets killed it will release the semaphore and the service will get it, providing the notification. But I was wondering if there wasn't an android-centric technique I could use.
[begin edit]
After reading the very helpful comments you've provided I'd like to clarify the scenario I'm presenting.
I've started two components: an activity and a service. The application is configured so that service can continue to run after the activity has stopped and been destroyed. The user can restart/start the activity multiple times and it will use the same instance of the service.
Normally the activity will notify the service it has been destroyed during onDestroy(). But onDestroy() may not be called.
I'd like to know whether there is some android-specific mechanism I can use to notify the service that the activity has been killed without the call to its onDestroy() method having been made.
[end edit]
Thanks for your help.
Will
As I said before, single activity won't be killed by android without calling onDestroy(). If Android needs more memory it kills whole process(with all activities and services). Here is description, documentation is wrong about this.
Service can be also created in other process but it has to be set int the manifest. And then you can use iBinder to get notification when process(with all activities) is killed by Android
Yes services and activities can run independently of each other.
To achieve what you're trying to do I would explicitly start your service using startService() in your activity's onStart() function (or wherever you wish to launch it) and also bind to it at the same point. Binding without an explicit startService will cause the service to stop when you kill the activity (unless some other activity is still bound to it).
In your activity's onStop() call a function on your service to tell it the activity has been killed.
In your Activity:
private ServiceRecordJourney yourService;
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
YourServiceBinder binder = (YourServiceBinder) service;
yourService= binder.getService();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
}
};
#Override
public void onStart(){
super.onStart();
startService(new Intent(this, YourService.class));
// Bind to Service
Intent intent= new Intent(this, YourService.class);
bindService(intent, serviceConnection , Context.BIND_AUTO_CREATE);
}
#Override
public void onStop(){
super.onStop();
if(yourService != null){
yourService.activityKilledFunction();
unbindService(serviceConnection);
}
}
Your service will need to be foreground (and display a notification) to further stop it from being killed off by the OS. Also as it's been explicitly started you will need to handle an explicit stop on the service (either call stopSelf() on the service or stopService() in a context object.
You can handle communication to the service using multiple startService() calls with different intents but I prefer the above approach (and I'm sure that in the case binding is the preferable approach).
Also whilst the service is running the activity will bind and unbind to the service each time the activity is started or stopped by the user.
I got a service that start a new activity, while screen is off.
I want the activity to stay on paused mode, and not get to the stopped mode.
Is there a way to achieve this?
No. You don't have control over the Activity lifecycle. Any processes that you need to run while the screen is off must be executed in a Service. You must rebuild the application state whenever the screen is turned back on. Always assume the Activity can be wiped from memory at any time.
You can't do that. it will be killed anyway.
but you can use a Service to receive Broadcast of Intent.ACTION_SCREEN_ON and relaunch activity from Service.
to restart your Activity from service check here
There is no way to achieve this. Your app is tied to the Activity lifecycle, and has to break down/restore the Activities to work with the lifecycle.
You can't override the onDestroy() method, and each OS version handles how an application is "killed" differently.
The Android developer documentation makes reference to an application being in a “killable” state. While Android tries to keep the process of an application resident even after it has exited (i.e. after onDestroy), it does need to be able to kill these processes in low-resource situations to reclaim memory. The states in which an application is killable differ per OS version. On all versions of Android, applications that have returned from onStop or onDestroy are silently killable. On versions of Android prior to Honeycomb, applications that had returned from onPause were also killable. Being killable simple means that Android reserves the right to terminate your application’s process at any time without running even another instruction of your app’s code. In other words, if you have any state that must be recoverable (such as a player’s game progress, items, awards, etc) you must save those to persistent storage no later than the last callback before entering a killable state.
In addition, while applications can run native threads even when they are in a killable
state and even post-onDestroy, this is to be avoided, since the process kill will also kill those threads. This could cause all manner of corruption and shutdown issues.
Source
I do not exactly now what you mean with paused mode or stopped mode. If you mean that the cpu keep wake up take a look at this.
With partial_wake_look you can have a long running AsyncTask for example also when the screen is of. Dont't forget to release the wakelook.
Why do you need to do this? Maybe best solution is to run it as a service as suggested by #DeeV. However, depending of what you need to do, this could help:
Ask Android to notify you when screen is turned on (and off if required). So your activity can be resumed and started immediately and you can perform any action.
To do that:
Create a class which extends Application
Register it in your Manifest:
In public void onCreate() {..., add this:
IntentFilter ioff = new IntentFilter(Intent.ACTION_SCREEN_OFF);
IntentFilter ion = new IntentFilter(Intent.ACTION_SCREEN_ON);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
//TODO
} else {
//TODO
}
}
};
context.registerReceiver(broadcastReceiver, ioff);
context.registerReceiver(broadcastReceiver, ion);
in public void onTerminate() {..., add this:
if (broadcastReceiver != null) {
context.unregisterReceiver(broadcastReceiver);
}
Lame hack would be to call onPause() method inside onStop() of activity
I have a VOIP Application, I need to login the application in background on device bootup.
Currently the init to my application is done on UI Active(onCreate()).
I have the following things in my mind, can anyone help and clear my doubts.
The service design is must to achieve this task??
Which Service Remote(AIDL) or Local Service and why?
How does the UI and Service interaction happens?
After UI is active who gets the Call- Backs? UI or Service?
Should i make Service as my Controller i.e Service to UI data Pass Vice-versa?
Sample App: Skype.
So there are many ways to achieve what you want, it is a matter of what fits your style and design better. Hopefully you will find this information useful.
For the application to login in the background on startup there are a few option. The first thing you will need is a BroadcastReceiver which is defined as a receiver in the manifest. Have the BroadcastReceiver catch the ACTION_BOOT_COMPLETED intent. From here you can launch your Service. This leads to #2.
If all you are doing are RESTful calls then really an IntentService would be ideal. The difference between an IntentService and a Service is simple: An IntentService runs off of the main thread, executes it's 'code' and dies. A Service, however runs on the main thread (this is an important fact) and is long running so it has to be told to stopSelf(). To take matters further, a Service is also less likely to be killed compared to an Activity (application components are killed to make room in memory for newly launched apps), ie. it takes higher precedence. The service can also be declared a foreground service which requires a notification but give even higher precedence. I think in your case a Service would be perfect.
Once your UI (Activity) is opened the best way to connect to the Service would be the Binder. This will allow multiple interfaces to the Service from different applications / components if need be. AIDL is pretty cool stuff but from my experience much harder to manage since all parameters must be primitive or Parcables. AIDL is also slower an less efficient because it is really a form of IPC. When a Service is started with an intent the onStartCommand() method is called. If the service is started by an application trying to bind to it then the onBind() method is called. But you can start the Service with and Intent and then bind to it. If you prefer the RESTful approach where you just have quick calls for data you can use an IntentService with a ResultReceiver. This is a great article written about Google I/O examples and just overall well implemented if you are interested in the IntentService and ResultReceiver.
This is up to you. Using the Binder or AIDL your Activity can call the Service methods just like object method where the 'callback' would just be the method return. If you use a ResultReceiver the Activity interfacing the Receiver would be the callback. You could also just pass Intents back and forth but this could get messy. Again for your case the Binder approach would be good as well as a Receiver.
Think of the Service as a model in the MVVM system - use it as a helper to get data from, not as something that controls the logic of the application.
Sorry if this seems messy there are so many ways to achieve what you are looking for. Its just a matter of what fits your situation best what you 'feel' is better. Not to mention the Android SDK is pretty large. I tried to hit on all the topics that could help you out. Good luck!
Try a service with a boot reciever. Here is an example I found after a quick google search. Then make sure to store in the login info somewhere for when the app starts. Not sure what callbacks you might have, so really hard to answer that part. I would say that if the callbacks should affect the UI then let the activity take them over when it starts up. If you need a UI when only the service is running, probably best to throw up a notification and have it call the appropriate activity with the callback data.
you can authanticate user login by background services
package com.javaorigin.android.sample.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
String tag="TestService";
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service created...", Toast.LENGTH_LONG).show();
Log.i(tag, "Service created...");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(tag, "Service started...");
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class SampleAction extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView view = new TextView(this);
view.setText("Service Test");
Intent i = new Intent();
i.setClassName( "com.javaorigin.android.sample.service",
"com.javaorigin.android.sample.service.MyService" );
bindService( i, null, Context.BIND_AUTO_CREATE);
this.startService(i);
setContentView(view);
}
}
If you login is takes so long use [AccountManager][1] and do it only once.
The idea behind the AccountManager a token or whatever credentials you need to use in your Service.
In your particular case I think the best way of communicating your Activity with the Service is binding to it.
Best source of knowledge about basic Service usage is SDK. Long story short AIDL is used for IPC communications and as long as you run the service in the same process you don't need it. I suppose you have two options:
If the only thing you need is just login, you can start a service on boot up, login and then i.e. send a sticky broadcast with bundled login data which will be then received in application. See this question for a good set of ways to start a service on boot up.
#Override
public void onCreate() {
Data data = performLogin();
Intent i = new Intent(ACTION_VOIP_LOGIN);
i.putExtra(EXTRA_LOGIN_DATA, data);
mContext.sendStickyBroadcast(i);
}
...
private final class LoginReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// You may use a Bundle instead
Data data = intent.getParcelableExtra();
processLoginData(data)
}
}
protected void onCreate(Bundle savedInstanceState) {
...
IntentFilter filter = new IntentFilter(ACTION_VOIP_LOGIN);
mContext.registerReceiver(new LoginReceiver(), filter);
}
In second case you might want to move all your logic to the service. Here you'll extend the Binder class. See this SDK article for details.