今天我們來弄最後剩下的代辦元件,順便把它結合GOOGLE Task,讓我們的APP可以讀取上面的資料
我們回到之前啟用行事曆API服務的地方,和上次一樣,選擇API服務,並在搜尋找Google Tasks API
並啟用他
由於我們之前已經設定好了OAuth 2.0的憑證了,這次我們就不用再做一次,直接使用上次的平正要求TASK的權限就好。
啟用完api後我們要先去build.gradle(APP)
添加google Tasks API的依賴項,讓我們能夠在程式中使
用Google Tasks API
dependencies {
...
implementation("com.google.apis:google-api-services-tasks:v1-rev71-1.25.0")//Google Tasks API 依賴項
}
這時你如果直接執行程式碼可能會遇到下面的報錯
2 files found with path 'META-INF/INDEX.LIST'.
Adding a packaging block may help, please refer to
https://developer.android.com/reference/tools/gradle-api/8.6/com/android/build/api/dsl/Packaging
for more information
這是因為某些中有重複的文件,Android Studio會發生錯誤,遇到這種情況應該要去確認是甚麼依賴相沖,更換合適的api或確認不會衝突的版本,但我弄了一下午還是沒有解決,於是只能先讓Android Studio忽略重複項了,我們在build.gradle(APP)
添加下面的程式碼。
程式碼如下。
packaging {
resources {
excludes += "META-INF/DEPENDENCIES"
excludes += "META-INF/INDEX.LIST"
excludes += "META-INF/*.kotlin_module"
}
}
然後我們建立一個新的kt檔來處理task相關的程式碼,程式碼如下
package com.example.a2024ironman
import android.app.Activity
import android.util.Log
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.api.client.extensions.android.http.AndroidHttp
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
import com.google.api.client.json.gson.GsonFactory
import com.google.api.services.tasks.Tasks
import com.google.api.services.tasks.TasksScopes
import com.google.api.services.tasks.model.Task
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
class GoogleTask(private val activity: Activity) {
private var tasksService: Tasks? = null
// 設定 Google Tasks 服務
fun setupTasksService(account: GoogleSignInAccount?) {
val credential = GoogleAccountCredential.usingOAuth2(
activity, listOf(TasksScopes.TASKS)
)
credential.selectedAccount = account?.account
tasksService = Tasks.Builder(
AndroidHttp.newCompatibleTransport(),
GsonFactory.getDefaultInstance(),
credential
).setApplicationName("YourAppName").build()
}
// 獲取代辦事項
fun fetchTasks(
taskListId: String = "@default",
onTasksFetched: (List<Task>) -> Unit,
onError: (Exception) -> Unit
) {
CoroutineScope(Dispatchers.IO).launch {
try {
val tasks = tasksService?.tasks()?.list(taskListId)?.execute()
Log.d("GoogleTask", "Fetched tasks: ${tasks?.items?.size}")
tasks?.items?.forEach {
Log.d("GoogleTask", "Task: ${it.title}")
}
withContext(Dispatchers.Main) {
onTasksFetched(tasks?.items ?: emptyList())
}
} catch (e: Exception) {
Log.e("GoogleTask", "Error fetching tasks", e)
withContext(Dispatchers.Main) {
onError(e)
}
}
}
}
}
添加完程式碼後,我們回到之前的GoogleCalendarAuth.kt修改一下googleSignInClient
,在裡面添加com.google.android.gms.common.api.Scope(TasksScopes.TASKS)
讓我們再登入時請求task的權限。
private var googleSignInClient = GoogleSignIn.getClient(
activity,
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(
com.google.android.gms.common.api.Scope(CalendarScopes.CALENDAR),
com.google.android.gms.common.api.Scope(TasksScopes.TASKS)
)
.build()
)
最後我們修改主程式的程式碼,如下所示。
class MainActivity : ComponentActivity() {
private var googleTask: GoogleTask? = null // 新增變數
private var tasks by mutableStateOf<List<Task>>(emptyList()) // 儲存代辦事項
...//原有程式碼
googleCalendarAuth = GoogleCalendarAuth(this) { success ->
if (success) {
Log.d("MainActivity", "Google Calendar Auth successful")
// 開始同步 Google Calendar 事件
googleCalendarAuth?.fetchEvents(
onEventsFetched = { events ->
calendarEvents = events
Log.d("MainActivity", "Fetched ${events.size} events from Google Calendar")
},
onError = { error ->
Log.e("MainActivity", "Error fetching calendar events: ${error.message}")
}
)
// 初始化 Google Tasks 服務
googleTask = GoogleTask(this)
googleTask?.setupTasksService(GoogleSignIn.getLastSignedInAccount(this))
// 獲取 Google Tasks 代辦事項
googleTask?.fetchTasks(
onTasksFetched = { taskList ->
tasks = taskList
Log.d("MainActivity", "Fetched ${taskList.size} tasks from Google Tasks")
},
onError = { error ->
Log.e("MainActivity", "Error fetching tasks: ${error.message}")
}
)
} else {
Log.e("MainActivity", "Google Calendar Auth failed")
}
}
...//原有程式碼
fun CalendarLayout() {
...//原有程式碼
// 顯示代辦事項區塊
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
.padding(4.dp)
.background(MaterialTheme.colorScheme.surface),
contentAlignment = Alignment.Center
) {
if (tasks.isNotEmpty()) {
Column {
tasks.forEach { task ->
Text(
text = task.title ?: "無標題",
style = TextStyle(
fontSize = 16.sp,
color = MaterialTheme.colorScheme.onSurface
),
modifier = Modifier.padding(4.dp)
)
}
}
} else {
Text(
text = "無代辦事項",
style = TextStyle(
fontSize = 20.sp,
color = MaterialTheme.colorScheme.onSurface
)
)
}
}
}
...//原有程式碼
上面都修改完後,原本代辦事項的box就會出現我們google task的資料了,為了測試,我在我的task裡建立了兩個代辦事件
app裡的呈現效果如下
如果我們打勾完成了一個事件
在app中,該代辦事件就會消失,如下圖所示
今天初步完成了代辦元件結合GOOGLE Task的功能,明天來處理一下app的刷新,目前app刷新資料都要重新開啟app才會讀到最新的資料,這樣對於原本打算把它放在桌上當擺件的想法來說太麻煩了,每次都要重開,我還不如開google行事曆呢。那今天的內容就到這邊了,這幾天是颱風天,大家請注意安全不要去危險的地方,我們明天再見。