我正在尝试与 iOS 和 Android 进行 Google 日历同步。
对于 iOS,我正在使用 google-api-objectivec-client-for-rest
对于 Android,我使用 contentResolver 和 ContentValues 的方法 日历提供商
据我所知,iOS 端使用 Rest API,Android 端使用内容提供程序。
为了不重复事件,我使用了来自 android 的 ID,它是一个长值。当我在iOS上实现时,我发现ID是一个字符串(很长而且不是整数)。
在 iOS 上我发现:
**
* Opaque identifier of the event. When creating new single or recurring
* events, you can specify their IDs. Provided IDs must follow these rules:
* - characters allowed in the ID are those used in base32hex encoding, i.e.
* lowercase letters a-v and digits 0-9, see section 3.1.2 in RFC2938
* - the length of the ID must be between 5 and 1024 characters
* - the ID must be unique per calendar Due to the globally distributed nature
* of the system, we cannot guarantee that ID collisions will be detected at
* event creation time. To minimize the risk of collisions we recommend using
* an established UUID algorithm such as one described in RFC4122.
* If you do not specify an ID, it will be automatically generated by the
* server.
* Note that the icalUID and the id are not identical and only one of them
* should be supplied at event creation time. One difference in their semantics
* is that in recurring events, all occurrences of one event have different ids
* while they all share the same icalUIDs.
*
* identifier property maps to 'id' in JSON (to avoid Objective C's 'id').
*
@property(nonatomic, copy, nullable) NSString *identifier;
原来来自rest的ID是一个Opaque iD,但来自Android的ID实际上是Google在事件创建后生成的序列。
我尝试从 Android 端搜索不透明 ID,但我无法在文档中找到它。这可能是故意这样做的,因为
ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, googleID)
实际上需要很长的 ID。
我在here找到了类似的答案,并且我按照它在Android端为参数CalendarContract.Events.UID_2445设置了自定义UID。 (即使我尝试在插入后进行查询也不会自动生成)
UUID.randomUUID().toString()
.replace("-", "")
.lowercase()
但是当我尝试从 iOS 获取相同的事件时,我无法做到这一点,因为我收到错误未找到。
我尝试获取所有事件和列,看看是否可以通过查询来获取它,但实际上它不是一个字段。
例如在Android端我设置了uID = 62b92a9f626c4a7da7653f7f5c758d04
但是在 iOS 上我得到了这个:
API 之间的这种差异是故意的吗?
我应该在android上使用rest api来得到同样的东西吗?我没有找到开箱即用的东西。
如果生成的事件id不同,如何同步Android和iOS之间的事件?
进一步调查,我发现在 Android 端,与在线日历同步完成后,内容解析器还会返回
_SYNC_ID
字段,该字段填充的 ID 与从 iOS Rest api 返回的 ID 相同。
为了得到它,在
contentResolver.insert
之后,我为插入的事件的相同URI注册了一个ContentObserver:
val uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values)
val longGoogleID = uri!!.lastPathSegment?.toLongOrNull()
val eventChangeObserver = object : ContentObserver(null)
{
override fun onChange(selfChange: Boolean)
{
super.onChange(selfChange)
val syncID = getEventSyncID(context, longGoogleID)
contentResolver.unregisterContentObserver(this)
}
}
contentResolver.registerContentObserver(uri, true, eventChangeObserver)
并使用函数获取同步ID:
private fun getEventSyncID(context: Context, longID: Long): String?
{
try
{
val contentResolver = context.contentResolver
val uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, longID)
val projection = arrayOf(CalendarContract.Events._ID, CalendarContract.Events._SYNC_ID)
val cursor = contentResolver.query(uri, projection, null, null, null) ?: return null
if (!cursor.moveToFirst()) return null
val eventSyncID = cursor.getString(1)
return eventSyncID
} catch (ex: Exception)
{
println(ex)
}
return null
}
这很可能是需要的,因为事件未在插入的同一时刻与 Google 服务器同步,因此我们必须在第二时刻获取它们。