I query the CallLog.Calls provider in order to retrieve a list of calls from a certain contact, based on the contact's display name. In particular, I use this query:
String selection = CallLog.Calls.CACHED_NAME + "= ?";
String dispName = dataCollector.getDisplayName();
Cursor callCursor =
cr.query(callLogUri, callLogProjection, selection,
new String[] {dispName},CallLog.Calls.DATE + " DESC");
The dataCollector object is used to hold information from queries based on a given contact id.
The problem is that this code only returns one call for the given contact. I can't understand why. Any clues?
int i=0;
while(cursor.moveToNext())
{
Sring id = cursor.getString(cursor.getColumnIndex(CallLog.Calls._ID));
numbersTemp[i]=cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
valuesTemp[i]=cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
i++;
}
Related
I want to retrieve all the contacts in an Android phone along with all their phone numbers. Let's say following is the list of contacts on my phone along with their phone numbers:
A - 1111 (Mobile), 2222(Home), 3333(Work)
B - 4444 (Mobile), 5555(Home)
C - 6666 (Mobile), 7777(Home), 8888(Work)
I want to display the contacts in the following fashion but using CursorLoader.
Things I have tried :
Get all the contacts and their phone numbers at a time and save them in an array list of custom contact objects and use them to display the list in a RecyclerView.
Issue with this is that if there are a lot of phone numbers then re-visiting this screen causes a blank screen possibly either due to resource not being free or memory leak issues.
Stack Overflow won't indent the code properly so here it is: https://pastebin.com/y9i5R5iN
final Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactListCursor.getLong(ContactsQuery.ID)));
Uri thisContactUri = ContactsContract.Contacts.lookupContact(context.getContentResolver(), uri);
final UserContact contact = new UserContact();
contact.setName(contactListCursor.getString(contactListCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
final ArrayList<PhoneType> multipleContacts = new ArrayList<>();
final Uri phoneNumUri = Uri.withAppendedPath(thisContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
final Cursor contactPhoneNumCursor = contentResolver.query(phoneNumUri, ContactPhoneQuery.PROJECTION, ContactPhoneQuery.SELECTION, null, null);
Get all the contacts using a CursorLoader and a CursorAdapter by querying the ContactsContract.Contacts.CONTENT_URI and getting the ID and DISPLAY_NAME_PRIMARY. In the getView() method I thought I could initialize a second CursorLoader to call into the details of the contact that the first cursor has given me. Something like this :
IF the user has multiple contacts then show a list of radio buttons, else show a textview with the only number they have.
This seems to load the phone numbers in advance and not update the view later on. Either because there's a delay or something I am not sure.
Found a way to do it.
Used the CursorLoader to pass to the CustomAdapter for initial query of contacts and then used the _ID field to lookup the contact and created a URI for the contact and looked up the Phone specific details inside the CustomAdapter's getView method itself.
I was trying to use CursorLoaders in both or Bulk loads in both. The hybrid approach worked out best.
Hope this helps someone. :)
You can use a single query to get all phone numbers in the Database along with their contact-ids and contact-names.
I would run this single query once, store all data in a map (contact-id => name, phone, ...)
And then use a custom adapter to display the map as a list of contacts.
Here's the code for querying all phones along with contact-ids and names (make sure you import everything from ContactsContract):
Map<Long, List<String>> contacts = new HashMap<Long, List<String>>();
String[] projection = { Data.CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3 };
String selection = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "')";
Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);
while (cur != null && cur.moveToNext()) {
long id = cur.getLong(0);
String name = cur.getString(1);
String mime = cur.getString(2); // type of data (e.g. "phone")
String data = cur.getString(3); // the actual info, e.g. +1-212-555-1234
int type = cur.getInt(4); // a numeric value representing type: e.g. home / office / personal
String label = cur.getString(5); // a custom label in case type is "TYPE_CUSTOM"
String labelStr = Phone.getTypeLabel(getResources(), type, label);
Log.d(TAG, "got " + id + ", " + name + ", " + kind + " - " + data + " (" + labelStr + ")");
// add info to existing list if this contact-id was already found, or create a new list in case it's new
List<String> infos;
if (contacts.containsKey(id)) {
infos = contacts.get(id);
} else {
infos = new ArrayList<String>();
infos.add("name = " + name);
contacts.put(id, infos);
}
infos.add(kind + " = " + data + " (" + labelStr + ")");
}
Note: The map's value is a list of strings, just for code-clarity. You should change it to be a custom Contact object that holds the name and list of phones in a proper Java Object
i am create an application which use contact to display. My problem is that i can show all conacts (from my email accounts,skype and other), but i want show only contacts from my device (with images like i am getting now), like when open native contacts app and go to Contacts->Menu->Settings->Contacts->Contact to display->Device contacts. I am not very well understand Contact content provider and need a help. There a lot of posts on stackoverflow, bu t i cant find post for my requirements.
For retreive all contact i am using this CursorLoader
CursorLoader cL = new CursorLoader(getActivity(),
contentUri,
ContactsQuery.PROJECTION,
ContactsQuery.SELECTION,
null,
ContactsQuery.SORT_ORDER
);
This is my criteria and projections:
final static int QUERY_ID = 1;
// A content URI for the Contacts table
final static Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
// The search/filter query Uri
final static Uri FILTER_URI = ContactsContract.Contacts.CONTENT_FILTER_URI;
// The selection clause for the CursorLoader query. The search criteria defined here
// restrict results to contacts that have a display name and are linked to visible groups.
// Notice that the search on the string provided by the user is implemented by appending
// the search string to CONTENT_FILTER_URI.
#SuppressLint("InlinedApi")
final static String SELECTION =
(Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME) +
"<>''" + " AND " + ContactsContract.Contacts.IN_VISIBLE_GROUP + "= 1 AND "+ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
// The desired sort order for the returned Cursor. In Android 3.0 and later, the primary
// sort key allows for localization. In earlier versions. use the display name as the sort
// key.
#SuppressLint("InlinedApi")
final static String SORT_ORDER =
Utils.hasHoneycomb() ? ContactsContract.Contacts.SORT_KEY_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME;
// The projection for the CursorLoader query. This is a list of columns that the Contacts
// Provider should return in the Cursor.
#SuppressLint("InlinedApi")
final static String[] PROJECTION = {
// The contact's row id
ContactsContract.Contacts._ID,
// A pointer to the contact that is guaranteed to be more permanent than _ID. Given
// a contact's current _ID value and LOOKUP_KEY, the Contacts Provider can generate
// a "permanent" contact URI.
ContactsContract.Contacts.LOOKUP_KEY,
// In platform version 3.0 and later, the Contacts table contains
// DISPLAY_NAME_PRIMARY, which either contains the contact's displayable name or
// some other useful identifier such as an email address. This column isn't
// available in earlier versions of Android, so you must use Contacts.DISPLAY_NAME
// instead.
Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME,
// In Android 3.0 and later, the thumbnail image is pointed to by
// PHOTO_THUMBNAIL_URI. In earlier versions, there is no direct pointer; instead,
// you generate the pointer from the contact's ID value and constants defined in
// android.provider.ContactsContract.Contacts.
Utils.hasHoneycomb() ? ContactsContract.Contacts.PHOTO_THUMBNAIL_URI : ContactsContract.Contacts._ID,
// The sort order column for the returned Cursor, used by the AlphabetIndexer
SORT_ORDER,
ContactsContract.Contacts.HAS_PHONE_NUMBER
};
After some time , i am return to search answer to thisquestion.
the answer maybe is not correct byt it helps me.
public static boolean getConnections(Context context, String contactId) {
// Read all data for contactId
String selection = ContactsContract.RawContacts.CONTACT_ID + " = ?";
String[] selectionArgs = new String[]{contactId};
Cursor c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, selection, selectionArgs, null);
String accountType = null;
while (c.moveToNext()) {
accountType = c.getString(c.getColumnIndexOrThrow(ContactsContract.RawContacts.ACCOUNT_TYPE));
}
Log.e("getConnections", accountType + "");
c.close();
if (accountType.equals("SIM Account") || accountType.equals("vnd.sec.contact.phone"))
return true;
else
return false;
}
After my query posted in question i am filter contacts by contactId and check their ACCOUNT_TYPE , in my logs i see on samsung vnd.sec.contact.phone(means that is phone contact) and on my lg with 2 sim i found this SIM Account.
Perhaps there is better solution, but i figure it out this way.
I'm new to android and i'm working with native contact.
So my app is let user put contact display name and their number for edit/delete.
In case the contact have more that one number.
I tried a lot but still have no luck, the app still doesn't update the number or it crashes.
What I'm going to do as my understanding is:
Find name in contact that matched name user inserted and use that to get contact_id that represent this contact datagroup.
Use contact_id in 1. and the number user input to find ._ID that represent the specific row id.
Do task with ._ID we get from 2.
This is 1. code to get contact_id:
public String getPeopleUniqueID(String name, Context context) {
String s = null;
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" like'%" + name +"%'";
String[] projection = new String[] {ContactsContract.Data.CONTACT_ID};
Cursor c = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, selection, null, null);
if(c.moveToFirst()) {
s = c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
}
c.close();
return s;
}
This is 2. code to get ._ID (num is number user inserted and name is from 1. > the contact_id)
public String checkPhoneNumber(String num, String name, Context context) {
String s = null;
String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + "=?" + " AND "+ContactsContract.Data.CONTACT_ID+ "=?";
String[] projection = new String[] {ContactsContract.Data._ID};
Cursor c = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, selection, new String[]{u,name}, null);
if(c.moveToFirst()) {
s=c.getString(c.getColumnIndex(ContactsContract.Data._ID));
}
c.close();
if (s==null){
s = "null";
}
return s;
}
To do something like editing (num is _.ID we get from 2. and newnum is new number user want to change into).
public void editNumber(String num , String newnum) {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(Data._ID + "=? AND " +
Data.MIMETYPE + "='" +
CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'",
new String[]{num})
.withValue(Data.DATA1, newnum)
.build());
try{
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);}
catch (RemoteException e){e.printStackTrace();}catch (OperationApplicationException e) {e.printStackTrace();}
}
And well it crashes when I call editNumber().
Can you help me fix my code and my understanding?
And another question, can I edit/insert group for the contact programatically, like I want to add this contact to family friend or co-worker group (the default group that we can set at contact edit page)?
Use ContactsContract.Contacts.CONTENT_FILTER_URI for searching a contact based on name - to get Id or anything else. The like operator cannot handle all cases which the CONTENT_FILTER_URI does handle - For various languages, special characters etc.
http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html#CONTENT_FILTER_URI
Use following uri to lookup a contact from phone number - you can get person id or anything else :
Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNumber));
In the set query you can also use contactId in the condition
For groups you can use custom mimetypes if the default one does not suit you (which is still very primitive for groups across different account types)
I am using MediaStore's media content and have a SearchView to filter the content displayed in a listfragment.
I keep a reference to the cursor(mainCursor) when the query string is null (which means all rows)
When user searches, i get new cursor based on the query
As per my understanding(I am very new to Cursor,DB & Contentprovider), the cursor will contain all the rows matching the query and the column to query is MediaStore.Audio.Media.TITLE, so i can see matching titles in list.
public void doQuery(String query) {
// TODO Auto-generated method stub
Log.e(TAG,"inside doQuery: "+query);
String search = MediaStore.Audio.Media.TITLE + " LIKE '%" + query + "%'";
Cursor cursorNew = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,columns, search , null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
sendBroadcast(new Intent(MainActivity.SWAP_CURSOR));
}
Now when user presses list element, i getPosition() of the cursor and retrieve the TRACK_ID of selected item.
My question is: How to search the initial cursor, i.e., mainCursor with TRACK_ID got from cursorNew and to get the position of the matching TRACK_ID in mainCursor?
I don't want to SELECT from the mainCursor, because i want to get the position of a specific TRACK from the un-filtered cursor
Thanks in advance
If you are just interested in the position, why dont you put the audio_ids in an array
ArrayList<String> audio_ids = new ArrayList<String>();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()){
String audio_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.AUDIO_ID));
audio_ids.add(audio_id);
}
and then use
String audio_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Playlists.Members.AUDIO_ID));
position = audio_ids.lastIndexOf(audio_id);
This example queries playlists. The above example would give you the last position if you had duplicates. (something you perhaps had not thought about?)
I hope this gives you some ideas
I know how to retrieve contact data for specific contacts. However, i can't find a way to get all contacts plus some of their details in a single query. The following code gets all contacts having a postal address:
Uri uri = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI;
String[] projection = new String[] {
StructuredPostal._ID,
StructuredPostal.LOOKUP_KEY,
StructuredPostal.DISPLAY_NAME,
StructuredPostal.STREET,
StructuredPostal.CITY
};
String sortOrder = StructuredPostal.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor c = getContentResolver().query(uri, projection, null, null, sortOrder);
But what i need are all contacts, whether they have postal address or not. Is this doable using the ContatsContract API, or do i need to create custom outer join query? Any hints on how?
if You have a contact ID and you want to fetch the Postal Address then use this :
Uri postal_uri = ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI;
Cursor postal_cursor = getContentResolver().query(postal_uri,null, ContactsContract.Data.CONTACT_ID + "="+contactId.toString(), null,null);
while(postal_cursor.moveToNext())
{
String Strt = postal_cursor.getString(postal_cursor.getColumnIndex(StructuredPostal.STREET));
String Cty = postal_cursor.getString(postal_cursor.getColumnIndex(StructuredPostal.CITY));
String cntry = postal_cursor.getString(postal_cursor.getColumnIndex(StructuredPostal.COUNTRY));
}
postal_cursor.close();
All contact information in Android 2.0 is stored in a single database table. So you can get all the information you need in a single query:
Cursor c = getContentResolver().query(ContactsContract.Data.CONTENT_URI,
null, null, null, sortOrder);
The just iterate through the data and check Data.MIMETYPE column. For example, if this column has StructuredPostal.CONTENT_ITEM_TYPE value, then you can get StructuredPostal fields from this column.