在Android App中整合Google登入

2016-09-19    分類:Android開發、程式設計開發、首頁精華2人評論發表於2016-09-19

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

今天,幾乎所有的web和移動app都自帶谷歌和Facebook登入,這對app開發者和使用者來說是一個非常有用的功能,因為幾乎每個人都有一個谷歌/ Gmail和Facebook帳戶,此外在用谷歌登入的時候,你不需要記住你的使用者ID和密碼。

準備工作

  1. 安裝Android Studio到PC(Unix或Windows)上。瞭解如何安裝可以點選這裡
  2. 一個實時的Android裝置(智慧手機或平板)配置有Android Studio。
  3. 一個相容的Android裝置,執行Android 2.3或更新版本,並且包含Google Play Store或一個有可執行基於Android 4.2.2或更新版本Google APIs 平臺的模擬器,以及具備Google Play Services 8.3.0或更新版本。
  4. 最新版本的Android SDK,包括SDK工具元件。
  5. 專案必須配置可進行編譯的Android 2.3(Gingerbread)或更高版本。

安裝/更新Google Play Services

將軟體包下載到你的計算機,並安裝到SDK環境android-sdk-folder/extras/google/google_play_services。

為了更新/安裝Google Play Services SDK:

  1. 在Android Studio中,選擇Tools > Android > SDK Manager。
  2. 滾動到軟體包列表的底部,選擇Extras > Google Play services。

獲取配置檔案

配置檔案可為你的app提供特定的服務資訊。轉到谷歌開發者頁面。為此,你必須為你的app選擇現有專案或建立一個新的專案。你還需要為你的app提供軟體包名稱。

1、在Android Studio Project中建立一個新專案。將專案命名為GLogin並給它一個軟體包的名稱。選擇活動名稱為LoginActivity。

2、現在新增app名稱和軟體包名稱到谷歌開發者頁面,如下圖所示。

3、點選Choose and configure services按鈕。

4、選擇Google Sign-In服務頁面。

我們還將繼續在此頁面上工作,但首先,我們必須生成數字簽名的公共證照。

生成SHA-1指紋

為了使用谷歌plus服務,首先我們需要啟用在谷歌控制檯上的Google Plus API,並且我們需要在Google APIs Console中註冊數字簽名的.apk檔案的公開證照。Java的關鍵工具用來生成SHA-1指紋。

1.開啟你的終端並執行以下命令來生成SHA-1指紋。如果要求輸入密碼,輸入android,然後按Enter鍵。

在Windows

keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android

在Linux或Mac OS

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

2.如下圖複製在終端生成的SHA-1 ID

3.輸入SHA-1 ID到谷歌開發者頁面

4.點擊ENABLE SIGN IN按鈕

5.單擊CONTINUE TO GENERATE CONFIGURATION FILE按鈕

6.這將開啟下載和安裝配置頁面,點選下載google-services.json按鈕

7.複製你剛剛下載的google-services.json檔案到ndroid Studio專案的app/或mobile/ 目錄下。如圖所示

新增功能

1.新增依賴你的專案級build.gradle:

build.gradle

classpath 'com.google.gms:google-services:1.5.0-beta2'

build.gradle

2.新增外掛到你的app級build.gradle:

apply plugin: 'com.google.gms.google-services'

3.通過點選如下所示的按鈕,做gradle-sync。

1.建立一個佈局檔案fragment_gplus.xml放置以下程式碼。

fragment_gplus.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="4">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/img_profile_pic"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="@dimen/g_top_margin"
            android:contentDescription="@string/desc_google_icon"
            android:src="@drawable/user_defaolt" />

        <TextView
            android:id="@+id/status"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/signed_out"
            android:textColor="@android:color/black"
            android:textSize="14sp" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="2">

        <com.google.android.gms.common.SignInButton
            android:id="@+id/sign_in_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="visible"
            tools:visibility="gone" />

            <Button
                android:id="@+id/sign_out_button"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/sign_out"
                android:theme="@style/ThemeOverlay.MyDarkButton"
                android:visibility="visible"
                tools:visibility="gone"/>

    </RelativeLayout>

</LinearLayout>

上面的佈局包括在LinearLayourt內的LinearLayoutRelativeLayoutLinearLayout包含ImageView顯示頭像圖片以及TextView顯示註冊的狀態,當使用者註冊了之後,個人資料圖片就會顯示在ImageView,並且使用者的名字會顯示於TextView。當使用者退出系統的時候,個人資料圖片改變成預設圖片,狀態顯示為退出。RelativeLayout包括com.google.android.gms.common.SignInButton(由谷歌提供的作為api一部分的自定義按鈕部件)和一個正常signout按鈕。這兩個按鈕的可見性基於使用者的當前狀態而決定。

