This article will introduce Huawei's game services and explain how to use the game services to implement account login and authentication functions in mobile game apps based on MVVM.
What is a game service?
Game service is a service provided by Huawei for mobile developers to meet various mobile game development needs. Using game services, you can easily implement leaderboards, events, achievements, archives and other functions in the game. The game service effectively simplifies the game development process, allowing you to create game projects with a short and orderly code structure.
Huawei Game Services provides you with the following development capabilities to help you develop games more efficiently:
· Account login
· Game anti-addiction
· Buoy
· Achievements
· Event
· Ranking
· Game Archive
· Player statistics
· Acquisition of basic game information
software and hardware requirements
· Android Studio 3.X and above
· JDK 1.8 and above
· Your application should meet the following conditions:
— minSdkVersion: 17
— targetSdkVersion: 29
— compileSdkVersion: 29
development process
1. Integrated
First, you must first register as a Huawei developer and integrate HMS Core into the project. You can access the material about this step from the link below.
https://medium.com/huawei-developers/android-integrating-your-apps-with-huawei-hms-core-1f1e2a090e98
2. Add dependency
After integrating HMS Core into the project and starting the game service in the AGC console, add the required libraries to the build.gradle file in the app directory, as shown below:
dependencies {
implementation 'com.huawei.agconnect:agconnect-auth:1.5.1.300'
implementation 'com.huawei.hms:base: 5.0.5.300'
implementation 'com.huawei.hms:hwid: 5.2.0.300'
implementation 'com.huawei.hms:iap:5.0.1.300'
implementation 'com.huawei.hms:game: 5.0.4.302'
}
3. Create Application class
When your application starts, the game service is triggered by the Application class. The game service is started in this class, and this class is started together with the project. After creating the BaseApplication class, you need to define it 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. Design the login page
After all permissions and libraries are added to the project, you can start developing a login page for your game. At this time, the Huawei certification service is used. The authentication service allows you to view all users of the game on the console. In addition, the authentication service also provides multiple login methods: including Facebook, Twitter, Google, email, phone number or Huawei ID. I will share a common login page design. The following is an example of logging in with Huawei ID.
You can view the documentation of the certification service at the following link:
<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>
5. Create LoginViewModel class
The LoginViewModel class will receive and process data from the View class and send the processed data to the View class. All login operations will be completed in the LoginViewModel class.
First, create a client in the HuaweiIdAuthService object.
private lateinit var mClient: HuaweiIdAuthService
The next step is to log out of the development account. The purpose of this is to end the open session in the app. After logging out, we need to create a login method. First, call the logout method. Then add the startActivityForResult method and override it in the View class.
The LoginViewModel class is 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()
}
}
6. Create the LoginViewModelFactory class
Create the LoginViewModelFactory class and set the context as a parameter. This class will return the 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
Add ViewModel dependency on the XML file and use it as a binding object. You need to open the XML file again, add the variable "viewmodel", and add type as the ViewModel class directory.
<data>
<variable
name="viewmodel"
type="com.xxx.xxx.viewmodel.LoginViewModel"/>
</data>
Return to LoginFragment and add factory class, viewmodel class, and bind.
private lateinit var binding: FragmentLoginBinding
private lateinit var viewModel: LoginViewModel
private lateinit var viewModelFactory: LoginViewModelFactory
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 login button click event listener, and call the login method in the ViewModel class.
var gameLoginButton = binding.id16.findViewById<View>(R.id.id_16)
gameLoginButton.setOnClickListener {
showProgressDialog()
viewModel.login(this)
}
Finally, create the onActivityResult method to view the login result. If the login is successful, you can see some user information, such as user name, ID, country/region, age, etc. The authentication service provides a wealth of user information, and you can use the authentication service in 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()
}
}
}
in conclusion
Now you can implement the login function on the game App. You can also choose to use the authentication service like me, because it can provide you with a variety of user information, and you can view all users in the AGC console.
In the next article, I will introduce "Building Achievements" (custom configuration achievements for gamers (up to 200), increase players' freshness and sense of accomplishment, and encourage players to continue participating) and provide an example. Please pay attention to the second article to develop your game application with a concise structure.
reference
Certification Service Document
For more details about HMS Core, please refer to:
Developer Alliance official website
Obtain the development guide document
To participate in the developer discussion, please go to CSDN community or Reddit community
To download demo and sample code, please go to Github or Gitee
To solve integration problems, please go to Stack Overflow
Original link: https://developer.huawei.com/consumer/cn/forum/topic/0201550888629240197?fid=18
Original Author: Pepper
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。