当前位置:   article > 正文

鸿蒙开发之Service Ability_com.huawei.hwddmp

com.huawei.hwddmp

1.基本概念

基于Service模板的Ability(简称“Service”)主要用于后台运行任务(如执行音乐播放、文件下载等),但不提供用户交互界面。Service可由其他应用或Ability启动,即使用户切换到其他应用,Service仍将在后台继续运行。

1.Service是单实例的。在一个设备上,相同的Service只会存在一个实例。

2.如果多个Ability共用这个实例,只有当与Service绑定的所有Ability都退出后,Service才能够退出。

3.由于Service是在主线程里执行的,因此,如果在Service里面的操作时间过长,必须在Service里创建新的线程来处理,防止造成主线程阻塞,应用程序无响应。

2.创建Service

创建Ability的子类,实现Service相关的生命周期方法。Service也是一种Ability,Ability为Service提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。

包上右键选择New => Ability => Empty Service Ability创建一个ServiceAbility1

public class ServiceAbility1 extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001101, "ServiceAbility1");

    @Override
    public void onStart(Intent intent) {
        HiLog.error(LABEL_LOG, "--------ServiceAbility1::onStart");
        super.onStart(intent);
    }

    @Override
    public void onBackground() {
        super.onBackground();
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::onBackground");
    }

    @Override
    public void onStop() {
        super.onStop();
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::onStop");
    }

 /**
     * 每次调用ServiceAbility1都会执行该方法
     * @param intent 数据载体
     * @param restart 启动状态 true:销毁后启动,false:正常启动
     * @param startId 启动的计数器
     */
    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::onCommand");
        System.out.println("数据载体:"+intent.getOperation().getAbilityName());
        System.out.println("启动状态:"+restart);
        System.out.println("启动的计数器:"+startId);
        
    }

    @Override
    public IRemoteObject onConnect(Intent intent) {
        return null;
    }

    @Override
    public void onDisconnect(Intent intent) {
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

2.注册Service

Service也需要在应用配置文件中进行注册,注册类型type需要设置为service。

{
    "module": {
        "abilities": [         
                 {
			        "name": "com.example.myapplication.ServiceAbility1",
			        "icon": "$media:icon",
			        "description": "$string:serviceability1_description",
			        "type": "service"
			      },
        ]
        ...
    }
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

3.启动Service

Ability为开发者提供了startAbility()方法来启动另外一个Ability。因为Service也是Ability的一种,开发者同样可以通过将Intent传递给该方法来启动Service。不仅支持启动本地Service,还支持启动远程Service。

启动Service主要用于启动一个服务执行后台任务或者远程启动一个功能,不进行通信,如设备A让设备B播放音乐。

可以通过构造包含DeviceId、BundleName与AbilityName的Operation对象来设置目标Service信息。

DeviceId:表示设备ID。如果是本地设备,则可以直接留空;如果是远程设备,可以通过ohos.distributedschedule.interwork.DeviceManager提供的getDeviceList获取设备列表。

BundleName:表示包名称。

AbilityName:表示待启动的Ability名称。
  • 1
  • 2
  • 3
  • 4
  • 5

Layout_ability_main布局xml

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

    <Button
    ohos:id="$+id:button1"
    ohos:width="match_content"
    ohos:height="match_content"
    ohos:background_element="$graphic:background_button"
    ohos:text="启动本地设备的Service"
    ohos:layout_alignment="horizontal_center"
    ohos:text_size="100"/>

    <Button
        ohos:id="$+id:button2"
        ohos:width="match_content"
        ohos:top_margin="100px"
        ohos:height="match_content"
        ohos:background_element="$graphic:background_button"
        ohos:text="停止本地设备的Service"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="100"/>

</DirectionalLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

背景xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
       ohos:shape="rectangle">
    <corners
        ohos:radius="10"/>
    <solid
        ohos:color="#007CFD"/>
</shape>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

启动本地设备Service

config.js配置分布式权限

"reqPermissions": [
        {"name": "ohos.permission.DISTRIBUTED_DATASYNC"},
        {"name": "ohos.permission.servicebus.ACCESS_SERVICE"},
        {"name": "com.huawei.hwddmp.servicebus.BIND_SERVICE"},
        {"name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"}, 
        {"name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" }, 
        {"name": "ohos.permission.GET_BUNDLE_INFO"} 
    ]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

显示声明需要使用的权限

public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());
       
        requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC",
                "ohos.permission.servicebus.ACCESS_SERVICE",
                "com.huawei.hwddmp.servicebus.BIND_SERVICE"}, 0);
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
public class MainAbilitySlice extends AbilitySlice {
    static final HiLogLabel LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00002, "MainAbilitySlice");

    /**
     * 启动本地设备的Service
     * @param intent
     */
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        Button button1 = (Button) findComponentById(ResourceTable.Id_button1);
        button1.setClickedListener(component -> {
         //构造包含DeviceId、BundleName与AbilityName的Operation对象来设置目标Service信息
            Intent intent1 = new Intent();
            Operation operation = new Intent.OperationBuilder()
                    .withDeviceId("")
                    .withBundleName("com.example.myapplication")
                    .withAbilityName("com.example.myapplication.ServiceAbility1")
                    .build();
            intent1.setOperation(operation);
            startAbility(intent1);
        });

    }
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

