目录

Developing Your App

Obtaining a Push Token

A token uniquely identifies an app on a device. The app calls the getToken method to obtain a token from the Push Kit server. Then you can send a message to the app based on the obtained token. When no token is returned by getToken, use onNewToken to obtain one.

You are advised to upload push tokens to your app server as a list and update the list periodically. You can call the downlink message sending API of the Push Kit server to send messages in batches based on the push tokens.

  1. Create a thread and call the getToken method to obtain a push token. (It is recommended that the getToken method be called in the first Ability class after app startup.)
    public class TokenAbilitySlice extends AbilitySlice {
        private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD001234, 
    "TokenAbilitySlice");
        private void getToken() {
            // Create a thread.
            new Thread("getToken") {
                @Override
                public void run() {
                    try {
                        // Obtain the value of client_id from the agconnect-services.json file.
                        String appId = "your client_id";
                        // Set tokenScope to HCM.
                        String tokenScope = "HCM";
                        // Obtain a push token.
                        String token = HmsInstanceId.getInstance(getAbility().getAbilityPackage(), TokenAbilitySlice.this).getToken(appId, tokenScope);
                    } catch (ApiException e) {
                        // An error code is recorded when the push token fails to be obtained.
                        HiLog.error(LABEL_LOG, "get token failed, the error code is %{public}d", e.getStatusCode());
                    }
                }
            }.start();
        }
    }
  2. Override the onNewToken method in your service (extended HmsMessageService). When the token changes, the new token can be returned through the onNewToken method.
    public class DemoHmsMessageServiceAbility extends HmsMessageService {
        private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD001234, "DemoHmsMessageServiceAbility");
    
        @Override
        // Obtain a push token.
        public void onNewToken(String token) {
            HiLog.info(LABEL_LOG, "onNewToken called, token:%{public}s", token);
        }
    
        @Override
        // An error code is recorded when the push token fails to be obtained.
        public void onTokenError(Exception exception) {
            HiLog.error(LABEL_LOG, "get onNewtoken error, error code is %{public}d", ((ZBaseException)exception).getErrorCode());
        }
    }

Obtaining Data Message Content

Overwrite the onMessageReceived method in your service (inherited from HmsMessageService). Then you can obtain data message content as long as you send the data message to devices.

public class DemoHmsMessageServiceAbility extends HmsMessageService {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD001234, 
"DemoHmsMessageServiceAbility");
    @Override
    public void onMessageReceived(ZRemoteMessage message) {
        // The fields in the message content are recorded.
        HiLog.info(LABEL_LOG, "get token, %{public}s", message.getToken());
        HiLog.info(LABEL_LOG, "get data, %{public}s", message.getData());

        ZRemoteMessage.Notification notification = message.getNotification();
        if (notification != null) {
            HiLog.info(LABEL_LOG, "get title, %{public}s", notification.getTitle());
            HiLog.info(LABEL_LOG, "get body, %{public}s", notification.getBody());
        }
    }
}

Sending Messages

  1. Call the https://oauth-login.cloud.huawei.com/oauth2/v3/token API of the Account Kit server to obtain an access token. Request example:
    POST /oauth2/v3/token HTTP/1.1
    Host: oauth-login.cloud.huawei.com
    Content-Type: application/x-www-form-urlencoded
     
    grant_type=client_credentials&client_id=<Client ID>&client_secret=<Client secret>

    In the example, set Client ID and Client Secret to the client ID and client secret in OAuth 2.0 client ID of your HarmonyOS app in AppGallery Connect.

    Response example:

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    Cache-Control: no-store
    
    {
        "access_token": "<Returned access token>",
        "expires_in": 3600,
        "token_type": "Bearer"
    }
    • Within the validity period (specified by expires_in) of the access token, do not frequently send requests. Otherwise, flow control may be triggered. The current threshold for triggering the app-level access token flow control is 1000 access tokens every 5 minutes. In 5 minutes, you can apply for another. You can apply for a new access token in advance or use a refresh token to update the access token within its validity period. In addition, you can trigger the access token application process again based on the returned access token timeout error (NSP_STATUS=6; for more information, please refer to Error Type).
    • For details about other error codes, please refer to Error Type.
  2. Call the API to send a message. The following is a request example:

    URL for calling the API using HTTPS POST:

    POST https://push-api.cloud.huawei.com/v1/[clientid]/messages:send

    In the URL, set [clientid] to the client ID in OAuth 2.0 client ID of your HarmonyOS app in AppGallery Connect.

    Request header example:

    Content-Type: application/json; charset=UTF-8
    Authorization: Bearer CF3Xl2XV6jMK************************DgAPuzvNm3WccUIaDg== 
    • The value of the Authorization parameter in the request header is the access token obtained in the response from step 1.
    • In each authorization mode, if an access token is manually obtained, for example, by running the curl command or using Postman, remember to restore the escape character \/ to / in the JSON character string so that the obtained access token is correct. To obtain a correct access token during code execution, you can use any third-party library to parse the JSON string.
    Request body example (for a notification message):
    {
        "validate_only": false,
        "message": {
            "android": {
                "notification": {
                    "title": "test title",
                    "body": "test body",
                    "click_action": {
                        "type": 3
                    }
                }
            },
            "token": ["pushtoken1"]
        }
    }

    The value of the token parameter in the request body is a push token. For details about the message body, please refer to en-us_topic_0000001050986197.html#EN-US_TOPIC_0000001050986197__p2316168162314.

