目录

LoginWithHuaweiIDButton (HUAWEI ID Sign-in Button Component)

This module provides the LoginWithHuaweiIDButton component. You can integrate this component into your app to implement the HUAWEI ID sign-in function.

The LoginWithHuaweiIDButton component must be used with loginComponentManager to implement the HUAWEI ID sign-in function. The text content of the LoginWithHuaweiIDButton component supports multiple languages by default.

Since: 4.1.0(11)

Modules to Import

import { LoginWithHuaweiIDButton, loginComponentManager } from '@kit.AccountKit';

LoginWithHuaweiIDButton

The @hms.core.account.LoginComponent module provides an independent HUAWEI ID sign-in button component that supports multiple styles. This component can be embedded into the custom sign-in screen of your app. You can integrate this component by following the procedure below:

  1. Create a loginComponentManager.LoginWithHuaweiIDButtonController object. You can register callbacks for button tap events through chained calls and proactively set the user agreement consent status. In the one-tap sign-in scenario, the input parameter setAgreementStatus must be set to ACCEPTED before initiating the sign-in.

  2. Construct a loginComponentManager.LoginWithHuaweiIDButtonParams object and configure properties such as the sign-in type and button style.

  3. Use the LoginWithHuaweiIDButton component in your screen component and pass the LoginWithHuaweiIDButtonController and LoginWithHuaweiIDButtonParams objects.

Model restriction: This API can be used only in the stage model.

Decorator: @Component

System capability: SystemCapability.AuthenticationServices.HuaweiID.UIComponent

Since: 4.1.0(11)

Parameters

Name Type Mandatory Decorator Type Description
params loginComponentManager.LoginWithHuaweiIDButtonParams Yes

@Require

Applicable versions: 26.0.0+

LoginWithHuaweiIDButton component parameters.
controller loginComponentManager.LoginWithHuaweiIDButtonController Yes

@Require

Applicable versions: 26.0.0+

LoginWithHuaweiIDButton component controller, which is used to receive tap events in the component.

[h2]build

build(): void

Constructor for the LoginWithHuaweiIDButton component.

Model restriction: This API can be used only in the stage model.

System capability: SystemCapability.AuthenticationServices.HuaweiID.UIComponent

Since: 4.1.0(11)

Example:

import { loginComponentManager, LoginWithHuaweiIDButton } from '@kit.AccountKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

@Entry
@Component
struct QuickLoginButtonComponent {
  logTag: string = 'QuickLoginButtonComponent';
  domainId: number = 0x0000;
  // Obtain the anonymous mobile number by referring to the Account Kit Development Guide.
  @State quickLoginAnonymousPhone: string = '';
  // Display the User Service Agreement, Privacy Statement, and HUAWEI ID User Authentication Agreement.
  privacyText: loginComponentManager.PrivacyText[] = [{
    text: 'I have read and agree to the ',
    type: loginComponentManager.TextType.PLAIN_TEXT
  }, {
    text: 'User Service Agreement, ',
    tag: 'User Service Agreement',
    type: loginComponentManager.TextType.RICH_TEXT
  }, {
    text: 'Privacy Statement, ',
    tag: 'Privacy Statement',
    type: loginComponentManager.TextType.RICH_TEXT
  }, {
    text: 'and ',
    type: loginComponentManager.TextType.PLAIN_TEXT
  }, {
    text: 'HUAWEI ID User Authentication Agreement',
    tag: 'HUAWEI ID User Authentication Agreement',
    type: loginComponentManager.TextType.RICH_TEXT
  }];
  // Construct the controller of the LoginWithHuaweiIDButton component.
  controller: loginComponentManager.LoginWithHuaweiIDButtonController =
    new loginComponentManager.LoginWithHuaweiIDButtonController()
      /**
       * With a custom sign-in UI, when a user does not accept the agreements, the app needs to set the agreement status to NOT_ACCEPTED,
       * and change the status to ACCEPTED after the user accepts the agreements. One-tap HUAWEI ID sign-in is available only when the agreement status is ACCEPTED.
       */
      .setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED)
      .onClickLoginWithHuaweiIDButton((error: BusinessError, response: loginComponentManager.HuaweiIDCredential) => {
        if (error) {
          this.dealAllError(error);
          return;
        }
        if (response) {
          // Send the obtained authorization code to the app server.
          const authorizationCode = response.authorizationCode;
          hilog.info(0x0000, 'testTag', 'Succeeded in getting response.');
          return;
        }
      })
      .onClickEvent((error: BusinessError, clickEvent: loginComponentManager.ClickEvent) => {
        if (error) {
          this.dealAllError(error);
          return;
        }
        hilog.info(0x0000, 'testTag', `onClickEvent clickEvent: ${clickEvent}`);
      });

  // Handle the error.
  dealAllError(error: BusinessError): void {
    hilog.error(0x0000, 'testTag', `Failed to login, errorCode=${error.code}, errorMsg=${error.message}`);
    // In sign-in scenarios involving UI interactions, it is advised to guide users with the following error code prompts:
    if (error.code === ErrorCode.ERROR_CODE_LOGIN_OUT) {
      // HUAWEI ID not signed in. Use a HUAWEI ID to sign in and try again, or sign in to the app in another way.
    } else if (error.code === ErrorCode.ERROR_CODE_NETWORK_ERROR) {
      // Network error. Check the network connection and try again.
    } else if (error.code === ErrorCode.ERROR_CODE_INTERNAL_ERROR) {
      // Failed to sign in. Try another way.
    } else if (error.code === ErrorCode.ERROR_CODE_USER_CANCEL) {
      // Authorization canceled by the user.
    } else if (error.code === ErrorCode.ERROR_CODE_SYSTEM_SERVICE) {
      // System service exception. Try again later or sign in to the app in another way.
    } else if (error.code === ErrorCode.ERROR_CODE_REQUEST_REFUSE) {
      // Repeated request. No further action is needed.
    } else if (error.code === ErrorCode.ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED) {
      // The user does not accept the agreements.
    } else {
      // Failed to sign in. Try another way.
    }
  }

  build() {
    Scroll() {
      Column() {
        Column() {
          Column() {
            // This is a sample icon. You can replace it with a real icon to ensure proper compilation and execution.
            Image($r('app.media.app_icon'))
              .width(48)
              .height(48)
              .draggable(false)
              .copyOption(CopyOptions.None)
              .onComplete(() => {
                hilog.info(0x0000, 'testTag', 'appIcon loading success');
              })
              .onError(() => {
                hilog.error(0x0000, 'testTag', 'appIcon loading fail');
              })

            Text($r('app.string.app_name'))
              .fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
              .fontWeight(FontWeight.Bold)
              .maxFontSize($r('sys.float.ohos_id_text_size_headline8'))
              .minFontSize($r('sys.float.ohos_id_text_size_body1'))
              .maxLines(1)
              .fontColor($r('sys.color.ohos_id_color_text_primary'))
              .constraintSize({ maxWidth: '100%' })
              .margin({
                top: 12
              })

            Text('App description')
              .fontSize($r('sys.float.ohos_id_text_size_body2'))
              .fontColor($r('sys.color.ohos_id_color_text_secondary'))
              .fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
              .fontWeight(FontWeight.Regular)
              .constraintSize({ maxWidth: '100%' })
              .margin({
                top: 8
              })
          }.margin({
            top: 100
          })

          Column() {
            Text(this.quickLoginAnonymousPhone)
              .fontSize(36)
              .fontColor($r('sys.color.ohos_id_color_text_primary'))
              .fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
              .fontWeight(FontWeight.Bold)
              .lineHeight(48)
              .textAlign(TextAlign.Center)
              .maxLines(1)
              .constraintSize({ maxWidth: '100%', minHeight: 48 })

            Text('Mobile number bound to a HUAWEI ID')
              .fontSize($r('sys.float.ohos_id_text_size_body2'))
              .fontColor($r('sys.color.ohos_id_color_text_secondary'))
              .fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
              .fontWeight(FontWeight.Regular)
              .lineHeight(19)
              .textAlign(TextAlign.Center)
              .maxLines(1)
              .constraintSize({ maxWidth: '100%' })
              .margin({
                top: 8
              })
          }.margin({
            top: 64
          })

          Column() {
            LoginWithHuaweiIDButton({
              params: {
                // Style supported by LoginWithHuaweiIDButton.
                style: loginComponentManager.Style.BUTTON_RED,
                // Set the HUAWEI ID sign-in button to the loading state while the user is signing in.
                extraStyle: {
                  buttonStyle: new loginComponentManager.ButtonStyle().loadingStyle({
                    show: true
                  })
                },
                // Rounded corner radius of LoginWithHuaweiIDButton.
                borderRadius: 24,
                // Sign-in type supported by LoginWithHuaweiIDButton.
                loginType: loginComponentManager.LoginType.QUICK_LOGIN,
                // The button style of LoginWithHuaweiIDButton can follow system settings (dark/light mode).
                supportDarkMode: true
              },
              controller: this.controller
            })
          }
          .height(40)
          .width('100%')
          .margin({
            top: 56
          })

          Column() {
            Button({
              type: ButtonType.Capsule,
              stateEffect: true
            }) {
              Text('Other ways to sign in')
                .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
                .fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
                .fontWeight(FontWeight.Medium)
                .fontSize($r('sys.float.ohos_id_text_size_button1'))
                .focusable(true)
                .focusOnTouch(true)
                .textOverflow({ overflow: TextOverflow.Ellipsis })
                .maxLines(1)
                .padding({ left: 8, right: 8 })
            }
            .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
            .fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
            .fontWeight(FontWeight.Medium)
            .backgroundColor($r('sys.color.ohos_id_color_button_normal'))
            .focusable(true)
            .focusOnTouch(true)
            .constraintSize({ minHeight: 40 })
            .width('100%')
            .onClick(() => {
              hilog.info(this.domainId, this.logTag, 'click optionalLoginButton.');
            })
          }.margin({ top: 16 })
        }.width('100%')

        Row() {
          Row() {
            Checkbox({ name: 'privacyCheckbox', group: 'privacyCheckboxGroup' })
              .width(24)
              .height(24)
              .focusable(true)
              .focusOnTouch(true)
              .margin({ top: 0 })
              .onChange((value: boolean) => {
                if (value) {
                  this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.ACCEPTED);
                } else {
                  this.controller.setAgreementStatus(loginComponentManager.AgreementStatus.NOT_ACCEPTED);
                }
                hilog.info(0x0000, 'testTag', `agreementChecked: ${value}`);
              })
          }

          Row() {
            Text() {
              ForEach(this.privacyText, (item: loginComponentManager.PrivacyText) => {
                if (item?.type === loginComponentManager.TextType.PLAIN_TEXT && item?.text) {
                  Span(item?.text)
                    .fontColor($r('sys.color.ohos_id_color_text_secondary'))
                    .fontFamily($r('sys.string.ohos_id_text_font_family_regular'))
                    .fontWeight(FontWeight.Regular)
                    .fontSize($r('sys.float.ohos_id_text_size_body3'))
                } else if (item?.type === loginComponentManager.TextType.RICH_TEXT && item?.text) {
                  Span(item?.text)
                    .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
                    .fontFamily($r('sys.string.ohos_id_text_font_family_medium'))
                    .fontWeight(FontWeight.Medium)
                    .fontSize($r('sys.float.ohos_id_text_size_body3'))
                    .onClick(() => {
                      // The app needs to implement the agreement redirection logic based on item.tag.
                      hilog.info(0x0000, 'testTag', `click privacy text tag: ${item.tag}`);
                    })
                }
              }, (item: loginComponentManager.PrivacyText) => item.text.toString())
            }
            .width('100%')
          }
          .margin({ left: 12 })
          .layoutWeight(1)
          .constraintSize({ minHeight: 24 })
        }
        .alignItems(VerticalAlign.Top)
        .margin({
          top: 16,
          bottom: 16
        })
      }
      .justifyContent(FlexAlign.SpaceBetween)
      .constraintSize({ minHeight: '100%' })
      .margin({
        left: 16,
        right: 16
      })
    }
    .width('100%')
    .height('100%')
  }
}

export enum ErrorCode {
  // No HUAWEI ID has been signed in.
  ERROR_CODE_LOGIN_OUT = 1001502001,
  // Network error.
  ERROR_CODE_NETWORK_ERROR = 1001502005,
  // Internal error.
  ERROR_CODE_INTERNAL_ERROR = 1001502009,
  // Authorization canceled by the user.
  ERROR_CODE_USER_CANCEL = 1001502012,
  // System service exception.
  ERROR_CODE_SYSTEM_SERVICE = 12300001,
  // The user does not accept the agreements.
  ERROR_CODE_AGREEMENT_STATUS_NOT_ACCEPTED = 1005300001,
  // Repeated request.
  ERROR_CODE_REQUEST_REFUSE = 1001500002
}