启动远程设备Service

   /**
     * 启动本地设备的Service
     * @param intent
     */
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

    //获取设备列表
        List<DeviceInfo> deviceList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
        if(deviceList.isEmpty()){
            return ;
        }
        int deviceNum = deviceList.size();
        List<String> deviceIds = new ArrayList<>(deviceNum);
        List<String> deviceNames = new ArrayList<>(deviceNum);
        deviceList.forEach((device)->{
            deviceIds.add(device.getDeviceId());
            deviceNames.add(device.getDeviceName());
        });

        //使用deviceIds的第一个元素,做为启动远程设备的目标id
        String devcieIdStr = deviceIds.get(0);

        Button button1 = (Button) findComponentById(ResourceTable.Id_button1);
        button1.setClickedListener(component -> {
            //构造包含DeviceId、BundleName与AbilityName的Operation对象来设置目标Service信息
            Intent intent1 = new Intent();
            Operation operation = new Intent.OperationBuilder()
                    .withDeviceId(devcieIdStr)
                    .withBundleName("com.example.myapplication")
                    .withAbilityName("com.example.myapplication.ServiceAbility1")
                    .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) // 设置支持分布式调度系统多设备启动的标识
                    .build();
            intent1.setOperation(operation);
            startAbility(intent1);
        });
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
Ability将通过startAbility() 方法来启动Service。

如果Service尚未运行,则系统会先调用onStart()来初始化Service,再回调Service的onCommand()方法来启动Service。

如果Service正在运行,则系统会直接回调Service的onCommand()方法来启动Service。
  • 1
  • 2
  • 3
  • 4
  • 5

4.停止Service

Service一旦创建就会一直保持在后台运行,除非必须回收内存资源,否则系统不会停止或销毁Service。开发者可以在Service中通过terminateAbility()停止本Service或在其他Ability调用stopAbility()来停止Service。

停止Service同样支持停止本地设备Service和停止远程设备Service,使用方法与启动Service一样。一旦调用停止Service的方法,系统便会尽快销毁Service。

停止本地设备Service

public class MainAbilitySlice extends AbilitySlice {
    static final HiLogLabel LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00002, "MainAbilitySlice");

    /**
     * 停止本地设备的Service
     * @param intent
     */
    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart2");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        
        Button button2 = (Button) findComponentById(ResourceTable.Id_button2);
        button2.setClickedListener(component -> {
        //构造包含DeviceId、BundleName与AbilityName的Operation对象来设置目标Service信息
            Intent intent1 = new Intent();
            ElementName elementName = new ElementName("","com.example.myapplication","ServiceAbility1");
           intent1.setElement(elementName);
            stopAbility(intent1);
        });
    }
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

停止远程设备Service

   /**
     * 停止本地设备的Service
     * @param intent
     */
    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart2");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

		        //获取设备列表
        List<DeviceInfo> deviceList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
        if(deviceList.isEmpty()){
            return ;
        }
        int deviceNum = deviceList.size();
        List<String> deviceIds = new ArrayList<>(deviceNum);
        List<String> deviceNames = new ArrayList<>(deviceNum);
        deviceList.forEach((device)->{
            deviceIds.add(device.getDeviceId());
            deviceNames.add(device.getDeviceName());
        });

        //使用deviceIds的第一个元素,做为启动远程设备的目标id
        String devcieIdStr = deviceIds.get(0);
        
        Button button2 = (Button) findComponentById(ResourceTable.Id_button2);
        button2.setClickedListener(component -> {
            Intent intent1 = new Intent();
            ElementName elementName = new ElementName(devcieIdStr,"com.example.myapplication","ServiceAbility1");
           intent1.setElement(elementName);
           intent1.setFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE); // 设置支持分布式调度系统多设备启动的标识
            stopAbility(intent1);
        });
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

5.连接Service

