I am trying to read SMS stored in sim card . That is why I have written the following function .
void read_sms()
{
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/icc"), null, null, null, null);
int indexBody = cursor.getColumnIndex("body");
int indexAddress = cursor.getColumnIndex("address");
if (indexBody < 0 || !cursor.moveToFirst())
return;
String fromNumber,smsMessageId;
try{
do {
SMSItem smsItem = new SMSItem();
String sms = cursor.getString(indexBody);
String str = "SMS From: " + cursor.getString(indexAddress)
+ "\n" + sms + " \n";
fromNumber = cursor.getString(indexAddress);
// arrayAdapter.add(str);
smsItem.sms = sms;
smsItem.status = false;
long millis = cursor.getLong(cursor
.getColumnIndexOrThrow("date"));
Date date = new Date(millis);
Calendar c = Calendar.getInstance();
// set the calendar to start of today
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
// and get that as a Date
Date today = c.getTime();
String smsDate;
if (date.before(today)) {
smsDate = (String) DateFormat.format(" MMMM dd ", new Date(
millis));
} else {
smsDate = (String) DateFormat.format(" h:mm ",
new Date(millis));
}
smsItem.time = smsDate;
smsMessageId = cursor.getString(cursor.getColumnIndex("_id"));
smsItem.ID = smsMessageId;
// Toast.makeText(this, "The id is "+smsMessageId,
// Toast.LENGTH_LONG).show();
smsBody.add(smsItem);
Toast.makeText(this, " "+smsItem.sms, Toast.LENGTH_LONG).show();
} while (cursor.moveToNext());
}
catch(Exception e)
{
Toast.makeText(this, "Message: "+e.getMessage(), Toast.LENGTH_LONG).show();
}
cursor.close();
}
But I am getting null pointer exception . Why am I getting null pointer exception ? How can I solve this ?
I tried putting your code in a test app and also got NPE (Null Pointer Exception). The trace tells me that the following line has a problem and returning NPE.
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/icc"), null, null, null, null);
When I changed replaced line with following, things started working fine.
Cursor cursor = managedQuery(Uri.parse("content://sms"), null, null, null, null);
Related
I am wondering how to read last five SMS received from a particular mobile number on a particular date.
I know how to read all SMS from a particular sender, and how to read the last SMS, but I am unable to fetch and read the last few SMS. I tried to read them by using
"date DESC LIMIT 5"
My code is like below
Uri mSmsinboxQueryUri = Uri.parse("content://sms/inbox");
String[] projection = {"address", "body"};
Cursor cursor1 = MainActivity.this.getContentResolver().query(mSmsinboxQueryUri,
null,
"address = ?",
new String[]{phoneNumber},
"date DESC LIMIT 5");
if (cursor1 != null && cursor1.moveToFirst()) {
body = cursor1.getString(cursor1.getColumnIndex("body"));
totalBody = totalBody + body;
Log.d("Registration", totalBody);
}
But every time it's showing only the last message.
You're only seeing one message because your code is only handling the first record in the returned Cursor. You need to loop over the Cursor to handle the rest. For example:
if (cursor != null && cursor.moveToFirst()) {
do {
body = cursor1.getString(cursor1.getColumnIndex("body"));
totalBody = totalBody + body;
Log.d("Registration", totalBody);
} while (cursor.moveToNext());
}
Also, if you want to restrict the query to one day, you can use a Calendar to figure the starting and ending times for that day in milliseconds - as that is how dates are stored in the SMS table - and add the appropriate comparison to the where clause. For example:
private static final int DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
private static final Uri inboxUri = Uri.parse("content://sms/inbox");
// Months are zero-based; i.e., JANUARY == 0
// Phone number must be exact in this example
private void listMessages(String phoneNumber, int year, int month, int day) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DATE, day);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
String[] projection = {"address", "body"};
String whereAddress = "address = ?";
String whereDate = "date BETWEEN " + cal.getTimeInMillis() +
" AND " + (cal.getTimeInMillis() + DAY_MILLISECONDS);
String where = DatabaseUtils.concatenateWhere(whereAddress, whereDate);
Cursor cursor = null;
try {
cursor = getContentResolver().query(inboxUri,
projection,
where,
new String[]{phoneNumber},
"date DESC LIMIT 5");
if (cursor != null && cursor.moveToFirst()) {
do {
Log.d("Message", cursor.getString(cursor.getColumnIndex("body")));
} while (cursor.moveToNext());
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (cursor != null) {
cursor.close();
}
}
}
I am wondering how to read last five SMS received from a particular mobile number on a particular date.
I know how to read all SMS from a particular sender, and how to read the last SMS, but I am unable to fetch and read the last few SMS. I tried to read them by using
"date DESC LIMIT 5"
My code is like below
Uri mSmsinboxQueryUri = Uri.parse("content://sms/inbox");
String[] projection = {"address", "body"};
Cursor cursor1 = MainActivity.this.getContentResolver().query(mSmsinboxQueryUri,
null,
"address = ?",
new String[]{phoneNumber},
"date DESC LIMIT 5");
if (cursor1 != null && cursor1.moveToFirst()) {
body = cursor1.getString(cursor1.getColumnIndex("body"));
totalBody = totalBody + body;
Log.d("Registration", totalBody);
}
But every time it's showing only the last message.
You're only seeing one message because your code is only handling the first record in the returned Cursor. You need to loop over the Cursor to handle the rest. For example:
if (cursor != null && cursor.moveToFirst()) {
do {
body = cursor1.getString(cursor1.getColumnIndex("body"));
totalBody = totalBody + body;
Log.d("Registration", totalBody);
} while (cursor.moveToNext());
}
Also, if you want to restrict the query to one day, you can use a Calendar to figure the starting and ending times for that day in milliseconds - as that is how dates are stored in the SMS table - and add the appropriate comparison to the where clause. For example:
private static final int DAY_MILLISECONDS = 24 * 60 * 60 * 1000;
private static final Uri inboxUri = Uri.parse("content://sms/inbox");
// Months are zero-based; i.e., JANUARY == 0
// Phone number must be exact in this example
private void listMessages(String phoneNumber, int year, int month, int day) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.DATE, day);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
String[] projection = {"address", "body"};
String whereAddress = "address = ?";
String whereDate = "date BETWEEN " + cal.getTimeInMillis() +
" AND " + (cal.getTimeInMillis() + DAY_MILLISECONDS);
String where = DatabaseUtils.concatenateWhere(whereAddress, whereDate);
Cursor cursor = null;
try {
cursor = getContentResolver().query(inboxUri,
projection,
where,
new String[]{phoneNumber},
"date DESC LIMIT 5");
if (cursor != null && cursor.moveToFirst()) {
do {
Log.d("Message", cursor.getString(cursor.getColumnIndex("body")));
} while (cursor.moveToNext());
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (cursor != null) {
cursor.close();
}
}
}
I use this code for date in sms inbox but it shows 01/01/70 wrong date for all sms how do I change correct?
public void refreshSmsInbox() {
ContentResolver contentResolver = getActivity().getContentResolver();
Cursor smsInboxCursor = contentResolver.query(Uri.parse("content://sms/inbox"), null, null, null, null);
int indexBody = smsInboxCursor.getColumnIndex("body");
int indexAddress = smsInboxCursor.getColumnIndex("address");
int timeMillis = smsInboxCursor.getColumnIndex("date");
Date date = new Date(timeMillis);
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy");
String dateText = format.format(date);
if (indexBody < 0 || !smsInboxCursor.moveToFirst()) return;
arrayAdapter.clear();
do {
String str = smsInboxCursor.getString(indexAddress) +" "+
"\n" + smsInboxCursor.getString(indexBody) +"\n"+ dateText+"\n";
arrayAdapter.add(str);
} while (smsInboxCursor.moveToNext());
smsInboxCursor.close();
}
#Mike M's comment was correct. You're trying to convert the index of the date column to Date format. You're not actually converting the value of the date. Try this:
public void refreshSmsInbox() {
ContentResolver contentResolver = getContentResolver();
Cursor smsInboxCursor = contentResolver.query(Uri.parse("content://sms/inbox"), null, null, null, null);
// get the index of the column
int indexBody = smsInboxCursor.getColumnIndex("body");
int indexAddress = smsInboxCursor.getColumnIndex("address");
int indexDate = smsInboxCursor.getColumnIndex("date");
if (indexBody < 0 || !smsInboxCursor.moveToFirst()) return;
// loop through the messages in inbox
do {
// get the value based on the index of the column
String address = smsInboxCursor.getString(indexAddress);
String body = smsInboxCursor.getString(indexBody);
long date = smsInboxCursor.getLong(indexDate);
// convert millis value to proper format
Date dateVal = new Date(date);
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy");
String dateText = format.format(dateVal);
String str = address + "\n" + body + "\n" + dateText + "\n";
System.out.println(str);
} while (smsInboxCursor.moveToNext());
smsInboxCursor.close();
}
This part is wrong:
int timeMillis = smsInboxCursor.getColumnIndex("date");
Date date = new Date(timeMillis);
getColumnIndex returns an index, not the actual value. I think you want this instead, though I haven't tested it myself:
int dateIndex = smsInboxCursor.getColumnIndex("date");
long timeMillis = smsInboxCursor.getLong(dateIndex);
Date date = new Date(timeMillis);
want to get the call log history by today, yesterday, last seven days and last 30days along with that i want to show the total duration of incoming and outgoing calls of that particular number.
suppose abc has 3 outgoing and 1 incoming calls. i should get the total duration of those calls.
just let me know if we can get duration and calls log by cursor GroupBy or ORDER BY clause rather than looping and adding duration. Just give me rough structure for better solution and can work effectively .
String[] whereValue=null;
Calendar calendar = Calendar.getInstance();
String currentDate = String.valueOf(calendar.getTimeInMillis());
switch (period) {
case DAY:
whereValue = new String[]{getTimeFrom(period),currentDate};
break;
case YESTERDAY:
whereValue = new String[]{getTimeFrom(period),currentDate};
break;
case WEEK:
whereValue = new String[]{getTimeFrom(period),currentDate};
break;
case MONTH:
whereValue = new String[]{getTimeFrom(period),currentDate};
break;
default:
Log.d(Utils.LOG_TAG, "Error:");
}
String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
Uri callUri = Uri.parse("content://call_log/calls");
Cursor cur = context.getContentResolver().query(callUri, null, android.provider.CallLog.Calls.DATE+" BETWEEN ? AND ?", whereValue, strOrder);
String callNumber = cur.getString(cur
.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
String callName = cur
.getString(cur
.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME));
String callType = cur.getString(cur
.getColumnIndex(android.provider.CallLog.Calls.TYPE));
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
case CallLog.Calls.INCOMING_TYPE:
break;
}
String duration = cur.getString(cur
.getColumnIndex(android.provider.CallLog.Calls.DURATION));
the above code is even not working for getting call log between fromdate to till date. any help?
I have managed to get the call log between two dates. You can get call log of today, yesterday, last seven days, last 30days. as well duration of calls (calls from same number multiple times also)
you should pass selection as
android.provider.CallLog.Calls.DATE + " BETWEEN ? AND ?"
and
selectionArgs
whereValue = new String[]{String.valueOf(calendar1.getTimeInMillis()),String.valueOf(calendar.getTimeInMillis());};
Map<String, StatEntry> callLogMap1 = new HashMap<>();
callLogMap1.clear();
String strOrder1 = android.provider.CallLog.Calls.DATE + " DESC limit 500";
Uri callUri = Uri.parse("content://call_log/calls");
Cursor cur = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, android.provider.CallLog.Calls.DATE + " BETWEEN ? AND ?", whereValue,
strOrder1);
if (cur != null) {
try {
while (cur.moveToNext()) {
String callNumber = cur.getString(cur.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
// String callDate = cur.getString(cur.getColumnIndex(android.provider.CallLog.Calls.DATE));
int duration = cur.getInt(cur.getColumnIndex(android.provider.CallLog.Calls.DURATION));
String name = cur.getString(cur.getColumnIndex(CallLog.Calls.CACHED_NAME));
StatEntry StatEntry1 = null;
int id = cur.getInt(cur.getColumnIndex(CallLog.Calls._ID));
int type = cur.getInt(cur.getColumnIndex(CallLog.Calls.TYPE));
if (callNumber != null & duration > 0 && (type == 1 || type == 2)) {
int n = callNumber.length();
String lastDigits;
String number = callNumber.replaceAll(Pattern.quote("+"), ""); //replacing the plus
//am just checking last 5digitis and saving to map so that we can get same //number duration
if (n >= 5) {
try {
lastDigits = String.valueOf(Long.parseLong(number) % 100000);
} catch (NumberFormatException e) {
e.printStackTrace();
lastDigits = callNumber;
}
} else {
lastDigits = callNumber;
}
if (callLogMap1.containsKey(lastDigits)) {
StatEntry1 = callLogMap1.get(callNumber);
StatEntry1.setTitle(callNumber);
StatEntry1.Duration += duration;
} else {
StatEntry1 = new StatEntry();
StatEntry1.setTitle(callNumber);
StatEntry1.Duration += duration;
}
StatEntry1.setTime((StatEntry1.Duration) / 60);
callLogMap1.put(callNumber, StatEntry1);
}
}
} catch (Exception e) {
e.printStackTrace(
);
} finally {
cur.close();
}
}
atlast passing hashmap data to arraylist.
ArrayList<StatEntry> callLogList1 = new ArrayList<>(callLogMap1.size());
if (callLogMap1.size() > 0) {
for (Map.Entry<String, StatEntry> entry : callLogMap1.entrySet()) {
callLogList1.add(entry.getValue());
}
}
hope this will be helpful for viewers.
I managed to get the call log between two dates and also you can get the duration of the calls.Try this method..
public class CallLogActivity extends Activity {
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call_log);
textView = (TextView) findViewById(R.id.textCallBetween);
textView.setVisibility(View.GONE);
// listcallLog = (ListView) findViewById(R.id.calllogItems);
getCalldetails();
}
public void getCalldetails() {
StringBuffer stringBuffer = new StringBuffer();
String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
Calendar calender = Calendar.getInstance();
calender.set(2016, calender.NOVEMBER, 18);
String fromDate = String.valueOf(calender.getTimeInMillis());
calender.set(2016, calender.NOVEMBER, 20);
String toDate = String.valueOf(calender.getTimeInMillis());
String[] whereValue = {fromDate,toDate};
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
Cursor managedCursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, android.provider.CallLog.Calls.DATE + " BETWEEN ? AND ?", whereValue, strOrder);
// Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null, android.provider.CallLog.Calls.DATE, new String[]{" BETWEEN ? AND ?"}, strOrder);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
stringBuffer.append("Call Log :");
while (managedCursor.moveToNext())
{
String phoneNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
SimpleDateFormat formatter = new SimpleDateFormat(
"dd-MMM-yyyy HH:mm");
String dateString = formatter.format(new Date(Long
.parseLong(callDate)));
// Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString(duration);
String dir = null;
int dirCode = Integer.parseInt(callType);
switch (dirCode)
{
case CallLog.Calls.OUTGOING_TYPE :
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED CALL";
break;
}
stringBuffer.append("\nPhone Number:--- " + phoneNumber + "\nCall Type:--- "
+ dir + "\nCall Date:---"
+ dateString + "\nCall Duration:---" + callDuration);
stringBuffer.append("\n--------------------------");
}
textView.setText(stringBuffer);
textView.setVisibility(View.VISIBLE);
}
}
I am reading unread sms from a particular number by the following code .
public void getUnreadMessage() {
Cursor smsInboxCursor1 = getContentResolver().query(
Uri.parse("content://sms/inbox"), new String[] {},
"read = 0 and address='" + pre_address + "'", null, null);
int indexBody = smsInboxCursor1.getColumnIndex("body");
int indexAddress = smsInboxCursor1.getColumnIndex("address");
if (indexBody < 0 || !smsInboxCursor1.moveToFirst())
return;
// arrayAdapter.clear();
do {
String str = "SMS From: " + smsInboxCursor1.getString(indexAddress)
+ "\n" + smsInboxCursor1.getString(indexBody) + " \n";
fromNumber = smsInboxCursor1.getString(indexAddress);
smsBody.add(smsInboxCursor1.getString(indexBody));
// arrayAdapter.add(str);
status.add(false);
} while (smsInboxCursor1.moveToNext());
}
Now I want to get the time of receiving sms from this particular number . How can I do that ?
There is a column named DATE that contains the date the message was received. You can get directly like the other fields you already retrieve:
int indexData = smsInboxCursor1.getColumnIndex("data");
...
long dateReceived = smsInboxCursor1.getLong(indexData);
Since it's a timestamp you need to convert in a human readable string. You can do it with this code:
private String getDate(long time) {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(time);
String date = DateFormat.format("dd-MM-yyyy HH:mm:ss", cal).toString();
return date;
}