I'm trying to write my first android app, and I need to display all the unique SMS senders in one screen. Like an inbox.
But I'm unable to use group by or distinct in the content resolver query, and all sql-injection-like workarounds on stackoverflow don't seem to be working.
Is there an obvious method I'm missing out? Because this seems to be a pretty basic thing. I'm querying the SMS db so can't use rawquery either (a method other similar posters seem to have used).
Some help would be greatly appreciated, thanks.
just find out URLS for SMS. then using content resolver get the data from that URL.
Take a look on how I did it:
// getting sender list from messages into spinner View
Spinner phoneListView = (Spinner) findViewById(R.id.phone_list);
Uri uri = Uri.parse("content://sms/inbox");
Cursor c = getContentResolver().query(uri, new String[]{"Distinct address"}, null, null, null);
List <String> list;
list= new ArrayList<String>();
list.clear();
int msgCount=c.getCount();
if(c.moveToFirst()) {
for(int ii=0; ii < msgCount; ii++) {
list.add(c.getString(c.getColumnIndexOrThrow("address")).toString());
c.moveToNext();
}
}
phoneListView.setAdapter(new ArrayAdapter<String>(BankActivity.this, android.R.layout.simple_dropdown_item_1line, list));
Related
I'm using the below code to retrieve a message from sms.
private List<String> getEveryLastMessages(){
List<String> listSms = new ArrayList<String>();
ContentResolver contentResolver = getActivity().getContentResolver();
Cursor c = contentResolver.query(Telephony.Sms.Inbox.CONTENT_URI, // Official CONTENT_URI from docs
new String[] { Telephony.Sms.Inbox.BODY }, // Select body text
null,
null,
Telephony.Sms.Inbox.DEFAULT_SORT_ORDER); // Default sort order
int totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < totalSMS; i++) {
listSms.add(c.getString(0));
listSms.add("\n");
c.moveToNext();
}
} else {
//Do something, no messages
}
c.close();
return listSms;
}
my problem is all of the message was retrieved and except the locked message.
what I'm trying to achieve is retrieve only the last message of
every conversation including the lock messages and populate it into my recyclerview adapater to show it as inbox.
If you want the last message in each conversation, regardless of whether it's sent or received, there's a handy built-in URI that you can use, in lieu of just grabbing everything and filtering it yourself.
Telephony.Sms.Conversations.CONTENT_URI (in the android.provider package) can be used in a ContentResolver query to retrieve a summary of the available conversations. For example:
Cursor c = contentResolver.query(Telephony.Sms.Conversations.CONTENT_URI,
null, null, null, null);
This query will return with three columns:
Telephony.Sms.Conversations.SNIPPET ("snippet")
Telephony.Sms.Conversations.MSG_COUNT ("msg_count")
Telephony.Sms.Conversations.THREAD_ID ("thread_id")
The SNIPPET column will be the most recent available message in that conversation.
Unfortunately, starting with Marshmallow (API level 21), any app that is not the default messaging app has access to only a restricted view of the SMS table. Such an app can only get messages with a Telephony.Sms.TYPE of MESSAGE_TYPE_INBOX or MESSAGE_TYPE_SENT. This means that you won't get MESSAGE_TYPE_FAILED, MESSAGE_TYPE_DRAFT, etc., unless your app is the current default app.
However, the Telephony.Sms.LOCKED column is a completely separate categorization from the TYPE column, and so should not figure into the restricted view. That is, you should be able to get locked messages, as long as they're sent or inbox, no matter if your app is the default or not. Of course, it's possible that a manufacturer has altered any of this described behavior, and you might need to account for that in your app.
Writing this on the fly, so I apologize for the code sample. This is NOT real code, it's something I wrote in a plain text editor on the fly. No compile checking, couldn't remember all the exact class and method names, etc. It's just a written concept of what I'm trying to do, I'm looking for feedback on the broader concepts.
I'm working on retrieving a list of contacts from the content provider. I want to be able to filter the results based on the contact's account name. the user will be presented with all available accounts, and will select which ones are to be used, and then that will be used in the retrieval method.
The thing is, the account name is in RawContacts, and the rest of the info I want (display name, lookupID) is in Contacts. I know that ContactsContract.Contacts.Entity is the shortcut to access all of this, so this code sample is what I'm planning to do.
Again, this is written on the fly with no IDE or looking up methods or anything. I'm sure my syntax is bad in many places, but this shows the concept I'm trying to do.
private static final URI URI = ContactsContract.Contacts.URI;
private static final String[] FIRST_PROJECTION = new String[]{
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.LOOKUP_KEY
};
private String[] acceptedAccountNames = {Accepted Account Names Will Go Here (dynamic)};
private static final String[] SECOND_PROJECTION = new String[]{
ContactsContract.Contacts.Entity.ACCOUNT_NAME //This is whatever the entity -> RawContacts field name would be
};
public List<Contact> loadContacts(Context context){
List<Contact> contacts = new ArrayList<>();
ContentProvider provider = context.getContentProvider();
Cursor contactsCursor = provider.query(URI, FIRST_PROJECTION, null, null);
contactsCursor.movetoFirst();
while(!contactsCursor.isAtLast()){
String name = contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
long lookupKey = contactsCursor.getLong(contactsCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri idUri = Uri.makeWithId(URI, lookupKey);
Uri entityUri = Uri.makeWithTableName(idUri, "entity");
Cursor contactEntityCursor = provider.query(entityUri, SECOND_PROJECTION, null, null);
contactEntityCursor.moveToFirst();
String accountName = contactEntityCursor.getString(contactEntityCursor.getColumnIndex(ContactsContract.Contacts.Entity.ACCOUNT_NAME));
if(Arrays.asList(acceptedAccountNames).contains(accountName)){
Contact contact = new Contact(lookupKey, name);
contacts.add(contact);
}
contactsCursor.moveToNext();
}
return contacts;
}
As you can see, I create a cursor while looping over another cursor. I'm essentially creating a new cursor for each contact in the list.
My question is twofold:
1) What would be the performance implications of this? With a large enough list, would this severely hurt app performance?
2) Is there a better way to do this? As in, a way to do this in a single query, getting all the data I'm looking for in the cursor.
Thanks so much in advance.
Thanks in advance for your help.
I would like to make an activity that would look similar to the starting activity of native android messaging app: contact image, contact name, first few words of the message body.
So far with the help of this website I could figure out how to retrieve Senders phone numbers in a list view. Here is a part of the code I am using:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
List<SMSData> smsList = new ArrayList<SMSData>();
Uri uri = Uri.parse("content://sms/inbox");
Cursor c = getContentResolver().query(uri, null, null, null, null);
if (c.moveToFirst()) {
for (int i = 0; i < c.getCount(); i++) {
SMSData sms = new SMSData();
sms.setBody(c.getString(c.getColumnIndexOrThrow("body"))
.toString());
sms.setNumber(c.getString(c.getColumnIndexOrThrow("address"))
.toString());
smsList.add(sms);
c.moveToNext();
}
}
c.close();
setListAdapter(new ListAdapter(this, smsList));
My question is, how to retrieve and display Contact Name with corresponding SMS body???
The closest solution I found so far is this, but I cannot figure out how to put together my code and this solution.
Have you added proper permissions needed for doing this operation in your manifest? i.e
needed for that to be in your manifest for that operation, read these tutorial and download source code available and try that
http://www.technotalkative.com/android-fetch-inbox-sms/
Hope that it will work....
After looking more closer this example actually helped me.
Thanks to everyone
iam not able to get the address of the draft SMS, it always giving me null iam using the following code
public static final Uri SMS_PROVIDER = Uri.parse("content://sms");
Cursor oCursorSMS = mContext.getContentResolver().query(SMS_PROVIDER, null,null,null, null);
oCursorSMS.moveToFirst();
final String[] columns = oCursorSMS.getColumnNames();
for (int i = 0; i < columns.length; i++) {
String ss = cursor.getString(i);
}
when iam reading a Draft SMS the Address Column returns null i have searched alot, there are alot of questions about this issue but no one have answer. can anyone help me with this
From the uri content://mms-sms/conversations?simple=true you can access the threads table, in the threads table there is a column recipient_ids which you can use to get the address, see my answer here to know how to do that. Basically, you want to get the thread_id from your sms and then use it to do a look on the threads table, i.e the filter should be _id = thread_id_from_sms. Now get the recipient_ids and use it to look up the address from content://mms-sms/canonical-addresses
I want to get the contact numbers in Android but as far as I found a tutorial, it puts out the number in ascending order, not in the order they appear in the contacts...
How can I modify the code to obtain the numbers in the exact order from my contact list??
Cursor cursor = getContentResolver().query(Phone.CONTENT_URI, new String[]{Phone.NUMBER}, null,null, null);
ArrayList <String> nr_formatat = new ArrayList <String> ();
if (cursor != null) {
while (cursor.moveToNext() == true)
nr_formatat.add(cursor.getString( cursor.getColumnIndex(Phone.NUMBER)));
}
You're going about it the wrong way. You need to query the number against the CONTACT_ID or else you won't have any correspondence between the two. Take a look at this tutorial.
It depends on how your contacts are ordered in your contact list. Hit the menu button and tap on 'Display Options'. Other than that, you don't have enough information in your question to adequately answer it.
From what I can see, you're going about it the wrong way. I would look over this example application. It fetches the contacts differently than you and will allow you to sort it however you want.
http://developer.android.com/resources/samples/BusinessCard/src/com/example/android/businesscard/index.html
Following should work if:
(Anna, 0342) has ID 1, (Lulu, 0311) has ID 2, (John, 0088) has ID 3
Cursor cursor = getContentResolver().query(Phone.CONTENT_URI, new String[]{Phone.NUMBER}, null,null, new String[]{Phone.ID});
ArrayList <String> nr_formatat = new ArrayList <String> ();
if (cursor != null) {
while (cursor.moveToNext() == true)
nr_formatat.add(cursor.getString( cursor.getColumnIndex(Phone.NUMBER)));
}
The last variable of ContentResolver().query() takes the sortorder. So here you put something like the ID, if your contactlist also sorts on ID.
ConecntResolver().Query() info here.