安卓service使用(一)

简介: service使用

如题,本文将简述,同一个进程内,service如何创建,绑定等操作。

首先,service是什么?

官方描述:

A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding  [<service>](https://developer.android.google.cn/reference/android/R.styleable#AndroidManifestService) declaration in its package's  AndroidManifest.xml. Services can be started with  [Context.startService()](https://developer.android.google.cn/reference/android/content/Context#startService(android.content.Intent)) and  [Context.bindService()](https://developer.android.google.cn/reference/android/content/Context#bindService(android.content.Intent,%20android.content.ServiceConnection,%20int)).

通俗一点,service可以理解为一个摸不着的东西,他区别于界面,运行在后台。

service的主要使用方法

1、startService()--用于启动service
2、stopService()--用于停止service
3、bindService()--绑定service
4、unBindService()--解绑service
要点:
(1)startService()和stopService(),bindService()和unBindService()都是成对出现的。
(2)首次使用startService(),service的onCreate()方法会执行,然后onStartCommand(),若无取消service()操作,后续再多次调用startService()方法时,service只会多次执行onStartCommand()方法。
(3)bindService()用于绑定service,结合ServiceConnection方法,实现绑定并且可以初始化一个绑定后的对象,用于调用binder方法。
(4)如果先调用bindService(),则service的生命周期方法执行顺序为:onCreate()-->onBind()。
(5)如果调用了startService()和bindService()方法,则后续需要同时调用unBindService()和stopService()用于取消绑定和停止service。
(6)注意在service不再使用的时候,及时释放service,避免导致内存泄漏
(7)注意安卓不同版本之间,service的适配
(8)使用service时,注意权限的申请

案例一

使用startService()和stopService()
代码地址
本次案例,主要调用startService()和stopService()两个方法,用于启动和取消service。
首先,看看service的实现:

//
 class FirstService( override val channelName: String =javaClass::class.java.simpleName,override val getChannelId: Int =javaClass.hashCode()) : BaseServiceCompat() { override fun onCreate() {
        super.onCreate()
        KtLogUtil.d("service onCreate")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        KtLogUtil.d("service onStartCommand")
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        KtLogUtil.d("service onDestroy")
        super.onDestroy()
    }

    override fun onBind(intent: Intent): IBinder? {
        KtLogUtil.d("service onBind")
        return null
    }
}
//

该service继承自BaseServiceCompat,父类主要是适配了不同安卓版本启动service的方法,主要核心代码,就是若当前版本大于android.O,启动service的方法为startForegroundService(),并且在创建service的时候,调用startForeground发出一个前台通知。具体实现代码如下:

fun startService(context: Context, intent: Intent?) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                //适配安卓8.0
                context.startForegroundService(intent)
            } else {
                context.startService(intent)
            }
        }
override fun onCreate() {
        super.onCreate()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            try {
                //适配安卓8.0
                val channelId = getChannelId
                val channelName = channelName
                val channel = NotificationChannel(
                    channelId.toString(),
                    channelName,
                    NotificationManager.IMPORTANCE_MIN
                )
                val manager = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
                manager.createNotificationChannel(channel)
                startForeground(channelId, notification)
            } catch (e: Exception) {
            }
        }
    }

而在MainActivity里面,我们直接调用即可:
代码如下图:

private fun initEvent() {
        findViewById<Button>(R.id.start_service).setOnClickListener {

            //显式开启
            val serviceIntent = Intent(this, FirstService::class.java)


//            //隐式开启--区别于显式, 需要在manifest中声明相关action参数
//            val serviceIntent = Intent()
//            serviceIntent.setAction("com.north.light.androidservice.FirstService")
//            serviceIntent.setPackage("com.north.light.androidservice")



            //启动service--android 8.0 service的启动方式有改变,需要适配
            //8.0 ps:在系统创建服务后,应用有五秒的时间来调用该服务的 startForeground() 方法以显示新服务的用户可见通知。
            //使用封装好的base service compat用于启动service
            BaseServiceCompat.startService(this, serviceIntent)
        }

        findViewById<Button>(R.id.stop_service).setOnClickListener {
            val serviceIntent = Intent(this, FirstService::class.java)
            //关闭service
            stopService(serviceIntent)
        }
    }

