• Introducing XDA Computing: Discussion zones for Hardware, Software, and more!    Check it out!
  • Fill out your device list and let everyone know which phones you have!    Edit Your Device Inventory

Beginner: Service Ability features in Huawei Harmony OS

Search This thread

shikkerimath

Senior Member
Nov 30, 2020
78
21
Introduction

In this article, we can create an application showing below features:

1. Service Ability

2. Create service ability

3. Connect page ability with service ability

4. Update result on UI received from service ability

Requirements

1. DevEco IDE

2. Wearable watch (Can use simulator also)

Harmony OS Supports two types of abilities

1. Feature Ability

2. Particle Ability

In this article, we will test Particle Ability template called Service template.

UI Design

1615886719739.png


Service Template (Service Abilities):

The Service template is used for Particle Ability that provide background tasks.

A Service ability has only one instance on a device and multiple abilities share this instance.

Service Abilities runs on Main thread, you must create another thread for that operation in the Service ability.

Life cycle methods can be find here:


Main uses, it can be used in playing music or downloading files or any other background tasks which doesn’t need UI.

Create Service Ability:

It has two steps:

1. Register ability in config.json

2. Create service class extending Ability

Add the below code in Config.json

JSON:
{
  "app": {
    "bundleName": "com.example.testserviceability",
    "vendor": "example",
    "version": {
      "code": 1,
      "name": "1.0"
    },
    "apiVersion": {
      "compatible": 3,
      "target": 3
    }
  },
  "deviceConfig": {},
  "module": {
    "package": "com.example.testserviceability",
    "name": ".MyApplication",
    "deviceType": [
      "wearable"
    ],
    "distro": {
      "deliveryWithInstall": true,
      "moduleName": "entry",
      "moduleType": "entry"
    },
    "abilities": [
      {
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
        "orientation": "landscape",
        "name": "com.example.testserviceability.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "TestServiceAbility",
        "type": "page",
        "launchType": "standard"
      },
      {
        "name": ".ServiceAbility",
        "type": "service",
        "visible": true
      }
    ]
  }
}

Add the below code in ServiceAbility.java

Java:
package com.example.testserviceability;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.LocalRemoteObject;
import ohos.aafwk.content.Intent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.rpc.IRemoteObject;

public class ServiceAbility extends Ability {
    static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MY_TAG");

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        HiLog.info(LABEL_LOG, "inside onStart!!");
    }


    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        super.onCommand(intent, restart, startId);
        HiLog.info(LABEL_LOG, "inside onCommand!!");
    }


    @Override
    public IRemoteObject onConnect(Intent intent) {
        super.onConnect(intent);
        HiLog.info(LABEL_LOG, "inside onConnect!!");
        //return super.onConnect(intent);
        return new MyRemoteObject();
    }

    String sayHello(String name){
        return "Hello "+name;
    }


    @Override
    public void onDisconnect(Intent intent) {
        super.onDisconnect(intent);
        HiLog.info(LABEL_LOG, "inside onDisconnect!!");
    }


    @Override
    public void onStop() {
        super.onStop();
        HiLog.info(LABEL_LOG, "inside onStop!!");
    }

     public class MyRemoteObject extends LocalRemoteObject {
        public MyRemoteObject() {
            super();
        }

        public String callHello(String name){
            return sayHello(name);
        }
    }
}

Connect Page Ability with Service Ability:

This can be done using LocalRemoteObject, like shown below.

Add the below code in MainAbilitySlice.java

Java:
package com.example.testserviceability.slice;


