uni-app mui(准确的说是html5+)Android原生日历提醒插入案例踩坑经历

发布于 1周前 作者 wuwangju 来自 Uni-App

uni-app mui(准确的说是html5+)Android原生日历提醒插入案例踩坑经历

缘起
需要在app里弄个定时提醒功能

过程
在问答社区看到一个大佬分享的安卓插入日历提醒的按理
点击这里过去看看???

但是
看得有点晕,很多代码都不知道在干嘛(毕竟不懂原生)
开始的时候就原样复制了一遍代码,也没怎么看,心想着能把项目完成了再说

后来发现
没登录日历账号的手机不能设置提醒,反正就是各种报错
好了,不说心路历程了
直接上干货
(html和引入date picker就省略了哈)

(function($) {  
var setcalendar = function() {  
    $.toast('功能加载中,请稍后', {  
        type: 'div',  
        duration: 1000  
    });  
};  
$.plusReady(function() {  
    var calanderURL = 'content://com.android.calendar/calendars',  
        ContentValues = plus.android.importClass("android.content.ContentValues"),  
        Uri = plus.android.importClass('android.net.Uri'),  
        Calendar = plus.android.importClass('java.util.Calendar'),  
        main = plus.android.runtimeMainActivity(),  
        userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null),  
        userCursor_count = plus.android.invoke(userCursor, 'getCount'),  
        TimeZone = plus.android.importClass('java.util.TimeZone'),  
        TimeZone_str = plus.android.invoke(TimeZone.getDefault(), 'getID');  
    setcalendar = function(title, description, date_str) {  
        if(userCursor_count <= 0) {//如果没有日历账户  
            var account = new ContentValues(),  
                buildUpon = plus.android.invoke(Uri.parse(calanderURL), 'buildUpon'),  
                CalendarContract = plus.android.importClass('android.provider.CalendarContract');  
            plus.android.invoke(buildUpon, 'appendQueryParameter', CalendarContract.CALLER_IS_SYNCADAPTER, 'true');  
            plus.android.invoke(buildUpon, 'appendQueryParameter', 'account_name', 'someone@something.com');  
            plus.android.invoke(buildUpon, 'appendQueryParameter', 'account_type', 'com.android.exchange');  
            //设置账户信息  
            account.put('name', 'someone');  
            account.put('account_name', 'someone@something.com');  
            account.put('account_type', 'com.android.exchange');  
            account.put('calendar_displayName', 'someone_calendar');  
            account.put('visible', 1);  
            account.put('calendar_color', '-9206951');  
            account.put('calendar_access_level', '700');  
            account.put('sync_events', 1);  
            account.put('calendar_timezone', TimeZone_str);  
            account.put('ownerAccount', 'someone@something.com');  
            account.put('canOrganizerRespond', 0);  
            //保存账户信息  
            plus.android.invoke(main.getContentResolver(), 'insert', plus.android.invoke(buildUpon, 'build'), account);  
            //重新定义userCursor  
            userCursor = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(calanderURL), null, null, null, null);  
            //重新定义userCursor_count  
            userCursor_count++;  
        }  
        plus.android.invoke(userCursor, 'moveToLast');  
        var calId = plus.android.invoke(userCursor, 'getString', plus.android.invoke(userCursor, 'getColumnIndex', '_id')),  
            events = new ContentValues(),  
            mCalendar = Calendar.getInstance(),  
            date = date_str.split(/\s{1}|:|-/g);  
        plus.android.invoke(mCalendar, 'set', Calendar.YEAR, ~~date[0]);  
        plus.android.invoke(mCalendar, 'set', Calendar.MONTH, ((~~date[1]) - 1));  
        plus.android.invoke(mCalendar, 'set', Calendar.DATE, ~~date[2]);  
        plus.android.invoke(mCalendar, 'set', Calendar.HOUR_OF_DAY, ~~date[3]);  
        plus.android.invoke(mCalendar, 'set', Calendar.MINUTE, ~~date[4]);  
        var start = plus.android.invoke(plus.android.invoke(mCalendar, 'getTime'), 'getTime'),  
              end = plus.android.invoke(plus.android.invoke(mCalendar, 'getTime'), 'getTime');  
        //设置日历事件  
        events.put('title', title);  
        events.put('description', description);  
        events.put('calendar_id', calId);  
        events.put('dtstart', start);  
        events.put('dtend', end);  
        events.put('hasAlarm', 1);  
        events.put('eventTimezone', TimeZone_str);  
        var newEvent = plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/events'), events);  
        var id = plus.android.invoke(newEvent, 'getLastPathSegment');  
        var values = new ContentValues();  
        values.put('event_id', id);  
        values.put('minutes', '5');  
        values.put('method', '1');  
        plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse('content://com.android.calendar/reminders'), values);  
        $.toast('设置提醒成功');  
    }  
});  
$.ready(function() {  
    $('.mui-content').on('tap', 'button.mui-btn', function() {  
        var picker = new $.DtPicker();  
        picker.show(function(rs) {  
            setcalendar('测试提醒标题', '测试提醒内容', rs.text);  
            picker.dispose();  
        });  
    });  
});  
})(mui);

