I am unable to update calendar event details programmatically. Here is the code sample. Any help should be greatly appreciated.
Uri CALENDAR_URI = Uri.parse("content://com.android.calendar/events");
Cursor c = context.getContentResolver().query(CALENDAR_URI, null, null, null, null);
String[] s = c.getColumnNames();
if (c.moveToFirst()) {
while (c.moveToNext()) {
String _id = c.getString(c.getColumnIndex("_id"));
String CalId = c.getString(c.getColumnIndex("calendar_id"));
if ((_id == null) && (CalId == null)) {
return false;
} else {
if (_id.equals(eventId) && CalId.equals(cal_Id)) {
Uri uri = ContentUris.withAppendedId(CALENDAR_URI, Integer.parseInt(_id));
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.SELF_ATTENDEE_STATUS, statusId);
context.getContentResolver().update(uri, event, null, null);// need to give your data here
return true;
}
}
}
}
Related
I am saving an event in the device calendar with the below code
ContentResolver cr = getCurrentContext().getContentResolver();
ContentValues values = new ContentValues();
Calendar startDate = Calendar.getInstance();
startDate.setTimeInMillis(contentDatum.getGist().getScheduleStartDate());
Calendar endDate = Calendar.getInstance();
endDate.setTimeInMillis(contentDatum.getGist().getScheduleEndDate());
values.put(CalendarContract.Events.DTSTART, startDate.getTimeInMillis());
values.put(CalendarContract.Events.DTEND, endDate.getTimeInMillis());
values.put(CalendarContract.Events.TITLE, contentDatum.getGist().getTitle());
values.put(CalendarContract.Events.DESCRIPTION, contentDatum.getGist().getDescription());
values.put(CalendarContract.Events.CALENDAR_ID, getCalendarId());
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());
Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
long eventID = Long.parseLong(uri.getLastPathSegment());
Log.e("event", "" + eventID);
setCalendarEventId(eventID);
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID));
getCurrentActivity().startActivityForResult(intent, 0);
I am saving the eventID it returns when it is inserted.
To retrieve the data on the basis of event id, i am using the below code
for (int i = 0; i < calendarEventIds.length; i++) {
long eventID = Long.parseLong(calendarEventIds[i]);
Uri event = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID);
Cursor cursor;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
cursor = getCurrentContext().getContentResolver().query(event, null, null, null);
} else {
cursor = getCurrentActivity().managedQuery(event, null, null, null, null);
}
if (cursor.getCount() == 1) {
if (cursor.moveToFirst()) {
if (cursor.getLong(cursor.getColumnIndex(CalendarContract.Events.DTSTART)) == contentDatum.getGist().getScheduleStartDate()
&& cursor.getLong(cursor.getColumnIndex(CalendarContract.Events.DTEND)) == contentDatum.getGist().getScheduleEndDate()
&& cursor.getString(cursor.getColumnIndex(CalendarContract.Events.TITLE)).equalsIgnoreCase(contentDatum.getGist().getTitle())
&& cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DESCRIPTION)).equalsIgnoreCase(contentDatum.getGist().getDescription())) {
Toast.makeText(getCurrentContext(), "Event already exists in your calendar.", Toast.LENGTH_SHORT).show();
calendarEventExist = true;
}
}
}
}
However I do not the details of the event I added.
I was saving the calendar id's in comma separated string. The below code works perfectly fine for fetching the details of event
if (getCalendarEventId() != null) {
String[] calendarEventIds = getCalendarEventId().split(";");
for (int i = 0; i < calendarEventIds.length; i++) {
long eventID = Long.parseLong(calendarEventIds[i]);
Uri event = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID);
Cursor cursor;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
cursor = getCurrentContext().getContentResolver().query(event, null, null, null);
} else {
cursor = getCurrentActivity().managedQuery(event, null, null, null, null);
}
if (cursor.moveToFirst()) {
do {
if ((cursor.getInt(cursor.getColumnIndex(CalendarContract.Events.DELETED)) == 1)) {
//The added event was deleted and is not visible in calendar but exists in calendar DB
calendarEventExist = false;
break;
}
if (cursor.getString(cursor.getColumnIndex(CalendarContract.Events.TITLE)).equalsIgnoreCase(contentDatum.getGist().getTitle())
&& cursor.getString(cursor.getColumnIndex(CalendarContract.Events.DESCRIPTION)).equalsIgnoreCase(contentDatum.getGist().getDescription())) {
Toast.makeText(getCurrentContext(), "Event already exists in your calendar.", Toast.LENGTH_SHORT).show();
calendarEventExist = true;
break;
}
} while (cursor.moveToNext());
}
}
} else {
calendarEventExist = false;
}
My code is returning ID = 1367(correct ID is 233). What is wrong? I have working code searching ID by phone number, but I need to change it to searching by display name.
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" like'%" + mStructuredName +"%'";
String[] projection = new String[] { ContactsContract.PhoneLookup._ID};
Cursor mcursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, selection, null, null);
long idPhone = 0;
try {
if (mcursor != null) {
if (mcursor.moveToFirst()) {
idPhone = Long.valueOf(mcursor.getString(0));
}
}
} finally {
if (mcursor != null) {
mcursor.close();
}
}
if (idPhone > 0) {
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, idPhone));
startActivity(intent);
}
Searching by phone number (working)
Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(tempPhoneNum));
Cursor mcursor = getContentResolver().query(lookupUri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup._ID}, null, null, null);
long idPhone = 0;
try {
if (mcursor != null) {
if (mcursor.moveToFirst()) {
idPhone = Long.valueOf(mcursor.getString(mcursor.getColumnIndex(ContactsContract.PhoneLookup._ID)));
}
}
} finally {
if (mcursor != null) {
mcursor.close();
}
}
if (idPhone > 0) {
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, idPhone));
startActivity(intent);
}
Your code seems too complicated, here is mine:
Cursor contacts_cur = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +" = ?",
new String[]{name}, null);
contacts_cur.moveToNext();
String id = cursor.getString(cursor.getColumnIndex( ContactsContract.Contacts._ID));
Note that is seems dangerous for me to retrieve the id by name since two contacts can have the same name (but not the same id).
I have an assynctask that will read all the content in the conversation box and it works well
protected String doInBackground(String... params) {
Uri inboxURI = Uri.parse("content://sms/conversations");
ContentResolver cr = getContentResolver();
Cursor c = cr.query(inboxURI, null, null, null, null);
c.moveToLast();
al = new ArrayList<MessageInfo>();
try{
for (int i = c.getCount(); i > 0; i--) {
MessageInfo mMessageInfo = new MessageInfo();
mMessageInfo.MessageText = c.getString(c.getColumnIndexOrThrow("snippet"));
mMessageInfo.ThreadId = c.getInt(c.getColumnIndex("thread_id"));
Uri uri = Uri.parse("content://sms/inbox");
String where = "thread_id=" + mMessageInfo.ThreadId;
Cursor Cursor = getContentResolver().query(uri, null, where,null, null);
startManagingCursor(Cursor);
//Cursor.moveToFirst();
String number = "";
String name = "";
if (Cursor.moveToFirst()) {
number = Cursor.getString(Cursor.getColumnIndexOrThrow("address")).toString();
name = GetNameAndNumber(Cursor, number, MessageBox.this);
Log.i("checkPoint","checkPoint-1 "+name);
}
else {
uri = Uri.parse("content://sms/sent");
where = "thread_id=" + mMessageInfo.ThreadId;
Cursor = GetCursor(uri, where, MessageBox.this);
if (Cursor.moveToFirst()) {
number = Cursor.getString(Cursor.getColumnIndexOrThrow("address")).toString();
name = GetNameAndNumber(Cursor, number, MessageBox.this);
Log.i("checkPoint","checkPoint-2 "+name);
}Cursor.close();
}
if (name.length() > 0) {
mMessageInfo.Name = name;
} else {
mMessageInfo.Name = number;
}
mMessageInfo.Number = number;
Log.i("name",name);
Log.i("number",number);
Log.i("mMessageInfo.ThreadId ",""+mMessageInfo.ThreadId );
al.add(mMessageInfo);
c.moveToPrevious();
}c.close();
}catch(Exception x){x.printStackTrace();}
return "Executed";
}
But if my app writes to content://sms/sent the above code gives null exception but the stock messaging app can read it well.
This is the method how I update my sent items
void sentBox(){
ContentValues values = new ContentValues();
values.put("address", number);
values.put("body", msgBox.getText().toString());
getContentResolver().insert(Uri.parse("content://sms/sent"), values);
finish();
}
To be specific I cannot get the address of the message in the sent items.. below returns null exception.. I think there is something to do with my URI.
if (Cursor.moveToFirst())
number = Cursor.getString(Cursor.getColumnIndexOrThrow("address")).toString();
Can someone give me hint why it can't read if I write/update my sent box that way?
I've Manage to fix the problem. It was another method which is writing to sent box using the message ID where there is another method writing to sent box using the address..
protected String doInBackground(String... params) {
al = new ArrayList<MessageInfo>();
String number = "";
String name = "";
Uri conversationURI = Uri.parse("content://sms/conversations");
ContentResolver cr = getContentResolver();
Cursor c = cr.query(conversationURI, null, null, null, null);
c.moveToLast();
for (int i = c.getCount(); i > 0; i--) {
MessageInfo mMessageInfo = new MessageInfo();
mMessageInfo.MessageText = c.getString(c.getColumnIndexOrThrow("snippet"));
mMessageInfo.ThreadId = c.getInt(c.getColumnIndex("thread_id"));
try{
Uri message = Uri.parse("content://sms/inbox");
ContentResolver cr_ = getContentResolver();
String where_ = "thread_id=" + mMessageInfo.ThreadId;
Cursor c_ = cr_.query(message, null, where_, null, null);
startManagingCursor(c_);
if (c_.moveToFirst() && c_ != null) {
number = c_.getString(c_.getColumnIndexOrThrow("address"));
name = GetNameAndNumber(c_, number, MessageBox.this);
}else{
Uri _message_ = Uri.parse("content://sms/sent");
ContentResolver _cr_ = getContentResolver();
String _where_ = "thread_id=" + mMessageInfo.ThreadId;
Cursor _c_ = _cr_.query(_message_, null, _where_, null, null);
if (_c_.moveToFirst() && _c_ != null) {
number = _c_.getString(_c_.getColumnIndexOrThrow("address"));
name = GetNameAndNumber(_c_, reformatNumber(number), MessageBox.this);
}
}
}catch(Exception x){x.printStackTrace();}
if (name.length() > 0) {
mMessageInfo.Name = name;
} else {
mMessageInfo.Name = number;
}
mMessageInfo.Number = number;
al.add(mMessageInfo);
c.moveToPrevious();
}c.close();
return null;
}
Changed this FROM:
void sentBox(){
ContentValues values = new ContentValues();
values.put("thread_id", getIntent().getExtras().getInt("ID"));
values.put("body", mMessageEditText.getText().toString());
getContentResolver().insert(Uri.parse("content://sms/sent"), values);
}
TO:
void sentBox(){
ContentValues values = new ContentValues();
values.put("address", getIntent().getExtras().getString("number"));
values.put("body", mMessageEditText.getText().toString());
}
I need to get the thread_id of the mms-sms/conversations Android content provider, this is what I have done so far:
public long findThreadIdFromPhoneNumber(Context context, PhoneNumber phoneNumber) {
Uri.Builder uriBuilder = Uri.withAppendedPath(Uri.parse(CONTENT_SMSMMS+"/"), "threadID").buildUpon();
// phoneNumber.msisdn() return the String phone number
uriBuilder.appendQueryParameter("recipient", phoneNumber.msisdn());
long threadId = -1L;
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(
uriBuilder.build(),
new String[] { Contacts._ID },
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
threadId = cursor.getLong(0);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return threadId;
}
The problem is that this code create new threads in the content provider, and I don't need that, I just need to return the thread_id if the conversation exists and -1 if it do not exists.
I also tried this code:
public long findThreadIdFromPhoneNumber(Context context, PhoneNumber phoneNumber) {
long threadId = -1L;
Cursor cursor = null;
try {
if (context==null || context.getContentResolver()==null || phoneNumber==null || phoneNumber.msisdn()==null)
return threadId;
cursor = context.getContentResolver().query(
Uri.parse(CONTENT_SMSMMS_CONVERSATIONS),
// phoneNumber.msisdn() return the String phone number
null, "address='"+phoneNumber.msisdn()+"' ",
null, null
);
if (cursor != null && cursor.moveToFirst()) {
if (cursor.getColumnIndex("thread_id")>=0)
threadId = cursor.getLong(cursor.getColumnIndex("thread_id"));
}
} catch (Exception e) {
e.printStackTrace();
String number = (phoneNumber!=null && phoneNumber.msisdn()!=null) ? phoneNumber.msisdn() : "";
Logcat.e("Error during findThreadIdFromPhoneNumber for "+number+": "+e.getMessage(), e);
return threadId;
} finally {
if (cursor != null) {
cursor.close();
}
}
return threadId;
}
But this code give me an external NullPointerException in the ContentResolver in some phones, and it works in other:
java.lang.NullPointerException
at android.os.Parcel.readException(Parcel.java:1437)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:385)
at android.content.ContentResolver.query(ContentResolver.java:417)
at android.content.ContentResolver.query(ContentResolver.java:360)
at com.mypackage.android.sms.SmsMmsManager.findThreadIdFromPhoneNumber(SmsMmsManager.java:115)
Use this uri for fetching
ContentResolver cr = context.getContentResolver();
Cursor pCur = cr.query(
Uri.parse("content://mms-sms/canonical-addresses"), new String[]{"_id"},
"address" + " = ?",
new String[]{your_address}, null);
String thread_id = null;
if (pCur != null) {
if (pCur.getCount() != 0) {
pCur.moveToNext();
thread_id = pCur.getString(pCur.getColumnIndex("_id"));
}
pCur.close();
}
public MessageObjects getSms2(Context context , String number) {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor cursor = contentResolver.query(uri, null, "thread_id IS NOT NULL) GROUP BY (thread_id AND address=?", new String[]{number}, "date DESC");
String displayName;
String formattedDate = "";
String photoUri = null;
MessageObjects contct = new MessageObjects();
while (cursor.moveToNext()) {
displayName = "";
long key = cursor.getLong(cursor.getColumnIndex("_id"));
long threadId = cursor.getLong(cursor.getColumnIndex("thread_id"));
String address = cursor.getString(cursor.getColumnIndex("address")); // phone #
long date = cursor.getLong(cursor.getColumnIndex("date"));
Date callDayTime = new Date(Long.valueOf(date));
String body = cursor.getString(cursor.getColumnIndex("body"));
String person = cursor.getString(cursor.getColumnIndex("person"));
contct.setThreadId(threadId);
contct.setNumber(address);
contct.setTime(date);
contct.setMsg(body);
contct.setPerson(displayName);
}
cursor.close();
return contct;
}
I'm trying to read all the contacts using RawContacts.entityIterator but I'm seeing this error:
android.database.CursorIndexOutOfBoundsException: Index -1 requested
Following is my code:
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(Contacts.CONTENT_URI,
null, null, null, null);
String id = cur.getString(cur.getColumnIndex(Contacts._ID));
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
final Uri uri = RawContactsEntity.CONTENT_URI;
final String selection = Data.CONTACT_ID + "=?";
final String[] selectionArgs = new String[] {id};
final Map<String, List<ContentValues>> contentValuesListMap =
new HashMap<String, List<ContentValues>>();
EntityIterator entityIterator = null;
entityIterator = RawContacts.newEntityIterator(cr.query(
uri, null, selection, selectionArgs, null));
while (entityIterator.hasNext()) {
Entity entity = entityIterator.next();
for (NamedContentValues namedContentValues : entity.getSubValues()) {
ContentValues contentValues = namedContentValues.values;
String key = contentValues.getAsString(Data.MIMETYPE);
if (key != null) {
List<ContentValues> contentValuesList =
contentValuesListMap.get(key);
if (contentValuesList == null) {
contentValuesList = new ArrayList<ContentValues>();
contentValuesListMap.put(key, contentValuesList);
}
contentValuesList.add(contentValues);
}
}
}
Log.i(tag, "Contact index=" + id);
}
}
Can somebody please tell me what's wrong with my code.
After you execute query, you must call cur.moveToFirst()...
Try this
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(Contacts.CONTENT_URI,
null, null, null, null);
if(cur != null && cur.moveToFirst())
{
String id = cur.getString(cur.getColumnIndex(Contacts._ID));
if (cur.getCount() > 0) {
...
It is not required to call moveToFirst but to ensure that you moved to any of the returned rows before accessing a value (see moveToLast(), moveToPosition(int position), ... ).
So this one:
Cursor cur = cr.query(Contacts.CONTENT_URI, null, null, null, null);
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(Contacts._ID));
final Uri uri = RawContactsEntity.CONTENT_URI;
would work as well - or even better, because there is an issue with the accepted answer, if you continue with ...
while (cur.moveToNext()) {
after
if (cur.getCount() > 0) {
It would skip the first row, what might not be obvious.