ACTION_MY_PACKAGE_REPLACED not received - android

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.

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...

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");
}
}

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

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

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>

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;
}
}

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.

I ran into this problem when I was building and installing my app from Android Studio.
When doing normal build & run (without debugging), I fixed the problem by turning off Instant Run.
When doing a build & run with debugging, I couldn't find a way to fix the problem.

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>

Related

How does PACKAGE_REPLACED works in android? [duplicate]

My application that is not on Play Store verify on the web If there are a new version and download and start it. After the installation I would like to restart the application and I would use a BroadcastRecevier with ACTION_PACKAGE_REPLACED. This is the code :
Broadcast:
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)){
ApplicationInfo app = new ApplicationInfo();
if(app.packageName.equals("it.android.downloadapk")){
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(app.packageName);
context.startActivity(LaunchIntent);
}
}
}
Manifest:
<receiver android:name="it.android.downloadapk.Broadcast">
<intent-filter>
<action android:name="android.intent.action.ACTION_PACKAGE_REPLACED"></action>
<data android:scheme="package" android:path="it.android.downloadapk" />
</intent-filter>
</receiver>
The problem is that when I install new apk, the Broadcast appears not to start, why ?
see this:
How to know my Android application has been upgraded in order to reset an alarm?
correct fix is that you use the wrong string in the manifest:
http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_REPLACED
it should be "android.intent.action.PACKAGE_REPLACED" instead.
ok , i see that what i've written is still not enough to try it out, so i will make an exception and publish a whole project just to show that it works:
app code is in a package called "com.broadcast_receiver_test" .
don't forget to run it before testing , or else it won't work on some android versions (i think API 11+) .
manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.broadcast_receiver_test" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="3" />
<application android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity android:name=".BroadcastReceiverTestActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<data android:scheme="package" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<data android:scheme="package" />
</intent-filter>
</receiver>
</application>
</manifest>
MyBroadcastReceiver.java:
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(final Context context,final Intent intent)
{
final String msg="intent:"+intent+" action:"+intent.getAction();
Log.d("DEBUG",msg);
Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
}
}
please just run it and see that it works perfectly .
EDIT: if your app is for API12 and above, and only wish to handle the case of updating of your app, you can use this intent alone:
http://developer.android.com/reference/android/content/Intent.html#ACTION_MY_PACKAGE_REPLACED
I put the following receiver in the AndroidManifest.xml
<receiver android:name=".StartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
So my app can be launched on update as well as device reboot. Ofcourse as everyone has mentioned that you need API 12+ for MY_PACKAGE_REPLACED.
After hours and hours of searching how to restart your app after it was updated, I finally find why it won't restart.
The app must NOT be launched by Android Studio or other IDE. If I manually install app with its apk and launch it from the current Android device, the app can recognize if there was an update of my application and it restarts correctly.
My user case is a custom launcher that can update by itself launching a PackageInstaller.Session without going to Google Play Store
Here it's the code
Manifest:
<receiver android:name="UpdateReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
UpdateReceiver (Kotlin code):
class UpdateReceiver: BroadcastReceiver() {
companion object {
private val TAG = UpdateReceiver::class.java.simpleName
}
override fun onReceive(context: Context?, intent: Intent?) {
Log.d(TAG, "onReceive ${intent?.action ?: "unknown action"}")
if (intent?.action == Intent.ACTION_MY_PACKAGE_REPLACED) {
//MainActivity = Your first activity
val yourIntent = Intent(context, MainActivity::class.java)
yourIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context?.startActivity(yourIntent)
}
}
}
After two days of struggle and experimentation, I found out the reason.
It turned out I need to carefully read the official documentation.
As said here: https://developer.android.com/reference/android/content/Intent#ACTION_MY_PACKAGE_REPLACED
It turned out the key phrase is:
It does not contain any additional data
those. if you changed the manifest,
then the application will not restart after updating
you are welcome
For anyone trying all the other answers without success, I recommend you restarting the app.
I noticed the app was successfully updated, but it wasn't being launched even though I tried starting the activity in many ways.
I used https://github.com/JakeWharton/ProcessPhoenix in the BroadcastReceiver, so basically in the update you're downloading, add ProcessPhoenix.triggerRebirth(context); in your BroadcastReceiver, or restart the app somehow in there.

android package restarted broadcast not working

I am developing an app which needs a broadcast when app opens every time. I had registered the receiver in manifest like this.
<receiver android:name="package.broadcast.example" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
But i cant able to receive the broadcast. I spent 3 hours on this still i cant find wats the mistake. Can anyone refer me the working example of this broadcast. Thanks.
Restarted Application/Package does not receive broadcast...
check the following link for details
you can check this link
http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_RESTARTED
do u have the following code which extends BroadcastReceiver, if not than try the following code:
public class AutoConnection extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ((intent.getAction() != null)
&& (intent.getAction()
.equals("android.intent.action.PACKAGE_RESTARTED"))) {
Toast.makeText(context, "Pacakge Restarted",
Toast.LENGTH_LONG).show();
}
}
}
and in android manifest file add the following code:
<receiver android:name=".AutoConnection" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