最后说一句
打包的时候记得勾选日历权限

这个问题坑死我了


1 回复

在uni-app中使用mui(特别是结合html5+扩展API)进行Android原生日历提醒插入时,确实可能会遇到一些坑。以下是一个较为完整的代码案例,以及我在实际开发中遇到的一些问题和解决方案,希望能帮助你避免这些坑。

代码案例

首先,确保你的项目已经正确配置了html5+扩展API的权限。

1. 配置文件

manifest.json中添加必要的权限:

"plus": {
    "distribute": {
        "android": {
            "permissions": [
                "android.permission.READ_CALENDAR",
                "android.permission.WRITE_CALENDAR"
            ]
        }
    }
}

2. 请求权限并插入日历提醒

在JavaScript代码中,首先请求日历权限,然后插入提醒:

// 请求日历权限
plus.android.requestPermissions(['android.permission.READ_CALENDAR', 'android.permission.WRITE_CALENDAR'], function(event) {
    if (event.deniedAlways.length > 0 || event.denied.length > 0) {
        console.error('Calendar permission denied');
    } else {
        insertCalendarReminder();
    }
});

// 插入日历提醒
function insertCalendarReminder() {
    var calendar = plus.android.importClass('android.provider.CalendarContract');
    var contentValues = new plus.android.importClass('android.content.ContentValues');
    contentValues.put(calendar.Events.DTSTART, new Date().getTime()); // 开始时间
    contentValues.put(calendar.Events.DTEND, new Date(new Date().getTime() + 3600 * 1000).getTime()); // 结束时间
    contentValues.put(calendar.Events.TITLE, 'Reminder Title'); // 标题
    contentValues.put(calendar.Events.DESCRIPTION, 'Reminder Description'); // 描述
    contentValues.put(calendar.Events.CALENDAR_ID, 1); // 日历ID,通常使用默认日历
    contentValues.put(calendar.Events.EVENT_TIMEZONE, 'UTC'); // 时区

    var resolver = plus.android.runtimeMainActivity().getContentResolver();
    resolver.insert(calendar.Events.CONTENT_URI, contentValues);

    console.log('Reminder inserted');
}

踩坑经历与解决方案

  1. 权限请求失败:确保在manifest.json中正确配置了权限,并在代码中动态请求权限。
  2. 日历ID获取:直接使用硬编码的日历ID(如1)可能不适用于所有设备。可以通过查询所有日历并选择合适的ID。
  3. 时区问题:时区设置不正确可能导致提醒时间出错。确保使用统一的时区格式。
  4. API兼容性:不同Android版本对日历API的支持可能有所不同,测试时需覆盖多个版本。
  5. 插入失败无反馈:在插入操作后添加错误处理逻辑,如捕获异常并打印日志。

通过上述代码和注意事项,你应该能够在uni-app中较为顺利地进行Android原生日历提醒的插入。如果遇到具体问题,可以进一步调试和排查。

回到顶部