Android Service 的基本用法


概述

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() 方法就可以了


上一篇:Kotlin


下一篇:JavaScript的变量赋值问题