iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0

前言

昨天我們設定好了OAuth 2.0憑證,今天我們來講如何在Android Studio使用OAuth 2.0連結我們的Google帳戶,APP會透過OAuth 2.0向用戶請求授權,然後用戶會登入並同意授權該應用程式存取其 Google 日曆的權限。之後應用程式會獲得訪問令牌(Access Token),用來代表用戶與 API 進行互動。

在 Android Studio 中使用 OAuth 2.0

1.設定 Gradle 相依性

build.gradle(APP)中加入以下相依性

  • kotlin
dependencies {
    implementation("com.google.android.gms:play-services-auth:20.5.0")
    implementation("com.google.api-client:google-api-client-android:1.33.0")
    implementation("com.google.apis:google-api-services-calendar:v3-rev20190609-1.30.1")
    implementation("com.google.oauth-client:google-oauth-client-jetty:1.33.0")
    implementation("com.google.http-client:google-http-client-android:1.40.0")
    implementation("com.google.http-client:google-http-client-gson:1.40.0")
}

2.在AndroidManifest.xml 中設定權限

  • XML
    AndroidManifest.xml加入需要的權限:
<?xml version="1.0" encoding="utf-8"?>
<manifest
    //略
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <application
       //略
        <activity
            //略
        </activity>
    </application>

</manifest>

3.建立GoogleCalendarAuth.kt檔案

下面我先將程式碼放上來,再來講解該程式碼的作用

  • kotlin
package your com.example

import android.app.Activity
import android.content.Intent
import android.util.Log
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.api.client.extensions.android.http.AndroidHttp
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
import com.google.api.services.calendar.Calendar
import com.google.api.services.calendar.CalendarScopes
import com.google.api.client.json.gson.GsonFactory

class GoogleCalendarAuth(
    private val activity: Activity,
    private val onSignInSuccess: (Boolean) -> Unit
) {

    companion object {
        private const val RC_SIGN_IN = 1001
    }

    private var googleSignInClient = GoogleSignIn.getClient(
        activity,
        GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestScopes(com.google.android.gms.common.api.Scope(CalendarScopes.CALENDAR))
            .build()
    )

    private var calendarService: Calendar? = null

    // 開始 Google 登入流程
    fun signIn() {
        val signInIntent = googleSignInClient.signInIntent
        activity.startActivityForResult(signInIntent, RC_SIGN_IN)
    }

    // 在 onActivityResult 中處理登入結果
    fun handleSignInResult(requestCode: Int, data: Intent?) {
        if (requestCode == RC_SIGN_IN) {
            val task = GoogleSignIn.getSignedInAccountFromIntent(data)
            try {
                val account = task.getResult(ApiException::class.java)
                setupCalendarService(account)
                Log.d("GoogleCalendarAuth", "Sign-in successful")
                onSignInSuccess(true) // 成功時回調 true
            } catch (e: ApiException) {
                Log.e("GoogleCalendarAuth", "Sign-in failed, code=${e.statusCode}")
                onSignInSuccess(false) // 失敗時回調 false
            }
        } else {
            Log.d("GoogleCalendarAuth", "handleSignInResult not called")
        }
    }

    // 設定 Google Calendar 服務
    private fun setupCalendarService(account: GoogleSignInAccount?) {
        val credential = GoogleAccountCredential.usingOAuth2(
            activity, listOf(CalendarScopes.CALENDAR)
        )
        credential.selectedAccount = account?.account

        calendarService = Calendar.Builder(
            AndroidHttp.newCompatibleTransport(),
            GsonFactory.getDefaultInstance(),
            credential
        ).setApplicationName("YourAppName").build()
    }

    // 取得 Google Calendar 服務
    fun getCalendarService(): Calendar? {
        return calendarService
    }
}
}

上面這段程式碼負責處理 Google Calendar 的登入與授權流程。在 Android 應用中,使用 GoogleSignInClient 讓使用者進行 Google 登入,並透過 onActivityResult 確認登入結果。登入成功後,會建立 Google Calendar API 服務實例,並將授權憑證 (GoogleAccountCredential) 設定給該服務。


