UNPKG

ionic

Version:

A tool for creating and developing Ionic Framework mobile apps.

662 lines (538 loc) • 19.9 kB
//Cross walk process //See the cordova-engine-crosswalk plugin for how to install the browser as a plugin //https://github.com/MobileChromeApps/cordova-crosswalk-engine //Find CrossWalk webviews here: //https://download.01.org/crosswalk/releases/crosswalk/android/stable/ //Download the release for cordova-crosswalk-engine //Download the release for cordova-android with crosswalk //Ensure Android API 19 is installed //Run ionic platform rm android //Run ionic platform add ./engine/cordova-android-crosswalk //Run ionic plugin add ./engine/cordova-crosswalk-engine //Run android update project on android file //Run project - cordova run android BUILD_MULTIPLE_APKS=true var fs = require('fs'), path = require('path'), argv = require('optimist').argv, request = require('request'), Q = require('q'), shelljs = require('shelljs'), Task = require('./task').Task, proxyMiddleware = require('proxy-middleware'), unzip = require('unzip'), Ionic = require('../ionic').Ionic, IonicStats = require('./stats').IonicStats, _ = require('underscore'), IonicProject = require('./project'), IonicInfo = require('./info').IonicTask; shelljs.config.silent = true; var crosswalkEngineVersion = 'c0.7.1', cordovaAndroidVersion = 'c0.6.1', platforms = ['android', 'ios']; var crosswalkVersions = [ { version: '8.37.189.14', publish_date: '2014-10-10 03:26' }, { version: '9.38.208.10', publish_date: '2014-11-25 11:45' }, { version: '10.39.235.15', publish_date: '2014-12-31 13:16' }, { version: '11.40.277.7', publish_date: '2015-02-26 07:03' }, { version: '12.41.296.5', publish_date: '2015-03-05 13:19' }, { version: '13.41.318.0', publish_date: '2015-03-11 09:22', canary: true } ]; var defaultCrosswalkVersion = crosswalkVersions[4].version; var iosBrowsers = [ { platform: 'iOS', name: 'WKWebView', available: false, command: 'ionic browser add wkwebview' }, { platform: 'iOS', name: 'UIWebView', available: false, command: 'ionic browser revert ios' } ], androidBrowsers = [ { platform: 'Android', name: 'Crosswalk', available: true, command: 'ionic browser add crosswalk', versions: crosswalkVersions }, { platform: 'Android', name: 'Browser (default)', available: true, command: 'ionic browser revert android' }, { platform: 'Android', name: 'GeckoView', available: false, command: 'ionic browser add geckoview' } ]; var IonicTask = function() {}; IonicTask.prototype = new Task(); IonicTask.prototype.getCordovaCrosswalkEngine = function getCordovaCrosswalkEngine() { var q = Q.defer(); if(!fs.existsSync(path.join(process.cwd(), 'engine'))) { shelljs.mkdir(path.join(process.cwd(), 'engine')); } var cordovaCrosswalkFolderName = ['cordova-crosswalk-engine-', crosswalkEngineVersion].join(''); if(fs.existsSync(path.join(process.cwd(), 'engine', cordovaCrosswalkFolderName))) { q.resolve(); return q.promise; } var downloadUrl = ['https://github.com/driftyco/cordova-crosswalk-engine/archive/', crosswalkEngineVersion, '.zip'].join(''); var tempZipFilePath = path.join(process.cwd(), 'engine', 'cordova-crosswalk-engine.zip'); var zipOutPath = path.join(process.cwd(), 'engine'); Ionic.fetchArchive(zipOutPath, downloadUrl) .then(function(data) { q.resolve(); }, function(error) { console.log('Failed to download cordova-crosswalk-engine - ', error); q.reject(); }) return q.promise; } // IonicTask.prototype.getAndroidRuntimes = function getAndroidRuntimes() { // var command = 'echo "y" | android update sdk --no-ui --all --filter 10'; // console.log('\nFetching Android SDK API 19.1.0') // // var result = shelljs.exec(command, { silent: true } ); // // if(result.code != 0) { // // var errorMessage = 'Had an error fetching the Android SDK required for Crosswalk.'; // // this.ionic.fail(errorMessage); // // throw new Error(errorMessage); // // } // } IonicTask.prototype.copyInCrosswalkLibrariesToCrosswalkEngine = function copyInCrosswalkLibrariesToCrosswalkEngine(architecture, version) { var copyMessage = ['\nCopying over Crosswalk Webview (', architecture, ') to the Crosswalk Engine\n'].join(''); console.log(copyMessage) var xwalkFilePath = path.join(process.cwd(), 'engine', 'xwalk-webviews', architecture); var fileName = fs.readdirSync(xwalkFilePath); var cordovaCrosswalkFolder = ['cordova-crosswalk-engine-', crosswalkEngineVersion].join(''); var copySource = path.join(xwalkFilePath, fileName[0], '*'); var copyDestination = path.join(process.cwd(), 'engine', cordovaCrosswalkFolder, 'libs', 'xwalk_core_library', '/'); // console.log('copying - ', copySource, copyDestination) shelljs.cp('-R', copySource, copyDestination); var copyCompleteMessage = ['Finished copying Crosswalk Webview (', architecture, ') to the Crosswalk Engine'].join(''); console.log(copyCompleteMessage) } IonicTask.prototype.downloadCrosswalkWebview = function downloadCrosswalkWebview(architecture, version, releaseStatus) { var q = Q.defer(); var self = this; var downloadUrl = 'https://download.01.org/crosswalk/releases/crosswalk/android/' + releaseStatus + '/' + version + '/' + architecture + '/crosswalk-webview-' + version + '-' + architecture + '.zip'; var tempZipFilePath = path.join(process.cwd(), 'engine', 'xwalk-webviews', architecture); if (!fs.existsSync(path.join(process.cwd(), 'engine', 'xwalk-webviews'))) { shelljs.mkdir(path.join(process.cwd(), 'engine', 'xwalk-webviews')); } var xwalkPath = ['crosswalk-webview-', version, '-', architecture].join(''); var xwalkArchPath = path.join(tempZipFilePath, xwalkPath) if(fs.existsSync(xwalkArchPath)) { //We've already downloaded it. Copy it over! self.copyInCrosswalkLibrariesToCrosswalkEngine(architecture, version) q.resolve() return; } Ionic.fetchArchive(tempZipFilePath, downloadUrl) .then(function(data) { self.copyInCrosswalkLibrariesToCrosswalkEngine(architecture, version) q.resolve(data); }, function(error) { console.log('Crosswalk webviews failed to download - ') q.reject(error); }) return q.promise; } IonicTask.prototype.getCrosswalkWebviews = function getCrosswalkWebviews(version) { // var version = version ? version : '8.37.189.14'; var xwalkVersion = _.findWhere(crosswalkVersions, { version: version }); // console.log('xwalk', xwalkVersion) if(!xwalkVersion) { console.log('\nYou must specify a valid version from crosswalk. Run `ionic browser list` to see versions') // q.reject('You must specify a valid version from crosswalk. Run `ionic browser list` to see versions') throw new Error('Invalid version of Crosswalk specified'); } var releaseStatus = 'stable'; if(xwalkVersion.beta) { releaseStatus = 'beta'; } else if(xwalkVersion.canary) { releaseStatus = 'canary'; } var armPromise = this.downloadCrosswalkWebview('arm', version, releaseStatus); var x86Promise = this.downloadCrosswalkWebview('x86', version, releaseStatus); return Q.all([armPromise, x86Promise]); } IonicTask.prototype.downloadCordova40x = function downloadCordova40x() { var q = Q.defer(); var self = this; var crosswalkEngineUnzipName = ['cordova-android-', cordovaAndroidVersion].join(''); var downloadUrl = ['https://github.com/driftyco/cordova-android/archive/', cordovaAndroidVersion, '.zip'].join(''); var tempZipFilePath = path.join(process.cwd(), 'engine'); var cordovaAndroid4Path = path.join(tempZipFilePath, crosswalkEngineUnzipName, 'bin'); var android4BinPath = path.join(cordovaAndroid4Path, 'templates', 'cordova'); if(fs.existsSync(path.join(tempZipFilePath, crosswalkEngineUnzipName))) { self.setPermissionsForFolder(cordovaAndroid4Path); self.setPermissionsForFolder(android4BinPath); q.resolve(); return; } Ionic.fetchArchive(tempZipFilePath, downloadUrl) .then(function(data) { console.log('\nFinished downloading cordova-android v4.0.x'); //Need to make certain files executable self.setPermissionsForFolder(cordovaAndroid4Path) self.setPermissionsForFolder(android4BinPath) console.log('\nAltered permissions for Android Paths') q.resolve(); }, function(error) { console.log('Failed to download cordova-android v4.0.x ', error); q.reject(); }) return q.promise; } IonicTask.prototype.setPermissionsForFolder = function setPermissionsForFolder(folderName) { var self = this; fs.readdir(folderName, function(err, files){ if(err) return; for(var x=0; x<files.length; x++) { var file = path.join(folderName, files[x]); try { fs.chmodSync(file, '755'); }catch (ex) { self.ionic.fail(['Error setting file permissions for file', file, ex].join(' ')) } } }); } IonicTask.prototype.removeAndroidProject = function removeAndroidProject() { var command = 'ionic platform remove android'; var result = shelljs.exec(command); console.log('\nRemoved old Cordova Android platform') } IonicTask.prototype.addCordova40xProject = function addCordova40xProject() { var command = ['ionic platform add ./engine/cordova-android-', cordovaAndroidVersion, '/'].join(''); var result = shelljs.exec(command); if(result.code != 0) { var errorMessage = ['There was an error adding the Cordova Android library', result.output].join('\n'); this.ionic.fail(errorMessage); throw new Error(errorMessage); } else { console.log('\nAdded Cordova Android 4.0') } } IonicTask.prototype.addGradleProperties = function addGradleProperties() { var gradlePropertiesPath = path.resolve(__dirname, 'assets', 'gradle.properties'); var copyPath = path.join('.', 'platforms', 'android', 'gradle.properties'); console.log('\nCopying default gradle.properties file') shelljs.cp(gradlePropertiesPath, copyPath) } IonicTask.prototype.addCrosswalkPlugin = function addCrosswalkPlugin() { var command = ['ionic plugin add ./engine/cordova-crosswalk-engine-', crosswalkEngineVersion].join(''); console.log('add crosswalk plugin', command) var result = shelljs.exec(command); console.log('\nAdded Crosswalk Webview Engine') } IonicTask.prototype.removeCrosswalkEngines = function removeCrosswalkEngines() { shelljs.exec('ionic plugin rm org.apache.cordova.engine.crosswalk'); shelljs.exec('ionic plugin rm org.crosswalk.engine'); shelljs.exec('ionic plugin rm cordova-plugin-crosswalk-webview'); } IonicTask.prototype.addSplashScreenPlugin = function addSplashScreenPlugin() { shelljs.exec('ionic plugin add org.apache.cordova.splashscreen'); } // IonicTask.prototype.updateAndroidProject = function updateAndroidProject() { // var crosswalkEnginePath = ['cordova-crosswalk-engine-', crosswalkEngineVersion].join(''); // var xwalkLibraryPath = path.join(process.cwd(), 'engine', crosswalkEnginePath, 'libs', 'xwalk_core_library'); // var updateCommand = ['android update lib-project --path "', xwalkLibraryPath, '" --target "4"'].join(''); // shelljs.cd(path.join(process.cwd(), 'platforms', 'android')); // shelljs.exec(updateCommand, {silent: true}); // shelljs.cd('../../'); // } IonicTask.prototype.downloadFiles = function downloadFiles(version) { var q = Q.defer(); var self = this; this.getCordovaCrosswalkEngine() .then(function(data) { console.log('\nDownloaded cordova-crosswalk-engine'); return self.downloadCordova40x(); }) .then(function(data) { console.log('\nDownloaded Cordova Android for Crosswalk'); return self.getCrosswalkWebviews(version); }) // .then(function(data) { // console.log('\nDownloaded Crosswalk webviews'); // return self.getAndroidRuntimes(); // }) .then(function(data) { console.log('\nDownloaded Crosswalk webviews'); q.resolve(); }, function(error) { q.reject(); }) .catch(function(error){ console.log('There was an error finishing the browser command - ', error); q.reject(error); }) return q.promise; } IonicTask.prototype.removeCrosswalk = function removeCrosswalk() { shelljs.exec('ionic plugin rm org.apache.cordova.engine.crosswalk') shelljs.exec('ionic plugin rm org.crosswalk.engine') shelljs.exec('ionic plugin rm cordova-plugin-crosswalk-webview') shelljs.exec('ionic platform rm android') shelljs.exec('ionic platform add android') } IonicTask.prototype.installCrosswalk = function installCrosswalk(version) { var self = this; return self.downloadFiles(version) .then(function(data) { self.removeAndroidProject(); self.removeCrosswalkEngines(); self.addCordova40xProject(); self.addCrosswalkPlugin(); self.addGradleProperties(); self.addSplashScreenPlugin(); // self.updateAndroidProject(); console.log('\nIonic Browser Add completed for Crosswalk'); }) .catch(function(error){ console.error('\nAn error with adding Crosswalk browser occured', error) self.ionic.fail(error) // console.log(error) }) } IonicTask.prototype.clean = function clean() { console.log('Cleaning up Ionic browser artifacts'.green) shelljs.rm('-rf', './engine'); console.log('Cleaned'.yellow) } IonicTask.prototype.upgradeCrosswalk = function upgradeCrosswalk() { console.log('Updating your Ionic project with the latest build of Crosswalk'.green) this.clean(); this.installCrosswalk(defaultCrosswalkVersion); } IonicTask.prototype.revertBrowser = function revertBrowser() { var self = this; var platform = argv._[2]; if (!platform) { console.log('You did not specify a platform to revert the browser'); return } if(platforms.indexOf(platform) == -1) { console.log('You did not specify a valid platform.'); return } console.log('Reverting', platform, 'browser'); var rmCommand = ['ionic platform rm', platform].join(' '); var addCommand = ['ionic platform add', platform].join(' '); shelljs.exec(rmCommand) if(platform == 'android') { self.removeCrosswalk(); } shelljs.exec(addCommand) console.log('Reverted', platform, 'browser'); } IonicTask.prototype.saveBrowserInstallation = function saveBrowserInstallation(platform, browser, version) { var project = IonicProject.load(); var browsers = project.get('browsers') || []; var platformExists = false, platformIndex = 0; var browserEntry = { platform: platform, browser: browser, version: version }; for( ; platformIndex < browsers.length; platformIndex++) { var platformBrowser = browsers[platformIndex]; if(platformBrowser.platform == platform) { platformExists = true; break; } } if(platformExists) { browsers[platformIndex] = browserEntry; } else { browsers.push(browserEntry) } project.set('browsers', browsers); project.save(); } IonicTask.prototype.addBrowser = function addBrowser() { var self = this; //Check which browser they wish to install var browserToInstall = 'crosswalk', platform = 'android', browserVersion = null validBrowserSpecified = false; if (argv._[2]) { browserToInstall = argv._[2]; } else { console.log('No browser specified. Nothing to do here.'.red.bold) return; } if(browserToInstall.indexOf('@') !== -1) { //Browser version specified. Find version number. var browserVersionAttempt = argv._[2].split('@'); browserToInstall = browserVersionAttempt[0]; browserVersion = browserVersionAttempt[1]; } else { browserVersion = defaultCrosswalkVersion; } switch(browserToInstall) { case 'crosswalk': console.log('Adding', browserToInstall, 'browser') self.installCrosswalk(browserVersion); validBrowserSpecified = true; break; case 'default': console.log('Adding', browserToInstall, 'browser') self.installDefaultBrowser(); validBrowserSpecified = true; break; default: console.log('No accepted browser was specified.'.red.bold) validBrowserSpecified = false; break; } if(validBrowserSpecified) { self.saveBrowserInstallation(platform, browserToInstall, browserVersion); } } IonicTask.prototype.removeBrowser = function removeBrowser() { var browser = 'crosswalk'; if (argv._[2]) { browser = argv._[2]; console.log('Removing', browser, 'browser') } else { console.log('You did not specify a browser to remove.'.red) return; } switch (browser) { case 'crosswalk': this.removeCrosswalk(); break; case 'default': this.removeDefault(); break; } } var printBrowsers = function printBrowsers(browsers) { for(var x = 0, y = browsers.length; x < y; x++) { var browser = browsers[x]; var avail = browser.available ? 'Yes' : 'No'; var installCommand = browser.command ? browser.command : ''; if(browser.available) { console.log('\nAvailable'.green.bold, '-', browser.name.green, '-', installCommand) if(browser.versions) { for(version in browser.versions) { var ver = browser.versions[version]; var betaCanaryMessage = null; if(ver.beta) { betaCanaryMessage = '(beta)\t' } else if (ver.canary) { betaCanaryMessage = '(canary)' } else { betaCanaryMessage = '\t'; } // console.log('betacanary', betaCanaryMessage) // console.log('beta canary msg', betaCanaryMessage) console.log(betaCanaryMessage, 'Version'.blue, ver.version.yellow, 'Published'.cyan, new Date(ver.publish_date)) } } } else { console.log('Not Available Yet'.red.bold, '-', browser.name.green) } } } IonicTask.prototype.listBrowsers = function listBrowsers() { console.log('iOS - Browsers Listing:\n') printBrowsers(iosBrowsers); console.log('\n\nAndroid - Browsers Listing:\n') printBrowsers(androidBrowsers); } IonicTask.prototype.listInstalledBrowsers = function listInstalledBrowsers() { var project = IonicProject.load(); var browsers = project.get('browsers'); console.log('\nInstalled browsers:\n'.green) for(browserIndex in browsers) { var browser = browsers[browserIndex] console.log('For', browser.platform, '-', browser.browser, browser.version) } console.log('\n') } IonicTask.prototype.run = function run(ionic) { var self = this; this.ionic = ionic; var infoChecker = new IonicInfo(); if(!infoChecker.checkRuntime()) { console.log('\nPlease update your runtime environment before running the browser command'); return } if(argv._.length < 2) { return this.ionic.fail('Invalid command usage', 'browser'); } var cmdArg, x, y, hasValidCmd = false; cmdArg = argv._[1] var validCommands = 'add remove rm list ls revert versions clean upgrade'.split(' '); for(y=0; y<validCommands.length; y++) { if(cmdArg == validCommands[y]) { hasValidCmd = true; break; } } if(!hasValidCmd) { return this.ionic.fail('You did not supply a valid command', 'browser'); } switch(cmdArg) { case 'add': this.addBrowser(); break; case 'clean': this.clean(); break; case 'remove': case 'rm': this.removeBrowser(); break; case 'revert': this.revertBrowser(); break; case 'list': case 'ls': this.listBrowsers(); break; case 'upgrade': this.upgradeCrosswalk(); break; case 'update': case 'up': this.addBrowser(); break; case 'check': console.log('Checking for engine'); break; case 'versions': this.listInstalledBrowsers(); } IonicStats.t(); }; exports.IonicTask = IonicTask;