android开发基本service

启动方式

startService

bindService

生命周期

在startService之后,执行onCreate方法,onStartCommand方法。当我们执行stopService的时候,执行onDestroy方法。(onCreate—>onStartCommand—->onDestroy)

通过bindService的方式来启动 (onCreate—->onBind—>onUnbind—->onDestroy)
1、系统设置不显示;
2、Activity销毁时,服务需要解绑(不求同生,但求同死);
3、解除绑定后停止运行,执行unBind方法—>onDestroy方法;
4、只可以解绑一次,多次解绑会抛异常;
5、绑定的connection和解绑的connection要一致,否则无法解绑。
6、如果onBind方法返回null,那么onServiceConnected不会被调用

binder接口的定义

interface IBindSecondService {

    fun callMethod()
}

binder接口的实现

class BindSecondServiceImpl : Binder(), IBindSecondService {
    override fun callMethod() {
        Log.e("BindSecondServiceImpl","调用到了callMethod()")
    }
}

service的继承

class SecondService : Service() {

    companion object{
        const val TAG = "SecondService"
    }

    override fun onCreate() {
        super.onCreate()
        Log.e(TAG,"onCreate====>")
    }

    override fun onBind(p0: Intent?): IBinder? {
        Log.e(TAG,"onBind====>")
        return BindSecondServiceImpl()
    }

    override fun onUnbind(intent: Intent?): Boolean {
        Log.e(TAG,"onUnbind====>")
        return super.onUnbind(intent)
    }

    override fun onDestroy() {
        Log.e(TAG,"onDestroy====>")
        super.onDestroy()
    }
}

bindService在activity中的操作

var isBindFlag = false
    fun onBindService(view: View) {
    	// 第一个是参数是意图对象,第二个参数是回调,第三个参数是标记,这个是自动创建的意思,如果服务没有start,那么会自己创建。
        val intent = Intent(this, SecondService::class.java)
        isBindFlag = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
    }

    fun onUnbindService(view: View) {
        if (isBindFlag) {
            unbindService(serviceConnection)
            bindService = null
        }

    }

    fun onCallMethod(view: View) {
        bindService?.callMethod()
    }

    var bindService: IBindSecondService? = null
    private var serviceConnection = object : ServiceConnection {

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.e(TAG, "onServiceConnected")
            if (service is IBindSecondService) {

                bindService = service
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.e(TAG, "onServiceDisconnected")
        }

    }

优缺点

1、startService启动的服务,是长期运行的,不可以通讯,只有调用stopService才会停止服务。
2、bindService启动的服务,不是长期运行的,可以通讯,不用的时候,需要调用unBindService,否则会导致context泄漏。

混合启动服务

先startService,再bindService,服务既长期在后台运行,又可通讯

1.开启服务—>绑定服务—>调用服务的方法——>解绑服务——>停止服务(不停止服务它会一直跑着)
此情况下解绑服务,没有执行onDestroy方法,说明服务还是运行的。
1、startService:服务在后台长期运行。
2、bindService:调用服务内部的方法,跟服务进行通讯
综述,只要以startService的方式开启服务,没有stopService,服务就一直运行。

2.开启服务 —->绑定服务—–>停止服务
综述,通过startService,再去bindService,如果没有解绑,服务是无法停止的

实际开发中的流程:
第一步:startService–>为了服务长期后台运行
第二步:bindService–>为了获取服务的控制binder
第三步:调用服务里的方法
第四步:unBindService—>解绑服务,否则无法停止服务的(但是服务,仍然在后台运行)
第五步:不需要服务的时候停止服务stopService

跨进程通讯AIDL

在这里插入图片描述

AIDL:android interface definition language

图中的服务相对于A来说是远程服务,相对于B来说是本地服务。
我们有两个应用,一个是应用A,一个是应用B。在应用B里有一个服务。目的是应用A绑定应用B的服务,并且调用里面的方法

第一步,创建两个应用:AIDLDemoA,和AIDLDemoB

第二步:在 AIDLDemoB的程序里面创建一个服务:AppBService;

public class AppBService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

第三步,在配置文件里注册这个服务,

<service
   android:exported="true"
   android:name=".service.AppBService">
   <intent-filter>
       <action android:name="com.example.app.service.INNER_SERVICE"/>
       <category android:name="android.intent.category.DEFAULT"/>
   </intent-filter>
</service>

exported=”true”允许外部启动此服务,绑定这个服务。默认true,如果改成false,外部无法绑定/启动了。

这个action是给第三方应用(应用A)绑定用的。

第四步,创建AIDL接口

在这里插入图片描述

package com.example.app;

// Declare any non-default types here with import statements

interface IBServiceAidlInterface {
    void innerCallMethod();
    void innerServiceWithParams(in String content);
}

基本数据类型不需要导包,我们自己定义的才要导包

第五步,点击build里的make一下,这样子就会自动生成一个关于aidl类

class AppBService : Service() {

    companion object{
        const val TAG = "AppBService"
    }

    override fun onBind(intent: Intent?): IBinder? {
        return object :IBServiceAidlInterface.Stub(){
            override fun innerCallMethod() {
                Log.e(TAG,"innerCallMethod====>")
            }

            override fun innerServiceWithParams(content: String?) {
                Log.e(TAG, "innerServiceWithParams====>$content")
            }
        }
    }
    override fun onUnbind(intent: Intent?): Boolean {
        Log.e(TAG,"onUnbind====>")
        return super.onUnbind(intent)
    }
}

以上是我们服务修改成这样子,IBServiceAidlInterface.Stub()这个类是根据我们的aidl接口生成的,它继承自己IBinder,所以我们可以直接使用。

第六步:复制aidl的整个文件夹到应用A,确保包名是一致的;
在这里插入图片描述

然后,在应用A绑定服务时,就可以拿到这个接口的实现了,

class TestActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)
    }

    companion object {
        const val TAG = "TestActivity"
    }

    /**
     * 远程服务的点击
     */
    var binderService: IBServiceAidlInterface? = null
    fun onRemoteServiceClick(view: View) {
        val intent = Intent()
        intent.setPackage("com.example.app")
        intent.action = "com.example.app.service.INNER_SERVICE"
        if (binderService == null) {
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceDisconnected(name: ComponentName?) {
            Log.e(TAG, "解绑了onServiceDisconnected===>")
            binderService = null
        }

        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            Log.e(TAG, "绑定了onServiceConnected===>")
            binderService = IBServiceAidlInterface.Stub.asInterface(service)
        }
    }

    /**
     * 解绑
     */
    fun onUnBindServiceClick() {
        if (binderService != null){
            unbindService(serviceConnection)
            binderService = null
        }

    }

    /**
     * 调用远程服务的方法
     */
    fun onRemoteServiceMethod(view: View){
        if (binderService != null){
            binderService?.innerCallMethod()
            binderService?.innerServiceWithParams("success info out")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        onUnBindServiceClick()
    }
}

注意:先跑起应用B,再跑起应用A

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值