Is it possible to have a broadcast receiver or service to be notified when a phone contact is added, deleted or modified?
I am making an application that needs fast access to phone contact, for what i was thinking of one copy sqlite phone contacts as accessed through contactsContracts.
If it's not possible, Does anyone know how to improve the response speed of the following code to see if a number is in the phone's contact list?
public boolean isNumberInContacts(String Num){
try {
Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()) {
String colID = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (Integer.parseInt(hasPhone)==1) {
Cursor phone = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ colID,null, null);
for (int i=0;phone.moveToNext();i++){
if (Num.equals(mNumber.getNumber((phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)))))){
return true;
}
}
}
}
cursor.close();
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Error when validate number in contacts: "+ e.toString());
}
return false;
}
Thanks
no broadcast when a contact is added. register a content observer in the contacts database to check for changes to it.
Related
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 would like to get all messages from one contact. I have the contact ID _id, so I've already do something like this :
private void displayMessages() {
ContentResolver cr = this.getContentResolver();
try {
Cursor cursor = cr.query(Uri.parse("content://mms-sms/conversations"), new String[]{"*"}, this.contID + "= _id" , null, null); //contID is the unique ID for one contact in our android.
while (cursor.moveToNext()) {
System.out.println("Number: " + cursor.getString(cursor.getColumnIndexOrThrow("address")));
System.out.println("Body : " + cursor.getString(cursor.getColumnIndexOrThrow("body")));
}
cursor.close();
}
catch (Exception e) {
System.out.print("ERROR");
}
I've asked something like
SELECT * FROM content://mms-sms/conversations WHERE _id = contID
As you can see, in my query, I ask system for messages from one contact (user id that I know) But I can just display the last message body. So I think it exists others query to get all messages from one user ?
Any ideas ???
I doubt that _id in this case is the id of the contact you are sending sms/mms to but rather the thread's id. The column you probably want to use for your query clause is RECIPIENT_IDS. For debugging purpose try without the where clause and dump the cursor to analyze the results
Cursor cursor = cr.query(Uri.parse("content://mms-sms/conversations"), new String[]{"*"}, null , null, null);
DatabaseUtils.dumpCursor(cursor);
Sorry for answer too late, but I've found a solution.
Here is my code :
private void displayMessages() {
ContentResolver cr = this.getContentResolver();
boolean isMe;
try {
Cursor cursor = cr.query(Uri.parse("content://sms"), null, this.cont.getThread_ID() + " = thread_id" , null, "date ASC");
while (cursor.moveToNext()) {
//if it's a received message :
if ((cursor.getString(cursor.getColumnIndexOrThrow("person")) != null)) {
isMe = false;
}
else {
//it's a message sent by me.
isMe = true;
}
date = cursor.getString(cursor.getColumnIndexOrThrow("date"));
System.out.println("Number: " + cursor.getString(cursor.getColumnIndexOrThrow("address")));
System.out.println("Body : " + cursor.getString(cursor.getColumnIndexOrThrow("body") + "\n");
}
cursor.close();
}
Thanks to "conent://sms" table, I can get all sms !
So I've used thread_id to display all messages, and thanks to the person column, I can know if the message was sent by me or my contact.
I have tried variations on deleting all or some messages from the SMS, including but not limited to thread id, id, where clause, etc.
Android manifest reflects read and write permissions.
I tried with variations on the SMS content, from inbox etc.
Nothing seems to delete the record.
Here is the last iteration:
Cursor c = getApplicationContext().getContentResolver().query(Uri.parse("content://sms/"), null, null, null,null);
try {
while (c.moveToNext()) {
int Id = c.getInt(0);
String pid = c.getString(0);
// String uri = "content://sms/conversations/" + threadId;
String strUriAll = "content://sms/" + pid;//SMS_ALL
Log.d("URI is ", strUriAll);
getApplicationContext().getContentResolver().delete(Uri.parse(strUriAll), null, null);
// getApplicationContext().getContentResolver().delete(Uri.parse(strUriAll), null, null);
}
}catch(Exception e){
Log.e(this.toString(),"Error deleting sms",e);
}finally {
c.close();
}
Android 4.4 Kitkat introduced changes in SMS handling where now only the default SMS app is allowed write access to the SMS database - all other apps silently fail when attempting to write.
I am new to android development.
I want to monitor the changes occurred in the call log.My code is fetching all the call history until the last recent call log.when I run my app it again fetches all the logs including the newest one but I want only the latest changes. Please guide me how can I achieve this with contentOberser ? Please help. this is my code
private void conatctDetails()
{
StringBuffer sb = new StringBuffer();
Cursor c1 = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.Contacts.DISPLAY_NAME);
sb.append("Contact details:");
try
{
while(c1.moveToNext())
{
String id = c1.getString(c1.getColumnIndex(ContactsContract.Contacts._ID));
String name =c1.getString(c1.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String timesContacted =c1.getString(c1.getColumnIndex(ContactsContract.Contacts.TIMES_CONTACTED));
String lastTimeContacted =c1.getString(c1.getColumnIndex(ContactsContract.Contacts.LAST_TIME_CONTACTED));
String number="";
// String number =c1.getString(c1.getColumnIndex(CommonDataKinds.Phone.NUMBER));
if(id==null||name==null)
continue;
Cursor cur = getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, null, CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{id}, null);
if(cur==null)
continue;
number = "";
while(cur.moveToNext())
{
number = cur.getString(cur.getColumnIndex(CommonDataKinds.Phone.NUMBER));
sb.append("\n Contact Number:--"+number);
}
sb.append("\n Contact Name:--"+name+"\n Contact ID:--"+id+"\n Last Time Contacted:--"+lastTimeContacted+"\n Total Time Contacted:--"+timesContacted);
sb.append("\n----------------------------");
}
//c1.close();
contact.setText(sb);
}
catch(Exception e)
{
}
finally
{
c1.close();
}
}
If there is an Intent that is fired on an incoming call you could get your app to respond by using a BroadcastReceiver and create an IntentFilter in your manifest.
Or just query the provider when your app launches...
ACTION_PHONE_STATE_CHANGED is a TelephonyManager intent you can listen for and check if it is TelephonyManager.CALL_STATE_RINGING.
Hey all i have a programmer thats having some trouble with getting my phone image to display in an app. the following code is what he is using to get the contact picture:
private long getContactIdFromNumber(String number) {
Cursor c = null;
try {
String[] projection = new String[] { Contacts.Phones.PERSON_ID };
Uri contactUri = Uri.withAppendedPath(
Contacts.Phones.CONTENT_FILTER_URL, Uri.encode(number));
c = getContentResolver().query(contactUri, projection, null, null,
null);
if (c.moveToFirst()) {
long contactId = c.getLong(c
.getColumnIndex(Contacts.Phones.PERSON_ID));
return contactId;
}
} finally {
c.close();
}
return -1;
}
private boolean initPhoto() {
boolean result = true;
try {
contactPhoto = People.loadContactPhoto(getApplicationContext(),
ContentUris.withAppendedId(People.CONTENT_URI,
getContactIdFromNumber(phoneNumber)),
R.drawable.header, null);
} catch (Exception e) {
result = false;
}
return result;
}
if (initPhoto()) {
contact1.setImageBitmap(contactPhoto);
contact2.setImageBitmap(contactPhoto);
contact3.setImageBitmap(contactPhoto);
}
I made a contact with my phone number and image but it never loads up in the app. What should he be looking for in the code i posted above in order to make sure it is grabbing the correct phone number?
Do you have to use Contacts instead of ContactsContract? Contacts was deprecated in API level 5.
If you're trying to load a photo for a phone number, use ContactsContract.PhoneLookup. There's an example in the reference doc for android.provider.ContactsContract.PhoneLookup. Querying on that table will return LOOKUP_KEY for the Contact. Use that to query
ContactsContract.Contacts.Photo.
Turned out the number was formatted incorrectly. It was looking for xxxxxxxxxx and the number was this way (xxx)xxx-xxxx in the phone so it never matched up.