I've worked hard on the following code, but unfortunately, the entry is assigned to the wrong contact. I don't know why. Tested for hours days but can't find the mistake. Can you help me?
I would like to use the code in order to select a person from the contact list (using the contact picker) and then adding an event entry (date of birth) for this person to the contacts table.
Step 1:
I've already set the permission in the manifest file:
<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>
Step 2:
The contact picker's ID is defined:
private static final int CONTACT_PICKER_ID = 123;
Step 3:
The contact picker is called:
Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(contactPickerIntent, CONTACT_PICKER_ID);
Step 4:
Another method listens for the contact picker's result and tries to add an event for the selected user:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case CONTACT_PICKER_ID:
Uri selectedPerson = data.getData();
String contactId = selectedPerson.getLastPathSegment();
// ADD A NEW EVENT FOR THE SELECTED CONTACT --- BEGIN
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
values.put(ContactsContract.Data.RAW_CONTACT_ID, contactId);
values.put(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY);
values.put(ContactsContract.CommonDataKinds.Event.RAW_CONTACT_ID, contactId);
values.put(ContactsContract.CommonDataKinds.Event.LABEL, "");
values.put(ContactsContract.CommonDataKinds.Event.START_DATE, "2010-01-28"); // hard-coded date of birth
Uri created = null;
try {
created = getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}
catch (Exception e) {
}
if (created == null) {
Toast.makeText(this.getApplicationContext(), "Failed inserting the event!", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this.getApplicationContext(), "Successfully inserted the event!", Toast.LENGTH_SHORT).show();
}
// ADD A NEW EVENT FOR THE SELECTED CONTACT --- END
break;
}
}
}
The event is successfully inserted to the database and also shown in the Google contacts - but unfortunately it's assigned to the wrong contact. Why is this so? Is my contactId wrong that I get from the contact picker?
The activity result that you get back from the contact picker is the full path to the contact. Something like:
content://com.android.contacts/contacts/lookup/0r7-2C46324E483C324A3A484634/7
This is what's in your:
Uri selectedPerson = data.getData();
This contains both the Contact's LOOKUP_KEY AND the Contact's _ID. However, you need to be using the RawContacts _ID when inserting into the Data table. What you need to do is grab the RawContact's _ID:
long rawContactId = -1;
Cursor c = getContentResolver().query(RawContacts.CONTENT_URI,
new String[]{RawContacts._ID},
RawContacts.CONTACT_ID + "=?",
new String[]{String.valueOf(contactId)}, null);
try {
if (c.moveToFirst()) {
rawContactId = c.getLong(0);
}
} finally {
c.close();
}
And then use the rawContactId:
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
However, it should be noted that there can be multiple RawContacts per one Contact. You may want to adjust your code so that it adds an event for each RawContact.
One entry is wrong in your content values. The Uri which you get in your onActivityResult data variable is not the raw_contact_id but the contact id. The difference between both is that one contact can contain multiple raw contacts. A raw contact is associated with a single account like Google or Facebook. But a contact can contain multiple raw_contacts.
Uri selectedPerson = data.getData();
String contactId = selectedPerson.getLastPathSegment();
// ADD A NEW EVENT FOR THE SELECTED CONTACT --- BEGIN
ContentValues values = new ContentValues();
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
***values.put(ContactsContract.Data.CONTACT_ID, contactId);***
values.put(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY);
values.put(ContactsContract.CommonDataKinds.Event.RAW_CONTACT_ID, contactId);
values.put(ContactsContract.CommonDataKinds.Event.LABEL, "");
values.put(ContactsContract.CommonDataKinds.Event.START_DATE, "2010-01-28"); // hard-coded date of birth
try switching...
Uri created = null;
try {
created = getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}catch (Exception e) {
}
if (created == null) {
Toast.makeText(this.getApplicationContext(), "Failed inserting the event!", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this.getApplicationContext(), "Successfully inserted the event!", Toast.LENGTH_SHORT).show();
}
to...
try{
Uri created = getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
if (created == null) {
Toast.makeText(this.getApplicationContext(), "Failed inserting the event!", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this.getApplicationContext(), "Successfully inserted the event!", Toast.LENGTH_SHORT).show();
}
}catch (Exception e) {}
Related
I'm using a function to select phone names from the android phone book and using a cursor to get the name and number of the contact. I am able to successfully do that and insert the values into the sqllite database that I have written with help from another question on here but the listview does not automatically update when there is a new value inserted to the database.
I've used all the lines required including
((BaseAdapter)display_contacts1.getAdapter()).notifyDataSetChanged();
display_contacts1.invalidateViews();
arrayAdapter.notifyDataSetChanged();
manageListView(getContext());
But I am still having no luck finding a solution. The only way the listview will update is if I go into a different fragment or restart the app.
Original SQL Database code
Android OnItemClick not working with loaded SQL Database into listview
SelectModemFragment.java
//--------------------------------------------------------------------
// Select Phone number from Contacts list
//--------------------------------------------------------------------
#Override
public void onActivityResult(int reqCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK)
{
// Check for the request code
switch (reqCode)
{
case CONTACT_PICKER:
contactPicked(data);
break;
}
}
else
{
Log.e("MainActiivity", "Failed to pick contact");
}
}
private void contactPicked(Intent data)
{
//Cursor cursor = null;
try
{
// getData() method will have the Content Uri of the selected contact
Uri uri = data.getData();
//Query the content uri
cursor = getActivity().getApplicationContext().getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
// column index of the contact name
int nameIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
// column index of the phone number
int phoneIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
name = cursor.getString(nameIndex);
phoneNo = cursor.getString(phoneIndex);
// Show message displaying the contact selected from the phonebook
Toast.makeText(getContext(),name, Toast.LENGTH_SHORT).show();
Toast.makeText(getContext(), phoneNo, Toast.LENGTH_SHORT).show();
// Insert values to sqlite database
dbHelper.insert(name, phoneNo);
// Need to immediately update the listview one the values have been inserted into the database
((BaseAdapter)display_contacts1.getAdapter()).notifyDataSetChanged();
//display_contacts1.invalidateViews(); // This isn't working
//arrayAdapter.notifyDataSetChanged(); // This isn't working
//manageListView(getContext());, this didn't work
}
catch (Exception e)
{
e.printStackTrace();
}
}
After inserting the values into the database you can still call notifyDataSetChanged() and then just open the fragment again
// Need to immediately update the listview one the values have been inserted into the database
((BaseAdapter)display_contacts1.getAdapter()).notifyDataSetChanged();
// Reopen the fragment
getFragmentManager().beginTransaction().replace(R.id.frame_layout, SelectModemFragment.newInstance()).commit();
So I've written a query to extract the WhatsApp contacts of a phone. My initial query goes like this:
Cursor c = con.getContentResolver().query(
ContactsContract.RawContacts.CONTENT_URI,
new String[]{ContactsContract.RawContacts.CONTACT_ID, ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY},
ContactsContract.RawContacts.ACCOUNT_TYPE + "= ?",
new String[]{"com.whatsapp"},
null
);
ArrayList<String> myWhatsappContacts = new ArrayList<String>();
int contactNameColumn = c.getColumnIndex(ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY);
while (c.moveToNext()) {
// You can also read RawContacts.CONTACT_ID to read the
// ContactsContract.Contacts table or any of the other related ones.
myWhatsappContacts.add(c.getString(contactNameColumn));
}
The purpose of this is to find out how many WhatsApp contacts the phone has at any one time. When I do:
Log.i("WhatsApp contacts found:", Integer.toString(myWhatsappContacts.size());
It should print out how many WhatsApp contacts there were into LogCat. And this works - up to a point.
Let's say for example that the number of WhatsApp contacts I have now is 101. The next phase of this little project is to delete away ALL contacts if there are more than 100 of them. In which case, we go:
if (myWhatsappContacts.size() > 100) {
//Delete all contacts code here
}
I've tested the delete contacts code, it works. I check the contacts directory of the phone via the contacts app, and it says 0. But now when I do the query again (refer to code above), it still shows 101! What's going on?
If it helps, my DeleteContacts method is as follows:
private void deleteContact(Context ctx, String phone, String name) {
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
Cursor cur = ctx.getContentResolver().query(contactUri, null, null, null, null);
try {
if (cur.moveToFirst()) {
do {
if (cur.getString(cur.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)).equalsIgnoreCase(name)) {
String lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
ctx.getContentResolver().delete(uri, null, null);
return;
}
} while (cur.moveToNext());
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
} finally {
cur.close();
}
return;
}
What am I doing wrong? Is my DeleteContacts code faulty? Or is the query itself faulty?
I want to retrieve the mobile number from the contacts (I want to send an sms). Here my code:
//Selecting the contact
Button buttonPickContact = (Button)findViewById(R.id.pickcontact);
buttonPickContact.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, RQS_PICK_CONTACT);
}});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Cursor cursor = null;
mName.setText(context.getString(R.string.not_available));
mNumber.setText(context.getString(R.string.not_available));
if(requestCode == RQS_PICK_CONTACT && resultCode == RESULT_OK && data != null){
Log.d(TAG, "requestCode, resultCode, data ok");
Uri uri = data.getData();
try{
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.HAS_PHONE_NUMBER};
// cursor = getContentResolver().query(uri, projection, null, null, null);
cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
Log.d(TAG, "Trying to retrieve the name and the number");
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String hasNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.HAS_PHONE_NUMBER));
Log.d(TAG, "hasNumber "+hasNumber);
mName.setText(name);
if(hasNumber.trim().equals("1")){
Log.d(TAG, "contact has telephone number");
//set name and number
String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
mNumber.setText(phoneNumber);
}
}catch(Exception ex){
CharSequence text = context.getString(R.string.cannot_choose_contact);
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
if(cursor!= null && !cursor.isClosed()){
cursor.close();
}
}else{
CharSequence text = context.getString(R.string.cannot_choose_contact);
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
I am getting: Failed to read row 0, column -1 from CursorWindow...
How do I get the phone number - am I trying to retrieve it from the right column?
Thanks in advance for your answers,
The detailed data for a contact is contained in a separate table from the main contact itself (see the Contacts API guide for more detail). Since you're sending an SMS, it might be more useful to only get the contacts who have a phone number associated, so you might as well go straight for the table which contains phone numbers. For the URI, I use:
CommonDataKinds.Phone.CONTENT_URI
Then you don't have to worry about HAS_PHONE_NUMBER. At a glance, the rest of your code looks right or very close. If you wanted to continue down your original path, you'd have to do a separate query on this table anyway, but provide it the ID of the contact that you initially found.
Use a CursorLoader to do queries. Always. If you continue to do queries on the UI thread, eventually you'll run into a situation where you hang the system and get an ANR.
You're requesting the user to pick contacts from the Contacts table, so you'll get back a URI that points to a contact in Contacts.
A trick for handling this is to strip the contact's LOOKUP_KEY from the returned URI using
Uri.getLastPathSegment(). Then search ContactsContract.Data for the LOOKUP_KEY and the
MIMETYPE value CommonDataKinds.Email.CONTENT_ITEM_TYPE. Based on your code, this would be:
mLookupKey = uri.getLastPathSegment();
String SELECTION = Data.LOOKUP_KEY + " = ? " +
" AND " +
Data.MIMETYPE + " = ?";
String[] selectionArgs = {
mLookupKey,
Email.CONTENT_ITEM_TYPE
};
...
iam adding a contact to the device using this code
long Contact_Id = 100;
ContentValues pCV =new ContentValues();
pCV.put(Contacts.People.NAME, "test");
pCV.put(ContactsContract.Contacts._ID, Contact_Id);
Uri newContactUri = insertContentValues(cResolver,
Contacts.People.CONTENT_URI, pCV);
i want to add this contact to a certain Account. iam using this code below
ContentResolver cResolver = context.getContentResolver();
cResolver.insert(uri, ContactsContract.RawContacts.CONTENT_URI,
getAccountType());
public ContentValues getAccountType() {
ContentValues cv = new ContentValues();
cv.put(ContactsContract.RawContacts.ACCOUNT_TYPE, "com.sonyericsson.localcontacts");
cv.put(ContactsContract.RawContacts.ACCOUNT_NAME, "Phone contacts");
return cv;
}
this code actually is adding a new contact to the "Phone contacts" Account. but i want to add the contact that i added above ("test") to be added to the "Phone contacts".
how can i do so?
You can try both the solution as per your choice/requirement.Both are working perfectly
To add contact open directly edit activity
try {
Intent addContactIntent = new Intent(Intent.ACTION_INSERT);
addContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
addContactIntent.putExtra(ContactsContract.Intents.Insert.PHONE, number);
addContactIntent.putExtra("finishActivityOnSaveCompleted", true);
context.startActivity(addContactIntent);
} catch (Exception e) {
e.printStackTrace();
}
option to create contact or add contact to existing contact
try {
Intent i = new Intent(Intent.ACTION_INSERT_OR_EDIT);
i.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
// i.putExtra(ContactsContract.Intents.Insert.NAME, "TESTTEST");
i.putExtra(ContactsContract.Intents.Insert.PHONE, number);
context.startActivity(i);
} catch (Exception e) {
e.printStackTrace();
}
After searching I have found that the best way to insert a Contact to the Local Phone contacts is to assign the ACCOUNT_TYPE, ACCOUNT_NAME to null take a look at this Link
I'm trying to allow a user to select a phone number from a contact using the contact picker. However, right now all the examples I see online show how you can select a contact, but I am hoping to have a second screen then pop up if that contact has multiple phone numbers so you can specify which one you want to select (the way that text message lets you do so when you select a contact).
My question is, do you have to gather all of the numbers and then ask the user to select a number, or is this functionality already built into Android? I'm hoping I just forgot a flag or something.
Alternatively, you can initially display the phone numbers associated with each contact in the Contact Picker and select one that way. Launch contact picker this way (note the different URI than my other answer):
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
startActivityForResult(intent, REQUEST_PICK_CONTACT);
Then, in onActivityResult():
Uri result = data.getData();
Log.v(TAG, "Got a result: " + result.toString());
// get the phone number id from the Uri
String id = result.getLastPathSegment();
// query the phone numbers for the selected phone number id
Cursor c = getContentResolver().query(
Phone.CONTENT_URI, null,
Phone._ID + "=?",
new String[]{id}, null);
int phoneIdx = c.getColumnIndex(Phone.NUMBER);
if(c.getCount() == 1) { // contact has a single phone number
// get the only phone number
if(c.moveToFirst()) {
phone = c.getString(phoneIdx);
Log.v(TAG, "Got phone number: " + phone);
loadContactInfo(phone); // do something with the phone number
} else {
Log.w(TAG, "No results");
}
}
I was able to do this by creating a second dialog which shows all the phone numbers associated with a contact.
First, call this somewhere in your code:
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, REQUEST_PICK_CONTACT);
Then in onActivityResult() use this to decide if the selected contact has multiple phone numbers, and display a dialog if so:
Uri result = data.getData();
Log.v(TAG, "Got a result: " + result.toString());
// get the contact id from the Uri
String id = result.getLastPathSegment();
// query for phone numbers for the selected contact id
c = getContentResolver().query(
Phone.CONTENT_URI, null,
Phone.CONTACT_ID + "=?",
new String[]{id}, null);
int phoneIdx = c.getColumnIndex(Phone.NUMBER);
int phoneType = c.getColumnIndex(Phone.TYPE);
if(c.getCount() > 1) { // contact has multiple phone numbers
final CharSequence[] numbers = new CharSequence[c.getCount()];
int i=0;
if(c.moveToFirst()) {
while(!c.isAfterLast()) { // for each phone number, add it to the numbers array
String type = (String) Phone.getTypeLabel(this.getResources(), c.getInt(phoneType), ""); // insert a type string in front of the number
String number = type + ": " + c.getString(phoneIdx);
numbers[i++] = number;
c.moveToNext();
}
// build and show a simple dialog that allows the user to select a number
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.select_contact_phone_number_and_type);
builder.setItems(numbers, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
String number = (String) numbers[item];
int index = number.indexOf(":");
number = number.substring(index + 2);
loadContactInfo(number); // do something with the selected number
}
});
AlertDialog alert = builder.create();
alert.setOwnerActivity(this);
alert.show();
} else Log.w(TAG, "No results");
} else if(c.getCount() == 1) {
// contact has a single phone number, so there's no need to display a second dialog
}
I know this is an old question but I hope it helps.
Just in case someone stumbles across this again.
Another alternative to the other answers is the library https://github.com/codinguser/android_contact_picker
Full Disclosure: I am the author of this library
it is simple explained on android developers reference:
https://developer.android.com/training/contacts-provider/modify-data.html#InsertEdit
and simple append code:
String phoneNumber = "+01 123 456 789";
Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
intent.putExtra(ContactsContract.Intents.Insert.PHONE, phoneNumber);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_CODE_ADD_PHONE_CONTACT);
}
if you needed activity result, you must listen to onActivityResult event on Activity by REQUEST_CODE_ADD_PHONE_CONTACT variable.