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.
Related
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.
So im making an app that uses sms to send data between two devices and am trying to get one to automaticly respond to the other. But the string getMessageBody() is returning isnt setting of the if statment to send the automatic message even tho the log output "(test)" seems to match the condition. I have added extra text to either side of the string in the log message to check for whitespace. Thanks in advance.
The code sending the message to be received.
SendSMS(inputNum.getText().toString(),"test");
The receiver code
public void onReceive(Context context, Intent intent)
{
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if(bundle != null)
{
Object[]pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for(int i = 0;i < msgs.length;i++)
{
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
originNumber = msgs[i].getOriginatingAddress();
messages = msgs[i].getMessageBody();
Log.e("Received Text", messages);
}
if(messages == "test")
SendSMS(originNumber, "auto send");
else
Log.e("else Text", "("+messages+")");
}
if(messages == "test")
String comparison in java need the equals method. With the == you will compare the address of message with the address of "test". Since those are differente String object the result will be false. Change it in:
if(messages.equals("test"))
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.
Since I am not able to compress a 256-byte long md5-like string within 160 characters, I decided to use Multi-part message in Android to divide the SMS into several parts and the receiver will listen the SMS then combine those messages.
I use the combination algorithm from here: Android - receiving long SMS (multipart)
And after a few testing I found that the SMS I sent was totally messed, though I encoded them with Base64 before sending.
Thinking the SMS is a 7-bit Encoding method I thought it might be the encoding problem.
But I have successfully sent Base 64 encoded message, but it was short and within 1 SMS.
My question is:
If it is a encoding problem, then why I can send a totally readable Base64 encoded messages within 160 characters, but cannot get a readable result when sending messages exceeding 160 characters?
I've attached my code here:
The string I intend to send:
static final String bigNum = "C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE428782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BFFAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83";
The Code
private void sendMsg (String phoneNum, String msg) {
SmsManager sms = SmsManager.getDefault();
ArrayList<String> parts = sms.divideMessage(msg);
sms.sendMultipartTextMessage(phoneNum, null, parts, null, null);
}
public void onStart() {
super.onStart();
final String bigNum64 = Base64.encodeToString(bigNum.getBytes(), 0);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendMsg("5554", bigNum64);
textView.setText(bigNum64);
}
});
}
public void onResume() {
super.onResume();
Bundle receiver = getIntent().getExtras();
if (receiver != null) {
String msg = receiver.getString("SMS");
textView.setText("Received" + msg);
}
}
}
The SMS Receiver:
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle bundle = intent.getExtras();
Object[] pdus = (Object[]) bundle.get("pdus");
SmsMessage[] messages = new SmsMessage[pdus.length];
String body = "";
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) {
}
Intent start = new Intent(context, SendLongSMSActivity.class);
start.putExtra("SMS", body);
start.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(start);
}
Thanks for your help!
Related Post: Any way to compress a 256 bytes "MD5-like" string into 160 bytes or less?
Even if I give a rather simple long string, like
"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
and no matter with or without Base64 encoding, the receiver cannot get the correct results.
UPDATE #2
When using real phone for testing, the receiver can receive correct message without base 64, it was due to the emulator garbled the text.
Question now closed.
Thanks for everyone who helps! And thanx #Dan
UPDATE:
The string "0123456789ABCDEF..." without base64, divided into 2 parts:
part [0] "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678"
part [1] "9ABCDEF0123456789ABCDEF"
Here's the divided base64 string of the "0123456789ABCDEF...:
part[0] "MDEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4\nOUFCQ0RFRjAxMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCQ0RFRjAx"
part[1] "\nMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlB\nQkNERUY=\n"
It appears that the sms divide is adding \n characters after every 77 characters and at the end, just strip those from your string and it will decode properly.
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.