Retrieve SMS sent after a specific time - android

I have a background service that listens to changes to Android SMS content provider. I store the last recorded id of the message that my Service recorded and using it, I want to find the number of messages that were sent when the service was Stopped/Killed.
So when the service is started again and another message is sent, I want to use the timestamp of the last recorded message. I use the below code to do this. My problem is that the cursor always returns 1 record irrespective of how many messages are sent when the service was killed before its restarted.
String COLUMN_NAME_DATE = "date"
String[] projection = new String[]{COLUMN_NAME_ID, COLUMN_NAME_DATE};
Cursor newMessagesCursor = mContext.getContentResolver().query(
Uri.parse(SMSManager.SMS_URI_SENT),
projection,
COLUMN_NAME_DATE + "> ? ",
new String[]{String.valueOf(lastMessageTimeStamp)}, null);
int newMessagesCount = (null != newMessagesCursor) ? newMessagesCursor.getCount() : 0;
Any pointers would be helpful. Let me know if there is any alternative approach as well.
Edit: Adding code to retrieve the lastMessageTimeStamp.
Cursor messageCursor = mContext.getContentResolver().query(
Uri.parse(SMSManager.SMS_URI_SENT),
projection,
COLUMN_NAME_ID + "= ? ",
new String[]{ lastMessageId}, null);
if(null != messageCursor && messageCursor.moveToFirst()) {
Long lastMessageTimeStamp = Long.parseLong(messageCursor.getString(messageCursor.getColumnIndex(COLUMN_NAME_DATE)));
}
Complete Source code for this class is located at:
https://github.com/midhunhk/message-counter/blob/unicorn/messageCounter/src/main/java/com/ae/apps/messagecounter/observers/SMSObserver.java

I was able to solve this issue by using a different approach.
It seems like when we query the table SMSManager.SMS_URI_SENT as in the question, it is only returning 1 row which is the last message that was sent.
Cursor newMessagesCursor = context.getContentResolver().query(
Uri.parse(SMSManager.SMS_URI_ALL),
MessagesTableConstants.SMS_TABLE_PROJECTION,
"person is null and " + MessagesTableConstants.COLUMN_NAME_DATE + "> ? ",
new String[]{String.valueOf(lastMessageTimeStamp)}, null);
I query for SMSManager.SMS_URI_ALL and check for person column as null which represents messages that are sent.

Related

Failed to retrieve the message from inbox in the real device

I am trying to get the inbox and sent messages. For this I have written my code below. My code runs well in the emulator but it doesn't work when I try to run it on a real device. It fails to collect the inbox messages even though there are messages in the inbox. I'd like to add that I want make the query with the contact number to retrieve the messages.
Cursor cursorsender = contentResolverSender.query(
Uri.parse("content://sms/sent"), null, "address = "
+ senderAddress, null, null);
Cursor cursor = contentResolver.query(Uri.parse("content://sms/inbox"),
null, "address = " + senderAddress, null, null);
my cursorsender.movetofirst() is returning false.

How to get the number of already read messages in android?

In my app,i want to give the user info about the number of already read and unread messages from inbox.I have searched and found out that there is no such content://sms/read is present in android api.I have tried this code till now:
Uri number_of_sms_read = Uri.parse("content://sms/read");
Cursor c = ShowTheMessages.this.getContentResolver().query(number_of_sms_read, null,null, null, null);
c.moveToFirst();
NumberOfSmsReadInInbox = c.getCount();
Can you please tell me is it possible to get the count of read and unread messages in android?
Thanks in advance.
I suppose you can take a look at this question which is the reverse of yours: Get number of unread sms
It provides the WHERE condition "read = 0" to the query, so you might want to supply a "read = 1".
final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
Cursor c = getContentResolver().query(SMS_INBOX, null, "read = 1", null, null);
int unreadMessagesCount = c.getCount();
c.deactivate();

Reading text from SMS, and show it as text view

I am trying to create app, that will get the text from SMS, and use it in textview. So something like this, message is recived, i check if it is message I want, then i extract text, save it to string, and then show this string in textview. Any suggestions from where should i start, any examples plese ??
You can start here for handling received SMS.
First I would listen for SMS incoming, and on incoming SMS show a notification. Then if the user opens your app, update your display using this to get the data you want:
Uri allMessage = Uri.parse("content://sms/inbox");
ContentResolver cr = getContentResolver();
Cursor c = cr.query(allMessage, null, null, null, null);
//shows one message
c.moveToNext();
//uncomment to cycle thru ALL messages... This will take AWHILE
//while (c.moveToNext()) {
for(int i = 0; i != c.getColumnCount(); i++){
String columnName = c.getColumnName(i);
String columnValue = c.getString(i);
Log.v(TAG, "Col: " + columnName);
Log.v(TAG, "Val: " + columnValue);
}
//}
Play around with it a little. It Should have all of the data you need (distinguish SMSs by timestamp)

Android Froyo: my life with call_log

