Android 集成 google 登錄並獲取 性別等隱私信息

前言

公司做海外產品的,集成的是 google 賬號登錄,賬號信息、郵箱等這些不涉及隱私的按 google 的正常登錄流程可以輕鬆實現 。但是一旦需要獲取涉及隱私的信息就比較麻煩,文檔也不是十分清晰,非常難找,很多坑。

google 賬號登錄

官方鏈接:https://developers.google.com/identity/sign-in/android/start
https://developers.google.com/identity/sign-in/android/sign-in
google 賬號登錄接入的坑:

  • 申請的 client_id必須是 api console 後臺 :https://console.cloud.google.com/apis 與 google play 後臺對應的應用關聯起來。
  • client_id 下的簽名信息和報名信息必須和測試時的 apk 的簽名信息和報名信息一致。
  • 在 google play 下啓動 google 的二次簽名,則 api console 後臺的簽名信息是二次簽名後的信息。打包測試時使用上傳 到 Google play 後臺的 apk 的簽名證書即可。

google 登錄的流程在這個文檔寫的比較清楚了:https://developers.google.com/identity/sign-in/android/sign-in,這裏大致說一下,不貼代碼了

  1. 構建需求請求的內容:
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
       .requestEmail()
       .requestIdToken("your client_id")
       .build();
// Build a GoogleSignInClient with the options specified by gso.
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

2.發起登錄請求,跳轉 google 登錄頁面。

Intent signInIntent = mGoogleSignInClient.getSignInIntent();
  startActivityForResult(signInIntent, RC_SIGN_IN);
  1. 獲取 Google 登錄返回
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        // The Task returned from this call is always completed, no need to attach
        // a listener.
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        handleSignInResult(task);
    }
}
  1. 獲取 用戶 id token,傳到你自己的 服務端 做驗證
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
    try {
        GoogleSignInAccount account = completedTask.getResult(ApiException.class);
        // Signed in successfully, show authenticated UI. 
    } catch (ApiException e) {
        // The ApiException status code indicates the detailed failure reason.
        // Please refer to the GoogleSignInStatusCodes class reference for more information.
        Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());    
    }
}
  1. 切換賬號
  /**
     * 重新獲取賬號列表
     */
    public void revokeAccess() {
        try {
            if (mGoogleSignInClient!=null && mActivity!=null){
                mGoogleSignInClient.revokeAccess().addOnCompleteListener(mActivity, new OnCompleteListener<Void>() {
                    @Override
                    public void onComplete(@NonNull Task<Void> task) {
                        Log.d(TAG, "onComplete: ");
                    }
                });
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

獲取公開資料和需要特別授權的信息(性別、生日等)

1、在構建請求是新增獲取 的公共資料信息 及 需要獲取的特殊信息

private static final String GENDER_SCOPE = "https://www.googleapis.com/auth/user.gender.read";
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail()
        .requestIdToken("your client_id")
        .requestScopes(new Scope(GENDER_SCOPE));
        .build();
// Build a GoogleSignInClient with the options specified by gso.
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

需要請求的信息可在如下鏈接查找:https://developers.google.com/people/api/rest/v1/people/get

2、檢測是否有權限

  GoogleSignInAccount lastSignedInAccount = GoogleSignIn.getLastSignedInAccount(mActivity);
       Scope scope = new Scope(GENDER_SCOPE);
       if (Utils.isNeedRequest() && !GoogleSignIn.hasPermissions(lastSignedInAccount,scope)){
                   SGLog.d(TAG+"   need requst permission...");
           GoogleSignIn.requestPermissions(mActivity,RC_GET_TOKEN,lastSignedInAccount,scope);
       }

注意:這一步不需要也可以,有這一步會出現一個 “再確認” 的授權頁面,沒有也不影響獲取的信息。
3、跳轉登錄頁面 (同以上 google 賬號登錄)
4、獲取登錄信息 (同以上 Google賬號登錄)
5、開啓線程獲取 特殊信息

 getProfileAsyncTask = new GetProfileAsyncTask(mActivity, new GpProfileInfoCallback() {
            @Override
            public void onGetProfileInfo(Person person) {
                SGLog.d(TAG+" onGetProfileInfo... ");
                getProfileInfo(person);
            }
        });
        getProfileAsyncTask.execute(signInAccount);

異步任務

// Global instance of the HTTP transport
    private static final HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport();

    // Global instance of the JSON factory
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

 private static class GetProfileAsyncTask extends AsyncTask<GoogleSignInAccount, Void, Person> {

        // Retrieved from the sigin result of an authorized GoogleSignIn
        private WeakReference<Activity> mActivityRef;
        private GpProfileInfoCallback mProfileInfoCallback;

        public GetProfileAsyncTask(Activity activity,GpProfileInfoCallback callback) {
            mActivityRef = new WeakReference<>(activity);
            mProfileInfoCallback = callback;
        }

        @Override
        protected Person doInBackground(GoogleSignInAccount... params) {
            if (mActivityRef.get() == null){
                SGLog.d(TAG+" GetProfileAsyncTask doInBackground activity is null.");
                return null;
            }

            GoogleSignInAccount signInAccount = params[0];
            Context context = mActivityRef.get().getApplicationContext();
            GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(
                    context,
                    Collections.singleton(GENDER_SCOPE));
            credential.setSelectedAccount(signInAccount.getAccount());
            SGLog.d(TAG+" get profile info start.");
            PeopleService service =
                    new PeopleService.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                    .setApplicationName(ApkUtils.getAppName(context)) // your app name
                    .build();
            SGLog.d(TAG+" get profile info start.");
            // Get info. on user
            Person person =null;
            try {
                person = service
                        .people()
                        .get("people/me")
                        .setPersonFields("genders")
                        .execute();
                SGLog.d(TAG+"  getPerson end.");
                // return the result
                if (mProfileInfoCallback!=null){
                    mProfileInfoCallback.onGetProfileInfo(person);
                }
            } catch (Exception e) {
                SGLog.e(TAG+e.getMessage());
                if (mProfileInfoCallback!=null){
                    mProfileInfoCallback.onGetProfileInfo(null);
                }
                e.printStackTrace();
            }
            return person;
        }

        @Override
        protected void onPostExecute(Person aVoid) {
            super.onPostExecute(aVoid);
        }
    }

獲取性別信息

 private void getProfileInfo(Person person){
        SGLog.d(TAG+" executeProfileInfo...");
        if (person == null){
            notifyResult(mLastUser,Utils.SUCCESS);
        }else {
            try {
                List<Gender> genders = person.getGenders();
                Gender gender = genders.get(0);
                String value = gender.getValue();
                SGLog.d(TAG+"  genders:"+genders.size()+ "  gender:"+value);
                mLastUser.setGender(value);
                notifyResult(mLastUser,Utils.SUCCESS);
            }catch (Exception e){
                SGLog.e(TAG+" getProfileInfo error.");
                notifyResult(null,SGErrorCode.LOGIN_FAILED);
                e.printStackTrace();
            }
        }
    }

參考文獻:
https://developers.google.com/identity/sign-in/android/sign-in
https://developers.google.cn/android/guides/http-auth
https://developers.google.com/people/api/rest/?apix=true
https://github.com/googlesamples/google-services/tree/master/android/signin
https://developers.google.com/people/api/rest/v1/people/get

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章