可以从上图看出,启动service,有两种方法:
第一个就是直接通过Service的对象作为intent初始化传参进行启动(显式调用)
第二个就是指定intent的action和package进行调用(隐式调用)
对于方法二:需要在manifest文件中,声明action

       <service
            android:name=".FirstService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.north.light.androidservice.FirstService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

声明以后才可以进行隐式调用。
对于service的参数声明析意如下:

enable:表示是否启用该服务
    exported:表示是否允许除了当前程序之外的其他程序访问这个服务
    process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。
    ps:很重要,它的意思是指要在当前进程名称前面附加上当前的包名,
    所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。

对于intent-filter参数,常用于外部调用(隐式调用的情况下声明)

至此,已经完成了service的startService()和stopService()的实现了

案例二

在案例一的基础上,进行bindservice操作,并且通过binder调用service的方法
代码链接
实际项目中,建议调用的service方法顺序为:
1、startService()
2、bindService()
3、unBindService()
4、stopService()
本次案例调用service的顺序也是如上。
首先,service里面定义一个binder,如下图:

    inner class FirstBinder : Binder() {

        fun getService(): FirstService {
            return this@FirstService
        }

        /**
         * 发送消息
         * */
        fun sendMessage(toString: String) {
            mListener.forEach {
                it.result("收到了,返回给你:${toString}")
            }
        }

        fun setOnListener(listener: FirstServiceListener) {
            mListener.add(listener)
        }

        fun removeListener(listener: FirstServiceListener) {
            mListener.remove(listener)
        }
    }

再在service的onBind()方法中,返回该binder的实例,至此,service的定义基本完成。
下面看看如何实现bindService()的。

        findViewById<Button>(R.id.bind_service).setOnClickListener {
            val serviceIntent = Intent(this, FirstService::class.java)
            //绑定service
            serConnect = object : ServiceConnection {
                override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
                    KtLogUtil.d("绑定了 service ")
                    mBinder = (p1 as FirstService.FirstBinder)
                    mBinder?.setOnListener(mBinderListener)
                }

                override fun onServiceDisconnected(p0: ComponentName?) {
                    mBinder = null
                    KtLogUtil.d("解绑了 service ")
                }
            }
            bindService(serviceIntent, serConnect!!, BIND_AUTO_CREATE)
        }

这里直接通过一个ServiceConnect即可实现bind service。里面有连接成功和断开连接的返回,这里只做案例实现,实际中需要在断开连接的时候,加上重连机制。
在onServiceConnected()方法中,能初始化binder,该binder则可以用作后续调用service方法的操作了。

that's all--------------------------------------------------------------------

目录
相关文章
|
6月前
|
Android开发
Android 11 添加Service服务SELinux问题
Android 11 添加Service服务SELinux问题
295 1
|
6月前
|
Android开发
Android基础知识:请解释Service是什么,它与IntentService的区别是什么?
Android基础知识:请解释Service是什么,它与IntentService的区别是什么?
105 0
|
5月前
|
调度 Android开发
43. 【Android教程】服务:Service
43. 【Android教程】服务:Service
51 2
|
6月前
|
Android开发
Android Service Call /dev/xxx SELinux
Android Service Call /dev/xxx SELinux
99 1
|
3月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
6月前
|
存储 监控 Java
Android Service之设备存储空间监控 DeviceStorageMonitorService
Android Service之设备存储空间监控 DeviceStorageMonitorService
119 2
|
6月前
|
Android开发 数据库管理
Android如何在Activity和Service之间传递数据
Android如何在Activity和Service之间传递数据
263 3
|
6月前
|
Android开发
Android Service的两种使用方法
Android Service的两种使用方法
47 2
|
6月前
|
数据可视化 Android开发
[Android 四大组件] --- Service
[Android 四大组件] --- Service
46 0
|
6月前
|
Android开发 Kotlin
android开发,使用kotlin学习Service
android开发,使用kotlin学习Service
148 1