Customizing Actions to Be Triggered upon Notification Message Tapping

You can customize the action triggered when a user taps the notification message, for example, opening the app home page, a website URL, or a specified app page.

[h2]Opening the App Home Page

[h2]Opening a Web Page

[h2]Opening a Specified App Page

  1. Create a custom app page (for example, MyActionAbility), and add the skills field of the ability to the config.json file in the entry/src/main directory of your project. In the field, entities has a fixed value of entity.system.default and actions can be set (for example, to com.test.myaction) as needed.
    {
        "orientation": "unspecified",
        "name": "com.test.java.MyActionAbility",
        "icon": "$media:icon",
        "description": "$string:myactionability_description",
        "label": "$string:entry_MyActionAbility",
        "type": "page",
        "launchType": "standard",
        "skills": [    
            {
                "entities": ["entity.system.default"],
                "actions": ["com.test.myaction"]    
            } 
        ]
    }
  2. Use AppGallery Connect to send messages, and set Action to Open app and App page to Custom action page. (Set action to the value of actions defined in the previous step.)

    You can also call the Push Kit server API to send messages. In this case, carry the click_action field, and set type to 1 (indicating to open a specified app page after message tapping) and action to the value of actions defined in the previous step.

    {
        "validate_only": false,
        "message": {
            "android": {
                "notification": {
                    "title": "test title",
                    "body": "test body",
                    "click_action": {
                        "type": 1,
                        "action":"com.test.myaction"
                    }
                }
            },
            "token": ["pushtoken1"]
        }
    }

[h2]Transferring Data

When sending a message, you can carry the data field in the messages. When a user taps the message, data in the data field will be transferred to the app in the specified way.

  1. Carry the data field in the message to be sent.
    • Use AppGallery Connect to send the message and set Key-value pair.
    • Call the Push Kit server API to send messages and carry the data field in the message body.
      {
          "validate_only": false,
          "message": {
              "android": {
                  "notification": {
                      "title": "test title",
                      "body": "test body",
                      "click_action": {
                          "type": 1,
                          "action":"com.test.myaction"
                      }
                  },
                  "data": "{'key_data':'value_data'}"
              },
              "token": ["pushtoken1"]
          }
      }
  2. Implement the app page displayed after message tapping to obtain the data field. Here, we assume that the app home page (MainAbilitySlice) is displayed after message tapping.
    public class MainAbilitySlice extends AbilitySlice {
        private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD001234, "myDemo");
        @Override    
        public void onStart(Intent intent) {        
            HiLog.info(LABEL_LOG, "MainAbilitySlice get started...");
            super.onStart(intent);
            super.setUIContent(ResourceTable.Layout_ability_main);
            // Call the parsing method.
            parseIntent(intent);
        }
    
        private void parseIntent(Intent intent){
            if (intent == null){return;}    
            IntentParams intentParams = intent.getParams();
            if (intentParams == null) {return;} 
            // Obtain the key-value pair in the data field.
            String key = "key_data";    
            Object obj = intentParams.getParam(key);
            try{
                // Print the key-value pair in the data field.
                HiLog.info(LABEL_LOG, "my key: %{public}s, my value: %{public}s", key, obj);    
            }catch (Exception e){
                HiLog.info(LABEL_LOG, "catch exception : " + e.getMessage());    
            }
        }
    }