如果Service需要与Page Ability或其他应用的Service Ability进行交互,则应创建用于连接的Connection。Service支持其他Ability通过connectAbility()方法与其进行连接。

在使用connectAbility()处理回调时,需要传入目标Service的Intent与IAbilityConnection的实例。

IAbilityConnection提供了两个方法供开发者实现:

onAbilityConnectDone()用来处理连接的回调

onAbilityDisconnectDone()用来处理断开连接的回调。
  • 1
  • 2
  • 3

链接与启动的不同在于链接Service后,可以进行通信,也就是需要链接的Service执行任务后返回数据,此时,就要用链接而不能是启动。

客户端可通过调用disconnectAbility​()断开连接。

// 与远程PA断开连接
private ClickedListener mDisconnectRemotePAListener = new ClickedListener() {
    @Override
    public void onClick(Component arg0) {
        disconnectAbility(conn);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用代理跨设备调度

在onAbilityConnectDone()中获取管理链接的代理,进一步为了使用该代理跨设备调度PA,开发者需要在本地及对端分别实现对外接口一致的代理。

发起连接端

package com.example.myapplication.connections;

import ohos.rpc.*;

public class StartRemoteProxy implements IRemoteBroker {
    //发起端与接受端之间的通信代码,有效的任意值
    private static final int MSGCODE = IRemoteObject.MIN_TRANSACTION_ID;
    //通信成功的code值: 0
    private static final int OK = 0;
    //获取远程代理对象的持有者
    private final IRemoteObject remote;

    /**
     * 初始远端代理对象,使用onAbilityDisconnectDone接口方法返回来获取
     *
     * @param remote
     */
    public StartRemoteProxy(IRemoteObject remote) {
        this.remote = remote;
    }

    /**
     * 获取远程代理对象
     *
     * @return
     */
    @Override
    public IRemoteObject asObject() {
        return remote;
    }


    /**
     * Servcie Ability具有的test功能
     *
     * @param text
     * @return
     */
    public String test(String text) {
        //传出的数据
        MessageParcel data = MessageParcel.obtain(); //返回一个空的MessageParcel对象
        data.writeString(text);
        //远端返回的响应数据
        MessageParcel reply = MessageParcel.obtain();
        //制定信息传输的模式的option 同步 or 异步
        MessageOption option = new MessageOption(MessageOption.TF_SYNC);
        String result = null;
        try {
            //最核心方法,实现调用Servcie Ability的功能
            remote.sendRequest(MSGCODE, data, reply, option);
            //通信结束,响应结果存放在reply容器中

            //判断通信状态
            int ec = reply.readInt();
            if (ec != OK) {
                throw new RemoteException();
            }
            result = reply.readString();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return result;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

接受端

package com.example.myapplication.connections;

import ohos.rpc.*;

public class AcceptRemoteProxy extends RemoteObject implements IRemoteBroker {

    //发起端与接受端之间的通信代码,有效的任意值
    private static final int MSGCODE = IRemoteObject.MIN_TRANSACTION_ID;
    //通信成功的code值 0
    private static final int OK = 0;
    //通信失败的Code值
    private static final int ERROR = -1;

    public AcceptRemoteProxy() {
        super("this is acceptRemoteProxy");
    }

    @Override
    public IRemoteObject asObject() {
        return this;
    }


    /**
     * 接受端接受发送端的请求数据,并处理这些数据,返回返回响应
     *
     * @param code   接受端与发送端间的通信code
     * @param data   发送端发送的数据
     * @param reply  接受端响应的数据
     * @param option 数据传输的模式
     * @return
     * @throws RemoteException
     */
    @Override
    public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) throws RemoteException {
        //发起端的通信code需与接受端通信code值一致
        if (code != MSGCODE) {
            //通信失败
            reply.writeInt(ERROR);
            return false;
        }
        //取发起端传递的参数
        String readString = data.readString();
        //设置返回发起端的响应数据
        reply.writeInt(OK);
        reply.writeString(readString);
        return true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

创建Service Ability

一个PA ServiceAbility1 ,实例化一个代理返回给发起端

public class ServiceAbility1 extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD001101, "ServiceAbility1");

    //实例化客户端,返回给发送方可调用的代理
    private AcceptRemoteProxy remote = new AcceptRemoteProxy();

    /**
     * 当该PA接收到连接请求时,将该客户端转化为代理返回给发起端
     * @param intent
     * @return
     */
    @Override
    public IRemoteObject onConnect(Intent intent) {
        return remote;
    }

    @Override
    public void onStart(Intent intent) {
        HiLog.error(LABEL_LOG, "--------ServiceAbility1::onStart");
        super.onStart(intent);
    }
    
    /**
     * 每次调用ServiceAbility1都会执行该方法
     *
     * @param intent  数据载体
     * @param restart 启动状态 true:销毁后启动,false:正常启动
     * @param startId 启动的计数器
     */
    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::onCommand");
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::1数据载体:" + intent.getOperation().getAbilityName());
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::启动状态:" + restart);
        HiLog.info(LABEL_LOG, "--------ServiceAbility1::启动的计数器:" + startId);
    }

    @Override
    public void onDisconnect(Intent intent) {
        HiLog.info(LABEL_LOG, "--------连接Service断开::onDisconnect");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

创建Page Ability

public class MainAbilitySlice extends AbilitySlice {
    static final HiLogLabel LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00002, "MainAbilitySlice");


    private StartRemoteProxy startRemoteProxy = null;
    // 创建连接回调实例
    private IAbilityConnection conn = new IAbilityConnection() {
        //连接到Service的回调
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            // Client侧(StartRemoteProxy)需要定义与Service侧(AcceptRemoteProxy)相同的IRemoteObject实现类。
            // 开发者获取服务端传过来IRemoteObject对象,并从中解析出服务端传过来的信息。
            startRemoteProxy = new StartRemoteProxy(iRemoteObject);
            HiLog.info(LOG_LABEL, "--------连接Service" + startRemoteProxy.toString());
        }

        // 意外情况导致断开连接的回调
        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
            HiLog.info(LOG_LABEL, "--------意外情况导致断开连接");
        }
    };

 
    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart2");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //链接service
        Button button1 = (Button) findComponentById(ResourceTable.Id_button1);
        button1.setClickedListener(component -> {
            Intent connectPAIntent = new Intent();
            Operation operation = new Intent.OperationBuilder()
                    .withDeviceId("")
                    .withBundleName("com.example.myapplication")
                    .withAbilityName("com.example.myapplication.ServiceAbility1")
                    .build();
            connectPAIntent.setOperation(operation);
            connectAbility(connectPAIntent, conn);
        });

        //连接后进行通信
        Button button2 = (Button) findComponentById(ResourceTable.Id_button2);
        button2.setClickedListener(component -> {
            if (startRemoteProxy != null) {
                String rs = startRemoteProxy.test("hello world!");
                HiLog.info(LOG_LABEL, "-------接受端响应数据:" + rs);
            }
        });

        //断开链接service
        Button button3 = (Button) findComponentById(ResourceTable.Id_button3);
        button3.setClickedListener(component -> {
            disconnectAbility(conn);
        });

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:width="match_parent"
    ohos:height="match_parent"
    ohos:orientation="vertical">

    <Button
    ohos:id="$+id:button1"
    ohos:width="match_content"
    ohos:height="match_content"
    ohos:background_element="$graphic:background_button"
    ohos:text="连接Service"
    ohos:layout_alignment="horizontal_center"
    ohos:text_size="100"/>

    <Button
        ohos:id="$+id:button2"
        ohos:width="match_content"
        ohos:top_margin="100px"
        ohos:height="match_content"
        ohos:background_element="$graphic:background_button"
        ohos:text="连接后通信"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="100"/>

    <Button
        ohos:id="$+id:button3"
        ohos:width="match_content"
        ohos:top_margin="100px"
        ohos:height="match_content"
        ohos:background_element="$graphic:background_button"
        ohos:text="断开Service"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="100"/>

</DirectionalLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

本地设备连接Service

在这里插入图片描述

远程设备连接Service

public class MainAbilitySlice extends AbilitySlice {
    static final HiLogLabel LOG_LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00002, "MainAbilitySlice");


    private StartRemoteProxy startRemoteProxy = null;
    // 创建连接回调实例
    private IAbilityConnection conn = new IAbilityConnection() {
        //连接到Service的回调
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int i) {
            // Client侧(StartRemoteProxy)需要定义与Service侧(AcceptRemoteProxy)相同的IRemoteObject实现类。
            // 开发者获取服务端传过来IRemoteObject对象,并从中解析出服务端传过来的信息。
            startRemoteProxy = new StartRemoteProxy(iRemoteObject);
            HiLog.info(LOG_LABEL, "--------连接Service" + startRemoteProxy.toString());
        }

        // 意外情况导致断开连接的回调
        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int i) {
            HiLog.info(LOG_LABEL, "--------意外情况导致断开连接");
        }
    };

    @Override
    public void onStart(Intent intent) {
        HiLog.info(LOG_LABEL, "--------onStart2");
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //获取设备列表
        List<DeviceInfo> deviceList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
        if(deviceList.isEmpty()){
            return ;
        }
        int deviceNum = deviceList.size();
        List<String> deviceIds = new ArrayList<>(deviceNum);
        List<String> deviceNames = new ArrayList<>(deviceNum);
        deviceList.forEach((device)->{
            deviceIds.add(device.getDeviceId());
            deviceNames.add(device.getDeviceName());
        });

        //使用deviceIds的第一个元素,做为启动远程设备的目标id
        String devcieIdStr = deviceIds.get(0);


        //链接service
        Button button1 = (Button) findComponentById(ResourceTable.Id_button1);
        button1.setClickedListener(component -> {
             if(devcieIdStr!=null){
            Intent connectPAIntent = new Intent();
            Operation operation = new Intent.OperationBuilder()
                    .withDeviceId("")
                    .withBundleName("com.example.myapplication")
                    .withAbilityName("com.example.myapplication.ServiceAbility1")
                    .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
                    .build();
            connectPAIntent.setOperation(operation);
            connectAbility(connectPAIntent, conn);
                }
        });

        //连接后进行通信
        Button button2 = (Button) findComponentById(ResourceTable.Id_button2);
        button2.setClickedListener(component -> {
            if (startRemoteProxy != null) {
                String rs = startRemoteProxy.test("hello world!");
                HiLog.info(LOG_LABEL, "-------接受端响应数据:" + rs);
            }
        });

        //断开链接service
        Button button3 = (Button) findComponentById(ResourceTable.Id_button3);
        button3.setClickedListener(component -> {
            disconnectAbility(conn);
        });

    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

6.生命周期

Ability为启动Service提供了以下生命周期方法,可以重写这些方法来添加自己的处理。Service将在其他Ability调用startAbility()时创建,然后保持运行。其他Ability通过调用stopAbility()来停止Service,Service停止后,系统会将其销毁。

根据调用方法的不同,其生命周期有以下两种路径:

启动Service

该Service在其他Ability调用startAbility()时创建,然后保持运行。其他Ability通过调用stopAbility()来停止Service,Service停止后,系统会将其销毁。

连接Service

该Service在其他Ability调用connectAbility()时创建,客户端可通过调用disconnectAbility​()断开连接。多个客户端可以绑定到相同Service,而且当所有绑定全部取消后,系统即会销毁该Service。

在这里插入图片描述
onStart()

该方法在创建Service的时候调用,用于Service的初始化。在Service的整个生命周期只会调用一次,调用时传入的Intent应为空。

onCommand()

在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用,用户可以在该方法中做一些调用统计、初始化类的操作。

onConnect​()

在Ability和Service连接时调用,该方法返回IRemoteObject对象,用户可以在该回调函数中生成对应Service的IPC通信通道,以便Ability与Service交互。Ability可以多次连接同一个Service,系统会缓存该Service的IPC通信对象,只有第一个客户端连接Service时,系统才会调用Service的onConnect方法来生成IRemoteObject对象,而后系统会将同一个RemoteObject对象传递至其他连接同一个Service的所有客户端,而无需再次调用onConnect方法。

onDisconnect​()

在Ability与绑定的Service断开连接时调用。

onStop()

在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。

7.生命周期测试

启动/停止Service的生命周期

在这里插入图片描述

第一次启动本地设备的Service

01-10 11:45:56.905 7290-7290/com.example.myapplication E 01101/ServiceAbility1: --------ServiceAbility1::onStart
01-10 11:45:56.906 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::onCommand
01-10 11:45:56.906 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::1数据载体:com.example.myapplication.ServiceAbility1
01-10 11:45:56.906 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::启动状态:false
01-10 11:45:56.906 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::启动的计数器:1
  • 1
  • 2
  • 3
  • 4
  • 5

第二次启动本地设备的Service

01-10 11:48:18.613 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::onCommand
01-10 11:48:18.613 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::1数据载体:com.example.myapplication.ServiceAbility1
01-10 11:48:18.613 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::启动状态:false
01-10 11:48:18.613 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::启动的计数器:2
  • 1
  • 2
  • 3
  • 4

当点击停止本地设备的Service时

01-10 11:49:31.327 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::onBackground
01-10 11:49:31.327 7290-7290/com.example.myapplication I 01101/ServiceAbility1: --------ServiceAbility1::onStop
  • 1
  • 2

启动/停止Service的生命周期

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/313505?site
推荐阅读
相关标签
  

闽ICP备14008679号