32

我正在使用 ACTION_MY_PACKAGE_REPLACED 来接收我的应用程序何时更新或重新安装。我的问题是该事件从未被触发(我尝试了 Eclipse 和真实设备)。这就是我所做的:

显现:

<receiver android:name=".MyEventReceiver" >
    <intent-filter android:priority="1000" >
        <action android:name="android.intent.action.ACTION_MY_PACKAGE_REPLACED" />
    </intent-filter>
</receiver>

代码:

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

这段代码很简单,实际上我使用了其他事件,如 BOOT_COMPLETED 和其他事件,它们可以工作,但 ACTION_MY_PACKAGE_REPLACED。谢谢。

4

9 回答 9

25

出于某种原因,谷歌开发人员(名为“Dianne Hackborn”)认为可以单独注册当前应用程序的 PACKAGE_REPLACED 意图(在此处阅读存档版本此处为原始链接)。

但是,我找不到任何正确的方法,所以我做出了妥协:它将在可用时使用最新的 API。

可悲的是,我不知道为什么它不能被调试,但它确实有效(如果你愿意,你可以写入日志)。

这是代码:

显现:

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

编辑:在今天的 Android 版本中,当你应该将 minSdk 设置为至少 14 时,你不需要这个,实际上你应该只使用 MY_PACKAGE_REPLACED 就可以了。不需要布尔值等...

于 2014-02-02T12:28:18.693 回答
15

由于清单合并问题,已接受的答案不再适用于 Android Studio 1.0+,如此处所示。完全基于android开发人员的回答,我通过以下实现解决了这个问题:

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>

更新接收器.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");
    }
}
于 2015-01-03T22:11:51.953 回答
12

从所有用户那里获取信息我可以通过这种方式解决我的问题。他们都是对的,几乎没有需要注意的地方:

在清单中:

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

和代码:

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

在我的 Android 版本(2.3 Gingerbread)中,我无法使用 MY_PACKAGE_REPLACED 但我们使用 PACKAGE_REPLACED 解决了(将告知任何应用程序已被替换)但询问它是否是我们的:

 if(intent.getData().getSchemeSpecificPart().equals(context.getPackageName()))
 {
 }

谢谢大家

于 2012-10-01T16:21:32.560 回答
8

我只想在这里添加我自己的两便士,因为我在让它工作和调试它时遇到了问题。我使用的是棒棒糖设备:

这是我使用的代码:

    <receiver android:name=".services.OnUpdateReceiver">
        <intent-filter>
            <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
        </intent-filter>
    </receiver>    

要调试它,你需要确保你已经在手机上安装了更新,只需通过 Eclipse 调试就可以了,并且至少打开了一次应用程序,然后你可以简单地编辑你的调试配置:

eclipse > run > debug configurations > launch action (do nothing) > then F11 like normal

我通过将一个小文件写入 SD 卡来确认它有效

于 2015-01-03T15:58:05.743 回答
3

简单清单适用于所有版本:

    <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>
于 2014-07-22T10:04:29.443 回答
2

您是在 API>=12 设备/模拟器上尝试吗?此广播不会在以前的情况下发送,因为它是 API 12。如果您需要您的应用程序为 Pre-ICS 和旧蜂巢设备接收此广播,

尝试:

if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
  if (!intent.getData().getSchemeSpecificPart()
       .equals(context.getPackageName())) {
    return;
  }
}
于 2012-10-01T02:12:26.443 回答
1

实际上,当您安装 apk 时,您的应用程序将启动两次。为您设置的每个接收器一次。

当您正在收听时,android.intent.action.PACKAGE_REPLACED您需要检查包名中的intent.getData()

请注意, intent.getData()当它来自时将为 Null android.intent.action.MY_PACKAGE_REPLACED

我认为使用其中之一就足够了。

于 2019-02-16T10:13:06.803 回答
0

当我从 Android Studio 构建和安装我的应用程序时遇到了这个问题。

  • 在进行正常的构建和运行(不进行调试)时,我通过关闭 Instant Run 解决了这个问题。
  • 在使用调试进行构建和运行时,我找不到解决问题的方法。
于 2019-04-13T23:21:52.563 回答
-4

您需要将数据方案添加到意图过滤器,如下所示

<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>
于 2012-10-01T03:35:21.560 回答