自动更新私有Android应用程序

52

我正在开发一款非公开的Android应用程序,即该应用程序不会在全球Android市场上提供。该应用程序将安装在有限数量的客户端上,例如使用apk文件。

如何在这个应用程序中启用自动更新功能?

我看到了不同的潜在选项(我不知道这些选项是否在技术上很难或甚至不可能实现,或者是否存在可以重用的任何现有功能):

  • 每次启动应用程序时,应用程序会测试是否存在新版本(通过请求服务器),如果有,则下载新的apk并替换自己成为新版本。
  • 使用(或开发?)一个分离的应用程序或服务来进行更新检查和替换流程。
  • 使用(或开发?)具有自动更新选项的私人市场应用程序。此选项类似于第二个选项,但更通用:市场应用程序将连接到存储库,即它将处理任意数量的(私有)应用程序。

我更喜欢第一种选项,因为自动更新功能包含在应用程序中,需要的开发工作较少。


1
“并用新版本替换自己”需要root权限。任何解决方案都可能需要root权限。我相信在默认的安卓固件中,用户必须与应用程序交互才能安装。如果没有root或自定义固件,就无法模拟这一点。 - Falmarri
14
谷歌应该提供自动更新应用程序的功能,以便从私有托管的APK更新,这样每个人都不需要使用定制的更新程序重新发明轮子。 - Jim
1
试试这个:https://github.com/commonsguy/cwac-updater 它使用起来相当容易。 - AVEbrahimi
1
有一个很好的服务可以帮助您的应用程序保持更新。请查看 https://www.push-link.com - CelinHC
@Jim,是的。更多锁定。这正是我们需要的。 - Pacerier
显示剩余3条评论
6个回答

18

在我工作的公司中,我们曾经遇到过Windows Mobile 6.x类似的问题,我们使用了与EboMike指出的解决方案基本相同的方法:

输入图像描述

主要应用程序会根据一个Web服务检查更新。如果有必要,它会收到当前版本和下载新版本的URL。然后,主要应用程序启动Updater应用程序,传递URL并退出。

Updater通过HTTP下载新程序,并向用户显示下载百分比。用户可以在可控的方式下随时取消下载,而且Updater可以记录这个取消操作。

由于新应用已经被下载,Updater运行新应用程序并退出。


6

我认为选项一对你来说是最少工作量的,实际上也是最干净的,因为它将通过使用Android内置的包安装程序来进行,其中包括用户通知和用户可以在需要时中止安装的选项。

你已经全部概述了-检查服务器上是否有新版本(给用户提供关闭此功能的选项会很好),如果有新版本,则可以只链接到APK的URL(如果我没记错,将使用浏览器的下载管理器来下载它),或者您可以使用您的应用程序下载它,然后将意图指向您的本地文件。使用HTTP链接在技术上更少的工作量和更干净-让操作系统做的越多,越好-除非有理由不这样做。


谢谢您的回答。我会尝试选项一:该应用程序下载一个apk文件并开始安装过程。如其他评论中所述,需要用户交互来确认更新。此问题https://dev59.com/qlHTa4cB1Zd3GeqPPCdS展示了如何启动已下载的apk文件。 - janjonas

3

启用“安装非市场应用程序”对于任何在 Google Play 之外的应用程序仍然是必需的。如果未启用,则安装过程将要求启用该选项,并将用户重定向到应用设置,然后用户可以安装该应用程序。

根据您的需求,您可以委托给第三方库。


2

我们将使用以下权限来完成此操作:

<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

让我稍微解释一下...最后一个权限WRITE_EXTERNAL_STORAGE是不言自明的。使用ACCESS_SUPERUSER权限,我们将告诉系统我们打算使用root权限。READ_EXTERNAL_STORAGE将来需要用于您的应用程序读取SD卡上的文件。

假设您已经下载了该文件,并且所有这些设备都可以获取root权限(有限数量的客户端,不在Play商店等),您可以执行以下操作:

String filePath = Environment.getExternalStorageDirectory().toString() + "/your_app_directory/your_app_filename.apk";
Process installProcess = null;
int installResult = -1337;

try {
    installProcess = Runtime.getRuntime().exec("su -c pm install -r " + filePath);
} catch (IOException e) {
    // Handle IOException the way you like.
}

if (installProcess != null) {
    try {
        installResult = installProcess.waitFor();
    } catch(InterruptedException e) {
        // Handle InterruptedException the way you like.
    }

    if (installResult == 0) {
        // Success!
    } else {
        // Failure. :-/
    }
} else {
    // Failure 2. :-(
}

你好,Nikola。我按照你的步骤操作了,但是 APK 没有被安装。"installProcess.waitFor()" 返回值为 255,安装失败了。你知道解决方法吗? - Santosh Prasad Sah
@SantoshSah:我不知道是什么原因导致的,但是这个退出代码告诉你已经知道的事情——安装不成功。设备是否已经取得了root权限? - Budimir Grom

0

这里可能有一个非常简单的方法,但对于某些公司而言,如果您认为它适用,这可能很容易实现。

  • 创建一个密码屏幕(passwordActivity),要求输入密码才能访问应用程序。
  • 一旦输入密码,就会提高标志(使用sharedpreferences将布尔值从false设置为true)。
  • 将.apk文件放置在Google Store上。
  • 一旦所有人都安装了应用程序,更改密码并在Google Play Store上发布新的更新。

由于软件将缓存标志值,即使更改密码,密码屏幕也不会显示出来。它只会在新安装中显示,因此可能需要重复此过程。

注意:如果使用该应用程序的用户不是数百人,则此方法可能更适合。请不要忘记该方法也不安全。总之,如果您正在寻找保持应用程序私密且没有安全问题的方法,那么我建议您采用此方法。


-1

更新应用程序 确保您已经将新的apk下载到指定位置

void installNewVersion(String location) {

 Intent intent = new Intent(Intent.ACTION_VIEW);
 intent.setDataAndType(Uri.fromFile(new File(location + "app-debug.apk")),
            "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接