import com.example.testserviceability.ResourceTable;
import com.example.testserviceability.ServiceAbility;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.IAbilityConnection;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.bundle.ElementName;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.rpc.IRemoteObject;


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


    ServiceAbility.MyRemoteObject myRemoteObject;
    Text text;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        text = (Text) findComponentById(ResourceTable.Id_text);
        Button btnStartService = (Button) findComponentById(ResourceTable.Id_button_start_service);
        btnStartService.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                startBackGroundService();
            }
        });


        Button btnCallServiceFunction = (Button) findComponentById(ResourceTable.Id_button_call_service_function);
        btnCallServiceFunction.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if(myRemoteObject != null){
                    String valueFromService = myRemoteObject.callHello("pavan");
                    HiLog.info(LABEL_LOG, "valueFromService-->"+valueFromService);
                    text.setText(valueFromService);
                }else{
                    HiLog.info(LABEL_LOG, "myRemoteObject is null!!");
                }
            }
        });
    }


    @Override
    public void onActive() {
        super.onActive();
    }


    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }


    private void startBackGroundService(){
        HiLog.info(LABEL_LOG, "inside startBackGroundService!!");
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName("com.example.testserviceability")
                .withAbilityName("com.example.testserviceability.ServiceAbility")
                .build();
        intent.setOperation(operation);
        connectAbility(intent, connection);
    }


    // Create an IAbilityConnection instance.
    private IAbilityConnection connection = new IAbilityConnection() {
        // Override the callback invoked when the Service ability is connected.
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {
            // The client must implement the IRemoteObject interface in the same way as the Service ability does. You will receive an IRemoteObject object from the server and can then parse information from it.
            myRemoteObject= (ServiceAbility.MyRemoteObject) iRemoteObject;
            HiLog.info(LABEL_LOG, "service connection made successful!!");
        }


        // Override  the callback invoked when the Service ability is disconnected.
        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int resultCode) {
        }
    };
}

Add the below code in ability_main.xml

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:orientation="vertical"
    ohos:background_element="#8c7373"
    ohos:padding="32">

    <Text
        ohos:multiple_lines="true"
        ohos:id="$+id:text"
        ohos:height="match_content"
        ohos:width="200"
        ohos:layout_alignment="horizontal_center"
        ohos:text="Text"
        ohos:text_size="10fp"/>

    <Button
        ohos:id="$+id:button_start_service"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_button"
        ohos:layout_alignment="horizontal_center"
        ohos:padding="5"
        ohos:text="Start service"
        ohos:text_size="30"
        ohos:top_margin="5"/>


    <Button
        ohos:id="$+id:button_call_service_function"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_button"
        ohos:layout_alignment="horizontal_center"
        ohos:padding="5"
        ohos:text="Call service function"
        ohos:text_size="30"
        ohos:top_margin="5"/>

</DirectionalLayout>

Connect Page ability with Service ability

Java:
private void startBackGroundService(){
     HiLog.info(LABEL_LOG, "inside startBackGroundService!!");
     Intent intent = new Intent();
     Operation operation = new Intent.OperationBuilder()
             .withDeviceId("")
             .withBundleName("com.example.testserviceability")
             .withAbilityName("com.example.testserviceability.ServiceAbility")
             .build();
     intent.setOperation(operation);
     connectAbility(intent, connection);
}

Call function of service from page ability

Code:
Button btnCallServiceFunction = (Button) findComponentById(ResourceTable.Id_button_call_service_function);
btnCallServiceFunction.setClickedListener(new Component.ClickedListener() {
     @Override
     public void onClick(Component component) {
         if(myRemoteObject != null){
             String valueFromService = myRemoteObject.callHello("pavan");
             HiLog.info(LABEL_LOG, "valueFromService-->"+valueFromService);
             text.setText(valueFromService);
         }else{
             HiLog.info(LABEL_LOG, "myRemoteObject is null!!");
         }
     }
});

Tips and Tricks

1. All Abilities must be registered into Config.json.

2. Service Ability runs on main thread, you must create other thread to handle work.

Conclusion

In this article, we have UI components communicating with background running service. Calling a function of background service and getting result back on UI.

Reference

1.
Harmony Official document

2. DevEco Studio User guide

3. JS API Reference

Checkout in forum
 
Last edited:

alej1286

New member
Jan 21, 2017
1
0
Well done, can you please upload the sources files, because i am new developing in DevEco, and need to know the distribution of the files in the project, thanks in advance