Broadcast Receiver not working for SMS - android

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.

Related

SMS receiver stops working after sometime

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>

Android static broadcast receivers for SMS (when app is closed) in 19+ api

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

using SMS BroadcastReceiver for both Kitkat and old versions

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.

I am unable to get a SMS Broadcast Receiver to work on Android 4.1.3 on HTC one

I am new to this. I am working on a simple SMS receiver that catches incoming text messages, does some logic with them and then forwards them to my email for more permanent storage. The broadcast receiver is registered in my manifest and the code works great when I test on the Galaxy S3. However, when I install it on a HTC One it seems that the Boradcast Receiver is never fired. Just wondering if anyone else has run into this on HTC and if there is any suggested course of action. It's frustrating that it works on my Samsung, but not on HTC.
Note:
I have tried all of the commonly found answers online (increase priority, make sure all permissions are in manifest, tried it in an activity, etc.). The catlog doesn't seem to be helpful either. If I set a break point at the beginning of the onReceive() method or make toast there, neither points of code are ever hit on the HTC.
Here is my manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sms.forward"
android:versionCode="1"
android:versionName="1.1" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<uses-permission android:name="android.permission.PERSISTENT_ACTIVITY" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Light" >
<service android:name=".SecureMessagesActivity" />
<receiver android:name="com.android.upsync.SmsReceiver" android:exported="true" android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="2147483647" >
<action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</receiver>
</application>
</manifest>
AND my code that receivers it:
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getExtras();
String messageBody = "";
if ( extras != null )
{
// Get received SMS array
Object[] smsExtra = (Object[]) extras.get( SMS_EXTRA_NAME );
for ( int i = 0; i < smsExtra.length; ++i )
{
SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
messageBody = sms.getMessageBody();
}
ForwardToEmail(messageBody);
extras = null;
messageBody = null;
}
// Display SMS message
}
Again this works great on my Samsung, but not at all on the HTC. I have also checked for other SMS applications on the phone (ex. gosms pro, etc). I do not see anything on there that has a higher prioity (well I cheated for now and put mine to the highest possible - usually it is only at 999).
Any insight or direction would be swell :).
Since Android 3.1 BroadcastReceivers wont be registered to the system until a component from your package has been launched.
So you need to create an Activity that will be launched on install. Starting this 'component' will register your manifest declared BroadcastReceivers
To previous answer... As you can see here https://stackoverflow.com/questions/19565172/the-different-behavior-of-the-service-program-on-the-htc-one-evo-3d-and-samsu it is possible to avoid starting of Activity to start BroadcastReceiver. I see that it does not depends on Android version but evidently it really can work unpredictable on different devices such as HTC and Samsung...

Android - Cannot receive C2DM Registration Intent

I am attempting to register my device with C2DM and am having major issues. I have followed several tutorials, all of which are very similar. I believe the issue has to do with the registration intent that it sends to the C2DM server. Does anyone have any suggestions. The following is the relevant code:
Manifest: The permissions (outside my application tag):
<!-- Used for C2DM -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.companyname.parade.permission.C2D_MESSAGE" />
This is the Intent registration (inside my application tag):
<receiver
android:name=".C2DMReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.companyname.parade" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.companyname.parade" />
</intent-filter>
</receiver>
The following is what I call to register my device to the C2DM server (it starts the service that contacts the C2DM servers that is suppose to send back a registration Intent with my registartionID in it). It is located in a file called C2DMessaging:
public static void register(Context context) {
Intent registrationIntent = new Intent(REQUEST_REGISTRATION_INTENT);
registrationIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT,
PendingIntent.getBroadcast(context, 0, new Intent(), 0));
registrationIntent.putExtra(EXTRA_SENDER, SENDER_ID);
ComponentName name = context.startService(registrationIntent);
if(name == null){
// FAIL!
Log.d(TAG, "FAIL");
}else{
// SUCCESS
Log.d(TAG, "Success");
}
}
The ComponentName info is the following:
com.google.android.gsf/com.google.android.gsf.gtalkservice.PushMessagingRegistrar
There is no logcat output. My receiver (named C2DMReceiver) is the following:
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (C2DMessaging.INTENT_REGISTRATION_CALLBACK.equals(action)) {
// Registration Intent
Log.w(TAG, "Registration Receiver called");
handleRegistration(context, intent);
} else if (action.equals(C2DMessaging.INTENT_RECEIVED_MESSAGE_CALLBACK)) {
Log.w(TAG, "Message Receiver called");
handleMessage(context, intent);
} else if (action.equals(C2DMessaging.INTENT_C2DM_RETRY)) {
C2DMessaging.register(context);
}
}
This does not get called at all.
Edit: This whole thing was a stupid mistake on my part. I simply forgot a step somehow in the tutorials I read. I need to add this to my permissions:
<permission android:name="com.companyname.parade.permission.C2D_MESSAGE" android:protectionLevel="signature" />
Thanks to MisterSquonk for the response.
From the Google docs for C2DM for Creating the Manifest, the manifest needs a <permission> entry to complement the <uses-permission> entry for C2D_MESSAGE.
Something like this...
<permission android:name="com.companyname.parade.permission.C2D_MESSAGE" android:protectionLevel="signature" />
This tutorial worked for me in getting me up to speed:
http://www.vogella.com/articles/AndroidCloudToDeviceMessaging/article.html
I'm not sure why you have two intent filters. I only needed one - com.google.android.c2dm.intent.REGISTRATION (see tutorial above for a complete example manifest)
I'd check your manifest is correctly referencing the receiver class - perhaps try a fully-qualified reference to the class. I had an issue at one point where I moved receiver class in my project structure and all messages stopped.
I'd also check that the C2DM account is set up right, and with the right package name.
I'd also try it on another device, as in my experience some Android devices fall off C2DM and just don't receive messages for a period of time. I find sometimes flicking to airplane mode and back sorts it out, but I found testing on several devices essential to rule out problems with a specific device.

Categories

Resources