服務可由其餘應用組件啓動,並且即便用戶切換到其餘應用,服務仍將在後臺繼續運行。此外,組件可經過綁定到服務與之進行交互,甚至是執行進程間通訊 (IPC)android
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" />
複製代碼
public class MyService extends Service {
private static final String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "--------onCreate: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "--------onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "--------onBind: ");
// TODO: Return the communication channel to the service.
return new InnerBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "--------onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.d(TAG, "--------onRebind: ");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "--------onDestroy: ");
}
}
複製代碼
1.startServicebash
2.bindService網絡
佈局文件:app
<string name="button">啓動服務</string>
<string name="button2">中止服務</string>
<string name="button3">調用服務內部方法</string>
<string name="button4">綁定服務</string>
<string name="button5">解綁服務</string>
複製代碼
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:onClick="startServiceClick"
android:text="@string/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="stopServiceClick"
android:text="@string/button2"
app:layout_constraintStart_toStartOf="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/button" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="188dp"
android:onClick="callService"
android:text="@string/button3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:onClick="bindService"
android:text="@string/button4"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="unBindService"
android:text="@string/button5"
app:layout_constraintBottom_toTopOf="@+id/button3"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/button4"
app:layout_constraintVertical_bias="0.298" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
複製代碼
接口定義:ide
public interface ICommunication {
void callServiceInnerMethod();
}
複製代碼
Service實現:佈局
public class MyService extends Service {
private static final String TAG = "MyService";
//自定義一個Binder內部類實現ICommunication接口實現服務的通信
private class InnerBinder extends Binder implements ICommunication{
@Override
public void callServiceInnerMethod() {
sayHello();
}
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "--------onCreate: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "--------onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "--------onBind: ");
// TODO: Return the communication channel to the service.
return new InnerBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "--------onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.d(TAG, "--------onRebind: ");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "--------onDestroy: ");
}
private void sayHello(){
Toast.makeText(this,"Hello World!",Toast.LENGTH_SHORT).show();
}
}
複製代碼
Activity實現:ui
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private boolean mIsServiceBind;
private ICommunication mICommunication;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "--------onCreate: ");
}
/**
* 開啓服務
*/
public void startServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, MyService.class);
startService(intent);
}
/**
* 中止服務
*/
public void stopServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, MyService.class);
stopService(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "--------onDestroy: ");
}
public void callService(View view) {
mICommunication.callServiceInnerMethod();
}
/**
* 綁定服務
*/
public void bindService(View view) {
Intent intent = new Intent();
intent.setClass(this, MyService.class);
mIsServiceBind = bindService(intent, mConnection, BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "--------onServiceConnected: ");
mICommunication = (ICommunication) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "--------onServiceDisconnected: ");
mICommunication = null;
}
};
/**
* 解綁服務
*/
public void unBindService(View view) {
if (mConnection != null && mIsServiceBind) {
unbindService(mConnection);
}
}
}
複製代碼
onCreate ——> onStartCommand ——> onDestory
複製代碼
onCreate ——> onBind ——> onUnbind ——> onDestory
複製代碼
前臺服務是用戶主動意識到的服務,不是內存不足時系統要殺死的候選對象。前臺服務必須爲狀態欄提供一個通知,該通知位於「正在進行」標題下。這意味着除非服務中止或從前臺刪除,不然沒法取消該通知。this
注意:使用時須要添加權限spa
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
複製代碼
public class MyForegroundService extends Service {
public MyForegroundService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
//後面一個參數爲渠道參數,Android8.0新增要求
Notification notification = new NotificationCompat.Builder(this, "foreground")
.setContentTitle("這是標題")
.setContentText("這是內容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pi)
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = null;
//Android8.0要求設置通知渠道
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
channel = new NotificationChannel("foreground", "foregroundName", NotificationManager.IMPORTANCE_HIGH);
if (notificationManager != null) notificationManager.createNotificationChannel(channel);
}
//給startForeground()的整數ID不能爲0
startForeground(1, notification);
}
@Override
public void onDestroy() {
stopForeground(true);// 中止前臺服務 參數:表示是否移除以前的通知
super.onDestroy();
}
}
複製代碼
注意:給startForeground()的整數ID不能爲0線程
Activity中啓動此服務:
/**
* 啓動前臺服務
*/
public void startFServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, MyForegroundService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
}
}
複製代碼