如何获取我在 config.xml 中定义的版本字符串
How do I get the version string I defined in the config.xml
我如何知道我的 Cordova 应用程序是哪个版本?我需要该信息才能在“关于”屏幕中显示它。
是否可以读取 config.xml 并获取我已经在此文件中维护的版本字符串?
<widget ... version="0.0.1" ...
我想要一个解决方案,无需在代码中的多个位置维护应用程序的版本号。另外,我不想要用于该目的的插件,因为大多数插件不支持 Android、iOS 和浏览器作为平台。
还是我忽略了核心插件属性?
或者是否有一种解决方案,我维护一个文件,而不是 config.xml,config.xml 从该文件获取版本信息?
您如何在应用的“关于”屏幕中实施 "display version info"?任何提示表示赞赏。
我的 Cordova 版本是:
>cordova -v
4.2.0
我会做这样的事情:
cordova.getAppVersion.getVersionNumber().then(function (version) {
if (!window.localStorage['version'] || window.localStorage['version'] < version) {
window.localStorage['version'] = version;
}
});
这样你就可以在任何需要的地方调用 window.localStorage['version']
。
我使用 https://github.com/whiteoctober/cordova-plugin-app-version 中描述的插件
第 1 步:cordova 插件添加 https://github.com/whiteoctober/cordova-plugin-app-version.git
2 步(剪切和粘贴)
如果您使用 jQuery 或 AngularJS,则支持承诺样式。使用类似:
cordova.getAppVersion.getVersionNumber().then(function (version) {
$('.version').text(version);
});
如果没有,传一个回调函数:
cordova.getAppVersion.getVersionNumber(function (version) {
alert(version);
});
干杯
如果您对使用任何第三方插件来实现此目的不感兴趣,那么我认为 Cordova hooks 是您的不二之选。您可以想出一个 before_build
挂钩来从 config.xml 文件中读取版本并在应用程序中使用相同的版本。
幸运的是,这个钩子在下面的 link 中很容易为您提供,他们正在从 config.xml 读取版本并将其作为依赖项注入到需要的地方。
建议你也看看cordova hooks的官方文档,以便更好地理解。
事实上,您也可以尝试从 config.xml 中读取版本信息,并直接将其放在您可以在 index.html
中创建的占位符中以显示版本信息。这可以在 cordova 构建之前使用钩子完成,钩子又使用执行文件操作的 windows 批处理文件。您可以在我的 github page.
中查看使用批处理文件的 cordova 挂钩工作示例
根据@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
// 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" />
根据其他答案,我创建了以下 before_prepare
挂钩,它在 cordova 9 / ionic 5
中最适合我。
它不需要任何额外的库来解析配置 xml,因为它通过正则表达式获取版本。
它适用于 browser
、iOS
和 android
平台环境。
它在 ionic serve
中也不起作用,因为此处未执行 cordova 挂钩。
#!/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");
我在2020年12月写的。现在最简单的解决办法就是使用插件cordova-plugin-app-version
Reads the version of your app from the target build settings [got from 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>
这里是我对不同答案的汇编。
我用它来更新 Xcode 项目中的一些参数以进行插件编译。
你可以看到我从 config.xml
获取应用程序 ID 和名称
你可以将它添加到 after_prepare 钩子中:
<hook src="scripts/addBuildSettingsToXcode.js" type="after_prepare" />
#!/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());
};
我如何知道我的 Cordova 应用程序是哪个版本?我需要该信息才能在“关于”屏幕中显示它。
是否可以读取 config.xml 并获取我已经在此文件中维护的版本字符串?
<widget ... version="0.0.1" ...
我想要一个解决方案,无需在代码中的多个位置维护应用程序的版本号。另外,我不想要用于该目的的插件,因为大多数插件不支持 Android、iOS 和浏览器作为平台。
还是我忽略了核心插件属性?
或者是否有一种解决方案,我维护一个文件,而不是 config.xml,config.xml 从该文件获取版本信息?
您如何在应用的“关于”屏幕中实施 "display version info"?任何提示表示赞赏。
我的 Cordova 版本是:
>cordova -v
4.2.0
我会做这样的事情:
cordova.getAppVersion.getVersionNumber().then(function (version) {
if (!window.localStorage['version'] || window.localStorage['version'] < version) {
window.localStorage['version'] = version;
}
});
这样你就可以在任何需要的地方调用 window.localStorage['version']
。
我使用 https://github.com/whiteoctober/cordova-plugin-app-version 中描述的插件 第 1 步:cordova 插件添加 https://github.com/whiteoctober/cordova-plugin-app-version.git
2 步(剪切和粘贴) 如果您使用 jQuery 或 AngularJS,则支持承诺样式。使用类似:
cordova.getAppVersion.getVersionNumber().then(function (version) {
$('.version').text(version);
});
如果没有,传一个回调函数:
cordova.getAppVersion.getVersionNumber(function (version) {
alert(version);
});
干杯
如果您对使用任何第三方插件来实现此目的不感兴趣,那么我认为 Cordova hooks 是您的不二之选。您可以想出一个 before_build
挂钩来从 config.xml 文件中读取版本并在应用程序中使用相同的版本。
幸运的是,这个钩子在下面的 link 中很容易为您提供,他们正在从 config.xml 读取版本并将其作为依赖项注入到需要的地方。
建议你也看看cordova hooks的官方文档,以便更好地理解。
事实上,您也可以尝试从 config.xml 中读取版本信息,并直接将其放在您可以在 index.html
中创建的占位符中以显示版本信息。这可以在 cordova 构建之前使用钩子完成,钩子又使用执行文件操作的 windows 批处理文件。您可以在我的 github page.
根据@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
// 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" />
根据其他答案,我创建了以下 before_prepare
挂钩,它在 cordova 9 / ionic 5
中最适合我。
它不需要任何额外的库来解析配置 xml,因为它通过正则表达式获取版本。
它适用于 browser
、iOS
和 android
平台环境。
它在 ionic serve
中也不起作用,因为此处未执行 cordova 挂钩。
#!/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");
我在2020年12月写的。现在最简单的解决办法就是使用插件cordova-plugin-app-version
Reads the version of your app from the target build settings [got from
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>
这里是我对不同答案的汇编。 我用它来更新 Xcode 项目中的一些参数以进行插件编译。
你可以看到我从 config.xml
获取应用程序 ID 和名称你可以将它添加到 after_prepare 钩子中:
<hook src="scripts/addBuildSettingsToXcode.js" type="after_prepare" />
#!/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());
};