[Android Tips] Calendar Provider で Event を登録すると Google カレンダーアプリが強制終了することがある

Android

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Google カレンダーが強制終了

久しぶりに Android に関するブログを書きます。

弊社では iCalSync という iCalendar 形式(.ics)のイベントデータを Android のローカルカレンダーに定期的に同期するアプリをリリースしています。

iCalSync

icalsync-app

好評いただいているんですが、先日 iCalSync で登録したイベントを Google カレンダーで開くと強制終了するという問題が発生しました。

google-calendar-01

この問題が発生する Google カレンダーは Material Design が適用された最新バージョン(Ver.5.0)です。

Googleカレンダー

google-calendar-app

OWNER_ACCOUNT が原因

ログを見てみたところ、どうやら NullPointerException で落ちているということが分かりました。つまり、登録したイベントのプロパティに何かが足りないということです。あとはどのデータが足りないかという話ですが…探しまくったところ、CalendarProvider で Calendar を登録する時、OWNER_ACCOUNT というプロパティが足りていないことが分かりました。

public void entryCalendar(String accountName, String displayName, int color) {

    ContentResolver contentResolver = App.getContext().getContentResolver();
    ContentValues calVal = new ContentValues();
    calVal.put(getAccountNameColumn(), accountName);
    calVal.put(getAccountTypeColumn(), AccountSetting.ACCOUNT_TYPE);
    calVal.put(getNameColumn(), Res.string(R.string.calendar_title));
    calVal.put(getCalendarDisplayNameColumn(), displayName);
    calVal.put(getCalendarColorColumn(), color);
    calVal.put(getCalendarAccessLevelColumn(), 700);
    calVal.put(getCalendarTimeZoneColumn(), TimeZone.getDefault().getID());
    calVal.put(getSyncEventsColumn(), 1);
    
    contentResolver.insert(asSyncAdapter(getCalendarsURI(), accountName, AccountSetting.ACCOUNT_TYPE), calVal).toString();
}

足りていないので、OWNER_ACCOUNT を追加します。

public void entryCalendar(String accountName, String displayName, int color, String ownerMailAddress) {

    ContentResolver contentResolver = App.getContext().getContentResolver();
    ContentValues calVal = new ContentValues();
    calVal.put(getAccountNameColumn(), accountName);
    calVal.put(getAccountTypeColumn(), AccountSetting.ACCOUNT_TYPE);
    calVal.put(getNameColumn(), Res.string(R.string.calendar_title));
    calVal.put(getCalendarDisplayNameColumn(), displayName);
    calVal.put(getCalendarColorColumn(), color);
    calVal.put(getCalendarAccessLevelColumn(), 700);
    calVal.put(getOwnerAccountColumn(), ownerMailAddress);
    calVal.put(getCalendarTimeZoneColumn(), TimeZone.getDefault().getID());
    calVal.put(getSyncEventsColumn(), 1);
    
    contentResolver.insert(asSyncAdapter(getCalendarsURI(), accountName, AccountSetting.ACCOUNT_TYPE), calVal).toString();
}

これで Google カレンダーで確認してみたところ、正常に表示されました。

google-calendar-02

まとめ

OWNER_ACCOUNT は必須項目ではないようですし、アプリの機能上必要がないので省いていましたが、Google カレンダーの動作には必要という感じでした。OWNER_ACCOUNT が設定できる iCalSync のアップデートは Google Play ストアで公開中です。なお同期実行時に OWNER_ACCOUNT がない場合は必ずセットするようになっているので、既存カレンダーをそのまま使えます。ぜひアップデートをよろしくお願いします!

AWS Cloud Roadshow 2017 福岡