I have an app that allows users to forward SMS messages as they are received. Back in the day, I had the android:priority in my intent-filter for android.provider.Telephony.SMS_RECEIVED set to barely above Android's default messaging app. I did so, so that the user can forward the messages without having to clear them in the messaging app. However, a few months later, Go SMS Pro released an update of their app with a android:priority value extremely high, so users with that app installed started having issues. I updated my app so that my priority was slightly higher than Go SMS Pro's and everything went fine. Now Go SMS Pro did it again, their android:priority has been taken up to the max value you can assign. 2147483647 on one of their broadcast receivers and 2147483640 on another (yes, Go SMS Pro has two broadcast receivers now).
To fix this, I tried changing my priority to max just like theirs, but somehow their app keeps wining the SMS fight even though our priorities are the same. I read somewhere that Android when having to decide between two apps with the same priority, it chooses the one installed the earliest. I tried installing Go SMS Pro AFTER my app, but still nothing.
What's the proper way to fix this? What are they doing in their app that makes them get the SMS broadcast before anyone else, even with same android:priority values?
What's the proper way to fix this?
Modify your app to survive being run after Go SMS Pro or any other app. You might also advise users if you detect apps monitoring the same broadcast with equal-or-higher priorities (use PackageManager for this), so they know to configure those apps accordingly.
Trying to have a higher priority than everyone else is an arms race, one in which you will eventually wind up, at best, tied with the same priority. The behavior of ordered broadcasts with tied priorities is undocumented, and therefore there is no guaranteed behavior. Android -- or customized versions of Android -- are welcome to modify the tie-breaker algorithm. That algorithm could be anything from:
alphabetical order by package name
order as found in a hashed collection, where the hash key could be based on anything (e.g., object ID)
random number generator
Since you cannot reliably "win", modify your app to be as successful as possible when you do indeed "lose".
go sms pro has set these lines in it's manifest for SmsReceiver:
<receiver android:name=".smspopup.SmsReceiver" android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.GSM_SMS_RECEIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
<intent-filter>
<action android:name="com.android.mms.transaction.MESSAGE_SENT" />
</intent-filter>
</receiver>
all these intent-filters make its priority higher than your receiver even if your reciever has the priority set to 2147483647. you can see the list of all receivers of all apps by:
List<ResolveInfo> receivers = getPackageManager().queryBroadcastReceivers(new Intent("android.provider.Telephony.SMS_RECEIVED"), 0);
the first receiver in the list, receives the sms before than others
Related
I have written an app which receives incoming SMSes, saves it and displays it to the users. Suddenly my app stopped receiving SMS due to Samsung's ChatOn app update.
Here is the my Manifest.xml:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<receiver android:name="com.myapp.sms.service.SMSReceiver"
android:permission="android.permission.BROADCAST_SMS" android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
I had this issue earlier with Hangout which started supporting SMS. So, at that time I added priority to 999 (max value) in manifest file. And this worked.
But after recent update of ChatOn app, my app stopped receiving SMS. Please tell me how can I overcome with this.
For work around, I unchecked SMS option on ChatOn app.
Any help is appreciated.
There is no guaranteed way that your app can get "first crack" at SMS messages, on Android 4.3 and below. Even if you set your app to be the highest possible priority, other apps can do the same. GoSMS notably does this, and you have indicated that ChatOn does as well. If they get the message first and abort the broadcast, you will not receive the message.
There is nothing that you can do, other than to detect this possibility (using PackageManager) and alert users as to the potential behavior.
Note that on Android 4.4, this is a lot different:
The broadcast can no longer be aborted
There are separate broadcasts for apps that are monitoring SMS and the actual final SMS client app
I am making an app and want to know when the app is uninstalling. For doing it, I used BroadcastReceiver but I don't know where is my code is wrong? (when my app is uninstalling, BroadcastReceiver can't receive any message about uninstalling)
It's my app's Manifest:
<receiver android:name="receiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED"/>
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<action android:name="android.intent.action.UID_REMOVED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.MEDIA_REMOVED"/>
<action android:name="android.intent.action.MEDIA_BAD_REMOVAL"/>
<action android:name="android.intent.action.BATTERY_OKAY"/>
<data android:scheme="com.example.testpermission"/>
</intent-filter>
You cannot get an event when your own app is uninstalling. See here. There is also a post on the subject here.
You can't, but if you have second installed application on the device - you can get notification via that application about the uninstallation of the first one (as far as I remember).
I believe that the application cannot monitor its own uninstall from two reasons:
It will make it much harder to uninstall application (some evil apps might even try to do something bad when their application is being removed).
If you remove application - you cannot run it, or send it events! The app should be closed for clean deletion.
About how to do it from second app:
Your second app should be a receiver to the ACTION_PACKAGE_REMOVED event (read about BroadcastReceiver, and see: http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_REMOVED)
I've recently added GCM messaging to my app using google's helper classes (GCMBroadcastReceiver, GCMBaseIntentService). It works beautifully when the app is running, both when it's in the foreground and when it's not. However, when it's not running, nothing works.
As a test, I extended GCMBroadcastReceiver and added log statements to getGCMIntentServiceClassName() and peekService(). When the app is running and a message arrives I see the former called. The OS then instantiates my service class, which eventually results in onMessage() being called.
When the app isn't running getGCMIntentServiceClassName() never gets called.
My manifest is pretty much the boiler-plate code from Google's GCM examples.
Is there an extra permission or flag I need to set in order for the OS to wake up my app when it's not running and a message arrives w/ the correct intent category? My receiver is defined as:
<receiver
android:name=".GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="PACKAGENAME" />
</intent-filter>
</receiver>
Bear in mind: this works when the app is running in the background.
Bleh. Figured it out. David Wasser's answer here:
BroadcastReceiver isn't working
explains why I'm not seeing the broadcasts when my app isn't running. I was force quitting it from Manage Applications, which puts it into the "stopped" state (and thereby causes the system to exclude it from broadcasts by default).
When I install the app, launch it, power down the device, then power it on again, I'm receiving the broadcasts properly.
I had same issue and fixed by just running the through RUN button from Android Studio.
I think in Debug Mode it doesn't work
I make some program, which removes unwanted SMS from phone (by special filter).
It uses aborBroadcast() meted to stop SMS.
In emulator, it works okay, on some mobile phones (I tested with Android 2.2) too.
But in some phones (Samsung, 2.3.3) it does not stop SMS. And after my program removed, mobile receives ALL sms again, which was aborted.
My android.manifest code:
<receiver android:name=".SmsHandler" >
<intent-filter android:priority="2147483647" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
My handler code:
if msgText.contains(GlobalVars.getInstance().getFilterText())) {
abortBroadcast();
}
Maybe, somebody can advice me?
There are two types of broadcasts, ordered and unordered. As far as I know, SMS is an unordered broadcast, and that is why you can't really abort it.
http://developer.android.com/reference/android/content/BroadcastReceiver.html#Security
I am not sure when you say that it works on some devices. Ideally, it shouldn't for the SMS received broadcast.
I have an broadcast receiver registered in the manifest for intercepting calls, like this:
<receiver android:name="CallTracker">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Everything works fine and the receiver gets called.
But after I restart the device or my AVD, the receiver doesn't get called anymore.
What do I have to do in order to get my broadcast receiver to work after reboot, too?
Do I need PackageManager for that?
I like the registration in the manifest, since the application doesn't have to be active in order for the app to intercept the call.
I know that this question is quite old but in my opinion still relevant. Since the currently accepted answer is wrong and the comment by user1806772 was the correct answer for me, I provide it as a new answer to the question:
It probably does work. But directly after reboot it can take a really long time (up to multiple minutes) until the intent is delivered. Some minutes after the reboot it should work fast again.
You need to add this action to your intent-filter.
<action android:name="android.intent.action.BOOT_COMPLETED" />