1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android日历信息获取错误 flutter对android的日历数据相关操作

android日历信息获取错误 flutter对android的日历数据相关操作

时间:2021-02-02 17:35:50

相关推荐

android日历信息获取错误 flutter对android的日历数据相关操作

系统日历

三个不同URL的作用

每个url通过contentProvider能获得对应数据库的访问句柄,所以可以理解三个url对应三个数据库,如果通过一个事件关联3个库呢,下面会详细介绍。

数据库介绍参考链接

//对系统日历插入行程事件的url

private static String CALANDER_EVENT_URL = "content://com.android.calendar/events";

//此表储存日历特定信息。 此表中的每一行都包含一个日历的详细信息,例如名称、颜色、同步信息等。

private static String CALANDER_URL = "content://com.android.calendar/calendars";

//为日历中的行程事件添加提醒功能,就是通过系统通知栏告知你今天有什么行程

private static String CALENDER_REMINDER_URL = "content://com.android.calendar/reminders";

同个事件关联不同表

这里以关联行程事件表和事件提醒表为例子进行说明

使用为uri: content://com.android.calendar/events,日历插入一个行程事件,使用ContentProvider进行数据库插入数据时,方法会返回一个Uri。如果插入失败,这个Uri为空;如果成功,则不为空。

ContentValues event = new ContentValues();

//事件的起始时间

event.put("dtstart", startDateMis);

if (cyclerType == 0) {

//如果不是循环事件,添加事件的结束事件

event.put("dtend", endDateMis);

} else {

//如果是循环事件,添加持续事件

long durationSecondTime = (endDateMis - startDateMis) / 1000;

event.put(CalendarContract.Events.DURATION, String.format("P%dS", durationSecondTime));

}

//日历id,必须要有,可以通过**CALANDER_URL**查询获取其id

event.put("calendar_id", calId);

event.put("title", title);

event.put("description", note);

event.put("hasAlarm", 1);

event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());//这个是时区,必须有

//这里的URL是event_url,别看错了

Uri events = activity.getContentResolver().insert(Uri.parse(CALANDER_EVENT_URL), event);

等待insert插入数据后,拿到Uri,使用uri:content://com.android.calendar/reminders,为我们的行程事件添加一个事件提醒功能,下面我们就可以开始把当前的数据的id关联到事件提醒功能表单中。

注意:关键代码ContentUris.parseId(Uri uri),将Uri转成关联表的id。

//重新生成一个ContentValues对象,用于插入 事件提醒功能 的表单中

ContentValues values = new ContentValues();

//将上面insert插入数据生成的uri转成id,再塞到 事件提醒功能 的表单作为关联id

values.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(events));

//提前到什么时候进行提示

values.put(CalendarContract.Reminders.MINUTES, 15);

//提醒的方式

values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);

Uri uri = activity.getContentResolver().insert(Uri.parse(CALENDER_REMINDER_URL), values);

到这里为止,我们就成功的为系统日历添加上event

如何获取android日历读取权限

这篇文章重点不在于讲解flutter如何与native通信,如果想看的可以连接下Registrar类与Channel类,大概是内存块映射关系。我会抽时间总结下如何通信这块再出一篇文章。

着重讲下权限问题,因为在android 6.0以上日历读写权限是需要动态申请的。下面就是flutter层如何申请android权限的问题。

第一步

在android目录的mainfest文件写入需要的权限

package="xxxxxxxxx">

//读日历数据

//写日历数据

第二步

在android代码中判断sdk版本,大于6.0动态申请权限

//REQUEST_CALENDAR_PERMISSION是requestCode,用来判断用户是否点击允许该权限了

public static int REQUEST_CALENDAR_PERMISSION = 10;

//ActivityCompat为androidx的包

requestCalendarAuthorization () {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_CALENDAR,

Manifest.permission.READ_CALENDAR}, REQUEST_CALENDAR_PERMISSION);

} else {

result.success(1)

}

}

第三步

为flutter注册方法映射入口,静态注册入口。permissions为映射句柄的名字。

问题:在这一步卡了很久,因为动态获取权限乃是要在onRequestPermissionsResult方法中才能知道用户是否点击了允许。但是我又不在不能拿到完全的activity,怎么能实现这个方法呢。后面才知道google官网已经把一切都考虑很全面了。查看Registrar类可以看到能添加各种各样的回调用来响应原生层的方法。

//android层面

@JvmStatic

fun registerWith(registrar: Registrar) {

mContext = registrar.context()

mActivity = registrar.activity()

val channel = MethodChannel(registrar.messenger(), "permissions")

//设置映射方法调用的回调,A类是实现MethodCallHandler方法的类

channel.setMethodCallHandler(A())

//设置动态获取权限的结果回调。

registrar.addRequestPermissionsResultListener { id, permissions, grantResults ->

//这里要注意通过grantResults来判断用户是同意还是拒绝权限

return if (requestCode == REQUEST_CALENDAR_PERMISSION && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

mCurrentResult?.success(1)

mCurrentResult = null

true

} else {

mCurrentResult?.success(0)

mCurrentResult = null

false

}

}

}

//当映射的方法调用时候,就能在onMethodCall找到相应方法;

//call:方法名 result:用于把结果回调给flutter

override fun onMethodCall(call: MethodCall, result: Result) {

when {

call.method == "requestPermission" -> {

//记录当前方法的result引用,用于等待权限结果回来时候回调给flutter

mCurrentResult = result

//第二步的方法

requestCalendarAuthorization()

}

……

}

}

flutter层调用

//生命调用的句柄:permissions

static const MethodChannel _channel = const MethodChannel('permissions');

//直接映射方法名,这里的result就会收到0 or 1

var result = await _channel.invokeMethod('requestPermission');

问题

如何能拿到Activity的onRequestPermissionsResult方法呢?

解决办法:通过Registrar类添加listener

不在mainfest里面声明权限,只是代码动态获取,然后没有弹窗让用户选择是否允许。就是在《如何获取android日历读取权限-第一步》我跳过了,直接从第二步开始,没有权限弹窗出现。

解决办法:把第一步加上,重新跑就可以了。好像是mainfest里面如果不声明权限的话,你手机-应用权限管理:看不到日历权限这一个开关的。所以自然也不会弹窗让用户选择是否允许打开。

添加无限循环事件失败,日历中只循环3次就不出现日程了。

解决办法:在插入Event事件时候要区分是否是循环事件,如果是循环事件则不要tend,需要duration参数。rrule和rdate二选一即可,但是循环事件必须要duration参数,不需要tend。参考链接

//startTime起始时间,endTime终止时间。cyclerType日程事件类型

……

if (cyclerType == 0) {

//如果不是循环事件

event.put("dtend", endDateMis);

} else {

//如果是循环事件

long durationSecondTime = (endDateMis - startDateMis) / 1000;

event.put(CalendarContract.Events.DURATION, String.format("P%dS", durationSecondTime));

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。