服务可由其余应用组件启动,并且即便用户切换到其余应用,服务仍将在后台继续运行。此外,组件可经过绑定到服务与之进行交互,甚至是执行进程间通讯 (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);
}
}
复制代码