I would like to get all the sent sms (text messages) from a device.
I can get all of them from the inbox with:
public List<SMS> getAllInboxSMS(Context ctx) {
List<SMS> inboxSMSList = new ArrayList<>();
try {
Uri uriSms = Uri.parse("content://sms/inbox");
Cursor c = ctx.getContentResolver().query(uriSms, new String[]{"_id", "thread_id", "address", "person", "date", "body"}, "read=0", null, null);
if (c != null && c.moveToFirst()) {
do {
inboxSMSList.add(new SMS(c));
} while (c.moveToNext());
}
} catch (Exception e) {
Log.e("getAllInboxSMS", e.toString());
}
Log.i("inbox", "size: " + inboxSMSList.size());
Log.i("inbox", inboxSMSList.toString());
return inboxSMSList;
}
However if I modify
Uri.parse("content://sms/inbox");
to
Uri.parse("content://sms/sent");
The returned list size is 0.
I tried to set the app as default sms app but it doesn't work in that way either.
I work on Lollipop (Android 5).
Please help if you can.
To read all messages for inbox or sent programmatically in Android use following function.
public List<Sms> getAllSms(String folderName) {
List<Sms> lstSms = new ArrayList<Sms>();
Sms objSms = new Sms();
Uri message = Uri.parse("content://sms/"+folderName);
ContentResolver cr = mActivity.getContentResolver();
Cursor c = cr.query(message, null, null, null, null);
mActivity.startManagingCursor(c);
int totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < totalSMS; i++) {
objSms = new Sms();
objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
objSms.setAddress(c.getString(c
.getColumnIndexOrThrow("address")));
objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
objSms.setReadState(c.getString(c.getColumnIndex("read")));
objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
lstSms.add(objSms);
c.moveToNext();
}
}
// else {
// throw new RuntimeException("You have no SMS in " + folderName);
// }
c.close();
return lstSms;}
Call above function to get all messages from inbox or send folder.
getAllSms("inbox"); // Get all sms from inbox
getAllSms("sent"); // Get all sms from sent
To get all sms from inbox or sent folder use following function
public List<Sms> getAllSms() {
List<Sms> lstSms = new ArrayList<Sms>();
Sms objSms = new Sms();
Uri message = Uri.parse("content://sms/");
ContentResolver cr = mActivity.getContentResolver();
Cursor c = cr.query(message, null, null, null, null);
mActivity.startManagingCursor(c);
int totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < totalSMS; i++) {
objSms = new Sms();
objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
objSms.setAddress(c.getString(c
.getColumnIndexOrThrow("address")));
objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
objSms.setReadState(c.getString(c.getColumnIndex("read")));
objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
if (c.getString(c.getColumnIndexOrThrow("type")).contains("1")) {
objSms.setFolderName("inbox");
} else {
objSms.setFolderName("sent");
}
lstSms.add(objSms);
c.moveToNext();
}
}
// else {
// throw new RuntimeException("You have no SMS");
// }
c.close();
return lstSms;}
Sms class is below:
public class Sms{
private String _id;
private String _address;
private String _msg;
private String _readState; //"0" for have not read sms and "1" for have read sms
private String _time;
private String _folderName;
public String getId(){
return _id;
}
public String getAddress(){
return _address;
}
public String getMsg(){
return _msg;
}
public String getReadState(){
return _readState;
}
public String getTime(){
return _time;
}
public String getFolderName(){
return _folderName;
}
public void setId(String id){
_id = id;
}
public void setAddress(String address){
_address = address;
}
public void setMsg(String msg){
_msg = msg;
}
public void setReadState(String readState){
_readState = readState;
}
public void setTime(String time){
_time = time;
}
public void setFolderName(String folderName){
_folderName = folderName;
}
}
Don’t forget to define following permission in your AndroidManifest.xml
<uses-permission android:name="android.permission.READ_SMS" />
for marshmallow device support you to check runtime permission
for reference runtime permission
Related
I am trying to fetch SMS's which start with TM-,ID-, AX-, AD- but I am getting sms's only which having number.
I am not able to receive any sms which will have text in address.
Here is my code :
Uri uriSms = Uri.parse("content://sms/inbox");
String[] projection = new String[]{"_id", "address", "date", "body", "person", "type"};
m_SMSCursor =context.getContentResolver().query(uriSms, projection, null,null,null);
if(m_SMSCursor.moveToFirst())
{
// Read each row from cursor and store it into the database
do {
// Extract fields from cursor
final String number = m_SMSCursor.getString(1);
final long date = m_SMSCursor.getLong(2);
final String body = m_SMSCursor.getString(3);
final String person = m_SMSCursor.getString(4);
final int type = m_SMSCursor.getInt(5);
try {
// Insert call log into database
long l;
new Thread(new Runnable() {
#Override
public void run() {
// create object for CallLogAdapter
SMSDataAdapter objSmsDataAdapter = new SMSDataAdapter(
context);
// open the database
objSmsDataAdapter = objSmsDataAdapter.Open();
try {
boolean isVMPresent = number.startsWith("VM-");
boolean isLMPresent = number.startsWith("LM-");
boolean isTMPresent = number.startsWith("TM-");
boolean isVKPresent = number.startsWith("VK-");
boolean isIXPresent = number.startsWith("IX-");
boolean isADPresent = number.startsWith("AD-");
boolean isAXPresent = number.startsWith("AX-");
boolean isBWPresent = number.startsWith("BW-");
boolean isIDPresent = number.startsWith("ID-");
boolean isIMPresent = number.startsWith("IM-");
Log.i(TAG, "Number1 : " + number + " body1 : " + body + " peron : " + person + " type : " + type);
if (isVMPresent || isLMPresent || isTMPresent || isVKPresent || isIXPresent || isADPresent || isAXPresent || isBWPresent || isIDPresent || isIMPresent) {
long lNumberOfEntry = objSmsDataAdapter.Insert(number, body, date, DATA_NOT_ANALYZED);
}
} catch (SQLException e1) {
} finally {
// Close the database
objSmsDataAdapter.Close();
}
}
}).start();
} catch (SQLException e) {
return FAILURE;
}
} while (m_SMSCursor.moveToNext());
}
But I am able to fetch all sms except which having text in address. I am able fetch sms's which having number in address.
Please give me hint or reference.
Use this method to get all data in a list first and then access the number by smsList.getNumber()
List<SMSData> smsList = new ArrayList<SMSData>();
Uri uri = Uri.parse("content://sms/inbox");
Cursor c= getContentResolver().query(uri, null, null ,null,null);
startManagingCursor(c);
// Read the sms data and store it in the list
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();
SMSData:
public class SMSData {
// Number from witch the sms was send
private String number;
// SMS text body
private String body;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
I am making an app which records the messages from a particular sender.For e.g I want to get all SMS from the bank HDFC in a Listview.The sender's address in my inbox is named as "AM-HDFC".I have tried the below code but the app crashes saying that URI is not found.What will be the possible solution?
public class MsgReader extends AppCompatActivity {
Cursor c;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_msg_reader);
List<Sms> smslist=getAllSms("inbox");
RecyclerView rView = (RecyclerView) findViewById(R.id.list);
rView.setLayoutManager(new LinearLayoutManager(this));
rView.setHasFixedSize(true);
MsgAdapter rcAdapter = new MsgAdapter(smslist);
rView.setAdapter(rcAdapter);
}
public List<Sms> getAllSms(String folderName) {
List<Sms> lstSms = new ArrayList<Sms>();
Sms objSms = new Sms();
Uri message = Uri.parse("content://sms/");
ContentResolver cr = this.getContentResolver();
c= cr.query(Uri.parse("content://mms-sms/AM-HDFC"), null, null, null, null);
this.startManagingCursor(c);
int totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < totalSMS; i++) {
objSms = new Sms();
objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
objSms.setAddress(c.getString(c.getColumnIndexOrThrow("address")));
objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
objSms.setReadState(c.getString(c.getColumnIndex("read")));
objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
lstSms.add(objSms);
c.moveToNext();
}
}
else {
throw new RuntimeException("You have no SMS in " + folderName);
}
c.close();
return lstSms;
}
#Override
protected void onPause() {
super.onPause();
if (c != null) {
c.close();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (c != null) {
c.close();
}
}
}
Try this :
public void getSmsInbox(Context context, String address) {
String selection = Telephony.Sms.ADDRESS+"='"+address+"'";
ContentResolver cr = context.getContentResolver();
Cursor c = cr.query(Telephony.Sms.CONTENT_URI, null, selection, null, null);
if (c != null) {
if (c.moveToFirst()) {
for (int j = 0; j < c.getCount() ; j++) {
String smsDate = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.DATE));
Date dateFormat = new Date(Long.valueOf(smsDate));
String body = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.BODY));
Log.d(TAG, address+", "+dateFormat.toString()+" : "+body);
c.moveToNext();
}
}
c.close();
} else {
Toast.makeText(this, "No message to show!", Toast.LENGTH_SHORT).show();
}
}
Use it like this :
getSmsInbox(MainActivity.this, "AM-HDFC");
And don't forget to ask for the permission :
<uses-permission android:name="android.permission.READ_SMS" />
I'm developping an Android App.
In my first Activity I list conversations and on conversation click, app launch an other activity with list of sms for the conversation.
But, on back press, I get that exception :
java.lang.RuntimeException: Unable to resume activity {com.example/com.example.activity.TalksActivity_}: android.database.StaleDataException: Attempted to access a cursor after it has been closed.
List conversations :
public static List<Talk> getTalks(Activity context) {
List<Talk> listTalk = new ArrayList<>();
Talk objTalk;
Cursor cur= context.getContentResolver().query(Uri.parse("content://mms-sms/conversations?simple=true"), null, null, null, null);
context.startManagingCursor(cur);
Log.w(TAG, "getTalks");
int total = cur.getCount();
if(cur.moveToFirst())
{
for (int i = 0; i < total; i++) {
objTalk = new Talk();
String snippet = cur.getString(cur.getColumnIndexOrThrow("snippet"));
if (snippet.length() > 30) {
objTalk.setSnippet(snippet.substring(0, 27)+"...");
} else {
objTalk.setSnippet(snippet);
}
Date date = DateHelper.getDate(Long.parseLong(cur.getString(1)));
objTalk.setDate(date);
objTalk.setDateString(DateHelper.formatDate(date));
String id = cur.getString(cur.getColumnIndexOrThrow("_id")).toString();
objTalk.setId(id);
String recipientId = cur.getString(cur.getColumnIndexOrThrow("recipient_ids")).toString();
Cursor c2= context.getContentResolver().query(Uri.parse("content://mms-sms/canonical-addresses"), null, "_id = " + recipientId, null, null);
context.startManagingCursor(c2);
if(c2.moveToFirst())
{
String phoneNumber = c2.getString(1);
objTalk.setContact(getContact(context, phoneNumber));
listTalk.add(objTalk);
}
c2.close();
cur.moveToNext();
}
}
cur.close();
return listTalk;
}
List SMS :
public static Contact getContact(Activity context, String phoneNumber) {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
String name;
long id;
Contact contact = new Contact();
ContentResolver contentResolver = context.getContentResolver();
Cursor contactLookup = contentResolver.query(uri, new String[] {ContactsContract.PhoneLookup._ID,
ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup.PHOTO_FILE_ID }, null, null, null);
try {
if (contactLookup != null && contactLookup.getCount() > 0) {
contactLookup.moveToNext();
name = contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
id = contactLookup.getLong(contactLookup.getColumnIndex(ContactsContract.PhoneLookup._ID));
contact.setId(id);
contact.setName(name);
}
else
{
contact.setId(-1);
contact.setName(phoneNumber);
}
} finally {
if (contactLookup != null) {
contactLookup.close();
}
}
return contact;
}
public static List<Sms> getAllSms(Activity context, String talkId) {
List<Sms> receivedSmsList = getSmsList(context, "content://sms/inbox", talkId, false);
List<Sms> sentSmsList = getSmsList(context,"content://sms/sent", talkId, true);
List<Sms> allSms = new ArrayList<>();
allSms.addAll(receivedSmsList);
allSms.addAll(sentSmsList);
Collections.sort(allSms);
return allSms;
}
private static List<Sms> getSmsList(Activity context, String uri, String talkId, boolean isSent) {
List<Sms> smsList = new ArrayList<>();
Sms objSms;
Log.w(TAG, "getSmsList talkId="+talkId);
ContentResolver cr = context.getContentResolver();
Cursor c = cr.query(Uri.parse(uri), null, "thread_id="+talkId, null, null);
context.startManagingCursor(c);
if (c == null || c.getCount() == 0) {
c.close();
Log.w(TAG, "getSmsList cursor is null");
return new ArrayList<>();
}
int totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < totalSMS; i++) {
Log.w(TAG, i+" -> getSmsList sms id="+c.getString(c.getColumnIndexOrThrow("_id"))+" msg="+c.getString(c.getColumnIndexOrThrow("body")));
objSms = new Sms();
objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
objSms.setAddress(c.getString(c.getColumnIndexOrThrow("address")));
objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
objSms.setSent(isSent);
Date date = DateHelper.getDate(Long.parseLong(c.getString(c.getColumnIndexOrThrow("date"))));
objSms.setDate(date);
objSms.setDateString(DateHelper.formatDate(date));
smsList.add(objSms);
c.moveToNext();
}
}
c.close();
return smsList;
}
EDIT
Conversations Activity code (Sms activity is same) :
public class ConversationsActivity extends AppCompatActivity {
#AfterViews
void afterViews() {
// [...init adapter...]
mAdapter.addAll(SmsHelper.getTalks(this));
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mRecyclerView.setAdapter(mAdapter);
}
EDIT 2
If I don't call .close() on my cursors, it don't crash !
But... Isn't it too durty ?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to build a sms app. I've managed to get all the inbox message and display them in a thread but my approaching is probably wrong. I use a HashMap to store the address and based on it to delete existing message(only display the newest sms)
public void refreshSmsInbox() {
ContentResolver contentResolver = getContentResolver();
Cursor smsInboxCursor = contentResolver.query(
Uri.parse("content://sms/inbox"), null, null, null, null);
int indexBody = smsInboxCursor.getColumnIndex("body");
int indexAddress = smsInboxCursor.getColumnIndex("address");
if (indexBody < 0 || !smsInboxCursor.moveToFirst())
return;
adapter.clear();
do {
String address = smsInboxCursor.getString(indexAddress);
if (!hashMap.containsKey(address))
hashMap.put(address, 0);
else
hashMap.put(address, hashMap.get(address) + 1);
try {
if (hashMap.containsKey(address)) {
String str = smsInboxCursor.getString(indexAddress) + ":\n"
+ smsInboxCursor.getString(indexBody) + "\n";
int count = adapter.getCount();
while(count>0){
String item = adapter.getItem(count);
String string = item.substring(0, item.indexOf(':'));
if (address.equals(string)) {
adapter.remove(item);
}
}
adapter.add(str);
}
} catch (Exception e) {
e.printStackTrace();
}
} while (smsInboxCursor.moveToNext());
smsInboxCursor.close();
}
and when I click a thread it will open an intent to display the conversation. The thing is, I have just managed to display only the inbox sms in a thread (no sent sms) like this
How to retrieve the whole conversation and display it like this
any help is greatly appreciated.
Please check below code it might help you -
public List<Sms> getAllSms() {
List<Sms> lstSms = new ArrayList<Sms>();
Sms objSms = new Sms();
Uri message = Uri.parse("content://sms/");
ContentResolver cr = mActivity.getContentResolver();
Cursor c = cr.query(message, null, null, null, null);
mActivity.startManagingCursor(c);
int totalSMS = c.getCount();
if (c.moveToFirst()) {
for (int i = 0; i < totalSMS; i++) {
objSms = new Sms();
objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
objSms.setAddress(c.getString(c
.getColumnIndexOrThrow("address")));
objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
objSms.setReadState(c.getString(c.getColumnIndex("read")));
objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
if (c.getString(c.getColumnIndexOrThrow("type")).contains("1")) {
objSms.setFolderName("inbox");
} else {
objSms.setFolderName("sent");
}
lstSms.add(objSms);
c.moveToNext();
}
}
// else {
// throw new RuntimeException("You have no SMS");
// }
c.close();
return lstSms;
}
and model class for sms -
public class Sms{
private String _id;
private String _address;
private String _msg;
private String _readState; //"0" for have not read sms and "1" for have read sms
private String _time;
private String _folderName;
public String getId(){
return _id;
}
public String getAddress(){
return _address;
}
public String getMsg(){
return _msg;
}
public String getReadState(){
return _readState;
}
public String getTime(){
return _time;
}
public String getFolderName(){
return _folderName;
}
public void setId(String id){
_id = id;
}
public void setAddress(String address){
_address = address;
}
public void setMsg(String msg){
_msg = msg;
}
public void setReadState(String readState){
_readState = readState;
}
public void setTime(String time){
_time = time;
}
public void setFolderName(String folderName){
_folderName = folderName;
}
}
and dont forget to add permission in your manifest -
<uses-permission android:name="android.permission.READ_SMS" />
I try to retrieve the data each time the Android sends SMS.
Data form:
destination phone number
delivery time
SMS body
Anyone knows how?
Get sms in sent box.
public List<SmsRep> getOutboxSms()
{
if(null == context)
{
return new ArrayList<SmsRep>();
}
Uri uriSms = Uri.parse("content://sms/sent");
Cursor cursor = context.getContentResolver().query(uriSms, null,null,null,null);
List<SmsRep> outboxSms = cursor2SmsArray(cursor);
if(!cursor.isClosed())
{
cursor.close();
}
return outboxSms;
}
And the method to handle data in sent box:
public static List<SmsRep> cursor2SmsArray(Cursor cursor)
{
if(null == cursor || 0 == cursor.getCount())
{
return new ArrayList<SmsRep>();
}
List<SmsRep> messages = new ArrayList<SmsRep>();
try
{
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
{
SmsRep singleSms = new SmsRep();
singleSms.id = cursor.getInt(cursor.getColumnIndexOrThrow("_id"));
singleSms.address = cursor.getString(cursor.getColumnIndexOrThrow("address"));
singleSms.timestamp = cursor.getLong(cursor.getColumnIndexOrThrow("date")) / 1000; //### the sent time
singleSms.type = cursor.getInt(cursor.getColumnIndexOrThrow("type"));
singleSms.protocol = cursor.getInt(cursor.getColumnIndexOrThrow("protocol"));
/*
String smsSubject = cursor.getString(cursor.getColumnIndex("subject"));
byte[] subjByts = smsSubject.getBytes("UTF8");
singleSms.subject = new String(subjByts, "UTF8");
*/
String smsBody = cursor.getString(cursor.getColumnIndexOrThrow("body")); //### body
byte[] bodyBytes = smsBody.getBytes("UTF8");
singleSms.body = TextUtils.htmlEncode(new String(bodyBytes, "UTF8")); //escape,handle '='
singleSms.deviceId = deviceId;
//singleSms.body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
messages.add(singleSms);
}
}
catch (Exception e)
{
Log.e(TAG, e.getMessage());
}
finally
{
cursor.close();
}
return messages;
}
Definition of SmsRep:
public class SmsRep
{
static String separator ;
public int id;
public String address;
public long timestamp;
public int type;
public int protocol;
public String subject;
public String body;
public String deviceId;
public SmsRep()
{
// do nothing in ctor
}
}
Is this what you want ?:)
There is nothing in the Android SDK for this, sorry.
We can get notified when you receive a SMS, but there is no way to get notified when a SMS is sent.
Uri uriSMS = Uri.parse("content://sms/sent");
Cursor cur = getActivity().getContentResolver().query(uriSMS , null, null, null, null);
Cursor messagesCursor = getActivity().getContentResolver().query(uriSMS , new String[]{"_id", "address", "body", "person", "date",}, null, null, null);
if(messagesCursor.getCount() > 0) {
try {
while (messagesCursor.moveToNext())
{
int x=messagesCursor.getInt(messagesCursor.getColumnIndex("_id"));
String address=messagesCursor.getString(messagesCursor.getColumnIndex("address"));
String body=messagesCursor.getString(messagesCursor.getColumnIndex("body"));
String person=messagesCursor.getString(messagesCursor.getColumnIndex("person"));
String date_=messagesCursor.getString(messagesCursor.getColumnIndex("date"));
}
}
catch(Exception ex)
{
}
}