In accordance with the latest notice issued by National Press and Publication Administration, all online game providers in the Chinese mainland should integrate the identity verification system for the game addiction prevention function, offer online game services to minors only from 20:00 to 21:00 on Fridays, weekends, and legal holidays, and set an upper limit on the payment and top-up amounts for minors.
Huawei provides a complete set of control logics for you to easily implement the game addiction prevention function. This codelab will show you a hands-on example of how to sign in to a game using Account Kit, and efficiently build the game addiction prevention function for the game.
In this codelab, you will create a simple Android game. The game will:
In this codelab, you will learn how to:
To integrate HMS Core capabilities, you must complete the following preparations:
The procedure for configuring the Maven repository address in Android Studio is different for Gradle plugin earlier than 7.0, Gradle plugin 7.0, and Gradle plugin 7.1 or later. Click a relevant link below to find the configuration procedure for the specific Gradle plugin version.
Gradle plugin earlier than 7.0 | Gradle plugin 7.0 | Gradle plugin 7.1 or later |
allprojects {
repositories {
google()
jcenter()
// Configure the following address:
maven {url 'https://developer.huawei.com/repo/'}
}
}
buildscript {
repositories {
google()
jcenter()
// Configure the following address:
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
// Add the AppGallery Connect plugin. You are advised to use the latest plugin version.
classpath 'com.huawei.agconnect:agcp:1.6.3.300'
}
}
buildscript {
repositories {
google()
jcenter()
// Configure the following address:
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
// Add the AppGallery Connect plugin. You are advised to use the latest plugin version.
classpath 'com.huawei.agconnect:agcp:1.6.3.300'
}
}
dependencyResolutionManagement {
...
repositories {
google()
jcenter()
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
}
}
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
// Add the AppGallery Connect plugin. You are advised to use the latest plugin version.
classpath 'com.huawei.agconnect:agcp:1.6.3.300'
}
}
c) Open the project-level settings.gradle file and configure the Maven repository address for the HMS Core SDK.
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
// Configure the Maven repository address for the HMS Core SDK.
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencyResolutionManagement {
...
repositories {
google()
mavenCentral()
// Configure the Maven repository address for the HMS Core SDK.
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencies {
implementation 'com.huawei.hms:hwid:{version}'
implementation 'com.huawei.hms:game:{version}'
}
apply plugin: 'com.huawei.agconnect'
Method 2: Add the plugin configuration in the plugins block.
plugins {
id 'com.android.application'
// Add the following configuration.
id 'com.huawei.agconnect'
}
Before compiling your app, configure the obfuscation scripts as follows:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-keep class com.huawei.gamebox.plugin.gameservice.**{*;}
-keep interface com.huawei.hms.analytics.type.HAEventType{*;}
-keep interface com.huawei.hms.analytics.type.HAParamType{*;}
-keep class com.huawei.hms.analytics.HiAnalyticsInstance{*;}
-keep class com.huawei.hms.analytics.HiAnalyticsInstance{*;}
-keep class com.huawei.hms.analytics.HiAnalytics{*;}
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/hms_download_progress,@drawable/screen_off,@layout/upsdk*,@drawable/c_buoycircle*,@drawable/hms_game*,@layout/c_buoycircle*,@layout/hms_game*,@strings/hms_game*,@strings/c_buoycircle*"
tools:shrinkMode="strict" />
In this codelab, you can create the following layout page, with three buttons required: Init for calling the initialization API, SignIn for calling the sign-in API, and GetGamePlayer for calling the API for obtaining player information.
<!--Layout code-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/init_btn"
android:layout_width="match_parent"
android:layout_height="@dimen/btn_height"
android:background="@color/btn_background"
android:gravity="center"
android:text="@string/init_text"
android:textColor="@color/text_color"
android:textSize="@dimen/button_size"/>
<TextView
android:id="@+id/login_btn"
android:layout_width="match_parent"
android:layout_height="@dimen/btn_height"
android:background="@color/btn_background"
android:layout_marginTop="@dimen/margin_top"
android:gravity="center"
android:text="@string/login_text"
android:textColor="@color/text_color"
android:textSize="@dimen/button_size" />
<TextView
android:id="@+id/player1_btn"
android:layout_width="match_parent"
android:layout_height="@dimen/btn_height"
android:background="@color/btn_background"
android:gravity="center"
android:layout_marginTop="@dimen/margin_top"
android:text="@string/game_player"
android:textColor="@color/text_color"
android:textSize="@dimen/button_size" />
</LinearLayout>
If you have requested the identity verification system, and obtained the game registration identifier (bizID), configure the game registration identifier. in AppGallery Connect. Huawei will automatically connect the system and enable the forcible identity verification function.
The code is as follows:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}
}
The code is as follows:
public void init() {
AccountAuthParams params = AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME;
JosAppsClient appsClient = JosApps.getJosAppsClient(this);
// Set the anti-addiction prompt context, this line must be added
// Set the game addiction prevention message context.
ResourceLoaderUtil.setmContext(this);
Task<Void> initTask = appsClient.init(new AppParams(params, new AntiAddictionCallback() {
@Override
public void onExit() {
// Implement the game addiction prevention function, such as saving the game and invoking the account exit interface.
// Implement the game addiction prevention function in this method, such as saving game progress or calling the sign-out API.
showLog("onExit");
}
}));
initTask.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
showLog("init success");
playersClient = Games.getPlayersClient(MainActivity.this);
// The login interface can be invoked only after the init is successful. Otherwise, error code 7018 is displayed.
// Call the sign-in API after successful initialization. Otherwise, the res**7018**code 7018 is returned.
// signIn();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
showLog("init failed, " + e.getMessage());
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
// Error code 7401 indicates that the user did not agree to Huawei joint operations privacy agreement
// Res**7401**code 7401 indicates that the user does not agree to Huawei's joint operations privacy agreement.
if (statusCode == JosStatusCodes.JOS_PRIVACY_PROTOCOL_REJECTED) {
showLog("has reject the protocol");
// You can exit the game or re-call the init interface.
// Exit the game or re-call the initialization API.
}
// Handle other error codes.
// Process other result codes.
}
}
});
}
/**
* Log output
* Log output
*/
public void showLog(String logLine) {
StringBuffer sbLog = new StringBuffer();
DateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:SS", Locale.ENGLISH);
String time = format.format(new Date());
sbLog.append(time).append(":").append(logLine);
Log.i(TAG, sbLog.toString());
}
/**
* Call the sign-in API first, and then call getCurrentPlayer or getGamePlayer to obtain player information.
* 1. Call the silent sign-in API. If a player has authorized your game and signed in, the authorization or sign-in screen will not display.
* 2.If the silent sign-in fails, call the sign-in API in the callback listener to display the authorization screen for players to sign in.
* The sign-in result will be returned in the onActivityResult callback. After that, call the API to obtain player information.
*/
public void signIn() {
Task<AuthAccount> authAccountTask = AccountAuthManager.getService(this, getHuaweiIdParams()).silentSignIn();
authAccountTask.addOnSuccessListener(
authAccount -> {
Toast.makeText(MainActivity.this, "signIn success", Toast.LENGTH_LONG).show();
showLog("signIn success");
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
Toast.makeText(MainActivity.this, "signIn failed:" + apiException.getStatusCode(), Toast.LENGTH_LONG).show();
showLog("signIn failed:" + apiException.getStatusCode());
signInNewWay();
}
}
});
}
/**
* Obtain the Intent object of the HUAWEI ID sign-in authorization screen. The page can be displayed through startActivityForResult(Intent, int).
*/
public void signInNewWay() {
Intent intent = AccountAuthManager.getService(MainActivity.this, getHuaweiIdParams()).getSignInIntent();
startActivityForResult(intent, SIGN_IN_INTENT);
}
public AccountAuthParams getHuaweiIdParams() {
return new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME).createParams();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SIGN_IN_INTENT) {
if (null == data) {
showLog("signIn intent is null");
return;
}
String jsonSignInResult = data.getStringExtra("HUAWEIID_SIGNIN_RESULT");
if (TextUtils.isEmpty(jsonSignInResult)) {
showLog("signIn result is empty");
return;
}
try {
HuaweiIdAuthResult signInResult = new HuaweiIdAuthResult().fromJson(jsonSignInResult);
if (0 == signInResult.getStatus().getStatusCode()) {
showLog("signIn success");
} else {
showLog("signIn failed: " + signInResult.getStatus().getStatusCode());
}
} catch (JSONException var7) {
showLog("Failed to convert json from signInResult.");
}
}
}
Call PlayersClient.getGamePlayer() to obtain player information after successful sign-in.
/**
* Obtains user information about gamers.
* Obtain the player information.
*/
public void getGamePlayer() {
playersClient = Games.getPlayersClient(this);
Task<Player> playerTask = playersClient.getGamePlayer();
playerTask.addOnSuccessListener(new OnSuccessListener<Player>() {
@Override
public void onSuccess(Player player) {
showLog("getPlayerInfo Success");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Failed to obtain the player information.
if (e instanceof ApiException) {
showLog("getPlayerInfo failed, status: " + ((ApiException) e).getStatusCode());
if (7400 == ((ApiException) e).getStatusCode() || 7018 == ((ApiException) e).getStatusCode()) {
// error code 7400 indicates that the user has not agreed to the joint operations privacy agreement
// error code 7018 indicates that the init API is not called.
// 7400 indicates that the user has not signed the joint operations agreement. You need to continue to call the init API.
// 7018 indicates that initialization fails. You need to continue to call the init API.
init();
}else if (GamesStatusCodes.GAME_STATE_NETWORK_ERROR == ((ApiException) e).getStatusCode()) {
//Error code 7002 indicates that the network is abnormal. You can prompt the player to check the network.
// 7002 indicates that a network exception occurs. You can prompt players to check their network connection.
showLog( "Network error");
}
}
}
});
}
Well done. You have successfully completed this codelab and learned how to:
For more information, please refer to the following links: