Service 是 Android 中实现程序后台运行的解决方案,它非常适合执行那些不需要和用户交互而且要求长期运行的任务。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>
定义两个按钮,在点击事件添加启动和停止逻辑
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) } } }
虽然我们学习了启动和停止 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() 方法就可以了