Skip to content

Commit

Permalink
Added scheduler option to create diaries with Google Calendar events
Browse files Browse the repository at this point in the history
  • Loading branch information
hanjoongcho committed Jan 1, 2024
1 parent b00eec4 commit d60a82e
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 182 deletions.
171 changes: 23 additions & 148 deletions app/src/gms/java/me/blog/korn123/easydiary/activities/DevActivity.kt
Original file line number Diff line number Diff line change
@@ -1,43 +1,23 @@
package me.blog.korn123.easydiary.activities

import android.accounts.Account
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.tasks.Task
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.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException
import com.google.api.client.json.gson.GsonFactory
import com.google.api.services.calendar.Calendar
import com.google.api.services.calendar.CalendarScopes
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.blog.korn123.easydiary.R
import me.blog.korn123.easydiary.adapters.OptionItemAdapter
import me.blog.korn123.easydiary.databinding.DialogFontsBinding
import io.github.aafactory.commons.extensions.showAlertDialog
import me.blog.korn123.easydiary.enums.DialogMode
import me.blog.korn123.easydiary.extensions.makeSnackBar
import me.blog.korn123.easydiary.extensions.makeToast
import me.blog.korn123.easydiary.extensions.pauseLock
import me.blog.korn123.easydiary.extensions.updateAlertDialogWithIcon
import me.blog.korn123.easydiary.helper.AAF_TEST
import me.blog.korn123.easydiary.extensions.showAlertDialog
import me.blog.korn123.easydiary.helper.DriveServiceHelper
import me.blog.korn123.easydiary.helper.EasyDiaryDbHelper
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.initGoogleSignAccount
import me.blog.korn123.easydiary.models.Diary
import me.blog.korn123.easydiary.services.FullBackupService

class DevActivity : BaseDevActivity() {
Expand All @@ -47,7 +27,7 @@ class DevActivity : BaseDevActivity() {
*
***************************************************************************************************/
private lateinit var mRequestGoogleSignInLauncher: ActivityResultLauncher<Intent>
private lateinit var mRequestGoogleCalendarPermissions: ActivityResultLauncher<Intent>
private lateinit var mPermissionCallback: () -> Unit

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -70,21 +50,22 @@ class DevActivity : BaseDevActivity() {
}
}

mRequestGoogleCalendarPermissions = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
pauseLock()
when (it.resultCode == Activity.RESULT_OK && it.data != null) {
true -> {
mPermissionCallback.invoke()
}
false -> {
makeSnackBar("Google account verification failed.")
// GMSP
val gmsButtons = arrayOf(
Button(this).apply {
text = "Check Google SignAccount"
layoutParams = mFlexboxLayoutParams
setOnClickListener {
if (GoogleOAuthHelper.isValidGoogleSignAccount(this@DevActivity)) {
GoogleOAuthHelper.getGoogleSignAccount(this@DevActivity)?.run {
showAlertDialog(account!!.name, null, null, DialogMode.DEFAULT, false)
}
} else {
showAlertDialog("Sign account is invalid.", null)
}
}
}
}

mBinding.linearDevContainer.addView(
// GMSP
createBaseCardView("GMSP", null, Button(this).apply {
},
Button(this).apply {
text = "Full-Backup"
layoutParams = mFlexboxLayoutParams
setOnClickListener {
Expand All @@ -106,120 +87,14 @@ class DevActivity : BaseDevActivity() {
}
}
}
}, Button(this@DevActivity).apply {
text ="Google Calendar"
layoutParams = mFlexboxLayoutParams
setOnClickListener {
initGoogleSignAccount(this@DevActivity, mRequestGoogleSignInLauncher) { account ->
requestCalendarPermissions(account) {
val credential: GoogleAccountCredential =
GoogleAccountCredential.usingOAuth2(
this@DevActivity,
arrayListOf(CalendarScopes.CALENDAR)
).apply {
selectedAccount = account
}
val calendarService = Calendar.Builder(
AndroidHttp.newCompatibleTransport(),
GsonFactory(),
credential
)
.setApplicationName(getString(R.string.app_name))
.build()

fun fetchData(calendarId: String, nextPageToken: String?, total: Int = 0) {
var insertCount = 0
CoroutineScope(Dispatchers.IO).launch {
val result = if (nextPageToken == null) calendarService.events().list(calendarId).setMaxResults(2000).execute() else calendarService.events().list("[email protected]").setPageToken(nextPageToken).setMaxResults(2000).execute()
withContext(Dispatchers.Main) {
val descriptions = arrayListOf<String>()
result.items.forEachIndexed { index, item ->
Log.i(AAF_TEST, "$index ${item.start?.date} ${item.summary} ${item.start?.dateTime}")
descriptions.add(item.summary)
val timeMillis = if (item.start?.dateTime != null) item.start.dateTime.value else item.start?.date?.value ?: 0
if (EasyDiaryDbHelper.findDiary(item.summary)
.none { diary -> diary.currentTimeMillis == timeMillis }
) {
EasyDiaryDbHelper.insertDiary(
Diary(
BaseDiaryEditingActivity.DIARY_SEQUENCE_INIT,
timeMillis,
if (item.description != null) item.summary else "",
item.description ?: item.summary,
10022,
item?.start?.dateTime == null
)
)
insertCount++
}
}
if (result.nextPageToken != null) {
fetchData(calendarId, result.nextPageToken, total.plus(insertCount))
} else {
makeToast("Total: ${total.plus(insertCount)}")
}
}
}
}
fun fetchCalendarList() {
var alertDialog: AlertDialog? = null
CoroutineScope(Dispatchers.IO).launch {
val result = calendarService.calendarList().list().execute()
withContext(Dispatchers.Main) {
val builder = AlertDialog.Builder(this@DevActivity)
builder.setNegativeButton(getString(android.R.string.cancel), null)
val dialogFontsBinding = DialogFontsBinding.inflate(layoutInflater)
val calendarInfo = ArrayList<Map<String, String>>()
result.items.forEach { calendar ->
calendarInfo.add(mapOf(
"optionTitle" to calendar.summary,
"optionValue" to calendar.id
))
}
val optionItemAdapter = OptionItemAdapter(this@DevActivity, R.layout.item_check_label, calendarInfo, null, null)
dialogFontsBinding.run {
listFont.adapter = optionItemAdapter
listFont.setOnItemClickListener { parent, view, position, id ->
calendarInfo[position]["optionValue"]?.let {
fetchData(it, null)
alertDialog?.dismiss()
}
}
}
alertDialog = builder.create().apply {
updateAlertDialogWithIcon(DialogMode.INFO, this, null, dialogFontsBinding.root, "Sync Google Calendar")
}
}
}
}
fetchCalendarList()
}
}
}
})
}
)
mBinding.linearDevContainer.addView(
createBaseCardView("GMSP", null, *gmsButtons)
)
}

private lateinit var mPermissionCallback: () -> Unit
private fun requestCalendarPermissions(account: Account, permissionCallback: () -> Unit) {
mPermissionCallback = permissionCallback
val credential: GoogleAccountCredential =
GoogleAccountCredential.usingOAuth2(this, arrayListOf(CalendarScopes.CALENDAR))
.apply { selectedAccount = account }
val calendarService: Calendar = Calendar.Builder(AndroidHttp.newCompatibleTransport(), GsonFactory(), credential)
.setApplicationName(getString(R.string.app_name))
.build()
CoroutineScope(Dispatchers.IO).launch {
try {
calendarService.calendarList().list().execute()
mPermissionCallback.invoke()
} catch (e: UserRecoverableAuthIOException) {
withContext(Dispatchers.Main) {
mRequestGoogleCalendarPermissions.launch(e.intent)
}
}
}
}



/***************************************************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ import me.blog.korn123.easydiary.helper.DriveServiceHelper
import me.blog.korn123.easydiary.helper.EXTERNAL_STORAGE_PERMISSIONS
import me.blog.korn123.easydiary.helper.EasyDiaryDbHelper
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.calendarEventToDiary
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.callAccountCallback
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.getCalendarCredential
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.getCalendarService
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.initGoogleSignAccount
import me.blog.korn123.easydiary.helper.SETTING_FLAG_EXPORT_GOOGLE_DRIVE
import me.blog.korn123.easydiary.helper.SETTING_FLAG_EXPORT_PHOTO_GOOGLE_DRIVE
Expand Down Expand Up @@ -422,21 +425,8 @@ class SettingsGMSBackupFragment : androidx.fragment.app.Fragment() {
progressContainer.visibility = View.VISIBLE
initGoogleSignAccount(requireActivity(), mRequestGoogleSignInLauncher) { account ->
requestCalendarPermissions(account) {
val credential: GoogleAccountCredential =
GoogleAccountCredential.usingOAuth2(
requireActivity(),
arrayListOf(CalendarScopes.CALENDAR_READONLY, CalendarScopes.CALENDAR_EVENTS_READONLY)
).apply {
selectedAccount = account
}
val calendarService = Calendar.Builder(
AndroidHttp.newCompatibleTransport(),
GsonFactory(),
credential
)
.setApplicationName(getString(R.string.app_name))
.build()

val credential = getCalendarCredential(requireContext())
val calendarService = getCalendarService(requireContext(), credential)
fun fetchData(calendarId: String, nextPageToken: String?, total: Int = 0) {
var insertCount = 0
progressContainer.visibility = View.VISIBLE
Expand Down Expand Up @@ -469,25 +459,8 @@ class SettingsGMSBackupFragment : androidx.fragment.app.Fragment() {
result.items.forEachIndexed { index, item ->
Log.i(AAF_TEST, "$index ${item.start?.date} ${item.summary} ${item.start?.dateTime}")
// descriptions.add(item.summary)
val timeMillis = if (item.start?.dateTime != null) item.start.dateTime.value else item.start?.date?.value ?: 0
withContext(Dispatchers.Main) {
if (EasyDiaryDbHelper.findDiary(item.summary)
.none { diary -> diary.currentTimeMillis == timeMillis }
&& !(item.description == null && item.summary == null)) {
EasyDiaryDbHelper.insertDiary(
Diary(
BaseDiaryEditingActivity.DIARY_SEQUENCE_INIT,
timeMillis,
if (item.description != null) item.summary else "",
item.description ?: item.summary,
SYMBOL_GOOGLE_CALENDAR,
item?.start?.dateTime == null
).apply { isHoliday =
calendarId == "ko.south_korea#[email protected]"
}
)
insertCount++
}
insertCount += calendarEventToDiary(item, calendarId)
mBinding.syncGoogleCalendarProgress.setProgressCompat(index.div(result.items.size.toFloat()).times(100).toInt(), true)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,29 @@ package me.blog.korn123.easydiary.helper
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
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.client.util.DateTime
import com.google.api.services.calendar.CalendarScopes
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.blog.korn123.commons.utils.EasyDiaryUtils
import me.blog.korn123.easydiary.activities.BaseDiaryEditingActivity
import me.blog.korn123.easydiary.extensions.isScreenOn
import me.blog.korn123.easydiary.extensions.openNotification
import me.blog.korn123.easydiary.extensions.reExecuteGmsBackup
import me.blog.korn123.easydiary.extensions.scheduleNextAlarm
import me.blog.korn123.easydiary.fragments.SettingsScheduleFragment
import me.blog.korn123.easydiary.helper.GoogleOAuthHelper.Companion.fetchData
import me.blog.korn123.easydiary.models.Alarm
import me.blog.korn123.easydiary.models.Diary
import me.blog.korn123.easydiary.services.FullBackupService
import java.util.Calendar

class AlarmWorkExecutor(context: Context) : BaseAlarmWorkExecutor(context) {

Expand Down Expand Up @@ -37,6 +54,17 @@ class AlarmWorkExecutor(context: Context) : BaseAlarmWorkExecutor(context) {
} ?: reExecuteGmsBackup(alarm, "Authentication token is not valid.", AlarmWorkExecutor::class.java.name)

}
Alarm.WORK_MODE_CALENDAR_SCHEDULE_SYNC -> {
val calendarService =
GoogleOAuthHelper.getCalendarService(context, GoogleOAuthHelper.getCalendarCredential(context))
CoroutineScope(Dispatchers.IO).launch {
val result = calendarService.calendarList().list().execute()
result.items.forEach { calendar ->
fetchData(context, calendarService, calendar.id, null)
}
}
openNotification(alarm)
}
else -> {}
}
}
Expand Down
Loading

0 comments on commit d60a82e

Please sign in to comment.