cordova-acoustic-mobile-push
Version:
Allows Cordova applications to integrate with Acoustic MCE Push Services
798 lines (730 loc) • 31.3 kB
JavaScript
/*
* Copyright (C) 2025 Acoustic, L.P. All rights reserved.
*
* NOTICE: This file contains material that is confidential and proprietary to
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
* prohibited.
*/
const fs = require('fs');
const plist = require('plist');
const path = require('path');
const ncp = require('ncp');
const xml2js = require('xml2js');
const chalk = require('chalk');
const { execSync } = require('child_process');
/**
* Used to add CampaignConfig.json.
*
* @param {*} currentAppWorkingDirectory Current application directory where cordova plugin add or npm install is being ran.
*/
function addOrReplaceMobilePushConfigFile(currentAppWorkingDirectory) {
const configName = 'CampaignConfig.json';
const pluginPath = path.resolve(__dirname, '..');
const defaultConfigFile = path.join(pluginPath, configName);
const appConfigFile = path.join(currentAppWorkingDirectory, configName);
logMessageInfo("Add or Replace CampaignConfig.json file into the App at " + currentAppWorkingDirectory);
if(!fs.existsSync(appConfigFile)) {
logMessageInfo("Add default CampaignConfig.json file into project - " + appConfigFile);
fs.copyFileSync(defaultConfigFile, appConfigFile);
} else {
logMessageWarning("CampaignConfig.json already exists at " + currentAppWorkingDirectory + "/" + configName);
}
return {
pluginPath: pluginPath,
defaultConfigFile: defaultConfigFile,
appConfigFile: appConfigFile
};
}
/**
* Used to read current settings in CampaignConfig.json and creating MceConfig.json.
*
* @param {*} currentAppWorkingDirectory Current application directory where cordova plugin add or npm install is being ran.
* @param {*} pluginPath Path to plugin.
* @param {*} campaignConfigFile CampaignConfig.json file.
*/
function readAndSaveMceConfig(currentAppWorkingDirectory, pluginPath, campaignConfigFile) {
try {
if (campaignConfigFile.android && campaignConfigFile.iOS) {
if (campaignConfigFile.android && hasAndroidPlatform(currentAppWorkingDirectory)) {
addGradlePropertiesToApp(currentAppWorkingDirectory);
const androidConfig = JSON.stringify(campaignConfigFile.android, null, 2);
const androidDestinationPath = path.join(pluginPath, 'postinstall/android/MceConfig.json');
saveConfig(androidConfig, androidDestinationPath);
} else {
logMessageError('Skipped Android install:platform is not installed!');
}
if (campaignConfigFile.iOS && hasIosPlatform(currentAppWorkingDirectory)) {
const iosConfig = JSON.stringify(campaignConfigFile.iOS, null, 2);
const iosDestinationPath = path.join(pluginPath, 'postinstall/ios/MceConfig.json');
saveConfig(iosConfig, iosDestinationPath);
} else {
logMessageError('Skipped iOS install:platform is not installed!');
}
} else {
logMessageError(`No "android/ios" object found in the ${campaignConfigFile} file.`);
}
if (campaignConfigFile.plugins) {
managePlugins(currentAppWorkingDirectory, pluginPath, campaignConfigFile);
} else {
logMessageError("Plugins section missing from Campaign");
}
} catch (error) {
if (error.code === 'ENOENT') { // Handle "file not found" error specifically
logMessageError(`File not found: ${campaignConfigFile}`);
} else {
logMessageError(`Error reading or parsing ${campaignConfigFile} file: ${error}`);
}
}
}
/**
* Used to save json configuration.
*
* @param {*} configData Data to be saved.
* @param {*} destinationPath Location to save file.
*/
function saveConfig(configData, destinationPath) {
try {
fs.writeFileSync(destinationPath, configData, { flag: 'w' });
logMessageWarning(`${destinationPath} saved successfully!`);
} catch (error) {
logMessageError(`Error saving ${destinationPath}:`, error);
}
}
/**
* Used to add or remove cordova plugin that are configured in CampaignConfig.json.
*
* @param {*} currentAppWorkingDirectory Current application directory where cordova plugin add or npm install is being ran.
* @param {*} pluginPath Path to plugin.
* @param {*} configData CampaignConfig.json data.
*/
function managePlugins(currentAppWorkingDirectory, pluginPath, configData) {
try {
logMessageTitle("Install required cordova plugins...");
let pluginName = "cordova-acoustic-mobile-push"
if (pluginPath.includes('-beta')) {
pluginName = `${pluginName}-beta`
}
let packagePluginPath = path.join(currentAppWorkingDirectory, 'node_modules', pluginName);
logMessageTitle(`Install base ${pluginName}`);
// iOS
if (hasIosPlatform(currentAppWorkingDirectory)) {
updateConfigXMLPreference(currentAppWorkingDirectory, "iOSAppkey", configData.iOS.appKey.dev);
updateConfigXMLPreference(currentAppWorkingDirectory, "iOSProdkey", configData.iOS.appKey.prod);
updateConfigXMLPreference(currentAppWorkingDirectory, "serverUrl", configData.iOS.baseUrl);
updateConfigXMLPreference(currentAppWorkingDirectory, "logLevel", configData.iOS.logLevel);
updatePluginXMLPodName(packagePluginPath, configData.plugins.useRelease, configData);
}
// Update Android
if (hasAndroidPlatform(currentAppWorkingDirectory)) {
updateBuildExtrasGradle(packagePluginPath, configData);
addGoogleServices(currentAppWorkingDirectory, configData);
updateBuildGradleMobilePushVersion(currentAppWorkingDirectory, configData);
customAction = configData.customAction;
androidAppkey = configData.android.appKey.prod;
iOSAppkey = configData.iOS.appKey.dev;
iOSProdkey = configData.iOS.appKey.prod;
serverUrl = configData.iOS.baseUrl;
logLevel = configData.iOS.loglevel;
mceCanSyncOverride = configData.mceCanSyncOverride;
logMessageTitle(`cd "${currentAppWorkingDirectory}" && cordova plugin add ${pluginName} --variable CUSTOM_ACTIONS="${customAction}" --variable ANDROID_APPKEY="${androidAppkey}" --variable IOS_DEV_APPKEY="${iOSAppkey}" --variable IOS_PROD_APPKEY="${iOSProdkey}" --variable SERVER_URL="${serverUrl}" --variable LOGLEVEL="${logLevel}" --variable MCE_CAN_SYNC_OVERRIDE="${mceCanSyncOverride}" --force`);
execSync(`cd "${currentAppWorkingDirectory}" && cordova plugin add ${pluginName} --variable CUSTOM_ACTIONS="${customAction}" --variable ANDROID_APPKEY="${androidAppkey}" --variable IOS_DEV_APPKEY="${iOSAppkey}" --variable IOS_PROD_APPKEY="${iOSProdkey}" --variable SERVER_URL="${serverUrl}" --variable LOGLEVEL="${logLevel}" --variable MCE_CAN_SYNC_OVERRIDE="${mceCanSyncOverride}" --force`, { stdio: 'inherit', cwd: process.cwd() });
}
} catch (error) {
console.error(`Failed to manage plugin ${plugin}:`, error);
} finally {
if (!hasIosPlatform(currentAppWorkingDirectory) && !hasAndroidPlatform(currentAppWorkingDirectory)) {
logMessageError(`Error not installing any additional plugin until you add a platform iOS or Android.`);
return;
}
Object.entries(configData.plugins).forEach(([plugin, isEnabled]) => {
if (plugin === 'cordova-acoustic-mobile-push' || plugin === 'cordova-acoustic-mobile-push-beta') {
return;
}
if (!plugin.includes('cordova-acoustic-mobile-push-')) {
return;
}
logMessageTitle(`Install ${plugin}`);
let installed = isNPMPluginInstalled(currentAppWorkingDirectory, plugin);
let cordovaPluginInstalled = isPluginInstalled(currentAppWorkingDirectory, plugin);
let update = false;
try {
logMessageInfo(`Review ${plugin}:installed=${installed}`);
if (isEnabled == true && !installed) {
logMessageInfo(`Adding ${plugin}...`);
if (plugin.includes('cordova-acoustic-mobile-push-plugin-location')) {
syncRadius = ""
syncInterval = ""
if (hasIosPlatform(currentAppWorkingDirectory)) {
syncRadius = configData.iOS.location.sync.syncRadius;
syncInterval = configData.iOS.location.sync.syncInterval;
} else if (hasAndroidPlatform(currentAppWorkingDirectory)) {
syncRadius = configData.android.location.sync.syncRadius;
syncInterval = configData.android.location.sync.syncInterval;
}
if (hasIosPlatform(currentAppWorkingDirectory) || hasAndroidPlatform(currentAppWorkingDirectory)) {
if(cordovaPluginInstalled) {
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin rm ${plugin} --variable SYNC_RADIUS="${syncRadius}" --variable SYNC_INTERVAL="${syncInterval}"`);
// runExecSync(`cd "${currentAppWorkingDirectory}" && npm uninstall ${plugin} --ignore-scripts`);
}
runExecSync(`cd "${currentAppWorkingDirectory}" && npm install ${plugin} --ignore-scripts`);
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin add ${plugin} --variable SYNC_RADIUS="${syncRadius}" --variable SYNC_INTERVAL="${syncInterval}"`);
update = true;
}
} else if (plugin.includes('cordova-acoustic-mobile-push-plugin-beacon')) {
myUuid = ""
if (hasIosPlatform(currentAppWorkingDirectory)) {
myUuid = configData.iOS.location.ibeacon.UUID;
} else if (hasAndroidPlatform(currentAppWorkingDirectory)) {
myUuid = configData.android.location.ibeacon.uuid;
}
if (hasIosPlatform(currentAppWorkingDirectory) || hasAndroidPlatform(currentAppWorkingDirectory)) {
if (cordovaPluginInstalled) {
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin rm ${plugin} --variable UUID="${myUuid}"`);
}
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin add ${plugin} --variable UUID="${myUuid}"`);
update = true;
}
} else {
if (cordovaPluginInstalled) {
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin rm ${plugin}`);
}
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin add ${plugin}`);
update = true;
}
} else if (isEnabled == false && installed) {
logMessageInfo(`Removing ${plugin}...`);
runExecSync(`cd "${currentAppWorkingDirectory}" && cordova plugin rm ${plugin}`);
} else {
logMessageInfo(`Skip for ${plugin} with ${isEnabled} which is installed using ${installed}`);
// update = true; review
}
} catch (error) {
logMessageError(`Failed to manage plugin ${plugin}:`, error);
}
if (update) {
packagePluginPath = path.join(currentAppWorkingDirectory, 'node_modules', plugin);
// Update iOS
if (hasIosPlatform(currentAppWorkingDirectory)) {
// Update podfile to use
updatePluginXMLPodName(packagePluginPath, configData.plugins.useRelease, configData);
}
// Update Android
if (hasAndroidPlatform(currentAppWorkingDirectory)) {
// Update gradle for beta/release version
if (!plugin.includes('cordova-acoustic-mobile-push-plugin-ios-notification-service') &&
!plugin.includes('cordova-acoustic-mobile-push-plugin-action-menu') &&
!plugin.includes('cordova-acoustic-mobile-push-plugin-passbook')) {
updateBuildExtrasGradle(packagePluginPath, configData);
}
}
}
});
}
}
function readMceConfig(campaignConfigFile) {
let jsonData;
try {
// Read the file synchronously
const fileData = fs.readFileSync(campaignConfigFile, 'utf8');
jsonData = JSON.parse(fileData);
} catch (error) {
logMessageError(`Failed to manage plugin ${plugin}:`, error);
}
return jsonData;
}
/**
* Used to update MceConfig.json to application location.
*
* @param {*} currentAppWorkingDirectory Current application directory where cordova plugin add or npm install is being ran.
* @param {*} pluginPath Path to plugin.
* @param {*} configData CampaignConfig.json data.
*/
function updateMceConfig(currentAppWorkingDirectory, pluginPath, configData) {
if (hasAndroidPlatform(currentAppWorkingDirectory)) {
updateMceConfigHelper(currentAppWorkingDirectory, pluginPath, configData, 'android');
}
if (hasIosPlatform(currentAppWorkingDirectory)) {
updateMceConfigHelper(currentAppWorkingDirectory, pluginPath, configData, 'ios');
}
}
/**
* Used to help save MceConfig.json to application location.
*
* @param {*} currentAppWorkingDirectory Current application directory where cordova plugin add or npm install is being ran.
* @param {*} pluginPath Path to plugin.
* @param {*} configData CampaignConfig.json data.
* @param {*} platform Use 'android' or 'ios'.
*/
function updateMceConfigHelper(currentAppWorkingDirectory, pluginPath, configData, platform) {
try {
// Read the file synchronously
const mceConfigPath = path.join(pluginPath, `postinstall/${platform}/MceConfig.json`);
const fileData = fs.readFileSync(mceConfigPath, 'utf8');
const jsonData = JSON.parse(fileData);
let needsLocation = false;
if (configData.plugins["cordova-acoustic-mobile-push-plugin-location"] ||
configData.plugins["cordova-acoustic-mobile-push-plugin-location-beta"] ||
configData.plugins["cordova-acoustic-mobile-push-plugin-beacon"] ||
configData.plugins["cordova-acoustic-mobile-push-plugin-beacon-beta"] ||
configData.plugins["cordova-acoustic-mobile-push-plugin-geofence"] ||
configData.plugins["cordova-acoustic-mobile-push-plugin-geofence-beta"]) {
needsLocation = true;
}
if (!needsLocation) {
// delete location config
delete jsonData["location"];
}
const config = JSON.stringify(jsonData, null, 2);
saveConfig(config, mceConfigPath);
// copy to app
let appPath = `platforms/${platform}/app/src/main/assets/MceConfig.json`;
if (platform === 'ios') {
appPath = `platforms/${platform}/MceConfig.json`;
}
const appDestinationPath = path.join(currentAppWorkingDirectory, appPath);
saveConfig(config, appDestinationPath);
// Update values in config.xml
logMessageTitle('Update values in config.xml');
const mainConfigXMLData = readXMLToJson(`${currentAppWorkingDirectory}/config.xml`);
if (platform == 'ios' && jsonData) {
const appConfigPath = `${currentAppWorkingDirectory}/platforms/ios/${mainConfigXMLData.widget.name[0]}/config.xml`;
var xmlData = readXMLToJson(appConfigPath);
// update file
for (let i = 0; i < xmlData.widget.preference.length; i++) {
var pref = xmlData.widget.preference[i]["$"]['name'];
// logMessageTitle(pref);
if (jsonData[pref] !== undefined) {
xmlData.widget.preference[i]["$"]['value'] = jsonData[pref];
} else if (pref == 'prodAppKey' && jsonData.appKey.dev) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.appKey.prod;
} else if (pref == 'devAppKey' && jsonData.appKey.dev) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.appKey.dev;
} else if (pref == 'autoInitialize' && jsonData.location.autoInitialize) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.location.autoInitialize;
} else if (pref == 'beaconUUID' && jsonData.location.ibeacon.UUID) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.location.ibeacon.UUID;
} else if (pref == 'locationSyncRadius' && jsonData.location.sync.syncRadius) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.location.sync.syncRadius;
} else if (pref == 'locationSyncInterval' && jsonData.location.sync.syncInterval) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.location.sync.syncInterval;
} else if (pref == 'locationSyncInterval' && jsonData.location.sync.syncInterval) {
xmlData.widget.preference[i]["$"]['value'] = jsonData.location.sync.syncInterval;
}
}
writeJsonToXML(appConfigPath, xmlData);
}
} catch (error) {
logMessageError(`Error reading or parsing ${mceConfigPath} file: ${error}`);
}
}
/**
* Return Javascript JSON object from XML file.
*
* @param {*} configPath Path of the XML file.
* @returns Javascript JSON object from XML file.
*/
function readXMLToJson(configPath) {
var resultFound
try {
const xmlData = fs.readFileSync(configPath, 'utf8');
logMessageTitle(`Original ${configPath}:`);
logMessageInfo(`${xmlData}`);
var parseString = require("xml2js").parseString;
parseString(xmlData, function(err, result) {
if (err)
logMessageError(`Parsing error for ${configPath}:\n${err}`);
resultFound = result;
})
} catch (error) {
logMessageError(`Failed to read xml ${configPath}:`, error);
}
return resultFound
}
/**
* Write Javascript JSON object to XML file.
*
* @param {*} configPath Path of the XML file to write.
* @param {*} jsonDataToConvert Javascript JSON object to XML file.
*/
function writeJsonToXML(configPath, jsonDataToConvert) {
try {
var builder = new xml2js.Builder();
var xml = builder.buildObject(jsonDataToConvert);
saveConfig(xml, configPath);
logMessageTitle(`Write to ${configPath}:`);
logMessageInfo(`${xml}`);
} catch (error) {
logMessageError(`Failed to write xml ${configPath}:`, error);
}
}
/**
* This function will print and run command.
*
* @param {*} cmdToRun Command to run.
*/
function runExecSync(cmdToRun) {
try {
console.log(cmdToRun);
const result = execSync(`${cmdToRun}`);
return result !== null ? result.toString() : result;
} catch (error) {
console.error(`Failed to run command:${cmdToRun}:`, error);
}
}
/**
* Used to update preference values in config.xml file.
*
* @param {*} currentAppWorkingDirectory Current application directory where cordova plugin add or npm install is being ran.
* @param {*} nam Name property in xml.
* @param {*} val Value in xml.
*/
function updateConfigXMLPreference(currentAppWorkingDirectory, nam, val) {
try {
const mainConfigXMLData = readXMLToJson(`${currentAppWorkingDirectory}/config.xml`);
let appName = mainConfigXMLData.widget.name[0];
let configPathEnd = (`platforms/ios/${appName}/config.xml`);
let configPath = path.join(currentAppWorkingDirectory, configPathEnd);
let configContent = fs.readFileSync(configPath, 'utf8');
const preferenceToAdd = `<preference name="${nam}" value="${val}" />`;
const regx = new RegExp(`\\<preference\\s*name="` + nam + `"\\s*value="[\\w\\s\\d\\:\\/\\-\\.]*"\\s*/>`, 'gi');
if (regx.test(configContent)) {
configContent = configContent.replace(regx, preferenceToAdd);
} else {
// Add
const widgetString = ` ${preferenceToAdd}\n</widget>\n`;
let configContentArray = configContent.split('</widget>');
configContent = configContentArray[0] + widgetString + configContentArray[1];
}
fs.writeFileSync(configPath, configContent, 'utf8');
console.log(`Add preference to ${configPath}`);
} catch (error) {
console.error(`Error updating ${configPath}:`, error);
}
}
/**
* Check if npm package has been installed.
*
* @param {*} pluginName Plugin name to be tested
* @returns Whether plugin is already installed.
*/
function isNPMPluginInstalled(currentAppWorkingDirectory, pluginName) {
const appPackageJsonFile = path.join(currentAppWorkingDirectory, 'package.json');
const packageJsonData = fs.readFileSync(appPackageJsonFile, 'utf8');
const packageJson = JSON.parse(packageJsonData);
return packageJson.dependencies && packageJson.dependencies[pluginName] ||
packageJson.devDependencies && packageJson.devDependencies[pluginName] ||
false;
}
/**
* Check if plugin has been installed.
*
* @param {*} pluginName Plugin name to be tested
* @returns Whether plugin is already installed.
*/
function isPluginInstalled(currentAppWorkingDirectory, pluginName) {
var cordovaPluginList = execSync(`cd "${currentAppWorkingDirectory}" && cordova plugin list`).toString();
return cordovaPluginList ? cordovaPluginList.includes(pluginName) : false;
}
/**
* Update the podname to be used in podfile.
*
* @param {*} pluginPath Path to plugin.
* @param {*} isRelease Whether configuration is to use release.
* @param {*} configData CampaignConfig.json file data.
*/
function updatePluginXMLPodName(plugPath, isRelease, configData) {
try {
let pluginPath = path.join(plugPath, "plugin.xml");
let pluginContent = fs.readFileSync(pluginPath, 'utf8');
let podNameRegex = /<pod name="AcousticMobilePush.*\/>/;
let podname = isRelease ? "AcousticMobilePush" : "AcousticMobilePushDebug";
if (plugPath.includes('cordova-acoustic-mobile-push-plugin-ios-notification-service')) {
podNameRegex = /<pod name="AcousticMobilePushNotification.*\/>/;
podname = isRelease ? "AcousticMobilePushNotification" : "AcousticMobilePushNotificationDebug";
}
if (podNameRegex.test(pluginContent)) {
let version = '';
if (configData.iOSVersion) {
version = `spec="${configData.iOSVersion}" `
}
const podNameUpdate = `<pod name="${podname}" ${version}/>`;
pluginContent = pluginContent.replace(podNameRegex, podNameUpdate);
fs.writeFileSync(pluginPath, pluginContent, 'utf8');
logMessageInfo(`Update to use podName: ${podname} for ${pluginPath}`);
}
} catch (error) {
logMessageError(`Error updating ${pluginPath}:`, error);
}
}
/**
* Adjust build-extras.gradle which is used to indicate to beta or release version of Android.
*
* @param {*} pluginPath Path to plugin.
* @param {*} configData CampaignConfig.json file data.
*/
function updateBuildExtrasGradle(plugPath, configData) {
try {
let pluginPath = path.join(plugPath, "src/android/build-extras.gradle");
let pluginContent = fs.readFileSync(pluginPath, 'utf8');
const mavenUrlRegex = /maven\s*{\s*url\s*\"https:\/\/s01\.oss\.sonatype\.org\/content\/repositories\/staging"\s*}/;
if (configData.plugins.useRelease && mavenUrlRegex.test(pluginContent)) {
// Remove Maven URL if useRelease is true and it exists
pluginContent = pluginContent.replace(mavenUrlRegex, '');
fs.writeFileSync(pluginPath, pluginContent, 'utf8');
logMessageInfo('Maven URL removed from build-extras.gradle');
} else if (!configData.plugins.useRelease && !mavenUrlRegex.test(pluginContent)) {
// Add Maven URL if useRelease is true and it doesn't already exist
const mavenUrlString = 'mavenCentral()\n maven { url "https://s01.oss.sonatype.org/content/repositories/staging" }\n';
let pluginContentArray = pluginContent.split('mavenCentral()')
pluginContent = pluginContentArray[0] + mavenUrlString + pluginContentArray[1]
fs.writeFileSync(pluginPath, pluginContent, 'utf8');
logMessageInfo(`Maven URL added to ${pluginPath}`);
} else {
logMessageWarning(`No changes needed in ${pluginPath}`);
}
} catch (error) {
logMessageError(`Error updating ${pluginPath}:`, error);
}
}
/**
* Display a message in green in terminal.
*
* @param {*} msg Message to display.
*/
function logMessageTitle(msg) {
console.log(chalk.green.bold(msg));
}
/**
* Display a message in blue in terminal.
*
* @param {*} msg Message to display.
*/
function logMessageInfo(msg) {
console.log(chalk.blue.bold(msg));
}
/**
* Display a message in yellow in terminal.
*
* @param {*} msg Message to display.
*/
function logMessageWarning(msg) {
console.log(chalk.yellow.bold(msg));
}
/**
* Display a message in red in terminal.
*
* @param {*} msg Message to display.
*/
function logMessageError(msg) {
console.log(chalk.red.bold(msg));
}
function getInstallDirectory() {
let installDirectory = process.cwd();
if (installDirectory.includes('node_modules')) {
let p = installDirectory.split('node_modules')
installDirectory = p[0]
}
return installDirectory;
}
/**
* Used to add default versions used for plugins in gradle.build.
*
* @param {*} appPath Path of the application being integrated.
*/
function addGradlePropertiesToApp(appPath) {
try {
let appGradlePath = path.join(appPath, "platforms/android/build.gradle");
let gradleContent = fs.readFileSync(appGradlePath, 'utf8');
const mobilePushVersionRegex = /mobilePushVersion/;
const libraryVersions =
`allprojects {
// This block encapsulates custom properties and makes them available to all
project.ext {
// The following are only a few examples of the types of properties you can define.
// Sdk and tools
mobilePushVersion = "3.10.122"
androidxLibVersion = "1.6.0"
playServicesBaseVersion = "18.3.0"
playServicesLocationVersion = "21.0.1"
firebaseCoreVersion = "19.0.2"
firebaseMessagingVersion = "22.0.0"
// This version supports 21 minimal
securityCryptoVersion = "1.1.0"
}
}`
if(mobilePushVersionRegex.test(gradleContent)) {
logMessageWarning(`No changes needed in ${appGradlePath} already has default values.`);
} else {
gradleContent = gradleContent.concat("\n", libraryVersions);
fs.writeFileSync(appGradlePath, gradleContent, 'utf8');
logMessageWarning(`Added default values in ${appGradlePath}`);
}
} catch (error) {
logMessageError(`Error updating ${appGradlePath}:`, error);
}
}
/**
* Adjust build.gradle which is used to indicate which version of MobilePush to use.
*
* @param {*} appPath Path of the application being integrated.
* @param {*} configData CampaignConfig.json file data.
*/
function updateBuildGradleMobilePushVersion(appPath, configData) {
try {
let updateVersion = "+";
let appGradlePath = path.join(appPath, "platforms/android/build.gradle");
let gradleContent = fs.readFileSync(appGradlePath, 'utf8');
const mobilePushVersionRegex = /mobilePushVersion = "(\d+\.\d+\.\d+|\+)"/;
const androidxLibVersionRegex = /androidxLibVersion = "(\d+\.\d+\.\d+|\+)"/;
const playServicesBaseVersionRegex = /playServicesBaseVersion = "(\d+\.\d+\.\d+|\+)"/;
const playServicesLocationVersionRegex = /playServicesLocationVersion = "(\d+\.\d+\.\d+|\+)"/;
const firebaseCoreVersionRegex = /firebaseCoreVersion = "(\d+\.\d+\.\d+|\+)"/;
const firebaseMessagingVersionRegex = /firebaseMessagingVersion = "(\d+\.\d+\.\d+|\+)"/;
if (configData.androidVersion) {
updateVersion = configData.androidVersion;
}
gradleContent = gradleContent.replace(mobilePushVersionRegex, `mobilePushVersion = "${updateVersion}"`);
if (configData.androidxLibVersion) {
updateVersion = configData.androidxLibVersion;
gradleContent = gradleContent.replace(androidxLibVersionRegex, `androidxLibVersion = "${updateVersion}"`);
}
if (configData.playServicesBaseVersion) {
updateVersion = configData.playServicesBaseVersion;
gradleContent = gradleContent.replace(playServicesBaseVersionRegex, `playServicesBaseVersion = "${updateVersion}"`);
}
if (configData.playServicesLocationVersion) {
updateVersion = configData.playServicesLocationVersion;
gradleContent = gradleContent.replace(playServicesLocationVersionRegex, `playServicesLocationVersion = "${updateVersion}"`);
}
if (configData.firebaseCoreVersion) {
updateVersion = configData.firebaseCoreVersion;
gradleContent = gradleContent.replace(firebaseCoreVersionRegex, `firebaseCoreVersion = "${updateVersion}"`);
}
if (configData.firebaseMessagingVersion) {
updateVersion = configData.firebaseMessagingVersion;
gradleContent = gradleContent.replace(firebaseMessagingVersionRegex, `firebaseMessagingVersion = "${updateVersion}"`);
}
fs.writeFileSync(appGradlePath, gradleContent, 'utf8');
logMessageInfo(`Updated ${appGradlePath}`);
} catch (error) {
logMessageError(`Error updating ${appGradlePath}:`, error);
}
}
/**
* Used to add google services to application gradle.
*
* @param {*} appPath Path of the application being integrated.
* @param {*} configData CampaignConfig.json file data.
*/
function addGoogleServices(appPath, configData) {
try {
let appGradlePath = path.join(appPath, "platforms/android/app/build.gradle");
let gradleContent = fs.readFileSync(appGradlePath, 'utf8');
const hasBeenAddedRegex = /Added by Acoustic/;
const googleServiceToAdd =
`buildscript {
repositories {
google()
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
maven {
url "https://maven.google.com"
name 'Google'
}
}
dependencies {
classpath 'com.google.gms:google-services:4.4.0'
}
}
// Added by Acoustic
apply plugin: 'com.google.gms.google-services'`
const googlServicesVersionRegex = /com.google.gms:google-services:"(\d+\.\d+\.\d+|\+)"/;
if (configData.addGoogleServicesToAndroid) {
if(hasBeenAddedRegex.test(gradleContent)) {
logMessageWarning(`No changes needed in ${appGradlePath} already has com.google.gms:google-services`);
} else {
gradleContent = gradleContent.concat("\n", googleServiceToAdd);
}
if (configData.comGoogleGmsGoogleServices) {
updateVersion = configData.comGoogleGmsGoogleServices;
gradleContent = gradleContent.replace(googlServicesVersionRegex, `com.google.gms:google-services:"${updateVersion}"`);
}
fs.writeFileSync(appGradlePath, gradleContent, 'utf8');
logMessageWarning(`Added com.google.gms:google-services in ${appGradlePath}`);
}
} catch (error) {
logMessageError(`Error updating ${appGradlePath}:`, error);
}
}
/**
* This will get latest release version from github for iOS.
*
* @returns Latest release version.
*/
function getLatestiOSVersion() {
return runExecSync(`curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/go-acoustic/Acoustic-Mobile-Push-iOS/releases | jq -r '.[0].tag_name'`);
}
/**
* This will get latest release version from github for Android.
*
* @returns Latest release version.
*/
function getLatestAndroidVersion() {
return runExecSync(`curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/go-acoustic/Acoustic-Mobile-Push-Android/releases | jq -r '.[0].tag_name'`);
}
/**
* Used to review if Android platform is installed.
*
* @param {*} appPath Path of the application being integrated.
* @returns If has Android platform in Cordova project.
*/
function hasAndroidPlatform(appPath) {
let androidPath = path.join(appPath, "platforms/android");
return hasDirectory(androidPath);
}
/**
* Used to review if iOS platform is installed.
*
* @param {*} appPath Path of the application being integrated.
* @returns If has iOS platform in Cordova project.
*/
function hasIosPlatform(appPath) {
let iosPath = path.join(appPath, "platforms/ios");
return hasDirectory(iosPath);
}
/**
* Helper to determine if directory exists.
*
* @returns If contains directory.
*/
function hasDirectory(folderPath) {
if (fs.existsSync(folderPath)) {
return true;
}
return false;
}
/**
* Start install of sdk on application.
*/
function startInstall() {
logMessageTitle('Setting up Acoustic Mobile Push SDK');
if (process.env.npm_command == 'uninstall') {
logMessageError('Skip for uninstall');
return;
}
const currentAppWorkingDirectory = getInstallDirectory();
const initPaths = addOrReplaceMobilePushConfigFile(currentAppWorkingDirectory);
const pluginPath = initPaths.pluginPath;
const defaultConfigFile = initPaths.defaultConfigFile;
const appConfigFile = initPaths.appConfigFile;
// Read and save corresponding ios/android json sections to postinstall folders, in the plugin project
const configData = readMceConfig(appConfigFile);
readAndSaveMceConfig(currentAppWorkingDirectory, pluginPath, configData);
updateMceConfig(currentAppWorkingDirectory, pluginPath, configData);
logMessageTitle("Installation Complete!");
}
startInstall();