I have an application, which has to listen for specific SMS. So far easy.
But when I receive the message, it's multipart. Is there a proper way to receive the SMS as one message?
Now my activity starts two times, for each part of the sms. Should I concatenate the SMS by hand?
It may be useful to look at how gTalkSMS handles incoming SMS'es, as it appears to handle multipart messages correctly.
Bundle bundle = intent.getExtras();
Object[] pdus = (Object[]) bundle.get("pdus");
messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++)
{
messages[i] =
SmsMessage.createFromPdu((byte[]) pdus[i]);
}
SmsMessage sms = messages[0];
try {
if (messages.length == 1 || sms.isReplace()) {
body = sms.getDisplayMessageBody();
} else {
StringBuilder bodyText = new StringBuilder();
for (int i = 0; i < messages.length; i++) {
bodyText.append(messages[i].getMessageBody());
}
body = bodyText.toString();
}
} catch (Exception e) {
}
Shorter solution:
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
if (bundle != null) {
//---retrieve the SMS message received---
try {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
String msgBody = "";
String msg_from = "";
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
msg_from = msgs[i].getOriginatingAddress();
msgBody += msgs[i].getMessageBody();
}
} catch (Exception e) {
// Log.d("Exception caught",e.getMessage());
}
}
}
Yes you should concatenate the SMS by hand, but obviously you don't want to be starting up a new activity for each message segment.
I suggest setting your Activity's launchMode attribute to singleTask or singleInstance so that that doesn't happen.
Alternatively have your SMS's received by a Service, which will fire up a new Activity only once it has a complete message.
I am not aware of a way to recive a multipart message as once. But if you have the right intent-filter setup you get only one Intent for more than one SMS. In fact, the Intent can contain SMS from different senders and/or zero or more multipart SMS .
You could try this approach:
Add an SmsReceiver Class with intent-filter android.provider.Telephony.SMS_RECEIVED in the Manifest.
The classes onReceive Method will get an intent with a bundle of pdus. These pdu's can origin from different senders each and/or there can be more pdus from the same sender in case of a multipart text message, which you have to concatenate.
Related
My application uses some web services for performing actions in server and getting results from it. Now I want my app to work in offline mode. I have a sms panel that can handle sending and receiving messages to clients. So the thing I need is to listen to messages in client and respond to it if it has a special format. I know how to listen to incoming sms from code, here it is:
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// ---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
Log.d("checking", "sms received!");
String str = "";
if (bundle != null) {
// ---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
String sender = null;
String body = null;
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
sender = msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
body = msgs[i].getMessageBody().toString();
str += "\n";
}
// ---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
and it works properly. The thing here is I don't want my special messages appear in user inbox or even hide sms notification from him. Is this possible? Should I listen to all incoming messages?
update:
I assume that things are different in KitKat so any solution works in api 19 appreciated.
thanks in advanced.
Try abortBroadcast(); in your BroadcastReceiver
if (intent.getAction().equals(android.provider.Telephony.SMS_RECEIVED)) {
abortBroadcast();
}
i don't know if this works on KitKat or not.
I search so much for sms filter for hangout enabled android phones where I only found that this is not possible.
But there is one app as sms filter by Tsvetan Nachev which blocks sms from hangout and link for this app is : https://play.google.com/store/apps/details?id=com.nachev.apps.smsfilter
I tested on 4.1.2
So anybody know how does that happening in that app?
here is my code
if (intent.getAction().equals(SMS_RECEIVED))
{
Bundle bundle = intent.getExtras();
if (bundle != null)
{
Object[] pdus = (Object[]) bundle.get("pdus");
if (pdus.length == 0)
{
return;
}
SmsMessage[] messages = new SmsMessage[pdus.length];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < pdus.length; i++)
{
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
sb.append(messages[i].getMessageBody());
}
String sender = messages[0].getOriginatingAddress();
String message = sb.toString();
if(message.equals("something"))
{
abortBroadcast();
}
}
Thanks in advance.
You May look at this-Intercept Incoming SMS Message and Modify it What you need to do is check when message is came from hangout application it it contains in address or subject that is diff from other message format.For message abort may look the abortBroadcast(); method inside broadcast message receiver in android that receives intent for incoming message.Hope this Helps you.
I am working on an android project, that deals with device authentication via sms.
The problem I am facing is, when the authentication key is being sent, the receiving device gets a garbled text and not the original sent content.
I am using two instances of the emulator to test the code.
Here is the relevant code :
String MyPublic = "__key("+N.toString()+")yek__";
ArrayList<String> parts = smsmgr.divideMessage(MyPublic);
smsmgr.sendMultipartTextMessage(senderNumber, null, parts, null, null);
How ever when I am sending a single sms within 160 characters, then this problem isn't disappears.
Here is the code I am using to listen for incoming messages.
public void onReceive(final Context context, Intent intent) {
msgReceived = false;
Object[] pdus=(Object[])intent.getExtras().get("pdus");
Bundle bundle = intent.getExtras();
if (bundle != null) {
pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
SmsMessage sms = messages[0];
String body;
if (messages.length == 1 || sms.isReplace()) {
body = sms.getDisplayMessageBody();
} else {
StringBuilder bodyText = new StringBuilder();
for (int i = 0; i < messages.length; i++) {
bodyText.append(messages[i].getMessageBody());
}
body = bodyText.toString();
}
}
The message that is received when the 'Multi-part' thing is used is of this type :
The "HelloWorld" was sent as a single-part message(Non-Multipart) and the 3rd and second from below are parts of that multipart authentication key.
Need Help resolving this.
Regards
Priyabrata.
I'm having trouble receiving multiPartTextMessages.
My application divides and then sends messages part by part.
However, whenever a part is coming broadcastreceiver works.
I need to combine this part to get the original message.
How can I do it?
put a special text at the start of every part like #myTag_msg1_part1. In broadcast receiver check the special text of every message to know the partno, then accordingly you can join them.
This should help
#Override
public void onReceive(Context context, Intent intent) {
Log.d(ClassName, "received SMS");
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
// here is what I need, just combine them all :-)
final SmsMessage[] messages = new SmsMessage[pdus.length];
Log.d(ClassName, String.format("message count = %s", messages.length));
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
}
}// onReceive()
I can catch newly incoming SMS messages. But if that is a multipart message, my broadcast receiver receives all parts of the message at several times.
Is there a way to receive the whole message at one time - like default messaging app does?
Holy...!
After reading the Android source (this file), I realize that this is such a stupid question...
Here is my receiver:
#Override
public void onReceive(Context context, Intent intent) {
Log.d(ClassName, "received SMS");
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
// here is what I need, just combine them all :-)
final SmsMessage[] messages = new SmsMessage[pdus.length];
Log.d(ClassName, String.format("message count = %s", messages.length));
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
}
}// onReceive()
Oops... I was too lazy to look at my code. I already got all parts of the message at a time.