Trying to replicate android homescreen Contact shortcuts, with issues - android

Okay, I'm trying to replicate the shortcuts which get placed on the homescreen when creating a contact shortcut, example shown:
I've got a working QuickContactBadge, which when clicked shows the QuickContact toolbar. However, I have two things I'm having trouble with.
One is the picture. I tried using the code from this question (I altered it by adding a parameter to pass in the contact ID). I then assign the image to my QuickContactBadge as so:
bdg.setImageURI(getPhotoUri(cid));
It definitely gets pictures, but it is getting TOTALLY the wrong picture. As illustrated here:
As you can see, the image it returned for Domino's is clearly NOT the Domino's logo.
I'm getting my contact ID to pass to the function from this code:
public static String[] ContactsProjection = new String[] {
Contacts._ID,
Contacts.LOOKUP_KEY,
Contacts.DISPLAY_NAME
};
public static Cursor getContacts() {
ContentResolver cr = CoreLib.ContentResolver();
Cursor contacts = cr.query(
ContactsContract.Data.CONTENT_URI,
ContactsProjection,
null, null,
Contacts.TIMES_CONTACTED + " DESC"
);
return contacts;
}
Which I believe should be returning me the proper ID for each record. Yes?
Next how do I get exactly the thumbnail shrunk or cropped as the shortcut shows it?
I was a little disappointed to see that the QuickContactBadge doesn't actually replicate the whole look and feel of the QuickContact shortcut, ... but just acts as in invocation target for the QuickContact card. Is there any built in way to easily replicate the contact shortcut in it's entirety, invocation, image, text and all, without needing to reproduce the whole thing from scratch?

Ah HAH! Figured out how to get the correct photo. While this seems counter-intuitive, when building your field projection to query the contacts, the fields Contacts._ID and ContactsContract.Data.CONTACT_ID are not the same thing.
ContactsContract.Data.CONTACT_ID is the correct one to pass in to get the photo. Use this, and everything is now golden.

Related

Detect if an android contact has been deleted

I am trying to maintain a contact database and get a callback for Add/Update/Delete as soon as something changes in the URI.
I have written a ContentObserver to observe on ContactsContract.Contacts.CONTENT_URI on contacts. I get a callback as soon as a contact changes and then I update my database by checking ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP.
While this works fine for add/update, it does does not work for deleting a contact.
I do not want to parse all the contacts that I have in memory and check against android database. That would take time and CPU.
I know there exists many question of these types but I am not able to figure out things specific to deleting the contact.
Does there exist a way to perform this ?
As I have posted in above comment as well, following code works for API level 18 and above.
You can query on a uri ContactsContract.DeletedContacts.CONTENT_URI to get the list of all the contacts that have been deleted.
My query looks like following :
String selection = ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP + " > ?";
String[] selectionArgs = new String[]{String.valueOf(mLastContactDeleteTime)};
Cursor cursor = mContext.getContentResolver().query(ContactsContract.DeletedContacts.CONTENT_URI, null, selection, selectionArgs, null);

Android - get contact where phone number LIKE something being typed

I've been trying to get a contact by it's number, the same way Android has implemented when your dialing a number on the stock dialer. If you're familiar, you know that when you are dialing it starts to show matches that contain those numbers (913284912 would match when dialing 3412 for example). (not sure if this way of search was only implemented on 5.x+)
I got this to work but only when the number is exactly equal to the contact one with the code below:
private Cursor getContacts(String number) {
// Run query
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number.trim()));
String[] projection = new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME,
ContactsContract.PhoneLookup.PHOTO_THUMBNAIL_URI, ContactsContract.PhoneLookup._ID};
return getContext().getContentResolver().query(
uri,
projection,
null,
null,
null
);
}
I'm having a bit difficulty on finding solutions for this, as everyone uses this to get a contact. But as I don't want an exact match, this won't do for me.
Thanks in advance.
You can use an Adapter with a Filter. Some examples can be found: Filtering ListView with custom (object) adapter or even better Custom Listview Adapter with filter Android

Should my function to get an Android Contact by name return a Cursor or something else?