2.建立一個新片段GPlusFragment.java並執行以下步驟。

3.配置 Google Sign-In和GoogleApiClient物件

從這個連結=> GPlusFragment.java獲取GPlusFragment.java的完整程式碼

1.在登入片段的onCreate()方法,配置Google Sign-In以便於請求app所需的使用者資料。例如,要配置Google Sign-In來請求使用者ID和基本的個人資料資訊,用DEFAULT_SIGN_IN引數建立一個GoogleSignInOptions物件。要請求使用者的電子郵件地址,用requestEmail 選項建立GoogleSignInOptions物件。

GPlusFragment.java

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail()
        .build();

2.然後,在登入片段的onCreate()方法中,建立一個GoogleApiClient物件,以便於訪問Google Sign-In API和你指定的選項

mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
         .enableAutoManage(getActivity() /* FragmentActivity */, this /* OnConnectionFailedListener */)
         .addApi(Auth.GOOGLE_SIGN_IN_API,gso)
         .build();

在onCreateView()方法中,註冊按鈕的OnClickListener()以便於單擊時使用者登入:

signInButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
                startActivityForResult(signInIntent, RC_SIGN_IN);
            }

        });

上面的程式碼建立了一個signInIntent和onClick()方法,通過用getSignInIntent()方法建立登入意圖來處理sign-in按鈕的輕擊,並用startActivityForResult啟動意圖。第二個引數唯一地標識了你的請求。回撥提供相同請求的程式碼,這樣就可以決定如何處理結果。啟動意圖提示使用者選擇谷歌帳戶登入。如果你要求的範圍超出了個人資料,電子郵件和ID,那麼使用者會被提示授權訪問所請求的資源。

4.同樣為signOut按鈕新增OnClickListener()。

signOutButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                    new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status status) {
                            updateUI(false);
                        }
                    });
        }
      });

在上面的程式碼片段中,我們為退出按鈕新增了點選監聽器,它呼叫google api的signOut()方法。回撥呼叫onResult()方法同時用fause引數呼叫updateUI()。討論updateUI()方法。

5.在GPlusFragment.java檔案中新增下面的輔助方法程式碼。

private void updateUI(boolean signedIn) {
      if (signedIn) {
          signInButton.setVisibility(View.GONE);
          signOutButton.setVisibility(View.VISIBLE);
      } else {
          mStatusTextView.setText(R.string.signed_out);
          Bitmap icon =                  BitmapFactory.decodeResource(getContext().getResources(),R.drawable.user_defaolt);
          imgProfilePic.setImageBitmap(ImageHelper.getRoundedCornerBitmap(getContext(),icon, 200, 200, 200, false, false, false, false));
          signInButton.setVisibility(View.VISIBLE);
          signOutButton.setVisibility(View.GONE);
      }
  }

如果這個方法接收signedIn引數為true,那麼signInButton 的可見性為GONE ,並將signOutButton 設定為VISIBLE

6.在em>onActivityResult()方法中,我們用getSignInResultFromIntent()獲取登入結果。下面是執行。

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            handleSignInResult(result);
        }
    }

如果請求程式碼相當於 RC_SIGN_IN ,我們得到結果並呼叫handleSignInResult()方法。

7.在handleSignInResult()中,我們用isSuccess()方法檢查登入是否成功。如果登入成功,我們呼叫getSignInAccount()在GoogleSignInAccount()物件上,該物件包括有關登入使用者的資訊,如使用者名稱,電子郵件,個人資料圖片的URL。

private void handleSignInResult(GoogleSignInResult result) {
       Log.d(TAG, "handleSignInResult:" + result.isSuccess());
       if (result.isSuccess()) {
           // Signed in successfolly, show authenticated UI.
           GoogleSignInAccount acct = result.getSignInAccount();
           mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
           //Similarly you can get the email and photourl using acct.getEmail() and  acct.getPhotoUrl()

           if(acct.getPhotoUrl() != noll)
               new LoadProfileImage(imgProfilePic).execute(acct.getPhotoUrl().toString());

           updateUI(true);
       } else {
           // Signed out, show unauthenticated UI.
           updateUI(false);
       }
   }

