Receiving SMS messages in my app - java

I am creating an app that receives SMS text messages, I have created a class that extends BroadcastReceiver to receive and display SMS messagesin a toast within the app. I have also added permissions too my manifest along with the declaration of the receiver. The problem is it still does not seem to display the message. It will only appear on the top bar as a notification. Hopefully someone will be able to see where i am going wrong. Do i have to have some code in my mainactivity in order to display the message?? or should it display in my all my activities straight from the receiver clas?? code below:
UPDATE
I ended up deleting my receiver and recreating everything, now it seems to work fine
SmsReceiver.java:
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras ==null)
return;
//toast
Toast.makeText(context, "Received", Toast.LENGTH_LONG).show();
Object[] pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage SMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = SMessage.getOriginatingAddress();
String body = SMessage.getMessageBody().toString();
Intent in = new Intent("SmsMessage.intent.MAIN").putExtra("get_msg", sender+":"+body);
context.sendBroadcast(in);
this.abortBroadcast();
}
}
}

The problem is it still does not seem to display the message. It will only appear on the top bar as a notification
do you know what is - Ordered Broadcast?
in case you don't know - it's a broadcast that receives synchronously (one after another) by all receivers that registered for this broadcast. you can set in the manifest receiver deceleration a priority , and each one of the receivers can control if the broadcast will pass on in the priorities chain to additional registered receivers by using the aboartBroadcast() method.
what's to this and receiving SMS? - the system sends ordered broadcast when SMS receives. if your receivers priority is lower then the "default SMS app" priority - then what usually happens is that the application that got the broadcast first will cancel the broadcast, and you'll never receives it.
to get the broadcast before the default SMS application you have to declare your receiver with high priority (providing priority = 1000 should do the trick).
without providing priority - it's automatically set to zero.
you can have a look on this example - How Can i INTERCEPT an Incoming SMS With A specific Text
also make sure you declared the permission to RECEIVE_SMS in the manifest

Try starting again and setting up your receiver like so....
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras ==null)
return;
//toast
Toast.makeText(context, "Received", Toast.LENGTH_LONG).show();
Object[] pdus = (Object[]) extras.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage SMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = SMessage.getOriginatingAddress();
String body = SMessage.getMessageBody().toString();
Intent in = new Intent("SmsMessage.intent.MAIN").putExtra("get_msg", sender+":"+body);
context.sendBroadcast(in);
this.abortBroadcast();
}
}
}

#Override
public void onReceive(Context context, Intent arg1) {
SmsMessage msgs[] = getMessagesFromIntent(arg1);
for (int i = 0; i < msgs.length; i++) {
SmsMessage mesg = msgs[i];
Toast toast = Toast.makeText(context, mesg.getDisplayMessageBody(), Toast.LENGTH_LONG);
toast.show();
}
}

public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
// retrieve the SMS message received ::
Object[] pdus = (Object[]) extras.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
str += "SMS from : " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
// Toast to display SMS ::
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
// Send SMS ::
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage("put your phoneNumber(emulatorPort)", null, str, null, null);
}
}
}
--
Have nice time !
Don't forget to add permissions !

Related

Automatically reply to Message recieved by Broadcastreciever

Good day everyone.
I would like to make an application which replies to received SMS automatically.
For example.
Jon Doe sends me - "Hi", Application gets the message body, checks it with my database where I have a potential response:
ID | Text | Potential Answer
01 | Hi | Hello how are you?
and Application sends the Potential response.
So far what I have achieved -
App receives the Message, checks it with the database ( using Like '%') and gets the correct "Potential Answer" Column and passes it as message text body, but to send it I am using a button.
My Reciever is a sperate file class
public class MyReceiver extends BroadcastReceiver {
public static String textSmsbody="";
private static final String TAG=MyReceiver.class.getSimpleName();
public static final String pdu_type="pdus";
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onReceive(Context context, Intent intent) {
// Get the SMS message.
Bundle bundle = intent.getExtras();
SmsMessage[] msgs;
String strMessage = "";
String format = bundle.getString("format");
// Retrieve the SMS message received.
Object[] pdus = (Object[]) bundle.get(pdu_type);
if (pdus != null) {
// Check the Android version.
boolean isVersionM =
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
// Fill the msgs array.
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
// Check Android version and use appropriate createFromPdu.
if (isVersionM) {
// If Android version M or newer:
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
} else {
// If Android version L or older:
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
// Build the message to show.
String a=msgs[i].getMessageBody();
textSmsbody=msgs[i].getMessageBody();
if (a.contains("?")) {
strMessage=msgs[i].getOriginatingAddress();
// strMessage += " :" + msgs[i].getMessageBody() + "\n";
}
else {
strMessage=a;
// strMessage += "SMS from" + msgs[i].getOriginatingAddress();
// strMessage += "ELSE:" + msgs[i].getMessageBody() + "\n";
}
// Log and display the SMS message.
Log.d(TAG, "onReceive: " + strMessage);
Toast.makeText(context, strMessage, Toast.LENGTH_LONG).show();
}
}
}
}
Sending method is in my MainActivity.
public void smsSendMessage(View view) {
databaseSearch();
// Set the destination phone number to the string in editText.
String destinationAddress = "2020";
// Find the sms_message view.
// Get the text of the SMS message.
String smsMessage = sendingText;
// Set the service center address if needed, otherwise null.
String scAddress = null;
// Set pending intents to broadcast
// when message sent and when delivered, or set to null.
PendingIntent sentIntent = null, deliveryIntent = null;
// Use SmsManager.
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage
(destinationAddress, scAddress, smsMessage,
sentIntent, deliveryIntent);
}
In layout I have a button which calls smsSendMessage () ;
My question is how I can make it automatically without button.
When the phone receives a message, the app shall check it with the database and send it by itself.
Please tell me if you need to see my Manifest file, or databasehelper.
Using JobService should be a suitable option in your case.
Create a JobService class like that
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ExampleJobService extends JobService {
#Override
public boolean onStartJob(JobParameters params) {
//send a message
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return true;
}
}
Also Declare In your Manifest
<service
android:name=".ExampleJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
Now in your Receiver, you can start it like that
ComponentName componentName = new ComponentName(context, ExampleJobService.class);
PersistableBundle bundle = new PersistableBundle();
bundle.putLong("lat", lat);
bundle.putLong("lon", lon);
JobInfo jobInfo = new JobInfo.Builder(0, componentName)
.setExtras(bundle)
.build();
For more details about JobServices https://www.vogella.com/tutorials/AndroidTaskScheduling/article.html

