【问题标题】:Android : restart application after update - ACTION_PACKAGE_REPLACEDAndroid:更新后重新启动应用程序 - ACTION_PACKAGE_REPLACED
【发布时间】:2012-05-30 11:28:09
【问题描述】:

我的应用程序不在 Play 商店中,请在网络上验证是否有新版本并下载并启动它。安装后我想重新启动应用程序,我会使用BroadcastRecevierACTION_PACKAGE_REPLACED。这是代码:

广播:

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

清单:

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

问题是当我安装新的apk时,Broadcast似乎无法启动,为什么?

【问题讨论】:

    标签: android broadcast


    【解决方案1】:

    看到这个:

    How to know my Android application has been upgraded in order to reset an alarm?

    正确的解决方法是您在清单中使用了错误的字符串: http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_REPLACED

    它应该是“android.intent.action.PACKAGE_REPLACED”。


    好的,我看到我写的内容仍然不足以尝试,所以我将破例发布整个项目以证明它有效: 应用程序代码位于名为 "com.broadcast_receiver_test" 的包中。 不要忘记在测试之前运行它,否则它将无法在某些 android 版本上运行(我认为 API 11+)。

    清单:

    <?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();
        }
      }
    

    请运行它并查看它是否完美运行。


    编辑:如果您的应用适用于 API12 及更高版本,并且只想处理更新应用的情况,您可以单独使用此意图:

    http://developer.android.com/reference/android/content/Intent.html#ACTION_MY_PACKAGE_REPLACED

    【讨论】:

    • 您是否尝试检查它是否可以手动安装更新版本?另外,也许它仅在内部版本号大于当前版本号时才有效?坦率地说,我从未使用过它,所以这只是我的猜测。
    • 您是否也尝试在其他应用更新时收听此事件?
    • 顺便说一句,您是如何克服确认安装 apk 的需要的?每次需要更新时它是否仍然出现在用户面前?
    • 我启动APK这个代码: Intent intenti = Intent new (Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "apkname.apk")), "application/vnd.android.package-archive");开始活动(意图);
    • @ShakeebAyaz 当它被清除时,您不会在应用程序内部收到通知,因为这也意味着您的应用程序将被停止(至少这是我注意到的)。无论如何,如果你想处理你的应用程序的升级,我找到了另一个解决方案,但它需要 API12:developer.android.com/reference/android/content/…
    【解决方案2】:

    我在AndroidManifest.xml中放了下面的receiver

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

    所以我的应用可以在更新和设备重启时启动。当然,正如每个人都提到的,MY_PACKAGE_REPLACED 需要 API 12+。

    【讨论】:

      【解决方案3】:

      经过数小时搜索如何在更新后重新启动您的应用后,我终于找到了它无法重新启动的原因。

      应用程序必须由 Android Studio 或其他 IDE 启动。如果我使用其 apk 手动安装应用程序并从当前的 Android 设备启动它,该应用程序可以识别我的应用程序是否有更新并正确重启。

      我的用户案例是一个自定义启动器,它可以自行更新启动 PackageInstaller.Session 而无需转到 Google Play 商店

      这是代码

      清单:

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

      UpdateReceiver(Kotlin 代码):

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

      【讨论】:

        【解决方案4】:

        经过两天的奋斗和实验,我找到了原因。 原来我需要仔细阅读官方文档。

        如这里所说:https://developer.android.com/reference/android/content/Intent#ACTION_MY_PACKAGE_REPLACED

        原来的关键短语是: 它不包含任何额外的数据

        那些。如果您更改了清单, 那么更新后应用程序将不会重新启动

        不客气

        【讨论】:

          【解决方案5】:

          对于尝试所有其他答案但没有成功的人,我建议您重新启动应用程序。

          我注意到应用程序已成功更新,但即使我尝试以多种方式启动活动,它也没有启动。

          我在BroadcastReceiver 中使用了https://github.com/JakeWharton/ProcessPhoenix,所以基本上在您正在下载的更新中,在您的BroadcastReceiver 中添加ProcessPhoenix.triggerRebirth(context);,或者以某种方式在那里重新启动应用程序。

          【讨论】:

            最近更新 更多