本篇博客主要记录一下如何利用Google Play Service进行安全检测。

1 Google Play Service的使用原理 
Google Play Service提供了大量的API供用户使用, 
以便让应用低成本地集成Google最新的产品及功能。

应用使用Google Play Service时,基本的原理如下图所示,其中: 
1、应用在使用Google Play Service时, 
必须集成Google提供的Client Library, 
通过Client Library,应用才能与Google Play Service进行IPC通信。

2、Google Play Service是独立运行在系统后台的服务, 
与Google Play Store共同发布。

3、Google Play Store负责更新Google Play Service。 
 
可以看出,Google通过引入Client Library后, 
将应用与Google Play Service解耦。

这样即使不修改应用,只要更新了Google Play Services, 
应用就能够使用到Google提供功能的最新版本。 
同时,Client Library还可以进行准入控制等相关操作。

2 集成Client Library 
 
为了使用Client Library,首先我们需要利用Android Studio的SDK Manager加载Google Repository。 
如上图所示,主要是勾选其中的红线部分,然后点击下载即可。

下载完Google Repository后,只需要修改应用Module对应的build.gradle文件, 
加载对应的库文件即可。

例如:

dependencies {compile fileTree(dir: 'libs', include: ['*.jar']).....................//添加对play-service的依赖//Google Play Service更新后,修改对应的版本号compile 'com.google.android.gms:play-services:11.0.1'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这里需要注意的是,com.google.android.gms:play-services引入的是Google Play Service全体API的集合。

当我们仅需要特定API接口时,可以仅引入独立的库, 
这样可以减小应用的体积,避免应用中方法数过多。

例如,仅需要SafetyNet时,可以仅compile:

com.google.android.gms:play-services-safetynet:11.0.1
  • 1

目前,Play Service定义的所有独立API库可以参考如下链接: 
https://developers.google.com/android/guides/setup

3 确保设备上的Google Play Service可用 
当应用导入了Client Library后,我们就可以在应用中使用Client Library提供的接口了。

不过,我们知道一个应用将被安装到不同厂商的机器上, 
部分厂商的ROM中并没有集成Google Play Store,更别提Google Play Service了。

因此,当应用需要使用Google Play Service的功能时, 
首先需要做的就是判断当前设备是否具有对应的能力。

目前从文档来看,判断Google Play Service是否可用, 
最好的办法就是使用Client Library中GoogleApiAvailability提供的接口。

具体的做法类似于:

//如果整个应用都依赖于Google Play Service
//那么就在MainActivity的onResume接口中进行判断
//如果只有部分功能依赖该服务,可在具体使用前进行判断
@Override
protected void onResume() {super.onResume();//获取GoogleApiAvailability的单例GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();//利用接口判断device是否支持Google Play Serviceint ret = googleApiAvailability.isGooglePlayServicesAvailable(this);//支持的话, 结果将返回SUCCESSif (ret == ConnectionResult.SUCCESS) {Log.d(TAG, "This phone has available google service inside");.............} else {Log.e(TAG, "This phone don't have available google service inside");//不支持时,可以利用getErrorDialog得到一个提示框, 其中第2个参数传入错误信息//提示框将根据错误信息,生成不同的样式//例如,我自己测试时,第一次Google Play Service不是最新的,//对话框就会显示这些信息,并提供下载更新的按键googleApiAvailability.getErrorDialog(this, ret, 0).show();}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

4 利用Google API Client访问服务 
当device支持Google Play Service时,应用就可以使用对应的功能了。

如下图所示,应用实际上必须使用Client Library中的Google API Client来访问具体的服务。 
 
从图中可以看出,Google API Client作为应用与服务的桥梁,负责具体的通信细节。

在应用中获取Google API Client的方法如下所示:

private GoogleApiClient mGoogleApiClient;//如果在Activity的onStart函数被调用前,创建出GoogleApiClient对象,
//则可以利用AutoManage, 使得该对象在onStart后, 自动连接GooglePlayService
private void connectGooglePlayService() {Log.d(TAG, "connect to google play service");mGoogleApiClient = new GoogleApiClient.Builder(this)//这里使用自动管理,手动连接的话,可以获取client后,主动调用其connect接口//传入FailedListener,以便处理失败.enableAutoManage(this, new FailedListener())//我们关注安全检测,因此可以添加SafetyNet.API//不过这种用法目前已经deprecated了.addApi(SafetyNet.API)//添加回调对象,连接成功或失败均有通知.addConnectionCallbacks(new ConnectionCallback()).build();
}private class FailedListener implements GoogleApiClient.OnConnectionFailedListener {@Overridepublic void onConnectionFailed(@NonNull ConnectionResult connectionResult) {Log.e(TAG, "connect failed: " + connectionResult);//可以做一些错误处理..............}
}private class ConnectionCallback implements GoogleApiClient.ConnectionCallbacks {@Overridepublic void onConnected(@Nullable Bundle bundle) {Log.d(TAG, "connect to google play service success");//连接成功, 进行相应的工作...........}@Overridepublic void onConnectionSuspended(int i) {Log.e(TAG, "connect to google play service fail");//连接失败,进行处理...........}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

一旦应用创建出GoogleApiClient,同时成功连接Google Play Service后, 
就可以通过对应的API,使用相应的功能了。

5 SafetyNet的安全检测功能 
接下来我们以SafetyNet为例,看看如何使用Google Play Service提供的安全检测功能。

5.1 Attestation API 
从文档和测试返回的结果来看,Attestation API主要用于检测: 
应用所在设备Android运行环境的安全性和兼容性,有点类似CTS测试的味道。

需要注意的是: 
在使用这个API前,需要进入 Google Developers Console, 
开通 Android Device Verification API 并申请对应的Apk key。 
具体的网址可以自行搜索,有Google邮箱即可申请。

申请到key值后,需要在应用的AndroidManifest.xml中添加如下内容:

<meta-data android:name="com.google.android.safetynet.ATTEST_API_KEY"<!--这里*隐藏了部分信息--> android:value="AIzaSyCPVFlNC********-*********2NcvGi2sj0" />
  • 1
  • 2
  • 3

当添加完key值后,应用就可以使用SafetyNet的attest接口了。

这里我们以一种老式的调用方式为例,介绍一下API的使用方式:

private void attest() {// attest接口需要一个token,且长度不小于16 bytesbyte[] nonce = getRequestNonce(); // Should be at least 16 bytes in length.//可以看到,接口中传入了mGoogleApiClient//可以想到,其底层实现需要依赖于mGoogleApiClient来通信SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)//设置回调接口,当连接服务得到返回结果后就会通知//可以看到这里是种异步回调的设计.setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {@Overridepublic void onResult(SafetyNetApi.AttestationResult result) {Status status = result.getStatus();//服务端成功返回结果后,就可以取出信息了if (status.isSuccess()) {//Attest得到的结果是JWS字符串,需要本地解析String ret = result.getJwsResult();Log.d(TAG, "attest success with ret: " + ret);..............} else {// An error occurred while communicating with the service.Log.d(TAG, "attest fail");}}});
}private byte[] getRequestNonce() {String token = "ATTest " + System.currentTimeMillis() + TAG;return token.getBytes();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

需要说明的是: 
该API每日访问Google服务的次数是受限制的(估计因为用的是免费的,所以才受限吧)。

实际上,Google API控制台会统计每个API的请求次数,如下图所示: 

5.2 Safe Browsing API 
Safe Browsing API主要用于检测: 
某个url对应的网址是否具有潜在威胁。

与Attestation API一样,使用该API前同样需要进入Google Developers Console, 
开通Safe Browsing API并申请对应的App key值。

在使用时,需要在AndroidManifest.xml中添加类似如下内容:

<meta-data android:name="com.google.android.safetynet.API_KEY"<!--对于同一个应用而言,使用不同的API时可以共享同一个key --><!--Google服务器端也会统计该API的访问情况-->android:value="AIzaSyCPVFlNC********-*********2NcvGi2sj0" />
  • 1
  • 2
  • 3
  • 4

应用使用该API的方式类似于:

private void browseTest(String url) {//容易看出具体的使用方式与Attest类似SafetyNet.SafetyNetApi.lookupUri(mGoogleApiClient, url,//指定关心威胁的种类SafeBrowsingThreat.TYPE_POTENTIALLY_HARMFUL_APPLICATION,SafeBrowsingThreat.TYPE_SOCIAL_ENGINEERING)//同样定义回调接口.setResultCallback(new ResultCallback<SafetyNetApi.SafeBrowsingResult>() {@Overridepublic void onResult(SafetyNetApi.SafeBrowsingResult result) {Status status = result.getStatus();if ((status != null) && status.isSuccess()) {// Indicates communication with the service was successful.// Identify any detected threats.Log.d(TAG, "browse test success");//返回的结果中可以获取List<SafeBrowsingThreat>//SafeBrowsingThreat可以通过getThreatType,得到威胁的类型mHandler.sendMessage(mHandler.obtainMessage(BROWSE, result.getDetectedThreats()));} else {// An error occurred. Let the user proceed without warning.Log.e(TAG, "browse test fail: " + result.getStatus());...........}}});
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

5.3 Verify Apps API 
最后,我们看看Google Play Service的Verify Apps API。

这个API主要用于检测: 
手机上已安装的应用是否有害。

与前面两个API不同的是,在使用这个API前,必须开启终端对应的Feature。

对应的代码类似于:

private void enableVerifyFeature() {if (!mEnableVerifyFeature) {//获取SafeNetClient的实例,这个对象的底层应该封装了GoogleApiClient        mSafetyNetClient = SafetyNet.getClient(this);//SafeNetClient有两个接口与Verify App所需的Feature有关//分别为isVerifyAppsEnabled和enableVerifyApps//其中,isVerifyAppsEnabled主要用于判断Feature是否开启//enableVerifyApps在判断Feature未开启时,会弹出dialog提醒用户开启(若已开启Feature, 则不弹出dialog)mSafetyNetClient.enableVerifyApps().addOnCompleteListener(new OnCompleteListener<SafetyNetApi.VerifyAppsUserResponse>() {@Overridepublic void onComplete(Task<SafetyNetApi.VerifyAppsUserResponse> task) {if (task.isSuccessful()) {SafetyNetApi.VerifyAppsUserResponse result = task.getResult();//用户点击完dialog或feature已经开启后,进入该分支if (result.isVerifyAppsEnabled()) {Log.d(TAG, "The user gave consent " +"to enable the Verify Apps feature.");..................} else {Log.e(TAG, "The user didn't give consent " +"to enable the Verify Apps feature.");...............}} else {Log.e(TAG, "A general error occurred.");...............}}});}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

一旦Verify App对应的Feature开启后,我们就可以利用Verify App的API了,其中老式的用法类似于:

private void listHarmfulApps() {//同样依赖于GoogleApiClientSafetyNet.SafetyNetApi.listHarmfulApps(mGoogleApiClient)//获取到结果后,回调.setResultCallback(new ResultCallbacks<SafetyNetApi.HarmfulAppsResult>() {@Overridepublic void onSuccess(@NonNull SafetyNetApi.HarmfulAppsResult harmfulAppsResult) {Log.d(TAG, "list harm full success");..............}@Overridepublic void onFailure(@NonNull Status status) {Log.d(TAG, "list harm full fail: " + status);}});
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

最后,我们来看看官方文档推荐的新的调用方式:

private void listHarmfulApps() {mSafetyNetClient.listHarmfulApps()//添加Listener回调.addOnCompleteListener(new OnCompleteListener<SafetyNetApi.HarmfulAppsResponse>() {@Overridepublic void onComplete(Task<SafetyNetApi.HarmfulAppsResponse> task) {Log.d(TAG, "listHarmfulApps onComplete");//接口返回有效结果if (task.isSuccessful()) {SafetyNetApi.HarmfulAppsResponse result = task.getResult();long scanTimeMs = result.getLastScanTimeMs();Log.d(TAG, "list harmful apps used time: " + scanTimeMs);//获取有害应用列表List<HarmfulAppsData> appList = result.getHarmfulAppsList();if (appList.isEmpty()) {Log.d(TAG, "There are no known " +"potentially harmful apps installed.");} else {Log.e(TAG,"Potentially harmful apps are installed!");//得到有害应用的信息for (HarmfulAppsData harmfulApp : appList) {Log.e(TAG, "Information about a harmful app:");Log.e(TAG,"  APK: " + harmfulApp.apkPackageName);Log.e(TAG,"  SHA-256: " + harmfulApp.apkSha256);// Categories are defined in VerifyAppsConstants.Log.e(TAG,"  Category: " + harmfulApp.apkCategory);}}} else {Log.e(TAG, "An error occurred. ");}}//添加一个失败的回调接口}).addOnFailureListener(new OnFailureListener() {@Overridepublic void onFailure(@NonNull Exception e) {e.printStackTrace();}});
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

需要说明的是: 
自己测试时发现,listHarmfulApps接口并不稳定,在Android 6.0上偶尔会遇到编码为12004的错误。 
参考Google的API文档,发现这是Verify App API的internal error。 
此外,该接口在Android 7.0平台上,似乎也没法有效使用(不知是否与具体厂商有关)。

最后,我不得不吐槽一下,这个接口的能力简直是渣渣,居然几乎难以有效检测出威胁样本。

6 总结 
本篇文档主要介绍了Google Play Service的原理和集成方法, 
并以SafetyNet API为例,介绍了应用如何使用Google Play Service提供的功能。

参考文献 
https://developers.google.com/android/guides/overview

https://developer.android.com/training/safetynet

原文地址: http://blog.csdn.net/gaugamela/article/details/73658554

Google Play Service中安全检测API的使用说明相关推荐

  1. Python中使用GoogleMaps API(包含Geocoding API,Places API Web Service )详细教程

    前言 业务需要根据经纬度获取该城市的邮政编码,需要通过调用GoogleMaps来搜索地点,来获取地点的详细信息.于是查阅了一些相关的资料,特意分享出来给大家参考参考. 涉及相关的资料: google官 ...

  2. Google Maps API v2 android版本开发 国内手机不支持google play Service相关问题解决--图文教程

    Google Maps API v2 android版本开发 国内手机不支持google play Service相关问题解决--图文教程 参考文章: (1)Google Maps API v2 an ...

  3. Google发布新的TensorFlow物体检测API

    \\ Google发布TensorFlow物体检测API,帮助开发人员和研究人员识别图片中的物体.Google专注于提高API的易用性和性能,新的模型于6月16号发布,在基准测试中表现出良好的性能,并 ...

  4. 如何知道一个域名是否存在_域名检测API实现查看一个域名在微信中是否被封

    针对微信转发分享链接过程中,您宝贵的域名被微信检测系统过滤拦截而无法正常浏览,例如该网页包含诱导分享内容,被多人投诉等,又例如提示该网页已停止访问等提示.怎么查询域名在微信中是否被封了呢? 以上接口可 ...

  5. 使用UWP人脸检测API在WPF中进行人脸检测

    目录 介绍 先决条件 背景 人脸检测 标记人脸 查看模型 视图 结论 Download repository 介绍 通用Windows平台的Windows.Media.FaceAnalysis名称空间 ...

  6. 全球航运港口高科技领军企业CIMC中集飞瞳,推出通用集装箱AI识别检测API飞瞳引擎,集装箱残损识别集装箱箱况检验集装箱箱号识别

    全球航运港口高科技领军企业CIMC中集飞瞳,是全球应用最广,最先进集装箱人工智能企业.CIMCAI已完成全球上百万人工智能集装箱箱况检验,已完成全球上亿集装箱信息识别.CIMC中集飞瞳AI智能验箱得到 ...

  7. 【译】SafetyNet:Google对Android的篡改检测 (SafetyNet: Google's tamper detection - Part 1 )

    什么是SafetyNet Android Pay应用程序已于几天前发布.一些使用植根设备的人发现它拒绝工作.这是因为它使用了新的Google Play服务功能:SafetyNet证明. SafetyN ...

  8. 谷歌地图api 微信小程序_使用Google的融合位置提供程序API进行实时位置跟踪

    谷歌地图api 微信小程序 Location tracking and monitoring have seen a surge in modern application development w ...

  9. GMS(Google Mobile Service)

    Android CTS官方网站:https://source.android.com/compatibility/cts/index.html GMS全称为Google Mobile Service, ...

最新文章

  1. 分布式系统 一致性模型的介绍 以及 zookeeper的 “线性一致性“ 讨论
  2. 编译android系统小结
  3. c#执行多句oracle,在Oracle命令C#中执行多次插入表命令
  4. 洛谷 P1897电梯里的爱情 题解
  5. vue事件总线_[面试] 聊聊你对 Vue.js 框架的理解
  6. 论文解读丨图神经网络应用于半结构化文档的命名实体识别和关系提取
  7. 课下作业——对正在使用的搜索类软件/输入法进行评价
  8. ACM 学习笔记(七) 贪心
  9. @excel 注解_SpringBoot中关于Excel的导入和导出
  10. 手机运行慢可以刷机吗_为什么手机卡顿,反应变慢怎么解决?一定要刷机吗?...
  11. 自适应特征融合用于Single-Shot目标检测(附源代码下载)
  12. 数据库知识与技巧日常汇总
  13. Ms08067年度技术文集合
  14. Python Matplotlib 3D绘图详解(汇总)
  15. 图像分割之常用损失函数-Dice Loss
  16. 【JavaBeans中的属性!】
  17. java执行CMD命令,文件路径或文件名带空格处理
  18. Cesium,mars3d,3dtiles 3d地图显示
  19. pcap如何转换为pcd_极光扫描操作系统漏洞.doc
  20. 2023第六届山东国际青少年眼睛健康产业展会,视力矫正仪展②

热门文章

  1. jQuery(UI)常用插件
  2. ORA-00910: specified length too long for its datatype
  3. Squid 代理服务器 编译源码 伪造HTTP_X_FORWARDED_FOR 请求头
  4. C#3.0语法新特性集合
  5. who whoami who am i的区别
  6. X Window、GNOME和KDE之间的关系
  7. java多态替换switch_第1章 重构,第一个案例(3):运用多态取代switch
  8. “相对论“ 2019-07-10
  9. 目标检测方法简介:RPN(Region Proposal Network) and SSD(Single Shot MultiBox Detector)
  10. go语言中的defer