什么是服务
当谈论 Android 应用组件时,服务(Service)是四大组件之一,用于在后台执行长时间运行的操作或为多个组件提供共享的处理。服务没有用户界面,通常在后台运行,并且可以与其他应用组件进行通信。以下是关于 Android 服务的一些重要概念和讲解:
1. 服务的类型:
-
前台服务(Foreground Service):
- 在通知栏显示一个通知,使用户知晓服务正在运行。
- 常用于执行用户明确请求的操作,如音乐播放器或下载服务。
-
后台服务(Background Service):
- 在后台默默执行任务,用户通常不直接感知。
- 例如,检查新邮件或上传数据。
2. 服务的生命周期:
服务有三种状态:
-
创建(Created):
- 通过调用
startService()
或bindService()
启动服务时进入此状态。 onCreate()
和onStartCommand()
方法会被调用。
- 通过调用
-
运行(Started/Running):
- 服务正在执行任务。
onStartCommand()
方法中定义的逻辑在此时执行。
-
销毁(Destroyed):
- 通过调用
stopSelf()
或stopService()
终止服务。 onDestroy()
方法被调用。
- 通过调用
3. 服务的通信方式:
服务可以与其他组件进行通信:
-
启动服务(Start Service):
- 使用
startService()
方法启动服务。 - 通过 Intent 传递数据。
- 使用
-
绑定服务(Bind Service):
- 使用
bindService()
方法启动服务。 - 返回一个用于与服务通信的 IBinder 对象。
- 使用
4. 在清单文件中声明服务:
在 AndroidManifest.xml 文件中声明服务:
<service
android:name=".MyService"
android:enabled="true"
android:exported="false">
<!-- 可以添加其他属性 -->
</service>
示例详解
1、启动服务(startService
)
-
生命周期独立: 启动服务的生命周期与启动它的组件(通常是Activity)独立。即使启动服务的组件被销毁,服务仍然可以在后台继续执行。
-
返回结果:
startService()
方法通常用于执行一次性任务,并且可以通过startService()
的返回值或者服务中的onStartCommand()
方法中的返回值传递结果。 -
多个组件: 多个组件可以同时启动同一个服务,而且服务只会有一个实例(即使被多个组件启动)。
-
通信通过Intent: 通过Intent传递数据给服务。
-
不可直接调用服务中的方法: 服务的方法不会直接暴露给其他组件,而是通过Intent传递数据。
/**
* @ClassName ServiceBackground
* @Description 后台服务 通常用于在后台执行长时间运行的任务,例如下载、数据同步等。
* @Author ZMROBO
* @Date 2023/12/26 16:35
*/
public class ServiceStudy extends Service {
private static String TAG="ServiceStudy";
/**
* @description 不需要绑定 可以返回null
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
MlogUtil.d(TAG,"onBind");
return null;
}
/**
* @description 生命周期 1
*/
@Override
public void onCreate() {
super.onCreate();
MlogUtil.d(TAG,"onCreate");
}
/**
* @description 生命周期 2 在这里执行逻辑
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
MlogUtil.d(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
/**
* @description 生命周期 3
*/
@Override
public void onDestroy() {
super.onDestroy();
MlogUtil.d(TAG,"onDestroy");
}
}
//开启服务
intent = new Intent(this, ServiceBackgroundForStart.class);
startService(intent);
3、绑定服务( bindService
)
-
生命周期绑定: 绑定服务的生命周期与绑定它的组件(通常是Activity)相关联。当绑定的组件被销毁时,服务也会被解绑。
-
返回结果:
bindService()
方法允许组件绑定到服务,并返回一个可以用于与服务进行通信的IBinder
对象。这使得组件能够调用服务中的方法。 -
单一组件: 绑定服务通常是为了在一个Activity中执行与服务相关的操作,因为一个服务只能被一个组件绑定。
-
直接调用服务中的方法: 绑定服务提供了直接调用服务中方法的方式,因为它返回一个可以用于与服务进行通信的
IBinder
对象。 -
通信通过IBinder: 绑定服务通常用于实现应用内的组件通信,而不是与外部服务通信。
/**
* @ClassName ServiceBackgroundForBind
* @Description 使用绑定的形式调用
* @Author ZMROBO
* @Date 2023/12/27 10:52
*/
public class ServiceBackgroundForBind extends Service {
private static final String TAG = ServiceBackgroundForBind.class.getSimpleName();
/**
* @description 创建MyBinder类
*/
private MyBinder myBinder = new MyBinder();
/**
* @description 返回IBinder对象
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
MlogUtil.d(TAG,"生命周期:onBind");
return myBinder;
}
@Override
public void onCreate() {
super.onCreate();
MlogUtil.d(TAG,"生命周期:onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
MlogUtil.d(TAG,"生命周期:onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
MlogUtil.d(TAG,"生命周期:onDestroy");
}
/**
* @description 暴露给外部调用
*/
public void doSomething() {
MlogUtil.d(TAG,"执行服务的逻辑");
}
/**
* @description IBInder类
*/
public class MyBinder extends Binder {
public ServiceBackgroundForBind getService() {
return ServiceBackgroundForBind.this;
}
}
}
使用
public class MainActivity extends BaseActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private Intent intent;
/**
* @description 是否绑定
*/
private boolean isBound = false;
private ServiceBackgroundForBind service;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*start服务
intent = new Intent(this, ServiceBackgroundForStart.class);
startService(intent);*/
//绑定服务
intent = new Intent(this, ServiceBackgroundForBind.class);
// Context.BIND_AUTO_CREATE 表示如果服务不存在,则应创建它
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
/**
* @description 这里执行服务里的方法 可以传参数 或者获取服务的数据 具体需求而定
*/
public void doSomething() {
MlogUtil.d(TAG,"doSomething: "+isBound+" ");
if (isBound&& service != null) {
service.doSomething();
}
}
/**
* @description 连接服务 监听服务是否绑定 用于处理连接和断开连接事件的 ServiceConnection
*/
private ServiceConnection mServiceConnection = new ServiceConnection() {
// 当与服务的连接时调用
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
isBound = true;
ServiceBackgroundForBind.MyBinder binder = (ServiceBackgroundForBind.MyBinder) iBinder;
//通过binder获取服务实例
service = binder.getService();
MlogUtil.d(TAG,"绑定状态:onServiceConnected "+isBound+" ");
}
// 当与服务的连接意外断开时调用
@Override
public void onServiceDisconnected(ComponentName componentName) {
isBound = false;
MlogUtil.d(TAG,"绑定状态:onServiceDisconnected "+isBound+" ");
}
};
@Override
protected void onDestroy() {
super.onDestroy();
/*if (intent != null) {
stopService(intent);
}*/
//记得解绑
if (isBound) {
unbindService(mServiceConnection);
}
}
public void doSomething(View view) {
doSomething();
}
}