目录

Privacy Agreement Management Service

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.

Use Cases

Service Process

[h2]Querying the Privacy Agreement URL

  1. A user needs to query the privacy agreement URL.

  2. The app or atomic service calls the getAppPrivacyMgmtInfo API to query the privacy agreement URL.

  3. The API returns the privacy agreement URL.

  4. The app or atomic service sends the query result to the user.

[h2]Querying the Privacy Agreement Signing Status

  1. A user needs to query the privacy agreement signing status.

  2. The app or atomic service calls the getAppPrivacyResult API to query the privacy agreement signing status.

  3. The API returns the privacy agreement signing status.

  4. The app or atomic service returns the result to the user.

Constraints

API Description

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.

Development Procedure

[h2]Querying the Privacy Agreement URL

  1. Import the privacyManager module and related common modules.

    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { privacyManager } from '@kit.AppGalleryKit';
  2. 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);
    }

[h2]Querying the Privacy Agreement Signing Status

  1. Import the privacyManager module and related common modules.

    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { privacyManager } from '@kit.AppGalleryKit';
  2. 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);
    }

Common Event Indicating the Privacy Agreement Signing Result

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.

[h2]Event Description

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);
      }
    });
  }
}

Integrating the Privacy Agreement Management Service into an Unreleased App

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.

  1. Change the build mode of the app project to debug.

  2. 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.
        }
    ]
}