【木棉花】:Service核心技术精要直播之学习笔记(下) 原创 精华

木棉花潘颖琳
发布于 2022-2-5 11:30
浏览
3收藏

春节不停更,此文正在参加「星光计划-春节更帖活动」

前言

这篇文章是我观看张荣超老师8月12日Service核心技术精要的直播后的学习笔记,温故而知新,跟着敲代码,跟着学知识,冲冲冲O(∩_∩)O

概述

【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区
这是直播的主要内容,本文是对连接和断开连接应用内的Service跨设备连接和断开连接应用内的Service两个Demo做点笔记记录

正文

一、知识要点

1、连接Service:如果Service需要与Page Ability或其他应用的Service Ability进行交互,则须创建用于连接的Connection。Service支持其他Ability通过connectAbility()方法与其进行连接。
在使用connectAbility() 处理回调时,需要传入目标Service的Intent与IAbilityConnection的实例。IAbilityConnection提供了两个方法供开发者实现:onAbilityConnectDone() 是用来处理连接Service成功的回调,onAbilityDisconnectDone() 是用来处理Service异常死亡的回调。同时,Service侧也需要在onConnect() 时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象,HarmonyOS提供了IRemoteObject的默认实现,用户可以通过继承LocalRemoteObject来创建自定义的实现类【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区

二、连接和断开连接应用内的Service

1.界面布局

【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区 【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区

/ability_main.xml/

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
   >

    <Text
        ohos:id="$+id:text_main"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_main"
        ohos:layout_alignment="horizontal_center"
        ohos:text="这是MainAbility"
        ohos:text_size="40vp"
        />

    <Button
        ohos:id="$+id:btn_connect"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="连接APP内的Service"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

    <Button
        ohos:id="$+id:btn_call"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="调用Service的方法"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

    <Button
        ohos:id="$+id:btn_disconnect"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="断开连接Service"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

    <Button
        ohos:id="$+id:btn_to_second"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="跳转到SecondAbility"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

</DirectionalLayout>

/ability_second.xml/

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    >

    <Text
        ohos:id="$+id:text_sec"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_main"
        ohos:layout_alignment="horizontal_center"
        ohos:text="这是SecondAbility"
        ohos:text_size="40vp"
        />

    <Button
        ohos:id="$+id:btn_sec_connect"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="连接APP内的Service"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

    <Button
        ohos:id="$+id:btn_sec_call"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="调用Service的方法"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

    <Button
        ohos:id="$+id:btn_sec_disconnect"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="断开连接Service"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />

    <Button
        ohos:id="$+id:btn_to_main"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="跳转到MainAbility"
        ohos:text_color="#ffffff"
        ohos:background_element="$graphic:background_button"
        ohos:left_margin="30vp"
        ohos:right_margin="30vp"
        ohos:top_margin="30vp"
        ohos:bottom_margin="30vp"
        ohos:top_padding="10vp"
        ohos:bottom_padding="10vp"
        ohos:auto_font_size="true"
        />
</DirectionalLayout>

2.ServiceAbility

设置一下打印日志的内容,定义一个内部类,定义一个方法plus作为Service调用的方法;在连接Service调用onConnect时返回这个内部类的一个实例对象

public class ServiceAbility extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");

    public static class MyLocalRemoteObject extends LocalRemoteObject{
        public MyLocalRemoteObject() {
            super();
        }

        public int plus(int num1, int num2){
            return num1 + num2;
        }
    }
    @Override
    public void onStart(Intent intent) {
        HiLog.info(LABEL_LOG, "onStart()被调用了");
        super.onStart(intent);
    }

    @Override
    public IRemoteObject onConnect(Intent intent) {
        HiLog.info(LABEL_LOG, "onConnect()被调用了");
        return new MyLocalRemoteObject();
    }

    @Override
    public void onDisconnect(Intent intent) {
        HiLog.info(LABEL_LOG, "onDisconnect()被调用了");
    }

    @Override
    public void onBackground() {
        super.onBackground();
        HiLog.info(LABEL_LOG, "onBackground()被调用了");
    }

    @Override
    public void onStop() {
        super.onStop();
        HiLog.info(LABEL_LOG, "onStop()被调用了");
    }

    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        HiLog.info(LABEL_LOG, "onCommand()被调用了");
    }

}

3.AbilitySlice

onAbilityConnectDone中的形参为iRemoteObject,要将其转化为它实际的类型,系统为这个形参传入的实参是Service中的onConnect返回的实例对象。
当本应用调用方法connectAbility的时候,就会根据指定的intent对象和AbilityConnection去连接Service,如果Service没有被其他Ability连接,那么系统就会先创建Service,并且回调onStart来初始化Service,然后再回调onConnect连接Service;如果已经连接到其他Ability,那么系统会直接回调onAbilityConnectDone。只有当所有Ability都与Service断开连接了,系统才与Service断开连接。
创建一个SecondAbility,如果跳转页面不成功可以去看看配置文件config.json是否配置了SecondAbility的相关信息
/MainAbilitySlice/

public class MainAbilitySlice extends AbilitySlice {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");
    private ServiceAbility.MyLocalRemoteObject myLocalRemoteObject;

