Get full conversation with Android query - android

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.

Related

Sql search statement always returning empty even when there is data in database in android

I am using the following to fetch a string from my table. The cursor is always returning empty even when I have data in database. Is the query wrong?
public void find(String myNumber){
String[] thecolumns = new String[]{
ID,
FLAG};
cursor = sqlDb.query(MY_TABLE,
thecolumns, NUMBER + "='"
+ myNumber+ "'", null, null, null, null);
if (cursorToFetchAssets != null ) {
cursorToFetchAssets.moveToFirst();{
try{
//code to fetch
}catch{
//return when there are no rows found.
}
}
EDIT: NUMBER is of type string "...+ NUMBER + " TEXT,.. " and myNumber is also a string
FIXED: Issue was on the server side of my code. Not over here..
try this:
cursor = sqlDb.query(
MY_TABLE,
thecolumns,
NUMBER + "=?",
new String[]{String.valueOf(number)},
null, null, null);

Unable to find Contact by Number due to Formatting difference

It's supposed to be a common problem but I don't know what is the right word to look for solution.
In my app, I user can key in a number, and I need to search if the contact exist in database. Also, given a contact ID and number, I want to find the phone label of the number..
The problem is, if I have a number in phone as "8710 2863" and my query arg is "87102863", I won't be able to get the contact and phone label... There must be a way to standardize the format.. But I can't find the way :(
Here is my code:
Cursor cursor = MyApp.getContext().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] {
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL
},
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? AND "
+ ContactsContract.CommonDataKinds.Phone.NUMBER + " = ? ",
new String[] { Long.toString(contactId), number },
ContactsContract.Data.IS_SUPER_PRIMARY + " DESC");
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
int type = cursor.getInt(0);
String label = cursor.getString(1);
String phoneLabel = (String) ContactsContract.CommonDataKinds.Phone
.getTypeLabel(MyApp.getContext().getResources(), type, label);
hashBuilder.put(Defs.ARG_PHONE_TYPE, phoneLabel);
}
} finally {
cursor.close();
}
}
Have you tried PhoneNumberUtils.formatNumber(String)?

Deleting Android SMS programmatically

