HMS Core华为帐号注册用户量已达到10亿+,通过华为帐号可以一键登录应用,通过与华为帐号绑定,可以为应用快速引入新用户和登录。华为帐号开放遵循OAuth2.0以及OpenID Connect标准规范。
您需要:
在这个codelab中,您将使用已经创建好的Demo Project实现对华为帐号开放服务的API调用,通过Demo Project您可以体验到:
Android基础开发能力
集成HUAWEI HMS Core能力需要完成以下准备工作:
至此,已经为创建的应用开通了"帐号"服务。
dependencies {
implementation 'com.huawei.hms:hwid:{version}'
}
点击Sync Now同步工程。
Android Studio的代码库配置在Gradle 插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请根据您当前的Gradle 插件版本,选择对应的配置过程。
7.0以下版本 | 7.0版本 | 7.1及以上版本 |
7.0以下版本
a. 打开Android Studio项目级"build.gradle"文件。
b. 添加HUAWEI agcp插件以及Maven代码库。
buildscript {
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
// 增加agcp插件配置,推荐您使用最新版本的agcp插件。
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
allprojects {
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
}
7.0版本
a. 打开Android Studio项目级"build.gradle"文件。
b. 添加HUAWEI agcp插件以及Maven代码库。
buildscript {
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
...
// 增加agcp插件配置,推荐您使用最新版本的agcp插件。
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
c. 打开项目级"settings.gradle"文件,配置HMS Core SDK的Maven仓地址。
dependencyResolutionManagement {
...
repositories {
google()
jcenter()
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}
}
}
7.1及以上版本
a. 打开Android Studio项目级"build.gradle"文件。
b. 如果App中添加了"agconnect-services.json"文件则需要在"buildscript > dependencies"中增加agcp插件配置。
buildscript {
dependencies {
...
// 增加agcp插件配置,推荐您使用最新版本的agcp插件。
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
c. 打开项目级"settings.gradle"文件,配置HMS Core SDK的Maven仓地址。
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
// 配置HMS Core SDK的Maven仓地址。
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencyResolutionManagement {
...
repositories {
google()
mavenCentral()
// 配置HMS Core SDK的Maven仓地址。
maven { url 'https://developer.huawei.com/repo/' }
}
}
打开Android Studio工程的混淆配置文件proguard-rules.pro。
加入混淆配置。
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
"R.string.hms*",
"R.string.connect_server_fail_prompt_toast",
"R.string.getting_message_fail_prompt_toast",
"R.string.no_available_network_prompt_toast",
"R.string.third_app_*",
"R.string.upsdk_*",
"R.layout.hms*",
"R.layout.upsdk_*",
"R.drawable.upsdk*",
"R.color.upsdk*",
"R.dimen.upsdk*",
"R.style.upsdk*",
"R.string.agc*"
Account SDK需要获取网络状态权限和获取Wi-Fi状态权限。需要在Manifest文件中添加下面权限:
<!--check network permissions-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--check wifi state-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
帐号的交互接口主要涉及登录、静默登录、退出帐号、取消授权。本次codelab中您可以在Android Studio工程中创建一个布局页面,参照下图进行UI设计。
调用AccountAuthParamsHelper的setIdToken方法请求授权。
Java
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setIdToken().createParams();
Kotlin
val authParams : AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setIdToken().createParams()
AccountAuthService service = AccountAuthManager.getService(MainActivity.this, authParams);
Kotlin
val service : AccountAuthService = AccountAuthManager.getService(this@MainActivity, authParams)
startActivityForResult(service.getSignInIntent(), 8888);
Kotlin
startActivityForResult(service.signInIntent, 8888)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//授权登录结果处理,从AuthAccount中获取ID Token
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 8888) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
//登录成功,获取用户的帐号信息和ID Token
AuthAccount authAccount = authAccountTask.getResult();
Log.i(TAG, "idToken:" + authAccount.getIdToken());
} else {
//登录失败,不需要做处理,打点日志方便定位
Log.e(TAG, "sign in failed : " +((ApiException) authAccountTask.getException()).getStatusCode());
}
}
}
Kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
//授权登录结果处理,从AuthAccount中获取ID Token
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
//登录成功,获取用户的帐号信息和ID Token
val authAccount = authAccountTask.result
Log.i(TAG, "idToken:" + authAccount.idToken)
} else {
//登录失败,不需要做处理,打点日志方便定位
Log.e(TAG, "sign in failed : " + (authAccountTask.exception as ApiException).statusCode)
}
}
}
帐号还支持使用Authorization Code授权登录。适用于拥有server端的应用授权。
调用AccountAuthParamsHelper的 setAuthorizationCode方法请求授权。
Java
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams();
Kotlin
val authParams : AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams()
AccountAuthService service = AccountAuthManager.getService(MainActivity.this, authParams);
Kotlin
val service : AccountAuthService = AccountAuthManager.getService(this@MainActivity, authParams)
startActivityForResult(service.getSignInIntent(), 8888);
Kotlin
startActivityForResult(service.signInIntent, 8888)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
//授权登录结果处理,从AuthAccount中获取Authorization Code
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 8888) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
//登录成功,获取用户的帐号信息和Authorization Code
AuthAccount authAccount = authAccountTask.getResult();
Log.i(TAG, "serverAuthCode:" + authAccount.getAuthorizationCode());
} else {
//登录失败
Log.e(TAG, "sign in failed:" + ((ApiException) authAccountTask.getException()).getStatusCode());
}
}
}
Kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
//授权登录结果处理,从AuthAccount中获取Authorization Code
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
//登录成功,获取用户的帐号信息和Authorization Code
val authAccount = authAccountTask.result
Log.i(TAG, "serverAuthCode:" + authAccount.authorizationCode)
} else {
//登录失败
Log.e(TAG, "sign in failed:" + (authAccountTask.exception as ApiException).statusCode)
}
}
}
POST /oauth2/v3/token HTTP/1.1
Host: oauth-login.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&
client_id=12345&
client_secret=bKaZ0VE3EYrXaXCdCe3d2k9few&
refresh_token=CF2Mm03n0aos9iZZ8nIhfyDtoXy74CXeBi50gVVhMpB0IUzlv9ZwizEvTBhVoF820ZPim0JwNR9j2p1qgEQWnIVYZRlp4T6ezMgekUnsHBkvNev5rd2MdfQMLP
返回样例
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "CFyJ4J\/l6wuwcFqYOJG4maq2ca8RAV+g0i+mel6qCV5lvqH0PYtW0+BNwfHWg0AqMnW6ZdBvUgs7ijkxMFh1xVP\/B+vQXz3PWsivkKCuL78XtbLt7vs=",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjExOGRmMjU0YjgzNzE4OWQxYmMyYmU5NjUwYTgyMTEyYzAwZGY1YTQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI3ODI0NTY2Njc4OTgtc2M0MzE3Y2l0NGEwMjB0NzdrbGdsbWo1ZjA4YWtnMWIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI3ODI0NTY2Njc4OTgtN2NkNGJpYWRkaGVwNGc4cnZic2VlOGtwcDA5Zm1hNzIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDE3MTIxMzkwMzgwNDE2MDc0MTQiLCJlbWFpbCI6Inh1ZXpoZW5odWF0anVAc2luYS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwicGljdHVyZSI6Imh0dHBzOi8vbGg1Lmdvb2dsZXVzZXJjb250ZW50LmNvbS8tMm9lTTllT09zNTAvQUFBQUFBQUFBQUkvQUFBQUFBQUFBQkkvMVpOSC0xdmxxc3cvczk2LWMvcGhvdG8uanBnIiwiaWF0IjoxNTYxNDUxMTUyLCJleHAiOjE1NjE0NTQ3NTJ9.Eo9IHMkid596jvt1YYzNsRtDq9c9K9dbougkU41Noh7TXNiko86_RuWwHID6k1kDg398AwC3wwH-t2hLcUjgrXPNd9XYU96Jp4-UxdDszP6ywEJgvvBCyTHzsi2auvKt_MnfSrs3qOKfh7noJvXq8AY-Hi3vqSUks5kGqbZKVzCHhBDO3RD9Fs9YHsB6w0XVKZojPOBDaAT_TiijoChn-Q-e8NbSGUx52OgeH-Nw5lOj6JVb_7fb6ucWRzlhiQuzFjklevLVw2pjw1MxKbl1vfRp0X699uZBVjgl9hj1L7LSDObuPzLiXF7ojji5JKYC6zIwAtZQUZ_VUmSk01GDLQ",
"expires_in": 3600,
"scope": "openid profile email",
"token_type": "Bearer"
}
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).createParams();
Kotlin
val authParams : AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).createParams()
AccountAuthService service = AccountAuthManager.getService(MainActivity.this, authParams);
Kotlin
val service : AccountAuthService = AccountAuthManager.getService(this@MainActivity, authParams)
Task<AuthAccount> task = service.silentSignIn();
Kotlin
val task : Task<AuthAccount> = service.silentSignIn()
task.addOnSuccessListener(new OnSuccessListener<AuthAccount>() {
@Override
public void onSuccess(AuthAccount authAccount) {
//获取帐号信息
Log.i(TAG, "displayName:" + authAccount.getDisplayName());
//获取帐号类型,0表示华为帐号、1表示AppTouch帐号
Log.i(TAG, "accountFlag:" + authAccount.getAccountFlag());
}
});
Kotlin
task.addOnSuccessListener { authAccount ->
//获取帐号信息
Log.i(TAG, "displayName:" + authAccount.displayName)
//获取帐号类型,0表示华为帐号、1表示AppTouch帐号
Log.i(TAG, "accountFlag:" + authAccount.accountFlag);
}
如果授权失败,可能是用户之前未进行过登录授权,应用可自行确认是否需要调用AccountAuthService的getSignInIntent方法显式展示登录授权页面。
Java
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
//登录失败,您可以尝试使用getSignInIntent()方法显式登录
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
Log.i(TAG, "sign failed status:" + apiException.getStatusCode());
}
}
});
Kotlin
task.addOnFailureListener { e ->
//登录失败,您可以尝试使用getSignInIntent()方法显式登录
if (e is ApiException) {
Log.i(TAG, "sign failed status:" + e.statusCode)
}
}
//service为登录授权时使用getService方法生成的AccountAuthService实例
Task<Void> signOutTask = service.signOut();
Kotlin
//service为登录授权时使用getService方法生成的AccountAuthService实例
val signOutTask = service.signOut()
signOutTask.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
//完成退出后的处理
Log.i(TAG, "signOut complete");
}
});
Kotlin
signOutTask.addOnCompleteListener { it ->
//完成退出后的处理
Log.i(TAG, "signOut complete")
}
//service为登录授权时使用getService方法生成的AccountAuthService实例
service.cancelAuthorization().addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
//取消授权成功后的处理
Log.i(TAG, "onSuccess: ");
} else {
//异常处理
Exception exception = task.getException();
if (exception instanceof ApiException){
int statusCode = ((ApiException) exception).getStatusCode();
Log.i(TAG, "onFailure: " + statusCode);
}
}
}
});
Kotlin
//service为登录授权时使用getService方法生成的AccountAuthService实例
service.cancelAuthorization().addOnCompleteListener { task ->
if (task.isSuccessful) {
//取消授权成功后的处理
Log.i(TAG, "onSuccess: ")
} else {
//异常处理
val exception = task.exception
if (exception is ApiException) {
val statusCode = exception.statusCode
Log.i(TAG, "onFailure: $statusCode")
}
}
}
开发完成后,点击图标,运行Android Studio工程打包生成APK,并安装在测试手机上。运行界面如下图所示:
干得好,您已经成功完成了codelab并学到了:
帐号服务相关API介绍
您可以点击下方按钮下载源码。