如何在安卓手机上添加新的日历?

11

Android上的日历应用程序可以合并多个独立的日历:本地电话日历、Google日历等。

我该如何在Android手机上添加一个新的日历? 我想动态生成该日历中的事件,而不需要访问任何在线资源,比如Google。

编辑:我希望支持安卓1.5和2.3.4的手机。将来可能会有更新到4.0的较新手机,但我们谁也不知道那会是什么时候...


ICS: 您需要为com.android.calendar权限实现同步适配器,并在CalendarContract.Calendar中创建一行,其中设置ACCOUNT_NAME和ACCOUNT_TYPE为您的名称和值。2.3及更早版本的功能未发布,但可以正常工作... 大致相同-但是如果要实现向后互操作性,将会很混乱并且需要耗费大量时间进行测试。 - Jens
4个回答

14

我刚刚成功使用ICS的新API添加了一个日历。Stefan的答案有所帮助,但想要能够写入所有列,必须将操作作为同步适配器进行。您可以使用CalendarContract.ACCOUNT_TYPE_LOCAL从普通应用程序中执行此操作。以下代码应该在ICS上工作。可能某些列值不正确。请查看CalendarContract.Calendars的文档。不幸的是,我无法为旧版本的Android提供帮助,但CalendarContract仅用于一些常量字符串值。也许这些也适用于旧版本。

Uri calUri = CalendarContract.Calendars.CONTENT_URI;
ContentValues cv = new ContentValues();
cv.put(CalendarContract.Calendars.ACCOUNT_NAME, yourAccountName);
cv.put(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL);
cv.put(CalendarContract.Calendars.NAME, yourInternalName);
cv.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, yourDisplayName);
cv.put(CalendarContract.Calendars.CALENDAR_COLOR, yourColor);
cv.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER);
cv.put(CalendarContract.Calendars.OWNER_ACCOUNT, true);
cv.put(CalendarContract.Calendars.VISIBLE, 1);
cv.put(CalendarContract.Calendars.SYNC_EVENTS, 1);

calUri = calUri.buildUpon()
    .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
    .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, ACCOUNT_NAME)
    .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CalendarContract.ACCOUNT_TYPE_LOCAL)
    .build();
Uri result = this.getContentResolver().insert(calUri, cv);

4

我已经编写了下面的活动(以及一些资源等),以便在API级别为15的模拟器上插入一个日历(不同步),因为那里的日历应用程序没有添加日历的功能,与我的手机上的应用程序不同(API 8),或者我没有找到它...)。布局有两个文本字段,用于日历的名称和显示名称,一个添加按钮和一个状态文本视图,在插入后提供反馈。请确保在清单中设置了权限:

<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>

这里是代码:
public class CalUtilActivity extends Activity {
private EditText name;
private EditText display;
private TextView status;

@Override
public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.main);

    this.name = (EditText) this.findViewById(R.id.name);
    this.display = (EditText) this.findViewById(R.id.displayname);
    this.status = (TextView) this.findViewById(R.id.status);

    final Button b = (Button) this.findViewById(R.id.add);
    b.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(final View v) {
            CalUtilActivity.this.addCalendar();
        }
    });
}

private void addCalendar() {
    final String cname = this.name.getText().toString();
    final String dname = this.display.getText().toString();
    if( cname.length() == 0 || dname.length() == 0 ) {
        this.status.setText(this.getResources().getString(R.string.errorNames));
        return;
    }
    this.status.setText("");

    final Uri calUri = CalendarContract.Calendars.CONTENT_URI;
    final ContentValues v = new ContentValues();
    v.put(CalendarContract.Calendars.NAME, cname);
    v.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, dname);
    v.put(CalendarContract.Calendars.VISIBLE, 1);

    final Uri result = this.getContentResolver().insert(calUri, v);

    this.status.setText(result.toString());
}

对于API 13及以前的版本,您无法使用内容提供程序,必须直接访问数据库。要添加日历,您必须向Calendars表中添加一行,该表根据以下创建语句进行定义:

CREATE TABLE Calendars (_id INTEGER PRIMARY KEY,_sync_account TEXT,_sync_account_type TEXT,_sync_id TEXT,_sync_version TEXT,_sync_time TEXT,_sync_local_id INTEGER,_sync_dirty INTEGER,_sync_mark INTEGER,url TEXT,name TEXT,displayName TEXT,hidden INTEGER NOT NULL DEFAULT 0,color INTEGER,access_level INTEGER,selected INTEGER NOT NULL DEFAULT 1,sync_events INTEGER NOT NULL DEFAULT 0,location TEXT,timezone TEXT,ownerAccount TEXT, organizerCanRespond INTEGER NOT NULL DEFAULT 1);

如果您不需要同步日历,则设置_id、名称和displayName应该是可行的。但是,您无法在模拟器上进行测试,因为日历应用程序及其数据库缺失。理论上,设备供应商可能已经修改了数据库架构,但由于有很多日历应用程序可用,我个人认为他们没有修改数据库架构。


3
我找到了一个讨论在 Android 4.0 之前如何访问手机日历内容提供者的链接
基本上你只需要知道提供者的 URI 字符串:
  • 对于 Android < 2.2,使用 content://calendar
  • 对于 Android 2.2+,使用 content://com.android.calendar
请注意,不要删除 HTML 标签。

-5
最简单的方法是在您的电脑上创建谷歌日历并同步它。

8
你让我笑了 :) ... 至少,我希望这是个玩笑。 - Glenn85

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接