前言
最近的uni-app项目中有一个直播日历的功能,同时也需要把对应的直播时间插入到手机的日历中,翻阅了很多资料,但是都是原生Android,类似于偏向前端的这种文章比较少,于是就记录下来。
以下为实际操作的一些效果
添加成功后:
一、引入插件(uni-app插件市场)
文前说到项目是uni-app项目,所以在插件市场引入对应的全下判断的插件插件地址,成功下载。
二、使用步骤
1.手机系统日历操作需要添加权限才能操作
在manifest.json文件中找到对应权限并勾选:
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
在App.vue页面中初始化:
onShow() {
console.log('App Show')
// #ifdef APP-PLUS
let that = this;
that.requestAndroidPermission('android.permission.READ_CALENDAR'); // 读取日历
that.requestAndroidPermission('android.permission.WRITE_CALENDAR'); // 写入日历
// #endif
},
methods:{
async requestAndroidPermission(permisionID) {
var result = await permision.requestAndroidPermission(permisionID)
console.log(result)
var strStatus;
if (result == 1) {
strStatus = "已获得授权"
} else if (result == 0) {
strStatus = "未获得授权"
} else {
strStatus = "被永久拒绝权限"
}
},
}
2.在对应的页面中进行使用
很多操作之前都必须要进行权限的获取,有权限则进行下一步操作,否则不允许操作,直接上代码了,文章中许多关键的地方都写了注释,可以在使用过程中进行一步步打印看结果,了解实际的一些逻辑操作。
<template>
<div class="test">
日历
</div>
</template>
<script>
var calanderURL = "content://com.android.calendar/calendars";
var calanderEventURL = "content://com.android.calendar/events";
var calanderRemiderURL = "content://com.android.calendar/reminders";
var calId; //日历账户id
export default {
data() {
return {
oneDayTime: 1000 * 60 * 60 * 24, //一天的毫秒数
currentTime: new Date().getTime(), //当前时间的时间戳(毫秒)
nextTime: 0,
}
},
onLoad() {
this.nextTime = this.currentTime + this.oneDayTime * 15;
// 设置播放器宽高,一般宽度铺满全屏,宽高比是16:9
console.log(calanderURL)
this.getplatform();
},
onUnload() {
},
methods: {
// 获取手机平台
getplatform() {
uni.getSystemInfo({
success: res => {
if (res.platform === 'android') {
// 1.新增日历事件
// this.addEvent({
// title: '中级会计师直播课',
// subtitle: '这是副标题',
// description: '这就是备注',
// dtstart: '1662076800000',
// dtend: '1662084000000',
// inAdvance: 10
// })
// 2.删除日历事件 (参数传入ID,需要根据实际条件去遍历对应的事件ID,打印数据里面有一个_id)
this.deleteEvent(29); //此处填写死数据,是为了测试删除操作
// 3.查询日历事件
// this.queryEvent().then(res=>{
// console.log(res)
// }).catch(err=>{
// console.log(err)
// })
}
}
})
},
// * 获取日历权限 *
getCalendarJurisdiction() {
return new Promise((resolve, reject) => {
plus.android.requestPermissions(['android.permission.READ_CALENDAR',
'android.permission.WRITE_CALENDAR'
],
function(e) {
if (e.deniedAlways.length > 0) { //权限被永久拒绝
// 弹出提示框解释为何需要定位权限,引导用户打开设置页面开启
console.log('Always Denied!!! ' + e.deniedAlways.toString());
reject({
data: -1,
message: "权限被永久拒绝了"
})
}
if (e.deniedPresent.length > 0) { //权限被临时拒绝
reject({
data: 0,
message: "权限被临时拒绝了"
})
// 弹出提示框解释为何需要定位权限,可再次调用plus.android.requestPermissions申请权限
console.log('Present Denied!!! ' + e.deniedPresent.toString());
}
if (e.granted.length > 0) { //权限被允许
//调用依赖获取定位权限的代码
resolve({
data: 1,
message: "ok"
})
}
})
})
},
// 新增日历
/*
第一步 :获取操作日历权限,然后获取app对应的日历账号,如果不存在则调用方法创建日历账号,返回账号ID,即calendar_id
然后通过calendar_id插入日历事件,返回事件ID,根据事件ID 插入日历提醒
*/
addEvent(Obj) {
var that = this;
var Cursor = plus.android.importClass("android.database.Cursor");
var Uri = plus.android.importClass("android.net.Uri");
var Calendar = plus.android.importClass("java.util.Calendar");
var main = plus.android.runtimeMainActivity();
// 权限查询函数 getCalendarJurisdiction
that.getCalendarJurisdiction().then(res => {
// 查询是否有日历账号
var calendarAccountList = plus.android.invoke(main.getContentResolver(), 'query', Uri.parse(
calanderURL), null, null, null, null);
var count = plus.android.invoke(calendarAccountList, "getCount"); //获取账号条数 null或者 数字
console.log(count, plus.android.invoke(calendarAccountList, 'moveToNext'))
var tampArr = []
while (plus.android.invoke(calendarAccountList, 'moveToNext')) {
let tampObj = {}
var keyLen = plus.android.invoke(calendarAccountList, 'getColumnCount');
console.log(keyLen)
for (var i = 0; i < keyLen; i++) {
var tampKey = plus.android.invoke(calendarAccountList, 'getColumnName', i);
var tampVal = plus.android.invoke(calendarAccountList, 'getString', plus.android
.invoke(calendarAccountList,
'getColumnIndex',
tampKey));
tampObj[tampKey] = tampVal;
}
tampArr.push(tampObj);
}
console.log(tampArr); //日历账号
// 查询是否有固定账号
var isHasAccout = false;
var accout_id = null;
tampArr.forEach(item => {
if (item.name == 'csw') {
accout_id = item._id;
isHasAccout = true;
}
})
// 如果有账号直接写入日历
if (isHasAccout) {
Obj.calendar_id = accout_id;
that.addEvent_tabel(Obj)
} else {
console.log(111)
// 添加账号
accout_id = that.initCalendars();
console.log(accout_id)
Obj.calendar_id = accout_id; //日历账户id
that.addEvent_tabel(Obj)
}
}).catch(err => {
console.log(err);
console.log('被拒绝或被临时拒绝')
})
},
/*
* 添加日历到表格
* calendar_id:日历账户id (不需要自己传进来,或根据账户匹配你首先设置的,得到对应的账户id)
* title:标题
* subtitle:副标题
* description:描述 (其实就是备注)
* dtstart: 开始时间
* dtend: 结束时间
* inAdvance:多少分钟前提醒
*/
// 添加日历到表格
addEvent_tabel(Obj) {
var Cursor = plus.android.importClass("android.database.Cursor");
var Uri = plus.android.importClass("android.net.Uri");
var Calendar = plus.android.importClass("java.util.Calendar");
var main = plus.android.runtimeMainActivity();
var TimeZone = plus.android.importClass("java.util.TimeZone");
var timeZone = TimeZone.getDefault();
var ContentValues = plus.android.importClass("android.content.ContentValues");
var values = new ContentValues();
values.put("calendar_id", Obj.calendar_id);
values.put("title", Obj.title); //标题
values.put("eventLocation", Obj.subtitle); //副标题
values.put("description", Obj.description); //时间描述(就是备注)
values.put("eventTimezone", plus.android.invoke(timeZone, "getID")); // 这个是时区,必须有,
values.put("dtstart", Obj.dtstart); //开始时间(时间戳毫秒)
values.put("dtend", Obj.dtend); //结束时间(时戳毫秒)
values.put("hasAlarm", 1); //是否闹钟提醒 默认提醒 因为大部分手机未实现此功能 故未实现
var mCalendar = Calendar.getInstance();
plus.android.invoke(mCalendar, "set", Calendar.HOUR_OF_DAY, 13); //设置小时制 此处为24小时制
plus.android.invoke(mCalendar, "set", Calendar.MINUTE, 0); //补0
// 添加事件
var newEvent = plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse(calanderEventURL),
values);
console.log(newEvent);
// 事件提醒的设定
var id = plus.android.invoke(newEvent, 'getLastPathSegment'); //事件的 ID
console.log(id);
var remindersObj = new ContentValues();
remindersObj.put('event_id', id);
// 提前5分钟有提醒
remindersObj.put('minutes', Obj.inAdvance); //多少分钟前提醒
remindersObj.put('method', '1');
plus.android.invoke(main.getContentResolver(), 'insert', Uri.parse(calanderRemiderURL), remindersObj);
console.log('设置提醒成功');
},
//添加账户
initCalendars() {
var TimeZone = plus.android.importClass("java.util.TimeZone");
var timeZone = TimeZone.getDefault();
var ContentValues = plus.android.importClass("android.content.ContentValues");
var value = new ContentValues();
var Calendars = plus.android.importClass("android.provider.CalendarContract.Calendars");
value.put("name", "csw");
value.put("account_name", "corty919@163.com");
value.put("account_type", "com.android.exchange");
value.put("calendar_displayName", "csw");
value.put("visible", 1);
value.put("calendar_color", "-9206951");
value.put("calendar_access_level", "700");
value.put("sync_events", 1);
value.put("calendar_timezone", plus.android.invoke(timeZone, "getID"));
value.put("ownerAccount", "corty919@163.com");
value.put("canOrganizerRespond", 0);
var Uri = plus.android.importClass("android.net.Uri");
var calendarUri = Uri.parse(calanderURL);
var buildUpon = plus.android.invoke(calendarUri, "buildUpon");
var CalendarContract = plus.android.importClass("android.provider.CalendarContract");
plus.android.invoke(buildUpon, "appendQueryParameter", CalendarContract.CALLER_IS_SYNCADAPTER, "true");
plus.android.invoke(buildUpon, "appendQueryParameter", "account_name", "corty919@163.com");
plus.android.invoke(buildUpon, "appendQueryParameter", "account_type", "com.android.exchange");
calendarUri = plus.android.invoke(buildUpon, "build");
var newAccoutList = plus.android.invoke(plus.android.runtimeMainActivity().getContentResolver(), "insert",
calendarUri,
value);
var newAccout_id;
newAccout_id = plus.android.invoke(plus.android.invoke(newAccoutList, "getPathSegments"), "get", 1);
return newAccout_id;
},
/*
* cs 2020-9-28
* 删除日历
* event_id 事件的ID
* success 成功回调
* error 失败回调
*/
deleteEvent(event_id) {
console.log(111, event_id)
var that = this;
var Uri = plus.android.importClass("android.net.Uri");
var main = plus.android.runtimeMainActivity();
var ContentUris = plus.android.importClass('android.content.ContentUris');
that.getCalendarJurisdiction().then(res => {
try {
var deleteUri = ContentUris.withAppendedId(Uri.parse(calanderEventURL), event_id);
var rows = plus.android.invoke(main.getContentResolver(), "delete", deleteUri, null, null);
console.log(rows)
} catch (e) {
console.log(e)
//TODO handle the exception
}
}).catch(err => {})
},
/*
* 查询日历
*/
queryEvent(Obj) {
console.log(55);
var that = this;
var Uri = plus.android.importClass("android.net.Uri");
var main = plus.android.runtimeMainActivity();
return new Promise((resolve, reject) => {
that.getCalendarJurisdiction().then(res => {
var userCursor = plus.android.invoke(main.getContentResolver(), "query", Uri.parse(
calanderEventURL), null, null, null, null);
var count = plus.android.invoke(userCursor, "getCount");
var tampArr = []
while (plus.android.invoke(userCursor, 'moveToNext')) {
let tampObj = {}
var keyLen = plus.android.invoke(userCursor, 'getColumnCount');
for (var i = 0; i < keyLen; i++) {
var tampKey = plus.android.invoke(userCursor, 'getColumnName', i);
var tampVal = plus.android.invoke(userCursor, 'getString', plus.android
.invoke(
userCursor, 'getColumnIndex',
tampKey));
tampObj[tampKey] = tampVal;
}
tampArr.push(tampObj);
}
console.log(tampArr)
resolve(tampArr)
}).catch(err => {
reject([])
})
})
}
}
}
</script>
<style>
.title {
text-align: center;
}
.btn {
margin-top: 25rpt;
}
</style>
总结
对一个前端来说,去操作Andriod的一些原生事件其实很不友好,而且文档也比较少,但是总结一句话就是:见识少,革命未成功,同志需努力。共勉~