SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Apache Cordovaで本格スマホアプリに挑戦しよう

カレンダーを管理するプラグインを使って、予定の追加と削除を行う

Apache Cordovaで本格スマホアプリに挑戦しよう 第13回

カレンダー内のイベントを管理する(2)

カレンダーからのイベント削除

 イベントを削除するには表4のメソッドを利用します。引数はcreateEventとほぼ同じです。

表4 カレンダーからイベントを削除するメソッド
メソッド名
deleteEvent(title, location, notes, startDate, endDate, calendarName, successCallback, errorCallback)
deleteEventFromNamedCalendar(title, location, notes, startDate, endDa te, calendarName, successCallback, errorCallback)

 指定した引数と一致したイベントを削除します。findEventで取得したイベントのidを指定しても削除はできないので注意が必要です。特定のイベントを削除するには、findEventで取得したデータを使って削除することになります。このあたりは少々使いにくく疑問が残るところです。

リスト2 イベントの削除(js/controllers/EventController.jsの抜粋)
var selectedItem; //  一覧で選択したイベント
// : 省略
$scope.deleteEvent = function(){
    if(device.platform == 'iOS') {
        // (1) iOSの場合
        window.plugins.calendar.deleteEventFromNamedCalendar(
            $scope.model.title,$scope.model.location,$scope.model.notes,$scope.model.startDate,$scope.model.endDate,
            selectedItem.calendar,
            // : 省略
    }
    else {
        //  (2) Androidの場合
        window.plugins.calendar.deleteEvent(
            $scope.model.title,$scope.model.location,$scope.model.notes,$scope.model.startDate,$scope.model.endDate,
            // : 省略
    }
}

 iOSの場合、カレンダーを指定しないと対象のイベントが見つからないようです。そのため、iOSでは(1)のようにdeleteEventFromNamedCalendarを使います。AndroidではdeleteEventFromNamedCalendarメソッドが用意されていないため、(2)のようにdeleteEventを使います。

カレンダーのイベント変更

 イベントの変更はiOSのみでサポートされており、表5のように3つのメソッドがあります。実体として実装されているものは他のメソッドと同様、modifyEventWithOptionsのみです。

表5 イベントを変更するメソッド
メソッド名 備考
modifyEvent(title, location, notes, startDate, endDate, newTitle, new Location, newNotes, newStartDate, newEndDate, successCallback, errorCallb ack) 変更前と変更後の値を指定してイベントを更新
modifyEventInNamedCalendar(title, location, notes, startDate, endDate , newTitle, newLocation, newNotes, newStartDate, newEndDate, calendarName , successCallback, errorCallback) カレンダーを指定して変更前と変更後の値を指定してイベントを更新
modifyEventWithOptions(title, location, notes, startDate, endDate, ne wTitle, newLocation, newNotes, newStartDate, newEndDate, options, newOpti ons, successCallback, errorCallback) オプションを指定して、変更前と変更後の値を指定してイベントを更新

 なお、変更系のメソッドは、Androidでは利用できません。Androidではイベントを一度削除してから、追加することになります。

リスト3 イベントの変更
$scope.modifyEvent = function(){

    // (1) イベントを特定できる情報を設定する
    var opts = window.plugins.calendar.getCalendarOptions();
    opts.id = selectedItem.id;
    opts.calendarName = selectedItem.calendar; // iOSのみ有効

    //  (2) カレンダー変更(指定)する場合のみ指定
    var newOpts = window.plugins.calendar.getCalendarOptions();
    //newOpts.recurrence = 'weekly';
    //newOpts.recurrenceInterval = 2;

    //  (3) 一覧で選択したイベントの情報を取得(変更元情報)
    var org = {
        title : selectedItem.title,
        location : selectedItem.location,
        notes : selectedItem.message,
        startDate : parseDate(selectedItem.startDate),
        endDate  : parseDate(selectedItem.endDate)
    };

    //  (4) イベントを新たな情報に変更
    window.plugins.calendar.modifyEventWithOptions(
        org.title,org.location,org.notes,org.startDate,org.endDate,
        $scope.model.title,$scope.model.location,$scope.model.notes,$scope.model.startDate,$scope.model.endDate,
        opts,
        newOpts,
        function(msg){
            alert("OK Modify: " + msg);
        },function(msg){
            alert("ERR Modify: "+ msg);
        }
    );
}
: // 省略
// (5) 取得した日付(文字列)をDate型に変更
function parseDate(str) {
        var nums = str.match(/\d+/g);

        var year = parseInt(nums[0],10);
        var month = parseInt(nums[1],10) - 1;
        var day = parseInt(nums[2],10);

        var hour = parseInt(nums[3],10);
        var min = parseInt(nums[4],10);
        var sec = parseInt(nums[5],10);
        return new Date(year,month,day,hour,min,sec);
 }

 (1)ではイベントが登録されているカレンダーを指定する際に、findEventで取得したカレンダー名を指定しています。続いて、(2)で変更後のカレンダーのオプション情報を作成し、(3)では変更するカレンダーの情報を設定しています。注意しなければいけない事は、findEventで取得したイベントの開始日時と終了日時がYYYY-MM-DD HH:MM:SS形式の文字列のため、(5)のようにDate型へ変換しています。そして、(4)で画面から入力された情報で変更します。

Android 6.0以降での操作権限について

 Android 6.0以降ではアプリごとに、以下の機能に対しての権限をユーザーが変更できるようになりました。今回紹介したプラグインでも影響が生じています。

  • SMS
  • カメラ
  • カレンダー
  • ストレージ
  • ボディセンサー
  • マイク
  • 位置情報(現在地)
  • 連絡先
  • 電話
  • その他の権限(例:Googleフォトアクセス)

 しかし、iOSと挙動が統一されたため、むしろ分かりやすくなったともいえます。権限が必要なAPIを実行すると、自動的に図2のようなダイアログが表示されます。

図2 Androidでの権限の許諾ダイアログ
図2 Androidでの権限の許諾ダイアログ

 これらの権限は、ダイアログで設定しても後でAndroidの設定画面から変更ができるので、一度許諾しても使えなくなっているケースがあります。

 以前のバージョンのAndroidでは、ユーザーがアプリに対し、権限の利用を一度でも許諾すると、どのタイミングで使われるか分かりませんでした。しかしAndroid 6.0の変更によって、権限を与えても良いかどうかをユーザーが判断しやすくなりました。

権限のチェック

 図2の許諾ダイアログは自動で差し込まれ、そしてコード上何の変更も入らないので(基本的な挙動に従うのであれば)アプリ開発者が書くべきコードはありません。ただし、カレンダープラグインでは表6のメソッドを用いる事で、権限のチェックとダイアログの表示タイミングの制御することもできます。

表6 Android 6.0以上での権限管理のためのメソッド
メソッド名 備考
hasReadPermission(callback) READ_CALENDARの権限が有るかの確認
hasWritePermission(callback) WRITE_CALENDARの権限があるかの確認
hasReadWritePermission(callback) READ_CALENDARとWRITE_CALENDARの権限が有るかの確認
requestReadPermission() READ_CALENDARの権限の要求
requestWritePermission() WRITE_CALENDARの権限の要求
requestReadWritePermission() READ_CALENDARとWRITE_CALENDARの権限の要求
リスト4 イベントの変更
// (1) アクセスする権限があるかどうかを確認する
window.plugins.calendar.hasReadWritePermission(
    function(result) {
        if(result){
            //  権限がある
        }
        else{
            //  (2) 権限がないので、リクエストを求める
            window.plugins.calendar.requestReadWritePermission();
        }
    }
);

 まず、(1)のようにhasReadWritePermissionメソッドで権限の有無を確認します。読み取りのみ、書き込みのみのチェックも可能なので、その場合にはコードを読み替えてください。次に、(2)で権限を求めるダイアログを表示します。しかし、Android 6.0以上の端末であっても、ダイアログが表示されないケースがあります。その場合は、Andorid SDKで使っているバージョンを確認してください。使っているAndroid SDKは、AndroidManifest.xmlから確認できます。

リスト5 Android SDKのバージョン指定(platforms/android/AndroidManifest.xml)
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />

最後に

 今回紹介したカレンダープラグインを実際に利用する場合、AndroidとiOSの違いを知らないと、ドキュメントだけで理解することは難しいかもしれません。筆者も細かい動作についてはそれぞれのネイティブ側のコードを参照しながら理解しました。

 これまでさまざまなプラグインを紹介してきましたが、AndroidやiOSなどの振る舞いの違いを意識せずにコードを記述するのは少々難しい部分もあります。これまでの記事が、それらの理解に少しでも役立てられれば幸いです。

 次回はプラグインではなく、Cordovaアプリをリリース/ビルドする際に必要な設定などについて紹介します。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Apache Cordovaで本格スマホアプリに挑戦しよう連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/9929 2017/02/13 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー