From 98d417ca7738be7eda4dfb89f17867b48f5109ca Mon Sep 17 00:00:00 2001 From: Koray Balci Date: Fri, 27 Dec 2013 10:42:39 +0200 Subject: [PATCH] Cordova 3.2 Android app Barebones app created using cordova cli. --- .cordova/config.json | 1 + .gitignore | 67 +- platforms/android/.classpath | 9 + platforms/android/.project | 33 + platforms/android/AndroidManifest.xml | 14 + platforms/android/assets/www/config.xml | 14 + platforms/android/assets/www/cordova.js | 1745 +++++++++++++++ .../android/assets/www/cordova_plugins.js | 3 + platforms/android/assets/www/css/index.css | 115 + platforms/android/assets/www/img/logo.png | Bin 0 -> 21814 bytes platforms/android/assets/www/index.html | 43 + platforms/android/assets/www/js/index.js | 49 + platforms/android/build.xml | 92 + platforms/android/cordova/android_sdk_version | 29 + platforms/android/cordova/build | 37 + platforms/android/cordova/build.bat | 26 + platforms/android/cordova/check_reqs | 28 + platforms/android/cordova/clean | 36 + platforms/android/cordova/clean.bat | 26 + platforms/android/cordova/defaults.xml | 50 + .../cordova/lib/android_sdk_version.js | 65 + platforms/android/cordova/lib/appinfo.js | 41 + platforms/android/cordova/lib/build.js | 87 + platforms/android/cordova/lib/check_reqs.js | 94 + platforms/android/cordova/lib/clean.js | 38 + platforms/android/cordova/lib/device.js | 86 + platforms/android/cordova/lib/emulator.js | 330 +++ platforms/android/cordova/lib/exec.js | 43 + platforms/android/cordova/lib/install-device | 42 + .../android/cordova/lib/install-device.bat | 26 + .../android/cordova/lib/install-emulator | 38 + .../android/cordova/lib/install-emulator.bat | 26 + platforms/android/cordova/lib/list-devices | 33 + .../android/cordova/lib/list-devices.bat | 26 + .../android/cordova/lib/list-emulator-images | 32 + .../cordova/lib/list-emulator-images.bat | 26 + .../cordova/lib/list-started-emulators | 32 + .../cordova/lib/list-started-emulators.bat | 26 + platforms/android/cordova/lib/log.js | 57 + platforms/android/cordova/lib/run.js | 139 ++ platforms/android/cordova/lib/start-emulator | 39 + .../android/cordova/lib/start-emulator.bat | 26 + platforms/android/cordova/log | 36 + platforms/android/cordova/log.bat | 26 + .../cordova/node_modules/q/CONTRIBUTING.md | 40 + .../android/cordova/node_modules/q/LICENSE | 19 + .../android/cordova/node_modules/q/README.md | 813 +++++++ .../q/benchmark/compare-with-callbacks.js | 71 + .../node_modules/q/benchmark/scenarios.js | 36 + .../cordova/node_modules/q/package.json | 93 + platforms/android/cordova/node_modules/q/q.js | 1937 +++++++++++++++++ .../android/cordova/node_modules/q/queue.js | 35 + .../node_modules/shelljs/.documentup.json | 6 + .../cordova/node_modules/shelljs/.jshintrc | 7 + .../cordova/node_modules/shelljs/.npmignore | 2 + .../cordova/node_modules/shelljs/.travis.yml | 5 + .../cordova/node_modules/shelljs/LICENSE | 26 + .../cordova/node_modules/shelljs/README.md | 552 +++++ .../cordova/node_modules/shelljs/global.js | 3 + .../cordova/node_modules/shelljs/make.js | 47 + .../cordova/node_modules/shelljs/package.json | 48 + .../shelljs/scripts/generate-docs.js | 21 + .../node_modules/shelljs/scripts/run-tests.js | 50 + .../cordova/node_modules/shelljs/shell.js | 153 ++ .../cordova/node_modules/shelljs/src/cat.js | 43 + .../cordova/node_modules/shelljs/src/cd.js | 19 + .../cordova/node_modules/shelljs/src/chmod.js | 208 ++ .../node_modules/shelljs/src/common.js | 189 ++ .../cordova/node_modules/shelljs/src/cp.js | 200 ++ .../cordova/node_modules/shelljs/src/dirs.js | 191 ++ .../cordova/node_modules/shelljs/src/echo.js | 20 + .../cordova/node_modules/shelljs/src/error.js | 10 + .../cordova/node_modules/shelljs/src/exec.js | 181 ++ .../cordova/node_modules/shelljs/src/find.js | 51 + .../cordova/node_modules/shelljs/src/grep.js | 52 + .../cordova/node_modules/shelljs/src/ls.js | 126 ++ .../cordova/node_modules/shelljs/src/mkdir.js | 68 + .../cordova/node_modules/shelljs/src/mv.js | 80 + .../cordova/node_modules/shelljs/src/popd.js | 1 + .../cordova/node_modules/shelljs/src/pushd.js | 1 + .../cordova/node_modules/shelljs/src/pwd.js | 11 + .../cordova/node_modules/shelljs/src/rm.js | 145 ++ .../cordova/node_modules/shelljs/src/sed.js | 43 + .../node_modules/shelljs/src/tempdir.js | 56 + .../cordova/node_modules/shelljs/src/test.js | 85 + .../cordova/node_modules/shelljs/src/to.js | 29 + .../cordova/node_modules/shelljs/src/toEnd.js | 29 + .../cordova/node_modules/shelljs/src/which.js | 79 + platforms/android/cordova/run | 37 + platforms/android/cordova/run.bat | 26 + platforms/android/cordova/version | 25 + platforms/android/cordova/version.bat | 26 + platforms/android/libs/cordova-3.2.0.jar | Bin 0 -> 292696 bytes platforms/android/platform_www/cordova.js | 1745 +++++++++++++++ platforms/android/proguard-project.txt | 20 + platforms/android/project.properties | 14 + platforms/android/res/drawable-hdpi/icon.png | Bin 0 -> 6080 bytes platforms/android/res/drawable-ldpi/icon.png | Bin 0 -> 3096 bytes platforms/android/res/drawable-mdpi/icon.png | Bin 0 -> 4090 bytes platforms/android/res/drawable-xhdpi/icon.png | Bin 0 -> 7685 bytes platforms/android/res/drawable/icon.png | Bin 0 -> 7685 bytes platforms/android/res/values/strings.xml | 4 + platforms/android/res/xml/config.xml | 19 + .../ccsoft/cordovasample/CordovaSample.java | 37 + plugins/android.json | 1 + www/config.xml | 14 + www/css/index.css | 115 + www/img/logo.png | Bin 0 -> 21814 bytes www/index.html | 43 + www/js/index.js | 49 + 110 files changed, 11878 insertions(+), 9 deletions(-) create mode 100644 .cordova/config.json create mode 100644 platforms/android/.classpath create mode 100644 platforms/android/.project create mode 100644 platforms/android/AndroidManifest.xml create mode 100644 platforms/android/assets/www/config.xml create mode 100644 platforms/android/assets/www/cordova.js create mode 100644 platforms/android/assets/www/cordova_plugins.js create mode 100644 platforms/android/assets/www/css/index.css create mode 100644 platforms/android/assets/www/img/logo.png create mode 100644 platforms/android/assets/www/index.html create mode 100644 platforms/android/assets/www/js/index.js create mode 100644 platforms/android/build.xml create mode 100644 platforms/android/cordova/android_sdk_version create mode 100644 platforms/android/cordova/build create mode 100644 platforms/android/cordova/build.bat create mode 100644 platforms/android/cordova/check_reqs create mode 100644 platforms/android/cordova/clean create mode 100644 platforms/android/cordova/clean.bat create mode 100644 platforms/android/cordova/defaults.xml create mode 100644 platforms/android/cordova/lib/android_sdk_version.js create mode 100644 platforms/android/cordova/lib/appinfo.js create mode 100644 platforms/android/cordova/lib/build.js create mode 100644 platforms/android/cordova/lib/check_reqs.js create mode 100644 platforms/android/cordova/lib/clean.js create mode 100644 platforms/android/cordova/lib/device.js create mode 100644 platforms/android/cordova/lib/emulator.js create mode 100644 platforms/android/cordova/lib/exec.js create mode 100644 platforms/android/cordova/lib/install-device create mode 100644 platforms/android/cordova/lib/install-device.bat create mode 100644 platforms/android/cordova/lib/install-emulator create mode 100644 platforms/android/cordova/lib/install-emulator.bat create mode 100644 platforms/android/cordova/lib/list-devices create mode 100644 platforms/android/cordova/lib/list-devices.bat create mode 100644 platforms/android/cordova/lib/list-emulator-images create mode 100644 platforms/android/cordova/lib/list-emulator-images.bat create mode 100644 platforms/android/cordova/lib/list-started-emulators create mode 100644 platforms/android/cordova/lib/list-started-emulators.bat create mode 100644 platforms/android/cordova/lib/log.js create mode 100644 platforms/android/cordova/lib/run.js create mode 100644 platforms/android/cordova/lib/start-emulator create mode 100644 platforms/android/cordova/lib/start-emulator.bat create mode 100644 platforms/android/cordova/log create mode 100644 platforms/android/cordova/log.bat create mode 100644 platforms/android/cordova/node_modules/q/CONTRIBUTING.md create mode 100644 platforms/android/cordova/node_modules/q/LICENSE create mode 100644 platforms/android/cordova/node_modules/q/README.md create mode 100644 platforms/android/cordova/node_modules/q/benchmark/compare-with-callbacks.js create mode 100644 platforms/android/cordova/node_modules/q/benchmark/scenarios.js create mode 100644 platforms/android/cordova/node_modules/q/package.json create mode 100644 platforms/android/cordova/node_modules/q/q.js create mode 100644 platforms/android/cordova/node_modules/q/queue.js create mode 100644 platforms/android/cordova/node_modules/shelljs/.documentup.json create mode 100644 platforms/android/cordova/node_modules/shelljs/.jshintrc create mode 100644 platforms/android/cordova/node_modules/shelljs/.npmignore create mode 100644 platforms/android/cordova/node_modules/shelljs/.travis.yml create mode 100644 platforms/android/cordova/node_modules/shelljs/LICENSE create mode 100644 platforms/android/cordova/node_modules/shelljs/README.md create mode 100644 platforms/android/cordova/node_modules/shelljs/global.js create mode 100644 platforms/android/cordova/node_modules/shelljs/make.js create mode 100644 platforms/android/cordova/node_modules/shelljs/package.json create mode 100644 platforms/android/cordova/node_modules/shelljs/scripts/generate-docs.js create mode 100644 platforms/android/cordova/node_modules/shelljs/scripts/run-tests.js create mode 100644 platforms/android/cordova/node_modules/shelljs/shell.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/cat.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/cd.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/chmod.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/common.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/cp.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/dirs.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/echo.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/error.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/exec.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/find.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/grep.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/ls.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/mkdir.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/mv.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/popd.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/pushd.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/pwd.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/rm.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/sed.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/tempdir.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/test.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/to.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/toEnd.js create mode 100644 platforms/android/cordova/node_modules/shelljs/src/which.js create mode 100644 platforms/android/cordova/run create mode 100644 platforms/android/cordova/run.bat create mode 100644 platforms/android/cordova/version create mode 100644 platforms/android/cordova/version.bat create mode 100644 platforms/android/libs/cordova-3.2.0.jar create mode 100644 platforms/android/platform_www/cordova.js create mode 100644 platforms/android/proguard-project.txt create mode 100644 platforms/android/project.properties create mode 100644 platforms/android/res/drawable-hdpi/icon.png create mode 100644 platforms/android/res/drawable-ldpi/icon.png create mode 100644 platforms/android/res/drawable-mdpi/icon.png create mode 100644 platforms/android/res/drawable-xhdpi/icon.png create mode 100644 platforms/android/res/drawable/icon.png create mode 100644 platforms/android/res/values/strings.xml create mode 100644 platforms/android/res/xml/config.xml create mode 100644 platforms/android/src/com/ccsoft/cordovasample/CordovaSample.java create mode 100644 plugins/android.json create mode 100644 www/config.xml create mode 100644 www/css/index.css create mode 100644 www/img/logo.png create mode 100644 www/index.html create mode 100644 www/js/index.js diff --git a/.cordova/config.json b/.cordova/config.json new file mode 100644 index 0000000..7585675 --- /dev/null +++ b/.cordova/config.json @@ -0,0 +1 @@ +{"id":"com.ccsoft.cordovasample","name":"CordovaSample"} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 648a292..ab74ff0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,29 @@ +# ObjectiveC https://github.com/github/gitignore/blob/master/Objective-C.gitignore +# OS X +.DS_Store + +# Xcode +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +profile +*.moved-aside +DerivedData +*.hmap +*.ipa + +# CocoaPods +Pods + +# Android https://github.com/github/gitignore/blob/master/Android.gitignore # built application files *.apk *.ap_ @@ -12,18 +38,41 @@ bin/ gen/ +# Ignore gradle files +.gradle/ +build/ + # Local configuration file (sdk path, etc) local.properties -# Eclipse project files -.classpath -.project - # Proguard folder generated by Eclipse proguard/ -# Intellij project files -*.iml -*.ipr -*.iws -.idea/ +# Eclipse https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore +*.pydevproject +.metadata +.gradle +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + +# TeXlipse plugin +.texlipse diff --git a/platforms/android/.classpath b/platforms/android/.classpath new file mode 100644 index 0000000..2731f9c --- /dev/null +++ b/platforms/android/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/platforms/android/.project b/platforms/android/.project new file mode 100644 index 0000000..223ac9e --- /dev/null +++ b/platforms/android/.project @@ -0,0 +1,33 @@ + + + CordovaSample + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/platforms/android/AndroidManifest.xml b/platforms/android/AndroidManifest.xml new file mode 100644 index 0000000..293e6c9 --- /dev/null +++ b/platforms/android/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/platforms/android/assets/www/config.xml b/platforms/android/assets/www/config.xml new file mode 100644 index 0000000..e138766 --- /dev/null +++ b/platforms/android/assets/www/config.xml @@ -0,0 +1,14 @@ + + + CordovaSample + + A sample Apache Cordova application that responds to the deviceready event. + + + Apache Cordova Team + + + + + + diff --git a/platforms/android/assets/www/cordova.js b/platforms/android/assets/www/cordova.js new file mode 100644 index 0000000..e1903d6 --- /dev/null +++ b/platforms/android/assets/www/cordova.js @@ -0,0 +1,1745 @@ +// Platform: android +// 3.2.0 +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +;(function() { +var CORDOVA_JS_BUILD_LABEL = '3.2.0'; +// file: lib/scripts/require.js + +/*jshint -W079 */ +/*jshint -W020 */ + +var require, + define; + +(function () { + var modules = {}, + // Stack of moduleIds currently being built. + requireStack = [], + // Map of module ID -> index into requireStack of modules currently being built. + inProgressModules = {}, + SEPERATOR = "."; + + + + function build(module) { + var factory = module.factory, + localRequire = function (id) { + var resultantId = id; + //Its a relative path, so lop off the last portion and add the id (minus "./") + if (id.charAt(0) === ".") { + resultantId = module.id.slice(0, module.id.lastIndexOf(SEPERATOR)) + SEPERATOR + id.slice(2); + } + return require(resultantId); + }; + module.exports = {}; + delete module.factory; + factory(localRequire, module.exports, module); + return module.exports; + } + + require = function (id) { + if (!modules[id]) { + throw "module " + id + " not found"; + } else if (id in inProgressModules) { + var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id; + throw "Cycle in require graph: " + cycle; + } + if (modules[id].factory) { + try { + inProgressModules[id] = requireStack.length; + requireStack.push(id); + return build(modules[id]); + } finally { + delete inProgressModules[id]; + requireStack.pop(); + } + } + return modules[id].exports; + }; + + define = function (id, factory) { + if (modules[id]) { + throw "module " + id + " already defined"; + } + + modules[id] = { + id: id, + factory: factory + }; + }; + + define.remove = function (id) { + delete modules[id]; + }; + + define.moduleMap = modules; +})(); + +//Export for use in node +if (typeof module === "object" && typeof require === "function") { + module.exports.require = require; + module.exports.define = define; +} + +// file: lib/cordova.js +define("cordova", function(require, exports, module) { + + +var channel = require('cordova/channel'); +var platform = require('cordova/platform'); + +/** + * Intercept calls to addEventListener + removeEventListener and handle deviceready, + * resume, and pause events. + */ +var m_document_addEventListener = document.addEventListener; +var m_document_removeEventListener = document.removeEventListener; +var m_window_addEventListener = window.addEventListener; +var m_window_removeEventListener = window.removeEventListener; + +/** + * Houses custom event handlers to intercept on document + window event listeners. + */ +var documentEventHandlers = {}, + windowEventHandlers = {}; + +document.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + if (typeof documentEventHandlers[e] != 'undefined') { + documentEventHandlers[e].subscribe(handler); + } else { + m_document_addEventListener.call(document, evt, handler, capture); + } +}; + +window.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + if (typeof windowEventHandlers[e] != 'undefined') { + windowEventHandlers[e].subscribe(handler); + } else { + m_window_addEventListener.call(window, evt, handler, capture); + } +}; + +document.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + // If unsubscribing from an event that is handled by a plugin + if (typeof documentEventHandlers[e] != "undefined") { + documentEventHandlers[e].unsubscribe(handler); + } else { + m_document_removeEventListener.call(document, evt, handler, capture); + } +}; + +window.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + // If unsubscribing from an event that is handled by a plugin + if (typeof windowEventHandlers[e] != "undefined") { + windowEventHandlers[e].unsubscribe(handler); + } else { + m_window_removeEventListener.call(window, evt, handler, capture); + } +}; + +function createEvent(type, data) { + var event = document.createEvent('Events'); + event.initEvent(type, false, false); + if (data) { + for (var i in data) { + if (data.hasOwnProperty(i)) { + event[i] = data[i]; + } + } + } + return event; +} + + +var cordova = { + define:define, + require:require, + version:CORDOVA_JS_BUILD_LABEL, + platformId:platform.id, + /** + * Methods to add/remove your own addEventListener hijacking on document + window. + */ + addWindowEventHandler:function(event) { + return (windowEventHandlers[event] = channel.create(event)); + }, + addStickyDocumentEventHandler:function(event) { + return (documentEventHandlers[event] = channel.createSticky(event)); + }, + addDocumentEventHandler:function(event) { + return (documentEventHandlers[event] = channel.create(event)); + }, + removeWindowEventHandler:function(event) { + delete windowEventHandlers[event]; + }, + removeDocumentEventHandler:function(event) { + delete documentEventHandlers[event]; + }, + /** + * Retrieve original event handlers that were replaced by Cordova + * + * @return object + */ + getOriginalHandlers: function() { + return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener}, + 'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}}; + }, + /** + * Method to fire event from native code + * bNoDetach is required for events which cause an exception which needs to be caught in native code + */ + fireDocumentEvent: function(type, data, bNoDetach) { + var evt = createEvent(type, data); + if (typeof documentEventHandlers[type] != 'undefined') { + if( bNoDetach ) { + documentEventHandlers[type].fire(evt); + } + else { + setTimeout(function() { + // Fire deviceready on listeners that were registered before cordova.js was loaded. + if (type == 'deviceready') { + document.dispatchEvent(evt); + } + documentEventHandlers[type].fire(evt); + }, 0); + } + } else { + document.dispatchEvent(evt); + } + }, + fireWindowEvent: function(type, data) { + var evt = createEvent(type,data); + if (typeof windowEventHandlers[type] != 'undefined') { + setTimeout(function() { + windowEventHandlers[type].fire(evt); + }, 0); + } else { + window.dispatchEvent(evt); + } + }, + + /** + * Plugin callback mechanism. + */ + // Randomize the starting callbackId to avoid collisions after refreshing or navigating. + // This way, it's very unlikely that any new callback would get the same callbackId as an old callback. + callbackId: Math.floor(Math.random() * 2000000000), + callbacks: {}, + callbackStatus: { + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 + }, + + /** + * Called by native code when returning successful result from an action. + */ + callbackSuccess: function(callbackId, args) { + try { + cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback); + } catch (e) { + console.log("Error in error callback: " + callbackId + " = "+e); + } + }, + + /** + * Called by native code when returning error result from an action. + */ + callbackError: function(callbackId, args) { + // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative. + // Derive success from status. + try { + cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback); + } catch (e) { + console.log("Error in error callback: " + callbackId + " = "+e); + } + }, + + /** + * Called by native code when returning the result from an action. + */ + callbackFromNative: function(callbackId, success, status, args, keepCallback) { + var callback = cordova.callbacks[callbackId]; + if (callback) { + if (success && status == cordova.callbackStatus.OK) { + callback.success && callback.success.apply(null, args); + } else if (!success) { + callback.fail && callback.fail.apply(null, args); + } + + // Clear callback if not expecting any more results + if (!keepCallback) { + delete cordova.callbacks[callbackId]; + } + } + }, + addConstructor: function(func) { + channel.onCordovaReady.subscribe(function() { + try { + func(); + } catch(e) { + console.log("Failed to run constructor: " + e); + } + }); + } +}; + + +module.exports = cordova; + +}); + +// file: lib/android/android/nativeapiprovider.js +define("cordova/android/nativeapiprovider", function(require, exports, module) { + +/** + * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi. + */ + +var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi'); +var currentApi = nativeApi; + +module.exports = { + get: function() { return currentApi; }, + setPreferPrompt: function(value) { + currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi; + }, + // Used only by tests. + set: function(value) { + currentApi = value; + } +}; + +}); + +// file: lib/android/android/promptbasednativeapi.js +define("cordova/android/promptbasednativeapi", function(require, exports, module) { + +/** + * Implements the API of ExposedJsApi.java, but uses prompt() to communicate. + * This is used only on the 2.3 simulator, where addJavascriptInterface() is broken. + */ + +module.exports = { + exec: function(service, action, callbackId, argsJson) { + return prompt(argsJson, 'gap:'+JSON.stringify([service, action, callbackId])); + }, + setNativeToJsBridgeMode: function(value) { + prompt(value, 'gap_bridge_mode:'); + }, + retrieveJsMessages: function(fromOnlineEvent) { + return prompt(+fromOnlineEvent, 'gap_poll:'); + } +}; + +}); + +// file: lib/common/argscheck.js +define("cordova/argscheck", function(require, exports, module) { + +var exec = require('cordova/exec'); +var utils = require('cordova/utils'); + +var moduleExports = module.exports; + +var typeMap = { + 'A': 'Array', + 'D': 'Date', + 'N': 'Number', + 'S': 'String', + 'F': 'Function', + 'O': 'Object' +}; + +function extractParamName(callee, argIndex) { + return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex]; +} + +function checkArgs(spec, functionName, args, opt_callee) { + if (!moduleExports.enableChecks) { + return; + } + var errMsg = null; + var typeName; + for (var i = 0; i < spec.length; ++i) { + var c = spec.charAt(i), + cUpper = c.toUpperCase(), + arg = args[i]; + // Asterix means allow anything. + if (c == '*') { + continue; + } + typeName = utils.typeName(arg); + if ((arg === null || arg === undefined) && c == cUpper) { + continue; + } + if (typeName != typeMap[cUpper]) { + errMsg = 'Expected ' + typeMap[cUpper]; + break; + } + } + if (errMsg) { + errMsg += ', but got ' + typeName + '.'; + errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg; + // Don't log when running unit tests. + if (typeof jasmine == 'undefined') { + console.error(errMsg); + } + throw TypeError(errMsg); + } +} + +function getValue(value, defaultValue) { + return value === undefined ? defaultValue : value; +} + +moduleExports.checkArgs = checkArgs; +moduleExports.getValue = getValue; +moduleExports.enableChecks = true; + + +}); + +// file: lib/common/base64.js +define("cordova/base64", function(require, exports, module) { + +var base64 = exports; + +base64.fromArrayBuffer = function(arrayBuffer) { + var array = new Uint8Array(arrayBuffer); + return uint8ToBase64(array); +}; + +//------------------------------------------------------------------------------ + +/* This code is based on the performance tests at http://jsperf.com/b64tests + * This 12-bit-at-a-time algorithm was the best performing version on all + * platforms tested. + */ + +var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var b64_12bit; + +var b64_12bitTable = function() { + b64_12bit = []; + for (var i=0; i<64; i++) { + for (var j=0; j<64; j++) { + b64_12bit[i*64+j] = b64_6bit[i] + b64_6bit[j]; + } + } + b64_12bitTable = function() { return b64_12bit; }; + return b64_12bit; +}; + +function uint8ToBase64(rawData) { + var numBytes = rawData.byteLength; + var output=""; + var segment; + var table = b64_12bitTable(); + for (var i=0;i> 12]; + output += table[segment & 0xfff]; + } + if (numBytes - i == 2) { + segment = (rawData[i] << 16) + (rawData[i+1] << 8); + output += table[segment >> 12]; + output += b64_6bit[(segment & 0xfff) >> 6]; + output += '='; + } else if (numBytes - i == 1) { + segment = (rawData[i] << 16); + output += table[segment >> 12]; + output += '=='; + } + return output; +} + +}); + +// file: lib/common/builder.js +define("cordova/builder", function(require, exports, module) { + +var utils = require('cordova/utils'); + +function each(objects, func, context) { + for (var prop in objects) { + if (objects.hasOwnProperty(prop)) { + func.apply(context, [objects[prop], prop]); + } + } +} + +function clobber(obj, key, value) { + exports.replaceHookForTesting(obj, key); + obj[key] = value; + // Getters can only be overridden by getters. + if (obj[key] !== value) { + utils.defineGetter(obj, key, function() { + return value; + }); + } +} + +function assignOrWrapInDeprecateGetter(obj, key, value, message) { + if (message) { + utils.defineGetter(obj, key, function() { + console.log(message); + delete obj[key]; + clobber(obj, key, value); + return value; + }); + } else { + clobber(obj, key, value); + } +} + +function include(parent, objects, clobber, merge) { + each(objects, function (obj, key) { + try { + var result = obj.path ? require(obj.path) : {}; + + if (clobber) { + // Clobber if it doesn't exist. + if (typeof parent[key] === 'undefined') { + assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated); + } else if (typeof obj.path !== 'undefined') { + // If merging, merge properties onto parent, otherwise, clobber. + if (merge) { + recursiveMerge(parent[key], result); + } else { + assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated); + } + } + result = parent[key]; + } else { + // Overwrite if not currently defined. + if (typeof parent[key] == 'undefined') { + assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated); + } else { + // Set result to what already exists, so we can build children into it if they exist. + result = parent[key]; + } + } + + if (obj.children) { + include(result, obj.children, clobber, merge); + } + } catch(e) { + utils.alert('Exception building cordova JS globals: ' + e + ' for key "' + key + '"'); + } + }); +} + +/** + * Merge properties from one object onto another recursively. Properties from + * the src object will overwrite existing target property. + * + * @param target Object to merge properties into. + * @param src Object to merge properties from. + */ +function recursiveMerge(target, src) { + for (var prop in src) { + if (src.hasOwnProperty(prop)) { + if (target.prototype && target.prototype.constructor === target) { + // If the target object is a constructor override off prototype. + clobber(target.prototype, prop, src[prop]); + } else { + if (typeof src[prop] === 'object' && typeof target[prop] === 'object') { + recursiveMerge(target[prop], src[prop]); + } else { + clobber(target, prop, src[prop]); + } + } + } + } +} + +exports.buildIntoButDoNotClobber = function(objects, target) { + include(target, objects, false, false); +}; +exports.buildIntoAndClobber = function(objects, target) { + include(target, objects, true, false); +}; +exports.buildIntoAndMerge = function(objects, target) { + include(target, objects, true, true); +}; +exports.recursiveMerge = recursiveMerge; +exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter; +exports.replaceHookForTesting = function() {}; + +}); + +// file: lib/common/channel.js +define("cordova/channel", function(require, exports, module) { + +var utils = require('cordova/utils'), + nextGuid = 1; + +/** + * Custom pub-sub "channel" that can have functions subscribed to it + * This object is used to define and control firing of events for + * cordova initialization, as well as for custom events thereafter. + * + * The order of events during page load and Cordova startup is as follows: + * + * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed. + * onNativeReady* Internal event that indicates the Cordova native side is ready. + * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created. + * onDeviceReady* User event fired to indicate that Cordova is ready + * onResume User event fired to indicate a start/resume lifecycle event + * onPause User event fired to indicate a pause lifecycle event + * onDestroy* Internal event fired when app is being destroyed (User should use window.onunload event, not this one). + * + * The events marked with an * are sticky. Once they have fired, they will stay in the fired state. + * All listeners that subscribe after the event is fired will be executed right away. + * + * The only Cordova events that user code should register for are: + * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript + * pause App has moved to background + * resume App has returned to foreground + * + * Listeners can be registered as: + * document.addEventListener("deviceready", myDeviceReadyListener, false); + * document.addEventListener("resume", myResumeListener, false); + * document.addEventListener("pause", myPauseListener, false); + * + * The DOM lifecycle events should be used for saving and restoring state + * window.onload + * window.onunload + * + */ + +/** + * Channel + * @constructor + * @param type String the channel name + */ +var Channel = function(type, sticky) { + this.type = type; + // Map of guid -> function. + this.handlers = {}; + // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired. + this.state = sticky ? 1 : 0; + // Used in sticky mode to remember args passed to fire(). + this.fireArgs = null; + // Used by onHasSubscribersChange to know if there are any listeners. + this.numHandlers = 0; + // Function that is called when the first listener is subscribed, or when + // the last listener is unsubscribed. + this.onHasSubscribersChange = null; +}, + channel = { + /** + * Calls the provided function only after all of the channels specified + * have been fired. All channels must be sticky channels. + */ + join: function(h, c) { + var len = c.length, + i = len, + f = function() { + if (!(--i)) h(); + }; + for (var j=0; jNative bridge. + POLLING: 0, + // For LOAD_URL to be viable, it would need to have a work-around for + // the bug where the soft-keyboard gets dismissed when a message is sent. + LOAD_URL: 1, + // For the ONLINE_EVENT to be viable, it would need to intercept all event + // listeners (both through addEventListener and window.ononline) as well + // as set the navigator property itself. + ONLINE_EVENT: 2, + // Uses reflection to access private APIs of the WebView that can send JS + // to be executed. + // Requires Android 3.2.4 or above. + PRIVATE_API: 3 + }, + jsToNativeBridgeMode, // Set lazily. + nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT, + pollEnabled = false, + messagesFromNative = []; + +function androidExec(success, fail, service, action, args) { + // Set default bridge modes if they have not already been set. + // By default, we use the failsafe, since addJavascriptInterface breaks too often + if (jsToNativeBridgeMode === undefined) { + androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT); + } + + // Process any ArrayBuffers in the args into a string. + for (var i = 0; i < args.length; i++) { + if (utils.typeName(args[i]) == 'ArrayBuffer') { + args[i] = base64.fromArrayBuffer(args[i]); + } + } + + var callbackId = service + cordova.callbackId++, + argsJson = JSON.stringify(args); + + if (success || fail) { + cordova.callbacks[callbackId] = {success:success, fail:fail}; + } + + if (jsToNativeBridgeMode == jsToNativeModes.LOCATION_CHANGE) { + window.location = 'http://cdv_exec/' + service + '#' + action + '#' + callbackId + '#' + argsJson; + } else { + var messages = nativeApiProvider.get().exec(service, action, callbackId, argsJson); + // If argsJson was received by Java as null, try again with the PROMPT bridge mode. + // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666. + if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && messages === "@Null arguments.") { + androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT); + androidExec(success, fail, service, action, args); + androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT); + return; + } else { + androidExec.processMessages(messages); + } + } +} + +function pollOnceFromOnlineEvent() { + pollOnce(true); +} + +function pollOnce(opt_fromOnlineEvent) { + var msg = nativeApiProvider.get().retrieveJsMessages(!!opt_fromOnlineEvent); + androidExec.processMessages(msg); +} + +function pollingTimerFunc() { + if (pollEnabled) { + pollOnce(); + setTimeout(pollingTimerFunc, 50); + } +} + +function hookOnlineApis() { + function proxyEvent(e) { + cordova.fireWindowEvent(e.type); + } + // The network module takes care of firing online and offline events. + // It currently fires them only on document though, so we bridge them + // to window here (while first listening for exec()-releated online/offline + // events). + window.addEventListener('online', pollOnceFromOnlineEvent, false); + window.addEventListener('offline', pollOnceFromOnlineEvent, false); + cordova.addWindowEventHandler('online'); + cordova.addWindowEventHandler('offline'); + document.addEventListener('online', proxyEvent, false); + document.addEventListener('offline', proxyEvent, false); +} + +hookOnlineApis(); + +androidExec.jsToNativeModes = jsToNativeModes; +androidExec.nativeToJsModes = nativeToJsModes; + +androidExec.setJsToNativeBridgeMode = function(mode) { + if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) { + console.log('Falling back on PROMPT mode since _cordovaNative is missing. Expected for Android 3.2 and lower only.'); + mode = jsToNativeModes.PROMPT; + } + nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT); + jsToNativeBridgeMode = mode; +}; + +androidExec.setNativeToJsBridgeMode = function(mode) { + if (mode == nativeToJsBridgeMode) { + return; + } + if (nativeToJsBridgeMode == nativeToJsModes.POLLING) { + pollEnabled = false; + } + + nativeToJsBridgeMode = mode; + // Tell the native side to switch modes. + nativeApiProvider.get().setNativeToJsBridgeMode(mode); + + if (mode == nativeToJsModes.POLLING) { + pollEnabled = true; + setTimeout(pollingTimerFunc, 1); + } +}; + +// Processes a single message, as encoded by NativeToJsMessageQueue.java. +function processMessage(message) { + try { + var firstChar = message.charAt(0); + if (firstChar == 'J') { + eval(message.slice(1)); + } else if (firstChar == 'S' || firstChar == 'F') { + var success = firstChar == 'S'; + var keepCallback = message.charAt(1) == '1'; + var spaceIdx = message.indexOf(' ', 2); + var status = +message.slice(2, spaceIdx); + var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1); + var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx); + var payloadKind = message.charAt(nextSpaceIdx + 1); + var payload; + if (payloadKind == 's') { + payload = message.slice(nextSpaceIdx + 2); + } else if (payloadKind == 't') { + payload = true; + } else if (payloadKind == 'f') { + payload = false; + } else if (payloadKind == 'N') { + payload = null; + } else if (payloadKind == 'n') { + payload = +message.slice(nextSpaceIdx + 2); + } else if (payloadKind == 'A') { + var data = message.slice(nextSpaceIdx + 2); + var bytes = window.atob(data); + var arraybuffer = new Uint8Array(bytes.length); + for (var i = 0; i < bytes.length; i++) { + arraybuffer[i] = bytes.charCodeAt(i); + } + payload = arraybuffer.buffer; + } else if (payloadKind == 'S') { + payload = window.atob(message.slice(nextSpaceIdx + 2)); + } else { + payload = JSON.parse(message.slice(nextSpaceIdx + 1)); + } + cordova.callbackFromNative(callbackId, success, status, [payload], keepCallback); + } else { + console.log("processMessage failed: invalid message:" + message); + } + } catch (e) { + console.log("processMessage failed: Message: " + message); + console.log("processMessage failed: Error: " + e); + console.log("processMessage failed: Stack: " + e.stack); + } +} + +// This is called from the NativeToJsMessageQueue.java. +androidExec.processMessages = function(messages) { + if (messages) { + messagesFromNative.push(messages); + // Check for the reentrant case, and enqueue the message if that's the case. + if (messagesFromNative.length > 1) { + return; + } + while (messagesFromNative.length) { + // Don't unshift until the end so that reentrancy can be detected. + messages = messagesFromNative[0]; + // The Java side can send a * message to indicate that it + // still has messages waiting to be retrieved. + if (messages == '*') { + messagesFromNative.shift(); + window.setTimeout(pollOnce, 0); + return; + } + + var spaceIdx = messages.indexOf(' '); + var msgLen = +messages.slice(0, spaceIdx); + var message = messages.substr(spaceIdx + 1, msgLen); + messages = messages.slice(spaceIdx + msgLen + 1); + processMessage(message); + if (messages) { + messagesFromNative[0] = messages; + } else { + messagesFromNative.shift(); + } + } + } +}; + +module.exports = androidExec; + +}); + +// file: lib/common/exec/proxy.js +define("cordova/exec/proxy", function(require, exports, module) { + + +// internal map of proxy function +var CommandProxyMap = {}; + +module.exports = { + + // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...); + add:function(id,proxyObj) { + console.log("adding proxy for " + id); + CommandProxyMap[id] = proxyObj; + return proxyObj; + }, + + // cordova.commandProxy.remove("Accelerometer"); + remove:function(id) { + var proxy = CommandProxyMap[id]; + delete CommandProxyMap[id]; + CommandProxyMap[id] = null; + return proxy; + }, + + get:function(service,action) { + return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null ); + } +}; +}); + +// file: lib/common/init.js +define("cordova/init", function(require, exports, module) { + +var channel = require('cordova/channel'); +var cordova = require('cordova'); +var modulemapper = require('cordova/modulemapper'); +var platform = require('cordova/platform'); +var pluginloader = require('cordova/pluginloader'); + +var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady]; + +function logUnfiredChannels(arr) { + for (var i = 0; i < arr.length; ++i) { + if (arr[i].state != 2) { + console.log('Channel not fired: ' + arr[i].type); + } + } +} + +window.setTimeout(function() { + if (channel.onDeviceReady.state != 2) { + console.log('deviceready has not fired after 5 seconds.'); + logUnfiredChannels(platformInitChannelsArray); + logUnfiredChannels(channel.deviceReadyChannelsArray); + } +}, 5000); + +// Replace navigator before any modules are required(), to ensure it happens as soon as possible. +// We replace it so that properties that can't be clobbered can instead be overridden. +function replaceNavigator(origNavigator) { + var CordovaNavigator = function() {}; + CordovaNavigator.prototype = origNavigator; + var newNavigator = new CordovaNavigator(); + // This work-around really only applies to new APIs that are newer than Function.bind. + // Without it, APIs such as getGamepads() break. + if (CordovaNavigator.bind) { + for (var key in origNavigator) { + if (typeof origNavigator[key] == 'function') { + newNavigator[key] = origNavigator[key].bind(origNavigator); + } + } + } + return newNavigator; +} +if (window.navigator) { + window.navigator = replaceNavigator(window.navigator); +} + +if (!window.console) { + window.console = { + log: function(){} + }; +} +if (!window.console.warn) { + window.console.warn = function(msg) { + this.log("warn: " + msg); + }; +} + +// Register pause, resume and deviceready channels as events on document. +channel.onPause = cordova.addDocumentEventHandler('pause'); +channel.onResume = cordova.addDocumentEventHandler('resume'); +channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready'); + +// Listen for DOMContentLoaded and notify our channel subscribers. +if (document.readyState == 'complete' || document.readyState == 'interactive') { + channel.onDOMContentLoaded.fire(); +} else { + document.addEventListener('DOMContentLoaded', function() { + channel.onDOMContentLoaded.fire(); + }, false); +} + +// _nativeReady is global variable that the native side can set +// to signify that the native code is ready. It is a global since +// it may be called before any cordova JS is ready. +if (window._nativeReady) { + channel.onNativeReady.fire(); +} + +modulemapper.clobbers('cordova', 'cordova'); +modulemapper.clobbers('cordova/exec', 'cordova.exec'); +modulemapper.clobbers('cordova/exec', 'Cordova.exec'); + +// Call the platform-specific initialization. +platform.bootstrap && platform.bootstrap(); + +pluginloader.load(function() { + channel.onPluginsReady.fire(); +}); + +/** + * Create all cordova objects once native side is ready. + */ +channel.join(function() { + modulemapper.mapModules(window); + + platform.initialize && platform.initialize(); + + // Fire event to notify that all objects are created + channel.onCordovaReady.fire(); + + // Fire onDeviceReady event once page has fully loaded, all + // constructors have run and cordova info has been received from native + // side. + channel.join(function() { + require('cordova').fireDocumentEvent('deviceready'); + }, channel.deviceReadyChannelsArray); + +}, platformInitChannelsArray); + + +}); + +// file: lib/common/modulemapper.js +define("cordova/modulemapper", function(require, exports, module) { + +var builder = require('cordova/builder'), + moduleMap = define.moduleMap, + symbolList, + deprecationMap; + +exports.reset = function() { + symbolList = []; + deprecationMap = {}; +}; + +function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) { + if (!(moduleName in moduleMap)) { + throw new Error('Module ' + moduleName + ' does not exist.'); + } + symbolList.push(strategy, moduleName, symbolPath); + if (opt_deprecationMessage) { + deprecationMap[symbolPath] = opt_deprecationMessage; + } +} + +// Note: Android 2.3 does have Function.bind(). +exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) { + addEntry('c', moduleName, symbolPath, opt_deprecationMessage); +}; + +exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) { + addEntry('m', moduleName, symbolPath, opt_deprecationMessage); +}; + +exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) { + addEntry('d', moduleName, symbolPath, opt_deprecationMessage); +}; + +exports.runs = function(moduleName) { + addEntry('r', moduleName, null); +}; + +function prepareNamespace(symbolPath, context) { + if (!symbolPath) { + return context; + } + var parts = symbolPath.split('.'); + var cur = context; + for (var i = 0, part; part = parts[i]; ++i) { + cur = cur[part] = cur[part] || {}; + } + return cur; +} + +exports.mapModules = function(context) { + var origSymbols = {}; + context.CDV_origSymbols = origSymbols; + for (var i = 0, len = symbolList.length; i < len; i += 3) { + var strategy = symbolList[i]; + var moduleName = symbolList[i + 1]; + var module = require(moduleName); + // + if (strategy == 'r') { + continue; + } + var symbolPath = symbolList[i + 2]; + var lastDot = symbolPath.lastIndexOf('.'); + var namespace = symbolPath.substr(0, lastDot); + var lastName = symbolPath.substr(lastDot + 1); + + var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null; + var parentObj = prepareNamespace(namespace, context); + var target = parentObj[lastName]; + + if (strategy == 'm' && target) { + builder.recursiveMerge(target, module); + } else if ((strategy == 'd' && !target) || (strategy != 'd')) { + if (!(symbolPath in origSymbols)) { + origSymbols[symbolPath] = target; + } + builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg); + } + } +}; + +exports.getOriginalSymbol = function(context, symbolPath) { + var origSymbols = context.CDV_origSymbols; + if (origSymbols && (symbolPath in origSymbols)) { + return origSymbols[symbolPath]; + } + var parts = symbolPath.split('.'); + var obj = context; + for (var i = 0; i < parts.length; ++i) { + obj = obj && obj[parts[i]]; + } + return obj; +}; + +exports.reset(); + + +}); + +// file: lib/android/platform.js +define("cordova/platform", function(require, exports, module) { + +module.exports = { + id: 'android', + bootstrap: function() { + var channel = require('cordova/channel'), + cordova = require('cordova'), + exec = require('cordova/exec'), + modulemapper = require('cordova/modulemapper'); + + // Tell the native code that a page change has occurred. + exec(null, null, 'PluginManager', 'startup', []); + // Tell the JS that the native side is ready. + channel.onNativeReady.fire(); + + // TODO: Extract this as a proper plugin. + modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app'); + + // Inject a listener for the backbutton on the document. + var backButtonChannel = cordova.addDocumentEventHandler('backbutton'); + backButtonChannel.onHasSubscribersChange = function() { + // If we just attached the first handler or detached the last handler, + // let native know we need to override the back button. + exec(null, null, "App", "overrideBackbutton", [this.numHandlers == 1]); + }; + + // Add hardware MENU and SEARCH button handlers + cordova.addDocumentEventHandler('menubutton'); + cordova.addDocumentEventHandler('searchbutton'); + + // Let native code know we are all done on the JS side. + // Native code will then un-hide the WebView. + channel.onCordovaReady.subscribe(function() { + exec(null, null, "App", "show", []); + }); + } +}; + +}); + +// file: lib/android/plugin/android/app.js +define("cordova/plugin/android/app", function(require, exports, module) { + +var exec = require('cordova/exec'); + +module.exports = { + /** + * Clear the resource cache. + */ + clearCache:function() { + exec(null, null, "App", "clearCache", []); + }, + + /** + * Load the url into the webview or into new browser instance. + * + * @param url The URL to load + * @param props Properties that can be passed in to the activity: + * wait: int => wait msec before loading URL + * loadingDialog: "Title,Message" => display a native loading dialog + * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error + * clearHistory: boolean => clear webview history (default=false) + * openExternal: boolean => open in a new browser (default=false) + * + * Example: + * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000}); + */ + loadUrl:function(url, props) { + exec(null, null, "App", "loadUrl", [url, props]); + }, + + /** + * Cancel loadUrl that is waiting to be loaded. + */ + cancelLoadUrl:function() { + exec(null, null, "App", "cancelLoadUrl", []); + }, + + /** + * Clear web history in this web view. + * Instead of BACK button loading the previous web page, it will exit the app. + */ + clearHistory:function() { + exec(null, null, "App", "clearHistory", []); + }, + + /** + * Go to previous page displayed. + * This is the same as pressing the backbutton on Android device. + */ + backHistory:function() { + exec(null, null, "App", "backHistory", []); + }, + + /** + * Override the default behavior of the Android back button. + * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired. + * + * Note: The user should not have to call this method. Instead, when the user + * registers for the "backbutton" event, this is automatically done. + * + * @param override T=override, F=cancel override + */ + overrideBackbutton:function(override) { + exec(null, null, "App", "overrideBackbutton", [override]); + }, + + /** + * Exit and terminate the application. + */ + exitApp:function() { + return exec(null, null, "App", "exitApp", []); + } +}; + +}); + +// file: lib/common/pluginloader.js +define("cordova/pluginloader", function(require, exports, module) { + +var modulemapper = require('cordova/modulemapper'); + +// Helper function to inject a + + + + diff --git a/platforms/android/assets/www/js/index.js b/platforms/android/assets/www/js/index.js new file mode 100644 index 0000000..31d9064 --- /dev/null +++ b/platforms/android/assets/www/js/index.js @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var app = { + // Application Constructor + initialize: function() { + this.bindEvents(); + }, + // Bind Event Listeners + // + // Bind any events that are required on startup. Common events are: + // 'load', 'deviceready', 'offline', and 'online'. + bindEvents: function() { + document.addEventListener('deviceready', this.onDeviceReady, false); + }, + // deviceready Event Handler + // + // The scope of 'this' is the event. In order to call the 'receivedEvent' + // function, we must explicity call 'app.receivedEvent(...);' + onDeviceReady: function() { + app.receivedEvent('deviceready'); + }, + // Update DOM on a Received Event + receivedEvent: function(id) { + var parentElement = document.getElementById(id); + var listeningElement = parentElement.querySelector('.listening'); + var receivedElement = parentElement.querySelector('.received'); + + listeningElement.setAttribute('style', 'display:none;'); + receivedElement.setAttribute('style', 'display:block;'); + + console.log('Received Event: ' + id); + } +}; diff --git a/platforms/android/build.xml b/platforms/android/build.xml new file mode 100644 index 0000000..4eae3ec --- /dev/null +++ b/platforms/android/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platforms/android/cordova/android_sdk_version b/platforms/android/cordova/android_sdk_version new file mode 100644 index 0000000..547f41b --- /dev/null +++ b/platforms/android/cordova/android_sdk_version @@ -0,0 +1,29 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var android_sdk_version = require('./lib/android_sdk_version'); + +android_sdk_version.run().done(null, function(err) { + console.log(err); + process.exit(2); +}); + + diff --git a/platforms/android/cordova/build b/platforms/android/cordova/build new file mode 100644 index 0000000..a38f3b6 --- /dev/null +++ b/platforms/android/cordova/build @@ -0,0 +1,37 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var build = require('./lib/build'), + reqs = require('./lib/check_reqs'), + args = process.argv; + +// Support basic help commands +if(args[2] == '--help' || args[2] == '/?' || args[2] == '-h' || + args[2] == 'help' || args[2] == '-help' || args[2] == '/help') { + build.help(); +} else { + reqs.run().then(function() { + return build.run(args[2]); + }).done(null, function(err) { + console.error(err); + process.exit(2); + }); +} diff --git a/platforms/android/cordova/build.bat b/platforms/android/cordova/build.bat new file mode 100644 index 0000000..2f317e3 --- /dev/null +++ b/platforms/android/cordova/build.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0build" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/check_reqs b/platforms/android/cordova/check_reqs new file mode 100644 index 0000000..2ac8752 --- /dev/null +++ b/platforms/android/cordova/check_reqs @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var check_reqs = require('./lib/check_reqs'); + +check_reqs.run().done(null, function(err) { + console.log(err); + process.exit(2); +}); + diff --git a/platforms/android/cordova/clean b/platforms/android/cordova/clean new file mode 100644 index 0000000..4e0808b --- /dev/null +++ b/platforms/android/cordova/clean @@ -0,0 +1,36 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var clean = require('./lib/clean'), + reqs = require('./lib/check_reqs'), + args = process.argv; + +// Usage support for when args are given +if(args.length > 2) { + clean.help(); +} else { + reqs.run().done(function() { + return clean.run(); + }, function(err) { + console.error('ERROR: ' + err); + process.exit(2); + }); +} diff --git a/platforms/android/cordova/clean.bat b/platforms/android/cordova/clean.bat new file mode 100644 index 0000000..fa1f669 --- /dev/null +++ b/platforms/android/cordova/clean.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0clean" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/defaults.xml b/platforms/android/cordova/defaults.xml new file mode 100644 index 0000000..24e5725 --- /dev/null +++ b/platforms/android/cordova/defaults.xml @@ -0,0 +1,50 @@ + + + + Hello Cordova + + + A sample Apache Cordova application that responds to the deviceready event. + + + + Apache Cordova Team + + + + + + + + + + + + + + diff --git a/platforms/android/cordova/lib/android_sdk_version.js b/platforms/android/cordova/lib/android_sdk_version.js new file mode 100644 index 0000000..d03e1e7 --- /dev/null +++ b/platforms/android/cordova/lib/android_sdk_version.js @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var shell = require('shelljs'), + child_process = require('child_process'), + Q = require('q'); + +get_highest_sdk = function(results){ + var reg = /\d+/; + var apiLevels = []; + for(var i=0;i/.exec(manifestData); + if (!activityTag) throw new Error('Could not find within ' + manifestPath); + var activityName = /\bandroid:name\s*=\s*"(.+?)"/.exec(activityTag); + if (!activityName) throw new Error('Could not find android:name within ' + manifestPath); + + return packageName[1] + '/.' + activityName[1]; +} + +exports.getActivityName = function() { + return cachedAppInfo = cachedAppInfo || readAppInfoFromManifest(); +}; diff --git a/platforms/android/cordova/lib/build.js b/platforms/android/cordova/lib/build.js new file mode 100644 index 0000000..e57e26b --- /dev/null +++ b/platforms/android/cordova/lib/build.js @@ -0,0 +1,87 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var shell = require('shelljs'), + exec = require('./exec'), + Q = require('q'), + clean = require('./clean'), + path = require('path'), + fs = require('fs'), + ROOT = path.join(__dirname, '..', '..'); + +/* + * Builds the project with ant. + * Returns a promise. + */ +module.exports.run = function(build_type) { + //default build type + build_type = typeof build_type !== 'undefined' ? build_type : "--debug"; + var cmd; + switch(build_type) { + case '--debug' : + cmd = 'ant debug -f ' + path.join(ROOT, 'build.xml'); + break; + case '--release' : + cmd = 'ant release -f ' + path.join(ROOT, 'build.xml'); + break; + case '--nobuild' : + console.log('Skipping build...'); + return Q(); + default : + return Q.reject('Build option \'' + build_type + '\' not recognized.'); + } + if(cmd) { + return clean.run() // TODO: Can we stop cleaning every time and let ant build incrementally? + .then(function() { + return exec(cmd); + }); + } + return Q(); +} + +/* + * Gets the path to the apk file, if not such file exists then + * the script will error out. (should we error or just return undefined?) + */ +module.exports.get_apk = function() { + if(fs.existsSync(path.join(ROOT, 'bin'))) { + var bin_files = fs.readdirSync(path.join(ROOT, 'bin')); + for (file in bin_files) { + if(path.extname(bin_files[file]) == '.apk') { + return path.join(ROOT, 'bin', bin_files[file]); + } + } + console.error('ERROR : No .apk found in \'bin\' folder'); + process.exit(2); + } else { + console.error('ERROR : unable to find project bin folder, could not locate .apk'); + process.exit(2); + } +} + +module.exports.help = function() { + console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'corodva', 'build')) + ' [build_type]'); + console.log('Build Types : '); + console.log(' \'--debug\': Default build, will build project in using ant debug'); + console.log(' \'--release\': will build project using ant release'); + console.log(' \'--nobuild\': will skip build process (can be used with run command)'); + process.exit(0); +} diff --git a/platforms/android/cordova/lib/check_reqs.js b/platforms/android/cordova/lib/check_reqs.js new file mode 100644 index 0000000..f4def79 --- /dev/null +++ b/platforms/android/cordova/lib/check_reqs.js @@ -0,0 +1,94 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var shell = require('shelljs'), + child_process = require('child_process'), + Q = require('q'), + path = require('path'), + fs = require('fs'), + ROOT = path.join(__dirname, '..', '..'); + +// Get valid target from framework/project.properties +module.exports.get_target = function() { + if(fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) { + var target = shell.grep(/target=android-[\d+]/, path.join(ROOT, 'framework', 'project.properties')); + return target.split('=')[1].replace('\n', '').replace('\r', '').replace(' ', ''); + } else if (fs.existsSync(path.join(ROOT, 'project.properties'))) { + // if no target found, we're probably in a project and project.properties is in ROOT. + var target = shell.grep(/target=android-[\d+]/, path.join(ROOT, 'project.properties')); + return target.split('=')[1].replace('\n', '').replace('\r', '').replace(' ', ''); + } +} + +// Returns a promise. +module.exports.check_ant = function() { + var d = Q.defer(); + child_process.exec('ant -version', function(err, stdout, stderr) { + if (err) d.reject(new Error('ERROR : executing command \'ant\', make sure you have ant installed and added to your path.')); + else d.resolve(); + }); + return d.promise; +} + +// Returns a promise. +module.exports.check_java = function() { + if(process.env.JAVA_HOME) { + var d = Q.defer(); + child_process.exec('java -version', function(err, stdout, stderr) { + if(err) d.reject(new Error('ERROR : executing command \'java\', make sure you java environment is set up. Including your JDK and JRE.' + err)); + else d.resolve(); + }); + return d.promise; + } else { + return Q.reject(new Error('ERROR : Make sure JAVA_HOME is set, as well as paths to your JDK and JRE for java.')); + } +} + +// Returns a promise. +module.exports.check_android = function() { + var valid_target = this.get_target(); + var d = Q.defer(); + child_process.exec('android list targets', function(err, stdout, stderr) { + if (err) d.reject(stderr); + else d.resolve(stdout); + }); + + return d.promise.then(function(output) { + if (!output.match(valid_target)) { + return Q.reject(new Error('Please install Android target ' + valid_target.split('-')[1] + ' (the Android newest SDK). Make sure you have the latest Android tools installed as well. Run \"android\" from your command-line to install/update any missing SDKs or tools.')); + } + return Q(); + }, function(stderr) { + if (stderr.match(/command\snot\sfound/)) { + return Q.reject(new Error('The command \"android\" failed. Make sure you have the latest Android SDK installed, and the \"android\" command (inside the tools/ folder) is added to your path.')); + } else { + return Q.reject(new Error('An error occurred while listing Android targets')); + } + }); +} + +// Returns a promise. +module.exports.run = function() { + return Q.all([this.check_ant(), this.check_java(), this.check_android()]).then(function() { + console.log('Looks like your environment fully supports cordova-android development!'); + }); +} + diff --git a/platforms/android/cordova/lib/clean.js b/platforms/android/cordova/lib/clean.js new file mode 100644 index 0000000..0f955f6 --- /dev/null +++ b/platforms/android/cordova/lib/clean.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var exec = require('./exec'), + path = require('path'), + ROOT = path.join(__dirname, '..', '..'); + +/* + * Cleans the project using ant + * Returns a promise. + */ +module.exports.run = function() { + return exec('ant clean -f ' + path.join(ROOT, 'build.xml')); +} + +module.exports.help = function() { + console.log('Usage: ' + path.relative(process.cwd(), process.argv[1])); + console.log('Cleans the project directory.'); + process.exit(0); +} diff --git a/platforms/android/cordova/lib/device.js b/platforms/android/cordova/lib/device.js new file mode 100644 index 0000000..df2a33c --- /dev/null +++ b/platforms/android/cordova/lib/device.js @@ -0,0 +1,86 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var exec = require('./exec'), + Q = require('q'), + path = require('path'), + build = require('./build'), + appinfo = require('./appinfo'), + ROOT = path.join(__dirname, '..', '..'); + +/** + * Returns a promise for the list of the device ID's found + */ +module.exports.list = function() { + return exec('adb devices') + .then(function(output) { + var response = output.split('\n'); + var device_list = []; + for (var i = 1; i < response.length; i++) { + if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) { + device_list.push(response[i].replace(/\tdevice/, '').replace('\r', '')); + } + } + return device_list; + }); +} + +/* + * Installs a previously built application on the device + * and launches it. + * Returns a promise. + */ +module.exports.install = function(target) { + var launchName; + return this.list() + .then(function(device_list) { + if (!device_list || !device_list.length) + return Q.reject('ERROR: Failed to deploy to device, no devices found.'); + + // default device + target = typeof target !== 'undefined' ? target : device_list[0]; + + if (device_list.indexOf(target) < 0) + return Q.reject('ERROR: Unable to find target \'' + target + '\'.'); + + var apk_path = build.get_apk(); + launchName = appinfo.getActivityName(); + console.log('Installing app on device...'); + var cmd = 'adb -s ' + target + ' install -r ' + apk_path; + return exec(cmd); + }).then(function(output) { + if (output.match(/Failure/)) return Q.reject('ERROR: Failed to install apk to device: ' + output); + + //unlock screen + var cmd = 'adb -s ' + target + ' shell input keyevent 82'; + return exec(cmd); + }, function(err) { return Q.reject('ERROR: Failed to install apk to device: ' + err); }) + .then(function() { + // launch the application + console.log('Launching application...'); + var cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName; + return exec(cmd); + }).then(function() { + console.log('LANCH SUCCESS'); + }, function(err) { + return Q.reject('ERROR: Failed to launch application on device: ' + err); + }); +} diff --git a/platforms/android/cordova/lib/emulator.js b/platforms/android/cordova/lib/emulator.js new file mode 100644 index 0000000..367cd94 --- /dev/null +++ b/platforms/android/cordova/lib/emulator.js @@ -0,0 +1,330 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var shell = require('shelljs'), + exec = require('./exec'), + Q = require('q'), + path = require('path'), + appinfo = require('./appinfo'), + build = require('./build'), + ROOT = path.join(__dirname, '..', '..'), + child_process = require('child_process'), + new_emulator = 'cordova_emulator'; + +/** + * Returns a Promise for a list of emulator images in the form of objects + * { + name : , + path : , + target : , + abi : , + skin : + } + */ +module.exports.list_images = function() { + return exec('android list avds') + .then(function(output) { + var response = output.split('\n'); + var emulator_list = []; + for (var i = 1; i < response.length; i++) { + // To return more detailed information use img_obj + var img_obj = {}; + if (response[i].match(/Name:\s/)) { + img_obj['name'] = response[i].split('Name: ')[1].replace('\r', ''); + if (response[i + 1].match(/Path:\s/)) { + i++; + img_obj['path'] = response[i].split('Path: ')[1].replace('\r', ''); + } + if (response[i + 1].match(/\(API\slevel\s/)) { + i++; + img_obj['target'] = response[i].replace('\r', ''); + } + if (response[i + 1].match(/ABI:\s/)) { + i++; + img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', ''); + } + if (response[i + 1].match(/Skin:\s/)) { + i++; + img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', ''); + } + + emulator_list.push(img_obj); + } + /* To just return a list of names use this + if (response[i].match(/Name:\s/)) { + emulator_list.push(response[i].split('Name: ')[1].replace('\r', ''); + }*/ + + } + return emulator_list; + }); +} + +/** + * Will return the closest avd to the projects target + * or undefined if no avds exist. + * Returns a promise. + */ +module.exports.best_image = function() { + var project_target = this.get_target().replace('android-', ''); + return this.list_images() + .then(function(images) { + var closest = 9999; + var best = images[0]; + for (i in images) { + var target = images[i].target; + if(target) { + var num = target.split('(API level ')[1].replace(')', ''); + if (num == project_target) { + return images[i]; + } else if (project_target - num < closest && project_target > num) { + var closest = project_target - num; + best = images[i]; + } + } + } + return best; + }); +} + +// Returns a promise. +module.exports.list_started = function() { + return exec('adb devices') + .then(function(output) { + var response = output.split('\n'); + var started_emulator_list = []; + for (var i = 1; i < response.length; i++) { + if (response[i].match(/device/) && response[i].match(/emulator/)) { + started_emulator_list.push(response[i].replace(/\tdevice/, '').replace('\r', '')); + } + } + return started_emulator_list; + }); +} + +module.exports.get_target = function() { + var target = shell.grep(/target=android-[\d+]/, path.join(ROOT, 'project.properties')); + return target.split('=')[1].replace('\n', '').replace('\r', '').replace(' ', ''); +} + +// Returns a promise. +module.exports.list_targets = function() { + return exec('android list targets') + .then(function(output) { + var target_out = output.split('\n'); + var targets = []; + for (var i = target_out.length; i >= 0; i--) { + if(target_out[i].match(/id:/)) { + targets.push(targets[i].split(' ')[1]); + } + } + return targets; + }); +} + +/* + * Starts an emulator with the given ID, + * and returns the started ID of that emulator. + * If no ID is given it will used the first image availible, + * if no image is availible it will error out (maybe create one?). + * + * Returns a promise. + */ +module.exports.start = function(emulator_ID) { + var self = this; + var emulator_id, num_started, started_emulators; + + return self.list_started() + .then(function(list) { + started_emulators = list; + num_started = started_emulators.length; + if (typeof emulator_ID === 'undefined') { + return self.list_images() + .then(function(emulator_list) { + if (emulator_list.length > 0) { + return self.best_image() + .then(function(best) { + emulator_ID = best.name; + console.log('WARNING : no emulator specified, defaulting to ' + emulator_ID); + return emulator_ID; + }); + } else { + return Q.reject('ERROR : No emulator images (avds) found, if you would like to create an\n' + + ' avd follow the instructions provided here:\n' + + ' http://developer.android.com/tools/devices/index.html\n' + + ' Or run \'android create avd --name --target \'\n' + + ' in on the command line.'); + } + }); + } else { + return Q(emulator_ID); + } + }).then(function() { + var cmd, args; + if(process.platform == 'win32' || process.platform == 'win64') { + cmd = '%comspec%'; + args = ['/c', 'start', 'cmd', '/c', 'emulator', '-avd', emulator_ID]; + } else { + cmd = 'emulator'; + args = ['-avd', emulator_ID]; + } + var proc = child_process.spawn(cmd, args, { stdio: 'inherit', detached: true }); + proc.unref(); // Don't wait for it to finish, since the emulator will probably keep running for a long time. + }).then(function() { + // wait for emulator to start + console.log('Waiting for emulator...'); + return self.wait_for_emulator(num_started); + }).then(function(new_started) { + if (new_started.length > 1) { + for (i in new_started) { + if (started_emulators.indexOf(new_started[i]) < 0) { + emulator_id = new_started[i]; + } + } + } else { + emulator_id = new_started[0]; + } + if (!emulator_id) return Q.reject('ERROR : Failed to start emulator, could not find new emulator'); + + //wait for emulator to boot up + process.stdout.write('Booting up emulator (this may take a while)...'); + return self.wait_for_boot(emulator_id); + }).then(function() { + console.log('BOOT COMPLETE'); + + //unlock screen + return exec('adb -s ' + emulator_id + ' shell input keyevent 82'); + }).then(function() { + //return the new emulator id for the started emulators + return emulator_id; + }); +} + +/* + * Waits for the new emulator to apear on the started-emulator list. + * Returns a promise with a list of newly started emulators' IDs. + */ +module.exports.wait_for_emulator = function(num_running) { + var self = this; + return self.list_started() + .then(function(new_started) { + if (new_started.length > num_running) { + return new_started; + } else { + return Q.delay(1000).then(function() { + return self.wait_for_emulator(num_running); + }); + } + }); +} + +/* + * Waits for the boot animation property of the emulator to switch to 'stopped' + */ +module.exports.wait_for_boot = function(emulator_id) { + var self = this; + return exec('adb -s ' + emulator_id + ' shell getprop init.svc.bootanim') + .then(function(output) { + if (output.match(/stopped/)) { + return; + } else { + process.stdout.write('.'); + return Q.delay(3000).then(function() { + return self.wait_for_boot(emulator_id); + }); + } + }); +} + +/* + * Create avd + * TODO : Enter the stdin input required to complete the creation of an avd. + * Returns a promise. + */ +module.exports.create_image = function(name, target) { + console.log('Creating avd named ' + name); + if (target) { + return exec('android create avd --name ' + name + ' --target ' + target) + .then(null, function(error) { + console.error('ERROR : Failed to create emulator image : '); + console.error(' Do you have the latest android targets including ' + target + '?'); + console.error(create.output); + }); + } else { + console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.'); + return exec('android create avd --name ' + name + ' --target ' + this.list_targets()[0]) + .then(function() { + // TODO: This seems like another error case, even though it always happens. + console.error('ERROR : Unable to create an avd emulator, no targets found.'); + console.error('Please insure you have targets availible by runing the "android" command'); + return Q.reject(); + }, function(error) { + console.error('ERROR : Failed to create emulator image : '); + console.error(error); + }); + } +} + +/* + * Installs a previously built application on the emulator and launches it. + * If no target is specified, then it picks one. + * If no started emulators are found, error out. + * Returns a promise. + */ +module.exports.install = function(target) { + var self = this; + return this.list_started() + .then(function(emulator_list) { + if (emulator_list.length < 1) { + return Q.reject('No started emulators found, please start an emultor before deploying your project.'); + } + + // default emulator + target = typeof target !== 'undefined' ? target : emulator_list[0]; + if (emulator_list.indexOf(target) < 0) { + return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.'); + } + + console.log('Installing app on emulator...'); + var apk_path = build.get_apk(); + return exec('adb -s ' + target + ' install -r ' + apk_path); + }).then(function(output) { + if (output.match(/Failure/)) { + return Q.reject('Failed to install apk to emulator: ' + output); + } + return Q(); + }, function(err) { + return Q.reject('Failed to install apk to emulator: ' + err); + }).then(function() { + //unlock screen + return exec('adb -s ' + target + ' shell input keyevent 82'); + }).then(function() { + // launch the application + console.log('Launching application...'); + var launchName = appinfo.getActivityName(); + cmd = 'adb -s ' + target + ' shell am start -W -a android.intent.action.MAIN -n ' + launchName; + return exec(cmd); + }).then(function(output) { + console.log('LAUNCH SUCCESS'); + }, function(err) { + return Q.reject('Failed to launch app on emulator: ' + err); + }); +} diff --git a/platforms/android/cordova/lib/exec.js b/platforms/android/cordova/lib/exec.js new file mode 100644 index 0000000..6afa9c0 --- /dev/null +++ b/platforms/android/cordova/lib/exec.js @@ -0,0 +1,43 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var child_process = require('child_process'), + Q = require('q'); + +// Takes a command and optional current working directory. +// Returns a promise that either resolves with the stdout, or +// rejects with an error message and the stderr. +module.exports = function(cmd, opt_cwd) { + var d = Q.defer(); + console.log('exec: ' + cmd); + try { + child_process.exec(cmd, {cwd: opt_cwd}, function(err, stdout, stderr) { + console.log([cmd, err, stdout, stderr]); + if (err) d.reject('Error executing "' + cmd + '": ' + stderr); + else d.resolve(stdout); + }); + } catch(e) { + console.error('error caught: ' + e); + d.reject(e); + } + return d.promise; +} + diff --git a/platforms/android/cordova/lib/install-device b/platforms/android/cordova/lib/install-device new file mode 100644 index 0000000..fc4b784 --- /dev/null +++ b/platforms/android/cordova/lib/install-device @@ -0,0 +1,42 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var device = require('./device'), + args = process.argv; + +if(args.length > 2) { + var install_target; + if (args[2].substring(0, 9) == '--target=') { + install_target = args[2].substring(9, args[2].length); + device.install(install_target).done(null, function(err) { + console.error('ERROR: ' + err); + process.exit(2); + }); + } else { + console.error('ERROR : argument \'' + args[2] + '\' not recognized.'); + process.exit(2); + } +} else { + device.install().done(null, function(err) { + console.error('ERROR: ' + err); + process.exit(2); + }); +} diff --git a/platforms/android/cordova/lib/install-device.bat b/platforms/android/cordova/lib/install-device.bat new file mode 100644 index 0000000..ac7214a --- /dev/null +++ b/platforms/android/cordova/lib/install-device.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0install-device" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'install-device' script in 'cordova\lib' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/lib/install-emulator b/platforms/android/cordova/lib/install-emulator new file mode 100644 index 0000000..aa2a34f --- /dev/null +++ b/platforms/android/cordova/lib/install-emulator @@ -0,0 +1,38 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var emulator = require('./emulator'), + args = process.argv; + +var install_target; +if(args.length > 2) { + if (args[2].substring(0, 9) == '--target=') { + install_target = args[2].substring(9, args[2].length); + } else { + console.error('ERROR : argument \'' + args[2] + '\' not recognized.'); + process.exit(2); + } +} + +emulator.install(install_target).done(null, function(err) { + console.error('ERROR: ' + err); + process.exit(2); +}); diff --git a/platforms/android/cordova/lib/install-emulator.bat b/platforms/android/cordova/lib/install-emulator.bat new file mode 100644 index 0000000..1ec6779 --- /dev/null +++ b/platforms/android/cordova/lib/install-emulator.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0install-emulator" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'install-emulator' script in 'cordova\lib' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/lib/list-devices b/platforms/android/cordova/lib/list-devices new file mode 100644 index 0000000..e390bff --- /dev/null +++ b/platforms/android/cordova/lib/list-devices @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var devices = require('./device'); + +// Usage support for when args are given +devices.list().done(function(device_list) { + device_list && device_list.forEach(function(dev) { + console.log(dev); + }); +}, function(err) { + console.error('ERROR: ' + err); + process.exit(2); +}); + diff --git a/platforms/android/cordova/lib/list-devices.bat b/platforms/android/cordova/lib/list-devices.bat new file mode 100644 index 0000000..c0bcdd9 --- /dev/null +++ b/platforms/android/cordova/lib/list-devices.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0list-devices" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'list-devices' script in 'cordova\lib' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/lib/list-emulator-images b/platforms/android/cordova/lib/list-emulator-images new file mode 100644 index 0000000..996cf55 --- /dev/null +++ b/platforms/android/cordova/lib/list-emulator-images @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var emulators = require('./emulator'); + +// Usage support for when args are given +emulators.list_images().done(function(emulator_list) { + emulator_list && emulator_list.forEach(function(emu) { + console.log(emu.name); + }); +}, function(err) { + console.error('ERROR: ' + err); + process.exit(2); +}); diff --git a/platforms/android/cordova/lib/list-emulator-images.bat b/platforms/android/cordova/lib/list-emulator-images.bat new file mode 100644 index 0000000..661cbf9 --- /dev/null +++ b/platforms/android/cordova/lib/list-emulator-images.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0list-emulator-images" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'list-emulator-images' script in 'cordova\lib' folder, aborting...>&2 + EXIT /B 1 +) diff --git a/platforms/android/cordova/lib/list-started-emulators b/platforms/android/cordova/lib/list-started-emulators new file mode 100644 index 0000000..2ae8c5a --- /dev/null +++ b/platforms/android/cordova/lib/list-started-emulators @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var emulators = require('./emulator'); + +// Usage support for when args are given +emulators.list_started().done(function(emulator_list) { + emulator_list && emulator_list.forEach(function(emu) { + console.log(emu); + }); +}, function(err) { + console.error('ERROR: ' + err); + process.exit(2); +}); diff --git a/platforms/android/cordova/lib/list-started-emulators.bat b/platforms/android/cordova/lib/list-started-emulators.bat new file mode 100644 index 0000000..a4e88f7 --- /dev/null +++ b/platforms/android/cordova/lib/list-started-emulators.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0list-started-emulators" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'list-started-emulators' script in 'cordova\lib' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/lib/log.js b/platforms/android/cordova/lib/log.js new file mode 100644 index 0000000..7339b1c --- /dev/null +++ b/platforms/android/cordova/lib/log.js @@ -0,0 +1,57 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var shell = require('shelljs'), + path = require('path'), + Q = require('q'), + child_process = require('child_process'), + ROOT = path.join(__dirname, '..', '..'); + +/* + * Starts running logcat in the shell. + * Returns a promise. + */ +module.exports.run = function() { + var cmd = 'adb logcat | grep -v nativeGetEnabledTags'; + var d = Q.defer(); + var adb = child_process.spawn('adb', ['logcat']); + + adb.stdout.on('data', function(data) { + var lines = data ? data.toString().split('\n') : []; + var out = lines.filter(function(x) { return x.indexOf('nativeGetEnabledTags') < 0; }); + console.log(out.join('\n')); + }); + + adb.stderr.on('data', console.error); + adb.on('close', function(code) { + if (code > 0) { + d.reject('Failed to run logcat command.'); + } else d.resolve(); + }); + + return d.promise; +} + +module.exports.help = function() { + console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'corodva', 'log'))); + console.log('Gives the logcat output on the command line.'); + process.exit(0); +} diff --git a/platforms/android/cordova/lib/run.js b/platforms/android/cordova/lib/run.js new file mode 100644 index 0000000..6806014 --- /dev/null +++ b/platforms/android/cordova/lib/run.js @@ -0,0 +1,139 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var path = require('path'), + build = require('./build'), + emulator = require('./emulator'), + device = require('./device'), + Q = require('q'); + +/* + * Runs the application on a device if availible. + * If not device is found, it will use a started emulator. + * If no started emulators are found it will attempt to start an avd. + * If no avds are found it will error out. + * Returns a promise. + */ + module.exports.run = function(args) { + var build_type; + var install_target; + + for (var i=2; i 0 ? Q() : emulator.start(); + return p.then(function() { emulator.install(); }); + }); + } else if (install_target) { + var devices, started_emulators, avds; + return device.list() + .then(function(res) { + devices = res; + return emulator.list_started(); + }).then(function(res) { + started_emulators = res; + return emulator.list_images(); + }).then(function(res) { + avds = res; + if (devices.indexOf(install_target) > -1) { + return device.install(install_target); + } else if (started_emulators.indexOf(install_target) > -1) { + return emulator.install(install_target); + } else { + // if target emulator isn't started, then start it. + var emulator_ID; + for(avd in avds) { + if(avds[avd].name == install_target) { + return emulator.start(install_target) + .then(function() { emulator.install(emulator_ID); }); + } + } + return Q.reject('Target \'' + install_target + '\' not found, unable to run project'); + } + }); + } else { + // no target given, deploy to device if availible, otherwise use the emulator. + return device.list() + .then(function(device_list) { + if (device_list.length > 0) { + console.log('WARNING : No target specified, deploying to device \'' + device_list[0] + '\'.'); + return device.install(device_list[0]); + } else { + return emulator.list_started() + .then(function(emulator_list) { + if (emulator_list.length > 0) { + console.log('WARNING : No target specified, deploying to emulator \'' + emulator_list[0] + '\'.'); + return emulator.install(emulator_list[0]); + } else { + console.log('WARNING : No started emulators found, starting an emulator.'); + return emulator.best_image() + .then(function(best_avd) { + if(best_avd) { + return emulator.start(best_avd.name) + .then(function(emulator_ID) { + console.log('WARNING : No target specified, deploying to emulator \'' + emulator_ID + '\'.'); + return emulator.install(emulator_ID); + }); + } else { + return emulator.start(); + } + }); + } + }); + } + }); + } + }); +} + +module.exports.help = function() { + console.log('Usage: ' + path.relative(process.cwd(), args[0]) + ' [options]'); + console.log('Build options :'); + console.log(' --debug : Builds project in debug mode'); + console.log(' --release : Builds project in release mode'); + console.log(' --nobuild : Runs the currently built project without recompiling'); + console.log('Deploy options :'); + console.log(' --device : Will deploy the built project to a device'); + console.log(' --emulator : Will deploy the built project to an emulator if one exists'); + console.log(' --target= : Installs to the target with the specified id.'); + process.exit(0); +} diff --git a/platforms/android/cordova/lib/start-emulator b/platforms/android/cordova/lib/start-emulator new file mode 100644 index 0000000..f96bdc3 --- /dev/null +++ b/platforms/android/cordova/lib/start-emulator @@ -0,0 +1,39 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var emulator = require('./emulator'), + args = process.argv; + +var install_target; +if(args.length > 2) { + if (args[2].substring(0, 9) == '--target=') { + install_target = args[2].substring(9, args[2].length); + } else { + console.error('ERROR : argument \'' + args[2] + '\' not recognized.'); + process.exit(2); + } +} + +emulator.start(install_target).done(null, function(err) { + console.error('ERROR: ' + err); + process.exit(2); +}); + diff --git a/platforms/android/cordova/lib/start-emulator.bat b/platforms/android/cordova/lib/start-emulator.bat new file mode 100644 index 0000000..9329d95 --- /dev/null +++ b/platforms/android/cordova/lib/start-emulator.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0start-emulator" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'start-emulator' script in 'cordova\lib' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/log b/platforms/android/cordova/log new file mode 100644 index 0000000..47f0605 --- /dev/null +++ b/platforms/android/cordova/log @@ -0,0 +1,36 @@ +#!/usr/bin/env node + +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +var log = require('./lib/log'), + reqs = require('./lib/check_reqs'), + args = process.argv; + +// Usage support for when args are given +if(args.length > 2) { + log.help(); +} else { + reqs.run().done(function() { + return log.run(); + }, function(err) { + console.error('ERROR: ' + err); + process.exit(2); + }); +} diff --git a/platforms/android/cordova/log.bat b/platforms/android/cordova/log.bat new file mode 100644 index 0000000..875982f --- /dev/null +++ b/platforms/android/cordova/log.bat @@ -0,0 +1,26 @@ +:: Licensed to the Apache Software Foundation (ASF) under one +:: or more contributor license agreements. See the NOTICE file +:: distributed with this work for additional information +:: regarding copyright ownership. The ASF licenses this file +:: to you under the Apache License, Version 2.0 (the +:: "License"); you may not use this file except in compliance +:: with the License. You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, +:: software distributed under the License is distributed on an +:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +:: KIND, either express or implied. See the License for the +:: specific language governing permissions and limitations +:: under the License. + +@ECHO OFF +SET script_path="%~dp0log" +IF EXIST %script_path% ( + node "%script_path%" %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'log' script in 'cordova' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file diff --git a/platforms/android/cordova/node_modules/q/CONTRIBUTING.md b/platforms/android/cordova/node_modules/q/CONTRIBUTING.md new file mode 100644 index 0000000..500ab17 --- /dev/null +++ b/platforms/android/cordova/node_modules/q/CONTRIBUTING.md @@ -0,0 +1,40 @@ + +For pull requests: + +- Be consistent with prevalent style and design decisions. +- Add a Jasmine spec to `specs/q-spec.js`. +- Use `npm test` to avoid regressions. +- Run tests in `q-spec/run.html` in as many supported browsers as you + can find the will to deal with. +- Do not build minified versions; we do this each release. +- If you would be so kind, add a note to `CHANGES.md` in an + appropriate section: + + - `Next Major Version` if it introduces backward incompatibilities + to code in the wild using documented features. + - `Next Minor Version` if it adds a new feature. + - `Next Patch Version` if it fixes a bug. + +For releases: + +- Run `npm test`. +- Run tests in `q-spec/run.html` in a representative sample of every + browser under the sun. +- Run `npm run cover` and make sure you're happy with the results. +- Run `npm run minify` and be sure to commit the resulting `q.min.js`. +- Note the Gzipped size output by the previous command, and update + `README.md` if it has changed to 1 significant digit. +- Stash any local changes. +- Update `CHANGES.md` to reflect all changes in the differences + between `HEAD` and the previous tagged version. Give credit where + credit is due. +- Update `README.md` to address all new, non-experimental features. +- Update the API reference on the Wiki to reflect all non-experimental + features. +- Use `npm version major|minor|patch` to update `package.json`, + commit, and tag the new version. +- Use `npm publish` to send up a new release. +- Send an email to the q-continuum mailing list announcing the new + release and the notes from the change log. This helps folks + maintaining other package ecosystems. + diff --git a/platforms/android/cordova/node_modules/q/LICENSE b/platforms/android/cordova/node_modules/q/LICENSE new file mode 100644 index 0000000..76c5fe4 --- /dev/null +++ b/platforms/android/cordova/node_modules/q/LICENSE @@ -0,0 +1,19 @@ + +Copyright 2009–2012 Kristopher Michael Kowal. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/platforms/android/cordova/node_modules/q/README.md b/platforms/android/cordova/node_modules/q/README.md new file mode 100644 index 0000000..c0f513c --- /dev/null +++ b/platforms/android/cordova/node_modules/q/README.md @@ -0,0 +1,813 @@ +[![Build Status](https://secure.travis-ci.org/kriskowal/q.png?branch=master)](http://travis-ci.org/kriskowal/q) + + + Promises/A+ logo + + +If a function cannot return a value or throw an exception without +blocking, it can return a promise instead. A promise is an object +that represents the return value or the thrown exception that the +function may eventually provide. A promise can also be used as a +proxy for a [remote object][Q-Connection] to overcome latency. + +[Q-Connection]: https://github.com/kriskowal/q-connection + +On the first pass, promises can mitigate the “[Pyramid of +Doom][POD]”: the situation where code marches to the right faster +than it marches forward. + +[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/ + +```javascript +step1(function (value1) { + step2(value1, function(value2) { + step3(value2, function(value3) { + step4(value3, function(value4) { + // Do something with value4 + }); + }); + }); +}); +``` + +With a promise library, you can flatten the pyramid. + +```javascript +Q.fcall(promisedStep1) +.then(promisedStep2) +.then(promisedStep3) +.then(promisedStep4) +.then(function (value4) { + // Do something with value4 +}) +.catch(function (error) { + // Handle any error from all above steps +}) +.done(); +``` + +With this approach, you also get implicit error propagation, just like `try`, +`catch`, and `finally`. An error in `promisedStep1` will flow all the way to +the `catch` function, where it’s caught and handled. (Here `promisedStepN` is +a version of `stepN` that returns a promise.) + +The callback approach is called an “inversion of control”. +A function that accepts a callback instead of a return value +is saying, “Don’t call me, I’ll call you.”. Promises +[un-invert][IOC] the inversion, cleanly separating the input +arguments from control flow arguments. This simplifies the +use and creation of API’s, particularly variadic, +rest and spread arguments. + +[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript + + +## Getting Started + +The Q module can be loaded as: + +- A `` + + + + diff --git a/www/js/index.js b/www/js/index.js new file mode 100644 index 0000000..31d9064 --- /dev/null +++ b/www/js/index.js @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +var app = { + // Application Constructor + initialize: function() { + this.bindEvents(); + }, + // Bind Event Listeners + // + // Bind any events that are required on startup. Common events are: + // 'load', 'deviceready', 'offline', and 'online'. + bindEvents: function() { + document.addEventListener('deviceready', this.onDeviceReady, false); + }, + // deviceready Event Handler + // + // The scope of 'this' is the event. In order to call the 'receivedEvent' + // function, we must explicity call 'app.receivedEvent(...);' + onDeviceReady: function() { + app.receivedEvent('deviceready'); + }, + // Update DOM on a Received Event + receivedEvent: function(id) { + var parentElement = document.getElementById(id); + var listeningElement = parentElement.querySelector('.listening'); + var receivedElement = parentElement.querySelector('.received'); + + listeningElement.setAttribute('style', 'display:none;'); + receivedElement.setAttribute('style', 'display:block;'); + + console.log('Received Event: ' + id); + } +};