這樣我們就完成一個簡單的Google Calendar API授權程式
接下來我們來檢測是否能成功運行
我們在MainActivity.kt修改一下程式碼,程式碼如下

  • kotlin
class MainActivity : ComponentActivity() {

    private var googleCalendarAuth: GoogleCalendarAuth? = null // 初始化變數
    private var loginSuccess = mutableStateOf(false) // 使用 mutableStateOf 追蹤登入狀態

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 初始化 GoogleCalendarAuth 並設定成功/失敗回調
        googleCalendarAuth = GoogleCalendarAuth(this) { success ->
            Log.d("MainActivity", "Sign-in result received: $success") // 確認是否收到回調
            if (success) {
                loginSuccess.value = true // 更新登入狀態
            }
        }

        // 使用 Jetpack Compose 設定 UI
        setContent {
            MyApp()
        }
    }

    @Composable
    fun MyApp() {
        val context = LocalContext.current // 取得當前的 Context
        val isLoggedIn by loginSuccess // 使用 by 來觀察 mutableState

        Column(modifier = Modifier.padding(16.dp)) {
            if (!isLoggedIn) {
                Button(onClick = {
                    googleCalendarAuth?.signIn()
                }) {
                    Text(text = "Sign in to Google Calendar")
                }
            } else {
                Text(text = "登入成功")
                // 顯示登入成功的 Toast 訊息
                LaunchedEffect(Unit) {
                    Toast.makeText(context, "登入成功", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

    // 處理 Google 登入的回調
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        googleCalendarAuth?.handleSignInResult(requestCode, data) // 呼叫 GoogleCalendarAuth 處理登入結果
    }
}

編譯結果如下
https://ithelp.ithome.com.tw/upload/images/20240926/20162649qOztnsdK1C.png
我們點擊Sign in to Google Calendar,APP程式將啟動 Google Sign-In 流程,並彈出一個 Google 登入頁面,要求你選擇一個 Google 帳戶並授權應用程式訪問 Google Calendar。如果你是在虛擬機上執行,通常會要求你先登入你的Google帳戶,如下圖
https://ithelp.ithome.com.tw/upload/images/20240926/201626495b8Ji7KJbM.png
登入帳戶後,點擊Sign in to Google Calendar,畫面上的按鈕將被替換為登入成功同時,應該彈出一個Toast 訊息,顯示登入成功如下圖所示
https://ithelp.ithome.com.tw/upload/images/20240926/20162649BvTg652obW.png
同時我們可以點選Android Studio左下角的Logcat(左下角像貓貓的那個ICON),能夠看到我們的LOG訊息,如下圖
https://ithelp.ithome.com.tw/upload/images/20240926/20162649E0Hf8VC5Xi.png
可以看到我們已經成功使用使用OAuth 2.0連結我們的Google帳戶了。

後話

今天我們使用了OAuth 2.0連結我們的Google帳戶,明天我們會開始透過程式來讀取行事曆上的事件,並透過程式碼新增事件到我們的行事曆上,這邊向各位勘誤一下,昨天的建立OAuthID那邊最後輸入的套件名稱應改為com. example.a2024ironman,如果沒有改成和build.gradle(APP)中的applicationId = "com.example.a2024ironman"一樣,在進行OAuth 2.0連結我們的Google帳戶時Logcat會報錯Sign-in failed, code=10錯誤代碼code=10代表 OAuth 2.0 客戶端設定錯誤,通常是由於 SHA-1 指紋或套件名稱配置錯誤,導致 Google API 無法驗證你的應用程式的身份。,昨天的內容我已經有修改過了,在這邊和大家勘誤一下,好的今天的內容就到這邊結束,感謝你能看到這邊,我們明天再見。


上一篇
Day11:連結GOOGLE行事曆(1)
下一篇
Day13:使用Accompanist建構行事曆功能,並同步Google行事曆上的資料
系列文
github裡永遠有一個還沒做的SideProject :用Kotlin來開發點沒用的酷東西30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言