亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Cordova創(chuàng)建系統(tǒng)日歷事件

snowLu / 1167人閱讀

摘要:在制作一款打卡的時候有這么一個需求創(chuàng)建提醒到系統(tǒng)日歷中,也就是利用系統(tǒng)日歷來做事件的提醒,這么做的好處很明顯,無需處理提醒的細節(jié),也無需后臺。

在制作一款打卡App的時候有這么一個需求 -- 創(chuàng)建提醒到系統(tǒng)日歷中,也就是利用系統(tǒng)日歷來做事件的提醒,這么做的好處很明顯,App無需處理提醒的細節(jié),也無需后臺。這個App是基于Cordova開發(fā)的,并沒有訪問系統(tǒng)日歷的接口,我們只能通過插件來完成,這是一個有趣的挑戰(zhàn)。

APP設(shè)計

請看下圖,App允許創(chuàng)建事項時,可以設(shè)置重復(fù),開始,結(jié)束和提醒時間四個選項:

這四個選項對創(chuàng)建到日歷的事件都有影響:

重復(fù) 可以設(shè)置一周中的任意幾天,比如選擇周一到周五表示只要工作日。

開始 從哪天天開始

結(jié)束 到哪天結(jié)束

提醒時間 在每天的哪個時間發(fā)出提醒

這個四個組合起來就構(gòu)成一個日歷事件。

插件

Cordova平臺實際上是一個基于web的平臺,所以除了webview提供的能力,其他和設(shè)備交互的功能全部依賴于插件來完成,插件的安裝和使用通常并不困難,比如增加一個關(guān)于狀態(tài)欄控制的插件,可以在項目下這么做:

cordova plugin add cordova-plugin-statusbar

然后在js里調(diào)用插件提供的接口就可以了,更多的關(guān)于cordova平臺和插件的使用,我有一個視頻課程可以參考。很明顯,創(chuàng)建系統(tǒng)日歷事件也需要通過插件來做,搜索之后我們可以發(fā)現(xiàn),完成這個功能的插件并不多,其中使用比較多的是cordova-plugin-calendar,試著安裝

cordova plugin add cordova-plugin-calendar

這個插件可以支持android和iOS,我們現(xiàn)在android下測試,首先在js里寫下下面的代碼:

let calOptions = window.plugins.calendar.getCalendarOptions()
calOptions.firstReminderMinutes = 0
calOptions.secondReminderMinutes = null
calOptions.recurrenceEndDate = actionRemindEnd(action)
if (action.repeat.length === 7) {
  calOptions.recurrence = "daily"
}
else {
  calOptions.recurrence = "weekly"
  calOptions.recurrenceByDay = dateRepeat2Calendar(action.repeat)
}
window.plugins.calendar.createEventWithOptions(
  action.name, null, "dayday", eventTime, new Date(eventTime.getTime() + 15 * 60000), calOptions,
  (result) => {
  }, (err) => {
  })

action保存了用戶所創(chuàng)建的一個活動事件的所有信息,其中有兩個函數(shù)就不展開了,看起來應(yīng)該可以了,實測的結(jié)果卻是,日歷事件創(chuàng)建起來了,沒有報錯,但是重復(fù)有問題,并沒有能一直重復(fù)下去,在重復(fù)數(shù)次之后,事件就停了,類似下圖這樣,到15號事件就沒有了:

修改插件

在這種情況下,調(diào)試js代碼已經(jīng)沒有什么幫助了,js代碼已經(jīng)完全按照插件的要求來傳遞了參數(shù),只能打開android studio,加載cordova項目下platforms/android下的這個工程,這個工程就是一個標準的android項目,打開之后可以定位到這個插件所提供的源碼文件,找到AbstractCalendarAccessor.java,其中的createEvent函數(shù)完成在android下創(chuàng)建一個日歷事件所做的事情,代碼如下:

public String createEvent(Uri eventsUri, String title, long startTime, long endTime, String description,
                              String location, Long firstReminderMinutes, Long secondReminderMinutes,
                              String recurrence, int recurrenceInterval, String recurrenceWeekstart,
                              String recurrenceByDay, String recurrenceByMonthDay, Long recurrenceEndTime, Long recurrenceCount,
                              String allday,
                              Integer calendarId, String url) {
        ContentResolver cr = this.cordova.getActivity().getContentResolver();
        ContentValues values = new ContentValues();
        final boolean allDayEvent = "true".equals(allday) && isAllDayEvent(new Date(startTime), new Date(endTime));
        if (allDayEvent) {
            //all day events must be in UTC time zone per Android specification, getOffset accounts for daylight savings time
            values.put(Events.EVENT_TIMEZONE, "UTC");
            values.put(Events.DTSTART, startTime + TimeZone.getDefault().getOffset(startTime));
            values.put(Events.DTEND, endTime + TimeZone.getDefault().getOffset(endTime));
        } else {
            values.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
            values.put(Events.DTSTART, startTime);
            values.put(Events.DTEND, endTime);
        }
        values.put(Events.ALL_DAY, allDayEvent ? 1 : 0);
        values.put(Events.TITLE, title);
        // there"s no separate url field, so adding it to the notes
        if (url != null) {
            if (description == null) {
                description = url;
            } else {
                description += " " + url;
            }
        }
        values.put(Events.DESCRIPTION, description);
        values.put(Events.HAS_ALARM, firstReminderMinutes > -1 || secondReminderMinutes > -1 ? 1 : 0);
        values.put(Events.CALENDAR_ID, calendarId);
        values.put(Events.EVENT_LOCATION, location);

        if (recurrence != null) {
            String rrule = "FREQ=" + recurrence.toUpperCase() +
                    ((recurrenceInterval > -1) ? ";INTERVAL=" + recurrenceInterval : "") +
                    ((recurrenceWeekstart != null) ? ";WKST=" + recurrenceWeekstart : "") +
                    ((recurrenceByDay != null) ? ";BYDAY=" + recurrenceByDay : "") +
                    ((recurrenceByMonthDay != null) ? ";BYMONTHDAY=" + recurrenceByMonthDay : "") +
                    ((recurrenceEndTime > -1) ? ";UNTIL=" + nl.xservices.plugins.Calendar.formatICalDateTime(new Date(recurrenceEndTime)) : "") +
                    ((recurrenceCount > -1) ? ";COUNT=" + recurrenceCount : "");
            values.put(Events.RRULE, rrule);
        }

        String createdEventID = null;
        try {
            Uri uri = cr.insert(eventsUri, values);
            createdEventID = uri.getLastPathSegment();
            Log.d(LOG_TAG, "Created event with ID " + createdEventID);

            if (firstReminderMinutes > -1) {
                ContentValues reminderValues = new ContentValues();
                reminderValues.put("event_id", Long.parseLong(uri.getLastPathSegment()));
                reminderValues.put("minutes", firstReminderMinutes);
                reminderValues.put("method", 1);
                cr.insert(Uri.parse(CONTENT_PROVIDER + CONTENT_PROVIDER_PATH_REMINDERS), reminderValues);
            }

            if (secondReminderMinutes > -1) {
                ContentValues reminderValues = new ContentValues();
                reminderValues.put("event_id", Long.parseLong(uri.getLastPathSegment()));
                reminderValues.put("minutes", secondReminderMinutes);
                reminderValues.put("method", 1);
                cr.insert(Uri.parse(CONTENT_PROVIDER + CONTENT_PROVIDER_PATH_REMINDERS), reminderValues);
            }
        } catch (Exception e) {
            Log.e(LOG_TAG, "Creating reminders failed, ignoring since the event was created.", e);
        }
        return createdEventID;
    }

這段代碼并不長,在Android Studio下設(shè)置斷點,連接真機調(diào)試,發(fā)現(xiàn)整個過程沒有任何錯誤,日歷事件已經(jīng)創(chuàng)建起來,但就是重復(fù)次數(shù)不正確。好吧,找到android api參考,看看官方文檔中怎么說的:

Here are the rules for inserting a new event:

You must include CALENDAR_ID and DTSTART.

You must include an EVENT_TIMEZONE. To get a list of the system"s installed time zone IDs, use getAvailableIDs(). Note that this rule does not apply if you"re inserting an event through the INSERT Intent, described in Using an intent to insert an event—in that scenario, a default time zone is supplied.

For non-recurring events, you must include DTEND.

For recurring events, you must include a DURATION in addition to RRULE or RDATE. Note that this rule does not apply if you"re inserting an event through the INSERT Intent, described in Using an intent to insert an event—in that scenario, you can use an RRULE in conjunction with DTSTART and DTEND, and the Calendar application converts it to a duration automatically.

仔細對照代碼和文檔,我們發(fā)現(xiàn)DURATION這個參數(shù)并沒有按照文檔來傳遞,好吧,我們修改一下關(guān)鍵代碼:

