[Huawei Developers] Freemind R:
More information like this, you can visit HUAWEI Developer Forum​

Original article link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201328115676930048&fid=0101187876626530001

Introduction

In this article I want to show how we can work with Achievements using Game Service, first of all what is an achievement?

Achievements are a great way to increase player engagement in our game and give them greater incentives to continue playing. An achievement can represent a player's achievements (for example, number of players defeated or missions completed) or the skills the player has acquired. We can periodically add achievements to keep the game fresh and encourage players to keep participating. An achievement can contain the following basic attributes:

ID: a unique string generated by AppGallery Connect to identify an achievement.

Name: a short name for the achievement that you define during the achievement setup.

Description: a concise description of the achievement.

Icon: displayed after getting an achievement.

Steps: Achievements can be designated as standard or incremental. An incremental achievement involves a player completing several steps to unlock the achievement. This predefined number of steps is known as the number of achievement steps.

List order: the order in which the current achievement appears among all achievements. It is designated during the achievement setup.

Status: An achievement can be in one of three different states in a game.

Hidden: A hidden achievement means that the details about the achievement are hidden from the player.

Revealed: A revealed achievement means that the player knows about the achievement, but has not earned it yet.

Unlocked: An achievement unlocked means that the player has successfully obtained the achievement.

The HMS Core SDK allow us to unlock an achievement offline. When a game comes back online, it syncs with Huawei's game server to update the achievement's unlocked status.S

Steps

1. How do I set up my Game information in App Gallery Connect?

2. How do I integrate the HMS Core sdk into my project?

3. Create MyApplication class

4. Create Login Activity

5. Create Achievement Adapter

6. Create Game Login Activity

How do I set up my Game information in App Gallery Connect?

To configure your Game in App gallery Connect, you must first create an App with the Game type, generate your signature and configure it on the platform. If you have doubts regarding how to generate the certificate, go to this link and everything will be clearer.

https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#1

How do I integrate the HMS Core sdk into my project?

At first this step seems complex but in reality it is not so complex, because there are really a few steps that we must follow in order to integrate the HMS Core SDK.

Add the necessary dependencies in case of Game Service we require

dependencies {
implementation 'com.huawei.hms:hwid:{version}'
implementation 'com.huawei.hms:iap:{version}'
implementation 'com.huawei.hms:game:{version}'
}

Add the required plugin

apply plugin: 'com.huawei.agconnect'

Let's configure the obfuscation scripts

Before building the APK it is good to configure these scripts to prevent the SDK from being obfuscated since if this happens there may be the possibility that HMS Core will not work correctly. To achieve this we must add the following code to our proguard-rules.pro file

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.HiAnalyticsTools{
public static void enableLog();
public static void enableLog(int);
}
-keep class com.huawei.hms.analytics.HiAnalyticsInstance{*;}
-keep class com.huawei.hms.analytics.HiAnalytics{*;}

Remember to add the signingConfigs on the build.gradle(app)

signingConfigs {
release {
storeFile file("your.jks")
keyAlias 'yourname'
keyPassword 'yourpass'
storePassword 'yourpass'
v1SigningEnabled true
v2SigningEnabled true
}
}

Set up your build Types

buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug{
signingConfig signingConfigs.release
debuggable true
}
}

Create MyApplication class

Let’s create the Application Activity with this class we will be able to set the instance of the application.

class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
HuaweiMobileServicesUtil.setApplication(this);
}
}

Create Login Activity

We are going to create an activity to provide the user an interface login with a Huawei ID our Goal is to create a screen like this one

You can design you own UI but if you want to use mine just copy the code

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"
tools:context=".LoginActivity">

android:id="@+id/code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />

android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:text="Authorization Code"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Let’s start of Login Creation

private val AUTH_CODE=100
private val AUTH_TOKEN=200
private val TAG="LoginActivity"
val scopes= listOf(Scope("email"))

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
code.setOnClickListener(this)
}

