Android 日历管理 Calendars的(日程、提醒)增删改查

掌握Android Calendar类:源码分析与实践指南 本文还有配套的精品资源,点击获取 简介:Android的Calendar类为处理日期和时间提供了一系列API和特性,适应移动设备需求。本文深入探讨了Calendar类的实现细节,包括日期时间的计算、设置、获取和比较,以及事件管理功能。通过分析源码,开发者可以更深入地理解Calendar的工作原理,并解决性能和兼容性问题。此外,文章还将介绍Calendar类的本地化支持和自定... 阅读详情
package com.szwistar.emistar.calendar;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Reminders;
import android.util.Log;

import com.szwistar.emistar.Const;
import com.szwistar.emistar.util.Utils;

/**
 * 日程管理提供者provider
 * @author fukun
 *
 */
public class CalendarsResolver {

	private ContentResolver resolver;
	
	/**
	 * 使用以下Uri时,Android版本>=14;
	 * 注意引用包路径:android.provider.CalendarContract下的; 
	 **/
	private Uri calendarsUri = Calendars.CONTENT_URI;
	private Uri eventsUri = Events.CONTENT_URI;
	private Uri remindersUri = Reminders.CONTENT_URI;
	private Uri attendeesUri = Attendees.CONTENT_URI;
	
	/** Calendars table columns */
	public static final String[] CALENDARS_COLUMNS = new String[] {
	    Calendars._ID,                           // 0
	    Calendars.ACCOUNT_NAME,                  // 1
	    Calendars.CALENDAR_DISPLAY_NAME,         // 2
	    Calendars.OWNER_ACCOUNT                  // 3
	};
	
	/** Events table columns */
	public static final String[] EVENTS_COLUMNS = new String[] {
		Events._ID,
		Events.CALENDAR_ID,
		Events.TITLE,
		Events.DESCRIPTION,
		Events.EVENT_LOCATION,
		Events.DTSTART,
		Events.DTEND,
		Events.EVENT_TIMEZONE,			
		Events.HAS_ALARM,
		Events.ALL_DAY,
		Events.AVAILABILITY,
		Events.ACCESS_LEVEL,
		Events.STATUS,
	};
	/** Reminders table columns */
	public static final String[] REMINDERS_COLUMNS = new String[] {
		Reminders._ID,
		Reminders.EVENT_ID,
		Reminders.MINUTES,
		Reminders.METHOD,
	};
	/** Reminders table columns */
	public static final String[] ATTENDEES_COLUMNS = new String[] {
		Attendees._ID,
		Attendees.ATTENDEE_NAME,
		Attendees.ATTENDEE_EMAIL,
		Attendees.ATTENDEE_STATUS
	};
	
	/**
	 * 构造方法
	 * @param resolver
	 */
	public CalendarsResolver(ContentResolver resolver) {
		this.resolver = resolver;
	}
	
	/**
	 * 获取时区
	 * @return String[]
	 */
	public static String[] getTimeZones(){
		return TimeZone.getAvailableIDs();
	}
	/**
	 * 更新日程提醒
	 * @param param
	 * @param ops
	 * @return Uri
	 * @throws Exception 
	 */
	public Map<String, String> updateReminder(Map<String, String> param){
		Map<String, String> result = new HashMap<String, String>();
		if (Utils.isEmpty(param)) {
			result.put("result", "0");
			result.put("obj", "日程提醒更新参数为空!");
			return result;
		}
		String id		= param.get("id");
		if (!isExistReminder(Long.parseLong(id))) {
			result.put("result", "0");
			result.put("obj", "日程提醒id无效,id不存在!");
			return result;
		}
		String mimutes 		= param.get("mimutes");//提醒在事件前几分钟后发出
		String method		= param.get("method");//提醒方法:METHOD_DEFAULT:0,*_ALERT:1,*_EMAIL:2,*_SMS:3
		
		if ( Utils.isEmpty(mimutes) && Utils.isEmpty(method) ){
			result.put("result", "0");
			result.put("obj", "日程提醒更新的信息不能都为空!");
			return result;
		}
		ContentValues reminderVal = new ContentValues();
		
		if (!Utils.isEmpty(mimutes)) {
			//提醒时间
			int m = Utils.isNumber(mimutes) ? Integer.parseInt(mimutes) : 0;
			reminderVal.put(Reminders.MINUTES, m);//提醒在事件前多少分钟后发出
		}
		if (!Utils.isEmpty(method)) {
			//提醒方法
			int methodType = Reminders.METHOD_DEFAULT;
			if (method.equals("1")) {
				methodType = Reminders.METHOD_ALERT;
			} else if (method.equals("2")) {
				methodType = Reminders.METHOD_EMAIL;
			} else if (method.equals("3")) {
				methodType = Reminders.METHOD_SMS;
			}
			reminderVal.put(Reminders.METHOD, methodType);
		}
		
		try{
			int n = resolver.update(remindersUri, reminderVal, Reminders._ID + "=" + id , null);
			result.put("result", "1");
			result.put("obj", n + "");
		} catch (Exception e) {
			Log.i(Const.APPTAG, e.getMessage());
			result.put("result", "-1");
			result.put("obj", e.getMessage());
		}
		return result;
	}
	
