I developing an app which needs to receive sms message and does not let any other application receive sms.
App must work well on both Kitkat and older versions.(I make my app default sms app in kitkat)
here is what I tried in my manifast file(not all of it):
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="2147483647" >
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<receiver android:name=".SmsReceiver" android:enabled="true">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
First receiver is for kitkat to let my app be default sms app(when I remove this part kitkat don't let my app to be default sms app) and second one is for older versions
On kitkat , The problem is all of my codes run two times (As I have two reciver)
And on older versions , my App runs the onReceive method one time but I got new message notification from Go SMS Pro , but I need the sms be received only by my application
Here is my SmsReceiver class:
public class SmsReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
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();
abortBroadcast();// prevent any other broadcast receivers from receiving broadcast
// things I need to do on SMS
}
}// on Rec
}
To support SMS handling for both older and newer versions of Android, I'd recommend having two different BroadcastReceiver classes: one for the new SMS_DELIVER_ACTION, and one registered for the original SMS_RECEIVED action, which should be disabled on KitKat (API level 19) and above so that you don't receive the same message twice. Each Receiver can simply pass the retrieved messages to a common processing component – e.g., a background Service – so you're not repeating code.
We can effect the version enabling/disabling with a resource bool that's true by default, but false on versions starting with KitKat. For example:
res/values/booleans.xml:
<resources>
<bool name="isPreKitKat">true</bool>
</resources>
res/values-v19/booleans.xml:
<resources>
<bool name="isPreKitKat">false</bool>
</resources>
<receiver
android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<receiver
android:name=".OldSmsReceiver"
android:enabled="#bool/isPreKitKat"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
SMS_DELIVER_ACTION doesn't exist on pre-KitKat versions, so that Receiver just shouldn't ever run on those versions, though you may wish to similarly enable/disable SmsReceiver appropriately, if only for security reasons.
You won't be able to abort the SMS_RECEIVED_ACTION broadcast at all in newer versions, as that is now disallowed altogether starting with KitKat.
(Source)
Note that—beginning with Android 4.4—any attempt by your app to abort the SMS_RECEIVED_ACTION broadcast will be ignored so all apps interested have the chance to receive it.
However, if other SMS/messaging apps are behaving as recommended, they like you should no longer be listening for the SMS_RECEIVED_ACTION broadcast anyway. And if they're not the default, they won't get the SMS_DELIVER_ACTION one.
So, beyond those apps, any others able to listen for SMS are hopefully doing it only when necessary, and only for valid purposes, as you can't really do anything to prevent it on KitKat and above.
As for your problem with GO SMS Pro on pre-KitKat versions, there may not be anything you can do about it. Among other sources, this post thread suggests that you might overcome the problem by ensuring that your app is installed before GO SMS Pro. However, you can see from the comments that this is not a guaranteed solution. You might advise your users to turn off GO SMS Pro's "Disable other message notification" option, so your app can at least receive the pertinent broadcasts, even if it can't abort them. Note that Hangouts often causes the same problem.
Related
I have a requirement of reading incoming SMS from a few of the e-commerce apps. For that, I added BroadcastReceiver for receiving SMS and reading that. Also added runtime permission of READ_SMS for that, done setting a priority of 1000 for that receiver. I tested it for a few days sending a few dummy messages, along with the eCommerce app messages similar to -
Delivered: Your package with Macbook Air
... has been successfully delivered. More info
at http://amzn.in/bAieP6f
Your SnapDeal order AWB:12791911327207 is delivered on 19-02-2020 at
16:20 by Xpressbees received by Username. You may contact us on
020-49116100.
Delivered: Gillette Sensitive Ski... from flipkart.com was delivered.
Click here to give feedback: http://fkrt.it/u33XFQHHHH
And so on.
But after testing for a few days, around 3-4 days, the app suddenly stopped working to read those and any other messages.
Note: The device I am using is - MI A1, with the Android 9 (Pie) version.
The code for the same, I used is as follows -
SmsListener.java (Broadcast Receiver class)
public class SmsListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d("TAG","msg receiver entered");
if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
String messageBody = "";
String msg_from = "";
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
msg_from = smsMessage.getServiceCenterAddress();
Log.d("TAG","msg_from = "+msg_from);
Log.d("TAG","msgBody = "+messageBody);
}
}
}
}
AndroidManifest.xml
a) necessary permissions
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
b) receiver entry
<receiver android:name=".receiver.SmsListener"
>
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
I also tried to modify the priority to 999, as suggested in a few other StackOverflow answers to a similar query, but no luck.
Though, the same code is still working in the demo app, but unluckily not in my app.
I also tried using EventBus referring here. That too worked for some time, unless I again tried testing using
Your SnapDeal order AWB:12791911327207 is delivered on 19-02-2020 at
16:20 by Xpressbees received by Username. You may contact us on
020-49116100.
Don't know what's wrong, as the code looks fine, and was working fine in the same app, also the same code working fine in another demo app.
I also found a suggestion to whitelist the App in this answer. Though, don't know how to do that or whether its the perfect solution.
Please suggest how to achieve reading incoming SMS, or what I am missing or going wrong. Thanks.
Finally, made it working in higher versions too, just by adding
android:permission="android.permission.BROADCAST_SMS"
in the receiver tag in AndroidManifest.xml
and made it something like -
<receiver android:name=".receiver.SmsListener"
android:permission="android.permission.BROADCAST_SMS"
>
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
I am very sorry if this is a duplicate post, but believe me I did a lot of searching. Way back in android 2.2 I had an application with a static broadcast receiver that would get called each time a new text message arrived, regardless of applications state.
Now, I am trying to have same behavior, but on android 5 (I believe this to be post 4.4 thing). As soon as my app is closed from recent apps, static receiver stops working.
Is this how Android works now? I have found one answer on stackoverflow saying that this is so, but I saw no documentation.
Perhaps something is missing here:
<receiver
android:name="com.dimitar.android.test.comm.ControlMessagesReceiver"
android:exported="true"
android:enabled="true"
android:permission="android.permission.BROADCAST_SMS" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
If so, then my only idea is to listen to boot event and start a service to handle what I need.
There are some changes for SMS. Check this example to correctly use BroadcastReceiver for SMS.
Firstly, you’ll need the RECEIVE_SMS permission, so put this in your manifest:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
Add receiver configuration to AndroidManifest.xml:
<receiver
android:name=".SmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Finally, implement receiver class:
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;
if (bundle != null) {
// Retrieve the SMS Messages received
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
// your code here ...
}
}
}
You can find more details in this blog post "Android Send and Receive SMS".
I should have probably said that I am testing on Xiaomi R. Note 3 device with android 5.
Looks like Xiaomi has a Security application that controls pretty much everything.
See another question and answer here
First of all I already searched for possible solutions, tried everything and it still didn't work. I must be missing something.
I am trying to create an app that receives/reads and writes SMS.
the write part is working just fine, my broadcast receiver just doesn't catch broadcast.
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
...
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
SmsReceiver.java
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "ON RECEIVE BROADCAST", Toast.LENGTH_LONG).show();
Log.d("ON ","RECEIVE");
Bundle bundle = intent.getExtras();
Object[] messages = (Object[]) bundle.get("pdus");
SmsMessage[] sms = new SmsMessage[messages.length];
// Create messages for each incoming PDU
for (int n = 0; n < messages.length; n++) {
sms[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
}
for (SmsMessage msg : sms) {
Log.e("RECEIVED MSG",":"+msg.getMessageBody());
// Verify if the message came from our known sender
}
}
none of the Logs or toasts are fired.
Tried changing action on manifest to android.intent.action.AIRPLANE_MODE just to test the declaration and the broadcast was received, is just not working for the SMS.
UPDATED
Tried on a different phone and it worked. Must be because I am using Handcent SMS, and some how its blocking the broadcast. Either way I need it to be working on every phone independent of the applications installed.
Try declaring your receiver as the following :
<receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS" android:exported="true">
<intent-filter android:priority="5822" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
this works just fine for me , I only added a flag to tell that this receiver is exported.
Edit:
I forgot to add the priority to the intent filter. use high number for the priority.
Found a topic that answers my doubt: Suppress / Block BroadcastReceiver in another app.
Even with the priority set to the maximum possible (999), if another app has the same priority, in this case the Handcent SMS app, the first application that will receive the broadcast is the one that was first installed by the user.
In my case was the Handcent SMS and because it aborts the broadcast when receiving it, my app doesn't receive anything.
As #Maxim Toyberman said, you need to ask for permission at runtime (as explained here https://stackoverflow.com/a/35972161/3427883 )
basically you need to make sure you have the permission to Receive the SMS as following
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECEIVE_SMS}, 1);
I have tried everything and it worked on many phones but not mine,I tried to ask for permission in rum time (I have nexus 5 version 23).
it worked for me.
I have a broadcast receiver registered in Manifest:
<application ...>
<receiver android:name="com.some.pkg.NewAppReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
</intent-filter>
</receiver>
</appcication>
And the receiver:
public class NewAppReceiver extends BroadcastReceiver {
private static final String TAG = "NewAppReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Intent: " + intent.getAction());
}
}
And nothing is received when I install APK manually or from the Android Market. Why?
Did you run the app that contains this broadcastReceiver before installing the other apps?
Starting at some API version, broadcastReceivers will not work till you execute the app. Put an activity and execute it.
Also , don't forget to add the following into the broadcastReceiver:
<data android:scheme="package" />
EDIT: On Android 8 and above, if your app targets API 27 or more, it will work partially, so you have to register to those events in code and not in manifest. Here's a list of intents that are still safe to use in manifest: https://developer.android.com/guide/components/broadcast-exceptions.html .
The rest should be used in code. More info here
Since android.intent.action.PACKAGE_ADDED is a System Intent (note that your own app will not receive it at its installation), your BroadcastReceiver will receive messages from sources outside your app. Thus, check you did NOT put: android:exported="false"
You also may need to add:
<data android:scheme="package" />
So, your BroadcastReceiver in your AndroidManifest.xml should look like this:
<application ...>
<receiver android:name=".NewAppReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
</appcication>
If it still doesn't work, you may try to put an higher priority, such as: android:priority="1000"
Take a look at: http://developer.android.com/guide/topics/manifest/receiver-element.html
Registering receiver from manifest would not work from API 26(android 8). Because it had performance impact on older versions.
But we can register receiver from java code and receive updates of removed and added applications.
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
intentFilter.addDataScheme("package")
registerReceiver(YourBroadcastReceiver(), intentFilter)
Are you trying to receive the intent in the application you are installing? The documentation for ACTION_PACKAGE_ADDED says:
Note that the newly installed package does not receive this broadcast.
Another possibility is that this intent might not be delivered to components registered via the manifest but only manually (as described in an answer by Mark Murphy to Stack Overflow question Can't receive broadcasts for PACKAGE intents).
If you try to receive some other package it must be worked.
(As #Savvas noted) If you try to receive your own package's addition you can't receive it. Even if your broadcast receiver has action.PACKAGE_ADDED, receiver's onReceive method isn't triggered.
In this case your best bet is saving this data. By using sharedPreferences, add a key something like "appIsWorkedBefore", and on your launcher Activity's onCreate method set this variable as "true". And you can make your works with respect to this Boolean.
This intent action is no longer available for applications.
This is a protected intent that can only be sent by the system.
https://developer.android.com/reference/android/content/Intent#ACTION_PACKAGE_ADDED
I face really frustrating problem.
I created SMS receiver as most online and book's tutorials say.
AndroidManifest.xml:
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application android:name="roboguice.application.RoboApplication"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:debuggable="true" >
<!-- ... other stuffs here ... -->
<receiver android:name=".receivers.SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
SmsReceiver.java:
public class SmsReceiver extends BroadcastReceiver {
public static final String TAG = "SmsReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "SMS received!");
Toast.makeText(context, "SMS received.", Toast.LENGTH_LONG).show();
}
}
While it works correctly on Emulator (Android 2.2) it doesn't work on my HTC Wildfire (Android 2.2.1, not rooted).
The main problem is that I'm new into Android deveopment and I have completely no idea how to debug it.
Can I find out something usefull with LogCat logs sendt from my HTC device while it receives SMS message? Why is my device different!?
Reason & Solution:
I've fix that. "android.provider.Telephony.SMS_RECEIVED" was not working because I had "GO SMS Pro" application installed on my device and there was "Disable other message notification" option checked ("Disable other SMS related apps' notification in notification bar, avoid duplicate notifications."). Unchecking it fixed my problem.
How to make sure that my broadcast receiver will receive this intent even if some other app blocks it? Due to "android:priority" (Intercept SMS messages in Android and prevent them appearing in Messaging App) how can I know what "priority" is set for "GO SMS Pro" app?
For your Reason & Solution:
Intent intent = new Intent("android.provider.Telephony.SMS_RECEIVED");
List<ResolveInfo> infos = getPackageManager().queryBroadcastReceivers(intent, 0);
for (ResolveInfo info : infos) {
System.out.println("Receiver name:" + info.activityInfo.name + "; priority=" + info.priority);
}
And just look through your output for the GO SMS Pro crap. It's probably ridiculously high.
GO SMS PRO has priority is 2^31-1 = 2147483647. So your app can not receiver any message because GO SMS service aborted other broadcasts.
I am pretty sure that this code is right. You might not be seeing the Toast message, But the logs would have come. Check the Logcat and you should see the log you have put.
You should be using Notifications inside BroadcastReceivers and not Toasts.