如何获取我在 config.xml 中定义的版本字符串

Posted

技术标签:

【中文标题】如何获取我在 config.xml 中定义的版本字符串【英文标题】:How do I get the version string I defined in the config.xml 【发布时间】:2015-02-03 16:41:35 【问题描述】:

我如何知道我的 Cordova 应用程序是哪个版本?我需要该信息才能在“关于”屏幕中显示它。

是否可以读取 config.xml 并获取我已经在此文件中维护的版本字符串?

<widget ... version="0.0.1" ...

我希望有一个解决方案,我不必在代码中的多个位置维护应用程序的版本号。另外,我不想要为此目的的插件,因为大多数插件不支持 androidios 和浏览器作为平台。

还是我忽略了核心插件属性?

或者有没有一种解决方案,我维护一个文件,不是 config.xml,而 config.xml 从该文件中获取版本信息?

您如何在应用的“关于”屏幕中实现“显示版本信息”?任何提示表示赞赏。

我的 Cordova 版本是:

>cordova -v
4.2.0

【问题讨论】:

与***.com/questions/23343902/…重复 不,它不是重复的。我不想要@Kamal Reddy 接受的这个插件解决方案。这不适用于浏览器作为平台! 【参考方案1】:

如果您对使用任何第三方插件来实现这一点不感兴趣,那么我觉得 Cordova 钩子是要走的路。你可以想出一个before_build 钩子来从 config.xml 文件中读取版本并在应用程序中使用它。

幸运的是,您可以在以下link 中轻松使用此挂钩,他们正在从 config.xml 读取版本并在需要时将其作为依赖项注入。

建议你也看看cordova hooks的官方文档,以便更好地理解。

其实,你也可以尝试从config.xml中读取版本信息,直接放到你可以在index.html中创建的某个占位符中显示版本信息。这可以在使用钩子构建cordova之前完成,钩子又使用执行文件操作的Windows批处理文件。您可以在我的github page 中签出使用批处理文件的科尔多瓦钩子的工作示例。

【讨论】:

+1 我相信这是一个完美的答案。对于这样的事情,我更喜欢钩子而不是插件,就好像 Cordova 发生了变化一样,我不依赖于等待或分叉插件并对其进行修改以使其工作。如果由于某种原因钩子停止工作,节目仍然继续。我会给它 48 小时看看是否还有其他答案,如果没有,我会奖励你。谢谢 如果这符合@strubbl 问题的标准,那么我要求他们接受这个作为答案。 钩子目前似乎是最好的解决方案。感谢您指出。 @Strubl 很高兴它有帮助。干杯 @william Isted 感谢您的认可...干杯【参考方案2】:

根据@Gandhi 在他的回答中指出的脚本,我更新了脚本以使其适用于当前的 cordova@8:我将它用作“after_prepare”挂钩,而不是“before_build”,在后一种情况下,当cordova将这些东西复制到平台目录时,更改的文件再次被覆盖钩子已经执行...

该脚本使用 xml2js,因此请务必执行 npm i xml2js --save-dev 以使 xml2js 可用。

#!/usr/bin/env node

// taken from https://www.bram.us/2015/01/04/cordova-build-hook-script-for-displaying-build-version-in-your-app/
// see https://***.com/a/42650842
// This plugin replaces text in a file with the app version from config.xml.

// be sure to exec `npm i xml2js --save-dev` to make xml2js available


var wwwFileToReplace = "js/config.js";

var fs = require('fs');
var path = require('path');
var xml2js = require('xml2js');

function loadConfigXMLDoc(filePath) 
    var json = "";
    try 
        var fileData = fs.readFileSync(filePath, 'ascii');
        var parser = new xml2js.Parser();
        parser.parseString(fileData.substring(0, fileData.length), function (err, result) 
                           //console.log("config.xml as JSON", JSON.stringify(result, null, 2));
                           json = result;
                           );
        console.log("File '" + filePath + "' was successfully read.");
        return json;
     catch (ex) 
        console.log(ex)
    


function replace_string_in_file(filename, to_replace, replace_with) 
    var data = fs.readFileSync(filename, 'utf8');

    var result = data.replace(new RegExp(to_replace, "g"), replace_with);
    fs.writeFileSync(filename, result, 'utf8');
    //console.log("replaced in ", filename, "(", to_replace, " -> ", replace_with);
    var data2 = fs.readFileSync(filename, 'utf8');
    console.log(data2);


module.exports = function(context) 

    // var rootdir = process.argv[2]; // old cordova version
    var rootdir = context.opts.projectRoot;
    console.log("projectRoot=", rootdir);

    var configXMLPath = "config.xml";
    var rawJSON = loadConfigXMLDoc(configXMLPath);
    var version = rawJSON.widget.$.version;
    console.log("Version:", version);

    // var currentBuildPlatforms = process.env.CORDOVA_PLATFORMS.split(","); // old cordova version
    var currentBuildPlatforms = context.opts.cordova.platforms;
    //console.log(JSON.stringify(context));
    console.log("Current build platforms: ", currentBuildPlatforms);

    if (rootdir) 
        currentBuildPlatforms.forEach(function(val, index, array) 
            var wwwPath = "";
            switch(val) 
                case "ios":
                    wwwPath = "platforms/ios/www/";
                    break;
                case "android":
                    wwwPath = "platforms/android/assets/www/";
                    break;
                default:
                    console.log("Unknown build platform: " + val);
            
            var fullfilename = path.join(rootdir, wwwPath + wwwFileToReplace);
            if (fs.existsSync(fullfilename)) 
                replace_string_in_file(fullfilename, "%%VERSION%%", version);
                console.log("Replaced version in file: " + fullfilename);
            
        );
    


在你的config.xml 中包含这个钩子:

<hook src="scripts/after_prepare_read_app_version.js" type="after_prepare" />

【讨论】:

像魅力一样工作! :) 作为旁注,如果与“cordova-custom-config”一起使用,您必须将钩子添加到“YourProject/plugins/cordova-custom-config/plugin.xml”而不是“YourProject/config.xml”。 xml" @Amsvartner 为什么我们需要在插件 config.xml 中添加钩子? 不要乱用javascript文件,而是编辑html【参考方案3】:

根据其他答案,我创建了以下 before_prepare 钩子,它在 cordova 9 / ionic 5 中最适合我。

它不需要任何额外的库来解析配置 xml,因为它通过正则表达式获取版本。 它适用于browseriOSandroid 平台环境。 它在ionic serve 中也不起作用,因为这里没有执行科尔多瓦钩子。

#!/usr/bin/env node
// Add %%VERSION%% at any place to index.html file to be replaced by this script.

var fs = require('fs');
var path = require('path');

function fileStringReplace(filename, search, replace) 
    var content = fs.readFileSync(filename, 'utf8');
    content = content.replace(new RegExp(search, "g"), replace);
    
    fs.writeFileSync(filename, content, 'utf8');


module.exports = function(context) 
    var rawConfig = fs.readFileSync("config.xml", 'ascii');
    var match = /^<widget.+version="([\d\.]+)".+?>$/gm.exec(rawConfig);
    
    if(!match || match.length != 2)
        throw new Error("version parse failed");
    
    var version = match[1];

    fileStringReplace("www/index.html", "%%VERSION%%", version);
    console.log("replaced version to " + version);

将以下钩子注册添加到config.xml

<hook src="hooks/patch-indexhtml-version.js" type="before_prepare" />

index.html 在行动:

<html lang="de" data-appversion="%%VERSION%%">

现在您可以执行以下操作来获取应用中的版本:

document.documentElement.getAttribute("data-appversion");

【讨论】:

我还使用 'before_prepare' 来更改 www/index.html 文件而不是 platform/~/index.html,因此所有平台可以同时具有相同的版本。我调整了一点 @cyptus 的 fileStringReplace(" 部分在 hook.js。我改变了 www/index.html 不必总是有 %%VERSION%% 字符串(data-appversion=“1.0.5”例如,无需运行 ng build -> cordova 每次只为版本更改做准备) var rootdir= context.opts.projectRoot; var fullfilename = path.join(rootdir, "www/index.html"); var versionRegex = /data-appversion="(.+?)"/; if (fs.existsSync(fullfilename)) fileStringReplace(fullfilename, versionRegex,`data-appversion="$version"`); 这不起作用,因为它替换了www/ 的源文件。您不想在源文件中替换,而是要在 dest/ 的文件中替换。这里应该怎么做:***.com/a/65471679/1243247 @JoãoPimentelFerreira in ionic www/ 就像您的环境中的 dest/。仍然适用于最新的 ionic。 @cyptus 啊,好的,在 Apache Cordova 中 www/ 是源目录【参考方案4】:

我使用https://github.com/whiteoctober/cordova-plugin-app-version 描述的插件 1步:cordova插件添加https://github.com/whiteoctober/cordova-plugin-app-version.git

2 步(剪切和粘贴) 如果您使用 jQuery 或 AngularJS,则支持 promise 样式。使用类似的东西:

cordova.getAppVersion.getVersionNumber().then(function (version) 
    $('.version').text(version);
);

如果没有,传递一个回调函数:

cordova.getAppVersion.getVersionNumber(function (version) 

alert(version);
);

干杯

【讨论】:

【参考方案5】:

我会做这样的事情:

cordova.getAppVersion.getVersionNumber().then(function (version) 
   if (!window.localStorage['version'] || window.localStorage['version'] <    version) 
       window.localStorage['version'] = version;
   
);

这样您就可以在任何需要的地方致电window.localStorage['version']

【讨论】:

并没有真正解释你是如何获得cordova.getAppVersion的。 @WilliamIsted cordova.getAppVersion 再次使用cordova插件 这是一个已被弃用的插件,因为该项目已被废弃。它与某些设备有问题,所以我不推荐它。 github.com/whiteoctober/cordova-plugin-app-version【参考方案6】:

我是2020年12月写的,现在最简单的办法就是使用插件cordova-plugin-app-version

从目标构建设置中读取您的应用版本 [来自config.xml]

安装它

cordova plugin add cordova-plugin-app-version

只需在你的 JS 中使用这样的东西:

cordova.getAppVersion.getVersionNumber(function (version) 
  console.log('APP version is ' + version)
  $('.version').text(version)
)

在您的 html 中,您可以使用它在任意位置插入版本:

<span class="version"></span>

【讨论】:

【参考方案7】:

这是我从不同答案的汇编。 我用它来更新 Xcode 项目中的一些参数以进行插件编译。

您可以看到我从 config.xml 获取应用程序 ID 和名称

您可以将其添加到 after_prepare 钩子中:

&lt;hook src="scripts/addBuildSettingsToXcode.js" type="after_prepare" /&gt;

#!/usr/bin/env node

let fs    = require('fs');
let xcode = require('xcode');
let path = require('path');
let et = require('elementtree');


module.exports = function (context) 
    //console.log(context);

    function addBuildPropertyToDebugAndRelease(prop, value) 
        console.log('Xcode Adding   ' + prop + '=' + value);
        myProj.addBuildProperty(prop, value, 'Debug');
        myProj.addBuildProperty(prop, value, 'Release');
    

    function updateBuildPropertyToDebugAndRelease(prop, value) 
        console.log('Xcode Updating ' + prop + '=' + value );
        myProj.updateBuildProperty(prop, value, 'Debug');
        myProj.updateBuildProperty(prop, value, 'Release');
    


    // Getting app id and name from config.xml
    let config_xml = path.join(context.opts.projectRoot, 'config.xml');
    let data = fs.readFileSync(config_xml).toString();
    let etree = et.parse(data);
    let appId = etree.getroot().attrib.id ;
    let appName = etree.getroot().find('name')['text'];

    // Building project path
    let projectPath = 'platforms/ios/' + appName + '.xcodeproj/project.pbxproj';

    // Opening Xcode project and parsing it
    myProj = xcode.project(projectPath);
    myProj = myProj.parseSync();

    // Common properties
    addBuildPropertyToDebugAndRelease('DEVELOPMENT_TEAM', 'CGXXXXXXX');
    addBuildPropertyToDebugAndRelease('CODE_SIGN_IDENTITY', '"Apple Development"');

    // Compilation properties
    addBuildPropertyToDebugAndRelease('ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES', 'YES');

    // Save project file
    fs.writeFileSync(projectPath, myProj.writeSync());

;

【讨论】:

以上是关于如何获取我在 config.xml 中定义的版本字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何在 app.config xml 文件中添加 Gitlab 自定义变量

如何使用Ionic 3为Android API 21构建apk?它继续为API 23构建,即使我在config.xml中将目标sdk更改为21

如何在 Mac / iOS 上制作 cordova 以停止在 config.xml 和 package.json 的插件版本号中添加插入符号 (^)

如何使用 Phonegap 2.9 在 config.xml 中声明插件

在流星应用程序中如何在cordova config.xml中添加orgin = *?

如何将注解与 faces-config.xml 混合