概述
Service 是 Android 中实现程序后台运行的解决方案,它非常适合执行那些不需要和用户交互而且要求长期运行的任务。Service 的运行不依赖于任何用户界面,即使程序被切换到后台,或者打开了另外一个应用程序,Service 仍然能够保持正常运行
定义 Service
定义一个 Service 代码如下:
class MyService : Service() {
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
super.onDestroy()
}
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
}
先忽略 onBind() 方法,这里我们重写了 onCreate()、onStartCommand() 和 onDestroy() 这三个方法,其中 onCreate() 方法会在 Service 创建的时候调用,onStartCommand() 方法会在每次 Service 启动时调用,onDestroy() 方法会在 Service 销毁的时候调用
通常情况下,如果我们希望 Service 一旦启动就立刻执行某个动作哦,可以将逻辑写在 onStartCommand() 方法里,而当 Service 销毁时,我们可以在 onDestroy() 方法中回收那些不再使用的资源
另外需要注意的是,每一个 Service 都需要在 AndroidManifest.xml 文件中进行注册才能生效
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicetest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.FragmentTest">
<service
android:name="com.example.MyService"
android:enabled="true"
android:exported="true"></service>
...
</application>
</manifest>
启动和停止 Service
定义两个按钮,在点击事件添加启动和停止逻辑
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 启动 Service
startServiceBtn.setOnClickListener {
val intent = Intent(this, MyService::class.java)
startService(intent)
}
// 停止 Service
stopServiceBtn.setOnClickListener {
val intent = Intent(this, MyService::class.java)
stopService(intent)
}
}
}
Activity 和 Service 进行通信
虽然我们学习了启动和停止 Service 的方法,但启动 Service 以后,Activity 与 Service 基本就没有什么关系了。Activity 并不知道 Service 干了什么,也无法干预。为了让 Activity 和 Service 的关系更紧密一点,就需要借助 onBind() 方法
假设,目前我们希望在 MyService 里提供一个下载功能,然后在 Activity 中可以决定何时开始下载,以及随时查看下载进度。实现该功能的思路是创建一个专门的 Binder 对象来对下载功能进行管理,修改 MyService 代码如下:
class MyService : Service() {
private val mBinder = DownloadBinder()
class DownloadBinder : Binder() {
fun startDownload() {
...
}
fun getProgress(): Int {
...
return 0
}
}
override fun onBind(intent: Intent): IBinder {
return mBinder
}
...
}
再创建两个按钮,分别用于绑定和取消绑定 Service,当一个 Activity 和 Service 绑定以后,就可以调用该 Service 里的 Binder 提供的方法
class MainActivity : AppCompatActivity() {
lateinit var downloadBinder: MyService.DownloadBinder
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
downloadBinder = service as MyService.DownloadBinder
downloadBinder.startDownload()
downloadBinder.getProgress()
}
override fun onServiceDisconnected(name: ComponentName?) {
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bindServiceBtn.setOnClickListener {
val intent = Intent(this, MyService::class.java)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
unbindServiceBtn.setOnClickListener {
unbindService(connection)
}
}
}
创建一个 ServiceConnection 的匿名类实现,onServiceConnected() 方法会在 Activity 与 Service 成功绑定的时候调用,onServiceDisconnected() 方法只有在 Service 的创建进程崩溃或者被杀掉的时候才会调用。通过在 onServiceConnected() 方法中向下转型得到 DownloadBinder 的实例,从而调用 Service 的方法
构建一个 Intent 对象,然后调用 bindService() 方法将 Activity 与 Service 进行绑定,bindService() 方法接收三个参数:第一个参数是刚刚构建的 Intent 对象,第二个参数是创建的 ServiceConnection 的实例,第三个参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在 Activity 和 Service 进行绑定后自动创建 Service
如果想接触 Activity 与 Service 之间的绑定,调用一下 unbindService() 方法就可以了