Search code examples
androidandroid-serviceandroid-service-binding

How do I create an unbound service in Android?


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.


Solution

  • 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();
    }