美文网首页
安卓service使用(一)

安卓service使用(一)

作者: motosheep | 来源:发表于2021-07-16 15:00 被阅读0次

如题,本文将简述,同一个进程内,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--------------------------------------------------------------------

相关文章

  • 安卓service使用(一)

    如题,本文将简述,同一个进程内,service如何创建,绑定等操作。 首先,service是什么? 官方描述: A...

  • 安卓service使用(二)

    前文回顾:service基本使用(一)[https://www.jianshu.com/p/7aa7542b3db...

  • Android面试资料库

    1. 安卓面试之Service 知道Service吗,它有几种启动方式? —— goeasyway Android...

  • Android Service基本用法

    Service的概念 1.Service作为安卓的四大组件之一,固然是每一位安卓开发者必须掌握的一个知识点。虽然它...

  • Service

    activity写了 那么多,现在轮到service了。 1. service是什么? 服务,安卓的四大组件之一,...

  • 安卓开发 开发前你需要了解的一些资料(一)

    前言   在安卓开发 初步了解安卓和配置安卓环境中,我们简单的介绍了安卓和配置安卓环境。我们使用了Android ...

  • 安卓中DDMS和TraceView

    DDMS DDMS (Dalvik Debug Monitor Service)是安卓开发环境中的Dalvik虚拟...

  • 【Android】学习Fragment

    前言:除了安卓四大组件(activity、service、content provider、broadcast r...

  • Android Gson使用详解

    Android Gson使用详解(出处: 安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户)

  • Framework services

    系统service 安卓开发的同学都知道,framework中存在各种各样的service来实现管理服务,比如我们...

网友评论

      本文标题:安卓service使用(一)

      本文链接:https://www.haomeiwen.com/subject/jacbpltx.html