I am currently using
ContentResolver cr = getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor messagesCursor = cr.query(uri, new String[] { "_id", "address", "body", "person" }, null, null, null);
if (messagesCursor.getCount() > 0) {
while (messagesCursor.moveToNext()) {
colName = getContactName(messagesCursor.getString(messagesCursor.getColumnIndex("address"))) + "\n";
}
}
to get all the text in the user's inbox. From there, messagesCursor.getColumnIndex("address") will get the SMS's number. Then it will be place in getContactName() where it will then get the contacts' name from their contact's list.
This method will take a long time as it goes though EVERY SINGLE text message, get number, then get the contact's name, check if name exist in array, if it doesn't put in array then from there create a ListView.
The app will take a long time to load on start up if the user's inbox contains lots of text.
Is there any special way to get UNIQUE numbers from inbox? Something in cr.query?
Thanks in advance.(:
EDIT :
I'm creating just a simple inbox application. It reads from the original inbox message and list the messages in it.
For this project, what I did was to read through ALL the "address" which is the phone number, put it in an ArrayList, and finally to the ListView. As it cycles through all the messages in inbox, it takes a long time to startup.
For example :
Inbox Messages
Person 1
Person 1
Person 1
Person 2
Person 2
Person 3
Person 3
Person 3
Person 3
What my current code does :
Read EVERY SINGLE message
Check if name in ArrayList
If it is, skip. If not, add in array.
Throw ArrayList into ListView.
What my intention was :
A code that only reads out :
Person 1
Person 2
Person 3
Try only using "address" in projection (that means, don't include even "_id") - I'm not sure about this but it may solve the case.
Related
So I'm reading in these contacts using Android's native implementation, using a test phone with about 1,056 contacts on it. The problem I'm having is that it's rather slow, so I'm logging the outcomes of my cursor.moveToNext(), and seeing that it's reading in contacts past the last in an overlapping, duplicating fashion. It does, however, have previous logic implemented so the app compares the hashed version of this list of entries to the previously saved one every second... which eventually brings the entries back to the correct value, order, and contents. However, using the code below, at worst it's pulling the entire contact list AGAIN, and then putting it in there with the same list (essentially reads the same address book twice and reads it in, doubling entries). This gets worse the larger your contact list is (smaller books, like this Galaxy I have with 9 contacts, don't seem to be affected; whereas my phone with about 106 is slightly, and this tester with 1,053 significantly) with the larger phones I've tested taking upwards of a minute and a half to two minutes before it's fully updated, accurate, and done.
What's confusing is that it somehow, even after all this duplication, the check manages to come back and be exactly what it was supposed to be (i.e 1,053 contact phone I see it adding the 2,106th row, then it immediately loads the proper 1,053 contact book).
Here's how my cursor is defined:
Cursor c = mContext.getContentResolver().query(addressBookURI,
CONTACTS_QUERY_PROJECTION, CONTACTS_QUERY_SELECTION, null, CONTACTS_QUERY_SORT);
Here's each of the components of said Cursor "c":
private static final Uri addressBookURI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "1").build();
private static final String[] CONTACTS_QUERY_PROJECTION = {
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Data.DATA1,
ContactsContract.Data.DATA2,
"account_name"
};
private static final String CONTACTS_QUERY_SELECTION = "in_default_directory=1 and has_phone_number=1 and mimetype='vnd.android.cursor.item/phone_v2'";
private static final String CONTACTS_QUERY_SORT = "contact_id ASC";
Processing the Cursor "c"'s reads:
List<String[]> entries = new ArrayList<>();
while (c.moveToNext()) {
String id = c.getString(0);
String name = c.getString(2);
String phone = c.getString(3);
String type = c.getString(4);
String account_name = c.getString(5);
Log.d(sTag, "contact:row:" + id + ":" + name + ":" + phone + ":" + type + ":" +
account_name);
entries.add(new String[]{id, name, phone, type});
It's in that Log.d() statement where I can see duplicates of contacts, wherein the only difference between the original contact and follow-up duplicates is the "id" variable (keeps increasing, period).
For example (if it happened with smaller amounts of contacts; all values are made up):
contact:row:1:Maurine Lastpass:4145737719:3:D8:0B:9A:CC:88:BF
contact:row:2:Blondell Sosig:4013008122:3:D8:0B:9A:CC:88:BF
contact:row:3:Amber Altingle:8885554422:2:D8:0B:9A:CC:88:BF
contact:row:4:Frank Helgenson:8885554422:2:D8:0B:9A:CC:88:BF
contact:row:5:Hiro Xin:8885554422:2:D8:0B:9A:CC:88:BF
contact:row:6:Baley Balix:6316773675:2:D8:0B:9A:CC:88:BF
contact:row:7:Henry Halgor:6316773675:2:D8:0B:9A:CC:88:BF
contact:row:8:Hammy Xevronic:6316773675:2:D8:0B:9A:CC:88:BF
contact:row:9:Maurine Lastpass:4145737719:3:D8:0B:9A:CC:88:BF
contact:row:10:Blondell Sosig:4013008122:3:D8:0B:9A:CC:88:BF
contact:row:11:Amber Altingle:8885554422:2:D8:0B:9A:CC:88:BF
contact:row:12:Frank Helgenson:8885554422:2:D8:0B:9A:CC:88:BF
contact:row:13:Hiro Xin:8885554422:2:D8:0B:9A:CC:88:BF
contact:row:14:Baley Balix:6316773675:2:D8:0B:9A:CC:88:BF
contact:row:15:Henry Halgor:6316773675:2:D8:0B:9A:CC:88:BF
contact:row:16:Hammy Xevronic:6316773675:2:D8:0B:9A:CC:88:BF
I've tried storing the very first contact and letting it read from the Cursor until it matches up with that contact, but since the "id" variable keeps increasing, it makes the contact different enough to be ignored. I removed the ID portion of the contact, changed the URI from the default to one with an explicit REMOVE_DUPLICATE_ENTRIES = 1 parameter on it, and I tried to bring in the "real" count using ContactsContract.Data._COUNT in order to check the number of entries on the cursor against it, but that just crashes with "no such column _COUNT".
Is there any reason why the cursor would be pulling duplicate contacts like this? Is there something wrong with the structure of my query that is causing this sort of duplication?
let's recap the way ContactsContract DB is organized:
Contacts table - contains one row per contact, but hardly any information
RawContacts table - can have multiple rows, each assigned to a single contact-ID (from the previous table), contains a logical group of multiple Data rows usually for a single SyncProvider such as Google.
Data table - contains the actual data of a RawContact, each row has a MIMETYPE column which states what kind of data this row is about (phone, email, name, etc.) + 15 data columns to hold the information itself.
There are also pseudo tables, such as ContactsContract.CommonDataKinds.Phone which you are querying in your code, which basically queries over the Data table but with a specific MIMETYPE value, for example Phone.CONTENT_ITEM_TYPE.
In your code you are querying over CommonDataKinds.Phone.CONTENT_URI which means you are asking for all the different phone numbers in the DB.
So if a single contact has 3 phone numbers, you will get 3 rows for that contact (each with a different phone number).
However looking at your output, it seems like every contact has a single phone number in the DB, but it looks like the contacts themselves are duplicated.
So for example Amber Altingle has contact ID 3 and also 11, which means you have two separate contacts named Amber Altingle.
This is not duplication in the query code, but possibly duplication in the contact creation code.
I am trying to create an sms conversation list. I am using this code to get a cursor:
Cursor cursor = activity.getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
The problem is that when I use the cursor, I get multiple messages from one contact. I am trying to get only the most recent message from all contacts so that I can show them in a recyclerview as a list of conversations.
Thanks in advance!
Querying the "content://sms/conversations" URI (Telephony.Sms.Conversations.CONTENT_URI) will return a summary of each conversation, with the "snippet" column (Telephony.Sms.Conversations.SNIPPET) being the last message in each.
This query will also return with a "msg_count" column (Telephony.Sms.Conversations.MESSAGE_COUNT) - which is pretty self-explanatory - and a "thread_id" column (Telephony.Sms.Conversations.THREAD_ID), which can be used to retrieve a complete conversation, by querying with that ID appended to the conversations URI. For example:
String threadId = ...
Uri convoUri = Telephony.Sms.Conversations.CONTENT_URI
.buildUpon().appendPath(threadId).build();
Do note that these queries will return only SMS messages. If you want MMS as well, Telephony.Mms and Telephony.MmsSms have similar URIs.
I am trying to create an sms conversation list. I am using this code to get a cursor:
Cursor cursor = activity.getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
The problem is that when I use the cursor, I get multiple messages from one contact. I am trying to get only the most recent message from all contacts so that I can show them in a recyclerview as a list of conversations.
Thanks in advance!
Querying the "content://sms/conversations" URI (Telephony.Sms.Conversations.CONTENT_URI) will return a summary of each conversation, with the "snippet" column (Telephony.Sms.Conversations.SNIPPET) being the last message in each.
This query will also return with a "msg_count" column (Telephony.Sms.Conversations.MESSAGE_COUNT) - which is pretty self-explanatory - and a "thread_id" column (Telephony.Sms.Conversations.THREAD_ID), which can be used to retrieve a complete conversation, by querying with that ID appended to the conversations URI. For example:
String threadId = ...
Uri convoUri = Telephony.Sms.Conversations.CONTENT_URI
.buildUpon().appendPath(threadId).build();
Do note that these queries will return only SMS messages. If you want MMS as well, Telephony.Mms and Telephony.MmsSms have similar URIs.
In my app I need to get sms from specific number to activity.I got it.Now how could I differentiate read and unread messages of that specific number.And also I need to show unread message count out off total messages from that number in my previous activity.Can anyone tell me how can I accomplish this task?I tried the following code,
Cursor cur = getContentResolver().query(uri,new String[] { "_id", "thread_id",
"address", "person", "date","body", "type" },"read=0", null, null);
But this return 0 rows in listview.I also tried to get the total number of messages by using
msgcount=list.size();
How can I get the msgcount value to my previous activity. I declared the variable as public static. But it shows 0 while the listsize is 11.
Please Help!
For unread message read=0 for more details follow this link Get number of unread sms
You can add sms_status flag as a column , it's default value 0 .
when you will finish to read sms ,update flag and value will be 1.
when you will query unread sms then check sms_status flag 0 and phone number
msgcount=list.size();
if(msgcount > 0){
for(SMS sms:list){
String smsFlag = sms.getSmsFlag();
if(smsFlag .equals("0")){
// read sms
}else{
//unread sms
}
}
}
I wrote an sms sending application using the instructions Here. Now I want to add a suggestion for the phone number when the number or name is typed according to the number saved in the phone book i.e like when we enter number to call it suggests a number(dynamically on typing).
Is it possible to do or not? If possible then How Can I do this?I have used API level 2.2.
Edit:
I have do this with the help of Question Here But When I click on the name from phone-book,it place name on text-box but I have need the number to send sms.
Question: How could I get number so that I can sent message to the selected name.
Yes, it is possible. You can change fetch the existing numbers in your phone with ContactsContract, change your phone number EditText to an AutoCompleteTextView, and use a SimpleCursorAdapter to bind the numbers from your contacts to the AutoCompleteTextView.
Addition
If you want to convert a contact name into a phone number you can try this in your "Submit" Button's onClick() method:
Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER },
ContactsContract.Contacts.DISPLAY_NAME + " = '" + autoComplete.getText() + "'",
null, null);
if(cursor.moveToFirst())
phoneNo = cursor.getString(0);
Understand that this only gets the first number from the first contact that matches the name from your AutoCompleteTextView. You'll have to discern a way to distinguish between contacts with the same name and contact with multiple numbers.