0

Many examples and tutorials for services on Android are for bound services, but what if I want to create an unbound service and not have to deal with binding at all?

 

Note to potential downvoters

Please read up on why answering your own questions is a good thing before downvoting.

Community
  • 1
  • 1
Magnus
  • 17,157
  • 19
  • 104
  • 189
  • Did you just answer your own post within a minute...!? – Shaishav Jul 31 '16 at 17:33
  • @Shaishav Yes I did. In fact, I answered it before I even posted it, using the checkbox at the bottom of the "Ask a question" page. I couldn't find any clear and complete demos for how to create a simple unbound service here on Stackoverflow, so I thought I'd post my own now that I know how to do it. [Read more about answering your own questions here.](http://stackoverflow.com/help/self-answer) – Magnus Jul 31 '16 at 18:10
  • Cool. Thanks for the info. – Shaishav Jul 31 '16 at 18:15
  • Don't they have SO Documentation for these things now? – Shaishav Jul 31 '16 at 19:00
  • Hey, I guess they do, thanks! I added it to the service documentation there. – Magnus Jul 31 '16 at 19:42

1 Answers1

1

The first thing to do is to add the service to your manifest, inside the <application> tag:

<application ...>

    ...        

    <service
        android:name=".RecordingService"
        android:exported="false">

</application>

Then we create the actual service class:

public class RecordingService extends Service {
    private int NOTIFICATION = 1; // Unique identifier for our notification

    public static boolean isRunning = false;
    public static RecordingService instance = null;


    private NotificationManager notificationManager = null;


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

    @Override
    public void onCreate(){
        instance = this;
        isRunning = true;

        notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)        // the status icon
                .setTicker("Service running...")           // the status text
                .setWhen(System.currentTimeMillis())       // the time stamp
                .setContentTitle("My App")                 // the label of the entry
                .setContentText("Service running...")      // the content of the entry
                .setContentIntent(contentIntent)           // the intent to send when the entry is clicked
                .setOngoing(true)                          // make persistent (disable swipe-away)
                .build();

        // Start service in foreground mode
        startForeground(NOTIFICATION, notification);

        return START_STICKY;
    }


    @Override
    public void onDestroy(){
        isRunning = false;
        instance = null;

        notificationManager.cancel(NOTIFICATION); // Remove notification

        super.onDestroy();
    }


    public void doSomething(){
        Toast.makeText(getApplicationContext(), "Doing stuff from service...", Toast.LENGTH_SHORT).show();
    }

}

All this service does is show a notification when it's running, and it can display toasts when its doSomething() method is called.

As you'll notice, it's implemented as a singleton, keeping track of its own instance - but without the usual static singleton factory method because services are naturally singletons and are created by intents. The instance is useful to the outside to get a "handle" to the service when it's running.

Last, we need to start and stop the service from an activity:

public void startOrStopService(){
    if( RecordingService.isRunning ){
        // Stop service
        Intent intent = new Intent(this, RecordingService.class);
        stopService(intent);
    }
    else {
        // Start service
        Intent intent = new Intent(this, RecordingService.class);
        startService(intent);
    }
}

In this example, the service is started and stopped by the same method, depending on it's current state.

We can also invoke the doSomething() method from our activity:

public void makeServiceDoSomething(){
    if( RecordingService.isRunning )
        RecordingService.instance.doSomething();
}
Magnus
  • 17,157
  • 19
  • 104
  • 189