I want to delete some certain SMS automatically in my Android application. Therefore I have a method which does exactly what I want it to do. However, it only works if I deploy the application directly to my phone from Eclipse. Then it deletes incoming SMS. However, it does not work if the application is downloaded from the market. But there is also no error. Does anybody know how I can solve this or does this only work on rooted devices?
public void deleteSMS(Context context, String message, String number) {
try {
mLogger.logInfo("Deleting SMS from inbox");
Uri uriSms = Uri.parse("content://sms/inbox");
Cursor c = context.getContentResolver().query(uriSms,
new String[] { "_id", "thread_id", "address",
"person", "date", "body" }, null, null, null);
if (c != null && c.moveToFirst()) {
do {
long id = c.getLong(0);
long threadId = c.getLong(1);
String address = c.getString(2);
String body = c.getString(5);
if (message.equals(body) && address.equals(number)) {
mLogger.logInfo("Deleting SMS with id: " + threadId);
context.getContentResolver().delete(
Uri.parse("content://sms/" + id), null, null);
}
} while (c.moveToNext());
}
} catch (Exception e) {
mLogger.logError("Could not delete SMS from inbox: " + e.getMessage());
}
}
Actually, the code in my post is 100% correct. The problem was that Android needs some time to store the SMS upon receiving it. So the solution is to just add a handler and delay the delete request for 1 or 2 seconds.
This actually solved the whole issue.
EDIT (thanks to Maksim Dmitriev):
Please consider that you can't delete SMS messages on devices with Android 4.4.
Also, the system now allows only the default app to write message data to the provider, although other apps can read at any time.
http://developer.android.com/about/versions/kitkat.html
No exception will be thrown if you try; nothing will be deleted. I have just tested it on two emulators.
How to send SMS messages programmatically
Please consider that you can't delete SMS messages on devices with Android 4.4.
Also, the system now allows only the default app to write message data
to the provider, although other apps can read at any time.
http://developer.android.com/about/versions/kitkat.html
No exception will be thrown if you try; nothing will be deleted. I have just tested it on two emulators.
How to send SMS messages programmatically
hey use this code to delete customize sms
1. By date
2. By number
3. By body
try {
Uri uriSms = Uri.parse("content://sms/inbox");
Cursor c = context.getContentResolver().query(
uriSms,
new String[] { "_id", "thread_id", "address", "person",
"date", "body" }, "read=0", null, null);
if (c != null && c.moveToFirst()) {
do {
long id = c.getLong(0);
long threadId = c.getLong(1);
String address = c.getString(2);
String body = c.getString(5);
String date = c.getString(3);
Log.e("log>>>",
"0--->" + c.getString(0) + "1---->" + c.getString(1)
+ "2---->" + c.getString(2) + "3--->"
+ c.getString(3) + "4----->" + c.getString(4)
+ "5---->" + c.getString(5));
Log.e("log>>>", "date" + c.getString(0));
ContentValues values = new ContentValues();
values.put("read", true);
getContentResolver().update(Uri.parse("content://sms/"),
values, "_id=" + id, null);
if (message.equals(body) && address.equals(number)) {
// mLogger.logInfo("Deleting SMS with id: " + threadId);
context.getContentResolver().delete(
Uri.parse("content://sms/" + id), "date=?",
new String[] { c.getString(4) });
Log.e("log>>>", "Delete success.........");
}
} while (c.moveToNext());
}
} catch (Exception e) {
Log.e("log>>>", e.toString());
}
You can choose which app is the default SMS app in 4.4+ and if your app is set as the default it will be able to delete SMS as well.
to make app as default app see this.
Check if your app is default sms app before deleting.
Use the URI provided by telephony class instead of hardcoding.
public void deleteSMS(Context context,int position)
{
Uri deleteUri = Uri.parse(Telephony.Sms.CONTENT_URI);
int count = 0;
Cursor c = context.getContentResolver().query(deleteUri, new String[]{BaseColumns._ID}, null,
null, null); // only query _ID and not everything
try {
while (c.moveToNext()) {
// Delete the SMS
String pid = c.getString(Telephony.Sms._ID); // Get _id;
String uri = Telephony.Sms.CONTENT_URI.buildUpon().appendPath(pid)
count = context.getContentResolver().delete(uri,
null, null);
}
} catch (Exception e) {
}finally{
if(c!=null) c.close() // don't forget to close the cursor
}
}
it delete all(inbox,outbox,draft) the SMS.
private int deleteMessage(Context context, SmsMessage msg) {
Uri deleteUri = Uri.parse("content://sms");
int count = 0;
#SuppressLint("Recycle") Cursor c = context.getContentResolver().query(deleteUri, null, null, null, null);
while (c.moveToNext()) {
try {
// Delete the SMS
String pid = c.getString(0); // Get id;
String uri = "content://sms/" + pid;
count = context.getContentResolver().delete(Uri.parse(uri),
null, null);
} catch (Exception e) {
}
}
return count;
}
use this code.............
or
getContentResolver().delete(Uri.parse("content://sms/conversations/" + threadIdIn), null, null);
I was looking for a method to delete all SMS with one click. Thanks to this post I succeeded.
Here is my method if it interests someone :
private void deleteSMS(){
Uri myUri= Uri.parse("content://sms/");
Cursor cursor = getContext().getContentResolver().query(myUri, null,null,null,null);
while (cursor.moveToNext()) {
int thread_id = cursor.getInt(1);
getContext().getContentResolver().delete(Uri.parse("content://sms/conversations/" + thread_id),null,null);
}
cursor.close();
}
if you want get a message and your sms app your android device phone didn't send any notification use Binary (Data) SMS.

Retrieving a contacts notes

I'm still very new to android app development, and I have hit a problem I hope u can help me with...
I am trying to retrieve any "Notes" stored against a contact within my phone. I want to check if a contact (current caller) has any notes associated to them, and then either display the contents or do some action depending on the content of them etc...
I have tried the code below as a test to see if the data is retrieved anywhere within my cursor, but although it retrieves some data, I can't see the content of a note - so I guess I'm in the wrong place!
Where I have declared contentID, this is a result of doing a lookup with the code below, and using the id that is recieved.
Uri lookupUri = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, Uri.encode(inCommingNumber));
String[] mPhoneNumberProjection = { Phone._ID, Phone.NUMBER, Phone.DISPLAY_NAME};
Cursor cur = getContentResolver().query(lookupUri , mPhoneNumberProjection, null, null, null);
private boolean hasNote(String contactID){
Boolean noteFound = false;
Cursor noteCur = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, null, null, null);
if(noteCur.moveToFirst()) {
int numCols = noteCur.getColumnCount();
if(numCols > 0){
for(int x = 0; x < numCols; x++){
Log.d(APP_TAG, " column " + x + " contains: " + noteCur.getString(x));
}
}
noteFound = true;
} else{
Log.d(APP_TAG, "No Note retrieved");
}
noteCur.close();
return noteFound;
}
Apologies, I cant seem to get the code to display properly in this post!!
Any help would be great
I have tried various things, but can't seem to be able to get this data. I have created the note by simply adding it through the normal contact manager. I'm using Android 2.2.
The following code would display the first note for all contacts on your phone:
Cursor contactsCursor = null;
try {
contactsCursor = getContentResolver().query(RawContacts.CONTENT_URI,
new String [] { RawContacts._ID },
null, null, null);
if (contactsCursor != null && contactsCursor.moveToFirst()) {
do {
String rawContactId = contactsCursor.getString(0);
Cursor noteCursor = null;
try {
noteCursor = getContentResolver().query(Data.CONTENT_URI,
new String[] {Data._ID, Note.NOTE},
Data.RAW_CONTACT_ID + "=?" + " AND "
+ Data.MIMETYPE + "='" + Note.CONTENT_ITEM_TYPE + "'",
new String[] {rawContactId}, null);
if (noteCursor != null && noteCursor.moveToFirst()) {
String note = noteCursor.getString(noteCursor.getColumnIndex(Note.NOTE));
Log.d(APP_TAG, "Note: " + note);
}
} finally {
if (noteCursor != null) {
noteCursor.close();
}
}
} while (contactsCursor.moveToNext());
}
} finally {
if (contactsCursor != null) {
contactsCursor.close();
}
}
If you are storing some sort of structured data on the note to take actions on using the free form note field may not be the best approach. With the new contacts contract model you are able to attach your own data fields (in ContactsContract.Data) to a contact just give them your own unique mimetype.

