Phonegap Android 应用程序如何通过编程触发更新

14
我正在构建一款Android应用程序,该程序托管在Google Play以外的服务器上。我需要应用程序在启动时检查新版本并提示用户更新。
我已经构建了一个机制来检查新版本(应用程序检查服务器上的文件并比较版本),这个机制运行良好。然后,我提示用户进行更新,但是如果用户选择继续更新,我无法触发下载和安装apk的操作。
我尝试简单地打开apk的url:
window.open(apkURL);

其中apkURL是托管在服务器上的.apk文件的完整http链接。

但它似乎没有任何作用。

我一直在研究,但我没有找到如何做到这一点的答案。我发现一些使用本地代码的建议,比如这篇文章在Android上编程安装应用程序,但我不知道如何在我的Phonegap应用程序内部执行此操作。

Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse("file:///path/to/your.apk"))
.setType("application/vnd.android.package-archive");
startActivity(promptInstall); 

这是触发更新的正确方法吗?如何从 Phonegap 应用程序内部执行此类操作?

谢谢!

5个回答

16

使用File API和WebIntent插件,我终于成功实现了这一点。以下是解决方案,希望有所帮助。

该代码将apk从远程服务器下载到SD卡的下载文件夹中,然后触发安装。

window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile('download/filename.apk', {
    create: true, 
    exclusive: false
  }, function(fileEntry) {
    var localPath = fileEntry.fullPath,
    fileTransfer = new FileTransfer();        
    fileTransfer.download(apkURL, localPath, function(entry) {
        window.plugins.webintent.startActivity({
            action: window.plugins.webintent.ACTION_VIEW,
            url: 'file://' + entry.fullPath,
            type: 'application/vnd.android.package-archive'
            },
            function(){},
            function(e){
                alert('Error launching app update');
            }
        );                              

    }, function (error) {
        alert("Error downloading APK: " + error.code);
  });
  }, function(evt){
      alert("Error downloading apk: " + evt.target.error.code);                                               
  });
}, function(evt){
alert("Error preparing to download apk: " + evt.target.error.code);
});

1
安装了PhoneGap后,如何自动启动APK?在FileAPI或WebIntent插件中是否有特定的方法,请告诉我。 - nida
1
我想从http://download.com/update/myapp.apk下载更新。那么代码应该是什么?请帮忙。 - Md Riad Hossain

12

对于使用 Cordova 3+ 的用户,类似 Vero 的解决方案是可行的:

首先,我们需要下载 .apk 文件。我们需要使用 file-transfer 插件来完成此操作。 您可以使用以下命令进行安装:

phonegap local plugin add org.apache.cordova.file-transfer

其次,我们需要另一个插件来启动WebIntent。这个WebIntent会提示用户是否需要更新。您可以使用以下命令进行安装:

phonegap local plugin add https://github.com/Initsogar/cordova-webintent.git

然后,您可以在您的代码中使用这两个函数来下载.apk文件和提示用户应用程序是否有更新:

/*
 * Uses the filetransfer plugin
 */
function downloadApkAndroid(data) {
    var fileURL = "cdvfile://localhost/persistent/CegekaMon.apk";

    var fileTransfer = new FileTransfer();
    var uri = encodeURI(data.android);

    fileTransfer.download(
        uri,
        fileURL,
        function (entry) {

            console.log("download complete: " + entry.fullPath);

            promptForUpdateAndroid(entry);
        },
        function (error) {
            console.log("download error source " + error.source);
            console.log("download error target " + error.target);
            console.log("upload error code" + error.code);
        },
        false,
        {

        }
    );
}
/*
 * Uses the borismus webintent plugin
 */
function promptForUpdateAndroid(entry) {
    window.plugins.webintent.startActivity({
            action: window.plugins.webintent.ACTION_VIEW,
            url: entry.toURL(),
            type: 'application/vnd.android.package-archive'
        },
        function () {
        },
        function () {
            alert('Failed to open URL via Android Intent.');
            console.log("Failed to open URL via Android Intent. URL: " + entry.fullPath);
        }
    );
}

2
谢谢您的回答。downloadApkAndroid函数中的“data”参数是什么?您能分享一个调用它的例子吗? - carlospiles
只是一个字符串数组,'data.android' 包含要下载的 APK 的 URL。 - janpio
我该如何调用那个函数?downloadApkAndroid({ android: "/files/app.apk" }) - Iago Bruno
1
这个对我来说几乎有效,除了我一直收到“解析错误 - 存在解析包的问题”的警报。将fileURL更改为以下内容解决了我的问题: var fileURL = cordova.file.externalDataDirectory + '<NAME_OF_FILE>.apk' - Paul Spaulding

0

2018年的工作示例

根据之前的评论,我实现了这个解决方案

它需要:

constructor(public navCtrl: NavController, private transfer: FileTransfer, private file: File, private webIntent: WebIntent) {
    const fileTransfer: FileTransferObject = this.transfer.create();
    const url = 'urlApkFile';//Modified this
    fileTransfer.download(url, this.file.externalDataDirectory + 'file.apk').then((entry) => 
    {
        webIntent.startActivity({
            action: (window).plugins.intentShim.ACTION_INSTALL_PACKAGE,
            url: entry.toURL(),
            type: 'application/vnd.android.package-archive'
        }).then(function () {
            //OK
        }, function (e) {
            alert('Error launching app update' + JSON.stringify(e));
        });
    }, (error) => {
        alert("downdload finish" + JSON.stringify(error));
    });
}
    


0

谢谢Vero的回答...它对我帮助很大... 在Cordova文件插件的最新版本中,您的代码存在问题。 如果您使用文件插件的1.0.0或更新版本,请用entry.toURL()替换entry.fullPath。 如果您使用entry.fullPath,则会抛出错误“存在解析包的问题”。

来自GitHub上的文件传输插件

以前在File插件返回的FileEntry和DirectoryEntry对象的fullPath属性中公开了这些路径。 但是,File插件的新版本不再将这些路径公开给JavaScript。

如果您要升级到新版(1.0.0或更高版本)的File,并且您之前一直在使用entry.fullPath作为download()或upload()方法的参数,则需要更改代码以使用文件系统URL。

FileEntry.toURL()和DirectoryEntry.toURL()返回形式为cdvfile:// localhost / persistent / path / to / file的文件系统URL,可以在download()和upload()方法中替代绝对文件路径。


0

遗憾的是,在Phonegap Web容器中,如果不使用插件,您无法访问该种本地功能。您只能将用户链接到apk(例如通过打开本机浏览器),并让他安装它。


谢谢你的回答。我现在正在检查webintent phonegap插件,看看它是否可行。当你说链接到apk时,它是一个常规链接吗?为什么链接有效但我的window.open无效呢?谢谢。 - Vero
当然,使用插件可以绕过 Cordova 的限制,我不知道这个插件,但我认为它应该可以工作。通过链接,我实际上是想打开本地浏览器,使用类似 navigator.app.loadUrl 的方式打开 apk 文件。 - zakinster

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