I'm trying to create an event using the new Calendar API and while it creates an event locally, it never shows up on the Google Calendar. I tried to manually create an event in the same calendar and that synced perfectly. I've seen quite a few similar posts, but none of the answers seem to do the trick.
Here's the code I'm using for Android 4.0+:
ContentValues values = new ContentValues();
values.put(Events.DTSTART, info.getStartTime());
values.put(Events.DTEND, info.getEndTime());
values.put(Events.TITLE, info.getTitle());
values.put(Events.DESCRIPTION, info.getDescription());
values.put(Events.CALENDAR_ID, this.getCalendarInfo().getId()); //hardcoded to 1, which is my default calendar
values.put(Events.EVENT_TIMEZONE, info.getTimeZone());
values.put(Events.STATUS, Events.STATUS_CONFIRMED);
values.put(Events.HAS_ALARM, 0);
this.getContentResolver().insert(Events.CONTENT_URI, values);
I'm not quite sure what's wrong and I hope someone can help me out! Thanks!
My Solution is request sync for calendar provider, it's work for me:
private void requestCalendarSync()
{
AccountManager aM = AccountManager.get(this);
Account[] accounts = aM.getAccounts();
for (Account account : accounts)
{
int isSyncable = ContentResolver.getIsSyncable(account, CalendarContract.AUTHORITY);
if (isSyncable > 0)
{
Bundle extras = new Bundle();
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(accounts[0], CalendarContract.AUTHORITY, extras);
}
}
}
permission:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
enter code hereits easy, the line
values.put(Events.CALENDAR_ID, this.getCalendarInfo().getId()); //hardcoded to 1, which is my default calendar
actually tells android to add event to LOCAL android calendar .... i assume that you would like to add it to calendar synced to your gmail account .... so instead of
values.put(Events.CALENDAR_ID, this.getCalendarInfo().getId());
try
values.put(Events.CALENDAR_ID, 2);
Related
I'm getting problems creating a new Calendar event from my Android app. Here's my code:
ContentResolver cr = getActivity().getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.DTSTART, dtStart.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());
values.put(CalendarContract.Events.DTEND, dtEnd.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());
values.put(CalendarContract.Events.TITLE, edittext.getText().toString());
values.put(CalendarContract.Events.CALENDAR_ID, calId);
values.put(CalendarContract.Events.VISIBLE, 0);
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.WRITE_CALENDAR},
MY_PERMISSIONS_REQUEST_WRITE_CALENDAR);
}
Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
In my manifest I have:
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>
I'm getting the following error:
java.lang.IllegalArgumentException: Only the provider may write to visible
I've had a good look around but can't find anything I'm doing wrong, all the code examples I've seen are basically the same as the above. Any help much appreciated.
I don't think you can modify the visibility of an event via a ContentResolver. Comment out the line
values.put(CalendarContract.Events.VISIBLE, 0);
and try again.
Building up from this Android documentation
Writing to Events
I'm trying to insert events in to a calendar i created. I'm using the following code to do so... it's taken from google's documentation on CalendarProvider.
The problem is that no matter what values i put in DTSTART or DTEND the event is always created as a single day event and the date is the current date.
I've also tried to use Intent(Intent.ACTION_EDIT) with .putExtra for the dates... but sadly this doesn't help as well... neither the dates are set nor it gives me to modify them in the edit intent.
Any Idea what might be causing this behavior?
ContentValues event = new ContentValues();
event.put(Events.CALENDAR_ID, e.getCalendarId());
event.put(Events.TITLE, e.getTitle());
event.put(Events.DESCRIPTION, e.getDescription());
event.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().getDisplayName());
event.put(Events.EVENT_END_TIMEZONE, TimeZone.getDefault().getDisplayName());
event.put(Events.GUESTS_CAN_MODIFY, 1);
event.put(Events.IS_ORGANIZER, 1);
event.put(Events.DTSTART, e.getDateStart());
event.put(Events.DTEND, e.getDateEnd());
event.put(Events.ALL_DAY, 1);
event.putNull(Events.DURATION);
event.putNull(Events.RRULE);
event.putNull(Events.RDATE);
Uri eventUri = context.getContentResolver().insert(Events.CONTENT_URI, event);
int eventID = Integer.parseInt(eventUri.getLastPathSegment());
My Android Google Account has sync options enabled in Settings (For Calendar/Contacts ect).
When I add new event from the native calendar app it syncs with the web Google Calendar.
When I add new event programmatically, although it appears in the native Android Calendar App, it never syncs with the Google Calendar on my account.
I searched for various snippets online and tried different things, my events (inserted from my app) are never appearing in the Google Calendar (only the local phone calendar).
This is how I am inserting an event:
#Override
protected void onCreate(Bundle savedInstanceState) {
accountName = getAccount().name;
accountType = getAccount().type;
setCalendarVisiblityAndSync();
addEvent(); //add single test event (this one appears in local calendar)
}
private void setCalendarVisiblityAndSync(){
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Calendars.SYNC_EVENTS, 1);
values.put(CalendarContract.Calendars.VISIBLE, 1);
Uri uri = asSyncAdapter(ContentUris.withAppendedId(Calendars.CONTENT_URI, 1),accountName, accountType);
cr.update(uri, values, null, null);
}
public long addEvent() {
DateTime dateFrom = new DateTime().withDayOfMonth(20).withHourOfDay(11);
DateTime dateTo = new DateTime().withDayOfMonth(20).withHourOfDay(12);
long startMillis = 0;
long endMillis = 0;
startMillis = dateFrom.getMillis();
endMillis = dateTo.getMillis();
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
String title = "ANDROID EVENT FROM MY APP";
values.put(Events.TITLE, title);
String description = "ANDROID EVENT FROM MY APP DESCRIPTION";
values.put(Events.DESCRIPTION, description);
values.put(Events.CALENDAR_ID, 1);
values.put(Events.EVENT_TIMEZONE, dateFrom.getZone().toTimeZone().getDisplayName());
values.put(Events.HAS_ALARM, true);
Uri eventUri = asSyncAdapter(Events.CONTENT_URI,accountName,accountType);
Uri uri = cr.insert(eventUri, values);
// get the event ID that is the last element in the Uri
long eventID = Long.parseLong(uri.getLastPathSegment());
return eventID;
}
public Account getAccount() {
Account[] accounts = AccountManager.get(this).getAccounts();
Account account = accounts[0];
return account;
}
//The static function below is a snippet of code I found as a suggestion on another thread (but I am not sure if I am using it right ?!)
static Uri asSyncAdapter(Uri uri, String account, String accountType) {
return uri.buildUpon()
.appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
.appendQueryParameter(Calendars.ACCOUNT_NAME, account)
.appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
}
The functions above come from different threads and I combined them myself in an attempt to achieve successful sync with Google Calendar but it is not working.
EDIT: I am also getting this message in the Log window:
/*05-02 10:40:16.670: W/EventHandler(29147): com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
05-02 10:40:16.670: W/EventHandler(29147): {
05-02 10:40:16.670: W/EventHandler(29147): "errors": [
05-02 10:40:16.670: W/EventHandler(29147): {
05-02 10:40:16.670: W/EventHandler(29147): "reason": "invalid",
05-02 10:40:16.670: W/EventHandler(29147): "domain": "global",
05-02 10:40:16.670: W/EventHandler(29147): "message": "Invalid time zone definition for start time." */
The problem is probably in "dateFrom.getZone().toTimeZone().getDisplayName()".
What it returns is the localized name of the timezone, for example "Pacific Standard Time". Such string version you can show to the user but server probably expects the timezone id instead. Try using dateFrom.getZone().getID().
Actually you don't have to do the insert by yourself, delegate it to your mobile's native calendar. You can use the Intent to do it.
Intents for adding events to calendar
it will automatically open your mobile's native calendar and you can refresh your view once it is added to reflect in your app.
I'm just getting up to speed on Android, and I want to send calendar event to others from mobile. Same as whatsapp sending contacts. For sending Contact in chat (XMPP) I've used vCard. So for sending calendar event in chat what should I use?
I have searched a lot. But can't find something fruitful.
Please suggest the library or code snippet for sending calendar event in XMPP.
Thanks in advance.
You may refer to iCal Import Export allows you to import iCalender files to your calender without using google synchronization services.
Using this you can import all calendar events to iCalendar files and also export those events back to calendar. Using Calendar Provider you can fetch all calendar data, but requires android API level 14 or above while using iCal Import Export you can fetch all calendar data for lower API levels too.
manifest
<uses-permission android:name="android.permission.READ_CALENDAR" />
Code:
Cursor cursor = cr.query(Uri.parse("content://calendar/calendars"), new String[]{ "_id", "displayname" }, null, null, null);
cursor.moveToFirst();
String[] CalNames = new String[cursor.getCount()];
int[] CalIds = new int[cursor.getCount()];
for (int i = 0; i < CalNames.length; i++) {
CalIds[i] = cursor.getInt(0);
CalNames[i] = cursor.getString(1);
cursor.moveToNext();
}
cursor.close();
Fetching all events, and particular event is done by specifying range
ContentResolver contentResolver = getContentResolver();
Uri.Builder builder = Uri.parse(getCalendarUriBase() + "/instances/when").buildUpon();
long now = new Date().getTime();
ContentUris.appendId(builder, now - DateUtils.MILLIS_PER_DAY*10000);
ContentUris.appendId(builder, now + DateUtils.MILLIS_PER_DAY * 10000);
and then let's say you wish to log events ID from calendar with ID = 1
Cursor eventCursor = contentResolver.query(builder.build(),
new String[] { "event_id"}, "Calendars._id=" + 1,
null, "startDay ASC, startMinute ASC");
// For a full list of available columns see http://tinyurl.com/yfbg76w
while (eventCursor.moveToNext()) {
String uid2 = eventCursor.getString(0);
Log.v("eventID : ", uid2);
}
Now display this event in Listview select one of this for send as a text messsage and on receiver side :
Calendar cal = Calendar.getInstance();
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setType("vnd.android.cursor.item/event");
intent.putExtra("beginTime", cal.getTimeInMillis());
intent.putExtra("allDay", true);
intent.putExtra("rrule", "FREQ=YEARLY");
intent.putExtra("endTime", cal.getTimeInMillis()+60*60*1000);
intent.putExtra("title", HERE MSG WHICH YOU RECEIVE);
startActivity(intent);
There is no library AFAIK and it's really just a matter of retrieving the calender event and transforming it's data into XML. Unfortunately there is also no XEP on how calendar events should be represented in XMPP/XML so you have to come up with your own representation.
iCalendar/vCalendar is the calendar file format similar to vCard
You can add new field in vcard that save calender info example
VCard vCard = new VCard();
vCard.setField("calender","calender info");
calender info should be a sting, it can be a json format string.
user who receives it can load your vcard and use method
vCard.load(connection, Jid);
String string=vCard.getField("calender");
You really don't need any specific library for that purpose.
You can check out Calendar Provider
They have an awesome example on it too!
Be sure to use these permissions in your manifest.xml
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
And if you wish to send contacts then check this out Android: How to import contact from phone?
Vote this up if it helped you! I really need it. :)
i'm trying to create a calendar on my account to fill with events that i get from some websites. I've searched and found some new android 4.0 calendar example that i've modified to obtain what i need. The problem is that the calendar is created, filled with events but not synced with google calendar, so in the next sync it is erased. The funcion i use are these:
This is the one for add the new calendar if don't alreay exist:
public static Uri createCalendarWithName(Context ctx, String name,String accountName) {
Uri target = Uri.parse(CalendarContract.Calendars.CONTENT_URI.toString());
target = target.buildUpon().appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, accountName)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, "com.google").build();
ContentValues values = new ContentValues();
values.put(Calendars.ACCOUNT_NAME, accountName);
values.put(Calendars.ACCOUNT_TYPE, "com.google");
values.put(Calendars.NAME, name);
values.put(Calendars.CALENDAR_DISPLAY_NAME, name);
values.put(Calendars.CALENDAR_COLOR, 0x00FF00);
values.put(Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_ROOT);
values.put(Calendars.OWNER_ACCOUNT, accountName);
values.put(Calendars.VISIBLE, 1);
values.put(Calendars.SYNC_EVENTS, 1);
values.put(Calendars.CALENDAR_TIME_ZONE, "Europe/Rome");
values.put(Calendars.CAN_PARTIALLY_UPDATE, 1);
values.put(Calendars.CAL_SYNC1, "https://www.google.com/calendar/feeds/" + accountName + "/private/full");
values.put(Calendars.CAL_SYNC2, "https://www.google.com/calendar/feeds/default/allcalendars/full/" + accountName);
values.put(Calendars.CAL_SYNC3, "https://www.google.com/calendar/feeds/default/allcalendars/full/" + accountName);
values.put(Calendars.CAL_SYNC4, 1);
values.put(Calendars.CAL_SYNC5, 0);
values.put(Calendars.CAL_SYNC8, System.currentTimeMillis());
Uri newCalendar = ctx.getContentResolver().insert(target, values);
return newCalendar;
}
and that one create the new event without interaction:
public static Uri createEventWithName(Context ctx, long id, String name, String data) {
long startMillis = 0;
long endMillis = 0;
int id2=(int)id;
String[] divisi = data.split("/");
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012,Integer.parseInt(divisi[0])-1, Integer.parseInt(divisi[1]));
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012,Integer.parseInt(divisi[0])-1, Integer.parseInt(divisi[1]));
endMillis = endTime.getTimeInMillis();
ContentValues cv = new ContentValues();
cv.put(Events.TITLE, name);
cv.put(Events.DTSTART, startMillis);
cv.put(Events.DTEND, endMillis);
cv.put(Events.CALENDAR_ID, id2);
Log.d("aggiungo a calendario",Integer.toString(id2));
cv.put(Events.EVENT_TIMEZONE, TimeZone.getDefault().toString());
//cv.put(Events.RRULE, "FREQ=DAILY;INTERVAL=2");
Uri newEvent = ctx.getContentResolver().insert(CalendarContract.Events.CONTENT_URI, cv);
return newEvent;
}
I'm not so experienced in Android programming so i think it's a stupid question =) i've read that accountName and Account Type must be the same that the one stored on android device, else the event is cancelled. I get accountName from android api and i think they are correct. The account type seems to work for other....
Thanks to anybody that help me!
Not possible for now.
After a lot of googling I could not find a way to create new syncable calendar in Gmail account (account type "com.google"). I've tried these scenarios:
1. without SyncAdapter and I get the same behaviour - calendar appears in external Google Calendar app with all events I added but shortly after (e.g. after couple of seconds) all events and calendar disappear.
2. with SyncAdapter and com.google authenticator - I get an error during the process
3. with SyncAdapter and com.example authenticator - possible to create calendar but not in Gmail account
Note you can create new account and create new calendar for that account (using SyncAdapter, scenario 3) but it's not a Gmail account so calendar is not syncable with Gmail Calendar (e.g. if you login to Gmail account in web browser and open Google Calendar that calendar you've just created will not show).
from http://developer.android.com/reference/android/provider/CalendarContract.html
public static final String ACCOUNT_TYPE_LOCAL
Added in API level 14 A special account type for calendars not
associated with any account. Normally calendars that do not match an
account on the device will be removed. Setting the account_type on a
calendar to this will prevent it from being wiped if it does not match
an existing account.
See Also ACCOUNT_TYPE Constant Value: "LOCAL"
Same issue i was facing. After making the below change now i am seeing the events permanently sticking to my calendar.
In the addEvent method add the below line
Uri uri = getContentResolver().insert(asSyncAdapter(Events.CONTENT_URI,"abc#gmail.com","com.gmail"), cv);
Code for asSyncAdapter is as below
static Uri asSyncAdapter(Uri uri, String account, String accountType) {
return uri.buildUpon()
.appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
.appendQueryParameter(Calendars.ACCOUNT_NAME, account)
.appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
}
According to the Javadoc for CalendarContract.Calendars:
"Calendars are designed to be primarily managed by a sync adapter and inserting new calendars should be done as a sync adapter."
If you are not a sync adapter (if you are just an arbitrary app, you are not a sync adapter), that may explain why your new calendar is not getting synchronized like you would expect.