uni-app调用Native.jsAPI实现对Android原生日历的增删查操作

4 篇文章 1 订阅


前言

最近的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的一些原生事件其实很不友好,而且文档也比较少,但是总结一句话就是:见识少,革命未成功,同志需努力。共勉~

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值