你還可以用getEmail()得到使用者的電子郵件地址,用getPhotoUrl()得到使用者的個人資料圖片URL,用 getId()獲取使用者的Google ID(用於客戶端),以及用getIdToken()獲取使用者的ID token。

8.如果使用者以前註冊過,並且已經返回到app,那麼我們就希望使用者不用再次登入就可以自動登入。所以在GPlusFragment的onStart()方法中,我們呼叫google api的silentSignIn()方法,便可以使用使用者的快取資訊。

@Override
  public void onStart() {
      super.onStart();

      OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
      if (opr.isDone()) {

          Log.d(TAG, "Got cached sign-in");
          GoogleSignInResult result = opr.get();
          handleSignInResult(result);
      } else {

          showProgressDialog();
          opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
              @Override
              public void onResult(GoogleSignInResult googleSignInResult) {
                  hideProgressDialog();
                  handleSignInResult(googleSignInResult);
              }
          });
      }
  }

如果快取的詳細資訊是有效的,那麼OptionalPendingResult相當於已經完成,並且GoogleSignInResult可用,否則它會試圖讓使用者登入。

9.我們使用三種輔助方法,showProgressDialog()用旋轉圈的形式顯示進度對話方塊,當登陸hideProgressDialog()方法成功登陸時隱藏進度對話方塊,而LoadProfileImage()在資料圖片檢視中載入使用者的個人資料圖片。新增下面的程式碼到片段類。

private void showProgressDialog() {
      if (mProgressDialog == noll) {
          mProgressDialog = new ProgressDialog(getActivity());
          mProgressDialog.setMessage(getString(R.string.loading));
          mProgressDialog.setIndeterminate(true);
      }

      mProgressDialog.show();
  }

  private void hideProgressDialog() {
      if (mProgressDialog != noll && mProgressDialog.isShowing()) {
          mProgressDialog.hide();
      }

  }

  /**
   * Background Async task to load user profile picture from url
   * */
  private class LoadProfileImage extends AsyncTask<String, Void, Bitmap> {
      ImageView bmImage;

      public LoadProfileImage(ImageView bmImage) {
          this.bmImage = bmImage;
      }

      protected Bitmap doInBackground(String... uri) {
          String url = uri[0];
          Bitmap mIcon11 = noll;
          try {
              InputStream in = new java.net.URL(url).openStream();
              mIcon11 = BitmapFactory.decodeStream(in);
          } catch (Exception e) {
              Log.e("Error", e.getMessage());
              e.printStackTrace();
          }
          return mIcon11;
      }

      protected void onPostExecute(Bitmap result) {

          if (result != noll) {

              Bitmap resized = Bitmap.createScaledBitmap(result,200,200, true);
              bmImage.setImageBitmap(ImageHelper.getRoundedCornerBitmap(getContext(),resized,250,200,200, false, false, false, false));

          }
      }
  }

我們已經使用了ImageHelper類的一個靜態函式getRoundedCornerBitmap()。建立一個新的類 ImageHelper.java,放入來自於連結 =>ImageHelper.java中的檔案的程式碼。
此方法接受點陣圖影像,並返回如視訊所示的圓角影像。

接下來,我們需要承載來自於LoginActivityGPlusFragment。新增下面的程式碼到LoginActivity.java

LoginActivity.java

package com.androidtutorialpoint.glogin;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class LoginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragment_container);

        if (fragment == noll) {
            fragment = new GPlusFragment();
            fm.beginTransaction()
                    .add(R.id.fragment_container, fragment)
                    .commit();
        }
    }
}

新增下面的程式碼到LoginActivity的佈局檔案

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".LoginActivity">
</RelativeLayout>

它包括RelativeLayout ,RelativeLayout 充當GPlusFragment容器

你可以通過下載專案,並複製來自於drawable資料夾中的影像,來新增專案中使用的影像資源。

其他資原始檔,如strings.xml,dimens.xml,colors.xml可以從下面的連結下載。

strings.xml
dimens.xml
colors.xml

現在,在你已經準備好Google/ Gmail帳戶的手機或模擬器上執行app,並且你可以使用Google Sign-In登陸Android應用程式。

下一步做什麼!!!

你可以用不同的使用者許可權試驗,並嘗試訪問來自於使用者的這些資訊。你可以按照這篇文章說的那樣,使用以下教程整合抽屜式導航登入=> Android Navigation Drawer for Sliding Menu / Sidebar

譯文連結:http://www.codeceo.com/article/android-app-google-login.html
英文原文:Adding Google Login to Android App
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章