Is it possible to extract the user data header from an sms message? if yes, any ideas on how to proceed with it?
also, is it possible to make changes to the data header before sending an sms?
the source code for receive a sms goes:
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
Log.i(LOG_TAG, "onReceive");
if (extras == null)
return;
Object[] pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]);
String fromAddress = message.getOriginatingAddress();
String messageBody = message.getMessageBody().toString();
Log.i(LOG_TAG, "From: " + fromAddress + " message: " + messageBody);
addNotification(context, fromAddress, messageBody);
}
}
so,it was byte[] type, so if you have a good knowledge of UDH which is described in User Data Header, I think it is possible.
Related
I am developing an android app which gets the SMS using broadcast receiver when its comes. Here is the code:
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs;
if (bundle != null) {
//---retrieve the SMS message received---
try {
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]);
String address = msgs[i].getOriginatingAddress();
String body = msgs[i].getMessageBody();
}
} catch(Exception e) {
Log.d("Exception caught",e.getMessage());
}
}
}
Problem is that few messages I receive comes in two or three parts. I don't know how to join these parts of messages. How can I detect that the first part of message needed to be combined with the next part message.
First Part: Your airtel mobile ********** online recharge txn ID ************ o
Second Part: f Rs *** has been initiated. Please keep the txn id for future refe
Third Part: rence.
You need to add message body(parts).
change this
String body = msgs[i].getMessageBody();
to
String body += msgs[i].getMessageBody();
The problem is inside your loop try this out, you should be fine
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null) {
// Retrieve the SMS Messages received
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
// For every SMS message received
for (int i=0; i < msgs.length; i++) {
// Convert Object array
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
// Sender's phone number
str += "SMS from " + msgs[i].getOriginatingAddress() + " : ";
// Fetch the text message
str += msgs[i].getMessageBody().toString();
str += "\n";
}
// Display the entire SMS Message
Log.d(TAG, str);
}
I have built an SMS messaging app, which both sends and receives text messages. In MainActivity, I have a two-dimensional array of people's names and phone numbers, and in my sending class, I have a for loop which sends the same message to all of the recipients by going through each of the numbers:
for (i=0; i<names.length; i++) {
phoneNo = names[i][2] + names[i][3];
sendMessage(phoneNo, message);
}
private void sendMessage(String phoneNo, String message) {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, message, null, null);
Toast.makeText(getApplicationContext(), "SMS sent", Toast.LENGTH_LONG).show();
}
catch (Exception e) {
Toast.makeText(getApplicationContext(), "SMS failed. Please try again!", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
When I send a message through the app, I can see very clearly from my own Samsung messaging app that the same message gets sent to each of the numbers in the list, which is perfect.
This is my shortened receiver class:
public class Receiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
SmsMessage[] smgs = null;
String infoSender = "";
String infoSMS = "";
if (extras != null) {
// Retrieve the sms message received
Object[] pdus = (Object[]) extras.get("pdus");
smgs = new SmsMessage[pdus.length];
for (int i = 0; i < smgs.length; i++) {
smgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
infoSender += smgs[i].getOriginatingAddress();
infoSMS += smgs[i].getMessageBody().toString();
}
}
I have found that despite the message being sent out once to each recipient, some recipients (with this app) receive it more than once consecutively. Hence, I suspected that there was something wrong with my receiver code, which is seemingly treating one received message as several consecutive received messages. This is not a consistent problem, as different people receive the consecutive messages at different times.
However, what I've also found is that if I hardcode phoneNo in the sending class to just one phone number, or if I have only one phone number in the array in MainActivity, then this problem doesn't occur. The message still gets sent out once to that one phone number only, but the receiver will always receive it just once as intended.
I am so confused by this now, so can somebody please give some suggestions as to what I could try? Literally in the last minute, I thought that it could be a problem with createFromPdu being deprecated? If so, please advise how to change my receiver code, as I couldn't find anything which resembles my current code too much.
Many thanks in advance:-)
Do like this you are making mistake check below code.
if (bundle != null) {
// get sms objects
Object[] pdus = (Object[]) bundle.get("pdus");
if (pdus.length == 0) {
return;
}
// large message might be broken into many
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());
}
senderNum = messages[0].getOriginatingAddress();
message = sb.toString();
}
Update: To check default app
public class Receiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
final String myPackageName = context.getPackageName();
if (Telephony.Sms.getDefaultSmsPackage(context).equals(
myPackageName)) {
// you are default
Bundle extras = intent.getExtras();
SmsMessage[] smgs = null;
String infoSender = "";
String infoSMS = "";
if (extras != null) {
// Retrieve the sms message received
Object[] pdus = (Object[]) extras.get("pdus");
smgs = new SmsMessage[pdus.length];
for (int i = 0; i < smgs.length; i++) {
smgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
infoSender += smgs[i].getOriginatingAddress();
infoSMS += smgs[i].getMessageBody().toString();
}
}
} else {
// you are not ignore
}
} else {
// for below KitKat do like normal
Bundle extras = intent.getExtras();
SmsMessage[] smgs = null;
String infoSender = "";
String infoSMS = "";
if (extras != null) {
// Retrieve the sms message received
Object[] pdus = (Object[]) extras.get("pdus");
smgs = new SmsMessage[pdus.length];
for (int i = 0; i < smgs.length; i++) {
smgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
infoSender += smgs[i].getOriginatingAddress();
infoSMS += smgs[i].getMessageBody().toString();
}
}
}
}
}
i hope this modication of your code base will help solve your problem
public class Receiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
SmsMessage[] smgs = null;
String infoSender = "";
String infoSMS = "";
if (extras != null) {
try{
// Retrieve the sms message received
Object[] pdus = (Object[]) extras.get("pdus");
if(pdus.length==0){return;}
smgs = new SmsMessage[pdus.length];
for (int i = 0; i < smgs.length; i++) {
smgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
infoSMS += smgs[i].getMessageBody();
}
infoSender = smgs[0].getOriginatingAddress();
}catch(Exception e){
e.printStackTrace ();
}
}
}
}
I'm trying to confirm a user's phone number by sending the a text to the user's phone then getting it and matching the number the user gave and the number the text just came from...problem is that although the text matches 100%, I've confirmed in a lot of ways, the byte arrays do not match therefore the "phone numbers" do not match, and the confirmation isn't possible. Is this a real thing: values sent via a network changing byte arrays?
Text sent:
String user_phone_number = phoneNumber.getText().toString();
String number = "" + user_phone_number;
String verificationCode = "717345221";
String message = verificationCode + user_phone_number;
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(number, null, message, null, null);
Text recieved:
if (intent.getAction()
.equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String msgFrom;
if (bundle != null) {
try {
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]);
msgFrom = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
String verificationCode = "717345221";
if (msgBody.startsWith(verificationCode)) {
msgBody = msgBody.substring(verificationCode
.length());
if (msgBody.trim() == msgFrom.trim()) {
showCorrectNotification(context);
try {
Intent o = new Intent(context,
ProfileInformation.class);
o.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(o);
} catch (Exception e) {
e.toString();
}
}
}
}
You cannot compare Strings like this:
msgBody.trim() == msgFrom.trim()
You should use:
msgBody.trim().equals(msgFrom.trim())
Anyone know how to send non-printing characters via SMS in Android?
I tried the following code but it does not work...The recipient will not receive the correct string.
String msg = "Testing special char" +(char) 3;
sendSMS(num,msg);//defined method
Or is there any other way to insert some kind of tags into a SMS, so that the recipient can perform some actions accordingly?
By default you send sms text messages in ascii format. Try to send binary SMS.
As there is an Android tag on the question, here is what I found while researching the topic (code from codetheory.in).
Send:
// Get the default instance of SmsManager
SmsManager smsManager = SmsManager.getDefault();
String phoneNumber = "9999999999";
byte[] smsBody = "Let me know if you get this SMS".getBytes();
short port = 6734;
// Send a text based SMS
smsManager.sendDataMessage(phoneNumber, null, port, smsBody, null, null);
Receive:
public class SmsReceiver extends BroadcastReceiver {
private String TAG = SmsReceiver.class.getSimpleName();
public SmsReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
// Get the data (SMS data) bound to intent
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null){
// Retrieve the Binary SMS data
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
// For every SMS message received (although multipart is not supported with binary)
for (int i=0; i<msgs.length; i++) {
byte[] data = null;
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "Binary SMS from " + msgs[i].getOriginatingAddress() + " :";
str += "\nBINARY MESSAGE: ";
// Return the User Data section minus the
// User Data Header (UDH) (if there is any UDH at all)
data = msgs[i].getUserData();
// Generally you can do away with this for loop
// You'll just need the next for loop
for (int index=0; index < data.length; index++) {
str += Byte.toString(data[index]);
}
str += "\nTEXT MESSAGE (FROM BINARY): ";
for (int index=0; index < data.length; index++) {
str += Character.toString((char) data[index]);
}
str += "\n";
}
// Dump the entire message
// Toast.makeText(context, str, Toast.LENGTH_LONG).show();
Log.d(TAG, str);
}
}
}
using the following code i can abortBroadcast() from my broadcastreciver and bundle the sms and address to my activity, what i am trying to do is abortBroadcast() from my activity,
so my activity checks if the address is the same as one of my stored addresses and then abortBroadcast(), but i cant find a way to do this, is it in any way possible to abortBroadcast() from my activity or any way of checking details from an activity then allow the broadcastreciver to abort?
heres my code:
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
// a notification message
String messages = "";
if (extras != null) {
Object[] smsExtra = (Object[]) extras.get("pdus");
for (int i = 0; i < smsExtra.length; ++i) {
SmsMessage sms = SmsMessage.createFromPdu((byte[]) smsExtra[i]);
String body = sms.getMessageBody().toString();// sf
String address = sms.getOriginatingAddress();
messages += "SMS from " + address + " :\n";
messages += body + "\n";
}
Intent data = new Intent(context, Details.class);
data.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
for (int i = 0; i < smsExtra.length; ++i) {
// get sms message
SmsMessage sms = SmsMessage.createFromPdu((byte[]) smsExtra[i]);
String body = sms.getMessageBody().toString();
String address = sms.getOriginatingAddress().toString();
// bundle
Bundle bundle1 = new Bundle();
bundle1.putString("title", body);
bundle1.putString("title2", address);
data.putExtras(bundle1);
context.startActivity(data);
abortBroadcast();
}
}
}
}
in my activity:
Bundle bundle1 = this.getIntent().getExtras();
String title = bundle1.getString("title");
String title2 = bundle1.getString("title2");
((EditText) findViewById(R.id.ettext)).setText(title);
((EditText) findViewById(R.id.etnumber)).setText(title2);
mSms =(TextView)findViewById(R.id.tvsms);
String sms = mSms.getText().toString();
if (sms.equals(title2))
abortBroadcast();????
I think this post is similar enough to your problem unless I am misunderstanding. You are trying to pass data between your broadcastReceiver and your activity, correct? This post is similar and I would agree with the first response - You should setup your broadcastReceiver as a sub-class of the activity
android communicate between activity and broadcast receiver
Hope it helps, best!