Why doesn't CalendarProvider allow writing ExtendedProperties?

Google calendar events have advanced properties that you can use to add name / value pairs to an event.

We will implement a collaboration calendar application that uses these advanced properties to add additional information to an event. As per Google guidelines, we use the Android CalendarProvider to read and create new events. When we create a new event, we need to add some extended properties to it, but we just realized that the calendar provider doesn't allow us to write CalendarContract.ExtendedProperties

if we try to get the following error:

Only sync adapters may write using content://com.android.calendar/extendedproperties

It seems a little odd that these properties are read-only in the CalendarProvider because it defeats their whole purpose of being able to attach some additional metadata to an event.

Does anyone know a workaround for this limitation?

+3


source to share


1 answer


you need to proceed like this:

  • the class you use to persist extended proposition events should extend AbstractThreadedSyncAdapter , then implement the onPerfomSync (...) method

    public void onPerformSync(Account account, Bundle extras, String authority,
        ContentProviderClient provider, SyncResult syncResult) {
    System.out.println("Sync......");
    saveEvent();//your saving events method... 
    
          

    }

add below method in the same class:

    static Uri asSyncAdapter(Uri uri, String account, String accountType) {
    return uri.buildUpon()
        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
 }

      

create a class that extends the Service class as shown below

public class SyncService extends Service {
private static final String TAG = "SyncService";

private static final Object sSyncAdapterLock = new Object();
private static EditEventHelper sSyncAdapter = null;

/**
 * Thread-safe constructor, creates static {@link SyncAdapter} instance.
 */
@Override
public void onCreate() {
    super.onCreate();
    Log.i(TAG, "Service created");
    synchronized (sSyncAdapterLock) {
        if (sSyncAdapter == null) {
            sSyncAdapter = new EditEventHelper(getApplicationContext());

        }
    }
}

@Override
/**
 * Logging-only destructor.
 */
public void onDestroy() {
    super.onDestroy();
    Log.i(TAG, "Service destroyed");
}

/**
 * Return Binder handle for IPC communication with {@link SyncAdapter}.
 *
 * <p>New sync requests will be sent directly to the SyncAdapter using this channel.
 *
 * @param intent Calling intent
 * @return Binder handle for {@link SyncAdapter}
 */
@Override
public IBinder onBind(Intent intent) {
    return sSyncAdapter.getSyncAdapterBinder();
}

      

}

In the res path, create an xml file syncadpater.xml with content:



<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
          android:contentAuthority="com.android.calendar"
          android:accountType="com.android.google"
          android:userVisible="true"
          android:supportsUploading="false"
          android:allowParallelSyncs="false"
          android:isAlwaysSyncable="false"
    />

      

Code to add Extendedproperties event to you:

ContentValues customerContentValues_1 = new ContentValues(); 
        customerContentValues_1.put(ExtendedProperties.EVENT_ID, model.mId);
        customerContentValues_1.put(ExtendedProperties.NAME, "name");
        customerContentValues_1.put(ExtendedProperties.VALUE, value);
activity.getContentResolver().insert(asSyncAdapter(ExtendedProperties.CONTENT_URI, mOwnerAccount, ACCOUNT_TYPE), customerContentValues_1);

      

In the AndroidManifest.xml file add the following permissions:

    <uses-permission android:name="android.permission.READ_SYNC_STATS" />
<!-- Required to enable our SyncAdapter after it created. -->
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<!-- Required because we're manually creating a new account. -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />

      

Then declare the service you created in the manifest file associated with the syncadapter.xml file:

        <service
        android:name="com.android.calendar.iselection.event.SyncService"
        android:exported="true" >

        <!--
        This intent filter is required. It allows the system to launch our sync service
        as needed.
        -->
        <intent-filter>
            <action android:name="android.content.SyncAdapter" />
        </intent-filter>
        <!-- This points to a required XML file which describes our SyncAdapter. -->
        <meta-data
            android:name="android.content.SyncAdapter"
            android:resource="@xml/syncadapter" />
    </service>

      

Good luck!

+2


source







All Articles