[Huawei Developers] Berk Özyurt:
Hello everyone,

In this article, I will give information about Game Service, which offered by Huawei to developers, and explain how to use it in the your mobile game app with the MVVM structure.

What Is Game Service?

HMS Game Service is a kind of Huawei service offered to mobile developers that meets all the needs of a mobile game application. Owing to Game Service, you can easily create a leaderboard in the game, create events, prepare achievements and let the users for save their games. Since you do all these operations through a ready-made service, you can create your game project reliably with a short and organized code structure.

With HUAWEI Game Service, you will have access to a range of development capabilities, to help you develop your games more efficiently:

HUAWEI ID sign-in

Game addiction prevention

Floating window

Achievements

Events

Leaderboards

Saved games

Player statistics

Access to basic game information

Requirements

Android Studio 3.X or later

JDK 1.8 or later

SDK:

— minSdkVersion: 17

— targetSdkVersion: 29

— compileSdkVersion: 29

Test device:

Development Process

1. Integration

First, a developer account must be created and HMS Core must be integrated into the project to use HMS. You can access the article about that steps from Huawei offical pages.

2. Adding Dependencies

After HMS Core is integrated into the project and the Game Service is activated through the console, the required library should added to the build.gradle file in the app directory as follows.

dependencies {

implementation 'com.huawei.hms:base: 5.0.5.300'

implementation 'com.huawei.hms:hwid:4.0.1.300'

implementation 'com.huawei.hms:iap:5.0.1.300'

implementation 'com.huawei.hms:game: 5.0.4.302'

}

3. Create Application Class

An Application class is required to launch the Game Service when starting the application. Game Service is launched in this class and it is provided to start with the project. After the BaseApplication class is created, it must be defined in the Manifest file.

class BaseApplication : Application(){
companion object{
lateinit var instance: BaseApplication
private set
}

override fun onCreate() {
super.onCreate()

instance = this

HuaweiMobileServicesUtil.setApplication(this)

HwAds.init(this)
}
}

4. Create Login Page Design

After all of the permissions and libraries have been added to the project, you can start to coding with sign-in for develop a game. For this, I used Huawei Auth Service. Thanks to Auth Service, you can see all of the users on the console. Also Auth Service provides many kind of login method. (With Facebook, Twitter, Google, Email, Phone Number or Huawei ID) I will share a general screen design. And I will give an example of login with Huawei ID.

​

<androidx.constraintlayout.motion.widget.MotionLayout
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"
app:layoutDescription="@xml/motion_scene_splash"
android:id="@+id/id_09"
android:layout_height="match_parent">

<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/background"
android:alpha="0.7"
android:id="@+id/id_11"/>
<ImageView
android:id="@+id/imgView_logo"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="80dp"
android:scaleType="centerInside"
android:src="@drawable/vs_logo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/imgView_logo_rays"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="80dp"
android:scaleType="centerInside"
android:src="@drawable/vs_logo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/imgView_cloudLeft"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="16dp"
android:scaleType="centerInside"
android:src="@drawable/cloud"
android:translationX="-20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="#9E9E9E" />

<ImageView
android:id="@+id/imgView_cloudRight"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_marginTop="120dp"
android:scaleType="centerInside"
android:src="@drawable/cloud"
android:translationX="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="#607D8B" />

<LinearLayout
android:id="@+id/linlay_inputs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:alpha="1"
android:layout_marginLeft="30dp"
android:layout_marginEnd="30dp"
android:layout_marginRight="30dp"
android:gravity="center"
android:layout_marginTop="10dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgView_cloudRight">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/muli_regular"
android:text="Welcome Back"
android:textColor="#000000"
android:textSize="20sp"
android:id="@+id/id_12" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/muli_regular"
android:text="Sign in to continue"
android:textColor="#000000"
android:textSize="14sp"
android:id="@+id/id_13" />

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:background="@drawable/et_background"
android:drawableStart="@drawable/ic_baseline_email_24"
android:drawableLeft="@drawable/ic_baseline_email_24"
android:drawablePadding="16dp"
android:hint="Email"
android:inputType="textEmailAddress"
android:padding="16dp"
android:textSize="14sp"
android:textColor="#000000"
android:fontFamily="@font/muli_regular"
android:id="@+id/id_14"/>

<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@drawable/et_background"
android:drawableStart="@drawable/ic_baseline_lock_24"
android:drawableLeft="@drawable/ic_baseline_lock_24"
android:drawableEnd="@drawable/ic_baseline_visibility_24"
android:drawableRight="@drawable/ic_baseline_visibility_24"
android:drawablePadding="16dp"
android:hint="Password"
android:inputType="textPassword"
android:padding="16dp"
android:textSize="14sp"
android:textColor="#000000"
android:fontFamily="@font/muli_regular"
android:id="@+id/id_15"/>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:background="@drawable/button_one"
android:text="@string/signInButton"
android:textAllCaps="false"
android:fontFamily="@font/muli_regular"
android:textColor="#7E675E"
android:id="@+id/id_16"/>

</LinearLayout>

<TextView
android:id="@+id/tv_forgotPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="30dp"
android:alpha="1"
android:layout_marginRight="30dp"
android:text="Forgot Password?"
android:textColor="#7E675E"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/linlay_inputs" />

