Loading src/androidTest/java/at/bitfire/ical4android/AndroidCalendarTest.kt +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading src/androidTest/java/at/bitfire/ical4android/AndroidEventTest.kt +17 −13 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) } Loading Loading @@ -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) Loading Loading @@ -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)) Loading @@ -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"))) Loading @@ -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() } Loading Loading @@ -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() } Loading Loading @@ -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) Loading @@ -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 Loading src/androidTest/java/at/bitfire/ical4android/AospTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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") } )!! Loading src/androidTest/java/at/bitfire/ical4android/MiscUtilsAndroidTest.kt +14 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) ) } } src/main/java/at/bitfire/ical4android/AndroidCalendar.kt +11 −25 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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) } Loading @@ -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()) { Loading @@ -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>() Loading @@ -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 Loading Loading @@ -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()) } Loading @@ -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) } Loading
src/androidTest/java/at/bitfire/ical4android/AndroidCalendarTest.kt +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
src/androidTest/java/at/bitfire/ical4android/AndroidEventTest.kt +17 −13 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) Loading Loading @@ -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) } Loading Loading @@ -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) Loading Loading @@ -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)) Loading @@ -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"))) Loading @@ -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() } Loading Loading @@ -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() } Loading Loading @@ -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) Loading @@ -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 Loading
src/androidTest/java/at/bitfire/ical4android/AospTest.kt +2 −0 Original line number Diff line number Diff line Loading @@ -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") } )!! Loading
src/androidTest/java/at/bitfire/ical4android/MiscUtilsAndroidTest.kt +14 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) ) } }
src/main/java/at/bitfire/ical4android/AndroidCalendar.kt +11 −25 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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) } Loading @@ -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()) { Loading @@ -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>() Loading @@ -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 Loading Loading @@ -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()) } Loading @@ -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) }