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
Related
I'm new to Android application development, would like to compare different variables over time.
My Service counts the number of SMS inside the smart-phone.
private static final Uri SMS_URI_ALL = Uri.parse("content://sms/");
final List<String> messages = new ArrayList<>();
String id;
final Cursor cursor = getContentResolver().query(SmsReader.SMS_URI_ALL,null, null,null, null);
assert cursor != null;
if (cursor.moveToFirst()){
do {
id = cursor.getString(cursor.getColumnIndexOrThrow("_id"));
messages.add(id);
currentMessage = messages.size();
} while (cursor.moveToNext());
}
if (! cursor.isClosed()){
cursor.close();
}
Every 15 mins service will be starts, and I would like to compare the value of "currentMessage" and calculate the difference between the old value of "currentMessage" and the new value of "currentMessage" for know how many message I have sent, received during this period of 15min
I don't know how to implement it, can you help me please
Store the count in database, also you cannot exactly monitor the count this way. Add broadcast receiver for when a sms is sent or received.
I found an other solution, I save the value inside a file, and I compare the current value whith the older value
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
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));