简体   繁体   English

Phonegap Android应用程序以编程方式触发更新

[英]Phonegap Android app trigger update programmatically

I am building an Android app that is hosted on a server outside Google Play. 我正在构建一个托管在Google Play外部服务器上的Android应用。 I need the app to check for new version and prompt user to update when the app starts. 我需要应用程序检查新版本并提示用户在应用程序启动时进行更新。

I built a mechanism to check for new version (the app checks for a file on server and compares version) which is working well. 我构建了一个机制来检查新版本(应用程序检查服务器上的文件并比较版本),该机制运行良好。 Then I prompt user to update, but if user chooses to proceed with the update, I'm not able to trigger the download and installation of the apk. 然后我提示用户更新,但如果用户选择继续更新,我无法触发apk的下载和安装。

I tried simply opening the apk url: 我试过打开apk url:

window.open(apkURL);

where the apkURL is the full http link to the .apk file hosted on server. 其中apkURL是服务器上托管的.apk文件的完整http链接。

But it doesn't seem to do anything. 但它似乎没有做任何事情。

I've been researching but I don't find an answer on how to do this. 我一直在研究,但我找不到如何做到这一点的答案。 I found some suggestions using native code, like this post Install Application programmatically on Android but I don't know how to do that from within my Phonegap app. 我发现了一些使用本机代码的建议,比如这篇文章在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); 

Is this the right way to trigger the update? 这是触发更新的正确方法吗? How can something like this be done from within a Phonegap app? 如何在Phonegap应用程序中完成这样的事情?

Thanks! 谢谢!

I finally managed to implement this, using the File api and the WebIntent plugin. 我终于使用File api和WebIntent插件设法实现了这一点。 I will post the solution here in case it helps anyone. 我会在这里发布解决方案,以防它帮助任何人。

The code downloads the apk from a remote server to the download folder in the sdcard and then triggers the install. 代码将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);
});

For you guys that use Cordova 3+, a similar solution like that of Vero is possible: 对于使用Cordova 3+的人来说,可以使用与Vero类似的解决方案:

So we're first going to download the .apk file. 所以我们首先要下载.apk文件。 We need the file-transfer plugin for this. 我们需要文件传输插件。 You can install it with following command: 您可以使用以下命令安装它:

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

Secondly, we need another plugin to start a webintent. 其次,我们需要另一个插件来启动webintent。 This webintent prompts the user if there is an update. 此webintent会提示用户是否有更新。 You can install it with the following command: 您可以使用以下命令安装它:

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

Then, you can use this 2 functions in your code to download the .apk and to prompt the user if there is an update of the application: 然后,您可以在代码中使用这两个函数来下载.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);
        }
    );
}

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

thank you Vero for answer ... it is help me so much... there is a problem with your code in cordova file plugin last version. 谢谢你Vero的回答......它对我帮助很大......你的代码在cordova文件插件的最后一个版本中有问题。 replace entry.fullPath with entry.toURL() if you use file plugin version 1.0.0 or newer. 如果您使用文件插件版本1.0.0或更高版本,请使用entry.toURL()替换entry.fullPath if you use entry.fullPath , it throw error 'there is a problem parsing package'. 如果你使用entry.fullPath,它会抛出错误'解析包有问题'。

from file-transfer plugin on github 来自github上的文件传输插件

These paths were previously exposed in the fullPath property of FileEntry and DirectoryEntry objects returned by the File plugin. 这些路径先前已在FileEntry的FullPath属性和File插件返回的DirectoryEntry对象中公开。 New versions of the File plugin, however, no longer expose these paths to JavaScript. 但是,新版本的File插件不再向JavaScript公开这些路径。

If you are upgrading to a new (1.0.0 or newer) version of File, and you have previously been using entry.fullPath as arguments to download() or upload(), then you will need to change your code to use filesystem URLs instead. 如果要升级到新的(1.0.0或更新版本)File,并且之前一直使用entry.fullPath作为download()或upload()的参数,那么您将需要更改代码以使用文件系统URL代替。

FileEntry.toURL() and DirectoryEntry.toURL() return a filesystem URL of the form FileEntry.toURL()和DirectoryEntry.toURL()返回表单的文件系统URL

cdvfile://localhost/persistent/path/to/file which can be used in place of the absolute file path in both download() and upload() methods. cdvfile:// localhost / persistent / path / to / file,可用于代替download()和upload()方法中的绝对文件路径。

Working example in 2018 2018年的工作实例

Based on previous comments I implement this solution 根据之前的评论,我实施了这个解决方案

It require: 它需要:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM