15

In my project I need to create a service in android. I am able to register the service like this :

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >

   <service   android:enabled="true"
    android:name=".ServiceTemplate"/>
      <activity
        android:name=".SampleServiceActivity"
        android:label="@string/app_name" >
        <intent-filter>
         <action android:name="android.intent.action.MAIN" />
         <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
     </activity>
</application>

I am calling this service inside an activity like below:-

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Intent service = new Intent(getApplicationContext(), ServiceTemplate.class);
    this.startService(service);
}

But if I kill the current activity , the service is also destroyed. I need this service always running in the background. What I need to do? How do I register the service? How do I start the service?

gprathour
  • 14,813
  • 5
  • 66
  • 90
Sathish
  • 1,481
  • 5
  • 20
  • 33

6 Answers6

17

Here is a semi-different way to keep the service going forever. There is ways to kill it in code if you'd wish

Background Service:

package com.ex.ample;

import android.app.Service;
import android.content.*;
import android.os.*;
import android.widget.Toast;

public class BackgroundService extends Service {

    public Context context = this;
    public Handler handler = null;
    public static Runnable runnable = null;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        Toast.makeText(this, "Service created!", Toast.LENGTH_LONG).show();

        handler = new Handler();
        runnable = new Runnable() {
            public void run() {
                Toast.makeText(context, "Service is still running", Toast.LENGTH_LONG).show();
                handler.postDelayed(runnable, 10000);
            }
        };

        handler.postDelayed(runnable, 15000);
    }

    @Override
    public void onDestroy() {
        /* IF YOU WANT THIS SERVICE KILLED WITH THE APP THEN UNCOMMENT THE FOLLOWING LINE */
        //handler.removeCallbacks(runnable);
        Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onStart(Intent intent, int startid) {
        Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show();
    }
}

Here is how you start it from your main activity or wherever you wish:

startService(new Intent(this, BackgroundService.class));

onDestroy() will get called when the application gets closed or killed but the runnable just starts it right back up. You need to remove the handler callbacks as well.

I hope this helps someone out.

The reason why some people do this is because of corporate applications where in some instances the users/employees must not be able to stop certain things :)

https://i.stack.imgur.com/rdUBn.png

Pierre
  • 8,397
  • 4
  • 64
  • 80
  • 3
    Yes, `` but this answer is old. For a newer solution, check out https://github.com/evernote/android-job – Pierre Mar 14 '18 at 10:50
  • 2
    thank you, this answer is enough for me, after declaring service in the manifest it works! and to stop Service I use onDestroy(){ super.onDestroy(); stopService(new Intent(BackgroundService.class)); } on Activity, it stop any background service when application closed – Faisal Mar 14 '18 at 16:03
  • @Pierre How can I stop/kill the started Service from an Activity? I mean when handler.removeCallbacks(runnable); is commented in onDestory() - it means that business wants to still alive started service for example when the application is minimized or closed. So, how could I stop/kill this kind of service, when handler.removeCallbacks(runnable); is commented? – Mikheil Zhghenti Mar 04 '19 at 21:41
  • @MishoZhghenti try `BackgroundService.runnable = null;` from any activity. runnable is public static. Or you will have to override `onHandleIntent` in `BackgroundService` then create an `Intent i = new Intent(this, BackgroundService.class);` then `i.setAction("com.app.bgservice.kill")` and call `startService(intent);`. In onHandleIntent check `if(intent.getAction() == "com.app.bgservice.kill") { handler.removeCallbacks(runnable);}` – Pierre Mar 05 '19 at 05:23
6

But if am kill the current activity the service also is killing. I need this service always running in the background. What I need to do?

If by "kill the current activity" you mean that you are using a task killer, or Force Stop from within the Settings app, your service will be stopped. There is nothing you can do about that. The user has indicated they do not want your app to run any more; please respect the user's wishes.

If by "kill the current activity" you mean you pressed BACK or HOME or something, then the service should keep running, at least for a little while, unless you call stopService(). It will not keep running forever -- Android will eventually get rid of the service, because too many developers write services that try to be "always running in the background". And. of course, the user can kill the service whenever the user wants to.

A service should only be "running" when it is actively delivering value to the user. This usually means the service should not be "always running in the background". Instead, use AlarmManager and an IntentService to do work on a periodic basis.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I am killing the current activity by adb shell kill command. Just I like to create the service like alarm, sms notification... – Sathish Feb 07 '12 at 14:25
  • 1
    @Sathish: I am not aware that the "adb shell kill command" is documented, and so I do not know what its characteristics are. – CommonsWare Feb 07 '12 at 17:12
  • 1
    But if the Application is closed will the AlarmManager able to trigger AlarmReceiver which internally triggers IntentService that performs actual task? – Naga Feb 28 '19 at 15:47
  • @Naga: I am uncertain what you mean by "closed". If you mean "the user navigated to another app, and your process was terminated after a while", that is perfectly normal and does not harm your `AlarmManager` setup. If you mean "the user swiped the app off of the overview screen", that too is not supposed to harm your `AlarmManager` setup. I have seen a bunch of complaints here on Stack Overflow that swiping a task from the overview screen does cause problems, but I have never been able to reproduce that behavior. – CommonsWare Mar 03 '19 at 20:59
  • 1
    @CommonsWare my hybrid app is getting closed by Android OS after certain period of time, in my App also has some native Java code which creates Alarms & handles it through receiver class, this scenario works perfectly as long the App is in foreground or background but once the App gets killed by OS the receiver is not triggered even if has process:remote attribute setting for this receiver in AndroidManifeast.xml, please suggest – Naga Mar 04 '19 at 10:02
  • @Naga: I do not know what "killed by the OS" means. You might consider using `adb shell dumpsys alarm` to see if your alarm is still scheduled. If it is, then most likely your problem lies in the code that is being executed as a result of the alarm. – CommonsWare Mar 04 '19 at 11:19
5

you can create background service and call that by AlarmManager

1- you have to create a BroadcastReceiver class for calling by AlarmManager

public class AlarmReceiver extends BroadcastReceiver

{
    /**

     * Triggered by the Alarm periodically (starts the service to run task)

     * @param context

     * @param intent

     */

    @Override

    public void onReceive(Context context, Intent intent)

    {

        Intent i = new Intent(context, AlmasService.class);

        i.putExtra("foo", "AlarmReceiver");

        context.startService(i);

    }

}

2-you have to create a IntentService class for calling by AlarmReceiver

public class AlmasService extends IntentService

{

    public Context context=null;

    // Must create a default constructor
    public AlmasService() {

        // Used to name the worker thread, important only for debugging.
        super("test-service");

    }

    @Override

    public void onCreate() {

        super.onCreate(); // if you override onCreate(), make sure to call super().

    }


    @Override
    protected void onHandleIntent(Intent intent) {

        context=this;
        try

        {

            Thread.sleep(5000);

        }

        catch (InterruptedException e)

        {

            e.printStackTrace();

        }



        String val = intent.getStringExtra("foo");

        // Do the task here
        Log.i("MyTestService", val);

    }

}

3- you have to add AlarmReceiver as receiver and AlmasService as service on manifest

    <service
        android:name=".ServicesManagers.AlmasService"
        android:exported="false"/>

    <receiver
        android:name=".ServicesManagers.AlmasAlarmReceiver"
        android:process=":remote" >
    </receiver>

4-now you can start service and call AlarmManager on MainActivity

public class MainActivity extends AppCompatActivity
{
    public static final int REQUEST_CODE = (int) new Date().getTime();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        scheduleAlarm();
    }

    public void scheduleAlarm()
    {
        // Construct an intent that will execute the AlarmReceiver
        Intent intent = new Intent(getApplicationContext(), AlmasAlarmReceiver.class);
        // Create a PendingIntent to be triggered when the alarm goes off
        final PendingIntent pIntent = PendingIntent.getBroadcast(
                this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // Setup periodic alarm every every half hour from this point onwards
        long firstMillis = System.currentTimeMillis(); // alarm is set right away
        AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        // First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
        // Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
        alarm.setRepeating(AlarmManager.RTC_WAKEUP, firstMillis, (long) (1000 * 60), pIntent);



    }
}
Milad Ahmadi
  • 1,019
  • 12
  • 19
  • The service is triggered by AlarmReceiver which is called by AlarmManager so, if the application is terminated AlarmManager cannot invoke AlarmReceiver, this solution is dependent on Application – Naga Feb 28 '19 at 15:40
4

Try to start the service in separate thread, so that when you will destroy your activity the service will not be affected. It will run without any interruption. Also, in the service return Service.START_STICKY from onStartCommand(intent, flags, startId) to make sure that the service is re-created if it is killed by the system (Android OS).

abhi
  • 1,412
  • 19
  • 25
1

override this method:

public int onStartCommand(Intent intent, int flags, int startId) {
    return Service.START_STICKY;
}
Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
Mohammad Ersan
  • 12,304
  • 8
  • 54
  • 77
0

to complete what @abhinav said : if you use onBind() you dont need to use onStartCommand() and vice versa :

in fact, If a component calls bindService() to create the service and onStartCommand() is not called, the service runs only as long as the component is bound to it. After the service is unbound from all of its clients, the system destroys it. To illustrate: onStartCommand() methos is called when your Service begins to do its work. onCreate() has completed and it is ready to get to doing what needs to be done. and if you use onBind() method, you tie the Service to the lifespan of, for example, an Activity. If the Activity completes then the Service is allowed to be released and can itself finish. The Service will last as long as there is something still bound to it.

Sanam Yavarpor
  • 348
  • 3
  • 10