I'm working on a class that is supposed to handle the user's Android contacts and interact with an SQL database where you can move your phone's contacts to (the information in the database will be displayed as a ListView). I've made a function that is supposed to retrieve an Android contact by name and return all of that contact's information. My function is as follows:
public Cursor getContactByName(String name)
{
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = null;
String selection = Data.DISPLAY_NAME + "=?";
String[] selectionArgs = new String[]{name};
String sortOrder = null;
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
}
So the idea is that this would be called by another function, which would first check if the contact existed. This function would return a cursor containing only that contact's information. First I want to know if I'm right in returning a Cursor containing the contact's information or should I instead create a class that stores this information and return an object of the class? Or perhaps I should return a string? Keeping in mind that what I'm returning is the contact that I intend to move to my database, I feel like returning a Cursor isn't what I should be aiming for. And as a side-question, is there any reason to use ContentResolver.query instead of managedQuery for my purposes?
It depends on what you are going to be using the data for. If you're going to be adding it to another database (as your question suggests) you are probably best off leaving it as a cursor and simply entering that cursor in your second database. If you like mapping your database rows to objects, then do that. Keep in mind Object Relational Mapping takes more memory and cycles but usually results in clearer code. It's really up to you as the programmer (sorry I know that's not what you want to hear).
Personally i would prefer to create an object Contact. So you are more flexible and you can also implement functions related to your objects in this class (or the related DAO).
Passing the values as Cursor or even as String gives more trouble than it will help you. In an object you can see exactly the propertynames for everything, with a cursor you have to know the names or the positions of the corresponding fields, and in a string you even have to parse your results.
EDIT:
As #DavidCowden metioned, it depends strongly on what you are trying to achieve. So my guess was, that you want to load your data and display it somewhere.
And as already mentioned, in this case i would prefer a seperate class as it's much cleaner and maintainable.

How to force refresh on CallLog.Calls.CACHED_NAME column?

My goal is to collect all unknown phone numbers from the Call Log.
This can be achieved by the following code:
private static final String[] CALLOG_PROJECTION = {CallLog.Calls._ID,
CallLog.Calls.CACHED_NAME, CallLog.Calls.NUMBER};
private static final String CALLOG_WHERE = CallLog.Calls.CACHED_NAME + " is null";
Cursor c = getContentResolver().query(CallLog.Calls.CONTENT_URI, CALLOG_PROJECTION,
CALLOG_WHERE, null, CallLog.Calls.DATE + " DESC");
This works well, but after i've created a contact from an unknown number, the result of the query still contains the unknown number.
If i open the Call Log activity window, i can see as the number changes to the name of the contact within a few seconds. So, the activity refreshes the CACHED_NAME column.
My question is, how can i programatically refresh (actualize) the Call Log ?
I landed on this question looking for ways to optimize what you're trying to do. Instead of using cached_name, I queried the Phone content provider for every number to get the actual name, but this led to performance issues.
I noticed that the stock application refreshes the list when a change occurred, as you did.
I'm going to implement a ContentObserver on the Phones table and update my name when that happens, I'll post if it works.
EDIT
I was checking the (Google's) Contacts app source code and they basically show the list with the CACHED_NAME first and, after the list is displayed, they check (on the background) if there were any changes to the contacts details. If there were any, they update the CallLog record and the list.
Basically, I've implemented something similar and it works. There were some performance issues when you scrolled the list while it was checking on the background for changes, because in a CallLog there are a lot of repeated numbers. So basically you just have to verify if those numbers are already being checked out.
Hope it helps!

Android: How to link sms draft with information about the receiver (like the name)?

if I write a new text message in the Android standard sms app and fill in a receiver and some body text and press the back button Android will save this as a draft. If the receiver is currently in my address book Android tells me also in the draft overview the name or, if the receiver is not in the address book, the number.
So far, so good.
Now I tried to do exactly the same thing on my own and I'm not quite sure why my solution doesn't work.
I've tried the following:
// in a Activity
final ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(Uri.parse("content://sms/draft"),
String[] {"_id", "date", "body", "person"},
null, null, null);
Later in my own cursor-Adapter I tried to get the person-id which links to the contacts table (I thought so). I do it this way:
// in my own CursorAdapter (bindView-Method)
Long receiverId = cursor.getLong("person");
But what I get is always "0". So what do I do wrong? Thanks in advance.
Btw: Is there any official documentation about the "content://sms"-thing? I only found some forum postings but nothing at developers.android.com!?

Categories

Resources