集成Google登录并获取个人性别等信息
前言:
最近海外产品更新需求要求获取到Google登录的用户的性别信息,于是开始了新一轮的踩坑之旅。不得不说在集成Firebase或者其他Google的SDK的时候真的是各种坑,避之不及。
0、准备工作
- 合适的网络
我们接下来的工作必须要能访问到Google,所以也请大家务必正确选择合适的网络。如果这一步解决不了的话下文可以不用浪费时间阅读了。 - Google账号
因为使用Google登录,所以需要你自己注册一个Google的账号,方便测试。貌似目前国内注册Google账号有点麻烦,所以请大家自行解决。地址:https://myaccount.google.com/ - Firebase账号
Firebase是包含了很多工具的一个平台,我们需要注册一个Firebase的账号,并创建项目,使用其中的三方登录功能,包括Google登录。控制台地址:https://console.firebase.google.com/ - Google Cloud Platform账号
Google Cloud Platform 是另一个Google的开发平台,我们需要在这其中开启获取用户信息的相关权限,然后完成获取用户性别的功能。控制台地址 :https://console.cloud.google.com
1、使用AS创建项目
我们使用AS直接创建演示工程:SignInDemo,为了下文方便我们直接生成release签名文件等。针对该项目我们生成了key.jks类型的签名文件,并放在了项目的根目录下。
然后在应用级的build.gradle的android节点中配置无论debug还是release统一使用release的签名配置,如下。
signingConfigs {
release {
storeFile rootProject.file('key.jks')
storePassword 'signindemo'
keyAlias 'signindemo'
keyPassword 'signindemo'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.release
}
}
OK,一切就绪后我们需要获取下调试签名整数 SHA-1 的值,因为我们使用Google登录的话必须使用该值,获取方式如下,在AS中打开Terminal:输入以下指令
keytool -list -v -alias 生成key时填写的Alias名 -keystore 生成key时填写的key名称
,所以我们这里输入keytool -list -v -alias signindemo -keystore key.jks
,然后AS会向我们索要密码,输入设置的密码即可,如下所示:
所以我们这里拿到了该项目的SHA1的值为:A3:59:F7:D6:80:5E:B2:9E:F3:2E:BA:81:8C:F0:73:95:25:73:13:93,存好下一步需要使用。
2、在Firebase创建项目
在Firebase控制台新建项目SignInDemo,第二步会让你设置Google Analytics,为了不必要的设置我们取消勾选该选项,直接创建项目。
项目创建完成后,打开该项目会直接提示我们“将Firebase添加至您的应用”,我们选择安卓平台,
2.1、填写信息
第一步控制台如下:
- 第一个是我们AS中创建的项目的applicationId
- 第二个应用别名可选填写
- 第三个要填写的SHA1的值就是我们上一步获取到的值
2.2、下载配置文件
第一步填写完毕后,第二步会要求你下载一个json文件,我们将其下载下来,并放到项目的app目录下,如下。
2.3、配置FirebaseSDK
接下来我们需要配置gradle文件来添加相关插件及依赖等:
首先在项目级的build.gradle文件中添加以下依赖:
dependencies {
...
classpath 'com.google.gms:google-services:4.3.4'
}
然后在应用级的build.gradle文件中添加插件:
apply plugin: 'com.google.gms.google-services'
然后添加依赖:
implementation platform('com.google.firebase:firebase-bom:26.3.0')
OK,到这里Firebase的基本集成已经完成了。
3、使用Firebase的Authentication功能,集成Google登录SDK
我们在Firebase控制台中点击左侧的 Authentication 菜单,然后点击开始按钮,打开如下页面:
默认Google的选项是停用的,我们点击编辑按钮填写相关信息,然后启用该选项。
接下来根据参考文档,我们现在需要集成Google登录的SDK等。
其实前面大部分工作都已经做完了,我们只需要添加Google的依赖即可,在应用级的build.gradle文件中添加依赖如下:
implementation 'com.google.firebase:firebase-auth'
implementation 'com.google.android.gms:play-services-auth:19.0.0'
构建项目,下载依赖,OK,集成完毕。
4、实现Google登录功能
经过上述各种配置我们已经具备了实现Google登录的功能了,接下来直接上代码:
private void googleSignIn() {
GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail() //可以获取到邮箱信息【这一步还挺有必要,不光可以获取到邮箱信息,还会影响到下面获取性别信息】
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, googleSignInOptions);
Intent intent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(intent, CODE_SIGN_IN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CODE_SIGN_IN && resultCode != 0) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
}
}
我们通过点击登录按钮,调用googleSignIn()函数,最后通过startActivityForResult(intent, CODE_SIGN_IN)函数,得到onActivityResult回调,该回调中的Task task就包含了我们的账户信息,简单处理下并输出到屏幕上。
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
String info = "获取登录信息成功:" + "\n" +
"ID:" + account.getId() + "\n" +
"photoUrl:" + account.getPhotoUrl() + "\n" +
"displayName:" + account.getDisplayName() + "\n" +
"familyName:" + account.getFamilyName() + "\n" +
"givenName:" + account.getGivenName();
((TextView) findViewById(R.id.tvLoginInfo)).setText(info);
} catch (ApiException e) {
((TextView) findViewById(R.id.tvLoginInfo)).setText("获取登录信息失败:" + e.getMessage());
}
}
然后当你点击Google登录按钮的时候,预览效果如下所示,会弹出你当前手机上的所有绑定的Google账号选择框,我们选择使用第二个DragonV的账号演示:
如果弹出权限窗口记得给定权限,选定DragonV后,我们可以看到当前页面的获取到信息如下:
基础的昵称、头像信息都可以拿到,ID和IdToken我们可以上传到后台服务器进行处理。
5、在Google Cloud Platform配置获取用户性别相关权限
5.1、启用Google People API服务
获取用户的性别这些属于用户的隐私信息,所以相比较来说需要申请各种权限,我们需要登陆Google Cloud Platform控制台,你在Firebase控制台创建的项目SignInDemo也会显示在Google Cloud Platform中,我们选中该项目,然后点击左侧的API和服务菜单:
进入到 API和服务 菜单后:我们点击 启用API和服务,然后搜索People,然后选中Google People API,进入新的页面后点击启用,这个过程可能需要一段时间,我们稍等片刻即可:
5.2、配置OAuth同意屏幕
开启People API服务后我们需要配置下OAuth同意屏幕,这个的意思就是说我需要声明下我们需要哪些权限,例如这里我们就需要获取下用户的性别,那么这个“OAuth同意屏幕”就是展示一个弹窗,标明了当前我们的应用需要获取用户的性别信息,后文有示例图。
我们在左侧菜单选中 OAuth同意屏幕,然后在菜单右侧,点击修改应用:
在修改页中,第一步默认即可,最后需要一个联系邮箱;第二步我们需要添加获取性别的权限内容,如下,我们点击 添加或移除范围,然后在右侧的弹出框中选择 性别 相关的信息,如下(如果您有其他范围需要选取,根据需要选择即可):
6、集成People API
经过上述的各种权限申请等,我们现在可以集成获取用户信息相关的SDK了,这一步就比较简单了,直接在应用的build.gradle中添加如下依赖(注意版本号对应):
implementation 'com.google.api-client:google-api-client:1.31.0'
implementation 'com.google.api-client:google-api-client-android:1.31.0'
implementation 'com.google.apis:google-api-services-people:v1-rev20201117-1.31.0'
构建,下载相关依赖即可。
注意:当你集成了这些依赖后,编译可能会报错More than one file was found with OS independent path 'META-INF/DEPENDENCIES'.
,因为工程生成了多个META-INF/DEPENDENCIES文件,所以我们先直接在应用的build.gradle文件的android节点下配置如下代码,排除其他文件:
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
}
7、实现获取用户性别功能
首先你的Google账户需要公开你自己的性别信息,请自行登录Google账户设置公开。
在获取用户的性别信息前也需要我们手动判断是否有相应的权限,当然这一切都要建立在我们已经Google登录成功了:
if (GoogleSignIn.hasPermissions(mGoogleSignInAccount, new Scope(CONTACTS_SCOPE))) {
requestAccountInfo();
} else {
GoogleSignIn.requestPermissions(MainActivity.this, CODE_PERMISSION, mGoogleSignInAccount, new Scope(CONTACTS_SCOPE));
}
注意,CONTACTS_SCOPE就是private static final String CONTACTS_SCOPE = "https://www.googleapis.com/auth/user.gender.read";
,也就是我们之前申请的性别的权限范围,请求权限结果还是会直接回调到onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
获取权限的这一步,会弹出如下弹窗,这就是我们之前配置的“OAuth同意屏幕”:
当用户点击允许后,我们就可以直接调用代码申请用户的性别信息了,但是不可以在主线程处理,以下实例代码直接开启线程进行了请求(仅供示例参考),如下所示:
private void requestAccountInfo(GoogleSignInAccount account) {
new Thread(new Runnable() {
@Override
public void run() {
try {
GoogleAccountCredential googleAccountCredential = GoogleAccountCredential
.usingOAuth2(MainActivity.this, Collections.singleton(CONTACTS_SCOPE))
.setSelectedAccount(account.getAccount());
PeopleService peopleService = new PeopleService
.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), googleAccountCredential)
.build();
Person person = peopleService.people()
.get("people/me")
.setRequestMaskIncludeField("person.genders")
.setFields("genders")
.execute();
StringBuilder builder = new StringBuilder();
builder.append("获取性别信息成功").append("\n");
List<Gender> genders = person.getGenders();
for (Gender gender : genders) {
builder.append("formattedValue:").append(gender.getFormattedValue());
builder.append("value:").append(gender.getValue());
}
runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.tvUserInfo)).setText(builder.toString());
}
});
} catch (IOException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
@Override
public void run() {
((TextView) findViewById(R.id.tvUserInfo)).setText("获取个人详细信息失败:" + e.getMessage());
}
});
}
}
}).start();
}
不出意外的话屏幕上可以直接打印出来用户的性别信息了。
这里有个坑就是,如果之前Google登录的时候代码中没有设置.requestEmail()
,那么上述代码在运行的时候会直接崩溃报错,并不清楚是什么原因导致的,也懒得去研究了,集成这种SDK真的是心累还没有技术含量。
而且同事还遇到一个问题就是,如果你在OAuth同意屏幕中,设置了发布状态为测试版,那么你的OAuth同意屏幕是无法弹出来的,会无限转圈圈。
网址相关
Firebase 控制台 https://console.firebase.google.com/
Google Cloud Platform控制台 https://console.cloud.google.com/
注意还有一个网址是只包含API和服务功能的,https://console.developers.google.com/,这个可以不用,只不过我一开始不知道为什么使用的是这个。
Google 账户控制台 https://myaccount.google.com/
Api文档地址相关
Google People Api文档 https://developers.google.com/people
最后再黑一下,Google People API的文档真的是辣鸡,示例陈旧,代码东一处西一处,而且BUG百出!!!