【问题标题】:How do I programmatically update apk silently and restart the app?如何以编程方式静默更新 apk 并重新启动应用程序?
【发布时间】:2016-06-26 21:23:06
【问题描述】:

我已经尝试过 StackOverFlow 和其他网站中给出的许多方法,但它并没有真正奏效。

我的问题是我有这个需要更新的应用程序,更新后它应该会自动重新打开相同的应用程序(更新)。

这是我的代码:

private synchronized void runRootUpdate() {    
    // Install Updated APK
    String command = "pm install -r " + downloadPath + apkFile;
    Process proc = Runtime.getRuntime().exec(new String[] {"su", "-c", command});
    int test = proc.waitFor(); // Error is here.

    if (proc.exitValue() == 0) {
        // Successfully installed updated app
        doRestart()
    } else {
        // Fail
        throw new Exception("Root installation failed");
    }
}

private void doRestart() {
    Intent mStartActivity = new Intent(context, MainActivity.class);
    int mPendingIntentId = 123456;
    PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
    System.exit(0);
}

看看我的“错误就在这里”。我的旧应用程序将安装一个新的更新应用程序并杀死自己,因此没有 proc.waitFor() 并最终回到主屏幕但正在安装新的更新应用程序。但是,我需要它来重新启动它。有什么办法可以做到吗?

【问题讨论】:

标签: android


【解决方案1】:

与其设置警报,不如让一个 Manifest 注册 BroadcastReceiver 专门用于此目的。它既可以收听android.intent.action.PACKAGE_REPLACED(注意:这个常量中缺少action这个词)也可以收听android.intent.action.MY_PACKAGE_REPLACED

<receiver android:name="...">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_REPLACED"></action>
        <data android:scheme="package" android:path="com.your.package" /> 
    </intent-filter>
</receiver>

重新安装后您的接收器将收到此消息,您将能够开始一个活动

【讨论】:

  • 不知道为什么这个答案如此受欢迎,因为广播接收器从未得到我的意图。
  • 对于在 Manifest 中注册的接收者 - 不是活动中的程序化接收者?
  • 是的,在 Manifest 中注册了它。
【解决方案2】:

更新应用程序涉及终止其所有进程。您应该启动 pm 命令之前设置警报(延迟超过 100 毫秒)

【讨论】:

    【解决方案3】:

    首先,您需要知道 .apk 文件的存储位置,因为这在升级应用程序时很重要。

    要静默升级和启动应用程序,您需要按照以下步骤操作。

    在升级应用程序时确保您的 sdcard 中有最新的 .apk 文件。如果有,则通过以下意图启动它以进行升级

    File file = new File(Environment.getExternalStorageDirectory(), "app-debug.apk"); // mention apk file path here
                    if (file.exists()) {
                        Intent intent = new Intent(Intent.ACTION_VIEW);
                        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                        startActivity(intent);
                    } else {
                        Toast.makeText(UpdateActivity.this, "file not exist", Toast.LENGTH_SHORT).show();
                    }
    

    以上代码将使用 android 的默认行为升级您的应用程序。

    创建一个广播接收器,它会知道何时执行升级

        <receiver android:name=".receiver.OnUpgradeReceiver">
                    <intent-filter>
    // Note: This intent can is available starting from API 12
                        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
                    </intent-filter>
                </receiver>
    

    如果你使用 api > 12 使用

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

    如果你有 api

      <action android:name="android.intent.action.PACKAGE_REPLACED" />
        <data android:scheme="package" android:path="your.app.package" />
    

    创建一个广播接收器,以便在更新和启动您想要的活动后获取广播

    例子:

    public class OnUpgradeReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
           // launch your fav activity from here.
        }
    }
    

    以上广播接收器可帮助您静默启动应用程序。

    希望这些对你有所帮助。

    【讨论】:

    • 感谢您的回答。但是应用程序应该在没有提示的情况下自动更新。
    • 那么它们不应该是任何方式,因为它是android默认行为。
    • 在我的例子中,它会抛出一个错误,说包已经存在。
    【解决方案4】:

    嗯...为什么要使用这个hard方法,当你使用root安装的时候?为什么不尝试创建简单的 shell 脚本来更新应用程序?那么你就不必设置闹钟和做其他事情了:

    脚本(How to pass argumentsHow to start app from terminal):

    am kill com.myapp.package
    pm install -r $1
    am start -n packageName/pkgName.ActivityName
    

    应用代码:

    String command = "sh script.sh " + downloadPath + apkFile;
    Process proc = Runtime.getRuntime().exec(new String[] {"su", "-c", command});
    

    【讨论】:

    • "sh script.sh"是什么意思,是脚本的路径吗?是否可以将其创建为稍后读取的文件?
    • sh 是用于执行脚本的 shell 命令 script.sh 是脚本的补丁,是的,您可以将其创建为文件。
    • 就是这样。谢谢!
    • 不工作。虽然 Runtime.getRuntime.exec 返回 0.
    • 如果你也可以看看这个stackoverflow.com/questions/59420253/…
    【解决方案5】:

    使用thisPlay Core Library In-app updates 来实现这一点

    dependencies {
    implementation 'com.google.android.play:core:1.5.0'
    ...}
    

    【讨论】:

    • 这不会“静默”更新 apk,它需要用户交互
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 2016-09-26
    • 1970-01-01
    • 2016-07-07
    相关资源
    最近更新 更多