Creating an unbound service
suggest changeThe first thing to do is to add the service to AndroidManifest.xml
, inside the <application>
tag:
<application ...>
...
<service
android:name=".RecordingService"
<!--"enabled" tag specifies Whether or not the service can be instantiated by the system — "true" -->
<!--if it can be, and "false" if not. The default value is "true".-->
android:enabled="true"
<!--exported tag specifies Whether or not components of other applications can invoke the -->
<!--service or interact with it — "true" if they can, and "false" if not. When the value-->
<!--is "false", only components of the same application or applications with the same user -->
<!--ID can start the service or bind to it.-->
android:exported="false" />
</application>
If your intend to manage your service class in a separate package (eg: .AllServices.RecordingService) then you will need to specify where your service is located. So, in above case we will modify:
android:name=".RecordingService"
to
android:name=".AllServices.RecordingService"
or the easiest way of doing so is to specify the full package name.
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();
}