if (allDayEvent) {
  //all day events must be in UTC time zone per Android specification, getOffset accounts for daylight savings time
  values.put(Events.EVENT_TIMEZONE, "UTC");
  values.put(Events.DTSTART, startTime + TimeZone.getDefault().getOffset(startTime));
  if (recurrence == null) {
    values.put(Events.DTEND, endTime + TimeZone.getDefault().getOffset(endTime));
  } else {
    values.put(Events.DURATION, "P" + ((endTime - startTime) / (24 * 60 * 60000)) + "D");
  }
} else {
  values.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
  values.put(Events.DTSTART, startTime);
  if (recurrence == null) {
    values.put(Events.DTEND, endTime);
  } else {
    values.put(Events.DURATION, "P" + ((endTime - startTime) / 60000) + "M");
  }
}

修改后的代碼再次測試,這次ok了,這個例子表明了cordova生態(tài)的一個現(xiàn)象,插件質(zhì)量參差不齊,有些插件可能需要我們的修改才能工作。

應(yīng)用修改

為了使用修改后的插件,我們可以刪除原來的插件,使用fork并修改后的插件,很簡單,方法如下:

cordova plugin remove cordova-plugin-calendar
cordova plugin add https://github.com/i38/Calendar-PhoneGap-Plugin.git

所有其他代碼都不用修改,這是cordova很靈活的一個地方,這樣一切都ok了,最后附上完整App的鏈接,有興趣可以參考: 天天。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/99841.html

相關(guān)文章

  • cordova研習(xí)筆記(二) —— cordova 6.X 源碼解讀(上)

    摘要:本文源碼為版本。的代碼結(jié)構(gòu)也是一個很經(jīng)典的定義結(jié)構(gòu)構(gòu)造函數(shù)實例修改函數(shù)原型共享實例方法,它提供事件通道上事件的訂閱撤消訂閱調(diào)用。 前言 cordova(PhoneGap) 是一個優(yōu)秀的經(jīng)典的中間件框架,網(wǎng)上對其源代碼解讀的文章確實不多,本系列文章試著解讀一下,以便對cordova 框架的原理理解得更深入。本文源碼為cordova android版本6.1.2。 源碼結(jié)構(gòu) 我們使用IDE...

    Java_oldboy 評論0 收藏0
  • vue和cordova項目整合打包,并實現(xiàn)vue調(diào)用android的相機的demo

    摘要:經(jīng)過網(wǎng)上查找很多資料,發(fā)現(xiàn)很多只有的項目整合,但是使用插件的文章很少,現(xiàn)在把從創(chuàng)建和創(chuàng)建到使用插件到項目打包到手機運行過程記錄下來先上項目結(jié)構(gòu)目錄項目創(chuàng)建安裝環(huán)境這個這邊就不描述了,網(wǎng)上很多教程創(chuàng)建應(yīng)用創(chuàng)建項目為目錄命名空間項目名稱添加平臺 經(jīng)過網(wǎng)上查找很多資料,發(fā)現(xiàn)很多只有vue+cordova的項目整合,但是vue使用cordova插件的文章很少,現(xiàn)在把從創(chuàng)建cordova和創(chuàng)建v...

    zhonghanwen 評論0 收藏0
  • vue和cordova項目整合打包,并實現(xiàn)vue調(diào)用android的相機的demo

    摘要:經(jīng)過網(wǎng)上查找很多資料,發(fā)現(xiàn)很多只有的項目整合,但是使用插件的文章很少,現(xiàn)在把從創(chuàng)建和創(chuàng)建到使用插件到項目打包到手機運行過程記錄下來先上項目結(jié)構(gòu)目錄項目創(chuàng)建安裝環(huán)境這個這邊就不描述了,網(wǎng)上很多教程創(chuàng)建應(yīng)用創(chuàng)建項目為目錄命名空間項目名稱添加平臺 經(jīng)過網(wǎng)上查找很多資料,發(fā)現(xiàn)很多只有vue+cordova的項目整合,但是vue使用cordova插件的文章很少,現(xiàn)在把從創(chuàng)建cordova和創(chuàng)建v...

    QiuyueZhong 評論0 收藏0
  • cordova研習(xí)筆記(一) —— 初試牛刀之cordova.js概要

    摘要:任何初始化任務(wù)應(yīng)該在文件中的事件的事件處理函數(shù)中。這個配置文件有幾個地方很關(guān)鍵,一開始沒有認真看,將插件導(dǎo)進工程跑的時候各種問題,十分頭痛,不得不重新認真看看文檔。 前言 來新公司的第一個任務(wù),研究hybrid App中間層實現(xiàn)原理,做中間層插件開發(fā)。這個任務(wù)挺有意思,也很有挑戰(zhàn)性,之前在DCloud雖然做過5+ App開發(fā),但是中間層的東西確實涉及不多。本系列文章屬于系列開篇cord...

    buildupchao 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<