<ImageView
android:id="@+id/safads"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:src="@drawable/color_logo"
app:tint="#9E9E9E"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/linlay_inputs"
android:visibility="invisible"/>

</androidx.constraintlayout.motion.widget.MotionLayout>

Secondly, we have to logout. The purpose of this is to terminate if there is a session in the application that was open before. After logout, we have to create login method. And firstly, call the logout method in there. Finally we should add startActivityForResult method and override it on the View class.

LoginViewModel class should be as follows.

class LoginViewModel(private val context: Context): ViewModel(){

private lateinit var mClient: HuaweiIdAuthService

fun login(fragment: Fragment){
logout()

val huaweiIdAuthParamsHelper =HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
val scopeList: MutableList<Scope> = ArrayList()
scopeList.add(Scope(HwIDConstant.SCOPE.ACCOUNT_BASEPROFILE))
huaweiIdAuthParamsHelper.setScopeList(scopeList)
val authParams = huaweiIdAuthParamsHelper.setAccessToken().createParams()

mClient = HuaweiIdAuthManager.getService(context, authParams)
fragment.startActivityForResult(mClient.signInIntent, 1002)
}

fun logout(){
Log.i(Constants.LOGIN_VIEWMODEL_TAG, "In LogOut Fun.")
val auth = AGConnectAuth.getInstance()
auth.signOut()
}
}

5. Create LoginViewModel Class

LoginViewModel class will receive data from View class, processes data and send again to View class. So, all of the login operations will be done in this class.

Firstly, create a client from HuaweiIdAuthService object.

private lateinit var mClient: HuaweiIdAuthService

6. Create LoginViewModelFactory Class

Create a view model factory class and set context as parameter. This class should be return ViewModel class.

class LoginViewModelFactory(private val context: Context): ViewModelProvider.NewInstanceFactory(){
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return LoginViewModel(context) as T
}
}

7. Create LoginFragment

Firstly, ViewModel dependencies should be added on Xml file. We will use it as binding object. For this, open again your Xml file and add variable name as “viewmodel” and add type as your ViewModel class directory like that.

<data>

<variable

name="viewmodel"

type="com.xxx.xxx.viewmodel.LoginViewModel"/>

</data>

Turn back LoginFragment and add factory class, viewmodel class and binding.

private lateinit var binding: FragmentLoginBinding

private lateinit var viewModel: LoginViewModel

private lateinit var viewModelFactory: LoginViewModelFactory

Secondly, define these objects on the onCreateView method.

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

binding = DataBindingUtil.inflate(inflater, R.layout.activity_splash_login, container,false) as ActivitySplashLoginBinding
viewModelFactory =LoginViewModelFactory(requireContext() )
viewModel = ViewModelProviders.of(this, viewModelFactory).get(LoginViewModel::class.java)

return binding.root
}

Create a click listener for login, and call the login method from ViewModel class.

var gameLoginButton = binding.id16.findViewById<View>(R.id.id_16)
gameLoginButton.setOnClickListener {
showProgressDialog()
viewModel.login(this)
}

Finally, create onActivityResult method and check login results. If login is successful, you can see some user informations in there. (User name, ID, Country, Age etc.) Auth Service provide to you so many user info. You can use it all of the app.

override fun onActivityResult(
requestCode: Int,
resultCode: Int,
@Nullable data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1002) {
val signInHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data)
if (signInHuaweiIdTask.isSuccessful) {
val huaweiAccount = signInHuaweiIdTask.result
val accessToken = huaweiAccount.accessToken
Log.w(Constants.LOGIN_FRAGMENT_TAG, "accessToken: $accessToken")

val credential = HwIdAuthProvider.credentialWithToken(accessToken)
val provider_now = credential.provider
Log.w(Constants.LOGIN_FRAGMENT_TAG, "provider_now: $provider_now")

AGConnectAuth.getInstance().signIn(credential)
.addOnSuccessListener { signInResult ->
val user = AGConnectAuth.getInstance().currentUser
Log.w(Constants.LOGIN_FRAGMENT_TAG, "Login Success. User Display Name : " + user.displayName)
userName = user.displayName
//Start another fragment here.
(activity as MainActivity?)!!.setSelectedTab(Constants.TAB_LOGIN,Constants.TAB_HOME,false)

dismisProgressDialog()

}.addOnFailureListener { e: Exception ->
Toast.makeText(context, R.string.authenticationError, Toast.LENGTH_SHORT).show()
Log.w(Constants.LOGIN_FRAGMENT_TAG, "sign in for agc failed: " + e.message)
dismisProgressDialog()
}
} else {
Toast.makeText(context, R.string.sıgnInError, Toast.LENGTH_SHORT).show()
Log.e(Constants.LOGIN_FRAGMENT_TAG,"sign in failed : " + (signInHuaweiIdTask.exception as ApiException).statusCode)

dismisProgressDialog()
}
}
}

Result

Thanks to this article, you can create login operations on your game app. We’ve used Auth Service. Because Auth Service provides so many user info to developers. And you can all of the users on the developer console.

In the next article, I will explain Achievements and give an example. Please follow second article for develop your game app with clean architecture.