您如何获得 Android 上具有日历的帐户列表?

How do you get a list of accounts on Android that have calendars?

我正在为 Android 编写一个应用程序,它会在日历中为用户创建一系列事件,而正常的重复事件无法处理这些事件。我想让用户选择他们想要用于日历的帐户(主要是为了以后共享日历)。

使用 AccountManager,我可以获得所有帐户,但并非所有帐户都有日历。 Google 帐户在技术上是可行的,但我想使用 Exchange 帐户或其他也有日历的帐户。

我读过的所有 AccountManager API 文档都说要搜索的功能是特定于身份验证器的(并且可以更改)。保留一份清单几乎是不可能的。仅限于已知帐户类型的列表比我真正想要的要多。

还有我错过的其他选择吗?

与我最初的看法相反,您实际上根本不需要触摸帐户列表。这有助于简化流程并减少所需权限的数量。

使用 the information from this page(在查询日历下),您可以编写对日历的查询 table 并获取日历及其所属帐户的完整列表。

最后,这种方法对我来说会更有用。基本上,EVENT_PROJECTION 从示例显示的内容更改如下。

public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,
    Calendars.ACCOUNT_NAME,
    Calendars.CALENDAR_DISPLAY_NAME,
    Calendars.ACCOUNT_TYPE,
    Calendars.CALENDAR_ACCESS_LEVEL,
    Calendars.IS_PRIMARY
};

ACCOUNT_TYPECALENDAR_ACCESS_LEVELIS_PRIMARY 已添加,以便我们知道 a) 哪个日历是帐户的主要日历,以便稍后进行排序,以及 b) 用户是否可以实际写入它,因为如果它是只读的,我们不想要它。

此外,在日历的实际查询中table,我做了以下更改。

// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, "", null, null);

由于我们希望所有日历都开始,因此示例中的 selectionselectionArgs 变量没有用。

直到我们得到查询的最终结果,基本上示例中的其他所有内容都保持不变。

一旦我们有了数据,就可以将其解析并放入 ListHashMap 等中,并根据需要进行排序和过滤.

型号

import java.util.ArrayList;
import java.util.List;

public class CalendarAccount {

    private String name;
    private List<Calendar> calendars;

    public CalendarAccount(String name) {
        this(name, new ArrayList<Calendar>());
    }

    public CalendarAccount(String name, List<Calendar> calendars) {
        this.name = name;
        this.calendars = calendars;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Calendar> getCalendars() {
        return calendars;
    }

    public void setCalendars(List<Calendar> calendars) {
        this.calendars = calendars;
    }
}

import android.support.annotation.ColorInt;

public class Calendar {

    private long id;
    private String displayName;
    @ColorInt private int color;
    private boolean userActivated;

    public Calendar(long id, String displayName, @ColorInt int color) {
        this(id, displayName, color, false);
    }

    public Calendar(long id, String displayName, int color, boolean userActivated) {
        this.id = id;
        this.displayName = displayName;
        this.color = color;
        this.userActivated = userActivated;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public boolean isUserActivated() {
        return userActivated;
    }

    public void setUserActivated(boolean userActivated) {
        this.userActivated = userActivated;
    }
}

使用 Calendar Provider 的实际代码

public static final String[] EVENT_PROJECTION = new String[] {
        Calendars._ID,                           // 0
        Calendars.ACCOUNT_NAME,                  // 1
        Calendars.CALENDAR_DISPLAY_NAME,         // 2
        Calendars.OWNER_ACCOUNT,                 // 3
        Calendars.CALENDAR_COLOR                 // 4
};

// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
private static final int PROJECTION_COLOR_INDEX = 4;


private List<CalendarAccount> getAccountCalendars() {
    // Run query
    Cursor cur;
    ContentResolver cr = context.getContentResolver();
    Uri uri = Calendars.CONTENT_URI;
    String selection = "(" + Calendars.VISIBLE + " = ?)";
    String[] selectionArgs = new String[] {"1"};
    // Submit the query and get a Cursor object back.
    cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
    List<CalendarAccount> calendarAccounts = new ArrayList<>();
    // Use the cursor to step through the returned records
    while (cur.moveToNext()) {
        long calID = 0;
        String displayName = null;
        String accountName = null;
        String ownerName = null;
        @ColorInt int color = 0;

        // Get the field values
        calID = cur.getLong(PROJECTION_ID_INDEX);
        displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
        accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
        ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
        color = cur.getInt(PROJECTION_COLOR_INDEX);

        Calendar calendar = new Calendar(calID, displayName, color);
        CalendarAccount calendarAccount = new CalendarAccount(accountName);
        int index = calendarAccounts.indexOf(calendarAccount);
        if (index != -1) {
            calendarAccount = calendarAccounts.get(index);
        } else {
            calendarAccounts.add(calendarAccount);
        }
        calendarAccount.getCalendars().add(calendar);
    }
    return calendarAccounts;
}