This topic describes how to use Alibaba Cloud Mobile Push to push HarmonyOS notification extension messages.
Feature description
The HarmonyOS push platform provides the notification extension message feature. For more information, see Send notification extension messages.
Key points about the HarmonyOS notification extension message feature
The notification extension message feature is built on the standard notification feature. You must integrate standard notifications first.
You must apply for the notification extension message feature. For more information, see Apply for rights to push notification extension messages. Without this permission, you cannot send any messages, including test messages.
The main differences from the standard notification feature are as follows:
When you push a message, the extraData field is added to the payload to carry additional data. For more information, see ExtensionPayload.extraData.
When the application is in the background, it receives push messages through the onReceiveMessage method of RemoteNotificationExtensionAbility. For more information, see Steps 3 and 4 in Developer guide.
When the application is in the foreground, it receives push messages through the callback interface registered by the pushService.receiveMessage method. For more information, see Step 6 in Developer guide.
Support for notification extension messages in Alibaba Cloud Mobile Push
The HarmonyExtensionPush and HarmonyExtensionExtraData fields are added to the OpenAPI to support notification extension messages.
When you push messages through the HarmonyOS channel, Alibaba Cloud Mobile Push encapsulates and encrypts the extraData field. It also provides an API to parse and retrieve the push data.
If you do not specify a push channel and the application is in the foreground, notification extension messages are sent through Alibaba Cloud's proprietary channel.
Alibaba Cloud Mobile Push supports notification extension messages based on the features of the HarmonyOS platform. Before you begin, you must complete the preparations and implement the application-side code as described in the HarmonyOS document Send notification extension messages.
Push notification extension messages
New fields are added to the OpenAPI for pushing notification extension messages. You must add the HarmonyExtensionPush and HarmonyExtensionExtraData fields to your existing notification push configuration.
The HarmonyExtensionPush field is added to Advanced Push and Batch Push. If you set this field to true, a notification extension message is sent. If you set it to false, a standard notification is sent. The default value is false.
The HarmonyExtensionExtraData field is added to Advanced Push and Batch Push. This field carries extra data for the notification extension message and is valid only when you send a notification extension message.
Note that if you push a message instead of a notification, the HarmonyExtensionPush and HarmonyExtensionExtraData fields are invalid.
For definitions of the HarmonyExtensionPush and HarmonyExtensionExtraData fields, see HarmonyExtensionPush and HarmonyExtensionExtraData.
Receive notification extension messages
There are three ways to receive notification extension messages:
When the application is not in the foreground, messages are sent through the HarmonyOS channel. The application receives these messages through the onReceiveMessage method of RemoteNotificationExtensionAbility.
When the application is in the foreground and you specify the HarmonyOS channel, the application receives messages through the callback interface registered by the pushService.receiveMessage method.
When the application is in the foreground, messages are sent through Alibaba Cloud's proprietary channel by default. The application receives these messages through the onReceiveNotification method of IPushListener, which is provided by the software development kit (SDK).
These three scenarios can occur simultaneously. You must implement a handler for each scenario in your application.
When the application is not in the foreground, messages are sent through the HarmonyOS channel
First, implement RemoteNotificationExtensionAbility. For more information, see Steps 3 and 4 in Developer guide.
Alibaba Cloud Mobile Push encapsulates and encrypts the extraData field. The SDK provides the parseExtensionPushData method to parse the push data. Therefore, you must modify the implementation in the onReceiveMessage method. After you receive the push data, you must first parse it and then return the notification data. The following code provides a complete example:
import { pushCommon, RemoteNotificationExtensionAbility } from '@kit.PushKit';
import { aliyunPush, ExtensionNotification } from '@aliyun/push';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { common } from '@kit.AbilityKit';
export default class SampleRemoteNotification extends RemoteNotificationExtensionAbility {
async onReceiveMessage(remoteNotificationInfo: pushCommon.RemoteNotificationInfo):
Promise<pushCommon.RemoteNotificationContent> {
// ************* Notification extension message processing start *************
// Initialize push parameters to parse push data
aliyunPush.init({
appKey: 'Enter the AppKey that you queried in the preparations',
appSecret: 'Enter the AppSecret that you queried in the preparations',
context: this.context as common.Context,
})
// Call parseExtensionPushData to parse the push parameters
const notification: ExtensionNotification = await aliyunPush.parseExtensionPushData(remoteNotificationInfo);
// Here, you can get the parameters of the notification extension message for business processing
// The SDK provides the getRemoteNotificationContent helper method to construct the return value. The parameter EntryAbility is the name of the Ability to open when the notification is tapped.
const result = aliyunPush.getPushHelper().getRemoteNotificationContent('EntryAbility', notification);
return result;
// If you want to modify the content of the notification, you can return the desired content. We recommend that you keep wantAgent. If you do not keep it, you cannot identify the push parameters when the user taps the notification, and the notification tap data will be lost.
// return {
// // Other modified fields are omitted. We recommend that you use the parameters constructed by the getRemoteNotificationContent method for wantAgent.
// wantAgent: result.wantAgent
// }
// ************* Notification extension message processing end *************
}
}This process consists of three main parts:
Call aliyunPush.init to configure push parameters. This is required because RemoteNotificationExtensionAbility runs independently and does not execute the standard push initialization code. You must configure the parameters here to enable data parsing.
Call the aliyunPush.parseExtensionPushData method to parse the push data, retrieve an ExtensionNotification object, and then perform business processing.
As required by HarmonyOS, call the aliyunPush.getPushHelper().getRemoteNotificationContent method to construct the notification data to be returned for display. Replace the 'EntryAbility' parameter with the name of the Ability that opens when the user taps the notification.
If you do not use the aliyunPush.getPushHelper().getRemoteNotificationContent method to construct the returned notification data in Step 3, the push data is lost from the displayed notification. When the user taps the notification, it is treated as a standard notification, not a push-generated notification. As a result, you cannot retrieve the push data. For more information, see Retrieve push data from a notification.
When the application is not in the foreground and a notification extension message is sent through the HarmonyOS channel, the HarmonyOS system displays the notification after the onReceiveMessage method returns. If the notification includes badge parameters, the system handles them automatically. No separate processing is required.
ExtensionNotification
ExtensionNotification inherits from PushNotification. Its definition is as follows:
export enum PushDataType {
Notification = 1,
Message = 2,
ExtensionNotification = 3,
}
/**
* Common data for push notifications and messages
*/
export interface BasePushData {
// Other parameters are omitted
/**
* Data type. 1: Push notification. 2: Push message. 3: Notification extension message.
*/
type: PushDataType;
}
/**
* Push data
*/
export interface PushNotification extends BasePushData {
// Other parameters are omitted
}
export interface ExtensionNotification extends PushNotification {
/**
* The extraData field of the notification extension message
*/
extensionExtraData?: string;
}A type field value of 3 indicates that the push data is for a notification extension message. extensionExtraData represents the HarmonyExtensionExtraData field set by the service.
When the application is in the foreground, messages are sent through the specified HarmonyOS channel
First, implement the pushService.receiveMessage method to register the callback interface. For more information, see Step 6 in Developer guide.
Then, in the callback interface, call the aliyunPush.parseExtensionPushData method to parse the push data and perform business processing. The following code provides an example:
import { UIAbility } from '@kit.AbilityKit';
import { pushService } from '@kit.PushKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { ExtensionNotification } from '@aliyun/push';
import { aliyunPush } from '@aliyun/push';
import { notificationManager } from '@kit.NotificationKit';
/**
* This example uses EntryAbility to receive the content of a notification extension message.
*/
export default class EntryAbility extends UIAbility {
onCreate(): void {
// ************* Initialize SDK start *************
aliyunPush.init({
appKey: 'Enter the AppKey that you queried in the preparations',
appSecret: 'Enter the AppSecret that you queried in the preparations',
context: this.context,
})
// ************* Initialize SDK end *************
// Other initialization configuration methods are omitted
try {
// The parameter in receiveMessage is fixed to IM
pushService.receiveMessage('IM', this, async (data) => {
// Process the message. We recommend using try-catch for the Callback.
try {
// ************* Parse push parameters start *************
const extensionNotification: ExtensionNotification = await aliyunPush.parseExtensionPushData(data);
// ************* Parse push parameters end *************
// Perform business processing based on the obtained parameters of the notification extension message
hilog.info(0x0000, 'testTag', `Receive im message ${JSON.stringify(extensionNotification)}`);
// To display a notification, you can use the createNotificationRequest method to create a notificationManager.NotificationRequest for display.
const request = await aliyunPush.getPushHelper().createNotificationRequest(extensionNotification);
await notificationManager.publish(request);
// If the notification extension message also carries badge settings
if(extensionNotification.badgeSetNum !== undefined && extensionNotification.badgeSetNum >= 0) {
await notificationManager.setBadgeNumber(extensionNotification.badgeSetNum)
}
} catch (e) {
let errRes: BusinessError = e as BusinessError;
hilog.error(0x0000, 'testTag', 'Failed to process data: %{public}d %{public}s', errRes.code, errRes.message);
}
});
} catch (err) {
let e: BusinessError = err as BusinessError;
hilog.error(0x0000, 'testTag', 'Failed to get message: %{public}d %{public}s', e.code, e.message);
}
}
}After the application retrieves the ExtensionNotification object, you can proceed with your business logic.
If you also need to display a notification, you can refer to the example above to publish it.
If the notification extension message also includes badge parameters, you can refer to the example above to set the badge. The logic is the same as for Badge processing for custom notifications.
When the application is in the foreground, messages are sent through Alibaba Cloud's proprietary channel
When messages are sent through the proprietary channel, the onReceiveNotification method of IPushListener is reused to receive push messages. For more information about the overall logic, see Receive pushes.
The main difference is that the relevant parameters are extended to accommodate the ExtensionNotification type. The following code provides an example:
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { aliyunPush, ExtensionNotification, IPushListener,
PushDataType,
PushMessage, PushNotification } from '@aliyun/push';
// ************* IPushListener interface implementation start *************
/**
* Implementation of the push callback interface to receive push data
*/
class MyPushListener implements IPushListener {
onReceiveNotification(data: PushNotification | ExtensionNotification): boolean {
if (data.type === PushDataType.Notification) {
// Process push notifications
} else if (data.type === PushDataType.ExtensionNotification) {
// Process notification extension messages
}
// Returning false means not customizing the notification. Returning true means customizing the notification.
return false;
}
onShowNotification(data: PushNotification | ExtensionNotification): void {
if (data.type === PushDataType.Notification) {
// Process notification display events
} else if (data.type === PushDataType.ExtensionNotification) {
// Process notification extension message display events
}
}
onReceiveMessage(data: PushMessage): void {
// Process push messages
}
}
// ************* IPushListener interface implementation end *************
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
aliyunPush.init({
appKey: 'Enter the AppKey that you queried in the SDK integration preparations',
appSecret: 'Enter the AppSecret that you queried in the SDK integration preparations',
context: this.context,
})
// ************* Register IPushListener interface start *************
aliyunPush.setPushListener(new MyPushListener());
// ************* Register IPushListener interface end *************
}
// Other code is omitted
onDestroy(): void {
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
return;
}
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
}
onForeground(): void {
// Ability has brought to foreground
}
onBackground(): void {
// Ability has back to background
}
}