Reputation: 9736
I am using ACTION_MY_PACKAGE_REPLACED to receive when my app is updated or resinstalled. My problem is that the event is never triggered (I tried Eclipse and real device). This is what I do:
Manifest:
<receiver android:name=".MyEventReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Code:
public class MyEventReceiver extends BroadcastReceiver
{
@Override public void onReceive(Context context, Intent intent)
{
if ("android.intent.action.ACTION_MY_PACKAGE_REPLACED".equals(intent.getAction()))
{ //Restart services
}
}
}
This code is simple, in real one I used other events like BOOT_COMPLETED and others, and they work but ACTION_MY_PACKAGE_REPLACED. Thanks.
Upvotes: 32
Views: 38284
Reputation: 116392
for some reason, a google developer (named "Dianne Hackborn") thinks it is possible to register to the PACKAGE_REPLACED intent of the current app alone (read archived version here, original link here).
however, i can't find any way of doing it correctly, so i've made a compromise: it will use the newest API when available.
Sadly, I can't find out why it can't be debugged, but it does work (you can write to the log if you wish).
here's the code:
manifest:
<receiver
android:name=".OnUpgradeBroadcastReceiver"
android:enabled="@bool/is_at_most_api_11" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<receiver
android:name=".OnUpgradeBroadcastReceiver"
android:enabled="@bool/is_at_least_api_12" >
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
res/values/version_checks.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="is_at_least_api_12" type="bool">false</item>
<item name="is_at_most_api_11" type="bool">true</item>
</resources>
res/values-v12/version_checks.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="is_at_least_api_12" type="bool">true</item>
<item name="is_at_most_api_11" type="bool">false</item>
</resources>
OnUpgradeBroadcastReceiver.java
public class OnUpgradeBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
if (VERSION.SDK_INT <= VERSION_CODES.HONEYCOMB
&& !context.getPackageName().equals(intent.getData().getSchemeSpecificPart())) {
android.util.Log.d("AppLog", "other apps were upgraded");
return;
}
android.util.Log.d("AppLog", "current app was upgraded");
EDIT: In today's Android versions, when you should set minSdk to be at least 14, you don't need this, and indeed you should just use MY_PACKAGE_REPLACED and that's it. No need for the booleans etc...
Upvotes: 25
Reputation: 42387
I ran into this problem when I was building and installing my app from Android Studio.
Upvotes: 0
Reputation: 73
Actually, your app will start twice when you install your apk. Once for each receiver that you have set.
When you are Listening to android.intent.action.PACKAGE_REPLACED
then you need to check for the package-name in the intent.getData()
Note that intent.getData()
will be Null when it is from
android.intent.action.MY_PACKAGE_REPLACED
I think using one of them is enough.
Upvotes: 1
Reputation: 19139
The accepted answer doesn't work any more with Android Studio 1.0+ because of manifest merge issues, as seen here. Totally based on android developer's answer, I fixed the issue with the following implementation:
AndroidManifest.xml:
<receiver android:name=".UpdateReceiver$LegacyUpdateReceiver" android:enabled="@bool/shouldUseActionPackageReplaced" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<receiver android:name=".UpdateReceiver" android:enabled="@bool/shouldUseActionMyPackageReplaced" >
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
/res/values/resources.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="shouldUseActionPackageReplaced">true</bool>
<bool name="shouldUseActionMyPackageReplaced">false</bool>
</resources>
/res/values-v12/resources.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="shouldUseActionPackageReplaced">false</bool>
<bool name="shouldUseActionMyPackageReplaced">true</bool>
</resources>
UpdateReceiver.java:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class UpdateReceiver extends BroadcastReceiver
{
public static class LegacyUpdateReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
if (intent != null && intent.getData() != null && context.getPackageName().equals(intent.getData().getSchemeSpecificPart()))
{
onUpdate(context);
}
}
}
@Override
public void onReceive(Context context, Intent intent)
{
onUpdate(context);
}
public static void onUpdate(Context context)
{
Log.d("LOG", "Current app updated");
}
}
Upvotes: 15
Reputation: 3224
I just want to add my own two pence worth here, because I had problems getting this to work and debugging it .. I am using a Lollipop device:
This is the code I used:
<receiver android:name=".services.OnUpdateReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
To debug it, you need to make sure you have installed the update on your phone, just via Eclipse debug is fine, and opened the app at least one time, then you can simply edit your debug configuration:
eclipse > run > debug configurations > launch action (do nothing) > then F11 like normal
I confirmed it worked by writing a small file to the SD card
Upvotes: 8
Reputation: 728
Simple Manifest working in all version :
<receiver
android:name=".Receiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Upvotes: 3
Reputation: 9736
Getting information from all the users I could solve my situation this way. All of them were right, with little points to notice:
In manifest:
<receiver android:name=".MyEventReceiver" >
<intent-filter android:priority="1000" >
<!--other actions I need-->
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
And code:
public class MyEventReceiver extends BroadcastReceiver
{
@Override public void onReceive(Context context, Intent intent)
{
if(Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction()))
{ if(intent.getData().getSchemeSpecificPart().equals(context.getPackageName()))
{ //Restart services.
}
}
}
}
In my Android release (2.3 Gingerbread) I was not able to use MY_PACKAGE_REPLACED but we solved using PACKAGE_REPLACED (will advise of any app been replaced) but asking if it is ours with:
if(intent.getData().getSchemeSpecificPart().equals(context.getPackageName()))
{
}
Thanks to all
Upvotes: 12
Reputation: 15477
You need to add data scheme to the intent filter like below
<receiver android:name=".MyEventReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
Upvotes: -4
Reputation: 5971
Are you trying it on a API>=12 device/emulator? This broadcast will not be sent on prior cases as it is API 12. If you need your app to receive this for Pre-ICS and the old honey comb devices,
try:
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
if (!intent.getData().getSchemeSpecificPart()
.equals(context.getPackageName())) {
return;
}
}
Upvotes: 2