使用Android 4.0(ICS)内容提供商创建日历

时间:2012-02-17 21:35:03

标签: android android-contentprovider android-4.0-ice-cream-sandwich

我正在尝试使用ICS的新日历内容提供程序创建日历。由于日历创建只能在SyncAdapter中完成,因此我创建了一个:

public class CalendarSyncAdapter extends AbstractThreadedSyncAdapter 
{

    public CalendarSyncAdapter(Context context, boolean autoInitialize)
    {
        super(context, autoInitialize);
    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
    {
        Log.i( Debug.TAG, "onPerformSync()" );
    }

    public void doCreateCalendar( Account account )
    {
            ContentResolver cr = getContext().getContentResolver();

            ContentValues values = new ContentValues();
            values.put(Calendars.ACCOUNT_NAME, account.name);
            values.put(Calendars.ACCOUNT_TYPE, account.type);
            values.put(Calendars.NAME, "newesttest");
            values.put(Calendars.CALENDAR_DISPLAY_NAME, "newestTest");
            values.put(Calendars.CALENDAR_COLOR, 0xFFFFFFFF);
            values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER );
            values.put(Calendars.OWNER_ACCOUNT, account.name);

            values.put(Calendars.SYNC_EVENTS, 1);
            values.put(Calendars.VISIBLE, 1);

            Uri creationUri = asSyncAdapter( Calendars.CONTENT_URI, account.name, account.type );
            Uri created = cr.insert( creationUri, values );
            long id = Long.parseLong( created.getLastPathSegment() );

            Log.i( Debug.TAG, "Calendar created: " + id + " - " + created );
    }

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

但它并不像我到处看到的那样在服务中运行,因为我想要的只是使用它来插入新的日历。不需要在服务中运行吗?似乎不是。

无论如何,我在我的Activity中实例化它并调用我的方法:

public void createCalendar( View v )
{
    m_syncAdapter.doCreateCalendar( this, m_account );
}

它成功执行,没有投诉,但它返回的URI始终是相同的。当我为行ID解析它时,它始终是12.当我检查我的日历时,没有什么新东西。

在我的清单中,我有一切设置:          

...

<application

...

    <activity android:name="Setup" android:label="@string/activity_title_setup">
        <intent-filter>
            <action android:name="android.content.SyncAdapter" />
        </intent-filter>
        <meta-data android:name="android.content.SyncAdapter" android:resource="@xml/calendar_sync_adapter" />
    </activity>

和calendar_sync_adapter.xml:

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
   android:contentAuthority="com.android.calendar"
   android:accountType="com.google"
   android:userVisible="true"
/>

所以不确定我在这里做错了什么。但这是我执行时在日志中看到的:

02-17 16:43:07.783: I/ActivityManager(184): Start proc com.android.providers.calendar for content provider com.android.providers.calendar/.CalendarProvider2: pid=20132 uid=10008 gids={3003, 1015}
02-17 16:43:07.806: I/ActivityThread(20132): Pub com.android.calendar: com.android.providers.calendar.CalendarProvider2
02-17 16:43:07.869: I/ActivityManager(184): Start proc com.google.android.calendar for service com.google.android.calendar/com.google.android.syncadapters.calendar.CalendarSyncAdapterService: pid=20145 uid=10007 gids={3003}
02-17 16:43:07.900: I/ActivityThread(20145): Pub com.google.android.calendar.CalendarRecentSuggestionsProvider: com.android.calendar.CalendarRecentSuggestionsProvider

// This is my print of the returned URI
02-17 16:43:08.009: I/C3(19995): Calendar created: 12 - content://com.android.calendar/calendars/12?caller_is_syncadapter=true&account_name=xxx%40gmail.com&account_type=com.google

02-17 16:43:08.876: I/CalendarProvider2(20132): Sending notification intent: Intent { act=android.intent.action.PROVIDER_CHANGED dat=content://com.android.calendar }
02-17 16:43:08.876: W/ContentResolver(20132): Failed to get type for: content://com.android.calendar (Unknown URL content://com.android.calendar)

3 个答案:

答案 0 :(得分:3)

答案是: 同步适配器必须与服务相关联。 Service在onCreate()中实例化同步适配器,并将IBinder返回到onBind()中的同步适配器。当SyncManager想要运行同步适配器时,它会调用该服务。

同步适配器由Android系统控制,特别是由SyncManager控制,而不是由您的应用程序控制。

SampleSyncAdapter示例应用程序显示了如何编写同步适配器和服务。如果您不想进行身份验证,则可以删除该部分。您需要做的就是实现扩展AbstractThreadedSyncAdapter的类和绑定它的Service类,以及同步适配器的XML文件。

更好的答案是: 同步适配器可帮助您在服务器和设备之间同步数据。如果您只想将日历数据从服务器下载到设备,则可以使用从服务器中删除数据并将其写入日历提供程序的应用程序。那不是同步;您没有保证您将进行更多下载或上传。当然,如果您想要保持两个数据源同步,那么同步适配器具有以下优势:

  • 系统将定期运行它,无需用户干预。
  • 系统会在尝试运行同步之前确保网络可用。但请注意,系统无法阻止您在网络服务脱机时尝试对服务器进行身份验证等愚蠢行为。
  • 系统确保在开始同步时,同一服务器和内容提供商的其他同步没有运行。
  • 系统提供标准工具,用于在用户想要添加帐户时显示可用的同步适配器。

答案 1 :(得分:2)

是的,日历API不适合创建新日历。该设备意味着更像是云的镜像。

答案 2 :(得分:0)

无法使用Android Calendar API以编程方式在现有的Google(Gmail)帐户中创建新的可同步日历。我在这里提供了更多详细信息:https://stackoverflow.com/a/19734278/237232