	/**
	 * 更新日程参与者
	 * @param param
	 * @param ops
	 * @return Uri
	 * @throws Exception 
	 */
	public Map<String, String> updateAttendee(Map<String, String> param){
		Map<String, String> result = new HashMap<String, String>();
		if (Utils.isEmpty(param)) {
			result.put("result", "0");
			result.put("obj", "更新参数为空!");
			return null;
		}
		String id		= param.get("id");
		if (!isExistAttendee(Long.parseLong(id))) {
			result.put("result", "0");
			result.put("obj", "参与者id无效,id不存在!");
			return null;
		}
		String name 		= param.get("name");//参与者姓名
		String email		= param.get("email");//参与者电子邮件
		if ( Utils.isEmpty(name) && Utils.isEmpty(email) ){
			result.put("result", "0");
			result.put("obj", "参与人更新的信息不能都为空!");
			return result;
		}
		ContentValues attendeesVal = new ContentValues();
		if (!Utils.isEmpty(email)) {
			attendeesVal.put(Attendees.ATTENDEE_NAME, name);
		}
		if (!Utils.isEmpty(email)) {
			attendeesVal.put(Attendees.ATTENDEE_EMAIL, email);//参与者 email
		}
		
		try{
			int n = resolver.update(attendeesUri, attendeesVal, Attendees._ID + "=" + id , null);
			result.put("result", "1");
			result.put("obj", n + "");
		} catch (Exception e) {
			Log.i(Const.APPTAG, e.getMessage());
			result.put("result", "-1");
			result.put("obj", e.getMessage());
		}
		return null;
	}
	/**
	 * 更新日程事件
	 * @param param
	 * @return
	 */
	public Map<String, String> updateEvent(Map<String, String> param){
		Map<String, String> result = new HashMap<String, String>();
		if (Utils.isEmpty(param)) {
			result.put("result", "0");
			result.put("obj", "更新参数为空!");
			return null;
		}
		String id 			= param.get("id");
		if (!isExistEvent(Long.parseLong(id))) {
			result.put("result", "0");
			result.put("obj", "事件id不能为空!");
			return result;
		}
		
		String calendarId 	= param.get("calendarId");
		String title 		= param.get("title");
		String description 	= param.get("description");
		String location 	= param.get("location");
		String startDate	= param.get("startDate");
		String endDate		= param.get("endDate");
		String status		= param.get("status");
		String timeZone		= param.get("timeZone");
		String hasAlarm 	= param.get("hasAlarm");
		String allDay		= param.get("allDay");
		String availability	= param.get("availability");
		String accessLevel	= param.get("accessLevel");
		
		if (!Utils.isNumber(calendarId) && Utils.isEmpty(title) && Utils.isEmpty(description) && Utils.isEmpty(location) 
				&& Utils.isEmpty(startDate) && Utils.isEmpty(endDate) && Utils.isEmpty(status)){
			result.put("result", "0");
			result.put("obj", "事件更新的信息不能都为空!");
			return result;
		}
		ContentValues values = new ContentValues();
		
		if (Utils.isNumber(calendarId)) {
			values.put(Events.CALENDAR_ID, calendarId);
		}
		if (!Utils.isEmpty(title)) {
			values.put(Events.TITLE, title);
		}
		if (!Utils.isEmpty(description)) {
			values.put(Events.DESCRIPTION, description);
		}
		if (!Utils.isEmpty(location)) {
			values.put(Events.EVENT_LOCATION, location);
		}
		
		//计算开始、结束时间,全部用Date也可以。 
		Calendar startCld 	= Calendar.getInstance();
		Calendar endCld 	= Calendar.getInstance();
		//如果是全天事件的话,取开始时间的那一整天
		if ((Utils.isNumber(allDay) && Integer.parseInt(allDay) == 1) && !Utils.isEmpty(startDate)) {
			Calendar cld 		= Calendar.getInstance();
			cld = Utils.parseStrToCld(startDate);
			//开始时间
			startCld.set(cld.get(Calendar.YEAR), cld.get(Calendar.MONTH), cld.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
			//结束时间
			endCld.set(cld.get(Calendar.YEAR), cld.get(Calendar.MONTH), cld.get(Calendar.DAY_OF_MONTH), 24 , 0 , 0);
			values.put(Events.ALL_DAY, true);
			values.put(Events.DTSTART, startCld.getTimeInMillis());
			values.put(Events.DTEND, endCld.getTimeInMillis());
		} else {
			//开始时间
			startCld = Utils.parseStrToCld(startDate);
			//结束时间
			endCld = Utils.parseStrToCld(endDate);
			if (!Utils.isEmpty(startDate)) {
				values.put(Events.DTSTART, startCld.getTimeInMillis());
			}
			if (!Utils.isEmpty(endDate)) {
				values.put(Events.DTEND, endCld.getTimeInMillis());
			}
		}
		if (!Utils.isEmpty(timeZone)) {
			values.put(Events.EVENT_TIMEZONE, timeZone);
		}
		if (Utils.isNumber(hasAlarm)) {
			values.put(Events.HAS_ALARM, hasAlarm);
		}
		if (Utils.isNumber(availability)) {
			values.put(Events.AVAILABILITY, availability);
		}
		if (Utils.isNumber(accessLevel)) {
			values.put(Events.ACCESS_LEVEL, accessLevel);
		}
		try {
			int n = resolver.update(eventsUri, values, Events._ID + "=" + id, null);
			result.put("result", "1");
			result.put("obj", n + "");
		} catch (Exception e) {
			Log.i(Const.APPTAG, e.getMessage());
			result.put("result", "-1");
			result.put("obj", e.getMessage());
		}
		return result;
	} 
	
	/**
	 * 查询日程(事件、提醒、参与人)
	 * @param param
	 * @return
	 */
	public List<Map<String, Object>> queryEvents(Map<String, String> param){
		List<Map<String, Object>> result = new ArrayList<Map<String,Object>>();
		
		StringBuffer selection = new StringBuffer();
		List<String> selectionArgs = new ArrayList<String>();
		if (!Utils.isEmpty(param)) {
			selection.append(" 1=1 ");
			
			String calendarId 	= param.get("calendarId");
			String eventId 		= param.get("id");
			String title 		= param.get("title");
			String description 	= param.get("description");
			String location 	= param.get("location");
			String startDate	= param.get("startDate");
			String endDate		= param.get("endDate");
			String status		= param.get("status");
			
			if (Utils.isNumber(calendarId)) {
				selection.append(" AND " + Events.CALENDAR_ID + "=? ");
				selectionArgs.add(calendarId);
			}
			if (Utils.isNumber(eventId)) {
				selection.append(" AND " + Events._ID + "=? ");
				selectionArgs.add(eventId);
			}
			if (!Utils.isEmpty(title)) {
				selection.append(" AND " + Events.TITLE + " LIKE ? ");
				selectionArgs.add("%" + title + "%");
			}
			if (!Utils.isEmpty(description)) {
				selection.append(" AND " + Events.DESCRIPTION + " LIKE ? ");
				selectionArgs.add("%" + description + "%");
			}
			if (!Utils.isEmpty(location)) {
				selection.append(" AND " + Events.EVENT_LOCATION + " LIKE ? ");
				selectionArgs.add("%" + location + "%");
			}
			if (Utils.isNumber(status)) {
				selection.append(" AND " + Events.STATUS + " =? ");
				selectionArgs.add(status);
			}
			
			if (!Utils.isEmpty(startDate)) {
				long startMillis = Utils.parseStrToCld(startDate).getTimeInMillis();
				selection.append(" AND " + Events.DTSTART + " >=? ");
				selectionArgs.add(startMillis + "");
			}
			if (!Utils.isEmpty(endDate)) {
				long endMillis   = Utils.parseStrToCld(endDate).getTimeInMillis();
				selection.append(" AND " + Events.DTEND + " <=? ");
				selectionArgs.add(endMillis + "");
			}
			Log.i(Const.APPTAG, "查询条件:" + selection.toString());
		}
//		EVENTS_COLUMNS 换成 null 查询所有字段 
		Cursor eventsCursor = resolver.query(
				eventsUri, 
				EVENTS_COLUMNS, 
				selection.length() == 0 ? null : selection.toString(), 
				selectionArgs.size() == 0 ?	null : selectionArgs.toArray(new String[]{}), 
				null);
		
		Map<String, Object> event = new HashMap<String, Object>();
		while (eventsCursor.moveToNext()) {
			//以下字段解释,在添加事件里可查看addEvents()
			String eid 		= eventsCursor.getString(eventsCursor.getColumnIndex(Events._ID));
			String calendarId 	= eventsCursor.getString(eventsCursor.getColumnIndex(Events.CALENDAR_ID));
			String title 		= eventsCursor.getString(eventsCursor.getColumnIndex(Events.TITLE));
			String description 	= eventsCursor.getString(eventsCursor.getColumnIndex(Events.DESCRIPTION));
			String location 	= eventsCursor.getString(eventsCursor.getColumnIndex(Events.EVENT_LOCATION));
			long startDate 		= eventsCursor.getLong(eventsCursor.getColumnIndex(Events.DTSTART));
			long endDate 		= eventsCursor.getLong(eventsCursor.getColumnIndex(Events.DTEND));
			String timeZone 	= eventsCursor.getString(eventsCursor.getColumnIndex(Events.EVENT_TIMEZONE));
			String hasAlarm 	= eventsCursor.getString(eventsCursor.getColumnIndex(Events.HAS_ALARM));
			String allDay 		= eventsCursor.getString(eventsCursor.getColumnIndex(Events.ALL_DAY));
			String availability = eventsCursor.getString(eventsCursor.getColumnIndex(Events.AVAILABILITY));
			String accessLevel 	= eventsCursor.getString(eventsCursor.getColumnIndex(Events.ACCESS_LEVEL));
			String status 		= eventsCursor.getString(eventsCursor.getColumnIndex(Events.STATUS));
			
			Calendar calendar = Calendar.getInstance();
			
			event.put("id",				eid);
			event.put("calendarId",		calendarId);
			event.put("title",			title);
			event.put("description",	description);
			event.put("location",		location);
			
			calendar.setTimeInMillis(startDate);
			event.put("startDate",		Utils.getFormatCld(calendar));
			
			calendar.setTimeInMillis(endDate);
			event.put("endDate",		Utils.getFormatCld(calendar));
			
			event.put("timeZone",		timeZone);
			event.put("hasAlarm",		hasAlarm);
			event.put("allDay",			allDay);
			event.put("availability",	availability);
			event.put("accessLevel",	accessLevel);
			event.put("status",			status);
			//查询提醒
			Cursor remindersCursor = resolver.query(
					remindersUri, 
					REMINDERS_COLUMNS, 
					Reminders.EVENT_ID + "=?", 
					new String[]{ eid }, 
					null);
			
			List<Map<String, Object>> reminders = new ArrayList<Map<String,Object>>();
			while (remindersCursor.moveToNext()) {
				Map<String, Object> reminder = new HashMap<String, Object>();
				
				String rid 		= remindersCursor.getString(remindersCursor.getColumnIndex(Reminders._ID));
				String eventId 	= remindersCursor.getString(remindersCursor.getColumnIndex(Reminders.EVENT_ID));
				String minutes 	= remindersCursor.getString(remindersCursor.getColumnIndex(Reminders.MINUTES));
				String method	= remindersCursor.getString(remindersCursor.getColumnIndex(Reminders.METHOD));
				
				reminder.put("id", 		rid);
				reminder.put("eventId", eventId);
				reminder.put("minutes", minutes);
				reminder.put("method", 	method);
				reminders.add(reminder);
			}
			remindersCursor.close();
			event.put("reminders", reminders);
			//查询参与人
			Cursor attendeesCursor = resolver.query(
					attendeesUri, 
					ATTENDEES_COLUMNS, 
					Attendees.EVENT_ID + "=?", 
					new String[]{ eid }, 
					null);
			
			List<Map<String, Object>> attendees = new ArrayList<Map<String,Object>>();
			while (attendeesCursor.moveToNext()) {
				Map<String, Object> attendee = new HashMap<String, Object>();
				String rid 		= attendeesCursor.getString(attendeesCursor.getColumnIndex(Attendees._ID));
				String name 	= attendeesCursor.getString(attendeesCursor.getColumnIndex(Attendees.ATTENDEE_NAME));
				String email 	= attendeesCursor.getString(attendeesCursor.getColumnIndex(Attendees.ATTENDEE_EMAIL));
				String _status	= attendeesCursor.getString(attendeesCursor.getColumnIndex(Attendees.ATTENDEE_STATUS));
				
				attendee.put("id", 		rid);
				attendee.put("name", 	name);
				attendee.put("email", 	email);
				attendee.put("status", 	_status);
				attendees.add(attendee);
			}
			attendeesCursor.close();
			event.put("attendees", reminders);
			
			result.add(event);
		}
		eventsCursor.close();
		
		return result;
	}
	
	/**
	 * 批量插入日程
	 * @param calendars
	 * @return Map<String, Object>
	 */
	public Map<String, Object> insertEvents(List<Map<String, Object>> calendars) {
		Map<String, Object> result = new HashMap<String, Object>();
		if (Utils.isEmpty(calendars)) {
			result.put("result", "0");
			result.put("obj", "日程信息为空,添加失败!");
			return null;
		}
		List<String> addResult = new ArrayList<String>();
		ArrayList<ContentProviderOperation> ops = null;
		
		for (int i = 0; i < calendars.size(); i++) {
			//获得日程
			Map<String, Object> calendar = calendars.get(i);
			//插入事件
			Uri eUri = null;
			try {
				eUri = insertEvent(calendar);
			} catch (Exception e) {
				addResult.add("第" + (i + 1) + "条日程,添加事件失败:" + e.getMessage());
			}
			//如果事件插入成功,则插入提醒和参与者
			if (!Utils.isEmpty(eUri)) {
				String eventId = eUri.getLastPathSegment();
				//存入插入事件的结果
				addResult.add(eUri.toString());
				
				ops = new ArrayList<ContentProviderOperation>();
				//插入提醒,可以添加多个提醒
				Map<Object, Map<String, String>> reminders = (Map<Object, Map<String, String>>) calendar.get("reminders");
				if (!Utils.isEmpty(reminders)) {
					for (Object key : reminders.keySet()) {
						reminders.get(key).put("eventId", eventId);
						try {
							insertReminder(reminders.get(key), ops);
						} catch (Exception e) {
							Log.i(Const.APPTAG, e.getMessage());
						}
					}
				}
				//插入参与者,可以添加多个参与者
				Map<Object, Map<String, String>> attendees = (Map<Object, Map<String, String>>) calendar.get("attendees");
				if (!Utils.isEmpty(attendees)) {
					for (Object key : attendees.keySet()) {
						attendees.get(key).put("eventId", eventId);
						try {
							insertAttendee(attendees.get(key), ops);
						} catch (Exception e) {
							Log.i(Const.APPTAG, e.getMessage());
						}
					}
				}
				if (!Utils.isEmpty(ops)) {
					//执行批量插入
					try {
						ContentProviderResult[] cps = resolver.applyBatch(CalendarContract.AUTHORITY, ops);
						//event表插入返回的Uri集合
						for (ContentProviderResult cp : cps) {
							Log.i(Const.APPTAG, cp.toString());
							addResult.add(cp.uri.toString());
						}
					} catch (Exception e) {
						Log.i(Const.APPTAG, e.getMessage());
						addResult.add("第" + (i + 1) + "条日程,添加(提醒和参与者)失败:" + e.getMessage());
					}
				}
			}
		}
		result.put("result", "1");
		result.put("obj", addResult);
		 
		return result;
	}
	/**
	 * 插入日程参与者,如果参数ops不为空,则不执行插入,添加到ops里执行批量插入
	 * @param attendees
	 * @param ops
	 * @return Uri
	 * @throws Exception 
	 */
	public Uri insertAttendee(Map<String, String> attendees, ArrayList<ContentProviderOperation> ops) throws Exception{
		if (Utils.isEmpty(attendees)) {
			return null;
		}
		try {
			String eventId		= attendees.get("eventId");//外键事件id
			String name 		= attendees.get("name");//参与者姓名
			//如果时间id、或者参与姓名为空,不添加参与者
			if (!isExistEvent(Long.parseLong(eventId)) || Utils.isEmpty(name)) {
				return null;
			}
			String email		= attendees.get("email");//参与者电子邮件
			
			/** 没明白具体什么意思,暂时用默认值  */
			int relationship	= Attendees.RELATIONSHIP_ATTENDEE;//与会者与事件的关系
			int type			= Attendees.TYPE_OPTIONAL;//与会者的类型
			int status			= Attendees.ATTENDEE_STATUS_INVITED;//与会者的状态
			if (ops == null) {
				ContentValues attendeesVal = new ContentValues();
				attendeesVal.put(Attendees.EVENT_ID, eventId);
				attendeesVal.put(Attendees.ATTENDEE_NAME, name);
				if (!Utils.isEmpty(email)) {
					attendeesVal.put(Attendees.ATTENDEE_EMAIL, email);//参与者 email
				}
				
				attendeesVal.put(Attendees.ATTENDEE_RELATIONSHIP, relationship);//关系
				attendeesVal.put(Attendees.ATTENDEE_TYPE, type);//类型
				attendeesVal.put(Attendees.ATTENDEE_STATUS, status);//状态
				
				Uri uri = resolver.insert(attendeesUri, attendeesVal);
				return uri;
			} else {
				Builder builder = ContentProviderOperation.newInsert(attendeesUri)
						.withYieldAllowed(true)
						.withValue(Attendees.EVENT_ID, eventId)
						.withValue(Attendees.ATTENDEE_NAME, name)
						.withValue(Attendees.ATTENDEE_EMAIL, email)
						.withValue(Attendees.ATTENDEE_RELATIONSHIP, relationship)
						.withValue(Attendees.ATTENDEE_TYPE, type)
						.withValue(Attendees.ATTENDEE_STATUS, status);
				if (!Utils.isEmpty(email)) {
					builder.withValue(Attendees.ATTENDEE_EMAIL, email);
				}
				ops.add(builder.build());
			}
		}catch (Exception e) {
			throw e;
		}
		return null;
	}
	/**
	 * 插入日程提醒,如果参数ops不为空,则不执行插入。
	 * @param reminders
	 * @param ops
	 * @return Uri
	 */
	public Uri insertReminder(Map<String, String> reminders, ArrayList<ContentProviderOperation> ops)
	 	throws Exception {
		//---------------------------Reminders表的数据------------------------------------
		//插入提醒,可以添加多个提醒
		if (!Utils.isEmpty(reminders)) {
			try {
				String eventId		= reminders.get("eventId");//外键事件id
				//如果时间id为空,不添加提醒
				if (!isExistEvent(Long.parseLong(eventId))) {
					return null;
				}
				
				String mimutes 		= reminders.get("mimutes");//提醒在事件前几分钟后发出
				String method		= reminders.get("method");//提醒方法:METHOD_DEFAULT:0,*_ALERT:1,*_EMAIL:2,*_SMS:3
				
				//提醒方法
				int methodType = Reminders.METHOD_DEFAULT;
				if (method.equals("1")) {
					methodType = Reminders.METHOD_ALERT;
				} else if (method.equals("2")) {
					methodType = Reminders.METHOD_EMAIL;
				} else if (method.equals("3")) {
					methodType = Reminders.METHOD_SMS;
				}
				//提醒时间
				int m = Utils.isNumber(mimutes) ? Integer.parseInt(mimutes) : 0;
				
				if (ops == null) {
					ContentValues alarmVal = new ContentValues();
					alarmVal.put(Reminders.EVENT_ID, eventId);
					alarmVal.put(Reminders.MINUTES, m);//提醒在事件前多少分钟后发出
					alarmVal.put(Reminders.METHOD, methodType);
					
					Uri uri = resolver.insert(remindersUri, alarmVal);
					return uri;
				} else {
					ContentProviderOperation op = ContentProviderOperation.newInsert(remindersUri)
							.withYieldAllowed(true)
							.withValue(Reminders.EVENT_ID, eventId)
							.withValue(Reminders.MINUTES, m)
							.withValue(Reminders.METHOD, methodType)
							.build();
					ops.add(op);
				}
			} catch (Exception e) {
				throw e;
			}
		}
		return null;
	}
	
	/**
	 * 插入日程事件
	 * @param events
	 * @return Uri
	 */
	public Uri insertEvent(Map<String, Object> events) throws Exception {
		if (Utils.isEmpty(events)) {
			return null;
		}
		try {
			ContentValues eventVal = new ContentValues();
			//---------------------------Event表的数据------------------------------------
			//插入一条事件,必须满足,有日历id、开始时间、结束时间、和标题或者内容,自定义的,不然插入没有意义
			String calendarId 	= (String) events.get("calendarId");//日历id
			String startDate 	= (String) events.get("startDate");//开始时间:格式=yyyy-MM-dd HH:mm:ss
			String endDate 		= (String) events.get("endDate");//结束时间:格式=yyyy-MM-dd HH:mm:ss
			String title 		= (String) events.get("title");//日程标题
			String description 	= (String) events.get("description");//日程内容
			if (!Utils.isNumber(calendarId) || Utils.isEmpty(startDate) || Utils.isEmpty(endDate) ||
					(Utils.isEmpty(title) || Utils.isEmpty(description))) {
				return null;
			}
			
			String location		= (String) events.get("location");//地点
			String timeZone		= (String) events.get("timeZone");//时区:TimeZone.getAvailableIDs()
			String hasAlarm 	= (String) events.get("hasAlarm");//是否事件触发报警:0=false, 1=true
			String allDay		= (String) events.get("allDay");//是否全天事件:0=false, 1=true
	//		String eventStatus	= (String) calendar.get("eventStatus");//事件状态:暂定(0),确认(1)或取消(2)
			String availability	= (String) events.get("availability");//我的状态:0=忙碌,1=有空
			String accessLevel	= (String) events.get("accessLevel");//访问权限:默认=0,机密=1,私有=2,公共=3
			
			eventVal.put(Events.CALENDAR_ID, calendarId);
			eventVal.put(Events.TITLE, title);
			eventVal.put(Events.DESCRIPTION, description);
			eventVal.put(Events.STATUS, 1);
			eventVal.put(Events.EVENT_TIMEZONE, Utils.isEmpty(timeZone) ? "Asia/Shanghai" : timeZone);
			eventVal.put(Events.HAS_ALARM, (Utils.isNumber(hasAlarm) ? Integer.parseInt(hasAlarm) : 0));
			//计算开始、结束时间,全部用Date也可以。 
			Calendar cld 		= Calendar.getInstance();
			Calendar startCld 	= Calendar.getInstance();
			Calendar endCld 	= Calendar.getInstance();
			cld = Utils.parseStrToCld(startDate);
			//如果地址不为空插入地址
			if (!Utils.isEmpty(location)) {
				eventVal.put(Events.EVENT_LOCATION, location);
			}
			//如果是全天事件的话,取开始时间的那一整天
			if (Utils.isNumber(allDay) && Integer.parseInt(allDay) == 1) {
				//开始时间
				startCld.set(cld.get(Calendar.YEAR), cld.get(Calendar.MONTH), cld.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
				//结束时间
				endCld.set(cld.get(Calendar.YEAR), cld.get(Calendar.MONTH), cld.get(Calendar.DAY_OF_MONTH), 24 , 0 , 0);
				eventVal.put(Events.ALL_DAY, true);
				eventVal.put(Events.DTSTART, startCld.getTimeInMillis());
				eventVal.put(Events.DTEND, endCld.getTimeInMillis());
			} else {
				//开始时间
				startCld = Utils.parseStrToCld(startDate);
				//结束时间
				endCld = Utils.parseStrToCld(endDate);
				eventVal.put(Events.ALL_DAY, false);
				eventVal.put(Events.DTSTART, startCld.getTimeInMillis());
				eventVal.put(Events.DTEND, endCld.getTimeInMillis());
			}
			//设置我的状态
			if (Utils.isNumber(availability) && Integer.parseInt(availability) == 0) {
				eventVal.put(Events.AVAILABILITY, Events.AVAILABILITY_BUSY);
			} else {
				eventVal.put(Events.AVAILABILITY, Events.AVAILABILITY_FREE);
			}
			//设置隐私
			if (Utils.isNumber(accessLevel) && Integer.parseInt(accessLevel) == 1) {
				eventVal.put(CalendarContract.Events.ACCESS_LEVEL, Events.ACCESS_CONFIDENTIAL);
			} else if (Utils.isNumber(accessLevel) && Integer.parseInt(accessLevel) == 2) {
				eventVal.put(CalendarContract.Events.ACCESS_LEVEL, Events.ACCESS_PRIVATE);
			} else if (Utils.isNumber(accessLevel) && Integer.parseInt(accessLevel) == 3) {
				eventVal.put(CalendarContract.Events.ACCESS_LEVEL, Events.ACCESS_PUBLIC);
			} else {
				eventVal.put(CalendarContract.Events.ACCESS_LEVEL, Events.ACCESS_DEFAULT);
			}
			
			return resolver.insert(eventsUri, eventVal);
		} catch (Exception e) {
			throw e;
		}
	}
	/**
	 * 查询Reminder是否存在
	 * @param id
	 * @return
	 */
	public boolean isExistAttendee(long id){
		Cursor cursor = resolver.query(
				attendeesUri, 
				new String[]{ Attendees._ID}, 
				Attendees._ID + "=" + id, 
				null, 
				null);
		if (cursor.moveToFirst()) {
			return true;
		}
		return false;
	}
	/**
	 * 查询Reminder是否存在
	 * @param id
	 * @return
	 */
	public boolean isExistReminder(long id){
		Cursor cursor = resolver.query(
				remindersUri, 
				new String[]{ Reminders._ID}, 
				Reminders._ID + "=" + id, 
				null, 
				null);
		if (cursor.moveToFirst()) {
			return true;
		}
		return false;
	}
	
	/**
	 * 查询event是否存在
	 * @param id
	 * @return
	 */
	public boolean isExistEvent(long id){
		Cursor cursor = resolver.query(
				eventsUri, 
				new String[]{ Events._ID}, 
				Events._ID + "=" + id, 
				null, 
				null);
		if (cursor.moveToFirst()) {
			return true;
		}
		return false;
	}
	/**
	 * 删除event表里数据
	 * @param id
	 * @return
	 */
	public Map<String, String> delEvents(List<String> ids, String calendarId, boolean delAll){
		Map<String, String> result = new HashMap<String, String>();
		
		String selection = null;
		
		if (delAll) {
			selection = Events._ID + " > 0";
		} else if (Utils.isNumber(calendarId)) {
			selection = Events.CALENDAR_ID + "=" + calendarId;
		} else if(Utils.isEmpty(ids)){
			result.put("result", "0");
			result.put("obj", "要删除日程事件的id为空!");
			return result;
		} else {
			String where = "";
			for (String id : ids) {
				if (Utils.isNumber(id)) {
					where += id + ",";
				} 
			}
			selection = Events._ID + " in(" + where.substring(0, where.length() - 1) + ")";
		}
		
		try {
			Log.i(Const.APPTAG, "====:" + selection);
			int n = resolver.delete(
					eventsUri, 
					selection,
					null);
			
			result.put("result", "1");
			result.put("obj", n + "");
			
		} catch (Exception e) {
			result.put("result", "-1");
			result.put("obj", "删除错误:" + e.toString());
		}
		return result;
	}
	
	/**
	 * 更新日历的名称
	 * @param param
	 * @return Map
	 */
	public Map<String, String> updateCalendars(Map<String, String> param){
		Map<String, String> result = new HashMap<String, String>();
		if (Utils.isEmpty(param)) {
			result.put("false", "更新参数不能为空!");
			return result; 
		}
		
		String calendarId = param.get("calendarId");
		String displayName = param.get("displayName");
		
		if (Utils.isEmpty(calendarId) && Utils.isNumber(calendarId)) {
			result.put("false", "日历id不合法!");
			return result; 
		}
		if (Utils.isEmpty(displayName)) {
			result.put("false", "日历名称不能为空!");
			return result; 
		}
		
		ContentValues values = new ContentValues();
		values.put(Calendars.CALENDAR_DISPLAY_NAME, displayName);
		Uri uri = ContentUris.withAppendedId(calendarsUri, Long.parseLong(calendarId));
		int n = resolver.update(uri, values, null, null);
		result.put("true", n + "");
		
		return result; 
	}
	
	/**
	 * 根据账户查询账户日历
	 * @param param Map<String, String>
	 * @return List
	 */
	public List<Map<String, String>> queryCalendars(Map<String, String> param){
		String accountName = null;
		String accountType = null;
		String ownerAccount = null;
		
		if (!Utils.isEmpty(param)) {
			accountName = param.get("accountName");//账户名称
			accountType = param.get("accountType");//账户类型
			ownerAccount = param.get("ownerAccount");//拥有者账户
		}
		
		List<Map<String, String>> calendars = new ArrayList<Map<String,String>>();
		
		Cursor cursor = null;
		StringBuffer selection = new StringBuffer(" 1 = 1 ");
		List<String> selectionArgs = new ArrayList<String>();
		//本地帐户查询:ACCOUNT_TYPE_LOCAL是一个特殊的日历账号类型,它不跟设备账号关联。这种类型的日历不同步到服务器
		//如果是谷歌的账户是可以同步到服务器的
		if (Utils.isEmpty(accountName) && Utils.isEmpty(accountType) && Utils.isEmpty(ownerAccount)) {
			selection.append(" AND " + Calendars.ACCOUNT_TYPE + " = ? ");
			selectionArgs.add("LOCAL");
		} else {
			if (!Utils.isEmpty(accountName)) {
				selection.append(" AND " + Calendars.ACCOUNT_NAME + " = ? ");
				selectionArgs.add(accountName);
			}
			if (!Utils.isEmpty(accountType)) {
				selection.append(" AND " + Calendars.ACCOUNT_TYPE + " = ? ");
				selectionArgs.add(accountType);
			}
			if (!Utils.isEmpty(ownerAccount)) {
				selection.append(" AND " + Calendars.OWNER_ACCOUNT + " = ? ");
				selectionArgs.add(ownerAccount);
			}
		}
		cursor = resolver.query(calendarsUri, CALENDARS_COLUMNS, selection.toString(), 
				selectionArgs.toArray(new String[]{}), null);
		while (cursor.moveToNext()) {
			Map<String, String> calendar = new HashMap<String, String>();
		    // Get the field values
			calendar.put("calendarId", cursor.getString(0));
			calendar.put("accountName", cursor.getString(1));
			calendar.put("displayName", cursor.getString(2));
			calendar.put("ownerAccount", cursor.getString(3));
			Log.i(Const.APPTAG, "查询到日历:" + calendar);
			calendars.add(calendar);
		}
		return calendars;
	}
}

Android开发,读写日历功能,闹钟设置功能开发demo Android开发,读写日历功能,闹钟设置功能 开发demo 立即下载

相关推荐

中标麒麟,postgres报错invalid value for parameter "timeZone":"Asia/Beijing"

在中标麒麟服务器上,安装postgres,启动tomcat容器时,报invalid value for parameter "timeZone":"Asia/Beijing"。 查看postgres运行日志,也报同样的错误。 报错原因:服务器的时区,在Postgres支持的时区目录中找不到。当时在服务器上信息为Beijing 解决步骤: 1. cat /etc/sysconfig/cloc

u010213931的博客 7924

android 日历 events 无法保存,CalendarContract.Events.CALENDAR_ID不使用Intent将事件存储在Android中指定的Calendar_Id中(Cal...

Hi I am using the following Code to add a Event to my Android Calendar using Intent.Calendar cal = Calendar.getInstance();Intent intent = new Intent(Intent.ACTION_INSERT); // Even Tried Intent.ACTION_...

weixin_39721924的博客 537

告别手动归档:基于Allegro Skill的XTools一键生成Gerber与生产文件实践

本文详细介绍了基于Allegro Skill的XTools工具如何实现一键生成Gerber与生产文件,大幅提升PCB设计效率。通过自动化流程,解决了传统手动归档中的重复劳动、人为失误和标准不统一等问题,特别适合需要频繁输出生产文件的工程师。文章包含安装配置、实战操作、问题排查及进阶技巧,帮助用户快速掌握这一高效工具。

weixin_30505225的博客 460

Android中Calendar类的用法总结

Calendar是Android开发中需要获取时间时必不可少的一个工具类,通过这个类可以获得的时间信息还是很丰富的,下面做一个总结,以后使用的时候就不用总是去翻书或者查资料了。 在获取时间之前要先获得Calendar这个类的实例: [java] view plain copy private Calendar c = Calendar.getInstance();   然后就可以用这个变...

weixin_33695450的博客 859

GPU核心性能指标

内存科普 CPU缓存分为三类,一级缓存(L1)、二级缓存(L2)和三级缓存(L3)。CPU在实际数据读取中重要的却是一级缓存,因为一级缓存速度最快,二级缓存其次,三级缓存最慢,只是三级缓存的容量最大。 DDR1,DDR2,DDR3内存条(DDR是Double Data Rate双倍速率同步动态随机存储器的英文缩写)就是俗称的一二三代内存条。这三种内存条工艺不同,接口不同,性能不同,互不兼容。要区分它们,也不难。内存条可以用在CPU内存或者GPU显存中。比如 the NVIDIA Tesla M2050 GP

Charles Ren's Tech Blog 2万+

学Simulink--基础微电网场景实例:基于Simulink的微电网经济调度优化策略仿真

指标传统调度PSO经济调度(本文)目标值总运行成本(元/h)45.232.5(工况1)降低≥20%调度响应时间(s)25<30储能SOC范围(%)50~50(不变)28~56(动态优化)20~80弃风弃光率(%)0(强制满发)0(优化消纳)0原理:微电网经济调度通过PSO算法优化各单元出力,以总成本最小化为目标,平衡功率平衡与设备约束;建模:Simulink中用实现PSO控制器,结合PV/WT/DG/ESS模型,完成闭环优化;验证。

amy_mhd的博客 67

Android Calendar

【代码】Android Calendar。

fromVillageCoolBoy的博客 864

LSTM在交通流量预测中的应用:优化城市交通管理

我们使用的数据集来自某个城市的交通监测系统,包含多个监测点在不同时间段内的交通流量记录。每个监测点的数据包括时间戳、交通流量、天气状况和道路状态等信息。

斌擎科技 1256

【Android开发--新手必看篇】Calendar类的使用

Android笔记 ​ ——其他 【若对该知识点有更多想了解的,欢迎私信博主~~】 Calendar类: 获取日期 注:在JDK1.0中,Date类是唯一处理时间的类,但是由于Date类中方法比较少并且有一些方法不便于实现国际化,所以从JDK1.1版本开始新增了Calendar类,增加了许多功能强大的方法,推荐使用 Calendar类进行时间和日期处理 获取当前日期 Calendar c = Calendar.getInstance(); Date date=new Date(System.cur

江川一梦的博客 966

渗透测试工具之Sliver

攻击者需要将生成的植入物传输到目标系统,并执行它。C2 框架的架构与 Metasploit(如 Meterpreter)类似,但更专注于。(Red Teaming)中常见的攻击工具之一,攻击者利用 C2 服务器。组成,二者共同实现 C2 服务器与受控设备的通信。植入物(Implants)是 Sliver 生成的。抓包分析时,可以看到所有数据都是加密传输的。和**监听器(Listeners)**功能。Sliver 支持多种通信协议,如。随着安全防御的不断提升,企业应加强。进行通信,数据仍然是加密的。

idlecloud0105的博客 1935

34、实数域上高效负循环卷积算法解析

本文介绍了一种高效的实数域负循环卷积算法,通过引入离散傅里叶负循环变换(DFNT)避免传统方法的冗余,显著提升计算效率。文章详细分析了算法原理、误差传播机制,并推导出误差与方差界,提出无误差和基于3σ规则的参数设置方案。结合Cooley-Tukey与Gentleman-Sande FFT路径优化,实验验证了算法在不同精度和多项式长度下的性能优势与结果正确性,为密码学与信号处理等领域提供了高精度、高性能的卷积计算解决方案。

salt的博客 114

如何用React Native Calendar Events构建完整的日程管理应用:终极指南

React Native Calendar Events是一个强大的React Native模块,专门用于在iOS和Android平台上处理日历事件。这个跨平台解决方案让开发者能够轻松构建功能完整的日程管理应用,实现日历事件的增删改查操作。📱 无论您是开发个人日程应用、企业会议管理系统,还是集成日历功能的社交应用,这个库都能提供完整的原生日历访问能力。 ## 🚀 快速开始:安装与配置 ##

gitblog_00322的博客 437

华为OD机考双机位C卷 - 评委评分 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 评委评分 (OD上机考试双机位C卷)。提供在线OJ刷题。Java、C++、Python、GO语言、C语言、JavaScript题解,并提供完整思路讲解。

算法大师! 1750

React Native Calendar Events API深度解析:从基础查询到高级操作

React Native Calendar Events是一个功能强大的模块,专为iOS和Android平台设计,让开发者能够轻松地与设备日历进行交互。无论是查询日历事件、添加新事件,还是管理日历权限,这个模块都提供了全面的API支持,帮助你在React Native应用中实现专业的日历功能。 ## 📋 核心功能概览 React Native Calendar Events模块的核心能力集中

gitblog_00927的博客 726

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

React Native Calendar Events完全指南:如何在iOS和Android应用中集成日历功能

想要为你的React Native应用添加完整的日历功能吗?📱 React Native Calendar Events是一个强大的跨平台日历事件管理库,让你能够在iOS和Android应用中轻松集成日历功能。这个开源项目提供了完整的日历API支持,包括创建事件、读取日历、管理提醒等功能。无论是开发日程管理应用、会议提醒工具,还是需要与系统日历集成的任何应用,这个库都能帮你快速实现需求。 ##

gitblog_00311的博客 677

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

android日历总结,Android中Calendar类的用法总结

Calendar是Android开发中需要获取时间时必不可少的一个工具类,通过这个类可以获得的时间信息还是很丰富的,下面做一个总结,以后使用的时候就不用总是去翻书或者查资料了。在获取时间之前要先获得Calendar这个类的实例:privateCalendarc=Calendar.getInstance();然后就可以用这个变量来获取时间了。获得当前的年份Log.i("MainActivit...

weixin_31965935的博客 5301

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

可能是第十好的Android 开源 日历 Calendar 仿小米,作为移动开发程序员

CalendarViewAdapter.saveDate(selectedDate); onSelectDateListener.onSelectDate(selectedDate); seedDate = selectedDate; } else if (weeks[row].days[col].getState() == State.PAST_MONTH){ selectedDate = weeks[row].days[col].getDate(); CalendarViewAdapter.saveDa

m0_65146387的博客 751

Android之 日历单选多选控件

日历单选多选控件

qq_29848853的博客 2970

android calendar控件,Android Calendar自定义日历控件

效果预览 image思路:1、RecyclerView+Calendar2、Calendar获取整月的天数3、Calendar获取上一个月和下一个月需要补全的天数1、Calendar获取整月的天数Calendar instance = Calendar.getInstance();if (indexDate != null) {//自定月份instance.setTime(indexDate.ge...

weixin_29409045的博客 1607

Android之Calendar类(时间大全)

前两天,学习自定义View画了一个时钟,用到了Calendar这个抽象类(日历时间)。 java常见类,在此记录一下简单的用法及意义。 //获得Calendar这个类的实例: private Calendar c = Calendar.getInstance(); //获得当前的年份 c.get(Calendar.YEAR) //获得当前的月份 c.get(Calendar.MONTH)...

Zachary的基地 1万+

Android Studio 基础 之 获取系统Calendar 日历日程(可获得当天以后可设定天数范围内的日历日程) (涉及指定日期时间判断是星期几的方法使用)的方法整理

Android Studio 基础 之 获取系统Calendar 日历日程 (涉及指定日期时间判断是星期几的方法使用)的方法整理 目录 Android Studio 基础 之 获取系统Calendar 日历日程 (涉及指定日期时间判断是星期几的方法使用)的方法整理 一、简单介绍 二、实现原理 三、注意实现 四、效果预览 五、实现步骤 六、关键代码 一、简单介绍 Android 开发中的一些基础操作,使用整理,便于后期使用。 本节介绍,Android 开发中,...

仙魁XAN 1万+

Android开发之日期Calendar、DatePickerDialog

/进行转换 得到字符串。获取的是当前系统的时间 需要转换为字符串。yyyy-MM-dd HH:mm:ss 主要时利用这些字符串来选取。

qq_15390089的博客 386

Android实现简单日历

主要通过ViewPager2+GridView实现打卡日历

weixin_43955048的博客 6302

Android CalendarView助你打造精美的Android日历应用

在本文中,我们介绍了如何集成和定制CalendarView控件,并探讨了其在Android开发中的各种应用场景和优化方法。通过适当的使用和持续的改进,CalendarView将继续为开发者提供强大而灵活的日历功能,促进移动应用的发展和创新。

虎哥LoveDroid 5709

Android 操作系统日历完成提醒功能 附带开关闹钟 适配高版本安卓

如果想要一个稳定且不用担心生命周期的提醒方式,可以试试利用系统日历去完成任务的提醒或某个活动的预约。环境Java 11Gredle 7.1测试机型 mi 8(安卓 9) mi10 pro(安卓11) huawei m8(安卓7)

doomwatcher的博客 2957
上一篇: Android 联系人管理(包括大部分字段),增删该查,批量插入、删除、更新,等等; 可能有问题,还望指证。
下一篇: 转:js判断是android访问还是ios访问
下嘻嘻呵呵
博客等级 码龄16年 6粉丝 2原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值