retrieve contact's nickname

I want to get the nickname of a contact from addressbook. I start with his phone number, query it and want the nickname (aka alias) as a result.
Cursor cur = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.NUMBER + " = " + incomingNumber, null, null);
if (cur.moveToFirst()) {
Log.e("saymyname", cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME)));
Log.e("saymyname", cur.getString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.LABEL)));
}
Output of the logs is the incomingNumber (first Log.e() ) and null (second Log.e() ), but I want to get the contact's nickname!
Thanks
Tom
Nickname is held in a different table than the phone numbers, you have to query ContactsContract.Data.CONTENT_URI
Check my answer on this question
(I don't have necessary reputation to comment so I have to add answer)
TomTasche's answer is misleading and it got me to waste a lot of time trying to figure out why I couldn't get the proper nickname on a contact I knew had one.
I found the answer by myself but got the confirmation from this post that I was now doing it properly.
Basically when you read the ContactsContract.Data documentation you read:
Each row of the data table is typically used to store a single piece of contact information (such as a phone number) and its associated metadata (such as whether it is a work or home number).
That explains the shady part of TomTasche's code :
if (nickname.equals(incomingNumber)) {
return name;
}
Since doing a search with just the CONTACT_ID can return multiple rows (one for each information type), it's not guaranteed that the first one contains the nickname. When there is a nickname it will be in DATA1, but the phone number is also found in DATA1.
The example part in the documentation of ContactsContract.Data makes it clear that rows must be selected based on their MIME_TYPE, only when the MIME_TYPE is selected, can we start making sense of the content in the row itself.
A proper query would therefore be:
cursor = getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
new String[]{Nickname.NAME},
ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + "= ?",
new String[]{contactID, Nickname.CONTENT_ITEM_TYPE},
null);
(where Nickname is ContactsContract.CommonDataKinds.Nickname)
I felt I had to say something on this topic to prevent other people wasting as much time as I did based on this sole topic (first one I found with my Google friend).
The answer from Pentium10 was very helpful! Thanks!
If anybody needs a sample, look at the following code:
public String accessContact(String incomingNumber) {
if (incomingNumber == null || "".equals(incomingNumber)) {
return "unknown";
}
try {
Cursor cur = context.getContentResolver().query(Phone.CONTENT_URI, new String[] {Phone.DISPLAY_NAME, Phone.TYPE, Phone.CONTACT_ID}, Phone.NUMBER + " = " + incomingNumber, null, null);
int nameIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int typeIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
int idIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
String name;
String type;
String id;
if (cur.moveToFirst()) {
name = cur.getString(nameIndex);
type = cur.getString(typeIndex);
id = cur.getString(idIndex);
} else {
return "unknown";
}
cur = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[] {ContactsContract.Data.DATA1}, ContactsContract.Data.CONTACT_ID + " = " + id, null, null);
int nicknameIndex = cur.getColumnIndex(ContactsContract.Data.DATA1);
String nickname;
if (cur.moveToFirst()) {
nickname = cur.getString(nicknameIndex);
if (nickname.equals(incomingNumber)) {
return name;
}
return nickname;
} else {
return name;
}
} catch (Exception e) {
e.printStackTrace();
return "unknown";
}

Categories

Resources