Andrew
Andrew

Reputation: 3

How to get updated information from a ContentProvider - Android Development

Android provides the framework to get on device information about calendars, that I can used to see the calendars and events that I've created in Google Calendar.

    fun getUpcomingEvents(calendarId: Long): List<CalendarEvent> {
        val eventsList = mutableListOf<CalendarEvent>()

        val now = Calendar.getInstance()
        val next24Hours = Calendar.getInstance().apply {
            add(Calendar.HOUR_OF_DAY, 24)
        }

        val startMillis = now.timeInMillis
        val endMillis = next24Hours.timeInMillis

        val selection = "${CalendarContract.Events.CALENDAR_ID} = ? AND " +
                "${CalendarContract.Events.DTSTART} >= ? AND " +
                "${CalendarContract.Events.DTEND} <= ?"
        val selectionArgs = arrayOf(calendarId.toString(), startMillis.toString(), endMillis.toString())

        val projection = arrayOf(
            CalendarContract.Events._ID,
            CalendarContract.Events.TITLE,
            CalendarContract.Events.DTSTART,
            CalendarContract.Events.DTEND,
            // Add other fields you want to retrieve
        )

        val eventsUri: Uri = CalendarContract.Events.CONTENT_URI
        ContentResolver.requestSync(
            getCalendarSyncAccount(), // Replace with the relevant account
            CalendarContract.AUTHORITY,
            Bundle().apply {
                putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
                putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
            }
        )
        val cursor: Cursor? = context.contentResolver.query(eventsUri, projection, selection, selectionArgs, null)
        cursor?.use {
            while (it.moveToNext()) {
                val eventIdIndex = it.getColumnIndex(CalendarContract.Events._ID)
                val titleIndex = it.getColumnIndex(CalendarContract.Events.TITLE)
                val dtstartIndex = it.getColumnIndex(CalendarContract.Events.DTSTART)
                val dtendIndex = it.getColumnIndex(CalendarContract.Events.DTEND)
                // Get indices for other fields

                val eventId = it.getLong(eventIdIndex)
                val title = it.getString(titleIndex)
                val dtstart = it.getLong(dtstartIndex)
                val dtend = it.getLong(dtendIndex)
                // Retrieve values for other fields

                eventsList.add(CalendarEvent(eventId, title, dtstart, dtend))
            }
        }

        return eventsList
    }

This works a treat if I provide a hardcoded time-frame in the past. But the information will only be as up-to-date as the last time I opened the Google Calendar app. The ContentResolver.requestSync(...) doesn't seem to have an effect. Not directly after I call it, not two days later. Only if I manually update the info by opening the Gcal app. But I don't think I have the rest of the correct boiler-plate for this sync to work.

What I require is the up-to-date calendar information. The Content Provider docs are woefully incomplete in this regard, only really mentioning something about sync adapters as a footnote. Looking for more info, it sounds like what I want, but again there's a big question mark as to what you actually run under onPerformSync:

override fun onPerformSync(
        account: Account,
        extras: Bundle,
        authority: String,
        provider: ContentProviderClient,
        syncResult: SyncResult
) {
    /*
     * Put the data transfer code here.
     */
}

Even in other tutorials I find online, it always seems entirely overcomplicated for simply refreshing data I already have access to and overly generic not really explaining what's required for my use case.

Are these SyncAdapters really the right tool for my job? If so, what kind of logic to I need to run to actually get Google Calendar information synced up with the on device info, reliably?

Upvotes: 0

Views: 42

Answers (0)

Related Questions