I am working on a sms blocker application, in which i am using broadcast receiver and abortBroadcast() method - as many ppl have suggested here - to prevent messages from reaching inbox and alerting the user. But in my case, when I send a sms using the emulator, the SMS message won't get blocked, and reaches the inbox, also I get an error :
06-29 09:19:05.854: E/BroadcastReceiver(868): BroadcastReceiver trying to return result during a non-ordered broadcast
which doesn't terminate the app in the emulator, however the application gets terminated when I test it on my phone.
And yes, I have set the receiver's priority to a high number and asked for the permissions as you see here:
<receiver android:name="SMSMonitor">
<intent-filter android:priority="9999999">
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY"/>
Finally, here's my code:
public class SMSMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
boolean isOn = loadState(context,"isOn");// is blocking enabled?
Bundle bundle = intent.getExtras();
Object messages[] = (Object[]) bundle.get("pdus");
SmsMessage smsMessage[] = new SmsMessage[messages.length];
String mAddress;
String mBody;
String mTime;
if(isOn){
// if spam blocking is enabled.
for (int n = 0; n < messages.length; n++) {
smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
mAddress=smsMessage[n].getDisplayOriginatingAddress().toString();
mBody=smsMessage[n].getDisplayMessageBody().toString();
mTime=getTime();
if(isBlackList( mAddress)== true) {
this.addLog(mAddress, mBody, mTime);
abortBroadcast();
Toast.makeText(context,"Incoming SMS was blocked and logged.", Toast.LENGTH_LONG).show();
}
}
}
}
}
Some one suggested here that the SMS broadcasts can't be aborted because Android won't allow it. But I have seen many guys here suggested using abortBroadcast() to block a sms, and also I know some SMS blocker apps on the market that actually CAN block SMSs. I don't know if they are using abortbroadcast or not.
Any ideas?
Definitely you can do this, code that you have written is perfectly fine,
Try changin priority from <intent-filter android:priority="9999999"> to <intent-filter android:priority="99999999"> , basically higher priority then what you have given, then try to check.
Is it showing the Toast from receiver? Probably your Receiver is not registered properly in Manifest.
try to change,
<receiver android:name="SMSMonitor">
to
<receiver android:name=".SMSMonitor">
"As of Android 1.6, incoming SMS message broadcasts (android.provider.Telephony.SMS_RECEIVED) are delivered as an "ordered broadcast" — meaning that you can tell the system which components should receive the broadcast first." and I am using Android 1.5 And the broadcast is non-ordered!
Thanks to this guy here link
Related
So last week my phone got stolen and the wifi and mobile data were turned off so I had no access to it. GPS was turned off as well but that's of no use if the phone doesn't have an internet connection. Even though the phone was protected by a fingerprint and my data would be safe, I still would've loved that phone back. Thinking about this I came up with an idea.
What if I create an Android app that would run silently in the background on my (new)phone and would do absolutely nothing. All it would do is listen for a certain string of characters in all the SMS the phone receives.
Now say my new phone gets stolen too (talk about tough luck). I immediately call at my number from someone's phone. If the phone is still turned on and has cellular connectivity, I would send an SMS with THAT string of characters to my number.
As soon as the phone receives the SMS, the app picks up on it and does the following:
Turns on GPS.
Gets a lock on its position.
Starts sending its own coordinates to the number it received the SMS from at
a rate of once every minute via SMS.
This way I get to know where my phone is and the thief won't know whats happening because everything is being done silently and the phone is locked as well. The main thing I want to cover with this app is the fact that this doesn't rely on an internet connection. It just trusts the fact that only I know the certain string of characters and that the app exists and is running 24/7. I know this isn't suitable for public use but for personal use, its ok I guess.
What I want to ask for is advice on what approach should I take? Any suggestions about things I should add? Have you ever tried something like this and if so, then can you share your experience with me?
Thanks in advance!
I have done in my project. Hope it will help you. Ask if it not clear to you. First you need to create SMSReceiver class for receiving sms into application which extend broadcast receiver & SMSListener interface for listening the SMS data and pass it to your desired activity.
Here is the code:
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");//pdus is the protocol of SMS data.
for(int i=0;i<pdus.length;i++){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
//You must check here if the sender is your provider and not another one with same text.
String messageBody = smsMessage.getMessageBody(); //SMS text data
mListener.messageReceived(messageBody);//Pass on the text to our listener.
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}
public static void unbindListener() {
mListener = null;
}
public interface SmsListener {
void messageReceived(String messageText);
}
}
Then you need to declare your receiver in manifest file. Like below.
<receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Then finally in your activity add this code for getting SMS data.
public Pattern p = Pattern.compile("(|^)\\d{4}"); //It will detect 4 number OTP value.
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Log.d("MESSAGE TEXT",messageText);
if(messageText != null)
{
Matcher m = p.matcher(messageText);
if(m.find()) {
//Do your code here after your sms received.
}
else
{
//Do here if you want to trigger anyof sms received.
}
}
}
});
BroadcastReceiver always listening for the incoming SMS. If it fails to trigger at app close or screen close state or always running issue look at this solution will help you.
Keep broadcast receiver running after application is closed
EDITED
Have a look at some workground scenario of never end service. All you need is monitoring the service & restart if killed. Also you can store the status of service in shared preference as well. Here some of the options & workcode for never end service. You can find more on search.
Android: keep Service running when app is killed
Creating a never ending background service in Android
Hope it will helps.
I want to receive a sms in my app, but I don't want my Android to show a notification about that event.
i was declare
<receiver android:name="mypackage.SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS" />
written code
public class SMSReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getExtras();
Object[] pdus = (Object[])extras.get("pdus");
for (Object pdu: pdus)
{
SmsMessage msg = SmsMessage.createFromPdu((byte[])pdu);
String origin = msg.getOriginatingAddress();
String body = msg.getMessageBody();
// Parse the SMS body
if (isMySpecialSMS)
{
// Stop it being passed to the main Messaging inbox
abortBroadcast();
}
}
}
}
and try set priority
<intent-filter android:priority="100">
But not work!Phone display notification!
have Android 4.4.2 (API 19) (Samsung Note 3)
Starting with KitKat (4.4), your app will need to be the default SMS app in order to suppress Notifications, as the default app is responsible for issuing them. Attempting to abort the SMS_RECEIVED broadcast no longer works. Any attempt to abort that broadcast is ignored by the system. Furthermore, the default app listens for the SMS_DELIVER broadcast, which cannot be aborted either, as it is delivered to only the default app. You can consult the following link for information on making your app eligible to be a default SMS app.
Getting Your SMS Apps Ready for KitKat
I am trying to verify the phone number of an Android device by having the device send an SMS to itself, and automatically checking if the SMS has been received. How can I do this?
To begin, this will require two permissions; one to send SMS messages, and one to receive them. The following needs to be in your AndroidManifest.xml, between the <manifest> tags, but outside of the <application> tags.
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
These are both dangerous permissions, so you will need to handle them accordingly if your app is to run on Marshmallow (API level 23) or above, and has a targetSdkVersion of 23+. Information on how to request these permissions at runtime can be found on this developer page.
The Java classes you will need are in the android.telephony package; specifically android.telephony.SmsManager and android.telephony.SmsMessage. Do make certain you've got the correct classes imported for both.
To send the outgoing SMS, you will use SmsManager's sendTextMessage() method, which has the following signature:
sendTextMessage(String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent)
Only two arguments are required in this method call - destinationAddress and text; the first being the phone number, the second being the message content. null can be passed for the rest. For example:
String number = "1234567890";
String message = "Verification message.";
SmsManager sm = SmsManager.getDefault();
sm.sendTextMessage(number, null, message, null, null);
It's important to keep the message text relatively short, as sendTextMessage() will usually fail silently if the text length exceeds the character limit for a single message.
To receive and read the incoming message, you will need to register a BroadcastReceiver with an IntentFilter for the "android.provider.Telephony.SMS_RECEIVED" action. This Receiver can be registered either statically in the manifest, or dynamically on a Context at runtime.
Statically registering the Receiver class in the manifest will allow your app to receive the incoming message even if your app should happen to be killed before receipt. It may, however, take a little extra work to get the results where you want them. Between the <application> tags:
<receiver
android:name=".SmsReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
The PackageManager#setComponentEnabledSetting() method can be used to enable and disable this <receiver> as needed.
Dynamically registering a Receiver instance on a Context can be a little easier to manage, code-wise, as the Receiver class could be made an inner class on whichever component registers it, and therefore have direct access to that component's members. However, this approach might not be as reliable as static registration, as a few different things could prevent the Receiver from getting the broadcast; e.g., your app's process being killed, the user navigating away from the registering Activity, etc.
SmsReceiver receiver = new SmsReceiver();
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(receiver, filter);
Do remember to unregister the Receiver when appropriate.
In the Receiver's onReceive() method, the actual message comes as an array of byte arrays attached to the Intent as an extra. The decoding details vary depending on the Android version, but the result here is a single SmsMessage object that will have the phone number and message you're after.
class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
SmsMessage msg;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);
msg = msgs[0];
} else {
Object pdus[] = (Object[]) intent.getExtras().get("pdus");
msg = SmsMessage.createFromPdu((byte[]) pdus[0]);
}
String number = msg.getOriginatingAddress();
String message = msg.getMessageBody();
...
}
}
At this point, you simply compare the number here to the one passed to the sendTextMessage() call. It's advisable to use PhoneNumberUtils.compare() for this, since the number retrieved in the Receiver might be in a different format than the one addressed.
Notes:
The example demonstrated here is using one single-part message, thus why the message text should be restricted to a relatively short length. If you do want to send a longer message, for some reason, the sendMultipartTextMessage() method can be used instead. You would need to split up the text first, using SmsManager#divideMessage(), and passing the resulting ArrayList to that method, in lieu of the message String. To reassemble the complete message in the Receiver, you'd have to decode each byte[] into an SmsMessage, and concatenate the message bodies.
Since KitKat (API level 19), if your app is not the default messaging app, the messages used here are going to be saved to the SMS Provider by the system and default app, and will therefore be available to any other app that uses the Provider. There's not much you can do about that, but if you really want to avoid it, this same technique can be used with data SMS, which do not trigger the default app, and won't be saved to the Provider.
For this, the sendDataMessage() method is used, which will need an additional short argument for the (arbitrary) port number, and the message is passed as a byte[], rather than a String. The action to filter for is "android.intent.action.DATA_SMS_RECEIVED", and the filter will need a data scheme and authority (host and port) set. In the manifest, it would look like:
<intent-filter>
<action android:name="android.intent.action.DATA_SMS_RECEIVED" />
<data
android:scheme="sms"
android:host="localhost"
android:port="1234" />
</intent-filter>
and there are corresponding methods in the IntentFilter class to set those dynamically.
Decoding the SmsMessage is the same, but the message byte[] is retrieved with getUserData(), rather than getMessageBody().
Prior to KitKat, apps were responsible for writing their own outgoing messages, so you can just not do that on those versions, if you don't want any record of it.
Incoming messages could be intercepted, and their broadcasts aborted before the main messaging app could receive and write them. To accomplish this, the filter's priority is set to the maximum, and abortBroadcast() is called in the Receiver. In the static option, the android:priority="999" attribute is added to the opening <intent-filter> tag. Dynamically, the IntentFilter#setPriority() method can do the same.
This is not at all reliable, as it is always possible for another app to have a higher precedence than yours.
I've omitted securing the Receiver with the broadcaster's permission in these examples, partly for simplicity and clarity, and partly because the nature of the thing wouldn't really leave you open to any sort of spoofing that could do harm. However, if you'd like to include this, then you merely need to add the android:permission="android.permission.BROADCAST_SMS" attribute to the opening <receiver> tag for the static option. For the dynamic, use the four-parameter overload of the registerReceiver() method, passing that permission String as the third argument, and null as the fourth.
I'm looking for an app that disables sending or receiving or both - of SMS messages from a android device . Once the app is installed it checks a web url for a boolean value 0 or 1, if it's zero, sms is disabled, else it's enabled.
Can anyone guide me from where to start ?Is this possible?
You can register a BroadcastReceiver for incoming SMS and use this.abortBroadcast(); to abort its further processing:
Inside you manifest:
<receiver android:name=".SMSBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
Implementation of the receiver:
public class SMSBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
...
this.abortBroadcast();
}
}
}
However - it is not possible to abort an outgoing SMS that way. Please note that if more than one BroadcastReceivers are registered, the one with the highest priority (android:priority) will be processed first.
Imho you cant disable SMS receiving/sending at all, but you can catch the SMS received Broadcast Intent.
The SMS received Broadcast Intent is a ordered Broadcast, it will be delivered to all Broadcast Receivers in order of the Priority defined in the Receiver.
If you register a Broadcast Receiver with Priority 0 you can catch the SMS Broadcast and cancel it.
Keep in mind that other SMS Apps can also register with Priority 0 the behavior is undefined for same priority values. Also the SMS is received anyway, you only hide the Resulting Notifications/Ringtone.
Another approach would be to set the SMS Central Number to some invalid Values, required a rooted Phone though
I want to know about intercepting an incoming SMS message for a specific key word; for example, "Hi", so that I can read that sms containing "Hi" in it and delete it after reading the message, and if that message doesn't contain any such text then it wouldn't be deleted and instead saved in the inbox.
Look for Broadcast Receiver, this is dependent on the apps installed on the phone but you can give your app priority for listening to messages. Although, when a notification is shown, the message won't be in the SMS Database yet, so you will need to use abortBroadcast() to stop other apps being notified. See example below:
public class MessageReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle pudsBundle = intent.getExtras();
Object[] pdus = (Object[]) pudsBundle.get("pdus");
SmsMessage messages =SmsMessage.createFromPdu((byte[]) pdus[0]);
Log.i(TAG, messages.getMessageBody());
if(messages.getMessageBody().contains("Hi")) {
abortBroadcast();
}
}
And you would need to declare the receiver in the manifest, like so:
<receiver android:name="com.encima.smsreceiver.MessageReceiver" android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
Finally, make sure you have the permission to RECEIVE_SMS in the manifest.
As of Android 4.4, what you ask to do in the question is impossible
Since Android version 4.4, If your app is not the default messaging app, you won't be able to perform those things promised in the accepted answer. You can neither stop the default messaging app from getting notified, nor you can delete an sms message.