Use asSyncAdapter() for calendar provider URIs

This commit is contained in:
Ricki Hirner 2022-01-26 14:41:30 +01:00
parent 62af6f45ab
commit 1532fab49e
6 changed files with 43 additions and 43 deletions

View file

@ -17,6 +17,7 @@ import androidx.test.rule.GrantPermissionRule
import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.Event
import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat
import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter
import net.fortuna.ical4j.model.property.DtStart
import net.fortuna.ical4j.model.property.RRule
import net.fortuna.ical4j.model.property.RecurrenceId
@ -94,7 +95,7 @@ class LocalCalendarTest {
val eventId = localEvent.id!!
// set event as dirty
provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply {
provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply {
put(Events.DIRTY, 1)
}, null, null)
@ -103,7 +104,7 @@ class LocalCalendarTest {
// verify that event is now marked as deleted
provider.query(
ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId),
ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId),
arrayOf(Events.DELETED), null, null, null
)!!.use { cursor ->
cursor.moveToNext()
@ -123,7 +124,7 @@ class LocalCalendarTest {
val eventId = localEvent.id!!
// set event as dirty
provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply {
provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply {
put(Events.DIRTY, 1)
}, null, null)
@ -132,7 +133,7 @@ class LocalCalendarTest {
// verify that event is not marked as deleted
provider.query(
ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId),
ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId),
arrayOf(Events.DELETED), null, null, null
)!!.use { cursor ->
cursor.moveToNext()

View file

@ -16,9 +16,9 @@ import android.provider.CalendarContract.Events
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.AndroidCalendar.Companion.syncAdapterURI
import at.bitfire.ical4android.Event
import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat
import at.techbee.jtx.JtxContract.asSyncAdapter
import net.fortuna.ical4j.model.Date
import net.fortuna.ical4j.model.DateList
import net.fortuna.ical4j.model.parameter.Value
@ -293,7 +293,7 @@ class LocalEventTest {
// Get the status of whether the event is deleted
provider.query(
syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!), account),
ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!).asSyncAdapter(account),
arrayOf(Events.DELETED),
null,
null, null
@ -340,7 +340,7 @@ class LocalEventTest {
val eventId = localEvent.id!!
// set event as dirty
provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply {
provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply {
put(Events.DIRTY, 1)
}, null, null)
@ -349,7 +349,7 @@ class LocalEventTest {
// verify that event is now marked as deleted
provider.query(
ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId),
ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId),
arrayOf(Events.DELETED), null, null, null
)!!.use { cursor ->
cursor.moveToNext()
@ -369,7 +369,7 @@ class LocalEventTest {
val eventId = localEvent.id!!
// set event as dirty
provider.update(ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId), ContentValues(1).apply {
provider.update(ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId), ContentValues(1).apply {
put(Events.DIRTY, 1)
}, null, null)
@ -378,7 +378,7 @@ class LocalEventTest {
// verify that event is not marked as deleted
provider.query(
ContentUris.withAppendedId(calendar.eventsSyncURI(), eventId),
ContentUris.withAppendedId(Events.CONTENT_URI.asSyncAdapter(account), eventId),
arrayOf(Events.DELETED), null, null, null
)!!.use { cursor ->
cursor.moveToNext()

View file

@ -20,6 +20,7 @@ import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.AndroidCalendarFactory
import at.bitfire.ical4android.BatchOperation
import at.bitfire.ical4android.DateUtils
import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter
import java.util.*
import java.util.logging.Level
@ -149,7 +150,7 @@ class LocalCalendar private constructor(
override fun markNotDirty(flags: Int): Int {
val values = ContentValues(1)
values.put(LocalEvent.COLUMN_FLAGS, flags)
return provider.update(eventsSyncURI(), values,
return provider.update(Events.CONTENT_URI.asSyncAdapter(account), values,
"${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL",
arrayOf(id.toString()))
}
@ -157,7 +158,7 @@ class LocalCalendar private constructor(
override fun removeNotDirtyMarked(flags: Int): Int {
var deleted = 0
// list all non-dirty events with the given flags and delete every row + its exceptions
provider.query(eventsSyncURI(), arrayOf(Events._ID),
provider.query(Events.CONTENT_URI.asSyncAdapter(account), arrayOf(Events._ID),
"${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL AND ${LocalEvent.COLUMN_FLAGS}=?",
arrayOf(id.toString(), flags.toString()), null)?.use { cursor ->
val batch = BatchOperation(provider)
@ -165,7 +166,7 @@ class LocalCalendar private constructor(
val id = cursor.getLong(0)
// delete event and possible exceptions (content provider doesn't delete exceptions itself)
batch.enqueue(BatchOperation.CpoBuilder
.newDelete(eventsSyncURI())
.newDelete(Events.CONTENT_URI.asSyncAdapter(account))
.withSelection("${Events._ID}=? OR ${Events.ORIGINAL_ID}=?", arrayOf(id.toString(), id.toString())))
}
deleted = batch.commit()
@ -176,7 +177,7 @@ class LocalCalendar private constructor(
override fun forgetETags() {
val values = ContentValues(1)
values.putNull(LocalEvent.COLUMN_ETAG)
provider.update(eventsSyncURI(), values, "${Events.CALENDAR_ID}=?",
provider.update(Events.CONTENT_URI.asSyncAdapter(account), values, "${Events.CALENDAR_ID}=?",
arrayOf(id.toString()))
}
@ -185,7 +186,7 @@ class LocalCalendar private constructor(
// process deleted exceptions
Logger.log.info("Processing deleted exceptions")
provider.query(
syncAdapterURI(Events.CONTENT_URI),
Events.CONTENT_URI.asSyncAdapter(account),
arrayOf(Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE),
"${Events.CALENDAR_ID}=? AND ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NOT NULL",
arrayOf(id.toString()), null)?.use { cursor ->
@ -198,7 +199,7 @@ class LocalCalendar private constructor(
// get original event's SEQUENCE
provider.query(
syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)),
ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account),
arrayOf(LocalEvent.COLUMN_SEQUENCE),
null, null, null)?.use { cursor2 ->
if (cursor2.moveToNext()) {
@ -207,14 +208,14 @@ class LocalCalendar private constructor(
// re-schedule original event and set it to DIRTY
batch.enqueue(BatchOperation.CpoBuilder
.newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)))
.newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account))
.withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence + 1)
.withValue(Events.DIRTY, 1))
}
}
// completely remove deleted exception
batch.enqueue(BatchOperation.CpoBuilder.newDelete(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))))
batch.enqueue(BatchOperation.CpoBuilder.newDelete(ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(account)))
batch.commit()
}
}
@ -222,7 +223,7 @@ class LocalCalendar private constructor(
// process dirty exceptions
Logger.log.info("Processing dirty exceptions")
provider.query(
syncAdapterURI(Events.CONTENT_URI),
Events.CONTENT_URI.asSyncAdapter(account),
arrayOf(Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE),
"${Events.CALENDAR_ID}=? AND ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NOT NULL",
arrayOf(id.toString()), null)?.use { cursor ->
@ -235,11 +236,11 @@ class LocalCalendar private constructor(
val batch = BatchOperation(provider)
// original event to DIRTY
batch.enqueue(BatchOperation.CpoBuilder
.newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)))
.newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, originalID).asSyncAdapter(account))
.withValue(Events.DIRTY, 1))
// increase SEQUENCE and set DIRTY to 0
batch.enqueue(BatchOperation.CpoBuilder
.newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)))
.newUpdate(ContentUris.withAppendedId(Events.CONTENT_URI, id).asSyncAdapter(account))
.withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1)
.withValue(Events.DIRTY, 0))
batch.commit()
@ -254,7 +255,7 @@ class LocalCalendar private constructor(
*/
fun deleteDirtyEventsWithoutInstances() {
provider.query(
syncAdapterURI(Events.CONTENT_URI),
Events.CONTENT_URI.asSyncAdapter(account),
arrayOf(Events._ID),
"${Events.DIRTY} AND NOT ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NULL", // Get dirty main events (and no exception events)
null, null

View file

@ -12,6 +12,7 @@ import android.provider.CalendarContract
import android.provider.CalendarContract.Events
import at.bitfire.davdroid.BuildConfig
import at.bitfire.ical4android.*
import at.bitfire.ical4android.MiscUtils.UriHelper.asSyncAdapter
import net.fortuna.ical4j.model.property.ProdId
import org.apache.commons.lang3.StringUtils
import java.util.*
@ -34,12 +35,10 @@ class LocalEvent: AndroidEvent, LocalResource<Event> {
*/
fun markAsDeleted(provider: ContentProviderClient, account: Account, eventID: Long) {
provider.update(
AndroidCalendar.syncAdapterURI(
ContentUris.withAppendedId(
Events.CONTENT_URI,
eventID
), account
),
ContentUris.withAppendedId(
Events.CONTENT_URI,
eventID
).asSyncAdapter(account),
ContentValues(1).apply {
put(Events.DELETED, 1)
},
@ -61,12 +60,10 @@ class LocalEvent: AndroidEvent, LocalResource<Event> {
var first: Long? = null
var last: Long? = null
provider.query(
AndroidCalendar.syncAdapterURI(
ContentUris.withAppendedId(
Events.CONTENT_URI,
eventID
), account
),
ContentUris.withAppendedId(
Events.CONTENT_URI,
eventID
).asSyncAdapter(account),
arrayOf(Events.DTSTART, Events.LAST_DATE), null, null, null
)?.use { cursor ->
cursor.moveToNext()
@ -82,7 +79,7 @@ class LocalEvent: AndroidEvent, LocalResource<Event> {
/* We can't use Long.MIN_VALUE and Long.MAX_VALUE because Android generates the instances
on the fly and it doesn't accept those values. So we use the first/last actual occurence
of the event (calculated by Android). */
val instancesUri = AndroidCalendar.syncAdapterURI(CalendarContract.Instances.CONTENT_URI, account)
val instancesUri = CalendarContract.Instances.CONTENT_URI.asSyncAdapter(account)
.buildUpon()
.appendPath(first.toString()) // begin timestamp
.appendPath(last.toString()) // end timestamp
@ -113,7 +110,7 @@ class LocalEvent: AndroidEvent, LocalResource<Event> {
// add the number of instances of every main event's exception
provider.query(
AndroidCalendar.syncAdapterURI(Events.CONTENT_URI, account),
Events.CONTENT_URI.asSyncAdapter(account),
arrayOf(Events._ID),
"${Events.ORIGINAL_ID}=?", // get exception events of the main event
arrayOf("$eventID"), null

View file

@ -39,6 +39,7 @@ import at.bitfire.ical4android.TaskProvider.ProviderName.OpenTasks
import at.bitfire.ical4android.UnknownProperty
import at.bitfire.vcard4android.ContactsStorageException
import at.bitfire.vcard4android.GroupMethod
import at.techbee.jtx.JtxContract.asSyncAdapter
import net.fortuna.ical4j.model.Property
import net.fortuna.ical4j.model.property.Url
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@ -438,7 +439,7 @@ class AccountSettings(
context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.use { provider ->
// Attention: CalendarProvider does NOT limit the results of the ExtendedProperties query
// to the given account! So all extended properties will be processed number-of-accounts times.
val extUri = AndroidCalendar.syncAdapterURI(ExtendedProperties.CONTENT_URI, account)
val extUri = ExtendedProperties.CONTENT_URI.asSyncAdapter(account)
provider.query(extUri, arrayOf(
ExtendedProperties._ID, // idx 0
@ -450,7 +451,7 @@ class AccountSettings(
val rawValue = cursor.getString(2)
val uri by lazy {
AndroidCalendar.syncAdapterURI(ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id), account)
ContentUris.withAppendedId(ExtendedProperties.CONTENT_URI, id).asSyncAdapter(account)
}
when (cursor.getString(1)) {
@ -519,7 +520,7 @@ class AccountSettings(
**/
private fun update_9_10() {
TaskProvider.acquire(context, OpenTasks)?.use { provider ->
val tasksUri = TaskProvider.syncAdapterUri(provider.tasksUri(), account)
val tasksUri = provider.tasksUri().asSyncAdapter(account)
val emptyETag = ContentValues(1)
emptyETag.putNull(LocalTask.COLUMN_ETAG)
provider.client.update(tasksUri, emptyETag, "${TaskContract.Tasks._DIRTY}=0 AND ${TaskContract.Tasks._DELETED}=0", null)
@ -528,7 +529,7 @@ class AccountSettings(
@SuppressLint("Recycle")
if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_CALENDAR) == PackageManager.PERMISSION_GRANTED)
context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)?.let { provider ->
provider.update(AndroidCalendar.syncAdapterURI(CalendarContract.Calendars.CONTENT_URI, account),
provider.update(CalendarContract.Calendars.CONTENT_URI.asSyncAdapter(account),
AndroidCalendar.calendarBaseValues, null, null)
provider.closeCompat()
}
@ -558,7 +559,7 @@ class AccountSettings(
TaskProvider.acquire(context, OpenTasks)?.use { provider ->
// ETag is now in sync_version instead of sync1
// UID is now in _uid instead of sync2
provider.client.query(TaskProvider.syncAdapterUri(provider.tasksUri(), account),
provider.client.query(provider.tasksUri().asSyncAdapter(account),
arrayOf(TaskContract.Tasks._ID, TaskContract.Tasks.SYNC1, TaskContract.Tasks.SYNC2),
"${TaskContract.Tasks.ACCOUNT_TYPE}=? AND ${TaskContract.Tasks.ACCOUNT_NAME}=?",
arrayOf(account.type, account.name), null)!!.use { cursor ->
@ -573,7 +574,7 @@ class AccountSettings(
values.putNull(TaskContract.Tasks.SYNC2)
Logger.log.log(Level.FINER, "Updating task $id", values)
provider.client.update(
TaskProvider.syncAdapterUri(ContentUris.withAppendedId(provider.tasksUri(), id), account),
ContentUris.withAppendedId(provider.tasksUri(), id).asSyncAdapter(account),
values, null, null)
}
}

@ -1 +1 @@
Subproject commit 16eba01bb255b8fbd3957a3461c3a62ee3374e45
Subproject commit f340ca7ff62b76dfed6ac07112d40c749072cc51