I noticed that an alarm is disabled when the application which sets this alarm has been upgraded. Is that true ?
Until now, I used the SharedPreferences with a FIRST_RUN key in order to know if it's the first run of my application. If I don't find this key, I enable the alarm and set FIRST_RUN to false, else I do nothing.
But I noticed also that these preferences remain intact between app upgrade !
So after an upgrade, the FIRST_RUN key is already false, so I do nothing while my alarm need to be enabled.
How to handle such case ?
Thanks in advance
Solution by Daniel Lew :
Need a receiver with the following lines in manifest :
<receiver android:name=".OnUpgradeReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" android:path="your.app.package" />
</intent-filter>
</receiver>
android:path is used in order to prevent OnUpgradeReceiver to be triggered by any upgrade of any application.
I've never tried this myself, but what about creating a BroadcastReceiver that listens to the ACTION_PACKAGE_REPLACED Intent?
I've thought about trying this before, but I'm not sure if there's a chicken-and-egg problem with it or not (e.g., does the Intent get sent before the new upgraded application can receive it?). Worth a try, though.
Simply, listen to the android.intent.action.MY_PACKAGE_REPLACED ... This INTENT will notify you if a new version of your application has been installed over an existing one
Note: This intent can is available starting from API 12
For the Android API level 12 and above, you need to register BroadcastReceiver with action ACTION_MY_PACKAGE_REPLACED
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Related
I am working on an app which will be pre-installed in the android device and i want to trigger it in background when end user actually start using its smart phone from the very first time. So is there any broadcast fired for this purpose or any other possible way to do this?
I've used a BroadcastReceiver to accomplish the running something on start, and as for knowing if it's the first time, you could use a shared preference for the app to track it's status of first time or not with a boolean.
Define a BroadcastReceiver the receiver will need the following in the manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver
android:name="com.androidfactorem.airwaves.BootAirWaveService"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
You can see a full implementation of a BroadcastReceiver on boot in my git project https://github.com/pbirdsall/airwave
I am tracking my installs with two methods like you can see here in my manifest:
<receiver
android:name="com.google.android.gms.tagmanager.InstallReferrerReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
<receiver
android:name=".tracking.ReferralReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
The second receiver generates a lint warning the first not. Does that mean that Google knows that for their InstallReferrerReceiver and know that it is safe to let it exported?
PS: I know I can use tools:ignore="ExportedReceiver".
The INSTALL_REFERRER intent is broadcasted when an app is installed from the Google Play Store.
android:exported="true" means that the receiver is allowed to receive broadcast intents from other applications. You do want this, or you will not be able to receive the event which is sent by another app (the system or the Play Store app, I'm not sure).
However, if you check the documentation for android:exported, its default value is true if it has at least one <intent-filter>, otherwise it is false.
So to sum up, you need android:exported="true" to catch the event. But omitting this property would be also OK, since the default value is true for your receivers (but it's safer to have it).
About the Lint warning: It recognizes the name, and that's why it knows that the first version is safe.
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
<receiver android:name=".receiver.AReceiver">
<intent-filter>
<action android:name="com.android.alarmclock.ALARM_ALERT" />
<action android:name="alarm_killed" />
<action android:name="cancel_snooze" />
</intent-filter>
</receiver>
This is my code in manifest and this is what I use to hear in my receiver on OnReceive(). I want to do something in the moment when you change your or set your native alarm clock in the android and this is not working.
When I add for example this:
action android:name="android.intent.action.TIME_SET"/>
action android:name="android.intent.action.TIMEZONE_CHANGED"/>
it is working if you set the time. So my broadcast receiver is good.
What to set in the intent filter to trigger (listen) when alarm is set?
I'm developing for android 2.3
This is my code in manifest
This is not part of the Android SDK. Anything with com.android in it is not part of the Android SDK. It may not work on some devices, if the alarm clock application is replaced or changed by the device manufacturer. It may not work on future versions of Android. Do not use this.
What to set in the intent filter to trigger (listen) when alarm is set?
There are no documented and supported broadcasts from the alarm clock application. More importantly, there simply is no broadcast when an alarm is set.
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" />