override fun onClick(v: View?) {
when(v?.id){
R.id.code ->{
val authParams = HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME)
.setAuthorizationCode()
.setScopeList(scopes)
.createParams()
val service = HuaweiIdAuthManager.getService(this, authParams)
startActivityForResult(service.getSignInIntent(), AUTH_CODE)
}

else -> {}
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when(requestCode){
AUTH_CODE ->{
val authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data)
if (authHuaweiIdTask.isSuccessful) {
//The sign-in is successful, and the user's HUAWEI ID information and authorization code are obtained.
val huaweiAccount = authHuaweiIdTask.result
Log.e(TAG,"Huawei Id ${huaweiAccount.displayName} ${huaweiAccount.avatarUriString} ${huaweiAccount.email}")
Log.e(TAG, "Authorization code:" + huaweiAccount.authorizationCode)
//sendCredentialToServer(huaweiAccount)
jump(huaweiAccount)
} else {
// The sign-in failed.
Log.e(TAG, "sign in failed : " + (authHuaweiIdTask.exception as ApiException).statusCode)
}
}

AUTH_TOKEN ->{
val authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data)
if (authHuaweiIdTask.isSuccessful) {
// The sign-in is successful, and the user's HUAWEI ID information and ID token are obtained.
val huaweiAccount = authHuaweiIdTask.result
Log.e(TAG,"Huawei Id ${huaweiAccount.displayName} ${huaweiAccount.avatarUriString} ${huaweiAccount.email}")
Log.i(TAG, "idToken:" + huaweiAccount.idToken)
Log.i(TAG, "image" + huaweiAccount.avatarUri)
jump(huaweiAccount)
} else {
// The sign-in failed. No processing is required. Logs are recorded to facilitate fault locating.
Log.e(TAG, "sign in failed : " + (authHuaweiIdTask.exception as ApiException).statusCode)
}
}
}
}

Create Achievement Adapter

Now we have to create our adapter to populate the recycler View in this case i will use the name Achievment Adapter

class AchievmentAdapter(val list:ArrayList, val listener:MyVH.OnItemClickListener): RecyclerView.Adapter() {

class MyVH(private val view: View, val listener: OnItemClickListener): RecyclerView.ViewHolder(view),View.OnClickListener {
public fun init(achievement: Achievement){
view.achName.text=achievement.displayName
view.achDesc.text=achievement.descInfo
view.achState.text=when(achievement.state){
3->"Ulocked"
else ->"Locked"
}
view.setOnClickListener(this)

}
public interface OnItemClickListener{
fun onAchievmentClicked(position:Int)
}

override fun onClick(v: View?) {
listener.onAchievmentClicked(adapterPosition)
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyVH {
val view= LayoutInflater.from(parent.context)
.inflate(R.layout.achievment, parent, false)
return MyVH(view,listener)
}

override fun getItemCount(): Int {
return list.size
}

override fun onBindViewHolder(holder: MyVH, position: Int) {
holder.init(list[position])
}
}

As well we need to create the layout for our recycler Row

xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical"
android:elevation="10dp"
android:background="@color/colorPrimary"
>

android:id="@+id/achName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="@color/white"
/>

android:id="@+id/achDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="@color/white"/>

android:id="@+id/achState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="@color/white"/>

Create Game Activity

This is the most important class because in here we will retrive the information from the service

We need to init the service

private fun init() {
val appsClient = JosApps.getJosAppsClient(this)
appsClient.init()
Log.i("Application", "init success")
}

I have created a method with to get the Achievments in this method we will have the listener which will be in charge to display the information.

private fun getAchievments() {
val task =
client.getAchievementList(true)
task.addOnSuccessListener(OnSuccessListener { data ->
if (data == null) {
Log.w("Achievement", "achievement list is null")
return@OnSuccessListener
}

adapter.list.clear()
adapter.list.addAll(data)
adapter.notifyDataSetChanged()
swipe.isRefreshing=false
for(entry in data){
Log.e("Achievment",entry.id)
}
}).addOnFailureListener { e ->
if (e is ApiException) {
val result = "rtnCode:" +
(e as ApiException).statusCode
Log.e("Achievement", result)
}
}
}

now we have to call the methods in the onCreate() Method

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_game)
swipe.setOnRefreshListener(this)
swipe.isRefreshing=true
init()
currentPlayerInfo()
client = Games.getAchievementsClient(this)
getAchievments()
adapter= AchievmentAdapter(ArrayList(),this)
recycler.layoutManager=LinearLayoutManager(this)
recycler.adapter=adapter
}

dont forget to declare our variables

lateinit var client: AchievementsClient
lateinit var adapter: AchievmentAdapter

Wait!!! Do not forget to add the curreontPlayerInfo() which will help us to retrieve HUAWEI ID Information of our User

private fun currentPlayerInfo() {
val playersClient = Games.getPlayersClient(this@GameActivity)
val playerTask = playersClient.currentPlayer
playerTask.addOnSuccessListener { player -> // The request is successful, and the player information is obtained.
name.text=player.displayName
id.text=player.playerId
level.text=player.level.toString()
Picasso.get().load(player.iconImageUri).into(avatarImg);

}.addOnFailureListener { e -> // The player information fails to be obtained.
if (e is ApiException) {
Log.e(TAG, "getPlayerInfo failed, status: " + e.statusCode)
}
}
}

Conclusion

Very good! With this example we have used the the Account kit and Game service Kit to obtain the achievements of a user, I hope this article will be of help to you when developing your video games. Here you have the repo for further information.

https://github.com/ADX2099/Achievment