diff options
author | Ricki Hirner <hirner@bitfire.at> | 2022-01-26 16:16:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-26 16:16:28 +0300 |
commit | f340ca7ff62b76dfed6ac07112d40c749072cc51 (patch) | |
tree | 2d0ce27636717097b1318a5aaab12652adb3d829 | |
parent | 16eba01bb255b8fbd3957a3461c3a62ee3374e45 (diff) |
Use Uri.asSyncAdapter() instead of syncAdapterUri() in various classes (closes #10)
9 files changed, 135 insertions, 89 deletions
diff --git a/src/androidTest/java/at/bitfire/ical4android/AndroidCalendarTest.kt b/src/androidTest/java/at/bitfire/ical4android/AndroidCalendarTest.kt index d754f9d..3af1bb8 100644 --- a/src/androidTest/java/at/bitfire/ical4android/AndroidCalendarTest.kt +++ b/src/androidTest/java/at/bitfire/ical4android/AndroidCalendarTest.kt @@ -15,6 +15,7 @@ import android.provider.CalendarContract.Colors import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat +import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import at.bitfire.ical4android.impl.TestCalendar import at.bitfire.ical4android.impl.TestEvent import net.fortuna.ical4j.model.property.DtEnd @@ -110,7 +111,7 @@ class AndroidCalendarTest { } private fun countColors(account: Account): Int { - val uri = AndroidCalendar.syncAdapterURI(Colors.CONTENT_URI, testAccount) + val uri = Colors.CONTENT_URI.asSyncAdapter(testAccount) provider.query(uri, null, null, null, null)!!.use { cursor -> cursor.moveToNext() return cursor.count diff --git a/src/androidTest/java/at/bitfire/ical4android/AndroidEventTest.kt b/src/androidTest/java/at/bitfire/ical4android/AndroidEventTest.kt index 00ac8ce..d9839ae 100644 --- a/src/androidTest/java/at/bitfire/ical4android/AndroidEventTest.kt +++ b/src/androidTest/java/at/bitfire/ical4android/AndroidEventTest.kt @@ -15,6 +15,7 @@ import androidx.test.filters.LargeTest import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat +import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import at.bitfire.ical4android.impl.TestCalendar import at.bitfire.ical4android.impl.TestEvent import at.bitfire.ical4android.util.AndroidTimeUtils @@ -118,7 +119,7 @@ class AndroidEventTest { private fun firstExtendedProperty(values: ContentValues, mimeType: String): String? { val id = values.getAsInteger(Events._ID) - provider.query(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI), arrayOf(ExtendedProperties.VALUE), + provider.query(ExtendedProperties.CONTENT_URI.asSyncAdapter(testAccount), arrayOf(ExtendedProperties.VALUE), "${ExtendedProperties.EVENT_ID}=?", arrayOf(id.toString()), null)?.use { if (it.moveToNext()) return it.getString(0) @@ -697,7 +698,7 @@ class AndroidEventTest { private fun firstReminder(row: ContentValues): ContentValues? { val id = row.getAsInteger(Events._ID) - provider.query(calendar.syncAdapterURI(Reminders.CONTENT_URI), null, + provider.query(Reminders.CONTENT_URI.asSyncAdapter(testAccount), null, "${Reminders.EVENT_ID}=?", arrayOf(id.toString()), null)?.use { cursor -> if (cursor.moveToNext()) { val subRow = ContentValues(cursor.count) @@ -883,7 +884,7 @@ class AndroidEventTest { private fun firstAttendee(row: ContentValues): ContentValues? { val id = row.getAsInteger(Events._ID) - provider.query(calendar.syncAdapterURI(Attendees.CONTENT_URI), null, + provider.query(Attendees.CONTENT_URI.asSyncAdapter(testAccount), null, "${Attendees.EVENT_ID}=?", arrayOf(id.toString()), null)?.use { cursor -> if (cursor.moveToNext()) { val subRow = ContentValues(cursor.count) @@ -1262,7 +1263,7 @@ class AndroidEventTest { private fun firstException(values: ContentValues): ContentValues? { val id = values.getAsInteger(Events._ID) - provider.query(calendar.syncAdapterURI(Events.CONTENT_URI), null, + provider.query(Events.CONTENT_URI.asSyncAdapter(testAccount), null, "${Events.ORIGINAL_ID}=?", arrayOf(id.toString()), null)?.use { cursor -> if (cursor.moveToNext()) { val result = ContentValues(cursor.count) @@ -1394,7 +1395,10 @@ class AndroidEventTest { valuesBuilder(values) Ical4Android.log.info("Inserting test event: $values") val uri = provider.insert( - if (asSyncAdapter) destinationCalendar.syncAdapterURI(Events.CONTENT_URI) else Events.CONTENT_URI, + if (asSyncAdapter) + Events.CONTENT_URI.asSyncAdapter(testAccount) + else + Events.CONTENT_URI, values)!! val id = ContentUris.parseId(uri) @@ -1566,7 +1570,7 @@ class AndroidEventTest { urlValues.put(ExtendedProperties.EVENT_ID, id) urlValues.put(ExtendedProperties.NAME, AndroidEvent.MIMETYPE_URL) urlValues.put(ExtendedProperties.VALUE, "https://example.com") - provider.insert(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI), urlValues) + provider.insert(ExtendedProperties.CONTENT_URI.asSyncAdapter(testAccount), urlValues) }, valuesBuilder = {}).let { result -> assertEquals(URI("https://example.com"), result.url) } @@ -1675,7 +1679,7 @@ class AndroidEventTest { populateEvent(true, valuesBuilder = { put(Events.ORGANIZER, "organizer@example.com") }, insertCallback = { id -> - provider.insert(calendar.syncAdapterURI(Attendees.CONTENT_URI), ContentValues().apply { + provider.insert(Attendees.CONTENT_URI.asSyncAdapter(testAccount), ContentValues().apply { put(Attendees.EVENT_ID, id) put(Attendees.ATTENDEE_EMAIL, "organizer@example.com") put(Attendees.ATTENDEE_TYPE, Attendees.RELATIONSHIP_ORGANIZER) @@ -1717,7 +1721,7 @@ class AndroidEventTest { populateEvent(true, valuesBuilder = { put(Events.ACCESS_LEVEL, Events.ACCESS_DEFAULT) }, insertCallback = { id -> - provider.insert(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI), ContentValues().apply { + provider.insert(ExtendedProperties.CONTENT_URI.asSyncAdapter(testAccount), ContentValues().apply { put(ExtendedProperties.EVENT_ID, id) put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(Clazz.CONFIDENTIAL)) @@ -1741,7 +1745,7 @@ class AndroidEventTest { populateEvent(true, valuesBuilder = { put(Events.ACCESS_LEVEL, Events.ACCESS_DEFAULT) }, insertCallback = { id -> - provider.insert(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI), ContentValues().apply { + provider.insert(ExtendedProperties.CONTENT_URI.asSyncAdapter(testAccount), ContentValues().apply { put(ExtendedProperties.EVENT_ID, id) put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(Clazz("TOP-SECRET"))) @@ -1766,7 +1770,7 @@ class AndroidEventTest { reminderValues.put(Reminders.EVENT_ID, id) builder(reminderValues) Ical4Android.log.info("Inserting test reminder: $reminderValues") - provider.insert(destinationCalendar.syncAdapterURI(Reminders.CONTENT_URI), reminderValues) + provider.insert(Reminders.CONTENT_URI.asSyncAdapter(testAccount), reminderValues) }).let { result -> return result.alarms.firstOrNull() } @@ -1843,7 +1847,7 @@ class AndroidEventTest { attendeeValues.put(Attendees.EVENT_ID, id) builder(attendeeValues) Ical4Android.log.info("Inserting test attendee: $attendeeValues") - provider.insert(calendar.syncAdapterURI(Attendees.CONTENT_URI), attendeeValues) + provider.insert(Attendees.CONTENT_URI.asSyncAdapter(testAccount), attendeeValues) }).let { result -> return result.attendees.firstOrNull() } @@ -2082,7 +2086,7 @@ class AndroidEventTest { values.put(ExtendedProperties.EVENT_ID, id) values.put(ExtendedProperties.NAME, UnknownProperty.CONTENT_ITEM_TYPE) values.put(ExtendedProperties.VALUE, UnknownProperty.toJsonString(unknownProperty)) - provider.insert(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI), values) + provider.insert(ExtendedProperties.CONTENT_URI.asSyncAdapter(testAccount), values) }).unknownProperties.first assertEquals("X-NAME", result.name) assertEquals("en", result.getParameter<Language>(Parameter.LANGUAGE).value) @@ -2095,7 +2099,7 @@ class AndroidEventTest { val exceptionValues = ContentValues() exceptionValues.put(Events.CALENDAR_ID, calendar.id) exceptionBuilder(exceptionValues) - provider.insert(calendar.syncAdapterURI(Events.CONTENT_URI), exceptionValues) + provider.insert(Events.CONTENT_URI.asSyncAdapter(testAccount), exceptionValues) }) @Test diff --git a/src/androidTest/java/at/bitfire/ical4android/AospTest.kt b/src/androidTest/java/at/bitfire/ical4android/AospTest.kt index 21cbf86..bf18803 100644 --- a/src/androidTest/java/at/bitfire/ical4android/AospTest.kt +++ b/src/androidTest/java/at/bitfire/ical4android/AospTest.kt @@ -40,6 +40,8 @@ class AospTest { fun prepare() { calendarUri = provider.insert( CalendarContract.Calendars.CONTENT_URI.asSyncAdapter(), ContentValues().apply { + put(CalendarContract.Calendars.ACCOUNT_NAME, testAccount.name) + put(CalendarContract.Calendars.ACCOUNT_TYPE, testAccount.type) put(CalendarContract.Calendars.NAME, "Test Calendar") } )!! diff --git a/src/androidTest/java/at/bitfire/ical4android/MiscUtilsAndroidTest.kt b/src/androidTest/java/at/bitfire/ical4android/MiscUtilsAndroidTest.kt index 67016e1..d6f7e40 100644 --- a/src/androidTest/java/at/bitfire/ical4android/MiscUtilsAndroidTest.kt +++ b/src/androidTest/java/at/bitfire/ical4android/MiscUtilsAndroidTest.kt @@ -4,10 +4,13 @@ package at.bitfire.ical4android +import android.accounts.Account import android.content.ContentValues import android.database.MatrixCursor +import android.net.Uri import androidx.test.filters.SmallTest import at.bitfire.ical4android.MiscUtils.CursorHelper.toValues +import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Test @@ -42,4 +45,15 @@ class MiscUtilsAndroidTest { Assert.assertNull(values.get("key3")) } + + @Test + fun testUriHelper_asSyncAdapter() { + val account = Account("testName", "testType") + val baseUri = Uri.parse("test://example.com/") + assertEquals( + Uri.parse("$baseUri?account_name=testName&account_type=testType&caller_is_syncadapter=true"), + baseUri.asSyncAdapter(account) + ) + } + } diff --git a/src/main/java/at/bitfire/ical4android/AndroidCalendar.kt b/src/main/java/at/bitfire/ical4android/AndroidCalendar.kt index 5736bde..398da20 100644 --- a/src/main/java/at/bitfire/ical4android/AndroidCalendar.kt +++ b/src/main/java/at/bitfire/ical4android/AndroidCalendar.kt @@ -11,6 +11,7 @@ import android.content.ContentValues import android.net.Uri import android.provider.CalendarContract.* import at.bitfire.ical4android.MiscUtils.CursorHelper.toValues +import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import java.io.FileNotFoundException import java.util.* import java.util.logging.Level @@ -58,12 +59,12 @@ abstract class AndroidCalendar<out T: AndroidEvent>( info.putAll(calendarBaseValues) Ical4Android.log.info("Creating local calendar: $info") - return provider.insert(syncAdapterURI(Calendars.CONTENT_URI, account), info) ?: + return provider.insert(Calendars.CONTENT_URI.asSyncAdapter(account), info) ?: throw Exception("Couldn't create calendar: provider returned null") } fun insertColors(provider: ContentProviderClient, account: Account) { - provider.query(syncAdapterURI(Colors.CONTENT_URI, account), arrayOf(Colors.COLOR_KEY), null, null, null)?.use { cursor -> + provider.query(Colors.CONTENT_URI.asSyncAdapter(account), arrayOf(Colors.COLOR_KEY), null, null, null)?.use { cursor -> if (cursor.count == Css3Color.values().size) // colors already inserted and up to date return @@ -78,7 +79,7 @@ abstract class AndroidCalendar<out T: AndroidEvent>( values.put(Colors.COLOR_KEY, color.name) values.put(Colors.COLOR, color.argb) try { - provider.insert(syncAdapterURI(Colors.CONTENT_URI, account), values) + provider.insert(Colors.CONTENT_URI.asSyncAdapter(account), values) } catch(e: Exception) { Ical4Android.log.log(Level.WARNING, "Couldn't insert event color: ${color.name}", e) } @@ -94,23 +95,23 @@ abstract class AndroidCalendar<out T: AndroidEvent>( 2) account_type and account_name can't be specified in selection (causes SQLiteException) WORKAROUND: unassign event colors for each calendar */ - provider.query(syncAdapterURI(Calendars.CONTENT_URI, account), arrayOf(Calendars._ID), null, null, null)?.use { cursor -> + provider.query(Calendars.CONTENT_URI.asSyncAdapter(account), arrayOf(Calendars._ID), null, null, null)?.use { cursor -> while (cursor.moveToNext()) { val calId = cursor.getLong(0) val values = ContentValues(1) values.putNull(Events.EVENT_COLOR_KEY) - provider.update(syncAdapterURI(Events.CONTENT_URI, account), values, + provider.update(Events.CONTENT_URI.asSyncAdapter(account), values, "${Events.EVENT_COLOR_KEY} IS NOT NULL AND ${Events.CALENDAR_ID}=?", arrayOf(calId.toString())) } } // remove color entries - provider.delete(syncAdapterURI(Colors.CONTENT_URI, account), null, null) + provider.delete(Colors.CONTENT_URI.asSyncAdapter(account), null, null) } fun<T: AndroidCalendar<AndroidEvent>> findByID(account: Account, provider: ContentProviderClient, factory: AndroidCalendarFactory<T>, id: Long): T { val iterCalendars = CalendarEntity.newEntityIterator( - provider.query(syncAdapterURI(ContentUris.withAppendedId(CalendarEntity.CONTENT_URI, id), account), null, null, null, null) + provider.query(ContentUris.withAppendedId(CalendarEntity.CONTENT_URI, id).asSyncAdapter(account), null, null, null, null) ) try { if (iterCalendars.hasNext()) { @@ -127,7 +128,7 @@ abstract class AndroidCalendar<out T: AndroidEvent>( fun<T: AndroidCalendar<AndroidEvent>> find(account: Account, provider: ContentProviderClient, factory: AndroidCalendarFactory<T>, where: String?, whereArgs: Array<String>?): List<T> { val iterCalendars = CalendarEntity.newEntityIterator( - provider.query(syncAdapterURI(CalendarEntity.CONTENT_URI, account), null, where, whereArgs, null) + provider.query(CalendarEntity.CONTENT_URI.asSyncAdapter(account), null, where, whereArgs, null) ) try { val calendars = LinkedList<T>() @@ -143,11 +144,6 @@ abstract class AndroidCalendar<out T: AndroidEvent>( } } - fun syncAdapterURI(uri: Uri, account: Account) = uri.buildUpon() - .appendQueryParameter(Calendars.ACCOUNT_NAME, account.name) - .appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type) - .appendQueryParameter(CALLER_IS_SYNCADAPTER, "true") - .build()!! } var name: String? = null @@ -189,7 +185,7 @@ abstract class AndroidCalendar<out T: AndroidEvent>( val whereArgs = (_whereArgs ?: arrayOf()) + id.toString() val events = LinkedList<T>() - provider.query(eventsSyncURI(), null, where, whereArgs, null)?.use { cursor -> + provider.query(Events.CONTENT_URI.asSyncAdapter(account), null, where, whereArgs, null)?.use { cursor -> while (cursor.moveToNext()) events += eventFactory.fromProvider(this, cursor.toValues()) } @@ -200,16 +196,6 @@ abstract class AndroidCalendar<out T: AndroidEvent>( ?: throw FileNotFoundException() - fun syncAdapterURI(uri: Uri) = uri.buildUpon() - .appendQueryParameter(CALLER_IS_SYNCADAPTER, "true") - .appendQueryParameter(Calendars.ACCOUNT_NAME, account.name) - .appendQueryParameter(Calendars.ACCOUNT_TYPE, account.type) - .build()!! - - fun calendarSyncURI() = syncAdapterURI(ContentUris.withAppendedId(Calendars.CONTENT_URI, id)) - fun eventsSyncURI() = syncAdapterURI(Events.CONTENT_URI) - - fun attendeesSyncUri() = syncAdapterURI(Attendees.CONTENT_URI) - fun remindersSyncUri() = syncAdapterURI(Reminders.CONTENT_URI) + fun calendarSyncURI() = ContentUris.withAppendedId(Calendars.CONTENT_URI, id).asSyncAdapter(account) } diff --git a/src/main/java/at/bitfire/ical4android/AndroidEvent.kt b/src/main/java/at/bitfire/ical4android/AndroidEvent.kt index ec5981b..3005d30 100644 --- a/src/main/java/at/bitfire/ical4android/AndroidEvent.kt +++ b/src/main/java/at/bitfire/ical4android/AndroidEvent.kt @@ -15,6 +15,7 @@ import android.util.Patterns import androidx.annotation.CallSuper import at.bitfire.ical4android.BatchOperation.CpoBuilder import at.bitfire.ical4android.MiscUtils.CursorHelper.toValues +import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import at.bitfire.ical4android.util.AndroidTimeUtils import at.bitfire.ical4android.util.TimeApiExtensions import at.bitfire.ical4android.util.TimeApiExtensions.requireZoneId @@ -113,7 +114,7 @@ abstract class AndroidEvent( try { iterEvents = EventsEntity.newEntityIterator( calendar.provider.query( - calendar.syncAdapterURI(ContentUris.withAppendedId(EventsEntity.CONTENT_URI, id)), + ContentUris.withAppendedId(EventsEntity.CONTENT_URI, id).asSyncAdapter(calendar.account), null, null, null, null), calendar.provider ) @@ -448,7 +449,7 @@ abstract class AndroidEvent( requireNotNull(id) val event = requireNotNull(event) - calendar.provider.query(calendar.syncAdapterURI(Events.CONTENT_URI), + calendar.provider.query(Events.CONTENT_URI.asSyncAdapter(calendar.account), null, Events.ORIGINAL_ID + "=?", arrayOf(id.toString()), null)?.use { c -> while (c.moveToNext()) { @@ -529,7 +530,7 @@ abstract class AndroidEvent( val event = requireNotNull(event) val builder = if (id == null) - CpoBuilder.newInsert(calendar.syncAdapterURI(eventsSyncURI())) + CpoBuilder.newInsert(Events.CONTENT_URI.asSyncAdapter(calendar.account)) else CpoBuilder.newUpdate(eventSyncURI()) @@ -585,7 +586,7 @@ abstract class AndroidEvent( } val exBuilder = CpoBuilder - .newInsert(calendar.syncAdapterURI(eventsSyncURI())) + .newInsert(Events.CONTENT_URI.asSyncAdapter(calendar.account)) .withEventId(Events.ORIGINAL_ID, idxEvent) buildEvent(exception, exBuilder) @@ -655,13 +656,13 @@ abstract class AndroidEvent( val batch = BatchOperation(calendar.provider) deleteExceptions(batch) batch .enqueue(CpoBuilder - .newDelete(calendar.remindersSyncUri()) + .newDelete(Reminders.CONTENT_URI.asSyncAdapter(calendar.account)) .withSelection("${Reminders.EVENT_ID}=?", arrayOf(existingId.toString()))) .enqueue(CpoBuilder - .newDelete(calendar.attendeesSyncUri()) + .newDelete(Attendees.CONTENT_URI.asSyncAdapter(calendar.account)) .withSelection("${Attendees.EVENT_ID}=?", arrayOf(existingId.toString()))) .enqueue(CpoBuilder - .newDelete(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI)) + .newDelete(ExtendedProperties.CONTENT_URI.asSyncAdapter(calendar.account)) .withSelection( "${ExtendedProperties.EVENT_ID}=? AND ${ExtendedProperties.NAME} IN (?,?,?)", arrayOf(existingId.toString(), MIMETYPE_CATEGORIES, MIMETYPE_URL, UnknownProperty.CONTENT_ITEM_TYPE) @@ -697,7 +698,7 @@ abstract class AndroidEvent( protected fun deleteExceptions(batch: BatchOperation) { val existingId = requireNotNull(id) batch.enqueue(CpoBuilder - .newDelete(eventsSyncURI()) + .newDelete(Events.CONTENT_URI.asSyncAdapter(calendar.account)) .withSelection("${Events.ORIGINAL_ID}=?", arrayOf(existingId.toString()))) } @@ -857,7 +858,7 @@ abstract class AndroidEvent( builder.withValue(Events.EVENT_COLOR_KEY, event.color?.let { color -> val colorName = color.name // set event color (if it's available for this account) - calendar.provider.query(calendar.syncAdapterURI(Colors.CONTENT_URI), arrayOf(Colors.COLOR_KEY), + calendar.provider.query(Colors.CONTENT_URI.asSyncAdapter(calendar.account), arrayOf(Colors.COLOR_KEY), "${Colors.COLOR_KEY}=? AND ${Colors.COLOR_TYPE}=${Colors.TYPE_EVENT}", arrayOf(colorName), null)?.use { cursor -> if (cursor.moveToNext()) return@let colorName @@ -907,7 +908,7 @@ abstract class AndroidEvent( protected open fun insertReminder(batch: BatchOperation, idxEvent: Int?, alarm: VAlarm) { val builder = CpoBuilder - .newInsert(calendar.remindersSyncUri()) + .newInsert(Reminders.CONTENT_URI.asSyncAdapter(calendar.account)) .withEventId(Reminders.EVENT_ID, idxEvent) val method = when (alarm.action?.value?.uppercase(Locale.ROOT)) { @@ -929,7 +930,7 @@ abstract class AndroidEvent( protected open fun insertAttendee(batch: BatchOperation, idxEvent: Int?, attendee: Attendee, organizer: String) { val builder = CpoBuilder - .newInsert(calendar.syncAdapterURI(Attendees.CONTENT_URI)) + .newInsert(Attendees.CONTENT_URI.asSyncAdapter(calendar.account)) .withEventId(Attendees.EVENT_ID, idxEvent) val member = attendee.calAddress @@ -966,7 +967,7 @@ abstract class AndroidEvent( protected open fun insertExtendedProperty(batch: BatchOperation, idxEvent: Int?, mimeType: String, value: String) { val builder = CpoBuilder - .newInsert(calendar.syncAdapterURI(ExtendedProperties.CONTENT_URI)) + .newInsert(ExtendedProperties.CONTENT_URI.asSyncAdapter(calendar.account)) .withEventId(ExtendedProperties.EVENT_ID, idxEvent) .withValue(ExtendedProperties.NAME, mimeType) .withValue(ExtendedProperties.VALUE, value) @@ -1019,11 +1020,9 @@ abstract class AndroidEvent( } - protected fun eventsSyncURI() = calendar.syncAdapterURI(Events.CONTENT_URI) - protected fun eventSyncURI(): Uri { val id = requireNotNull(id) - return calendar.syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)) + return ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(calendar.account) } override fun toString() = MiscUtils.reflectionToString(this) diff --git a/src/main/java/at/bitfire/ical4android/AndroidTaskList.kt b/src/main/java/at/bitfire/ical4android/AndroidTaskList.kt index 4cd784b..8439d80 100644 --- a/src/main/java/at/bitfire/ical4android/AndroidTaskList.kt +++ b/src/main/java/at/bitfire/ical4android/AndroidTaskList.kt @@ -9,6 +9,7 @@ import android.content.ContentUris import android.content.ContentValues import android.net.Uri import at.bitfire.ical4android.MiscUtils.CursorHelper.toValues +import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter import org.dmfs.tasks.contract.TaskContract import org.dmfs.tasks.contract.TaskContract.Property.Relation import org.dmfs.tasks.contract.TaskContract.TaskLists @@ -22,14 +23,14 @@ import java.util.* * Communicates with third-party content providers to store the tasks. * Currently, only the OpenTasks tasks provider (org.dmfs.provider.tasks) is supported. */ -abstract class AndroidTaskList<out T: AndroidTask>( - val account: Account, - val provider: TaskProvider, - val taskFactory: AndroidTaskFactory<T>, - val id: Long +abstract class AndroidTaskList<out T : AndroidTask>( + val account: Account, + val provider: TaskProvider, + val taskFactory: AndroidTaskFactory<T>, + val id: Long ) { - companion object { + companion object { fun create(account: Account, provider: TaskProvider, info: ContentValues): Uri { info.put(TaskContract.ACCOUNT_NAME, account.name) @@ -37,12 +38,23 @@ abstract class AndroidTaskList<out T: AndroidTask>( info.put(TaskLists.ACCESS_LEVEL, 0) Ical4Android.log.info("Creating local task list: $info") - return provider.client.insert(TaskProvider.syncAdapterUri(provider.taskListsUri(), account), info) ?: - throw CalendarStorageException("Couldn't create task list (empty result from provider)") + return provider.client.insert(provider.taskListsUri().asSyncAdapter(account), info) + ?: throw CalendarStorageException("Couldn't create task list (empty result from provider)") } - fun<T: AndroidTaskList<AndroidTask>> findByID(account: Account, provider: TaskProvider, factory: AndroidTaskListFactory<T>, id: Long): T { - provider.client.query(TaskProvider.syncAdapterUri(ContentUris.withAppendedId(provider.taskListsUri(), id), account), null, null, null, null)?.use { cursor -> + fun <T : AndroidTaskList<AndroidTask>> findByID( + account: Account, + provider: TaskProvider, + factory: AndroidTaskListFactory<T>, + id: Long + ): T { + provider.client.query( + ContentUris.withAppendedId(provider.taskListsUri(), id).asSyncAdapter(account), + null, + null, + null, + null + )?.use { cursor -> if (cursor.moveToNext()) { val taskList = factory.newInstance(account, provider, id) taskList.populate(cursor.toValues()) @@ -52,12 +64,25 @@ abstract class AndroidTaskList<out T: AndroidTask>( throw FileNotFoundException() } - fun<T: AndroidTaskList<AndroidTask>> find(account: Account, provider: TaskProvider, factory: AndroidTaskListFactory<T>, where: String?, whereArgs: Array<String>?): List<T> { + fun <T : AndroidTaskList<AndroidTask>> find( + account: Account, + provider: TaskProvider, + factory: AndroidTaskListFactory<T>, + where: String?, + whereArgs: Array<String>? + ): List<T> { val taskLists = LinkedList<T>() - provider.client.query(TaskProvider.syncAdapterUri(provider.taskListsUri(), account), null, where, whereArgs, null)?.use { cursor -> + provider.client.query( + provider.taskListsUri().asSyncAdapter(account), + null, + where, + whereArgs, + null + )?.use { cursor -> while (cursor.moveToNext()) { val values = cursor.toValues() - val taskList = factory.newInstance(account, provider, values.getAsLong(TaskLists._ID)) + val taskList = + factory.newInstance(account, provider, values.getAsLong(TaskLists._ID)) taskList.populate(values) taskLists += taskList } @@ -104,19 +129,22 @@ abstract class AndroidTaskList<out T: AndroidTask>( * so that missing [Tasks.PARENT_ID] fields are updated. * * @return number of touched [Relation] rows - */ + */ fun touchRelations(): Int { Ical4Android.log.fine("Touching relations to set parent_id") val batchOperation = BatchOperation(provider.client) - provider.client.query(tasksSyncUri(true), null, - "${Tasks.LIST_ID}=? AND ${Tasks.PARENT_ID} IS NULL AND ${Relation.MIMETYPE}=? AND ${Relation.RELATED_ID} IS NOT NULL", - arrayOf(id.toString(), Relation.CONTENT_ITEM_TYPE), - null, null)?.use { cursor -> + provider.client.query( + tasksSyncUri(true), null, + "${Tasks.LIST_ID}=? AND ${Tasks.PARENT_ID} IS NULL AND ${Relation.MIMETYPE}=? AND ${Relation.RELATED_ID} IS NOT NULL", + arrayOf(id.toString(), Relation.CONTENT_ITEM_TYPE), + null, null + )?.use { cursor -> while (cursor.moveToNext()) { val values = cursor.toValues() val id = values.getAsLong(Relation.PROPERTY_ID) val propertyContentUri = ContentUris.withAppendedId(tasksPropertiesSyncUri(), id) - batchOperation.enqueue(BatchOperation.CpoBuilder + batchOperation.enqueue( + BatchOperation.CpoBuilder .newUpdate(propertyContentUri) .withValue(Relation.RELATED_ID, values.getAsLong(Relation.RELATED_ID)) ) @@ -141,9 +169,10 @@ abstract class AndroidTaskList<out T: AndroidTask>( val tasks = LinkedList<T>() provider.client.query( - tasksSyncUri(), - null, - where, whereArgs, null)?.use { cursor -> + tasksSyncUri(), + null, + where, whereArgs, null + )?.use { cursor -> while (cursor.moveToNext()) tasks += taskFactory.fromProvider(this, cursor.toValues()) } @@ -151,19 +180,22 @@ abstract class AndroidTaskList<out T: AndroidTask>( } fun findById(id: Long) = queryTasks("${Tasks._ID}=?", arrayOf(id.toString())).firstOrNull() - ?: throw FileNotFoundException() + ?: throw FileNotFoundException() - fun taskListSyncUri() = TaskProvider.syncAdapterUri(ContentUris.withAppendedId(provider.taskListsUri(), id), account) + fun taskListSyncUri() = + ContentUris.withAppendedId(provider.taskListsUri(), id).asSyncAdapter(account) + fun tasksSyncUri(loadProperties: Boolean = false): Uri { - val uri = TaskProvider.syncAdapterUri(provider.tasksUri(), account) + val uri = provider.tasksUri().asSyncAdapter(account) return if (loadProperties) - uri .buildUpon() - .appendQueryParameter(TaskContract.LOAD_PROPERTIES, "1") - .build() + uri.buildUpon() + .appendQueryParameter(TaskContract.LOAD_PROPERTIES, "1") + .build() else uri } - fun tasksPropertiesSyncUri() = TaskProvider.syncAdapterUri(provider.propertiesUri(), account) + + fun tasksPropertiesSyncUri() = provider.propertiesUri().asSyncAdapter(account) } diff --git a/src/main/java/at/bitfire/ical4android/MiscUtils.kt b/src/main/java/at/bitfire/ical4android/MiscUtils.kt index 2b0e57d..0c76624 100644 --- a/src/main/java/at/bitfire/ical4android/MiscUtils.kt +++ b/src/main/java/at/bitfire/ical4android/MiscUtils.kt @@ -4,11 +4,14 @@ package at.bitfire.ical4android +import android.accounts.Account import android.content.ContentProviderClient import android.content.ContentValues import android.database.Cursor import android.database.DatabaseUtils +import android.net.Uri import android.os.Build +import android.provider.CalendarContract import org.apache.commons.lang3.StringUtils import java.lang.reflect.Modifier import java.util.* @@ -91,4 +94,15 @@ object MiscUtils { } + + object UriHelper { + + fun Uri.asSyncAdapter(account: Account): Uri = buildUpon() + .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account.name) + .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, account.type) + .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") + .build() + + } + }
\ No newline at end of file diff --git a/src/main/java/at/bitfire/ical4android/TaskProvider.kt b/src/main/java/at/bitfire/ical4android/TaskProvider.kt index 108875f..041204c 100644 --- a/src/main/java/at/bitfire/ical4android/TaskProvider.kt +++ b/src/main/java/at/bitfire/ical4android/TaskProvider.kt @@ -120,12 +120,6 @@ class TaskProvider private constructor( } } - fun syncAdapterUri(uri: Uri, account: Account) = uri.buildUpon() - .appendQueryParameter(TaskContract.ACCOUNT_NAME, account.name) - .appendQueryParameter(TaskContract.ACCOUNT_TYPE, account.type) - .appendQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER, "true") - .build()!! - } |