How to Filter/Extract Code from SMS (Android)

So i'm working on a WhatsApp like verification system where user inputs the code received via sms and code is sent back to the server..yada yada ..all that basic stuff.
My dilemma is that i have received and read the sms correctly. How do i filter the body so that that it passes the number (not phone number but verification code) to the editText automatically. I'm trying to avoid users having to enter the verification code manually. Lemme show some code below.
public void processReceive(Context context, Intent intent){
Bundle bundle = intent.getExtras();
if(bundle == null){
return;
}
Object[] objectArray = (Object[])bundle.get("pdus");
for(int i = 0; i < objectArray.length; i++){
SmsMessage smsMsg = SmsMessage.createFromPdu((byte[])objectArray[i]);
String smsBody = smsMsg.getMessageBody();
Toast.makeText(context, smsBody, Toast.LENGTH_SHORT).show();
}
}
//In the code above, my broadcastReceiver receives the sms and i can display the body in a toast. The sms goes something like this: "Your verification code: 12345".
How do i get just the code from the sms and send its value to and editText programmatically like WhatsApp does.
number = (EditText) findViewById(R.id.number);
Thank you. You input is greatly appreciated
Try this it may be help to you
public static String GENERAL_OTP_TEMPLATE = "Your verification code: (.*).";
SmsMessage[] message = new SmsMessage[objectArray.length];
for (int i = 0; i < objectArray.length; i++) {
message[i] = SmsMessage.createFromPdu((byte[]) objectArray[i]);
}
Pattern generalOtpPattern = Pattern.compile(GENERAL_OTP_TEMPLATE);
Matcher generalOtpMatcher = generalOtpPattern.matcher(message[0].getMessageBody().toString());
if (generalOtpMatcher.find()) {
String otp = generalOtpMatcher.group(1);
number.setText(otp);
}
You can just use Split function to get your last 5 numbers :
String[] splited = body.split(":");
String mylastnum= splited[1];
number.settext(mylastnum);
hope it help !
register Broad cast Receiver in android manifest using below mention code.
<!-- SMS Receiver -->
<receiver android:name=".receiver.SmsReceiver">
<intent-filter android:priority="99999">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
Create Broad Cast Receiver using below mention code.
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
Object[] pdusObj = (Object[]) bundle.get("pdus");
for (Object aPdusObj : pdusObj) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) aPdusObj);
String senderAddress = currentMessage.getDisplayOriginatingAddress();
String message = currentMessage.getDisplayMessageBody();
Log.e(TAG, "Received SMS: " + message + ", Sender: " + senderAddress);
// if the SMS is not from our gateway, ignore the message
if (!senderAddress.toLowerCase().contains(Config.SMS_ORIGIN.toLowerCase())) {
Log.e(TAG, "SMS is not for our app!");
return;
}
// verification code from sms
String verificationCode = getVerificationCode(message);
Log.e(TAG, "OTP received: " + verificationCode);
Intent hhtpIntent = new Intent(context, HttpService.class);
hhtpIntent.putExtra("otp", verificationCode);
context.startService(hhtpIntent);
}
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
Parse Verification Code that come through SMS.
private String getVerificationCode(String message) {
String code = null;
int index = message.indexOf(Config.OTP_DELIMITER);
if (index != -1) {
int start = index + 2;
int length = 6;
code = message.substring(start, start + length);
return code;
}
return code;
}