How to make my app receive broadcast when other applications are installed or removed

I want to make an app that can receive broadcast when other apps on the device are installed or removed.
my code
in manifset:
<receiver android:name=".apps.AppListener">
<intent-filter android:priority="100">
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
</intent-filter>
</receiver>
in AppListener:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AppListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
// TODO Auto-generated method stub
Log.v(TAG, "there is a broadcast");
}
}
but I can't receive any broadcast. I think this problem is due to app permissions, any idea?
Thanks for helps.
In your manifest:
<receiver android:name=".apps.AppListener">
<intent-filter android:priority="100">
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
</intent-filter>
</receiver>
Add the line before the intent-filter tag
<data android:scheme="package"/>
So your manifest should look like this:
<receiver android:name=".apps.AppListener">
<intent-filter android:priority="100">
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
Am not sure about the PACKAGE_REMOVED intent in that if its actually is available.
You must eliminate android.intent.action.PACKAGE_INSTALL as it is deprecated and no longer recommended, because it is just for the system. Everything else is perfect and I would recommend that instead of 100, put 999, the documentation does not give maximum or minimum number to use, the larger the number, the higher priority will have your receiver for that intent. Sorry for the translator. I speak and write in Spanish.
Information
<receiver android:name=".apps.AppListener">
<intent-filter android:priority="999">
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
Great Answers, just one small thing left:
On every App update first ACTION_PACKAGE_REMOVED will be called followed by ACTION_PACKAGE_ADDED- if you wish to ignore these events, just add it on your onReceive():
if(!(intent.getExtras() != null &&
intent.getExtras().containsKey(Intent.EXTRA_REPLACING) &&
intent.getExtras().getBoolean(Intent.EXTRA_REPLACING, false))) {
//DO YOUR THING
}
This is from the docs:
EXTRA_REPLACING Added in API level 3 String EXTRA_REPLACING Used as a
boolean extra field in ACTION_PACKAGE_REMOVED intents to indicate that
this is a replacement of the package, so this broadcast will
immediately be followed by an add broadcast for a different version of
the same package.
Constant Value: "android.intent.extra.REPLACING"
Starting from Android 11, since direct access to all packages is restricted, there is a new permission introduced:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
This is to be used along with the accepted answer, to get the information of all the packages. For getting information about only a few packages, a <queries> declaration can be added in Manifest file, read more at this medium article.
from Android 11 and above, you need to use filtring as mentioned in the docs, and the broadcast will receive the action correctly,
<queries>
<package android:name="com.example.myApp" />
</queries>
or you can use QUERY_ALL_PACKAGES permission, but you should know, this permission needs subject to approval to be uploaded to google play as mentioned in the docs
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />

K-9 Mail's REFRESH_OBSERVER?

Does anyone know how K9 Mail's REFRESH_OBSERVER should work? I tried the following as test, but I'm not getting a broadcast when I read/unread/delete/receive:
Manifest:
<receiver android:name=".Monitor">
<intent-filter>
<action android:name="com.fsck.k9.intent.action.REFRESH_OBSERVER"/>
</intent-filter>
</receiver>
...
</application>
<uses-permission android:name="com.fsck.k9.permission.READ_MESSAGES" />
I also tried scheme=email with REFRESH_OBSERVER, but it didn't work.
Monitor.java:
public class Monitor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("test", "onReceive()");
}
}
On the other hand, the following works:
<intent-filter>
<action android:name="com.fsck.k9.intent.action.EMAIL_RECEIVED" />
<action android:name="com.fsck.k9.intent.action.EMAIL_DELETED" />
<data android:scheme="email" />
</intent-filter>
But I would really like to get a broadcast when messages are read (for counting unread messages) and these two are insufficient for that.
Thanks!
REFRESH_OBSERVER is used only in src/com/fsck/k9/K9.java as part of the MessagingListener method searchStats(), to "let observers know a fetch occurred". It's only called when using the local search feature. Feel free to submit a patch to us if you wish to add some functionality to K-9. See https://github.com/k9mail/k-9/wiki

Android: receiving intent sent by system ACTION_PACKAGE_RESTARTED

I am new to android. I get completely stuck in using ACTION_PACKAGE_RESTARTED in my application
I have removed pacakge from my emulator, also added using adb install but get nothing. Start an app. close that one and again start that app. nothing seems work for me. There is no log in logcat.
Is there anything that i'm missing? Please help
public class RestartReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action= intent.getAction();
Log.i("D", "Inside receiver");
}
And here is the manifest file
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".ReceiverTest">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.ACTION_PACKAGE_RESTARTED" />
</intent-filter>
</receiver>
</application>
the value specified in the intent filter is incorrect..actual value is
<action android:name="android.intent.action.PACKAGE_RESTARTED" />
and this broadcast can be received for other packages only. Restarted application/package doesn't receive this broadcast.
You should add a data specification to the intent-filter:
<data android:scheme="package" />

Categories

Resources