Google Play Service中安全检测API的使用说明
本篇博客主要記錄一下如何利用Google Play Service進行安全檢測。
1 Google Play Service的使用原理?
Google Play Service提供了大量的API供用戶使用,?
以便讓應(yīng)用低成本地集成Google最新的產(chǎn)品及功能。
應(yīng)用使用Google Play Service時,基本的原理如下圖所示,其中:?
1、應(yīng)用在使用Google Play Service時,?
必須集成Google提供的Client Library,?
通過Client Library,應(yīng)用才能與Google Play Service進行IPC通信。
2、Google Play Service是獨立運行在系統(tǒng)后臺的服務(wù),?
與Google Play Store共同發(fā)布。
3、Google Play Store負(fù)責(zé)更新Google Play Service。?
?
可以看出,Google通過引入Client Library后,?
將應(yīng)用與Google Play Service解耦。
這樣即使不修改應(yīng)用,只要更新了Google Play Services,?
應(yīng)用就能夠使用到Google提供功能的最新版本。?
同時,Client Library還可以進行準(zhǔn)入控制等相關(guān)操作。
2 集成Client Library?
?
為了使用Client Library,首先我們需要利用Android Studio的SDK Manager加載Google Repository。?
如上圖所示,主要是勾選其中的紅線部分,然后點擊下載即可。
下載完Google Repository后,只需要修改應(yīng)用Module對應(yīng)的build.gradle文件,?
加載對應(yīng)的庫文件即可。
例如:
dependencies {compile fileTree(dir: 'libs', include: ['*.jar']).....................//添加對play-service的依賴//Google Play Service更新后,修改對應(yīng)的版本號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的集合。
當(dāng)我們僅需要特定API接口時,可以僅引入獨立的庫,?
這樣可以減小應(yīng)用的體積,避免應(yīng)用中方法數(shù)過多。
例如,僅需要SafetyNet時,可以僅compile:
com.google.android.gms:play-services-safetynet:11.0.1- 1
目前,Play Service定義的所有獨立API庫可以參考如下鏈接:?
https://developers.google.com/android/guides/setup
3 確保設(shè)備上的Google Play Service可用?
當(dāng)應(yīng)用導(dǎo)入了Client Library后,我們就可以在應(yīng)用中使用Client Library提供的接口了。
不過,我們知道一個應(yīng)用將被安裝到不同廠商的機器上,?
部分廠商的ROM中并沒有集成Google Play Store,更別提Google Play Service了。
因此,當(dāng)應(yīng)用需要使用Google Play Service的功能時,?
首先需要做的就是判斷當(dāng)前設(shè)備是否具有對應(yīng)的能力。
目前從文檔來看,判斷Google Play Service是否可用,?
最好的辦法就是使用Client Library中GoogleApiAvailability提供的接口。
具體的做法類似于:
//如果整個應(yīng)用都依賴于Google Play Service //那么就在MainActivity的onResume接口中進行判斷 //如果只有部分功能依賴該服務(wù),可在具體使用前進行判斷 @Override protected void onResume() {super.onResume();//獲取GoogleApiAvailability的單例GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();//利用接口判斷device是否支持Google Play Serviceint ret = googleApiAvailability.isGooglePlayServicesAvailable(this);//支持的話, 結(jié)果將返回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個參數(shù)傳入錯誤信息//提示框?qū)⒏鶕?jù)錯誤信息,生成不同的樣式//例如,我自己測試時,第一次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訪問服務(wù)?
當(dāng)device支持Google Play Service時,應(yīng)用就可以使用對應(yīng)的功能了。
如下圖所示,應(yīng)用實際上必須使用Client Library中的Google API Client來訪問具體的服務(wù)。?
?
從圖中可以看出,Google API Client作為應(yīng)用與服務(wù)的橋梁,負(fù)責(zé)具體的通信細(xì)節(jié)。
在應(yīng)用中獲取Google API Client的方法如下所示:
private GoogleApiClient mGoogleApiClient;//如果在Activity的onStart函數(shù)被調(diào)用前,創(chuàng)建出GoogleApiClient對象, //則可以利用AutoManage, 使得該對象在onStart后, 自動連接GooglePlayService private void connectGooglePlayService() {Log.d(TAG, "connect to google play service");mGoogleApiClient = new GoogleApiClient.Builder(this)//這里使用自動管理,手動連接的話,可以獲取client后,主動調(diào)用其connect接口//傳入FailedListener,以便處理失敗.enableAutoManage(this, new FailedListener())//我們關(guān)注安全檢測,因此可以添加SafetyNet.API//不過這種用法目前已經(jīng)deprecated了.addApi(SafetyNet.API)//添加回調(diào)對象,連接成功或失敗均有通知.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");//連接成功, 進行相應(yīng)的工作...........}@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
一旦應(yīng)用創(chuàng)建出GoogleApiClient,同時成功連接Google Play Service后,?
就可以通過對應(yīng)的API,使用相應(yīng)的功能了。
5 SafetyNet的安全檢測功能?
接下來我們以SafetyNet為例,看看如何使用Google Play Service提供的安全檢測功能。
5.1 Attestation API?
從文檔和測試返回的結(jié)果來看,Attestation API主要用于檢測:?
應(yīng)用所在設(shè)備Android運行環(huán)境的安全性和兼容性,有點類似CTS測試的味道。
需要注意的是:?
在使用這個API前,需要進入 Google Developers Console,?
開通 Android Device Verification API 并申請對應(yīng)的Apk key。?
具體的網(wǎng)址可以自行搜索,有Google郵箱即可申請。
申請到key值后,需要在應(yīng)用的AndroidManifest.xml中添加如下內(nèi)容:
<meta-data android:name="com.google.android.safetynet.ATTEST_API_KEY"<!--這里*隱藏了部分信息--> android:value="AIzaSyCPVFlNC********-*********2NcvGi2sj0" />- 1
- 2
- 3
當(dāng)添加完key值后,應(yīng)用就可以使用SafetyNet的attest接口了。
這里我們以一種老式的調(diào)用方式為例,介紹一下API的使用方式:
private void attest() {// attest接口需要一個token,且長度不小于16 bytesbyte[] nonce = getRequestNonce(); // Should be at least 16 bytes in length.//可以看到,接口中傳入了mGoogleApiClient//可以想到,其底層實現(xiàn)需要依賴于mGoogleApiClient來通信SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)//設(shè)置回調(diào)接口,當(dāng)連接服務(wù)得到返回結(jié)果后就會通知//可以看到這里是種異步回調(diào)的設(shè)計.setResultCallback(new ResultCallback<SafetyNetApi.AttestationResult>() {@Overridepublic void onResult(SafetyNetApi.AttestationResult result) {Status status = result.getStatus();//服務(wù)端成功返回結(jié)果后,就可以取出信息了if (status.isSuccess()) {//Attest得到的結(jié)果是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服務(wù)的次數(shù)是受限制的(估計因為用的是免費的,所以才受限吧)。
實際上,Google API控制臺會統(tǒng)計每個API的請求次數(shù),如下圖所示:?
5.2 Safe Browsing API?
Safe Browsing API主要用于檢測:?
某個url對應(yīng)的網(wǎng)址是否具有潛在威脅。
與Attestation API一樣,使用該API前同樣需要進入Google Developers Console,?
開通Safe Browsing API并申請對應(yīng)的App key值。
在使用時,需要在AndroidManifest.xml中添加類似如下內(nèi)容:
<meta-data android:name="com.google.android.safetynet.API_KEY"<!--對于同一個應(yīng)用而言,使用不同的API時可以共享同一個key --><!--Google服務(wù)器端也會統(tǒng)計該API的訪問情況-->android:value="AIzaSyCPVFlNC********-*********2NcvGi2sj0" />- 1
- 2
- 3
- 4
應(yīng)用使用該API的方式類似于:
private void browseTest(String url) {//容易看出具體的使用方式與Attest類似SafetyNet.SafetyNetApi.lookupUri(mGoogleApiClient, url,//指定關(guān)心威脅的種類SafeBrowsingThreat.TYPE_POTENTIALLY_HARMFUL_APPLICATION,SafeBrowsingThreat.TYPE_SOCIAL_ENGINEERING)//同樣定義回調(diào)接口.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");//返回的結(jié)果中可以獲取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主要用于檢測:?
手機上已安裝的應(yīng)用是否有害。
與前面兩個API不同的是,在使用這個API前,必須開啟終端對應(yīng)的Feature。
對應(yīng)的代碼類似于:
private void enableVerifyFeature() {if (!mEnableVerifyFeature) {//獲取SafeNetClient的實例,這個對象的底層應(yīng)該封裝了GoogleApiClient mSafetyNetClient = SafetyNet.getClient(this);//SafeNetClient有兩個接口與Verify App所需的Feature有關(guān)//分別為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已經(jīng)開啟后,進入該分支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對應(yīng)的Feature開啟后,我們就可以利用Verify App的API了,其中老式的用法類似于:
private void listHarmfulApps() {//同樣依賴于GoogleApiClientSafetyNet.SafetyNetApi.listHarmfulApps(mGoogleApiClient)//獲取到結(jié)果后,回調(diào).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
最后,我們來看看官方文檔推薦的新的調(diào)用方式:
private void listHarmfulApps() {mSafetyNetClient.listHarmfulApps()//添加Listener回調(diào).addOnCompleteListener(new OnCompleteListener<SafetyNetApi.HarmfulAppsResponse>() {@Overridepublic void onComplete(Task<SafetyNetApi.HarmfulAppsResponse> task) {Log.d(TAG, "listHarmfulApps onComplete");//接口返回有效結(jié)果if (task.isSuccessful()) {SafetyNetApi.HarmfulAppsResponse result = task.getResult();long scanTimeMs = result.getLastScanTimeMs();Log.d(TAG, "list harmful apps used time: " + scanTimeMs);//獲取有害應(yīng)用列表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!");//得到有害應(yīng)用的信息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. ");}}//添加一個失敗的回調(diào)接口}).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
需要說明的是:?
自己測試時發(fā)現(xiàn),listHarmfulApps接口并不穩(wěn)定,在Android 6.0上偶爾會遇到編碼為12004的錯誤。?
參考Google的API文檔,發(fā)現(xiàn)這是Verify App API的internal error。?
此外,該接口在Android 7.0平臺上,似乎也沒法有效使用(不知是否與具體廠商有關(guān))。
最后,我不得不吐槽一下,這個接口的能力簡直是渣渣,居然幾乎難以有效檢測出威脅樣本。
6 總結(jié)?
本篇文檔主要介紹了Google Play Service的原理和集成方法,?
并以SafetyNet API為例,介紹了應(yīng)用如何使用Google Play Service提供的功能。
參考文獻?
https://developers.google.com/android/guides/overview?
https://developer.android.com/training/safetynet
原文地址: http://blog.csdn.net/gaugamela/article/details/73658554
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的Google Play Service中安全检测API的使用说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (原创)Android6.0亮屏流程之K
- 下一篇: 先读懂CapsNet架构然后用Tenso