I'm creating a simple Android application where I'm trying to intercept incoming SMS messages. The problem I am having is that the toast messages from the onReceive isn't showing up. Please help!
Thanks,
Isaiah Thompson
public class SMSR extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//Print Message
Toast.makeText(context,"Received Message Start",Toast.LENGTH_SHORT).show();
// Get the data (SMS data) bound to intent
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();
// Newline <img draggable="false" class="emoji" alt="🙂" src="https://s.w.org/images/core/emoji/72x72/1f642.png">
str += "\n";
}
}
//Print Message
Toast.makeText(context,"Received Message End",Toast.LENGTH_SHORT).show();
Toast.makeText(context,str,Toast.LENGTH_SHORT).show();
}
}
Try this
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
Toast.makeText(context, R.string.sent, Toast.LENGTH_SHORT).show();
}
});
Check out this answer
https://stackoverflow.com/a/11436473/6051131
also, make sure your priority (in the manifest file) is less than or equal 2147483647
Related
I'm building an application that should trigger a function when an SMS is received. I've used Broadcast Receivers and NotificationListeners before, but for this specific purpose, I need to register this Broadcast receiver. At this time, I'm unable to register it, and I can't quite tell why.
I've tried multiple answers to similar issues on stack overflow but for some reason, the Log.d that I'm using to troubleshoot right now will not print when I receive an SMS. I think I'm fundamentally misunderstanding the problem, although I'm not sure how.
Here is my SmsListener.java class:
public class SmsListener extends BroadcastReceiver {
private SharedPreferences preferences;
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
Log.d("Test","test");
}
}
}
Here is my Manifest:
<receiver android:name=".SmsListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Here is the onCreate() function of my activity that should be calling it:
BroadcastReceiver br = new SmsListener();
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(br,filter);
Thank you any help. I'm at a total loss.
This is Your Receiver Class-
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null) {
if (intent.getAction().equals(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]);
Log.e("Message Content : ", " == " + messages[i].getMessageBody());
Log.e("Message Content Body : ", " == " + messages[i].getDisplayMessageBody());
Log.e("Message recieved From", " == " + messages[0].getOriginatingAddress());
}
/*if (messages.length > -1) {
Log.e("Message recieved: "," == "+ messages[0].getMessageBody());
Log.e("Message recieved From"," == "+ messages[0].getOriginatingAddress());
}*/
}
}
}
}
In your fragment
val smsReciever = SmsReciever()
val smsIntentFilter = IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)
context?.registerReceiver(smsReciever, smsIntentFilter)
In your manifest
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
In your receiver
class SmsReciever : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val message = Telephony.Sms.Intents.getMessagesFromIntent(intent)
val content = message[0].displayMessageBody
Toast.makeText(context, content,
Toast.LENGTH_SHORT).show()
}
}
The onReceive() in my class listens for SMSs and sends an SMS in reply, everything is working fine but once. After sending SMS the app shuts down with the message "Unfortunately, yourApp has stopped". I want it to remain active. I wonder where I'm missing out. Thanks for help!
public class SMSReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED="android.provider.Telephony.SMS_RECEIVED";
private static final String TAG="SMSReceiver";
#Override
public void onReceive(Context context,Intent intent){
SmsManager smsManager=SmsManager.getDefault();
int i;
Toast.makeText(context,"Intent recieved",Toast.LENGTH_LONG).show();
Log.i(TAG,"Intent recieved: "+intent.getAction());
String messageContent="";
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
messageContent=messages[i].getMessageBody().toString();
}
if (messages.length > -1 && messageContent.charAt(8)=='#') {
Log.i(TAG, "Message recieved: " + messages[0].getMessageBody());
Toast.makeText(context, "Message received from victim: "+messageContent, Toast.LENGTH_LONG).show();
smsManager.sendTextMessage("+919032687185",null,"Request#",null,null);
//Toast.makeText(context, "SMS sent.",Toast.LENGTH_LONG).show();
/*for(i=0;i<7;i++){
MediaPlayer mediaPlayer=MediaPlayer.create(context, R.raw.fire_engine_siren_could_be_police_ambulance_etc);
mediaPlayer.start();
}*/
}
/*else if(messages.length > -1 && messageContent.charAt(6) == '#'){
Log.i(TAG, "Location from patrol" + messages[0].getMessageBody());
Toast.makeText(context, "Message received from ambulance: "+messageContent, Toast.LENGTH_LONG).show();
}*/
}
}
}
}
It seems like you're getting a java.lang.StringIndexOutOfBoundsException and my guess is the culprit is messageContent.charAt(8) because the logcat indicates length=8; index=8
Try using indexOf instead if finding this #'s location is necessary. Its a bit more flexible and won't throw exceptions at you.
I have a working application that uses a BroadcastReceiver to process incoming SMS messages. My question is what is the best way to do work on an incoming SMS? Currently I am launching a new thread to do the work, as shown below in the onReceive() method of my BroadcastReceiver.
#Override
public void onReceive(final Context ctx, Intent intent) {
if(intent.getAction().equals(ANDROID_SMS_DELIVER)) {
Bundle bundle = intent.getExtras();
if (bundle != null){
try{
Object[] pdus = (Object[]) bundle.get("pdus");
SmsMessage[] msgs = new SmsMessage[pdus.length];
for(int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
final String smsFrom = msgs[i].getOriginatingAddress();
final String smsBody = msgs[i].getMessageBody();
// Launch a thread to do work on the SMS
new Thread() {
public void run() {
// Work..
}
}.start();
}
} catch(Exception e){}
}
}
}
Is this the best way? Alternatively, should I be sending a broadcast to some other IntentService to do the work, or will this work just as well?
Thanks.
This is not the way to do it! The BroadcastReceiver will only be alive for 10 seconds (give or take). I have no clue what will happen with your thread.
The best way to do is use a IntentService. This Service is launched/started via an Intent and will shutdown itself when done.
My application has the following modules,
To collect users CB location code.
To save that in a database of user's choice, say for example my CB code is 465783 and I can save that as 'College' in my database.
To provide alarm feature, in this module I can give a text input say I give it as 'College' and when the Cell Broadcast is updated if the value college matches alarm is given out.
Now, in my below code I've achieved first 2 modules and also the required database entries, databases search etc, I'm not able to read the updated CB location value.
public class Alarm extends MainActivity {
public String str;
public void onReceive(Context context, Intent intent) {
//---get the CB message passed in---
Bundle bundle = intent.getExtras();
SmsCbMessage[] msgs = null;
str = "";
if (bundle != null) {
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsCbMessage[pdus.length];
for (int i=0; i<msgs.length; i++) {
msgs[i] = SmsCbMessage.createFromPdu((byte[])pdus[i]);
str += "CB " + msgs[i].getGeographicalScope() + msgs[i].getMessageCode() + msgs[i].getMessageIdentifier() + msgs[i].getUpdateNumber();
str += " :";
str += "\n";
}
}
}
EditText user_value;
Button startalarm;
Button stopalarm;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.third);
startalarm = (Button) findViewById(R.id.startalarm);
stopalarm = (Button) findViewById(R.id.stopalarm);
user_value = (EditText) findViewById(R.id.user_value);
final Ringtone ringtone;
ringtone = RingtoneManager.getRingtone(getBaseContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
startalarm.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
// TODO Auto-generated method stub
if(user_value.length()==0)
{
Toast.makeText(getBaseContext(), "Please enter a value.", Toast.LENGTH_LONG).show();
}
Toast.makeText(getApplicationContext(), "alarm set", Toast.LENGTH_LONG).show();
//I want my alarm event to be started from here whenever a new CB sms arrives.
SQLiteDatabase aa = openOrCreateDatabase("MLIdata", MODE_WORLD_READABLE, null);
Cursor c = aa.rawQuery("SELECT CblocationName FROM MLITable WHERE CblocationCode = '"+str+"'", null);
c.moveToFirst();
c.getString(c.getColumnIndex("CblocationName"));
String sas = user_value.getText().toString();
if(sas.equals(c.getString(c.getColumnIndex("CblocationName"))))
{
//here comes the alarm code
if(ringtone == null)
{
Log.d("Debug", "ringtone is null");
}
else
{
ringtone.play();
}
}
}
});
stopalarm.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
ringtone.stop();
}
});
}
}
Detailed Explanation : whenever a user enters a new tower location he gets the updated Cell Broadcast message from the tower, so when this cbsms arrives I need to start my event of retrieving the CB area code and compare it with my database of area codes (which obviously have corresponding area code names set by the user) and when there is a match between the user given area name's corresponding area code with my current area code an alarm needs to be started, here I'm not able to do detect the arrival of updated location.
If further explanation is required of my problem statement, please comment.
From the comments received below, I've deduced that I'd need a receiver class, I've created one for my widget which does the same function (Displays the Cb location code on the widget), Now I do not how to activate that in my app.
My WidgetReceiver.java
public class CbReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent) {
//---get the CB message passed in---
Bundle bundle = intent.getExtras();
SmsCbMessage[] msgs = null;
String str = "";
if (bundle != null) {
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsCbMessage[pdus.length];
for (int i=0; i<msgs.length; i++) {
msgs[i] = SmsCbMessage.createFromPdu((byte[])pdus[i]);
str += "CB " + msgs[i].getGeographicalScope() + msgs[i].getMessageCode() + msgs[i].getMessageIdentifier() + msgs[i].getUpdateNumber();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
abortBroadcast();
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
ComponentName thisWidget = new ComponentName(context,MyWidget.class);
remoteViews.setTextViewText(R.id.update,str);
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
}}
}
Help required.
Thank you.
Start your activity from your receiver on tower change. Use Intents to start your activity from receivers.
Ex: Refer this alarm example for above point, Alarm Example
Register your receiver in Android Manifest.xml.
Send a broadcast message from your receiver class also update your DB inside your receiver.
Catch the same in your activity. You can use Custom Broadcast for this.
Now activate your alarm in activity.
Hope these steps will help you. Refer the example I have mentioned.
I have an app that listens to incoming messages, and if the originating sender is the one specified by the user, it then reacts accordingly, showing a special alert and aborting the broadcast, preventing it from reaching the inbox. On Verizon, it works perfectly. I've sent over 300 without any issue, as have a few other testers.
On any other carrier though, it's a mess.
On AT&T, the broadcast is never aborted and it shows up in the sms inbox.
On Sprint, the broadcast is aborted, but it never gets beyond that. The AlertActivity intent is never called, nor either of the toast messages I put to check.
On T-Mobile, the broadcast is never aborted and it shows up in the sms inbox.
I have the receiver done in java rather than registered in the Manifest because I register it in a service which is started on app launch and on BOOT_COMPLETED.
Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void startService() {
IntentFilter SMSfilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
this.registerReceiver(Receiver.br, SMSfilter);
}
Receiver
static public BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
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[i].getOriginatingAddress().equals(Test.SENDER)) {
abortBroadcast();
String[] body = messages[i].getDisplayMessageBody().split(" ", 7);
if (body[0].equals("test")) {
test = true;
}
cat = body[1];
level = body[2];
urgency = body[3];
certainty = body[4];
carrier = body[5];
message = body[6];
intent = new Intent(context, AlertActivity.class);
Bundle b = new Bundle();
b.putString("title", cat);
b.putString("certainty", certainty);
b.putString("urgency", urgency);
b.putString("level", level);
b.putString("message", message);
b.putBoolean("test", test);
intent.putExtras(b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
carrierName = manager.getNetworkOperatorName();
if (carrierName.replaceAll(" ", "").equals(carrier)) {
context.startActivity(intent);
} else {
//testing
toast(carrierName.replaceAll(" ", ""), context);
}
}
}
}
}
};
I use these imports in the app,
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
I know that there is a gsm version of these as well, which I don't use. Could this be why the app isn't detecting the incoming messages on the gsm carriers?
UPDATE 1
According to http://developer.android.com/reference/android/telephony/gsm/package-summary.html its not due to not using the gsm specific imports.
ANSWER
Got it.
It has to do with how the incoming message senders number is read.
On the verizon device it would register as xxxxxxx on others, +1xxxxxxx. Added an option to acces Test.SENDER or Test.SENDER_LAME which is +1xxxxxxx
Got it. It has to do with how the incoming message senders number is read. On the verizon device it would register as xxxxxxx on others, +1xxxxxxx. Added an option to acces Test.SENDER or Test.SENDER_LAME which is +1xxxxxxx