I am following this example retrieve list of contacts to retrieve contacts from android device.
It gives all the contacts which includes email contacts and some empty contacts.
I tried modifying ContactsContract like ContactsContract.Contacts.HAS_PHONE_NUMBERin the projection and selection to get mobile contacts but nothing worked out.
String[] PROJECTION = {ContactsContract.Contacts._ID,ContactsContract.Contacts.LOOKUP_KEY,
ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts._ID,
SORT_ORDER,ContactsContract.Contacts.HAS_PHONE_NUMBER};
String SELECTION =
ContactsContract.Contacts.DISPLAY_NAME +
"<>''" + " AND "ContactsContract.Contacts.IN_VISIBLE_GROUP + "=1";
Any idea to get only contacts which has mobile numbers?
I have created this library to solve all your queries. It will only save contacts with at least one email or phone number. Also it will remove duplicates from emails and phone numbers from same contacts (created by 3rd party apps like whatsapp).
Suggestions are welcome.
Link : https://github.com/raghavsatyadev/ContactFetcher/
You can use this code to get all contact names and numbers
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
while (phones.moveToNext())
{
String contactName=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String contactNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
phones.close();
Show only contacts with phone number and open contact list intent:
Intent pickContactIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); // Uri.parse("content://contacts")
// Show only user contacts with phone numbers
pickContactIntent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE); // Show only user contacts with phone numbers
startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
Get the phone number from response/contact:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
Uri contactUri = data.getData();
String[] projection = {ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor cursor = getActivity().getContentResolver().query(contactUri, projection, null, null, null);
if (cursor == null) {
// show error msg
return;
}
cursor.moveToFirst();
int column = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
if (column >= 0) {
String phoneNo = cursor.getString(column);
sendSmsMessage(phoneNo);
} else {
// show error msg
}
cursor.close();
}
}
}
Make sure, you also handle runtime permissions in API 23+
android.permission.READ_CONTACTS
Related
I want to access different contact information like a number, an email etc.
I use code from official Android documentation:
static final int PICK_CONTACT_REQUEST = 1; // The request code
private void pickContact() {
Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request it is that we're responding to
if (requestCode == PICK_CONTACT_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// Get the URI that points to the selected contact
Uri contactUri = data.getData();
String[] projection = {Phone.NUMBER};
Cursor cursor = getContentResolver()
.query(contactUri, projection, null, null, null);
cursor.moveToFirst();
// Retrieve the phone number from the NUMBER column
int column = cursor.getColumnIndex(Phone.NUMBER);
String number = cursor.getString(column);
// Do something with the phone number...
}
}
}
The problem is, I can only access phone number and name, other data not. I can change pickContactIntent.setType to Email content type, but that I can access only Email... How can I access different kind of data in this case ?
I have created a class to find phone number in my contact.
It looks like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(resultCode == RESULT_OK){
if(requestCode == 1){
Uri returnUri = data.getData();
Cursor cursor = getContentResolver().query(returnUri, null,null,null, null);
if(cursor.moveToNext()){
//get ID
int columnIndex_ID = cursor.getColumnIndex(ContactsContract.Contacts._ID);
String contactID = cursor.getString(columnIndex_ID);
//get name
String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
name.setText(contactName);
int columnIndex_HASPHONENUMBER = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
String hasPhoneNumber = cursor.getString(columnIndex_HASPHONENUMBER);
if(hasPhoneNumber.equals("1")){
Cursor cursorNum = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactID,
null,
null
);
//get the first phone number
if(cursorNum.moveToNext()){
int columnIndex_number = cursorNum.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String stringNumber = cursorNum.getString(columnIndex_number);
phoneNumber.setText(stringNumber);
}
}else{
phoneReceiver.setText("No Phone Number");
}
}else{
Toast.makeText(ActivityPager.this,"No Data!", Toast.LENGTH_SHORT).show();
}
}
}
}
but, in my mind, i need to get the currently phone number in currently device that i use.
could i get it?
It's just a suggestion. If you want to get the contact name and details from the device means tou can do the following.
But you need to have stored the phone number on the SIM card, and there´s no other way to get your "own number".
Read the phone number from SIM by using telephones manager.
TelephonyManager tm = (TelephonyManager)this.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
String myPhoneNumber = tm.getLine1Number();
You are reading all the phone numbers from your phone. So compare this and get other details.
I have an app that allows the user to enter a phone number or select one from their contacts. To do this I use :
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
//intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT); //PICK_CONTACT is defined earlier as 1
This works fine, but it includes contacts from various apps such as Facebook emails and such. If I uncomment
//intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
It only shows contacts that you would see in the Contacts app, but it doesn't return phone numbers. Any way to fix that?
I do have the READ_CONTACTS permission.
Code to read the Uri of the contact
#Override
public void onActivityResult(int reqCode, int resultCode, Intent data)
{
super.onActivityResult(reqCode, resultCode, data);
if(reqCode != PICK_CONTACT) return;
Cursor cur = getContentResolver().query(data.getData(), null,
null, null, null);
if (cur.getCount() <= 0) return;
while (cur.moveToNext())
{
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
// Query phone here. Covered next
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ id,null, null);
while (phones.moveToNext())
//phone is the EditText view where the user enters a phone number
phone.setText(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
phones.close();
}
}
}
but it doesn't return phone numbers
If you add the READ_CONTACTS permission, you can query ContactsContract, either to present the entire list yourself, or to query to get the phone number of a contact the user selected via ACTION_PICK.
Without READ_CONTACTS, you have no right to access contact phone numbers by any means, other than the user typing one into your app directly.
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
};
...
I'm trying to call the contact picker, get the persons name, phone and e-mail into strings and send them to another activity using an intent. So far this works:
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, 1);
// ...
#Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor c = managedQuery(contactData, null, null, null, null);
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
Intent intent = new Intent(CurrentActivity.this, NewActivity.class);
intent.putExtra("name", name);
startActivityForResult(intent, 0);
}
}
}
But if i add in:
String number = c.getString(c.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
it force closes
Maybe theres another way to get their number?
Phone Numbers
Phone numbers are stored in their own table and need to be queried separately. To query the phone number table use the URI stored in the SDK variable ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Use a WHERE conditional to get the phone numbers for the specified contact.
if (Integer.parseInt(cur.getString(
cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
// Do something with phones
}
pCur.close();
}
Perform a second query against the Android contacts SQLite database. The phone numbers are queried against the URI stored in ContactsContract.CommonDataKinds.Phone.CONTENT_URI. The contact ID is stored in the phone table as ContactsContract.CommonDataKinds.Phone.CONTACT_ID and the WHERE clause is used to limit the data returned.
Email Addresses
Querying email addresses is similar to phone numbers. A query must be performed to get email addresses from the database. Query the URI stored in ContactsContract.CommonDataKinds.Email.CONTENT_URI to query the email address table.
Cursor emailCur = cr.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
new String[]{id}, null);
while (emailCur.moveToNext()) {
// This would allow you get several email addresses
// if the email addresses were stored in an array
String email = emailCur.getString(
emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
String emailType = emailCur.getString(
emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
}
emailCur.close();
As with the phone query the field names for the email table are also stored under ContactsContract.CommonDataKinds. The email query is performed on the URI in ContactsContract.CommonDataKinds.Email.CONTENT_URI and the WHERE clause has to match the ContactsContract.CommonDataKinds.Email.CONTACT_ID field. Since multiple email addresses can be stored loop through the records returned in the Cursor.
More tutorials here
This method requires Android API version 5 or higher.
Building on the accepted answer, if you want to jump straight to the desired email address and not require the contacts permission use something like this:
private static final int REQUEST_CODE_EMAIL = 1;
void startSelectingEmail() {
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Email.CONTENT_URI);
startActivityForResult(intent, REQUEST_CODE_EMAIL);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_EMAIL) {
Uri emailUri = data.getData();
Cursor emailCursor = getContext().getContentResolver().query(emailUri, null, null, null, null);
if (emailCursor != null) {
if (emailCursor.moveToFirst()) {
String email = emailCursor.getString(
emailCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.DATA));
String emailType = emailCursor.getString(
emailCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.TYPE));
Log.d(TAG, "Email: " + emailType + " " + email);
}
emailCursor.close();
}
}
}
This doesn't require the contacts permission to read the email address like the double query methods above. It also makes it so that you do not need to write UI for the user to select the appropriate email address for contacts with multiple emails, the user selects a specific email in the Contacts app so you only get one result.
The cursor comes back with quite a few columns in addition to just email address like display name, though that has only been verified on a Nexus 5 running Android M.