I'm stuck with the call_log functionality in Froyo. As many of you know, Froyo logs in call log not only calls but also each outgoing and incomming SMS message. You can chose in options to show all that crap, or only specific types (outgoing calls, incoming calls, sent messages, received messages etc), but since this is radio button, you cannot specify for example only ongoing and incoming calls. Very known and annoing Froyo functionality.
So I started to write some simple tool to read the call log by myself. Here is the code snippet:
try {
mCur = getApplicationContext().getContentResolver()
.query(CallLog.Calls.CONTENT_URI, columns, null, null, null );
mCur.moveToFirst();
io = mCur.getColumnIndex(CallLog.Calls._ID);
bo = mCur.getColumnIndex(CallLog.Calls.NUMBER);
no = mCur.getColumnIndex(CallLog.Calls.CACHED_NAME);
to = mCur.getColumnIndex(CallLog.Calls.TYPE);
while (mCur.isAfterLast() == false) {
i = mCur.getString(io);
b = mCur.getString(bo);
n = mCur.getString(no);
t = mCur.getString(to);
Log.i(TAG, "CallLog: ID="+i+" number="+b+" name="+n+" type="+t);
mCur.moveToNext();
}
} catch (Exception e) {
Log.e(TAG, "updateCallLog", e);
} finally {
if (mCur != null) {
mCur.close();
mCur = null;
}
}
Surprise, surprise, the call_log provider skips the sms records from the call log. So with the code above I see only call records (incoming or outgoing), all other records are skipped. The little more digging into it revealed that the CallLog provider adds internally filtering to the call log database:
02-03 09:26:42.348 E/CLCService(28244): android.database.sqlite.SQLiteException:
near ")": syntax error: , while compiling:
SELECT _id, name, number, type FROM logs WHERE (logtype=100 OR logtype=500) AND (_ID=)
Do not look for the syntax error, it was created on purpose to force provider to dump the SQL query by calling query(CallLog.Calls.CONTENT_URI, columns, "_ID=", null, null )). The (_ID=) is what is provided in the query, the rest of (logtype=100 OR logtype=500) is apparently added by the call log provider itself.
So I have two questions:
Where I can find in the Android code how the provider is adding the logtype filter? I was looking into CallLog.java and CallLogProvider.java and cannot find it.
How can I read all records from the call log in Froyo? I cannot bypass the call log provider and use my own SQL helper for this until I will not root the phone, which is not an option. Is there any other way to do it?
I'm not certain just what is going wrong but reading the call log to get just incoming or outgoing calls is simple enough. The sample below adds restrictions to the query so that it only returns data for outgoing calls made after a certain date. The where string uses question marks to indicate where the values from the wargs array should be substituted in to form the sql query.
About where the extra WHERE clause occurs. Almost certainly in the calllog provider implementation. The providers commonly have a switch statement that uses the uri that you use to open the provider and then adds restrictions based on the uri. The calllog one seems to be in packages/providers/ContactsProvider.
public static int getMinutesUsedSince(Context context, Date date) {
Uri uri = CallLog.Calls.CONTENT_URI;
String columns[] = new String[] { CallLog.Calls.DURATION };
String where = CallLog.Calls.TYPE + "=? AND " + CallLog.Calls.DATE + ">?";
String wargs[] = new String[] {
String.valueOf(CallLog.Calls.OUTGOING_TYPE),
String.valueOf(date.getTime())
};
String sortOrder = "date DESC";
Cursor c = context.getContentResolver().query(uri, columns, where, wargs, sortOrder);
long sum = 0;
int durationIndex = c.getColumnIndex(CallLog.Calls.DURATION);
if (c.moveToFirst()) {
do {
/* for each individual call, round up to the nearest minute */
long duration = c.getLong(durationIndex);
long minutes = (long)Math.ceil(duration / 60.0);
sum += minutes;
} while (c.moveToNext());
}
c.close();
return (int)sum;
}

How to retrieve missed calls on Android SDK 2.2

in my app I should do some action when a call comes but not answered by the user.
I have searched in the android.telephony and the NotificationManager, but I haven't found a method to solve this problem.
Does someone have an idea of how to get to know if there is a missed call on the phone or not ?
Here is code that can query the call log for a missed call. Basically, you will have to trigger this somehow and make sure that you give the call log some time ( a few seconds should do it) to write the information otherwise if you check the call log too soon you will not find the most recent call.
final String[] projection = null;
final String selection = null;
final String[] selectionArgs = null;
final String sortOrder = android.provider.CallLog.Calls.DATE + " DESC";
Cursor cursor = null;
try{
cursor = context.getContentResolver().query(
Uri.parse("content://call_log/calls"),
projection,
selection,
selectionArgs,
sortOrder);
while (cursor.moveToNext()) {
String callLogID = cursor.getString(cursor.getColumnIndex(android.provider.CallLog.Calls._ID));
String callNumber = cursor.getString(cursor.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
String callDate = cursor.getString(cursor.getColumnIndex(android.provider.CallLog.Calls.DATE));
String callType = cursor.getString(cursor.getColumnIndex(android.provider.CallLog.Calls.TYPE));
String isCallNew = cursor.getString(cursor.getColumnIndex(android.provider.CallLog.Calls.NEW));
if(Integer.parseInt(callType) == MISSED_CALL_TYPE && Integer.parseInt(isCallNew) > 0){
if (_debug) Log.v("Missed Call Found: " + callNumber);
}
}
}catch(Exception ex){
if (_debug) Log.e("ERROR: " + ex.toString());
}finally{
cursor.close();
}
I hope you find this useful.
From what I understand, you need to query the CallLog provider (or maybe CallLog.Calls), and this page explains how to query content provider: http://developer.android.com/guide/topics/providers/content-providers.html#basics
I'd be happy to see the code if you can make this work !
I suppose you have content providers to access call logs.
http://www.anddev.org/video-tut_-_querying_and_displaying_the_calllog-t169.html
http://www.devx.com/wireless/Article/41133
If this code works you just need to run this query at the right time. I mean check some samples that can notify you when you get a call in your device
http://groups.google.com/group/android-developers/browse_thread/thread/d97a759a3708cbe3
Once you get this notification put a timer or use some built in Intents to find that the phone is back to normal state and access the call logs...
Possible duplicate
broadcast receiver for missed call in android
Show Toast on Missed Call in android application

Categories

Resources