问题
I am looking for a calendar plugin that works with specifically with iOS, though I'd also be interested in an Android plugin too, that is compatible with Phonegap 3.0.0. I have seen the old one, but from what I've seen it does not work with the newest version of Phonegap. Does anyone know of where I can get a plugin that works with Phonegap 3.0.0?
回答1:
If anyone is still looking for a cross-platofrm (iOS and Android) Calendar for PhoneGap 3.0 (also for PhoneGap Build), take a look here: https://github.com/EddyVerbruggen/Calendar-PhoneGap-Plugin
回答2:
There is an "official" 3rd party Calendar plugin available in the PhoneGap plugin section:
https://build.phonegap.com/plugins/168
Plugin ID nl.x-services.plugins.calendar
Version 3.2
Platform(s) Android, iOS
PhoneGap Version(s) 3.0.0, 3.1.0
License MIT
回答3:
hi i just build a plugin for android and ios respectively i changed the plugin from Felix Montanez so that it is working with phonegap 3.0.0 for android i used the plugin from devgirl i just changed the javascript that it is working with both platforms:
calendar.js:
function CalendarPlugin() {}
CalendarPlugin.prototype.createEvent = function(title, location, notes, startDate, endDate, successCallback, errorCallback) {
if (typeof errorCallback != "function") {
console.log("CalendarPlugin.createEvent failure: errorCallback parameter must be a function");
return;
}
if (typeof successCallback != "function") {
console.log("CalendarPlugin.createEvent failure: successCallback parameter must be a function");
return;
}
cordova.exec(successCallback, errorCallback, "CalendarPlugin", "createEvent", [title, location, notes, startDate, endDate, {
"title": title,
"description": notes,
"eventLocation": location,
"startTimeMillis": startDate.getTime(),
"endTimeMillis": endDate.getTime()
}]);
};
CalendarPlugin.install = function() {
if (!window.plugins) {
window.plugins = {};
}
window.plugins.CalendarPlugin = new CalendarPlugin();
return window.plugins.CalendarPlugin;
};
cordova.addConstructor(CalendarPlugin.install);
CalendarPlugin.h
#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>
#import <Cordova/CDV.h>
#import <EventKitUI/EventKitUI.h>
#import <EventKit/EventKit.h>
@interface CalendarPlugin : CDVPlugin
@property (nonatomic, retain) EKEventStore* eventStore;
- (void)initEventStoreWithCalendarCapabilities;
-(NSArray*)findEKEventsWithTitle: (NSString *)title
location: (NSString *)location
message: (NSString *)message
startDate: (NSDate *)startDate
endDate: (NSDate *)endDate;
// Calendar Instance methods
- (void)createEvent:(CDVInvokedUrlCommand*)command;
- (void)modifyEvent:(CDVInvokedUrlCommand*)command;
- (void)findEvent:(CDVInvokedUrlCommand*)command;
- (void)deleteEvent:(CDVInvokedUrlCommand*)command;
@end
CalendarPlugin.m
#import "CalendarPlugin.h"
#import <EventKitUI/EventKitUI.h>
#import <EventKit/EventKit.h>
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
@implementation CalendarPlugin
@synthesize eventStore;
#pragma mark Initialisation functions
- (CDVPlugin*) initWithWebView:(UIWebView*)theWebView
{
self = (CalendarPlugin*)[super initWithWebView:theWebView];
if (self) {
//[self setup];
[self initEventStoreWithCalendarCapabilities];
}
return self;
}
- (void)initEventStoreWithCalendarCapabilities {
__block BOOL accessGranted = NO;
eventStore= [[EKEventStore alloc] init];
if([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
self.eventStore = eventStore;
}
}
#pragma mark Helper Functions
-(NSArray*)findEKEventsWithTitle: (NSString *)title
location: (NSString *)location
message: (NSString *)message
startDate: (NSDate *)startDate
endDate: (NSDate *)endDate {
// Build up a predicateString - this means we only query a parameter if we actually had a value in it
NSMutableString *predicateString= [[NSMutableString alloc] initWithString:@""];
if (title.length > 0) {
[predicateString appendString:[NSString stringWithFormat:@"title == '%@'" , title]];
}
if (location.length > 0) {
[predicateString appendString:[NSString stringWithFormat:@" AND location == '%@'" , location]];
}
if (message.length > 0) {
[predicateString appendString:[NSString stringWithFormat:@" AND notes == '%@'" , message]];
}
NSPredicate *matches = [NSPredicate predicateWithFormat:predicateString];
NSArray *datedEvents = [self.eventStore eventsMatchingPredicate:[eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:nil]];
NSArray *matchingEvents = [datedEvents filteredArrayUsingPredicate:matches];
return matchingEvents;
}
#pragma mark Cordova functions
- (void)createEvent:(CDVInvokedUrlCommand*)command {
// Import arguments
NSArray *arguments = command.arguments;
NSString* title = [arguments objectAtIndex:0];
NSString* location = [arguments objectAtIndex:1];
NSString* message = [arguments objectAtIndex:2];
NSString *startDate = [arguments objectAtIndex:3];
NSString *endDate = [arguments objectAtIndex:4];
//creating the dateformatter object
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *myStartDate = [df dateFromString:startDate];
NSDate *myEndDate = [df dateFromString:endDate];
EKEvent *myEvent = [EKEvent eventWithEventStore: self.eventStore];
myEvent.title = title;
myEvent.location = location;
myEvent.notes = message;
myEvent.startDate = myStartDate;
myEvent.endDate = myEndDate;
myEvent.calendar = self.eventStore.defaultCalendarForNewEvents;
EKAlarm *reminder = [EKAlarm alarmWithRelativeOffset:-2*60*60];
[myEvent addAlarm:reminder];
NSError *error = nil;
[self.eventStore saveEvent:myEvent span:EKSpanThisEvent error:&error];
// Check error code + return result
CDVPluginResult* pluginResult = nil;
if (!error) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
-(void)deleteEvent:(CDVInvokedUrlCommand*)command {
// Import arguments
NSArray *arguments = command.arguments;
NSString* title = [arguments objectAtIndex:0];
NSString* location = [arguments objectAtIndex:1];
NSString* message = [arguments objectAtIndex:2];
NSString *startDate = [arguments objectAtIndex:3];
NSString *endDate = [arguments objectAtIndex:4];
bool delAll = [arguments objectAtIndex:5];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *myStartDate = [df dateFromString:startDate];
NSDate *myEndDate = [df dateFromString:endDate];
NSArray *matchingEvents = [self findEKEventsWithTitle:title location:location message:message startDate:myStartDate endDate:myEndDate];
if (delAll || matchingEvents.count == 1) {
// Definitive single match - delete it!
NSError *error = NULL;
bool hadErrors = false;
if (delAll) {
for (EKEvent * event in matchingEvents) {
[self.eventStore removeEvent:event span:EKSpanThisEvent error:&error];
// Check for error codes and return result
if (error) {
hadErrors = true;
}
}
}
else {
[self.eventStore removeEvent:[matchingEvents lastObject] span:EKSpanThisEvent error:&error];
}
// Check for error codes and return result
CDVPluginResult* pluginResult = nil;
if (error || hadErrors) {
NSString *messageString;
if (hadErrors) {
messageString = @"Error deleting events";
}
else {
messageString = error.userInfo.description;
}
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
messageAsString:messageString];
}
else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
}
-(void)findEvent:(CDVInvokedUrlCommand*)command {
// Import arguments
NSArray *arguments = command.arguments;
NSString* title = [arguments objectAtIndex:0];
NSString* location = [arguments objectAtIndex:1];
NSString* message = [arguments objectAtIndex:2];
NSString *startDate = [arguments objectAtIndex:3];
NSString *endDate = [arguments objectAtIndex:4];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *myStartDate = [df dateFromString:startDate];
NSDate *myEndDate = [df dateFromString:endDate];
NSArray *matchingEvents = [self findEKEventsWithTitle:title location:location message:message startDate:myStartDate endDate:myEndDate];
NSMutableArray *finalResults = [[NSMutableArray alloc] initWithCapacity:matchingEvents.count];
// Stringify the results - Cordova can't deal with Obj-C objects
for (EKEvent * event in matchingEvents) {
NSMutableDictionary *entry = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
event.title, @"title",
event.location, @"location",
event.notes, @"message",
[df stringFromDate:event.startDate], @"startDate",
[df stringFromDate:event.endDate], @"endDate", nil];
[finalResults addObject:entry];
}
CDVPluginResult *pluginResult = nil;
if (finalResults.count > 0) {
// Return the results we got
pluginResult = [CDVPluginResult
resultWithStatus: CDVCommandStatus_OK
messageAsArray:finalResults
];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
-(void)modifyEvent:(CDVInvokedUrlCommand*)command {
// Import arguments
NSArray *arguments = command.arguments;
NSString* title = [arguments objectAtIndex:0];
NSString* location = [arguments objectAtIndex:1];
NSString* message = [arguments objectAtIndex:2];
NSString *startDate = [arguments objectAtIndex:3];
NSString *endDate = [arguments objectAtIndex:4];
NSString* ntitle = [arguments objectAtIndex:5];
NSString* nlocation = [arguments objectAtIndex:6];
NSString* nmessage = [arguments objectAtIndex:7];
NSString *nstartDate = [arguments objectAtIndex:8];
NSString *nendDate = [arguments objectAtIndex:9];
// Make NSDates from our strings
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *myStartDate = [df dateFromString:startDate];
NSDate *myEndDate = [df dateFromString:endDate];
// Find matches
NSArray *matchingEvents = [self findEKEventsWithTitle:title location:location message:message startDate:myStartDate endDate:myEndDate];
CDVPluginResult *pluginResult = nil;
if (matchingEvents.count == 1) {
// Presume we have to have an exact match to modify it!
// Need to load this event from an EKEventStore so we can edit it
EKEvent *theEvent = [self.eventStore eventWithIdentifier:((EKEvent*)[matchingEvents lastObject]).eventIdentifier];
if (ntitle) {
theEvent.title = ntitle;
}
if (nlocation) {
theEvent.location = nlocation;
}
if (nmessage) {
theEvent.notes = nmessage;
}
if (nstartDate) {
NSDate *newMyStartDate = [df dateFromString:nstartDate];
theEvent.startDate = newMyStartDate;
}
if (nendDate) {
NSDate *newMyEndDate = [df dateFromString:nendDate];
theEvent.endDate = newMyEndDate;
}
// Now save the new details back to the store
NSError *error = nil;
[self.eventStore saveEvent:theEvent span:EKSpanThisEvent error:&error];
// Check error code + return result
if (error) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
messageAsString:error.userInfo.description];
}
else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
}
}
else {
// Otherwise return a no result error
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end
CalendarPlugin.java
package de.drid.calendarPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
public class CalendarPlugin extends CordovaPlugin {
public static final String ACTION_ADD_CALENDAR_ENTRY = "createEvent";
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
try {
if (ACTION_ADD_CALENDAR_ENTRY.equals(action)) {
JSONObject arg_object = args.getJSONObject(5);
Intent calIntent = new Intent(Intent.ACTION_EDIT)
.setType("vnd.android.cursor.item/event")
.putExtra("beginTime", arg_object.getLong("startTimeMillis"))
.putExtra("endTime", arg_object.getLong("endTimeMillis"))
.putExtra("title", arg_object.getString("title"))
.putExtra("description", arg_object.getString("description"))
.putExtra("eventLocation", arg_object.getString("eventLocation"));
this.cordova.getActivity().startActivity(calIntent);
callbackContext.success();
return true;
}
callbackContext.error("Invalid action");
return false;
} catch(Exception e) {
System.err.println("Exception: " + e.getMessage());
callbackContext.error(e.getMessage());
return false;
}
}
}
回答4:
Here is a PhoneGap Calendar Plugin for Android that will work with 3.0
For PG 3.0 you’ll need to modify the import statements in the .java class as it changed from 2.9:
From this…
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
to this…
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
来源:https://stackoverflow.com/questions/18622090/phonegap-3-0-0-calendar-plugin