Reputation: 1345
I am writing a Cordova plugin for android that has a Gradle dependency. I want the developers to be able to specify what version of the dependency they want without editing the plugin directly.
Right now I have this in my plugin.xml:
<hook type="before_plugin_install" src="modifyPluginXML.js" />
<framework src="resources/custom.gradle" custom="true" type="gradleReference"/>
<framework src="$TO_BE_DEFINED_PACKAGE" type="gradleReference"/>
and I have a hook that takes the command line argument and replaces $TO_BE_DEFINED_PACKAGE in the plugin.xml with the package path/name provided in the argument.
Here is the modifyPluginXML.js hook:
module.exports = function(context) {
var Q = context.requireCordovaModule('q');
var deferral = new Q.defer();
var fs = require('fs'),
xml2js = require('xml2js'),
path = require('path'),
util = require('util');
var parser = new xml2js.Parser({explicitArray:false});
var cb = function(data){
console.log("plugin.xml updated");
deferral.resolve();
}
fs.readFile(__dirname + '/plugin.xml', function(err, data) {
parser.parseString(data, function (err, result) {
//console.log(util.inspect(result, false, null));
var externalDep = "";
for (var i = 0; i < process.argv.length;i++){
if(process.argv[i].indexOf('EXTERNAL_DEP') >= 0){
externalDep = process.argv[i].replace("EXTERNAL_DEP=", "");
console.log(externalDep);
}
}
result.plugin.platform.framework[1]['$'].src = externalDep;
var builder = new xml2js.Builder();
var xml = builder.buildObject(result);
var filepath = path.normalize(path.join(__dirname, '/plugin.xml'));
fs.writeFile(filepath, xml, cb);
});
});
return deferral.promise;
}
As of right now if you add the plugin with cordova plugin add plugin-name EXTERNAL_DEP=5.0
it will correctly replace the framework src in the plugin.xml with the source specified in the command line argument.
The problem I am running into is that cordova doesn't seem to care about the new plugin.xml. It still uses the old plugin.xml's framework tags.
In the generate build.gradle file I still see this:
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
// SUB-PROJECT DEPENDENCIES START
debugCompile project(path: "CordovaLib", configuration: "debug")
releaseCompile project(path: "CordovaLib", configuration: "release")
compile "$TO_BE_DEFINED_PACKAGE"
// SUB-PROJECT DEPENDENCIES END
}
So even though the plugin.xml is getting updated correctly with the before_plugin_install hook, cordova uses the old value to generate the build.gradle file.
Does anyone have any suggestions, or different routes I could take?
Upvotes: 1
Views: 726
Reputation: 1345
Took @jcesarmobile advice and instead wrote to the build.gradle file. I first check the cmd line for any arguments than I check the config.xml for any variables set for the specific plugin. Here is the script I came up with.
module.exports = function (context) {
var Q = context.requireCordovaModule('q');
var deferral = new Q.defer();
var result = null;
var externalDep = null;
var fs = require('fs'),
xml2js = require('xml2js'),
path = require('path'),
util = require('util');
var gradleLocation = process.cwd() + "/platforms/android/build.gradle";
var parser = new xml2js.Parser({explicitArray: false});
function findPluginVarInConfig() {
fs.readFile(process.cwd() + '/config.xml', function (err, data) {
parser.parseString(data, function (err, result) {
//console.log(util.inspect(result, false, null));
for (var i = 0; i < result.widget.plugin.length; i++) {
if (result.widget.plugin[i]['$'].name == 'plugin-name') {
externalDep = result.widget.plugin[i].variable['$'].value;
}
}
if (externalDep) {
console.log("found " + externalDep + " in config.xml");
replaceGradleReference();
} else {
console.log("plugin-name could not find defined dependency defined in config.xml or cmd line args defaulting to 0.0.1");
externalDep = "0.0.1";
replaceGradleReference();
}
});
});
}
function findPluginVarInCmdArgs() {
for (var i = 0; i < process.argv.length; i++) {
if (process.argv[i].indexOf('EXTERNAL_DEP') >= 0) {
externalDep = process.argv[i].replace("EXTERNAL_DEP=", "");
}
}
if (externalDep) {
console.log("found " + externalDep + " in command line args");
replaceGradleReference();
} else {
findPluginVarInConfig();
}
}
function replaceGradleReference() {
fs.readFile(gradleLocation, 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
var replaced = false;
if (data.indexOf('$INITIAL_PBR_SOURCE' >= 0)) {
result = data.replace('$INITIAL_PBR_SOURCE', function (text) {
replaced = true;
return externalDep
});
if (!replaced) {
console.log("FAILED TO ADD " + externalDep + " TO BUILD SCRIPT");
}
}
if (result) {
fs.writeFile(gradleLocation, result, 'utf8', function (err) {
if (err) {
console.log(err);
} else {
console.log("Succesfully added " + externalDep + " to buildscript");
}
deferral.resolve();
});
} else {
console.log("PBR external dependency is already added to buildscript");
}
});
}
findPluginVarInCmdArgs();
return deferral.promise;
};
Upvotes: 0
Reputation: 53301
You don't have to write in the plugin.xml because that is only read on plugin install.
If you want to edit the gradle references you can write on the platforms/android/build.gradle file, that is where the references from the plugin.xml are copied.
Anyway, I don't think is a good idea to allow users to choose the version to use, you, as developer of the plugin, should choose the version that you tested and you are sure that works fine, using a different version might do the plugin to not work correctly or not work at all.
Upvotes: 1