    private final IAbilityConnection abilityConnection = new IAbilityConnection() {
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            HiLog.info(LABEL_LOG,"onAbilityConnectDone()被调用了");
            myLocalRemoteObject = (ServiceAbility.MyLocalRemoteObject)iRemoteObject;
        }

        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
            HiLog.info(LABEL_LOG,"onAbilityDisconnectDone()被调用了");
        }
    };

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        setListenerForBtnConnect();
        setListenerForBtnCall();
        setListenerForBtnDisconnect();
        setListenerForBtnToSecond();
    }

    private void setListenerForBtnConnect(){
        Intent intent = new Intent();
        Operation serviceOperation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(getBundleName())
                .withAbilityName(ServiceAbility.class.getName())
                .build();
        intent.setOperation(serviceOperation);

        Component btnConnect = (Button)findComponentById(ResourceTable.Id_btn_connect);
        btnConnect.setClickedListener(component -> {
            connectAbility(intent,abilityConnection);
        });
    }

    private void setListenerForBtnCall(){
        Button btnCall = (Button)findComponentById(ResourceTable.Id_btn_call);
        btnCall.setClickedListener(component -> {
            if(myLocalRemoteObject != null){
                int result = myLocalRemoteObject.plus(2,3);
                HiLog.info(LABEL_LOG,"plus(2,3)的返回值:"+result);
            }
        });
    }

    private void setListenerForBtnDisconnect(){
        Button btnDisconnect = (Button)findComponentById(ResourceTable.Id_btn_disconnect);
        btnDisconnect.setClickedListener(component -> {
            disconnectAbility(abilityConnection);
        });
    }

    private void setListenerForBtnToSecond(){
        Intent intent = new Intent();
        Operation serviceOperation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(getBundleName())
                .withAbilityName(SecondAbility.class.getName())
                .build();
        intent.setOperation(serviceOperation);

        Button btnToSecond = (Button)findComponentById(ResourceTable.Id_btn_to_second);
        btnToSecond.setClickedListener(component -> {
            HiLog.info(LABEL_LOG,"ToSecond()被调用了");
            startAbility(intent);
        });
    }
}

/SecondAbilitySlice/

public class SecondAbilitySlice extends AbilitySlice {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");
    private ServiceAbility.MyLocalRemoteObject myLocalRemoteObject;

    private final IAbilityConnection abilityConnection = new IAbilityConnection() {
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            HiLog.info(LABEL_LOG,"onAbilityConnectDone()被调用了");
            myLocalRemoteObject = (ServiceAbility.MyLocalRemoteObject)iRemoteObject;
        }

        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
            HiLog.info(LABEL_LOG,"onAbilityDisconnectDone()被调用了");
        }
    };

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_second);

        setListenerForBtnConnect();
        setListenerForBtnCall();
        setListenerForBtnDisconnect();
        setListenerForBtnToMain();
    }

    private void setListenerForBtnConnect(){
        Intent intent = new Intent();
        Operation serviceOperation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(getBundleName())
                .withAbilityName(ServiceAbility.class.getName())
                .build();
        intent.setOperation(serviceOperation);

        Component btnConnect = (Button)findComponentById(ResourceTable.Id_btn_sec_connect);
        btnConnect.setClickedListener(component -> {
            connectAbility(intent,abilityConnection);
        });
    }

    private void setListenerForBtnCall(){
        Button btnCall = (Button)findComponentById(ResourceTable.Id_btn_sec_call);
        btnCall.setClickedListener(component -> {
            if(myLocalRemoteObject != null){
                int result = myLocalRemoteObject.plus(5,6);
                HiLog.info(LABEL_LOG,"plus(5,6)的返回值:"+result);
            }
        });
    }

    private void setListenerForBtnDisconnect(){
        Button btnDisconnect = (Button)findComponentById(ResourceTable.Id_btn_sec_disconnect);
        btnDisconnect.setClickedListener(component -> {
            disconnectAbility(abilityConnection);
        });
    }

    private void setListenerForBtnToMain(){
        Button btnToMain = (Button)findComponentById(ResourceTable.Id_btn_to_main);
        btnToMain.setClickedListener(component -> {
            terminateAbility();
        });
    }
}

打印的日志如下
【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区
【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区

三、跨设备连接和断开连接应用内的Service

代码内容跟跨设备启动和停止Service差不多,要配置相关权限,发送弹窗形式请求用户授权,再定义一个工具类去获取所有设备的Id列表… …
要点:1.本地设备连接和断开连接应用内的Service中的ServiceAbility的内部类是继承LocalRemoteObject,而跨设备的是继承RemoteAbilityStub。
2.RemoteAbilityStub这个类来自idl,idl:当跨进程进行通信的时候,它可以用于定义客户端和服务端两者共同认可的接口,创建idl文件,定义好接口后,打开Gradle,找到对应模块下的下图的位置compileDebugIdl双击,系统会自动生成三个文件,一个是接口文件,一个是客户端的代理类,一个是服务端的装类.
【木棉花】:Service核心技术精要直播之学习笔记(下)-鸿蒙开发者社区

结语

以上就是我这次的小分享啦❀❀!!2022,学习路上继续前进!

更多资料请关注我们的项目 : Awesome-Harmony_木棉花

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
ServiceDemo.zip 37.18M 11次下载
已于2022-2-5 11:30:57修改
5
收藏 3
回复
举报
回复
    相关推荐