建立未繫結的服務
首先要做的是將服務新增到 AndroidManifest.xml
標籤內的 AndroidManifest.xml
:
<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>
如果你打算在單獨的包中管理服務類(例如:.AllServices.RecordingService),那麼你需要指定服務的位置。因此,在上述情況下,我們將修改:
android:name=".RecordingService"
至
android:name=".AllServices.RecordingService"
或者最簡單的方法是指定完整的包名稱。
然後我們建立實際的服務類:
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();
}
}
所有這些服務都在執行時顯示通知,並且在呼叫 doSomething()
方法時可以顯示 toasts。
正如你將注意到的,它被實現為單例 ,跟蹤它自己的例項 - 但是沒有通常的靜態單例工廠方法,因為服務是自然的單例並且是由意圖建立的。該例項對於外部有用,可以在服務執行時獲得服務的控制代碼。
最後,我們需要從活動中啟動和停止服務:
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);
}
}
在此示例中,服務以相同的方法啟動和停止,具體取決於它的當前狀態。
我們也可以從我們的活動中呼叫 doSomething()
方法:
public void makeServiceDoSomething(){
if( RecordingService.isRunning )
RecordingService.instance.doSomething();
}