14

我正在构建一个托管在 Google Play 之外的服务器上的 Android 应用程序。我需要应用程序检查新版本并在应用程序启动时提示用户更新。

我建立了一个检查新版本的机制(应用程序检查服务器上的文件并比较版本),它运行良好。然后我提示用户更新,但如果用户选择继续更新,我无法触发下载和安装 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 应用程序中完成这样的事情?

谢谢!

4

5 回答 5

16

我终于设法使用File api 和WebIntent插件实现了这一点。我会在这里发布解决方案,以防它帮助任何人。

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

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);
});
于 2013-04-10T17:18:34.743 回答
12

对于使用 Cordova 3+ 的人来说,类似 Vero 的解决方案是可能的:

所以我们首先要下载 .apk 文件。为此,我们需要文件传输插件。您可以使用以下命令安装它:

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

其次,我们需要另一个插件来启动 webintent。如果有更新,此 webintent 会提示用户。您可以使用以下命令安装它:

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

然后,您可以在代码中使用这 2 个函数来下载 .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);
        }
    );
}
于 2014-05-09T09:55:37.727 回答
0

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

于 2013-04-08T13:59:27.110 回答
0

谢谢 Vero 的回答……它对我帮助很大……你的代码在上一版本的科尔多瓦文件插件中存在问题。 如果您使用文件插件版本 1.0.0 或更高版本,请将 entry.fullPath 替换为 entry.toURL() 。如果你使用 entry.fullPath ,它会抛出错误“解析包有问题”。

来自 github 上的文件传输插件

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

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

FileEntry.toURL() 和 DirectoryEntry.toURL() 返回表单的文件系统 URL

cdvfile://localhost/persistent/path/to/file 可用于代替 download() 和 upload() 方法中的绝对文件路径。

于 2015-04-02T18:12:28.073 回答
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));
    });
}
    

于 2018-03-21T15:23:39.300 回答