This service provides apps and atomic services that have integrated the standardized privacy statement hosting service with the ability to query privacy agreement URLs, check the privacy agreement signing status, revoke the privacy agreement consent record, and display the standardized privacy agreement pop-up to request user consent.
If the standardized privacy statement hosting service is integrated into an app or atomic service, the standardized privacy agreement pop-up will be displayed by default when the app or atomic service is opened for the first time. Do not implement the display of the privacy agreement pop-up in the app or atomic service yourself. Otherwise, the app or atomic service will be rejected during release review.
Querying privacy agreement URLs
This function supports querying or displaying a privacy agreement within your app or atomic service if your app or atomic service has integrated the standardized privacy statement hosting service.
Querying the privacy agreement signing status
This function supports querying the agreement signing status so that your app or atomic service can plan permissions and obtain data properly and compliantly. If a user has not signed the privacy agreement, they cannot request system permissions.
Revoking the consent record
This function is used to revoke the privacy agreement consent record. After revocation, reopening the app or atomic service will trigger the standardized privacy agreement pop-up again.
Requesting user consent
This function is used for you to proactively display the standardized privacy agreement pop-up to request user consent if your app has integrated the standardized privacy statement hosting service.
A user needs to query the privacy agreement URL.
The app or atomic service calls the getAppPrivacyMgmtInfo API to query the privacy agreement URL.
The API returns the privacy agreement URL.
The app or atomic service sends the query result to the user.
A user needs to query the privacy agreement signing status.
The app or atomic service calls the getAppPrivacyResult API to query the privacy agreement signing status.
The API returns the privacy agreement signing status.
The app or atomic service returns the result to the user.
A user needs to revoke the privacy agreement consent record.
The app or atomic service calls the disableService API to revoke the privacy agreement consent record.
A user needs to display the standardized privacy agreement pop-up.
The app or atomic service calls the requestAppPrivacyConsent API to launch the standardized privacy agreement pop-up.
The pop-up result is returned.
The standardized privacy agreement pop-up is displayed to request user consent.
The loadContent() method cannot be repeatedly called to load pages in the same ability.
The app or atomic service needs to integrate the standardized privacy statement hosting service.
The privacy agreement management service is supported on phones, tablets, and PCs/2-in-1 devices. Starting from version 5.1.1(19), it is also supported on TVs.
The privacy agreement management service does not support the Emulator. Use a real device for debugging.
The privacy agreement management service provides the following APIs. For details, please refer to the API reference.
| API | Description |
|---|---|
| getAppPrivacyMgmtInfo(): AppPrivacyMgmtInfo | Queries the privacy agreement URL. |
| getAppPrivacyResult(): AppPrivacyResult[] | Queries the privacy agreement signing status. |
| disableService():void | Revokes the privacy agreement consent record. |
| requestAppPrivacyConsent(context:common.UIAbilityContext):Promise<ConsentResult> | Displays the standardized privacy agreement pop-up to request user consent. |
Import the privacyManager module and related common modules.
import { hilog } from '@kit.PerformanceAnalysisKit';
import { privacyManager } from '@kit.AppGalleryKit'; Call the getAppPrivacyMgmtInfo method to obtain the privacy agreement URL.
try {
let appPrivacyManageInfo: privacyManager.AppPrivacyMgmtInfo = privacyManager.getAppPrivacyMgmtInfo();
hilog.info(0, 'TAG', 'Succeeded in getting AppPrivacyManageInfo type: ' + appPrivacyManageInfo['type']);
let privacyLinkInfoArray : privacyManager.AppPrivacyLink[] = appPrivacyManageInfo.privacyInfo;
hilog.info(0, 'TAG', 'Succeeded in getting AppPrivacyManageInfo size = ' + privacyLinkInfoArray.length);
for (let i = 0; i < privacyLinkInfoArray.length; i++) {
hilog.info(0, 'TAG', 'Succeeded in getting AppPrivacyManageInfo type = ' + privacyLinkInfoArray[i]['type'] + ', version = ' + privacyLinkInfoArray[i]['versionCode'] + ', url = ' + privacyLinkInfoArray[i]['url']);
}
} catch (error) {
hilog.error(0, 'TAG', 'GetAppPrivacyManageInfoPublic exception code: ' + error.code + ', exception message: ' + error.message);
} Import the privacyManager module and related common modules.
import { hilog } from '@kit.PerformanceAnalysisKit';
import { privacyManager } from '@kit.AppGalleryKit'; Call the getAppPrivacyResult API to query the privacy agreement signing status.
try {
let appPrivacyResults: privacyManager.AppPrivacyResult[] = privacyManager.getAppPrivacyResult();
hilog.info(0, 'TAG', 'Succeeded in getting AppPrivacyResult size = ' + appPrivacyResults.length);
for (let i = 0; i < appPrivacyResults.length; i++) {
hilog.info(0, 'TAG', 'Succeeded in getting AppPrivacyResult type = ' + appPrivacyResults[i]['type'] + ', version = ' + appPrivacyResults[i]['versionCode'] + ', result = '+appPrivacyResults[i]['result']);
}
} catch (error) {
hilog.error(0, 'TAG', 'GetAppPrivacyResultPublic exception code: ' + error.code + ', exception message: ' + error.message);
} Import the privacyManager module and related common modules.
import { hilog } from '@kit.PerformanceAnalysisKit';
import { privacyManager } from '@kit.AppGalleryKit'; Call the disableService API to revoke the consent record.
try {
privacyManager.disableService();
hilog.info(0, 'TAG', 'Succeeded in disabling Service success.');
} catch (error) {
hilog.error(0, 'TAG', 'DisableService exception code: ' + error.code + ', exception message: ' + error.message);
} Import the privacyManager module and related common modules.
import { privacyManager } from '@kit.AppGalleryKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import type { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit'; Call the requestAppPrivacyConsent API to display the standardized privacy agreement pop-up to request user consent.
try {
const uiContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
privacyManager.requestAppPrivacyConsent(uiContext).then((consentResult : privacyManager.ConsentResult) => {
let appPrivacyResults: privacyManager.AppPrivacyResult[] = consentResult['results'];
for (let i = 0; i < appPrivacyResults.length; i++) {
hilog.info(0, 'TAG', 'GetAppPrivacyResult type = ' + appPrivacyResults[i]['type'] + ', version = ' + appPrivacyResults[i]['versionCode'] + ', result = ' + appPrivacyResults[i]['result'] + ', signingTimestamp = ' + appPrivacyResults[i]['signingTimestamp']);
}
}).catch((error: BusinessError<Object>) => {
hilog.error(0, 'TAG', `requestAppPrivacyConsent failed, Code: ${error.code}, message: ${error.message}`);
});
} catch (error) {
hilog.error(0, 'TAG', 'requestAppPrivacyConsent exception code: ' + error.code + ', exception message: ' + error.message);
} After your app or atomic service integrates the standardized privacy statement hosting service, if a user has not agreed to the privacy agreement, a standardized privacy agreement pop-up will appear when the user launches the app or atomic service.
When the user taps Agree in the pop-up, AppGallery will send a common event indicating the privacy agreement pop-up signing result. Your app or atomic service can listen to this event to obtain the privacy agreement signing result.
| Event | Value | Description |
|---|---|---|
| COMMON_EVENT_PRIVACY_STATE_CHANGED | usual.event.PRIVACY_STATE_CHANGED | Common event indicating the privacy agreement signing result. The event carries the following data: { 'resultType': privacyResultType, 'appIndex': appIndex } Note: - The options of privacyResultType are as follows: 1: The user has agreed to the privacy agreement for enabling full-mode access. 0: The user has not agreed to the privacy agreement. - appIndex: twin index. |
The following is an example of receiving a common event (without an app twin):
import { hilog } from '@kit.PerformanceAnalysisKit';
import { commonEventManager } from '@kit.BasicServicesKit';
// ...
const TAG = 'PrivacySubscribe';
// ...
class PrivacySubscribeSample {
// ...
private readonly eventId = 'usual.event.PRIVACY_STATE_CHANGED';
// Subscriber information. Used to save the created subscriber object for subsequent subscription and unsubscription.
private subscriber: commonEventManager.CommonEventSubscriber | undefined = undefined;
// Event list.
private subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
events: [this.eventId]
};
// ...
public subscribe(): void {
hilog.info(0, TAG, 'subscribe');
// Create a subscriber.
commonEventManager.createSubscriber(this.subscribeInfo).then((commonEventSubscriber) => {
hilog.info(0, TAG, 'createSubscriber');
this.subscriber = commonEventSubscriber;
// Subscribe to a common event.
try {
commonEventManager.subscribe(this.subscriber, (err, data) => {
if (err) {
hilog.error(0, TAG, `subscribe failed, code is ${err?.code}, message is ${err?.message}`);
return;
}
let result = JSON.parse(data?.data ?? '{}')?.resultType as number;
// ...
if (result === 1) {
// The user agrees to the privacy agreement.
}
// ...
});
} catch (error) {
hilog.error(0, TAG, 'init createSubscriber failed, exception code: ' + error.code + ', exception message: ' + error.message);
}
});
}
} The following is an example of receiving a common event (with an app twin):
import { hilog } from '@kit.PerformanceAnalysisKit';
import { commonEventManager } from '@kit.BasicServicesKit';
import { UIAbility } from '@kit.AbilityKit';
const TAG = 'PrivacyEventSubscriber';
export default class MyAbility extends UIAbility {
onBackground() {
let appCloneIndex = 0;
let applicationContext = this.context.getApplicationContext();
try {
appCloneIndex = applicationContext.getCurrentAppCloneIndex();
} catch (error) {
hilog.error(0, TAG, `getCurrentAppCloneIndex fail, exception code:` + error.code + `, exception message: ` + error.message);
}
new PrivacyEventSubscriber(appCloneIndex).subscribe();
}
}
class PrivacyEventSubscriber {
private appCloneIndex: number = 0;
private readonly eventId = 'usual.event.PRIVACY_STATE_CHANGED';
// Subscriber information. Used to save the created subscriber object for subsequent subscription and unsubscription.
private subscriber: commonEventManager.CommonEventSubscriber | undefined = undefined;
// Event list.
private subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
events: [this.eventId]
};
constructor(appCloneIndex: number) {
this.appCloneIndex = appCloneIndex;
}
public subscribe(): void {
hilog.info(0, TAG, 'subscribe');
// Create a subscriber.
commonEventManager.createSubscriber(this.subscribeInfo).then((commonEventSubscriber) => {
hilog.info(0, TAG, 'createSubscriber');
this.subscriber = commonEventSubscriber;
// Subscribe to a common event.
try {
commonEventManager.subscribe(this.subscriber, (err, data) => {
if (err) {
hilog.error(0, TAG, `subscribe failed, code is ${err?.code}, message is ${err?.message}`);
return;
}
let result = JSON.parse(data?.data ?? '{}')?.resultType as number;
let appIndex = JSON.parse(data?.data ?? '{}')?.appIndex as number ?? 0;
// The twin index passed by the common event is the same as the twin index of the current app.
if (appIndex === this.appCloneIndex) {
if (result === 1) {
// The user agrees to the privacy agreement.
}
}
});
} catch (error) {
hilog.error(0, TAG, 'init createSubscriber failed, exception code: ' + error.code + ', exception message: ' + error.message);
}
});
}
} For apps or atomic services that are not yet available on AppGallery, you can manually preset privacy agreement URLs to simulate the integration of the privacy statement hosting and agreement management services.
Once this information is set up, a privacy agreement pop-up will be displayed when a user opens your app. Your app can then use the functions provided by the privacy agreement management service, such as querying privacy agreement URLs, checking the privacy agreement signing status, and revoking the privacy agreement consent record.
Change the build mode of the app project to debug.
Open the module whose type is entry in the code project, and modify the src/main/module.json5 file by adding the module.metadata information, which contains the following fields with values of the string type.
| Field | Description | Mandatory |
|---|---|---|
| appgallery_privacy_hosted | Indicates whether to enable the privacy agreement pop-up. 1 indicates yes, while other values indicate no. | Yes |
| appgallery_privacy_link_privacy_statement | Privacy agreement URL (HTTPS). A link specified by this URL will be displayed in the pop-up. | Yes |
| appgallery_privacy_link_user_agreement | User agreement URL (HTTPS). A link specified by this URL will be displayed in the pop-up. | No |
| appgallery_privacy_link_user_agreements | Multiple user agreement URLs (HTTPS). Links specified by these URLs will be displayed in the pop-up. This field points to a JSON file stored in the resources/rawfile folder of the module whose type is entry. When there are multiple user agreement URLs, the appgallery_privacy_link_user_agreements field takes precedence, and the single user agreement URL configured through appgallery_privacy_link_user_agreement will become invalid. Since: 5.0.2(14) | No |
When AppGallery is functioning properly and the network is connected, you can run the hdc command to install your app from a local file. Then you can test the privacy agreement pop-up and debug the privacy agreement management service APIs using the preset privacy agreement URLs.
The sample code is as follows:
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
// ...
"metadata": [
{
"name": "appgallery_privacy_hosted",
"value": "1"
},
{
"name": "appgallery_privacy_link_privacy_statement",
"value": "https://www.example.com/" // Must be an HTTPS URL.
},
{
"name": "appgallery_privacy_link_user_agreement",
"value": "https://www.example.com/" // Must be an HTTPS URL.
},
{
"name": "appgallery_privacy_link_user_agreements",
"value": "../ets/resources/privacyLinkUserAgreements/link_user_agreements.json" // Name of the JSON configuration file. For details, see the following example.
},
// ...
]
}
} The sample code in the link_user_agreements.json file is as follows:
{
"user_agreement_Infos": [
{
"name": "User agreement 1", // Name of user agreement 1 to be displayed.
"url": "https://xxxx" // User agreement URL.
},
{
"name": "User agreement 2", // Name of user agreement 2 to be displayed.
"url": "https://xxxx" // User agreement URL.
}
]
}