Is there any way that I can insert a predefined message into an existing conversation in the inbox from an app built on the Android platform?
With this code I am able to retrieve the last sent and received messages.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
Uri uriSMS = Uri.parse("content://sms/");
Cursor cur = getContentResolver().query(uriSMS, null, null, null, null);
cur.moveToNext();
String body = cur.getString(cur.getColumnIndex("body"));
String add = cur.getString(cur.getColumnIndex("address"));
String time = cur.getString(cur.getColumnIndex("date"));
String protocol = cur.getString(cur.getColumnIndex("protocol"));
String contactName = "";
Uri personUri = Uri.withAppendedPath( ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(add));
Cursor c = getContentResolver().query(personUri, new String[] { PhoneLookup.DISPLAY_NAME }, null, null, null );
if( c.moveToFirst() ) {
int nameIndex = c.getColumnIndex(PhoneLookup.DISPLAY_NAME);
contactName = c.getString(nameIndex);
}
c.close();
cur.close();
String out = "";
Date d = new Date(Long.valueOf(time));
if (protocol == null)
out = "Sending to: "+ contactName + " <"+add +">\nDate: "+d +"\nBody: "+body+"\n\n";
else
out = "Received from: "+ contactName + " <"+add +">\nDate: "+d +"\nBody: "+body+"\n\n";
tv.setText(out);
setContentView(tv);
}
Is there any way that I can incorporate this into my broadcast receiver (SmsReceiver.java)? Hopefully there is a way that I can trigger an event so that when a new message is received I can insert a predefined message into the conversation related to the newest text message in the inbox.
While I'm at it. Is there any way to accurately retrive the native phone number without asking the user to enter it manually?
Solved using the following code in my receiver.
ContentValues values = new ContentValues();
values.put("address", "0123456789");
values.put("body", "Message goes here");
context.getContentResolver().insert(Uri.parse("content://sms/"), values);
Related
I am trying to read latest SMS from All contacts but the procedure Currently I am using seems to be very slow. How can I improve it?
public Map<String, SMS> getLatestMsgs(){
Uri uriSMSURI = Uri.parse("content://sms/");
String[] projection = {_id, address, body,
read, date, subscriptionId, type};
String selection = "";
String[] selectionArgs = {};
String sortOrder = Telephony.Sms.DATE +" desc";
Cursor c = context.getContentResolver()
.query(uriSMSURI, projection, selection, selectionArgs, sortOrder);
LinkedHashMap<String, SMS> smsMap = new LinkedHashMap<>();
log.info(methodName, "Reading Messages..");
if(c==null){
log.info(methodName, "Query returned null cursor");
return smsMap;
}
while (c.moveToNext()) {
String id = c.getString(c.getColumnIndexOrThrow(this._id));
String from = c.getString(c.getColumnIndexOrThrow(this.address));
String body = c.getString(c.getColumnIndexOrThrow(this.body));
int serviceCenter = c.getInt(c.getColumnIndexOrThrow(this.subscriptionId));
boolean readState = c.getInt(c.getColumnIndex(this.read)) == 1;
long time = c.getLong(c.getColumnIndexOrThrow(this.date));
long type = c.getLong(c.getColumnIndexOrThrow(this.type));
if(!smsMap.containsKey(from)) {
SMS sms = new SMS();
sms.setId(id);
sms.setFrom(from);
sms.setBody(body);
sms.setRead(readState);
sms.setDateTime(time);
sms.setType(type);
sms.setSubscription(serviceCenter);
smsMap.put(from, sms);
}
}
c.close();
return smsMap;
}
This method has following steps:
Read all sms in decreasing order of timestamp
Start Iterating over fetched rows
If sms address already in map then ignore
else put SMS into LinkedHashMap
I need advise...
My app working with contacts, who have correspondence (SMS dialogs).
I have some difficulties with optimization getting process.
I decided realize that scheme:
On first launch read all "content://sms/inbox" and add unique value (broup by number of contact) to array new String [n.count()][4]. (fiedls: name, number, date, message and type)
Sort array as I want and transmit to main activity (or i can read db table directly there it doesn't matter)
Main activity class has procedure, which fill ListView (list.setAdapter) from receive data.
Everything works at the emulator perfectly, but when I trying setup at real device app catch fatal error.
So after aforesaid I have 2 quesions:
1. Why app is crashing? (any ideas)
2. How I can fix / rebuild my algorithm. Any pertinent criticism. I need function, which display in ListView contacts, "-" if contact does not have any incoming SMS, message of SMS if they exist.
Thanks.
below you can see procedures which insert and read data from db.
I will repeat, everything works at the emulator perfectly. It means db created, tables created and data insert, read and update. I public code "for a full picture".
public void Contact_to_db () {
dbHelper = new DBHelper(this);
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query( Uri.parse( "content://sms/inbox" ), null, null, null, "DATE ASC");
int indexBody = cursor.getColumnIndex( SmsReceiver.BODY );
int indexAddr = cursor.getColumnIndex( SmsReceiver.ADDRESS );
int indexDate = cursor.getColumnIndex( SmsReceiver.DATE );
if ( indexBody < 0 || !cursor.moveToFirst() ) return;
String sender = "";
String number = "";
String message = "";
String type = "";
do {
sender = "";
message = "";
type = "";
number = cursor.getString( indexAddr );
if (getContactDisplayNameByNumber(cursor.getString( indexAddr )).equals(""))
sender = cursor.getString( indexAddr );
else
sender = getContactDisplayNameByNumber(cursor.getString( indexAddr ));
message = cursor.getString( indexBody );
SQLiteDatabase db_read = dbHelper.getReadableDatabase();
Cursor c = db_read.query(dbHelper.USER_TABLE, null, "number like " + number , null, null, null, null);
if (c.moveToFirst())
//fiend...
else {
Pattern pattern = Pattern.compile("[0-9]");
Matcher matcher = pattern.matcher(sender);
boolean look = matcher.lookingAt();
if (look)
type = "1";
else
type = "0";
SQLiteDatabase db_whrite = dbHelper.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("name", sender);
cv.put("number", number);
cv.put("msg", message);
cv.put("date", cursor.getString( indexDate ));
cv.put("type", type);
db_whrite.insert(dbHelper.USER_TABLE, null, cv);
db_whrite.close();
}
c.close();
db_read.close();
}
}
while( cursor.moveToNext() );
cursor.close();
dbHelper.close();
}
read and fill...
public void UpdateTableRows() {
SMSDataCollection = new ArrayList<HashMap<String,String>>();
HashMap<String,String> map = null;
String message = "";
SQLiteDatabase db_read = dbHelper.getReadableDatabase();
Cursor c = db_read.query(dbHelper.USER_TABLE, null, null, null, null, null, null);
prmax = c.getCount();
cnt = 0;
pbCount.setMax(prmax-1);
pbCount.setProgress(0);
int i = 0;
if (c.moveToFirst()) {
do {
message = c.getString(3);
if (!(message.equals(""))) {
if ((message.substring(0, 2).equals("SM")) && (message.length()>6)) {
try {
String CutMsg = message.substring(message.indexOf('|')+1, message.length());
String key = message.substring(2, message.indexOf('|'));
Pattern pattern = Pattern.compile("[0-9]");
Matcher matcher = pattern.matcher(key);
boolean look = matcher.lookingAt();
if (look)
message = StringCryptor.decrypt(CutMsg, Integer.parseInt(key));
} catch (Exception e) {
e.printStackTrace(); }
} else
message = StringCryptor.decrypt(message, uPassword);
}
if (message.length() > 25)
message = message.substring(0, 24) + "...";
map = new HashMap<String,String>();
map.put(KEY_SENDER, c.getString(1));
map.put(KEY_NUMBER, c.getString(2));
map.put(KEY_MESS, message);
if (c.getString(4).equals("0"))
map.put(KEY_ICON, "person_icon_a");
else
map.put(KEY_ICON, "person_icon_f");
SMSDataCollection.add(map);
h.post(updateProgress);
} while (c.moveToNext());
}
c.close();
db_read.close();
dbHelper.close();
final BinderData bindingData = new BinderData(this,SMSDataCollection);
list.post(new Runnable(){
public void run() {
list = (ListView) findViewById(R.id.SMSList);
list.setAdapter(bindingData);
list.setEnabled(true);
//pbCount.setVisibility(View.GONE);
pbRound.setVisibility(View.GONE);
img_update.setVisibility(View.VISIBLE);
}
});
}
I am sending messages using android SmsManager.sendTextMessage(..)
but while on reading the SMS content provider columns, I am getting the type column value 1 which should be 2 for sent messages and even on device default messaging app, my sent messages are showing as Received.
The code I am using to send the messages is
public static final String SMS_URI = "content://sms";
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(address.get(i), null, messagetosend, null, null);
ContentResolver contentResolver = getContentResolver();
ContentValues values = new ContentValues();
values.put(ADDRESS, address.get(i));
values.put(BODY, messagetosend);
contentResolver.insert(Uri.parse(SMS_URI), values);
And I am printing the values on Logcat with this piece of code:
Uri allMessages = Uri.parse("content://sms/");
//Cursor cursor = managedQuery(allMessages, null, null, null, null); Both are same
Cursor cursor = this.getContentResolver().query(allMessages, null, null, null, null);
while (cursor.moveToNext()) {
for (int i = 0; i < cursor.getColumnCount(); i++) {
Log.d(cursor.getColumnName(i) + "", cursor.getString(i) + "");
}
Log.d("One row finished", "**************************************************");
}
Try to change
public static final String SMS_URI = "content://sms";
to
public static final String SMS_URI = "content://sms/sent";
and you could also add
values.put("type", 2);
How can I search the sms inbox and show latest message from a special number. For example search for "999999999" and show last message received from this number. Is any way to do this?
I have use this code to return the count of messages my inbox
TextView view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view = (TextView) findViewById(R.id.textView1);
final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
Cursor c = getContentResolver().query(SMS_INBOX, null, null, null, null);
int unreadMessagesCount = c.getCount();
c.deactivate();
view.setText(String.valueOf(unreadMessagesCount));
If you only want the last message sent by a specific number use this:
final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(SMS_INBOX, null, "address = ?",
new String[] {"9999999999"}, "date desc limit 1");
if(cursor.moveToFirst()) {
// Do something
Log.v("Example", cursor.getString(cursor.getColumnIndex("body")));
}
cursor.close();
The second answer to How many database columns associated with a SMS in android? is a great reference for different columns in an SMS.
try as:
final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
Cursor c = getContentResolver().query(SMS_INBOX,null,null, null,"DATE desc");
if(c.moveToFirst()){
for(int i=0;i<c.getCount();i++){
String body= c.getString(c.getColumnIndexOrThrow("body")).toString();
String number=c.getString(c.getColumnIndexOrThrow("address")).toString();
if(number=="999999999")
{
//get message body here
break;
}
else
c.moveToNext();
}
}
c.close();
I want to read the message body of a new incoming SMS in android, programmatically.
I tried something but that doesn't return any contents:
Uri uri = Uri.parse("content://sms/inbox");
ContextWrapper context = null;
Cursor c = context.getContentResolver().query(uri, null, null ,null,null);
String body = null;
String number=null;
if(c.moveToFirst()) {
body = c.getString(c.getColumnIndexOrThrow("body")).toString();
number = c.getString(c.getColumnIndexOrThrow("address")).toString();
}
c.close();
I have posted some sample programs about this on my class website.
Here is the example Read SMS Example
Here is a snippet of code. Basically your can register a broadcast receiver to listen for SMS_Receive and check out the following.
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("mySMS");
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
SmsMessage sms = SmsMessage.createFromPdu((byte[])pdus[0]);
Log.i("mobile.cs.fsu.edu", "smsActivity : SMS is <" + sms.getMessageBody() +">");
//strip flag
String message = sms.getMessageBody();
while (message.contains("FLAG"))
message = message.replace("FLAG", "");
TextView tx = (TextView) findViewById(R.id.TextBox);
tx.setText(message);
} else
Log.i("mobile.cs.fsu.edu", "smsActivity : NULL SMS bundle");
Below is the piece of code which read the incoming message and display in the list view, don' forget to add the permission in manifest file:
<uses-permission android:name="android.permission.READ_SMS"/>
Here the code:
listitem=(ListView)findViewById(R.id.ListView);
Uri mSmsQueryUri = Uri.parse("content://sms/inbox");
List<String> messages = new ArrayList<String>();
Cursor cursor = null;
try {
cursor = getContentResolver().query(mSmsQueryUri, null, null, null, null);
if (cursor == null) {
Log.i(TAG, "cursor is null. uri: " + mSmsQueryUri);
}
for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
final String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
messages.add(body);
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
} finally {
cursor.close();
}
listitem.setAdapter(new ArrayAdapter<String>(ReadMessage.this, android.R.layout.simple_list_item_1,messages));
A very easy solution would be to use this SMS Parser library:
https://github.com/adorsys/sms-parser-android
compile 'de.adorsys.android:smsparser:0.0.3'
Using it you can either read the whole message, or specific parts of the incoming message. You can also set the phone numbers from which the message will be coming.
If you need more info about how it works or its usage check the github repository I listed above.
Here in this example i'll demonstrate you that how to read the recent received(incoming) sms from inbox and to show it in textview.
fstmsgBtn.setOnClickListener(new OnClickListener()
{ public void onClick(View v)
{
Uri my_uri = Uri.parse("content://sms/inbox");
Cursor readFstSms =v.getContext().getContentResolver().query(my_uri, null, null ,null,null);
if(readFstSms.moveToFirst())
{
String msg_body = c.getString(c.getColumnIndexOrThrow("body")).toString();
//String sender_number = c.getString(c.getColumnIndexOrThrow("address")).toString();
readtxt.setText(msg_body);
}
readFstSms.close();
}
});
listitem=(ListView)findViewById(R.id.list_view);
Uri mSmsQueryUri = Uri.parse("content://sms/inbox");
List<String> messages = new ArrayList<String>();
Cursor cursor = null;
try {
cursor = getContentResolver().query(mSmsQueryUri, null, null, null, null);
if (cursor == null) {
// Log.i(TAG, "cursor is null. uri: " + mSmsQueryUri);
}
for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
final String body = cursor.getString(cursor.getColumnIndexOrThrow("body")).toString();
final String sender_no= cursor.getString(cursor.getColumnIndexOrThrow("address")).toString();
final String date= cursor.getString(cursor.getColumnIndexOrThrow("date"));
final String type =cursor.getString(cursor.getColumnIndexOrThrow("type"));
messages.add(body);
messages.add(sender_no);
messages.add(date);
messages.add(type);
}
} catch (Exception e) {
//Log.e(TAG, e.getMessage());
} finally {
cursor.close();
}
listitem.setAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,messages));
}
}