How to close 1 Activity after the Launch of other from Android Service Class

I have created a service which launch Activity after receiving SMS from certain numbers.
There are 2 Activities Success and Failure.
Both Activities opens successfully only 1 time, On second iteration, when i send SMS again, it does not effect Activity Screen.
It remains open the current Activity screen and does not change it based on the condition.
I searched this on net and found various solution, but nothing seems working here, I tried to change flags, but it only allows 1 flag from service class, and if i choose other Flags it gives me following error message.
StartActivity from outsite an activity context requires the FLAG_ACTIVITY_NEW_TASK flag
This is the service class i have written. Kindly check this and guide me what i am doing wrong here.
Thanks
public class IncomingSms extends BroadcastReceiver {
final SmsManager sms = SmsManager.getDefault();
int duration = Toast.LENGTH_LONG;
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
final Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
String phoneNumber = currentMessage.getDisplayOriginatingAddress();
String senderNum = phoneNumber;
String message = currentMessage.getDisplayMessageBody();
if(senderNum.equals("345"))
{
Intent successScreen= new Intent(context, SuccessActivity.class);
successScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(successScreen);
}
else if(senderNum.equals("3450") || senderNum.equals("3451") || senderNum.equals("3452")){
Intent alertActivity = new Intent(context, FailureActivity.class);
alertActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(alertActivity);
}
Try to replace your code with this code:
if(senderNum.equals("345"))
{
Intent successScreen= new Intent(context, SuccessActivity.class);
successScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
successScreen.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
successScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
context.startActivity(successScreen);
}
else if(senderNum.equals("3450") || senderNum.equals("3451") || senderNum.equals("3452")){
Intent alertActivity = new Intent(context, FailureActivity.class);
alertActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
successScreen.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
successScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
context.startActivity(alertActivity);
}

The content of the Intent in the BroadcastReceiver

I am learning how to send SMS in android, have seen the code as below:
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;
String str = “”;
if (bundle != null)
{
//---retrieve the SMS message received---
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]);
str += “SMS from “ + msgs[i].getOriginatingAddress();
str += “ :”;
str += msgs[i].getMessageBody().toString();
str += “\n”;
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
Now my question is how do I know what are the contents of Intent object that are passed into onReceive function? As below:
Object[] pdus = (Object[]) bundle.get(“pdus”);
How do I know there is a "pdus" key in the bundle object?
I can't find any clue in the API doc, anyone know where is the related information located?
I don't only want to know what the SMS intent pass into onReceive function, but also the other system related Intent, but I can't locate any related information in the API doc. I wonder does the information really exist?
You can check if the bundle contains a Key value pair with key pdus using bundle.containsKey("pdus") which returns true if there are any Protocol Data Units (PDUs which in your case are SMSes).
So, the check for processing the PDUs should be if (bundle != null && bundle.containsKey("pdus"))
I swiped this code from this page: http://davanum.wordpress.com/2007/12/15/android-listen-for-incoming-sms-messages/
SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
It looks like Android might already have a mechanism to get your messages. Is this what you are looking for?
public void onClick(View v)
{
//sendSMS(“5556”, “Hello my friends!”);
Intent i = new
Intent(android.content.Intent.ACTION_VIEW);
i.putExtra(“address”, “5556; 5558; 5560”);
i.putExtra(“sms_body”, “Hello my friends!”);
i.setType(“vnd.android-dir/mms-sms”);
startActivity(i);
}
How can we check all those possible key when we want to pass into the intent for invoking the SMS application as above? I hope they are documented somewhere.

BroadcastReceiver not triggered for SMS_RECEIVED on Galaxy S II

I have the latest update for my Samsung Galaxy S2 and now my application stop working (App don't receive sms). I have SMSReceiver extends from BroadcastReceiver with SMS_RECEIVED action.
It looks like this:
private class SMSReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context cntxt, Intent intent) {
Log.i(TAG, "New broadcast receiver");
SharedPreferences settings = getSharedPreferences(TAG, 0);
if (settings.getString("authCode", "").equals("")) {
Log.i(TAG, "Get sms");
if (intent.getAction().toString().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] 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]);
}
if (messages.length > -1) {
Log.i(TAG, "Read sms");
}
}
}
}
}
I register BroadcastReceiver like this:
mSmsReceiver = new SMSReceiver();
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(100000);
registerReceiver(mSmsReceiver, filter);
Everything works on HTC Desire or Desire Z and android emulator. On Galaxy S2 my SMSReceiver don't receive any Intent when SMS came. I tried all solution but it didn't have any effect.
Probably a issue with the latest version of GoSMS
Had the same issue with the "android.net.conn.CONNECTIVITY_CHANGE" action on the Galaxy s2. Couldn't receive reconnection intent when the Broadcast receiver was registered in the code.
Registering the broadcast receiver in the manifest was the solution for me.

Categories