I want to start an Android Service after killing the application and close service after done specific method.
If it's possible then a snippet or a sample would be very welcome.
In Android Studio:
Choose File > New > Service > Service.
Give it a name then click finish.
It will now create a new class with the name you entered and register it in the manifest for you.
All you have to do now is override onStartCommand and return the integer constant START_STICKY to let the system know you would like the service to be running even after the application is removed from recents...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service started!", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
Now you can stop the service anywhere in your code calling stopSelf();
Related
I have two Application A and B.In app B I have a service that I can run it from app A. I want to send data to app B with intent but always my intent is null!
I run app B's service from app A with this Code:
try {
String packageName = "app_B_package";
String appService = packageName + ".activity.InternetService";
Intent start = new Intent();
start.setComponent(new ComponentName(packageName, appService));
start.putExtra("LAUNCHER_COMMAND_CLOSE" , true);
G.context.startService(start);
} catch (Exception e) {
e.printStackTrace();
}
But when service of app B will run the intent is null. This is onStart of the service in app B:
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i("LOGO_OFFICE_IN", "onStart");
if (intent != null) {
if (intent.getExtras().getBoolean("LAUNCHER_COMMAND_CLOSE")) {
Tools.clearApplicationData(InternetService.this);
new AppStatus(InternetService.this).isAppRunning(getPackageName(), true);
}
}
}
Why my intent is null all the time? I can't find it out.
Thank you for your help.
It looks like your service is type fire-and-forget - it does one quick thing and should quit immediately because it's done. Correct?
1. Don't leave your idle service running
Documentation says
If a component starts the service by calling startService() (which results in a call to onStartCommand()), the service continues to run until it stops itself with stopSelf() or another component stops it by calling stopService().
so after your workload is done call stopSelf().
When your service is not running there's nothing to restart.
2. Use correct start mode
Unless you stop it, your service is by default automatically restarted after it's killed by system (because system needed resources). The default mode is called START_STICKY and does this:
This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.
Since your service is a quick one-time job, it makes no sense for it do be restarted later at an arbitrary time.
To let Android know, you should return START_NOT_STICKY from onStartCommand.
3. Use current API
Don't use onStart, it was deprecated 9 years ago. It doesn't support start modes mentioned above. Implement onStartCommand instead. Your service would look like this:
#Override
public void onStartCommand(Intent intent, int flags, int startId) {
// No super call.
Log.i("LOGO_OFFICE_IN", "onStart");
// Intent cannot be null.
if (intent.getExtras().getBoolean("LAUNCHER_COMMAND_CLOSE")) {
Tools.clearApplicationData(InternetService.this);
new AppStatus(InternetService.this).isAppRunning(getPackageName(), true);
}
stopSelf(); // Work is done, stop service.
return START_NOT_STICKY; // Don't restart if killed.
}
Now that I think of it, only step 1 is absolutely necessary. Anyway, get into habit of using current APIs and finding out how things work.
I have an android app with service that has to track user's location even with closed application only if user set flag in app. So I start service in code after user clicks button and stop when he clicks it again with following code
alarm.changeAlarmStatus();
if(alarm.getAlarmStatus()) {
SharedPreferences.Editor ed = alarmPreferences.edit();
ed.putFloat("MARKER_LATITUDE", (float) theMarker.getPosition().latitude);
ed.putFloat("MARKER_LONGITUDE", (float) theMarker.getPosition().longitude);
ed.commit();
startService(myIntent);
}
else{
stopService(myIntent);
}
It seems to work fine. Service works and does what it should. But problem is if I close application through the task manager I see in logcat that Service starts again(but only if service is already working) and it causes nullPointerException because intent is null. You can see in this code why it happens
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Bundle bundle = intent.getExtras();
alarm = (Alarm) bundle.getSerializable("alarm");
Log.d("service","On Start Command is called ");
serviceIntent = intent;
return START_STICKY;
}
However I need to start my service only by pressing button and no other way. Does anyone know how to fix that?
Return START_NOT_STICKY in onStartCommand instead of START_STICKY.
If START_STICKY is returned, system will try to re-create service after it is killed.
If START_NOT_STICKY is returned, system will not try to re-create service after it is killed.
I'm trying to do a StartedService in android to send periodically the user location to a server.
Until this moment I managed to create the service and starting it from the 'parent ' application and I don't know how to keep it alive after the application was killed. From what I found on internet the 'StartCommandResult.Sticky' should restart the service if this one is killed but from some reason this is not restarted.
I overried the OnStartCommand:
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
locationTask = new Task(() =>
{
//stuff to do
});
locationTask.Start();
return StartCommandResult.Sticky;
}
And the service is started like this:
Intent intent = new Intent(this.Activity, Class.FromType(typeof(LocationService)));
this.Activity.StartService(intent);
Any suggestions what should I do in order to keep my service alive after the application was killed?
As observation I'm using xamarin to do it, but I won't mind an answer in android(java).
As stated in the official documentation:
A service is "started" when an application component (such as an
activity) starts it by calling startService(). Once started, a service
can run in the background indefinitely, even if the component that
started it is destroyed. Usually, a started service performs a
single operation and does not return a result to the caller. For
example, it might download or upload a file over the network. When the
operation is done, the service should stop itself.
So, starting the service like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
Will have your service running even while your app is destroyed.
Regarding Service.START_STICKY in the official documentation:
If the system kills the service after onStartCommand() returns,
recreate the service and call onStartCommand(), but do not redeliver
the last intent. Instead, the system calls onStartCommand() with a
null intent, unless there were pending intents to start the service,
in which case, those intents are delivered. This is suitable for media
players (or similar services) that are not executing commands, but
running indefinitely and waiting for a job.
This is how I do it but its in JAVA code.
in your service you should implement a LocalBinder, onStartCommand and onCreate methods.
public class LocalBinder extends Binder {
ServiceName getService() {
return ServiceName .this;
}
}
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
The onStartCommand should return START_STICKY;. And also, include this code on your Service:
#Override
public void onTaskRemoved(Intent rootIntent) {
// TODO Auto-generated method stub
Intent restartService = new Intent(getApplicationContext(),this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartServicePI = PendingIntent.getService(getApplicationContext(), 1, restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() +1000, restartServicePI);
}
This will restart your Service on 1 second from the time you close it. Also, dont forget to add your service in your AndroidManifest.xml
<service android:name=".ServiceName"
android:exported="false"
android:stopWithTask="false" >
</service>
Override onStartCommand like this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
For me, everything in the code was right but the problem was with the use of debugging while checking if the service was on. When I use a release version (or just dev version without connecting to the debug), the process is not killed and the service is running normally.
No idea why though. I am using Xamarin Studio 6.0.
I am building an application using PhoneGap, which revolves around a timer I have created. I am struggling at the moment as I need a way of having the app open itself if the timer reaches zero. I have currently put in place a notification for when the timer runs out, and the user can launch the app from there. However I need a way of launching the app if the user "misses" the notification or something similar.
For example, when the timer on the local "timer" app on a mobile device runs out, it will open itself to notify the user that the time has ran out.
Any suggestion would be appreciated,
Thanks.
Just write the code for opening the launcher Activity instead of showing notification in your service class.When the timer runs out the launcher activity will start instead of notification.
the code will look similar to this:
public class AlarmService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//calling Launcher Activity
Intent alarmIntent = new Intent(getBaseContext(), AlarmScreen.class);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmIntent.putExtras(intent);
getApplication().startActivity(LauncherActivity.class);
AlarmManagerHelper.setAlarms(this);
return super.onStartCommand(intent, flags, startId);
}
}
I hope you are satisfied with this answer.
Application thread get close if its killed by task manager. Need to re-invoke application as though its killed by other application or task manager. Any idea?
You have to run background service with START_STICKY command.
Just extends Service and override onCommand like this :
#Override
public int onStartCommand(Intent intent,int flags,int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
Like this your Service is restart when it's close (by system or anything else)
You just have now check on your service (onCreate for example) if application is running or not and launch it again if not. I suppose PackageManager let you check this or simply put a static boolean is_alive to see if your activity is always running.
Regards
Jim
Bug in Android 2.3 with START_STICKY
I needed to keep alive a Service with all my forces. If the service is running anytime you can pop the UI.
onDestroy()
it will re-launch.
Can't be uninstalled the app, because it has a Device Administrator.
It is a kind of parental control, the user knows it is there.
Only way to stop is to remove the Device Admin, and uninstall it, but removing Device Admin will lock the phone as Kaspersky how it does.
There are a loot of braodcast receivers, such as boot finshed, user presen, screen on, screen off... , many other, all starting the service, you can do it with UI too. Or in the service check if your activity alive , visible, if not, than pop it.
I hope you will use with good reason the info!
Edit: Restart service code snippet:
// restart service:
Context context = getApplicationContext();
Intent myService = new Intent(context, MyService.class);
context.startService(myService);
Edit2: add spippet to check if the service is running in ... a load of Broadcasts
public static boolean isMyServiceRunning(Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(service.service.getClassName())) {
Log.d("myTag", "true");
return true;
}
}
Log.d("myTag", "false");
return false;
}
Edit3 other service start:
public static void startTheService(Context context) {
Intent myService = new Intent(context, MyService.class);
context.startService(myService);
}
Dont't forget Android 2.3 bug: do the logic for initialization in
#Override
public void onCreate()
and not in:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
While look at Google IO official product source code I have found the following
((AlarmManager) context.getSystemService(ALARM_SERVICE))
.set(
AlarmManager.RTC,
System.currentTimeMillis() + jitterMillis,
PendingIntent.getBroadcast(
context,
0,
new Intent(context, TriggerSyncReceiver.class),
PendingIntent.FLAG_CANCEL_CURRENT));
URL for code
You can start a sticky service and register an alarm manager that will check again and again that is your application is alive if not then it will run it.
You can also make a receiver and register it for <action android:name="android.intent.action.BOOT_COMPLETED" /> then you can start your service from your receiver. I think there should be some broadcast message when OS or kills some service/application.
Just to give you a rough idea I have done this and its working
1) register receiver
Receiver Code:
#Override
public void onReceive(Context context, Intent intent) {
try {
this.mContext = context;
startService(intent.getAction());
uploadOnWifiConnected(intent);
} catch (Exception ex) {
Logger.logException(ex);
Console.showToastDelegate(mContext, R.string.msg_service_starup_failure, Toast.LENGTH_LONG);
}
}
private void startService(final String action) {
if (action.equalsIgnoreCase(ACTION_BOOT)) {
Util.startServiceSpawnProcessSingelton(mContext, mConnection);
} else if (action.equalsIgnoreCase(ACTION_SHUTDOWN)) {
}
}
Service Code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.logInfo("Service Started onStartCommand");
return Service.START_STICKY;
}
I prefer doing nothing in onStartCommand because it will get called each time you start service but onCreate is only called 1st time service is started, so I do most of the code in onCreate, that way I don't really care about weather service is already running or not.
according to #RetoMeyer from Google, the solution is to make the app "sticky".
for this, you must establisH START_STICKY in your intent service management.
check this reference from developer android
Yes, Once memory low issue comes android os starts killing application to compensate the required memory. Using services you can achieve this, your service should run parallely with your application but see, some of the cases even your service will be also killed at the same time. After killing if memory is sufficient android os itself try to restart the application not in all the cases. Finally there is no hard and fast rule to re-invoke your application once killed by os in all the cases it depends on os and internal behaviours.