🍣

【RN】端末のカレンダーにイベントを追加する

2021/09/03に公開

はじめに

今回はReactNativeアプリから端末のカレンダーへイベントを登録する方法について紹介します。
会議やイベント情報などを表示するようなタイプのアプリでは、OSのカレンダーと同期を行いたいケースも多いので役立つかと思います。

使用するライブラリ

使用するライブラリはreact-native-calendar-eventsです。
端末内のカレンダー情報の取得から、そこにイベントを追加するまでを行うことができます。

https://github.com/wmcmahan/react-native-calendar-events

インストール

以下コマンドでインストールを行います。

yarn add react-native-calendar-events

iOSを扱う場合はpod installも合わせて行います。

cd ios
pod install

v0.6以上のReactNativeならauto linkが働くため、基本的にはこれだけで使用する準備が整います。
※もしauto linkを使わない場合は、公式ページよりManual linkingの項を参照してください。

権限設定

iOSの場合、カレンダーアクセス時に表示する文言を設定する必要があります。
Info.plistNSCalendarsUsageDescriptionの項目を追加しましょう。

Info.plist
<plist version="1.0">
  <dict>
    <!-- 略 -->
    <key>NSCalendarsUsageDescription</key>
    <string>カレンダーにイベントを登録します。</string>
  </dict>
</plist>

ここで入力した内容が、アプリがカレンダー権限の利用を求める際に表示されます。

使用方法

以下に主な使用方法を記載します。
共通の処理としてimportを記載する必要があります。

import RNCalendarEvents from "react-native-calendar-events";

権限の確認

カレンダーにアクセスする権限があるかどうか確認します。

// 現在の権限の状態
const permission = await RNCalendarEvents.checkPermissions();

// 正常に取得できた場合、permissionには"denied", "restricted", "authorized", "undetermined"のいずれかが入る

ここで取得した結果が"denied"(拒否)などの場合は権限をリクエストする必要があります。

権限のリクエスト

// 権限をリクエストして結果を取得
const permission = await RNCalendarEvents.requestPermissions();

// 正常に取得できた場合、permissionには"denied", "restricted", "authorized", "undetermined"のいずれかが入る

実行時に権限へのアクセスを求めるダイアログが画面に表示されます。

取得する結果はcheckPermissions()と同じです。
※実行前に、既に権限が"authorized"だった場合、ダイアログは表示されず"authorized"を返します。

カレンダーの取得

端末が扱っているカレンダーのリストを取得します。
※例えばAndroid端末のGoogle Calendarのようにいくつかのカレンダーを持っている場合は全件取得します。

後述の「イベントの追加」の際に「どのカレンダーに追加するか」を指定するためにカレンダーのidを取得しておく必要があります。
メインで使っているカレンダーにはisPrimaryのフラグが付いているので、そのカレンダーを利用しましょう。

const calendars = await RNCalendarEvents.findCalendars();
console.log(calendar);

取得した結果は以下のような構造になっています。

[
    {
        "allowedAvailabilities": [], 
        "allowsModifications": true, 
        "color": "#1BADF8", 
        "id": "XXXXXXXXXXX", 
        "isPrimary": true, 
        "source": "Default", 
        "title": "Calendar"
    }, 
    {
        "allowedAvailabilities": [], 
        "allowsModifications": false, 
        "color": "#8295AF", 
        "id": "XXXXXXXXXXX", 
        "isPrimary": 
        false, "source": "Other", 
        "title": "Siri Suggestions"
    }, 
    {
        "allowedAvailabilities": [], 
        "allowsModifications": false, 
        "color": "#8295AF", 
        "id": "XXXXXXXXXXX", 
        "isPrimary": false,
        "source": "Other", 
        "title": "Birthdays"
    }
]

イベントの追加

カレンダーに対してイベントの追加を行います。
「イベントのタイトル」や「開始、終了日時」や「終日かどうか」などを指定する必要があります。

const id: string = await RNCalendarEvents.saveEvent("Zennに記事を投稿する", {
  // 追加するカレンダー
  calendarId: "【カレンダーのID】",
  // 開始日時(ISO8601)
  startDate: "2021-09-03T12:00:00.000Z",
  // 終了日時(ISO8601)
  endDate: "2021-09-04T12:00:00.000Z",
  // 終日フラグ
  allDay: true,
  // 場所
  location: "https://zenn.dev/"
});

// 正常に完了した場合はidにイベントIDが入る

OSによって日時のフォーマットを分ける必要がある

上記の通り、開始終了日時ともに文字列で指定する必要がありますが、OSによって求められるフォーマットが異なるようです。
以下のIssueにその記載がありました。

https://github.com/wmcmahan/react-native-calendar-events/issues/25

それによると、下記のようにOSで書き分ける必要があります。

if (Platform.OS !== 'android') {
  return "YYYY-MM-DTHH:mm:ss.SSS" + "UTC");
} else {
  return "YYYY-MM-DTHH:mm:ss.SSS" + 'Z');
}

このあたりは将来的にはバージョンアップで改善されるかもしれません。

2021/12/16追記

以下のように書けばよいようです。

const isoFormat = date.toISOString();

まとめ

今回はreact-native-calendar-eventsについてご紹介しました。
主な処理のみの紹介でしたが、他にも「イベントの取得」や「イベントの削除」など、端末内のカレンダーを操作するロジックは一通り揃っています。

アプリに表示している情報を端末カレンダーに反映させたい場合に役立つので是非使ってみてはいかがでしょうか。

Discussion