diff options
Diffstat (limited to 'StoneIsland/plugins')
182 files changed, 14968 insertions, 21811 deletions
diff --git a/StoneIsland/plugins/android.json b/StoneIsland/plugins/android.json deleted file mode 100755 index 1285146b..00000000 --- a/StoneIsland/plugins/android.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "prepare_queue": { - "installed": [], - "uninstalled": [] - }, - "config_munge": { - "files": {} - }, - "installed_plugins": { - "cordova-plugin-inappbrowser": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-x-socialsharing": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-customurlscheme": { - "URL_SCHEME": "stoneisland", - "ANDROID_SCHEME": " ", - "ANDROID_HOST": " ", - "ANDROID_PATHPREFIX": "/", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-whitelist": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-device": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-network-information": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-dialogs": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-geolocation": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "ionic-plugin-keyboard": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-statusbar": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-app-name": { - "APP_NAME": "Stone Island", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-splashscreen": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "phonegap-plugin-push": { - "SENDER_ID": "85075801930", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-sim": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "phonegap-plugin-mobile-accessibility": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - } - }, - "dependent_plugins": { - "cordova-plugin-compat": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - } - } -}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-androidx-adapter/README.md b/StoneIsland/plugins/cordova-plugin-androidx-adapter/README.md new file mode 100644 index 00000000..de9cdc6b --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx-adapter/README.md @@ -0,0 +1,67 @@ +cordova-plugin-androidx-adapter +=============================== + +If your Cordova project contains plugins/libraries which reference both the Android Support Library and AndroidX, your Android build will fail because the two cannot live side-by-side in an Android build. + +This plugin provides a shim to migrate references to the legacy [Android Support Library](https://developer.android.com/topic/libraries/support-library/index) to the new [AndroidX](https://developer.android.com/jetpack/androidx/migrate) mappings in a Cordova Android platform project. + +This enables a Cordova project for which AndroidX has been enabled (e.g. using [cordova-plugin-androidx](https://github.com/dpa99c/cordova-plugin-androidx)) to successfully build even if it contains plugins which reference the legacy Support Library. + +The plugin uses a hook script to replace any legacy Support Library references: +- Gradle artifacts in `app/build.gradle` and `project.properties` with new [artifact mappings](https://developer.android.com/jetpack/androidx/migrate#artifact_mappings) +- Class/package names in `AndroidManifest.xml` or the Java source code (of Cordova plugins) with new [class mappings](https://developer.android.com/jetpack/androidx/migrate#class_mappings). + +<!-- DONATE --> +[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZRD3W47HQ3EMJ) + +I dedicate a considerable amount of my free time to developing and maintaining this Cordova plugin, along with my other Open Source software. +To help ensure this plugin is kept updated, new features are added and bugfixes are implemented quickly, please donate a couple of dollars (or a little more if you can stretch) as this will help me to afford to dedicate time to its maintenance. Please consider donating if you're using this plugin in an app that makes you money, if you're being paid to make the app, if you're asking for new features or priority bug fixes. +<!-- END DONATE --> + + +# Requirements + +This plugin requires a minimum of [`cordova@8`](https://github.com/apache/cordova-cli) and [`cordova-android@8`](https://github.com/apache/cordova-android). + +# Installation + + $ cordova plugin add cordova-plugin-androidx-adapter + +**IMPORTANT:** This plugin relies on a [Cordova hook script](https://cordova.apache.org/docs/en/latest/guide/appdev/hooks/) so will not work in Cloud Build environments such as Phonegap Build which do not support Cordova hook scripts. + +**WARNING**: Do not install this plugin in a Cordova project in which AndroidX has not already been enabled or the build will fail. + +# Usage + +Once the plugin is installed it will run on each `after_prepare` hook in the Cordova build lifecycle, scanning and migrating any references to legacy Support Library entries in the `build.gradle` or Java source code. + +Note: this plugin operates only during the build process and contains no code which is bundled with or executed inside of the resulting Android app produced by the Cordova build process. + +# Enabling AndroidX + +If AndroidX is not already enabled in your Cordova project you can persistently enable it in your Cordova Android platform project by installing my [cordova-plugin-androidx](https://github.com/dpa99c/cordova-plugin-androidx) plugin. + +License +================ + +The MIT License + +Copyright (c) 2019 Dave Alden / Working Edge Ltd. + +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/StoneIsland/plugins/cordova-plugin-androidx-adapter/apply.js b/StoneIsland/plugins/cordova-plugin-androidx-adapter/apply.js new file mode 100644 index 00000000..7dc44b85 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx-adapter/apply.js @@ -0,0 +1,101 @@ +var PLUGIN_NAME = "cordova-plugin-androidx-adapter"; +var ARTIFACT_MAPPINGS_FILE = "artifact-mappings.json"; +var CLASS_MAPPINGS_FILE = "class-mappings.json"; +var SRC_PATH = "./platforms/android/app/src/main"; +var BUILD_GRADLE_PATH = "./platforms/android/app/build.gradle"; +var PROJECT_PROPERTIES_PATH = "./platforms/android/project.properties"; +var MANIFEST_PATH = "./platforms/android/app/src/main/AndroidManifest.xml"; +var TARGET_FILE_REGEX = /(\.java|\.xml)/; + +var deferral, fs, path, now, recursiveDir; + +function log(message) { + console.log(PLUGIN_NAME + ": " + message); +} + +function onFatalException(ex){ + log("EXCEPTION: " + ex.toString()); + deferral.resolve(); // resolve instead of reject so build doesn't fail +} + +function run() { + try { + fs = require('fs'); + path = require('path'); + recursiveDir = require("recursive-readdir"); + now = require("performance-now") + } catch (e) { + throw("Failed to load dependencies: " + e.toString()); + } + + var startTime = now(); + + var artifactMappings = JSON.parse(fs.readFileSync(path.join(__dirname, '.', ARTIFACT_MAPPINGS_FILE)).toString()), + buildGradle = fs.readFileSync(BUILD_GRADLE_PATH).toString(), + projectProperties = fs.readFileSync(PROJECT_PROPERTIES_PATH).toString(), + androidManifest = fs.readFileSync(MANIFEST_PATH).toString(); + + // Replace artifacts in build.gradle, project.properties & AndroidManifest.xml + for(var oldArtifactName in artifactMappings){ + var newArtifactName = artifactMappings[oldArtifactName], + artifactRegExpStr = sanitiseForRegExp(oldArtifactName) + ':[0-9.+]+'; + buildGradle = buildGradle.replace(new RegExp(artifactRegExpStr, 'gm'), newArtifactName); + projectProperties = projectProperties.replace(new RegExp(artifactRegExpStr, 'gm'), newArtifactName); + } + fs.writeFileSync(BUILD_GRADLE_PATH, buildGradle, 'utf8'); + fs.writeFileSync(PROJECT_PROPERTIES_PATH, projectProperties, 'utf8'); + + var classMappings = JSON.parse(fs.readFileSync(path.join(__dirname, '.', CLASS_MAPPINGS_FILE)).toString()); + + // Replace class/package names in AndroidManifest.xml + for (var oldClassName in classMappings){ + androidManifest = androidManifest.replace(new RegExp(oldClassName, 'g'), classMappings[oldClassName]); + } + fs.writeFileSync(MANIFEST_PATH, androidManifest, 'utf8'); + + // Replace class/package names in source code + recursiveDir(SRC_PATH, [function(file, stats){ + if(stats.isDirectory()){ + return false; + } + return !file.match(TARGET_FILE_REGEX); + }], attempt(function(err, files){ + if(err) throw err; + + for(var filePath of files){ + var fileContents = fs.readFileSync(filePath).toString(); + for (var oldClassName in classMappings){ + fileContents = fileContents.replace(new RegExp(oldClassName, 'g'), classMappings[oldClassName]); + } + fs.writeFileSync(filePath, fileContents, 'utf8'); + } + log("Processed " + files.length + " source files in " + parseInt(now() - startTime) + "ms"); + deferral.resolve(); + })); +} + +function sanitiseForRegExp(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); +} + +function attempt(fn) { + return function () { + try { + fn.apply(this, arguments); + } catch (e) { + onFatalException(e); + } + } +} + +module.exports = function (ctx) { + try{ + deferral = require('q').defer(); + }catch(e){ + e.message = 'Unable to load node module dependency \'q\': '+e.message; + onFatalException(e); + throw e; + } + attempt(run)(); + return deferral.promise; +}; diff --git a/StoneIsland/plugins/cordova-plugin-androidx-adapter/artifact-mappings.json b/StoneIsland/plugins/cordova-plugin-androidx-adapter/artifact-mappings.json new file mode 100644 index 00000000..10b2de65 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx-adapter/artifact-mappings.json @@ -0,0 +1,105 @@ +{
+ "android.arch.core:common": "androidx.arch.core:core-common:2.0.0-rc01",
+ "android.arch.core:core": "androidx.arch.core:core:2.0.0-rc01",
+ "android.arch.core:core-testing": "androidx.arch.core:core-testing:2.0.0-rc01",
+ "android.arch.core:runtime": "androidx.arch.core:core-runtime:2.0.0-rc01",
+ "android.arch.lifecycle:common": "androidx.lifecycle:lifecycle-common:2.0.0-rc01",
+ "android.arch.lifecycle:common-java8": "androidx.lifecycle:lifecycle-common-java8:2.0.0-rc01",
+ "android.arch.lifecycle:compiler": "androidx.lifecycle:lifecycle-compiler:2.0.0-rc01",
+ "android.arch.lifecycle:extensions": "androidx.lifecycle:lifecycle-extensions:2.0.0-rc01",
+ "android.arch.lifecycle:livedata": "androidx.lifecycle:lifecycle-livedata:2.0.0-rc01",
+ "android.arch.lifecycle:livedata-core": "androidx.lifecycle:lifecycle-livedata-core:2.0.0-rc01",
+ "android.arch.lifecycle:reactivestreams": "androidx.lifecycle:lifecycle-reactivestreams:2.0.0-rc01",
+ "android.arch.lifecycle:runtime": "androidx.lifecycle:lifecycle-runtime:2.0.0-rc01",
+ "android.arch.lifecycle:viewmodel": "androidx.lifecycle:lifecycle-viewmodel:2.0.0-rc01",
+ "android.arch.paging:common": "androidx.paging:paging-common:2.0.0-rc01",
+ "android.arch.paging:runtime": "androidx.paging:paging-runtime:2.0.0-rc01",
+ "android.arch.paging:rxjava2": "androidx.paging:paging-rxjava2:2.0.0-rc01",
+ "android.arch.persistence.room:common": "androidx.room:room-common:2.0.0-rc01",
+ "android.arch.persistence.room:compiler": "androidx.room:room-compiler:2.0.0-rc01",
+ "android.arch.persistence.room:guava": "androidx.room:room-guava:2.0.0-rc01",
+ "android.arch.persistence.room:migration": "androidx.room:room-migration:2.0.0-rc01",
+ "android.arch.persistence.room:runtime": "androidx.room:room-runtime:2.0.0-rc01",
+ "android.arch.persistence.room:rxjava2": "androidx.room:room-rxjava2:2.0.0-rc01",
+ "android.arch.persistence.room:testing": "androidx.room:room-testing:2.0.0-rc01",
+ "android.arch.persistence:db": "androidx.sqlite:sqlite:2.0.0-rc01",
+ "android.arch.persistence:db-framework": "androidx.sqlite:sqlite-framework:2.0.0-rc01",
+ "com.android.support.constraint:constraint-layout": "androidx.constraintlayout:constraintlayout:1.1.2",
+ "com.android.support.constraint:constraint-layout-solver": "androidx.constraintlayout:constraintlayout-solver:1.1.2",
+ "com.android.support.test.espresso.idling:idling-concurrent": "androidx.test.espresso.idling:idling-concurrent:3.1.0",
+ "com.android.support.test.espresso.idling:idling-net": "androidx.test.espresso.idling:idling-net:3.1.0",
+ "com.android.support.test.espresso:espresso-accessibility": "androidx.test.espresso:espresso-accessibility:3.1.0",
+ "com.android.support.test.espresso:espresso-contrib": "androidx.test.espresso:espresso-contrib:3.1.0",
+ "com.android.support.test.espresso:espresso-core": "androidx.test.espresso:espresso-core:3.1.0",
+ "com.android.support.test.espresso:espresso-idling-resource": "androidx.test.espresso:espresso-idling-resource:3.1.0",
+ "com.android.support.test.espresso:espresso-intents": "androidx.test.espresso:espresso-intents:3.1.0",
+ "com.android.support.test.espresso:espresso-remote": "androidx.test.espresso:espresso-remote:3.1.0",
+ "com.android.support.test.espresso:espresso-web": "androidx.test.espresso:espresso-web:3.1.0",
+ "com.android.support.test.janktesthelper:janktesthelper": "androidx.test.jank:janktesthelper:1.0.1",
+ "com.android.support.test.services:test-services": "androidx.test:test-services:1.1.0",
+ "com.android.support.test.uiautomator:uiautomator": "androidx.test.uiautomator:uiautomator:2.2.0",
+ "com.android.support.test:monitor": "androidx.test:monitor:1.1.0",
+ "com.android.support.test:orchestrator": "androidx.test:orchestrator:1.1.0",
+ "com.android.support.test:rules": "androidx.test:rules:1.1.0",
+ "com.android.support.test:runner": "androidx.test:runner:1.1.0",
+ "com.android.support:animated-vector-drawable": "androidx.vectordrawable:vectordrawable-animated:1.0.0",
+ "com.android.support:appcompat-v7": "androidx.appcompat:appcompat:1.0.0",
+ "com.android.support:asynclayoutinflater": "androidx.asynclayoutinflater:asynclayoutinflater:1.0.0",
+ "com.android.support:car": "androidx.car:car:1.0.0-alpha5",
+ "com.android.support:cardview-v7": "androidx.cardview:cardview:1.0.0",
+ "com.android.support:collections": "androidx.collection:collection:1.0.0",
+ "com.android.support:coordinatorlayout": "androidx.coordinatorlayout:coordinatorlayout:1.0.0",
+ "com.android.support:cursoradapter": "androidx.cursoradapter:cursoradapter:1.0.0",
+ "com.android.support:customtabs": "androidx.browser:browser:1.0.0",
+ "com.android.support:customview": "androidx.customview:customview:1.0.0",
+ "com.android.support:design": "com.google.android.material:material:1.0.0-rc01",
+ "com.android.support:documentfile": "androidx.documentfile:documentfile:1.0.0",
+ "com.android.support:drawerlayout": "androidx.drawerlayout:drawerlayout:1.0.0",
+ "com.android.support:exifinterface": "androidx.exifinterface:exifinterface:1.0.0",
+ "com.android.support:gridlayout-v7": "androidx.gridlayout:gridlayout:1.0.0",
+ "com.android.support:heifwriter": "androidx.heifwriter:heifwriter:1.0.0",
+ "com.android.support:interpolator": "androidx.interpolator:interpolator:1.0.0",
+ "com.android.support:leanback-v17": "androidx.leanback:leanback:1.0.0",
+ "com.android.support:loader": "androidx.loader:loader:1.0.0",
+ "com.android.support:localbroadcastmanager": "androidx.localbroadcastmanager:localbroadcastmanager:1.0.0",
+ "com.android.support:media2": "androidx.media2:media2:1.0.0-alpha03",
+ "com.android.support:media2-exoplayer": "androidx.media2:media2-exoplayer:1.0.0-alpha01",
+ "com.android.support:mediarouter-v7": "androidx.mediarouter:mediarouter:1.0.0",
+ "com.android.support:multidex": "androidx.multidex:multidex:2.0.0",
+ "com.android.support:multidex-instrumentation": "androidx.multidex:multidex-instrumentation:2.0.0",
+ "com.android.support:palette-v7": "androidx.palette:palette:1.0.0",
+ "com.android.support:percent": "androidx.percentlayout:percentlayout:1.0.0",
+ "com.android.support:preference-leanback-v17": "androidx.leanback:leanback-preference:1.0.0",
+ "com.android.support:preference-v14": "androidx.legacy:legacy-preference-v14:1.0.0",
+ "com.android.support:preference-v7": "androidx.preference:preference:1.0.0",
+ "com.android.support:print": "androidx.print:print:1.0.0",
+ "com.android.support:recommendation": "androidx.recommendation:recommendation:1.0.0",
+ "com.android.support:recyclerview-selection": "androidx.recyclerview:recyclerview-selection:1.0.0",
+ "com.android.support:recyclerview-v7": "androidx.recyclerview:recyclerview:1.0.0",
+ "com.android.support:slices-builders": "androidx.slice:slice-builders:1.0.0",
+ "com.android.support:slices-core": "androidx.slice:slice-core:1.0.0",
+ "com.android.support:slices-view": "androidx.slice:slice-view:1.0.0",
+ "com.android.support:slidingpanelayout": "androidx.slidingpanelayout:slidingpanelayout:1.0.0",
+ "com.android.support:support-annotations": "androidx.annotation:annotation:1.0.0",
+ "com.android.support:support-compat": "androidx.core:core:1.0.0",
+ "com.android.support:support-content": "androidx.contentpager:contentpager:1.0.0",
+ "com.android.support:support-core-ui": "androidx.legacy:legacy-support-core-ui:1.0.0",
+ "com.android.support:support-core-utils": "androidx.legacy:legacy-support-core-utils:1.0.0",
+ "com.android.support:support-dynamic-animation": "androidx.dynamicanimation:dynamicanimation:1.0.0",
+ "com.android.support:support-emoji": "androidx.emoji:emoji:1.0.0",
+ "com.android.support:support-emoji-appcompat": "androidx.emoji:emoji-appcompat:1.0.0",
+ "com.android.support:support-emoji-bundled": "androidx.emoji:emoji-bundled:1.0.0",
+ "com.android.support:support-fragment": "androidx.fragment:fragment:1.0.0",
+ "com.android.support:support-media-compat": "androidx.media:media:1.0.0",
+ "com.android.support:support-tv-provider": "androidx.tvprovider:tvprovider:1.0.0",
+ "com.android.support:support-v13": "androidx.legacy:legacy-support-v13:1.0.0",
+ "com.android.support:support-v4": "androidx.legacy:legacy-support-v4:1.0.0",
+ "com.android.support:support-vector-drawable": "androidx.vectordrawable:vectordrawable:1.0.0",
+ "com.android.support:swiperefreshlayout": "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0",
+ "com.android.support:textclassifier": "androidx.textclassifier:textclassifier:1.0.0",
+ "com.android.support:transition": "androidx.transition:transition:1.0.0",
+ "com.android.support:versionedparcelable": "androidx.versionedparcelable:versionedparcelable:1.0.0",
+ "com.android.support:viewpager": "androidx.viewpager:viewpager:1.0.0",
+ "com.android.support:wear": "androidx.wear:wear:1.0.0",
+ "com.android.support:webkit": "androidx.webkit:webkit:1.0.0"
+}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-androidx-adapter/class-mappings.json b/StoneIsland/plugins/cordova-plugin-androidx-adapter/class-mappings.json new file mode 100644 index 00000000..17ff5c6b --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx-adapter/class-mappings.json @@ -0,0 +1,1938 @@ +{
+ "android.arch.core.executor.AppToolkitTaskExecutor": "androidx.arch.core.executor.AppToolkitTaskExecutor",
+ "android.arch.core.executor.ArchTaskExecutor": "androidx.arch.core.executor.ArchTaskExecutor",
+ "android.arch.core.executor.DefaultTaskExecutor": "androidx.arch.core.executor.DefaultTaskExecutor",
+ "android.arch.core.executor.JunitTaskExecutorRule": "androidx.arch.core.executor.JunitTaskExecutorRule",
+ "android.arch.core.executor.TaskExecutor": "androidx.arch.core.executor.TaskExecutor",
+ "android.arch.core.executor.TaskExecutorWithFakeMainThread": "androidx.arch.core.executor.TaskExecutorWithFakeMainThread",
+ "android.arch.core.executor.testing.CountingTaskExecutorRule": "androidx.arch.core.executor.testing.CountingTaskExecutorRule",
+ "android.arch.core.executor.testing.InstantTaskExecutorRule": "androidx.arch.core.executor.testing.InstantTaskExecutorRule",
+ "android.arch.core.internal.FastSafeIterableMap": "androidx.arch.core.internal.FastSafeIterableMap",
+ "android.arch.core.internal.SafeIterableMap": "androidx.arch.core.internal.SafeIterableMap",
+ "android.arch.core.util.Function": "androidx.arch.core.util.Function",
+ "android.arch.lifecycle.AndroidViewModel": "androidx.lifecycle.AndroidViewModel",
+ "android.arch.lifecycle.ClassesInfoCache": "androidx.lifecycle.ClassesInfoCache",
+ "android.arch.lifecycle.CompositeGeneratedAdaptersObserver": "androidx.lifecycle.CompositeGeneratedAdaptersObserver",
+ "android.arch.lifecycle.ComputableLiveData": "androidx.lifecycle.ComputableLiveData",
+ "android.arch.lifecycle.DefaultLifecycleObserver": "androidx.lifecycle.DefaultLifecycleObserver",
+ "android.arch.lifecycle.Elements_extKt": "androidx.lifecycle.Elements_extKt",
+ "android.arch.lifecycle.EmptyActivityLifecycleCallbacks": "androidx.lifecycle.EmptyActivityLifecycleCallbacks",
+ "android.arch.lifecycle.ErrorMessages": "androidx.lifecycle.ErrorMessages",
+ "android.arch.lifecycle.FullLifecycleObserver": "androidx.lifecycle.FullLifecycleObserver",
+ "android.arch.lifecycle.FullLifecycleObserverAdapter": "androidx.lifecycle.FullLifecycleObserverAdapter",
+ "android.arch.lifecycle.GeneratedAdapter": "androidx.lifecycle.GeneratedAdapter",
+ "android.arch.lifecycle.GenericLifecycleObserver": "androidx.lifecycle.GenericLifecycleObserver",
+ "android.arch.lifecycle.HolderFragment": "androidx.lifecycle.HolderFragment",
+ "android.arch.lifecycle.Input_collectorKt": "androidx.lifecycle.Input_collectorKt",
+ "android.arch.lifecycle.Lifecycle": "androidx.lifecycle.Lifecycle",
+ "android.arch.lifecycle.LifecycleDispatcher": "androidx.lifecycle.LifecycleDispatcher",
+ "android.arch.lifecycle.LifecycleObserver": "androidx.lifecycle.LifecycleObserver",
+ "android.arch.lifecycle.LifecycleOwner": "androidx.lifecycle.LifecycleOwner",
+ "android.arch.lifecycle.LifecycleProcessor": "androidx.lifecycle.LifecycleProcessor",
+ "android.arch.lifecycle.LifecycleRegistry": "androidx.lifecycle.LifecycleRegistry",
+ "android.arch.lifecycle.LifecycleRegistryOwner": "androidx.lifecycle.LifecycleRegistryOwner",
+ "android.arch.lifecycle.LifecycleService": "androidx.lifecycle.LifecycleService",
+ "android.arch.lifecycle.Lifecycling": "androidx.lifecycle.Lifecycling",
+ "android.arch.lifecycle.LiveData": "androidx.lifecycle.LiveData",
+ "android.arch.lifecycle.LiveDataReactiveStreams": "androidx.lifecycle.LiveDataReactiveStreams",
+ "android.arch.lifecycle.MediatorLiveData": "androidx.lifecycle.MediatorLiveData",
+ "android.arch.lifecycle.MethodCallsLogger": "androidx.lifecycle.MethodCallsLogger",
+ "android.arch.lifecycle.model.AdapterClass": "androidx.lifecycle.model.AdapterClass",
+ "android.arch.lifecycle.model.AdapterClassKt": "androidx.lifecycle.model.AdapterClassKt",
+ "android.arch.lifecycle.model.EventMethod": "androidx.lifecycle.model.EventMethod",
+ "android.arch.lifecycle.model.EventMethodCall": "androidx.lifecycle.model.EventMethodCall",
+ "android.arch.lifecycle.model.InputModel": "androidx.lifecycle.model.InputModel",
+ "android.arch.lifecycle.model.LifecycleObserverInfo": "androidx.lifecycle.model.LifecycleObserverInfo",
+ "android.arch.lifecycle.MutableLiveData": "androidx.lifecycle.MutableLiveData",
+ "android.arch.lifecycle.Observer": "androidx.lifecycle.Observer",
+ "android.arch.lifecycle.ObserversCollector": "androidx.lifecycle.ObserversCollector",
+ "android.arch.lifecycle.OnLifecycleEvent": "androidx.lifecycle.OnLifecycleEvent",
+ "android.arch.lifecycle.ProcessLifecycleOwner": "androidx.lifecycle.ProcessLifecycleOwner",
+ "android.arch.lifecycle.ProcessLifecycleOwnerInitializer": "androidx.lifecycle.ProcessLifecycleOwnerInitializer",
+ "android.arch.lifecycle.ReflectiveGenericLifecycleObserver": "androidx.lifecycle.ReflectiveGenericLifecycleObserver",
+ "android.arch.lifecycle.ReportFragment": "androidx.lifecycle.ReportFragment",
+ "android.arch.lifecycle.ServiceLifecycleDispatcher": "androidx.lifecycle.ServiceLifecycleDispatcher",
+ "android.arch.lifecycle.SingleGeneratedAdapterObserver": "androidx.lifecycle.SingleGeneratedAdapterObserver",
+ "android.arch.lifecycle.TransformationKt": "androidx.lifecycle.TransformationKt",
+ "android.arch.lifecycle.Transformations": "androidx.lifecycle.Transformations",
+ "android.arch.lifecycle.Validator": "androidx.lifecycle.Validator",
+ "android.arch.lifecycle.ViewModel": "androidx.lifecycle.ViewModel",
+ "android.arch.lifecycle.ViewModelProvider": "androidx.lifecycle.ViewModelProvider",
+ "android.arch.lifecycle.ViewModelProviders": "androidx.lifecycle.ViewModelProviders",
+ "android.arch.lifecycle.ViewModelStore": "androidx.lifecycle.ViewModelStore",
+ "android.arch.lifecycle.ViewModelStoreOwner": "androidx.lifecycle.ViewModelStoreOwner",
+ "android.arch.lifecycle.ViewModelStores": "androidx.lifecycle.ViewModelStores",
+ "android.arch.lifecycle.WriterKt": "androidx.lifecycle.WriterKt",
+ "android.arch.paging.AsyncPagedListDiffer": "androidx.paging.AsyncPagedListDiffer",
+ "android.arch.paging.ContiguousDataSource": "androidx.paging.ContiguousDataSource",
+ "android.arch.paging.ContiguousPagedList": "androidx.paging.ContiguousPagedList",
+ "android.arch.paging.DataSource": "androidx.paging.DataSource",
+ "android.arch.paging.ItemKeyedDataSource": "androidx.paging.ItemKeyedDataSource",
+ "android.arch.paging.ListDataSource": "androidx.paging.ListDataSource",
+ "android.arch.paging.LivePagedListBuilder": "androidx.paging.LivePagedListBuilder",
+ "android.arch.paging.LivePagedListProvider": "androidx.paging.LivePagedListProvider",
+ "android.arch.paging.PagedList": "androidx.paging.PagedList",
+ "android.arch.paging.PagedListAdapter": "androidx.paging.PagedListAdapter",
+ "android.arch.paging.PagedStorage": "androidx.paging.PagedStorage",
+ "android.arch.paging.PagedStorageDiffHelper": "androidx.paging.PagedStorageDiffHelper",
+ "android.arch.paging.PageKeyedDataSource": "androidx.paging.PageKeyedDataSource",
+ "android.arch.paging.PageResult": "androidx.paging.PageResult",
+ "android.arch.paging.PositionalDataSource": "androidx.paging.PositionalDataSource",
+ "android.arch.paging.RxPagedListBuilder": "androidx.paging.RxPagedListBuilder",
+ "android.arch.paging.SnapshotPagedList": "androidx.paging.SnapshotPagedList",
+ "android.arch.paging.TiledDataSource": "androidx.paging.TiledDataSource",
+ "android.arch.paging.TiledPagedList": "androidx.paging.TiledPagedList",
+ "android.arch.paging.WrapperItemKeyedDataSource": "androidx.paging.WrapperItemKeyedDataSource",
+ "android.arch.paging.WrapperPageKeyedDataSource": "androidx.paging.WrapperPageKeyedDataSource",
+ "android.arch.paging.WrapperPositionalDataSource": "androidx.paging.WrapperPositionalDataSource",
+ "android.arch.persistence.db.framework.FrameworkSQLiteDatabase": "androidx.sqlite.db.framework.FrameworkSQLiteDatabase",
+ "android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper": "androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper",
+ "android.arch.persistence.db.framework.FrameworkSQLiteOpenHelperFactory": "androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory",
+ "android.arch.persistence.db.framework.FrameworkSQLiteProgram": "androidx.sqlite.db.framework.FrameworkSQLiteProgram",
+ "android.arch.persistence.db.framework.FrameworkSQLiteStatement": "androidx.sqlite.db.framework.FrameworkSQLiteStatement",
+ "android.arch.persistence.db.SimpleSQLiteQuery": "androidx.sqlite.db.SimpleSQLiteQuery",
+ "android.arch.persistence.db.SupportSQLiteDatabase": "androidx.sqlite.db.SupportSQLiteDatabase",
+ "android.arch.persistence.db.SupportSQLiteOpenHelper": "androidx.sqlite.db.SupportSQLiteOpenHelper",
+ "android.arch.persistence.db.SupportSQLiteProgram": "androidx.sqlite.db.SupportSQLiteProgram",
+ "android.arch.persistence.db.SupportSQLiteQuery": "androidx.sqlite.db.SupportSQLiteQuery",
+ "android.arch.persistence.db.SupportSQLiteQueryBuilder": "androidx.sqlite.db.SupportSQLiteQueryBuilder",
+ "android.arch.persistence.db.SupportSQLiteStatement": "androidx.sqlite.db.SupportSQLiteStatement",
+ "android.arch.persistence.room.ColumnInfo": "androidx.room.ColumnInfo",
+ "android.arch.persistence.room.Dao": "androidx.room.Dao",
+ "android.arch.persistence.room.Database": "androidx.room.Database",
+ "android.arch.persistence.room.DatabaseConfiguration": "androidx.room.DatabaseConfiguration",
+ "android.arch.persistence.room.Delete": "androidx.room.Delete",
+ "android.arch.persistence.room.Embedded": "androidx.room.Embedded",
+ "android.arch.persistence.room.EmptyResultSetException": "androidx.room.EmptyResultSetException",
+ "android.arch.persistence.room.Entity": "androidx.room.Entity",
+ "android.arch.persistence.room.EntityDeletionOrUpdateAdapter": "androidx.room.EntityDeletionOrUpdateAdapter",
+ "android.arch.persistence.room.EntityInsertionAdapter": "androidx.room.EntityInsertionAdapter",
+ "android.arch.persistence.room.ext.AndroidTypeNames": "androidx.room.ext.AndroidTypeNames",
+ "android.arch.persistence.room.ext.ArchTypeNames": "androidx.room.ext.ArchTypeNames",
+ "android.arch.persistence.room.ext.CommonTypeNames": "androidx.room.ext.CommonTypeNames",
+ "android.arch.persistence.room.ext.Element_extKt": "androidx.room.ext.Element_extKt",
+ "android.arch.persistence.room.ext.GuavaBaseTypeNames": "androidx.room.ext.GuavaBaseTypeNames",
+ "android.arch.persistence.room.ext.GuavaUtilConcurrentTypeNames": "androidx.room.ext.GuavaUtilConcurrentTypeNames",
+ "android.arch.persistence.room.ext.Javapoet_extKt": "androidx.room.ext.Javapoet_extKt",
+ "android.arch.persistence.room.ext.KotlinMetadataProcessor": "androidx.room.ext.KotlinMetadataProcessor",
+ "android.arch.persistence.room.ext.LifecyclesTypeNames": "androidx.room.ext.LifecyclesTypeNames",
+ "android.arch.persistence.room.ext.PagingTypeNames": "androidx.room.ext.PagingTypeNames",
+ "android.arch.persistence.room.ext.ReactiveStreamsTypeNames": "androidx.room.ext.ReactiveStreamsTypeNames",
+ "android.arch.persistence.room.ext.RoomGuavaTypeNames": "androidx.room.ext.RoomGuavaTypeNames",
+ "android.arch.persistence.room.ext.RoomRxJava2TypeNames": "androidx.room.ext.RoomRxJava2TypeNames",
+ "android.arch.persistence.room.ext.RoomTypeNames": "androidx.room.ext.RoomTypeNames",
+ "android.arch.persistence.room.ext.RxJava2TypeNames": "androidx.room.ext.RxJava2TypeNames",
+ "android.arch.persistence.room.ext.SupportDbTypeNames": "androidx.room.ext.SupportDbTypeNames",
+ "android.arch.persistence.room.ForeignKey": "androidx.room.ForeignKey",
+ "android.arch.persistence.room.guava.GuavaRoom": "androidx.room.guava.GuavaRoom",
+ "android.arch.persistence.room.Ignore": "androidx.room.Ignore",
+ "android.arch.persistence.room.Index": "androidx.room.Index",
+ "android.arch.persistence.room.Insert": "androidx.room.Insert",
+ "android.arch.persistence.room.InvalidationTracker": "androidx.room.InvalidationTracker",
+ "android.arch.persistence.room.log.RLog": "androidx.room.log.RLog",
+ "android.arch.persistence.room.migration.bundle.BundleUtil": "androidx.room.migration.bundle.BundleUtil",
+ "android.arch.persistence.room.migration.bundle.DatabaseBundle": "androidx.room.migration.bundle.DatabaseBundle",
+ "android.arch.persistence.room.migration.bundle.EntityBundle": "androidx.room.migration.bundle.EntityBundle",
+ "android.arch.persistence.room.migration.bundle.FieldBundle": "androidx.room.migration.bundle.FieldBundle",
+ "android.arch.persistence.room.migration.bundle.ForeignKeyBundle": "androidx.room.migration.bundle.ForeignKeyBundle",
+ "android.arch.persistence.room.migration.bundle.IndexBundle": "androidx.room.migration.bundle.IndexBundle",
+ "android.arch.persistence.room.migration.bundle.PrimaryKeyBundle": "androidx.room.migration.bundle.PrimaryKeyBundle",
+ "android.arch.persistence.room.migration.bundle.SchemaBundle": "androidx.room.migration.bundle.SchemaBundle",
+ "android.arch.persistence.room.migration.bundle.SchemaEquality": "androidx.room.migration.bundle.SchemaEquality",
+ "android.arch.persistence.room.migration.bundle.SchemaEqualityUtil": "androidx.room.migration.bundle.SchemaEqualityUtil",
+ "android.arch.persistence.room.migration.Migration": "androidx.room.migration.Migration",
+ "android.arch.persistence.room.OnConflictStrategy": "androidx.room.OnConflictStrategy",
+ "android.arch.persistence.room.paging.LimitOffsetDataSource": "androidx.room.paging.LimitOffsetDataSource",
+ "android.arch.persistence.room.parser.Collate": "androidx.room.parser.Collate",
+ "android.arch.persistence.room.parser.ParsedQuery": "androidx.room.parser.ParsedQuery",
+ "android.arch.persistence.room.parser.ParserErrors": "androidx.room.parser.ParserErrors",
+ "android.arch.persistence.room.parser.QueryType": "androidx.room.parser.QueryType",
+ "android.arch.persistence.room.parser.QueryVisitor": "androidx.room.parser.QueryVisitor",
+ "android.arch.persistence.room.parser.Section": "androidx.room.parser.Section",
+ "android.arch.persistence.room.parser.SectionType": "androidx.room.parser.SectionType",
+ "android.arch.persistence.room.parser.SQLiteBaseListener": "androidx.room.parser.SQLiteBaseListener",
+ "android.arch.persistence.room.parser.SQLiteBaseVisitor": "androidx.room.parser.SQLiteBaseVisitor",
+ "android.arch.persistence.room.parser.SQLiteLexer": "androidx.room.parser.SQLiteLexer",
+ "android.arch.persistence.room.parser.SQLiteListener": "androidx.room.parser.SQLiteListener",
+ "android.arch.persistence.room.parser.SQLiteParser": "androidx.room.parser.SQLiteParser",
+ "android.arch.persistence.room.parser.SQLiteVisitor": "androidx.room.parser.SQLiteVisitor",
+ "android.arch.persistence.room.parser.SqlParser": "androidx.room.parser.SqlParser",
+ "android.arch.persistence.room.parser.SQLTypeAffinity": "androidx.room.parser.SQLTypeAffinity",
+ "android.arch.persistence.room.parser.Table": "androidx.room.parser.Table",
+ "android.arch.persistence.room.preconditions.Checks": "androidx.room.preconditions.Checks",
+ "android.arch.persistence.room.PrimaryKey": "androidx.room.PrimaryKey",
+ "android.arch.persistence.room.processor.cache.Cache": "androidx.room.processor.cache.Cache",
+ "android.arch.persistence.room.processor.Context": "androidx.room.processor.Context",
+ "android.arch.persistence.room.processor.CustomConverterProcessor": "androidx.room.processor.CustomConverterProcessor",
+ "android.arch.persistence.room.processor.DaoProcessor": "androidx.room.processor.DaoProcessor",
+ "android.arch.persistence.room.processor.DatabaseProcessor": "androidx.room.processor.DatabaseProcessor",
+ "android.arch.persistence.room.processor.DeletionMethodProcessor": "androidx.room.processor.DeletionMethodProcessor",
+ "android.arch.persistence.room.processor.EntityProcessor": "androidx.room.processor.EntityProcessor",
+ "android.arch.persistence.room.processor.FieldProcessor": "androidx.room.processor.FieldProcessor",
+ "android.arch.persistence.room.processor.InsertionMethodProcessor": "androidx.room.processor.InsertionMethodProcessor",
+ "android.arch.persistence.room.processor.OnConflictProcessor": "androidx.room.processor.OnConflictProcessor",
+ "android.arch.persistence.room.processor.PojoMethodProcessor": "androidx.room.processor.PojoMethodProcessor",
+ "android.arch.persistence.room.processor.PojoProcessor": "androidx.room.processor.PojoProcessor",
+ "android.arch.persistence.room.processor.ProcessorErrors": "androidx.room.processor.ProcessorErrors",
+ "android.arch.persistence.room.processor.QueryMethodProcessor": "androidx.room.processor.QueryMethodProcessor",
+ "android.arch.persistence.room.processor.QueryParameterProcessor": "androidx.room.processor.QueryParameterProcessor",
+ "android.arch.persistence.room.processor.RawQueryMethodProcessor": "androidx.room.processor.RawQueryMethodProcessor",
+ "android.arch.persistence.room.processor.ShortcutMethodProcessor": "androidx.room.processor.ShortcutMethodProcessor",
+ "android.arch.persistence.room.processor.ShortcutParameterProcessor": "androidx.room.processor.ShortcutParameterProcessor",
+ "android.arch.persistence.room.processor.SuppressWarningProcessor": "androidx.room.processor.SuppressWarningProcessor",
+ "android.arch.persistence.room.processor.TransactionMethodProcessor": "androidx.room.processor.TransactionMethodProcessor",
+ "android.arch.persistence.room.processor.UpdateMethodProcessor": "androidx.room.processor.UpdateMethodProcessor",
+ "android.arch.persistence.room.Query": "androidx.room.Query",
+ "android.arch.persistence.room.RawQuery": "androidx.room.RawQuery",
+ "android.arch.persistence.room.Relation": "androidx.room.Relation",
+ "android.arch.persistence.room.Room": "androidx.room.Room",
+ "android.arch.persistence.room.RoomDatabase": "androidx.room.RoomDatabase",
+ "android.arch.persistence.room.RoomMasterTable": "androidx.room.RoomMasterTable",
+ "android.arch.persistence.room.RoomOpenHelper": "androidx.room.RoomOpenHelper",
+ "android.arch.persistence.room.RoomProcessor": "androidx.room.RoomProcessor",
+ "android.arch.persistence.room.RoomSQLiteQuery": "androidx.room.RoomSQLiteQuery",
+ "android.arch.persistence.room.RoomWarnings": "androidx.room.RoomWarnings",
+ "android.arch.persistence.room.RxRoom": "androidx.room.RxRoom",
+ "android.arch.persistence.room.SharedSQLiteStatement": "androidx.room.SharedSQLiteStatement",
+ "android.arch.persistence.room.SkipQueryVerification": "androidx.room.SkipQueryVerification",
+ "android.arch.persistence.room.solver.binderprovider.CursorQueryResultBinderProvider": "androidx.room.solver.binderprovider.CursorQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.DataSourceFactoryQueryResultBinderProvider": "androidx.room.solver.binderprovider.DataSourceFactoryQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.DataSourceQueryResultBinderProvider": "androidx.room.solver.binderprovider.DataSourceQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.FlowableQueryResultBinderProvider": "androidx.room.solver.binderprovider.FlowableQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.GuavaListenableFutureQueryResultBinderProvider": "androidx.room.solver.binderprovider.GuavaListenableFutureQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.InstantQueryResultBinderProvider": "androidx.room.solver.binderprovider.InstantQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.LiveDataQueryResultBinderProvider": "androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.RxCallableQueryResultBinderProvider": "androidx.room.solver.binderprovider.RxCallableQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.RxMaybeQueryResultBinderProvider": "androidx.room.solver.binderprovider.RxMaybeQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.binderprovider.RxSingleQueryResultBinderProvider": "androidx.room.solver.binderprovider.RxSingleQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.CodeGenScope": "androidx.room.solver.CodeGenScope",
+ "android.arch.persistence.room.solver.ObservableQueryResultBinderProvider": "androidx.room.solver.ObservableQueryResultBinderProvider",
+ "android.arch.persistence.room.solver.query.parameter.ArrayQueryParameterAdapter": "androidx.room.solver.query.parameter.ArrayQueryParameterAdapter",
+ "android.arch.persistence.room.solver.query.parameter.BasicQueryParameterAdapter": "androidx.room.solver.query.parameter.BasicQueryParameterAdapter",
+ "android.arch.persistence.room.solver.query.parameter.CollectionQueryParameterAdapter": "androidx.room.solver.query.parameter.CollectionQueryParameterAdapter",
+ "android.arch.persistence.room.solver.query.parameter.QueryParameterAdapter": "androidx.room.solver.query.parameter.QueryParameterAdapter",
+ "android.arch.persistence.room.solver.query.result.ArrayQueryResultAdapter": "androidx.room.solver.query.result.ArrayQueryResultAdapter",
+ "android.arch.persistence.room.solver.query.result.BaseObservableQueryResultBinder": "androidx.room.solver.query.result.BaseObservableQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.CursorQueryResultBinder": "androidx.room.solver.query.result.CursorQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.DataSourceFactoryQueryResultBinder": "androidx.room.solver.query.result.DataSourceFactoryQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.EntityRowAdapter": "androidx.room.solver.query.result.EntityRowAdapter",
+ "android.arch.persistence.room.solver.query.result.FlowableQueryResultBinder": "androidx.room.solver.query.result.FlowableQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.GuavaListenableFutureQueryResultBinder": "androidx.room.solver.query.result.GuavaListenableFutureQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.GuavaOptionalQueryResultAdapter": "androidx.room.solver.query.result.GuavaOptionalQueryResultAdapter",
+ "android.arch.persistence.room.solver.query.result.InstantQueryResultBinder": "androidx.room.solver.query.result.InstantQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.ListQueryResultAdapter": "androidx.room.solver.query.result.ListQueryResultAdapter",
+ "android.arch.persistence.room.solver.query.result.LiveDataQueryResultBinder": "androidx.room.solver.query.result.LiveDataQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.OptionalQueryResultAdapter": "androidx.room.solver.query.result.OptionalQueryResultAdapter",
+ "android.arch.persistence.room.solver.query.result.PojoRowAdapter": "androidx.room.solver.query.result.PojoRowAdapter",
+ "android.arch.persistence.room.solver.query.result.PositionalDataSourceQueryResultBinder": "androidx.room.solver.query.result.PositionalDataSourceQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.QueryResultAdapter": "androidx.room.solver.query.result.QueryResultAdapter",
+ "android.arch.persistence.room.solver.query.result.QueryResultBinder": "androidx.room.solver.query.result.QueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.RowAdapter": "androidx.room.solver.query.result.RowAdapter",
+ "android.arch.persistence.room.solver.query.result.RxCallableQueryResultBinder": "androidx.room.solver.query.result.RxCallableQueryResultBinder",
+ "android.arch.persistence.room.solver.query.result.SingleColumnRowAdapter": "androidx.room.solver.query.result.SingleColumnRowAdapter",
+ "android.arch.persistence.room.solver.query.result.SingleEntityQueryResultAdapter": "androidx.room.solver.query.result.SingleEntityQueryResultAdapter",
+ "android.arch.persistence.room.solver.query.result.TransactionWrapper": "androidx.room.solver.query.result.TransactionWrapper",
+ "android.arch.persistence.room.solver.query.result.TransactionWrapperKt": "androidx.room.solver.query.result.TransactionWrapperKt",
+ "android.arch.persistence.room.solver.QueryResultBinderProvider": "androidx.room.solver.QueryResultBinderProvider",
+ "android.arch.persistence.room.solver.TypeAdapterStore": "androidx.room.solver.TypeAdapterStore",
+ "android.arch.persistence.room.solver.types.BoxedBooleanToBoxedIntConverter": "androidx.room.solver.types.BoxedBooleanToBoxedIntConverter",
+ "android.arch.persistence.room.solver.types.BoxedPrimitiveColumnTypeAdapter": "androidx.room.solver.types.BoxedPrimitiveColumnTypeAdapter",
+ "android.arch.persistence.room.solver.types.ByteArrayColumnTypeAdapter": "androidx.room.solver.types.ByteArrayColumnTypeAdapter",
+ "android.arch.persistence.room.solver.types.ColumnTypeAdapter": "androidx.room.solver.types.ColumnTypeAdapter",
+ "android.arch.persistence.room.solver.types.CompositeAdapter": "androidx.room.solver.types.CompositeAdapter",
+ "android.arch.persistence.room.solver.types.CompositeTypeConverter": "androidx.room.solver.types.CompositeTypeConverter",
+ "android.arch.persistence.room.solver.types.CursorValueReader": "androidx.room.solver.types.CursorValueReader",
+ "android.arch.persistence.room.solver.types.CustomTypeConverterWrapper": "androidx.room.solver.types.CustomTypeConverterWrapper",
+ "android.arch.persistence.room.solver.types.NoOpConverter": "androidx.room.solver.types.NoOpConverter",
+ "android.arch.persistence.room.solver.types.PrimitiveBooleanToIntConverter": "androidx.room.solver.types.PrimitiveBooleanToIntConverter",
+ "android.arch.persistence.room.solver.types.PrimitiveColumnTypeAdapter": "androidx.room.solver.types.PrimitiveColumnTypeAdapter",
+ "android.arch.persistence.room.solver.types.StatementValueBinder": "androidx.room.solver.types.StatementValueBinder",
+ "android.arch.persistence.room.solver.types.StringColumnTypeAdapter": "androidx.room.solver.types.StringColumnTypeAdapter",
+ "android.arch.persistence.room.solver.types.TypeConverter": "androidx.room.solver.types.TypeConverter",
+ "android.arch.persistence.room.testing.MigrationTestHelper": "androidx.room.testing.MigrationTestHelper",
+ "android.arch.persistence.room.Transaction": "androidx.room.Transaction",
+ "android.arch.persistence.room.TypeConverter": "androidx.room.TypeConverter",
+ "android.arch.persistence.room.TypeConverters": "androidx.room.TypeConverters",
+ "android.arch.persistence.room.Update": "androidx.room.Update",
+ "android.arch.persistence.room.util.StringUtil": "androidx.room.util.StringUtil",
+ "android.arch.persistence.room.util.TableInfo": "androidx.room.util.TableInfo",
+ "android.arch.persistence.room.verifier.ColumnInfo": "androidx.room.verifier.ColumnInfo",
+ "android.arch.persistence.room.verifier.DatabaseVerificaitonErrors": "androidx.room.verifier.DatabaseVerificaitonErrors",
+ "android.arch.persistence.room.verifier.DatabaseVerifier": "androidx.room.verifier.DatabaseVerifier",
+ "android.arch.persistence.room.verifier.QueryResultInfo": "androidx.room.verifier.QueryResultInfo",
+ "android.arch.persistence.room.vo.CallType": "androidx.room.vo.CallType",
+ "android.arch.persistence.room.vo.Constructor": "androidx.room.vo.Constructor",
+ "android.arch.persistence.room.vo.CustomTypeConverter": "androidx.room.vo.CustomTypeConverter",
+ "android.arch.persistence.room.vo.Dao": "androidx.room.vo.Dao",
+ "android.arch.persistence.room.vo.DaoMethod": "androidx.room.vo.DaoMethod",
+ "android.arch.persistence.room.vo.Database": "androidx.room.vo.Database",
+ "android.arch.persistence.room.vo.DeletionMethod": "androidx.room.vo.DeletionMethod",
+ "android.arch.persistence.room.vo.EmbeddedField": "androidx.room.vo.EmbeddedField",
+ "android.arch.persistence.room.vo.Entity": "androidx.room.vo.Entity",
+ "android.arch.persistence.room.vo.Field": "androidx.room.vo.Field",
+ "android.arch.persistence.room.vo.FieldGetter": "androidx.room.vo.FieldGetter",
+ "android.arch.persistence.room.vo.FieldSetter": "androidx.room.vo.FieldSetter",
+ "android.arch.persistence.room.vo.FieldWithIndex": "androidx.room.vo.FieldWithIndex",
+ "android.arch.persistence.room.vo.ForeignKey": "androidx.room.vo.ForeignKey",
+ "android.arch.persistence.room.vo.ForeignKeyAction": "androidx.room.vo.ForeignKeyAction",
+ "android.arch.persistence.room.vo.HasSchemaIdentity": "androidx.room.vo.HasSchemaIdentity",
+ "android.arch.persistence.room.vo.Index": "androidx.room.vo.Index",
+ "android.arch.persistence.room.vo.InsertionMethod": "androidx.room.vo.InsertionMethod",
+ "android.arch.persistence.room.vo.Pojo": "androidx.room.vo.Pojo",
+ "android.arch.persistence.room.vo.PojoMethod": "androidx.room.vo.PojoMethod",
+ "android.arch.persistence.room.vo.PrimaryKey": "androidx.room.vo.PrimaryKey",
+ "android.arch.persistence.room.vo.QueryMethod": "androidx.room.vo.QueryMethod",
+ "android.arch.persistence.room.vo.QueryParameter": "androidx.room.vo.QueryParameter",
+ "android.arch.persistence.room.vo.RawQueryMethod": "androidx.room.vo.RawQueryMethod",
+ "android.arch.persistence.room.vo.Relation": "androidx.room.vo.Relation",
+ "android.arch.persistence.room.vo.RelationCollector": "androidx.room.vo.RelationCollector",
+ "android.arch.persistence.room.vo.SchemaIdentityKey": "androidx.room.vo.SchemaIdentityKey",
+ "android.arch.persistence.room.vo.ShortcutMethod": "androidx.room.vo.ShortcutMethod",
+ "android.arch.persistence.room.vo.ShortcutQueryParameter": "androidx.room.vo.ShortcutQueryParameter",
+ "android.arch.persistence.room.vo.TransactionMethod": "androidx.room.vo.TransactionMethod",
+ "android.arch.persistence.room.vo.UpdateMethod": "androidx.room.vo.UpdateMethod",
+ "android.arch.persistence.room.vo.Warning": "androidx.room.vo.Warning",
+ "android.arch.persistence.room.writer.ClassWriter": "androidx.room.writer.ClassWriter",
+ "android.arch.persistence.room.writer.DaoWriter": "androidx.room.writer.DaoWriter",
+ "android.arch.persistence.room.writer.DatabaseWriter": "androidx.room.writer.DatabaseWriter",
+ "android.arch.persistence.room.writer.EntityCursorConverterWriter": "androidx.room.writer.EntityCursorConverterWriter",
+ "android.arch.persistence.room.writer.EntityDeleteComparator": "androidx.room.writer.EntityDeleteComparator",
+ "android.arch.persistence.room.writer.EntityDeletionAdapterWriter": "androidx.room.writer.EntityDeletionAdapterWriter",
+ "android.arch.persistence.room.writer.EntityInsertionAdapterWriter": "androidx.room.writer.EntityInsertionAdapterWriter",
+ "android.arch.persistence.room.writer.EntityUpdateAdapterWriter": "androidx.room.writer.EntityUpdateAdapterWriter",
+ "android.arch.persistence.room.writer.FieldReadWriteWriter": "androidx.room.writer.FieldReadWriteWriter",
+ "android.arch.persistence.room.writer.PreparedStatementWriter": "androidx.room.writer.PreparedStatementWriter",
+ "android.arch.persistence.room.writer.QueryWriter": "androidx.room.writer.QueryWriter",
+ "android.arch.persistence.room.writer.RelationCollectorMethodWriter": "androidx.room.writer.RelationCollectorMethodWriter",
+ "android.arch.persistence.room.writer.SQLiteOpenHelperWriter": "androidx.room.writer.SQLiteOpenHelperWriter",
+ "android.arch.persistence.room.writer.TableInfoValidationWriter": "androidx.room.writer.TableInfoValidationWriter",
+ "android.databinding.adapters.AbsListViewBindingAdapter": "androidx.databinding.adapters.AbsListViewBindingAdapter",
+ "android.databinding.adapters.AbsSeekBarBindingAdapter": "androidx.databinding.adapters.AbsSeekBarBindingAdapter",
+ "android.databinding.adapters.AbsSpinnerBindingAdapter": "androidx.databinding.adapters.AbsSpinnerBindingAdapter",
+ "android.databinding.adapters.ActionMenuViewBindingAdapter": "androidx.databinding.adapters.ActionMenuViewBindingAdapter",
+ "android.databinding.adapters.AdapterViewBindingAdapter": "androidx.databinding.adapters.AdapterViewBindingAdapter",
+ "android.databinding.adapters.AutoCompleteTextViewBindingAdapter": "androidx.databinding.adapters.AutoCompleteTextViewBindingAdapter",
+ "android.databinding.adapters.CalendarViewBindingAdapter": "androidx.databinding.adapters.CalendarViewBindingAdapter",
+ "android.databinding.adapters.CardViewBindingAdapter": "androidx.databinding.adapters.CardViewBindingAdapter",
+ "android.databinding.adapters.CheckedTextViewBindingAdapter": "androidx.databinding.adapters.CheckedTextViewBindingAdapter",
+ "android.databinding.adapters.ChronometerBindingAdapter": "androidx.databinding.adapters.ChronometerBindingAdapter",
+ "android.databinding.adapters.CompoundButtonBindingAdapter": "androidx.databinding.adapters.CompoundButtonBindingAdapter",
+ "android.databinding.adapters.Converters": "androidx.databinding.adapters.Converters",
+ "android.databinding.adapters.DatePickerBindingAdapter": "androidx.databinding.adapters.DatePickerBindingAdapter",
+ "android.databinding.adapters.ExpandableListViewBindingAdapter": "androidx.databinding.adapters.ExpandableListViewBindingAdapter",
+ "android.databinding.adapters.FrameLayoutBindingAdapter": "androidx.databinding.adapters.FrameLayoutBindingAdapter",
+ "android.databinding.adapters.ImageViewBindingAdapter": "androidx.databinding.adapters.ImageViewBindingAdapter",
+ "android.databinding.adapters.LinearLayoutBindingAdapter": "androidx.databinding.adapters.LinearLayoutBindingAdapter",
+ "android.databinding.adapters.ListenerUtil": "androidx.databinding.adapters.ListenerUtil",
+ "android.databinding.adapters.NumberPickerBindingAdapter": "androidx.databinding.adapters.NumberPickerBindingAdapter",
+ "android.databinding.adapters.ObservableListAdapter": "androidx.databinding.adapters.ObservableListAdapter",
+ "android.databinding.adapters.ProgressBarBindingAdapter": "androidx.databinding.adapters.ProgressBarBindingAdapter",
+ "android.databinding.adapters.RadioGroupBindingAdapter": "androidx.databinding.adapters.RadioGroupBindingAdapter",
+ "android.databinding.adapters.RatingBarBindingAdapter": "androidx.databinding.adapters.RatingBarBindingAdapter",
+ "android.databinding.adapters.SearchViewBindingAdapter": "androidx.databinding.adapters.SearchViewBindingAdapter",
+ "android.databinding.adapters.SeekBarBindingAdapter": "androidx.databinding.adapters.SeekBarBindingAdapter",
+ "android.databinding.adapters.SpinnerBindingAdapter": "androidx.databinding.adapters.SpinnerBindingAdapter",
+ "android.databinding.adapters.SwitchBindingAdapter": "androidx.databinding.adapters.SwitchBindingAdapter",
+ "android.databinding.adapters.SwitchCompatBindingAdapter": "androidx.databinding.adapters.SwitchCompatBindingAdapter",
+ "android.databinding.adapters.TabHostBindingAdapter": "androidx.databinding.adapters.TabHostBindingAdapter",
+ "android.databinding.adapters.TableLayoutBindingAdapter": "androidx.databinding.adapters.TableLayoutBindingAdapter",
+ "android.databinding.adapters.TabWidgetBindingAdapter": "androidx.databinding.adapters.TabWidgetBindingAdapter",
+ "android.databinding.adapters.TextViewBindingAdapter": "androidx.databinding.adapters.TextViewBindingAdapter",
+ "android.databinding.adapters.TimePickerBindingAdapter": "androidx.databinding.adapters.TimePickerBindingAdapter",
+ "android.databinding.adapters.ToolbarBindingAdapter": "androidx.databinding.adapters.ToolbarBindingAdapter",
+ "android.databinding.adapters.VideoViewBindingAdapter": "androidx.databinding.adapters.VideoViewBindingAdapter",
+ "android.databinding.adapters.ViewBindingAdapter": "androidx.databinding.adapters.ViewBindingAdapter",
+ "android.databinding.adapters.ViewGroupBindingAdapter": "androidx.databinding.adapters.ViewGroupBindingAdapter",
+ "android.databinding.adapters.ViewStubBindingAdapter": "androidx.databinding.adapters.ViewStubBindingAdapter",
+ "android.databinding.adapters.ZoomControlsBindingAdapter": "androidx.databinding.adapters.ZoomControlsBindingAdapter",
+ "android.databinding.BaseObservable": "androidx.databinding.BaseObservable",
+ "android.databinding.BaseObservableField": "androidx.databinding.BaseObservableField",
+ "android.databinding.Bindable": "androidx.databinding.Bindable",
+ "android.databinding.BindingAdapter": "androidx.databinding.BindingAdapter",
+ "android.databinding.BindingBuildInfo": "androidx.databinding.BindingBuildInfo",
+ "android.databinding.BindingConversion": "androidx.databinding.BindingConversion",
+ "android.databinding.BindingMethod": "androidx.databinding.BindingMethod",
+ "android.databinding.BindingMethods": "androidx.databinding.BindingMethods",
+ "android.databinding.CallbackRegistry": "androidx.databinding.CallbackRegistry",
+ "android.databinding.DataBinderMapper": "androidx.databinding.DataBinderMapper",
+ "android.databinding.DataBinderMapperImpl": "androidx.databinding.DataBinderMapperImpl",
+ "android.databinding.DataBindingComponent": "androidx.databinding.DataBindingComponent",
+ "android.databinding.DataBindingUtil": "androidx.databinding.DataBindingUtil",
+ "android.databinding.InverseBindingAdapter": "androidx.databinding.InverseBindingAdapter",
+ "android.databinding.InverseBindingListener": "androidx.databinding.InverseBindingListener",
+ "android.databinding.InverseBindingMethod": "androidx.databinding.InverseBindingMethod",
+ "android.databinding.InverseBindingMethods": "androidx.databinding.InverseBindingMethods",
+ "android.databinding.InverseMethod": "androidx.databinding.InverseMethod",
+ "android.databinding.ListChangeRegistry": "androidx.databinding.ListChangeRegistry",
+ "android.databinding.MapChangeRegistry": "androidx.databinding.MapChangeRegistry",
+ "android.databinding.MergedDataBinderMapper": "androidx.databinding.MergedDataBinderMapper",
+ "android.databinding.Observable": "androidx.databinding.Observable",
+ "android.databinding.ObservableArrayList": "androidx.databinding.ObservableArrayList",
+ "android.databinding.ObservableArrayMap": "androidx.databinding.ObservableArrayMap",
+ "android.databinding.ObservableBoolean": "androidx.databinding.ObservableBoolean",
+ "android.databinding.ObservableByte": "androidx.databinding.ObservableByte",
+ "android.databinding.ObservableChar": "androidx.databinding.ObservableChar",
+ "android.databinding.ObservableDouble": "androidx.databinding.ObservableDouble",
+ "android.databinding.ObservableField": "androidx.databinding.ObservableField",
+ "android.databinding.ObservableFloat": "androidx.databinding.ObservableFloat",
+ "android.databinding.ObservableInt": "androidx.databinding.ObservableInt",
+ "android.databinding.ObservableList": "androidx.databinding.ObservableList",
+ "android.databinding.ObservableLong": "androidx.databinding.ObservableLong",
+ "android.databinding.ObservableMap": "androidx.databinding.ObservableMap",
+ "android.databinding.ObservableParcelable": "androidx.databinding.ObservableParcelable",
+ "android.databinding.ObservableShort": "androidx.databinding.ObservableShort",
+ "android.databinding.OnRebindCallback": "androidx.databinding.OnRebindCallback",
+ "android.databinding.PropertyChangeRegistry": "androidx.databinding.PropertyChangeRegistry",
+ "android.databinding.Untaggable": "androidx.databinding.Untaggable",
+ "android.databinding.ViewDataBinding": "androidx.databinding.ViewDataBinding",
+ "android.databinding.ViewStubProxy": "androidx.databinding.ViewStubProxy",
+ "android.support.animation.AnimationHandler": "androidx.dynamicanimation.animation.AnimationHandler",
+ "android.support.animation.DynamicAnimation": "androidx.dynamicanimation.animation.DynamicAnimation",
+ "android.support.animation.FlingAnimation": "androidx.dynamicanimation.animation.FlingAnimation",
+ "android.support.animation.FloatPropertyCompat": "androidx.dynamicanimation.animation.FloatPropertyCompat",
+ "android.support.animation.FloatValueHolder": "androidx.dynamicanimation.animation.FloatValueHolder",
+ "android.support.animation.Force": "androidx.dynamicanimation.animation.Force",
+ "android.support.animation.SpringAnimation": "androidx.dynamicanimation.animation.SpringAnimation",
+ "android.support.animation.SpringForce": "androidx.dynamicanimation.animation.SpringForce",
+ "android.support.annotation.AnimatorRes": "androidx.annotation.AnimatorRes",
+ "android.support.annotation.AnimRes": "androidx.annotation.AnimRes",
+ "android.support.annotation.AnyRes": "androidx.annotation.AnyRes",
+ "android.support.annotation.AnyThread": "androidx.annotation.AnyThread",
+ "android.support.annotation.ArrayRes": "androidx.annotation.ArrayRes",
+ "android.support.annotation.AttrRes": "androidx.annotation.AttrRes",
+ "android.support.annotation.BinderThread": "androidx.annotation.BinderThread",
+ "android.support.annotation.BoolRes": "androidx.annotation.BoolRes",
+ "android.support.annotation.CallSuper": "androidx.annotation.CallSuper",
+ "android.support.annotation.CheckResult": "androidx.annotation.CheckResult",
+ "android.support.annotation.ColorInt": "androidx.annotation.ColorInt",
+ "android.support.annotation.ColorLong": "androidx.annotation.ColorLong",
+ "android.support.annotation.ColorRes": "androidx.annotation.ColorRes",
+ "android.support.annotation.DimenRes": "androidx.annotation.DimenRes",
+ "android.support.annotation.Dimension": "androidx.annotation.Dimension",
+ "android.support.annotation.DrawableRes": "androidx.annotation.DrawableRes",
+ "android.support.annotation.FloatRange": "androidx.annotation.FloatRange",
+ "android.support.annotation.FontRes": "androidx.annotation.FontRes",
+ "android.support.annotation.FractionRes": "androidx.annotation.FractionRes",
+ "android.support.annotation.GuardedBy": "androidx.annotation.GuardedBy",
+ "android.support.annotation.HalfFloat": "androidx.annotation.HalfFloat",
+ "android.support.annotation.IdRes": "androidx.annotation.IdRes",
+ "android.support.annotation.IntDef": "androidx.annotation.IntDef",
+ "android.support.annotation.IntegerRes": "androidx.annotation.IntegerRes",
+ "android.support.annotation.InterpolatorRes": "androidx.annotation.InterpolatorRes",
+ "android.support.annotation.IntRange": "androidx.annotation.IntRange",
+ "android.support.annotation.Keep": "androidx.annotation.Keep",
+ "android.support.annotation.LayoutRes": "androidx.annotation.LayoutRes",
+ "android.support.annotation.LongDef": "androidx.annotation.LongDef",
+ "android.support.annotation.MainThread": "androidx.annotation.MainThread",
+ "android.support.annotation.MenuRes": "androidx.annotation.MenuRes",
+ "android.support.annotation.NavigationRes": "androidx.annotation.NavigationRes",
+ "android.support.annotation.NonNull": "androidx.annotation.NonNull",
+ "android.support.annotation.Nullable": "androidx.annotation.Nullable",
+ "android.support.annotation.PluralsRes": "androidx.annotation.PluralsRes",
+ "android.support.annotation.Px": "androidx.annotation.Px",
+ "android.support.annotation.RawRes": "androidx.annotation.RawRes",
+ "android.support.annotation.RequiresApi": "androidx.annotation.RequiresApi",
+ "android.support.annotation.RequiresFeature": "androidx.annotation.RequiresFeature",
+ "android.support.annotation.RequiresPermission": "androidx.annotation.RequiresPermission",
+ "android.support.annotation.RestrictTo": "androidx.annotation.RestrictTo",
+ "android.support.annotation.Size": "androidx.annotation.Size",
+ "android.support.annotation.StringDef": "androidx.annotation.StringDef",
+ "android.support.annotation.StringRes": "androidx.annotation.StringRes",
+ "android.support.annotation.StyleableRes": "androidx.annotation.StyleableRes",
+ "android.support.annotation.StyleRes": "androidx.annotation.StyleRes",
+ "android.support.annotation.TransitionRes": "androidx.annotation.TransitionRes",
+ "android.support.annotation.UiThread": "androidx.annotation.UiThread",
+ "android.support.annotation.VisibleForTesting": "androidx.annotation.VisibleForTesting",
+ "android.support.annotation.WorkerThread": "androidx.annotation.WorkerThread",
+ "android.support.annotation.XmlRes": "androidx.annotation.XmlRes",
+ "android.support.app.recommendation.ContentRecommendation": "androidx.recommendation.app.ContentRecommendation",
+ "android.support.app.recommendation.RecommendationExtender": "androidx.recommendation.app.RecommendationExtender",
+ "android.support.compat.R": "androidx.core.R",
+ "android.support.constraint.Barrier": "androidx.constraintlayout.widget.Barrier",
+ "android.support.constraint.ConstraintHelper": "androidx.constraintlayout.widget.ConstraintHelper",
+ "android.support.constraint.ConstraintLayout": "androidx.constraintlayout.widget.ConstraintLayout",
+ "android.support.constraint.Constraints": "androidx.constraintlayout.widget.Constraints",
+ "android.support.constraint.ConstraintSet": "androidx.constraintlayout.widget.ConstraintSet",
+ "android.support.constraint.Group": "androidx.constraintlayout.widget.Group",
+ "android.support.constraint.Guideline": "androidx.constraintlayout.widget.Guideline",
+ "android.support.constraint.Placeholder": "androidx.constraintlayout.widget.Placeholder",
+ "android.support.constraint.R": "androidx.constraintlayout.widget.R",
+ "android.support.constraint.solver.ArrayLinkedVariables": "androidx.constraintlayout.solver.ArrayLinkedVariables",
+ "android.support.constraint.solver.ArrayRow": "androidx.constraintlayout.solver.ArrayRow",
+ "android.support.constraint.solver.Cache": "androidx.constraintlayout.solver.Cache",
+ "android.support.constraint.solver.GoalRow": "androidx.constraintlayout.solver.GoalRow",
+ "android.support.constraint.solver.LinearSystem": "androidx.constraintlayout.solver.LinearSystem",
+ "android.support.constraint.solver.Metrics": "androidx.constraintlayout.solver.Metrics",
+ "android.support.constraint.solver.Pools": "androidx.constraintlayout.solver.Pools",
+ "android.support.constraint.solver.SolverVariable": "androidx.constraintlayout.solver.SolverVariable",
+ "android.support.constraint.solver.widgets.Analyzer": "androidx.constraintlayout.solver.widgets.Analyzer",
+ "android.support.constraint.solver.widgets.Barrier": "androidx.constraintlayout.solver.widgets.Barrier",
+ "android.support.constraint.solver.widgets.Chain": "androidx.constraintlayout.solver.widgets.Chain",
+ "android.support.constraint.solver.widgets.ChainHead": "androidx.constraintlayout.solver.widgets.ChainHead",
+ "android.support.constraint.solver.widgets.ConstraintAnchor": "androidx.constraintlayout.solver.widgets.ConstraintAnchor",
+ "android.support.constraint.solver.widgets.ConstraintHorizontalLayout": "androidx.constraintlayout.solver.widgets.ConstraintHorizontalLayout",
+ "android.support.constraint.solver.widgets.ConstraintTableLayout": "androidx.constraintlayout.solver.widgets.ConstraintTableLayout",
+ "android.support.constraint.solver.widgets.ConstraintWidget": "androidx.constraintlayout.solver.widgets.ConstraintWidget",
+ "android.support.constraint.solver.widgets.ConstraintWidgetContainer": "androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer",
+ "android.support.constraint.solver.widgets.ConstraintWidgetGroup": "androidx.constraintlayout.solver.widgets.ConstraintWidgetGroup",
+ "android.support.constraint.solver.widgets.Guideline": "androidx.constraintlayout.solver.widgets.Guideline",
+ "android.support.constraint.solver.widgets.Helper": "androidx.constraintlayout.solver.widgets.Helper",
+ "android.support.constraint.solver.widgets.Optimizer": "androidx.constraintlayout.solver.widgets.Optimizer",
+ "android.support.constraint.solver.widgets.Rectangle": "androidx.constraintlayout.solver.widgets.Rectangle",
+ "android.support.constraint.solver.widgets.ResolutionAnchor": "androidx.constraintlayout.solver.widgets.ResolutionAnchor",
+ "android.support.constraint.solver.widgets.ResolutionDimension": "androidx.constraintlayout.solver.widgets.ResolutionDimension",
+ "android.support.constraint.solver.widgets.ResolutionNode": "androidx.constraintlayout.solver.widgets.ResolutionNode",
+ "android.support.constraint.solver.widgets.Snapshot": "androidx.constraintlayout.solver.widgets.Snapshot",
+ "android.support.constraint.solver.widgets.WidgetContainer": "androidx.constraintlayout.solver.widgets.WidgetContainer",
+ "android.support.content.ContentPager": "androidx.contentpager.content.ContentPager",
+ "android.support.content.InMemoryCursor": "androidx.contentpager.content.InMemoryCursor",
+ "android.support.content.LoaderQueryRunner": "androidx.contentpager.content.LoaderQueryRunner",
+ "android.support.content.Query": "androidx.contentpager.content.Query",
+ "android.support.coordinatorlayout.R": "androidx.coordinatorlayout.R",
+ "android.support.customtabs.CustomTabsCallback": "androidx.browser.customtabs.CustomTabsCallback",
+ "android.support.customtabs.CustomTabsClient": "androidx.browser.customtabs.CustomTabsClient",
+ "android.support.customtabs.CustomTabsIntent": "androidx.browser.customtabs.CustomTabsIntent",
+ "android.support.customtabs.CustomTabsService": "androidx.browser.customtabs.CustomTabsService",
+ "android.support.customtabs.CustomTabsServiceConnection": "androidx.browser.customtabs.CustomTabsServiceConnection",
+ "android.support.customtabs.CustomTabsSession": "androidx.browser.customtabs.CustomTabsSession",
+ "android.support.customtabs.CustomTabsSessionToken": "androidx.browser.customtabs.CustomTabsSessionToken",
+ "android.support.customtabs.ICustomTabsCallback": "android.support.customtabs.ICustomTabsCallback",
+ "android.support.customtabs.ICustomTabsService": "android.support.customtabs.ICustomTabsService",
+ "android.support.customtabs.IPostMessageService": "android.support.customtabs.IPostMessageService",
+ "android.support.customtabs.PostMessageService": "androidx.browser.customtabs.PostMessageService",
+ "android.support.customtabs.PostMessageServiceConnection": "androidx.browser.customtabs.PostMessageServiceConnection",
+ "android.support.customtabs.R": "androidx.browser.R",
+ "android.support.customtabs.TrustedWebUtils": "androidx.browser.customtabs.TrustedWebUtils",
+ "android.support.design.animation.AnimationUtils": "com.google.android.material.animation.AnimationUtils",
+ "android.support.design.animation.AnimatorSetCompat": "com.google.android.material.animation.AnimatorSetCompat",
+ "android.support.design.animation.ArgbEvaluatorCompat": "com.google.android.material.animation.ArgbEvaluatorCompat",
+ "android.support.design.animation.ChildrenAlphaProperty": "com.google.android.material.animation.ChildrenAlphaProperty",
+ "android.support.design.animation.DrawableAlphaProperty": "com.google.android.material.animation.DrawableAlphaProperty",
+ "android.support.design.animation.ImageMatrixProperty": "com.google.android.material.animation.ImageMatrixProperty",
+ "android.support.design.animation.MatrixEvaluator": "com.google.android.material.animation.MatrixEvaluator",
+ "android.support.design.animation.MotionSpec": "com.google.android.material.animation.MotionSpec",
+ "android.support.design.animation.MotionTiming": "com.google.android.material.animation.MotionTiming",
+ "android.support.design.animation.Positioning": "com.google.android.material.animation.Positioning",
+ "android.support.design.behavior.HideBottomViewOnScrollBehavior": "com.google.android.material.behavior.HideBottomViewOnScrollBehavior",
+ "android.support.design.bottomappbar.BottomAppBar": "com.google.android.material.bottomappbar.BottomAppBar",
+ "android.support.design.bottomappbar.BottomAppBarTopEdgeTreatment": "com.google.android.material.bottomappbar.BottomAppBarTopEdgeTreatment",
+ "android.support.design.bottomnavigation.LabelVisibilityMode": "com.google.android.material.bottomnavigation.LabelVisibilityMode",
+ "android.support.design.button.MaterialButton": "com.google.android.material.button.MaterialButton",
+ "android.support.design.button.MaterialButtonBackgroundDrawable": "com.google.android.material.button.MaterialButtonBackgroundDrawable",
+ "android.support.design.button.MaterialButtonHelper": "com.google.android.material.button.MaterialButtonHelper",
+ "android.support.design.canvas.CanvasCompat": "com.google.android.material.canvas.CanvasCompat",
+ "android.support.design.card.MaterialCardView": "com.google.android.material.card.MaterialCardView",
+ "android.support.design.card.MaterialCardViewHelper": "com.google.android.material.card.MaterialCardViewHelper",
+ "android.support.design.chip.Chip": "com.google.android.material.chip.Chip",
+ "android.support.design.chip.ChipDrawable": "com.google.android.material.chip.ChipDrawable",
+ "android.support.design.chip.ChipGroup": "com.google.android.material.chip.ChipGroup",
+ "android.support.design.circularreveal.cardview.CircularRevealCardView": "com.google.android.material.circularreveal.cardview.CircularRevealCardView",
+ "android.support.design.circularreveal.CircularRevealCompat": "com.google.android.material.circularreveal.CircularRevealCompat",
+ "android.support.design.circularreveal.CircularRevealFrameLayout": "com.google.android.material.circularreveal.CircularRevealFrameLayout",
+ "android.support.design.circularreveal.CircularRevealGridLayout": "com.google.android.material.circularreveal.CircularRevealGridLayout",
+ "android.support.design.circularreveal.CircularRevealHelper": "com.google.android.material.circularreveal.CircularRevealHelper",
+ "android.support.design.circularreveal.CircularRevealLinearLayout": "com.google.android.material.circularreveal.CircularRevealLinearLayout",
+ "android.support.design.circularreveal.CircularRevealRelativeLayout": "com.google.android.material.circularreveal.CircularRevealRelativeLayout",
+ "android.support.design.circularreveal.CircularRevealWidget": "com.google.android.material.circularreveal.CircularRevealWidget",
+ "android.support.design.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout": "com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout",
+ "android.support.design.drawable.DrawableUtils": "com.google.android.material.drawable.DrawableUtils",
+ "android.support.design.expandable.ExpandableTransformationWidget": "com.google.android.material.expandable.ExpandableTransformationWidget",
+ "android.support.design.expandable.ExpandableWidget": "com.google.android.material.expandable.ExpandableWidget",
+ "android.support.design.expandable.ExpandableWidgetHelper": "com.google.android.material.expandable.ExpandableWidgetHelper",
+ "android.support.design.internal.BaselineLayout": "com.google.android.material.internal.BaselineLayout",
+ "android.support.design.internal.BottomNavigationItemView": "com.google.android.material.bottomnavigation.BottomNavigationItemView",
+ "android.support.design.internal.BottomNavigationMenu": "com.google.android.material.bottomnavigation.BottomNavigationMenu",
+ "android.support.design.internal.BottomNavigationMenuView": "com.google.android.material.bottomnavigation.BottomNavigationMenuView",
+ "android.support.design.internal.BottomNavigationPresenter": "com.google.android.material.bottomnavigation.BottomNavigationPresenter",
+ "android.support.design.internal.Experimental": "com.google.android.material.internal.Experimental",
+ "android.support.design.internal.FlowLayout": "com.google.android.material.internal.FlowLayout",
+ "android.support.design.internal.ForegroundLinearLayout": "com.google.android.material.internal.ForegroundLinearLayout",
+ "android.support.design.internal.NavigationMenu": "com.google.android.material.internal.NavigationMenu",
+ "android.support.design.internal.NavigationMenuItemView": "com.google.android.material.internal.NavigationMenuItemView",
+ "android.support.design.internal.NavigationMenuPresenter": "com.google.android.material.internal.NavigationMenuPresenter",
+ "android.support.design.internal.NavigationMenuView": "com.google.android.material.internal.NavigationMenuView",
+ "android.support.design.internal.NavigationSubMenu": "com.google.android.material.internal.NavigationSubMenu",
+ "android.support.design.internal.ParcelableSparseArray": "com.google.android.material.internal.ParcelableSparseArray",
+ "android.support.design.internal.ScrimInsetsFrameLayout": "com.google.android.material.internal.ScrimInsetsFrameLayout",
+ "android.support.design.internal.TextScale": "com.google.android.material.internal.TextScale",
+ "android.support.design.internal.ThemeEnforcement": "com.google.android.material.internal.ThemeEnforcement",
+ "android.support.design.internal.ViewUtils": "com.google.android.material.internal.ViewUtils",
+ "android.support.design.R": "com.google.android.material.R",
+ "android.support.design.resources.MaterialResources": "com.google.android.material.resources.MaterialResources",
+ "android.support.design.resources.TextAppearance": "com.google.android.material.resources.TextAppearance",
+ "android.support.design.resources.TextAppearanceConfig": "com.google.android.material.resources.TextAppearanceConfig",
+ "android.support.design.ripple.RippleUtils": "com.google.android.material.ripple.RippleUtils",
+ "android.support.design.shape.CornerTreatment": "com.google.android.material.shape.CornerTreatment",
+ "android.support.design.shape.CutCornerTreatment": "com.google.android.material.shape.CutCornerTreatment",
+ "android.support.design.shape.EdgeTreatment": "com.google.android.material.shape.EdgeTreatment",
+ "android.support.design.shape.InterpolateOnScrollPositionChangeHelper": "com.google.android.material.shape.InterpolateOnScrollPositionChangeHelper",
+ "android.support.design.shape.MaterialShapeDrawable": "com.google.android.material.shape.MaterialShapeDrawable",
+ "android.support.design.shape.RoundedCornerTreatment": "com.google.android.material.shape.RoundedCornerTreatment",
+ "android.support.design.shape.ShapePath": "com.google.android.material.shape.ShapePath",
+ "android.support.design.shape.ShapePathModel": "com.google.android.material.shape.ShapePathModel",
+ "android.support.design.shape.TriangleEdgeTreatment": "com.google.android.material.shape.TriangleEdgeTreatment",
+ "android.support.design.snackbar.ContentViewCallback": "com.google.android.material.snackbar.ContentViewCallback",
+ "android.support.design.stateful.ExtendableSavedState": "com.google.android.material.stateful.ExtendableSavedState",
+ "android.support.design.theme.MaterialComponentsViewInflater": "com.google.android.material.theme.MaterialComponentsViewInflater",
+ "android.support.design.transformation.ExpandableBehavior": "com.google.android.material.transformation.ExpandableBehavior",
+ "android.support.design.transformation.ExpandableTransformationBehavior": "com.google.android.material.transformation.ExpandableTransformationBehavior",
+ "android.support.design.transformation.FabTransformationBehavior": "com.google.android.material.transformation.FabTransformationBehavior",
+ "android.support.design.transformation.FabTransformationScrimBehavior": "com.google.android.material.transformation.FabTransformationScrimBehavior",
+ "android.support.design.transformation.FabTransformationSheetBehavior": "com.google.android.material.transformation.FabTransformationSheetBehavior",
+ "android.support.design.transformation.TransformationChildCard": "com.google.android.material.transformation.TransformationChildCard",
+ "android.support.design.transformation.TransformationChildLayout": "com.google.android.material.transformation.TransformationChildLayout",
+ "android.support.design.widget.AppBarLayout": "com.google.android.material.appbar.AppBarLayout",
+ "android.support.design.widget.BaseTransientBottomBar": "com.google.android.material.snackbar.BaseTransientBottomBar",
+ "android.support.design.widget.BottomNavigationView": "com.google.android.material.bottomnavigation.BottomNavigationView",
+ "android.support.design.widget.BottomSheetBehavior": "com.google.android.material.bottomsheet.BottomSheetBehavior",
+ "android.support.design.widget.BottomSheetDialog": "com.google.android.material.bottomsheet.BottomSheetDialog",
+ "android.support.design.widget.BottomSheetDialogFragment": "com.google.android.material.bottomsheet.BottomSheetDialogFragment",
+ "android.support.design.widget.CheckableImageButton": "com.google.android.material.internal.CheckableImageButton",
+ "android.support.design.widget.CircularBorderDrawable": "com.google.android.material.internal.CircularBorderDrawable",
+ "android.support.design.widget.CircularBorderDrawableLollipop": "com.google.android.material.internal.CircularBorderDrawableLollipop",
+ "android.support.design.widget.CollapsingTextHelper": "com.google.android.material.internal.CollapsingTextHelper",
+ "android.support.design.widget.CollapsingToolbarLayout": "com.google.android.material.appbar.CollapsingToolbarLayout",
+ "android.support.design.widget.CoordinatorLayout": "androidx.coordinatorlayout.widget.CoordinatorLayout",
+ "android.support.design.widget.CutoutDrawable": "com.google.android.material.textfield.CutoutDrawable",
+ "android.support.design.widget.DescendantOffsetUtils": "com.google.android.material.internal.DescendantOffsetUtils",
+ "android.support.design.widget.DrawableUtils": "com.google.android.material.internal.DrawableUtils",
+ "android.support.design.widget.FloatingActionButton": "com.google.android.material.floatingactionbutton.FloatingActionButton",
+ "android.support.design.widget.FloatingActionButtonImpl": "com.google.android.material.floatingactionbutton.FloatingActionButtonImpl",
+ "android.support.design.widget.FloatingActionButtonImplLollipop": "com.google.android.material.floatingactionbutton.FloatingActionButtonImplLollipop",
+ "android.support.design.widget.HeaderBehavior": "com.google.android.material.appbar.HeaderBehavior",
+ "android.support.design.widget.HeaderScrollingViewBehavior": "com.google.android.material.appbar.HeaderScrollingViewBehavior",
+ "android.support.design.widget.IndicatorViewController": "com.google.android.material.textfield.IndicatorViewController",
+ "android.support.design.widget.MathUtils": "com.google.android.material.math.MathUtils",
+ "android.support.design.widget.NavigationView": "com.google.android.material.navigation.NavigationView",
+ "android.support.design.widget.ShadowDrawableWrapper": "com.google.android.material.shadow.ShadowDrawableWrapper",
+ "android.support.design.widget.ShadowViewDelegate": "com.google.android.material.shadow.ShadowViewDelegate",
+ "android.support.design.widget.Snackbar": "com.google.android.material.snackbar.Snackbar",
+ "android.support.design.widget.SnackbarContentLayout": "com.google.android.material.snackbar.SnackbarContentLayout",
+ "android.support.design.widget.SnackbarManager": "com.google.android.material.snackbar.SnackbarManager",
+ "android.support.design.widget.StateListAnimator": "com.google.android.material.internal.StateListAnimator",
+ "android.support.design.widget.SwipeDismissBehavior": "com.google.android.material.behavior.SwipeDismissBehavior",
+ "android.support.design.widget.TabItem": "com.google.android.material.tabs.TabItem",
+ "android.support.design.widget.TabLayout": "com.google.android.material.tabs.TabLayout",
+ "android.support.design.widget.TextInputEditText": "com.google.android.material.textfield.TextInputEditText",
+ "android.support.design.widget.TextInputLayout": "com.google.android.material.textfield.TextInputLayout",
+ "android.support.design.widget.ViewOffsetBehavior": "com.google.android.material.appbar.ViewOffsetBehavior",
+ "android.support.design.widget.ViewOffsetHelper": "com.google.android.material.appbar.ViewOffsetHelper",
+ "android.support.design.widget.ViewUtilsLollipop": "com.google.android.material.appbar.ViewUtilsLollipop",
+ "android.support.design.widget.VisibilityAwareImageButton": "com.google.android.material.internal.VisibilityAwareImageButton",
+ "android.support.graphics.drawable.AndroidResources": "androidx.vectordrawable.graphics.drawable.AndroidResources",
+ "android.support.graphics.drawable.Animatable2Compat": "androidx.vectordrawable.graphics.drawable.Animatable2Compat",
+ "android.support.graphics.drawable.AnimatedVectorDrawableCompat": "androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat",
+ "android.support.graphics.drawable.AnimationUtilsCompat": "androidx.vectordrawable.graphics.drawable.AnimationUtilsCompat",
+ "android.support.graphics.drawable.AnimatorInflaterCompat": "androidx.vectordrawable.graphics.drawable.AnimatorInflaterCompat",
+ "android.support.graphics.drawable.ArgbEvaluator": "androidx.vectordrawable.graphics.drawable.ArgbEvaluator",
+ "android.support.graphics.drawable.PathInterpolatorCompat": "androidx.vectordrawable.graphics.drawable.PathInterpolatorCompat",
+ "android.support.graphics.drawable.VectorDrawableCommon": "androidx.vectordrawable.graphics.drawable.VectorDrawableCommon",
+ "android.support.graphics.drawable.VectorDrawableCompat": "androidx.vectordrawable.graphics.drawable.VectorDrawableCompat",
+ "android.support.media.ExifInterface": "androidx.exifinterface.media.ExifInterface",
+ "android.support.media.tv.BasePreviewProgram": "androidx.tvprovider.media.tv.BasePreviewProgram",
+ "android.support.media.tv.BaseProgram": "androidx.tvprovider.media.tv.BaseProgram",
+ "android.support.media.tv.Channel": "androidx.tvprovider.media.tv.Channel",
+ "android.support.media.tv.ChannelLogoUtils": "androidx.tvprovider.media.tv.ChannelLogoUtils",
+ "android.support.media.tv.CollectionUtils": "androidx.tvprovider.media.tv.CollectionUtils",
+ "android.support.media.tv.PreviewChannel": "androidx.tvprovider.media.tv.PreviewChannel",
+ "android.support.media.tv.PreviewChannelHelper": "androidx.tvprovider.media.tv.PreviewChannelHelper",
+ "android.support.media.tv.PreviewProgram": "androidx.tvprovider.media.tv.PreviewProgram",
+ "android.support.media.tv.Program": "androidx.tvprovider.media.tv.Program",
+ "android.support.media.tv.TvContractCompat": "androidx.tvprovider.media.tv.TvContractCompat",
+ "android.support.media.tv.TvContractUtils": "androidx.tvprovider.media.tv.TvContractUtils",
+ "android.support.media.tv.WatchNextProgram": "androidx.tvprovider.media.tv.WatchNextProgram",
+ "android.support.media2.BaseRemoteMediaPlayerConnector": "android.support.media2.BaseRemoteMediaPlayerConnector",
+ "android.support.media2.DataSourceDesc2": "android.support.media2.DataSourceDesc2",
+ "android.support.media2.MediaPlayerConnector": "android.support.media2.MediaPlayerConnector",
+ "android.support.media2.MediaPlaylistAgent": "android.support.media2.MediaPlaylistAgent",
+ "android.support.media2.MediaSession2": "android.support.media2.MediaSession2",
+ "android.support.mediacompat.R": "androidx.media.R",
+ "android.support.multidex.MultiDex": "androidx.multidex.MultiDex",
+ "android.support.multidex.MultiDexApplication": "androidx.multidex.MultiDexApplication",
+ "android.support.multidex.MultiDexExtractor": "androidx.multidex.MultiDexExtractor",
+ "android.support.multidex.ZipUtil": "androidx.multidex.ZipUtil",
+ "android.support.percent.PercentFrameLayout": "androidx.percentlayout.widget.PercentFrameLayout",
+ "android.support.percent.PercentLayoutHelper": "androidx.percentlayout.widget.PercentLayoutHelper",
+ "android.support.percent.PercentRelativeLayout": "androidx.percentlayout.widget.PercentRelativeLayout",
+ "android.support.percent.R": "androidx.percentlayout.R",
+ "android.support.test.annotation.Beta": "androidx.test.annotation.Beta",
+ "android.support.test.annotation.UiThreadTest": "androidx.test.annotation.UiThreadTest",
+ "android.support.test.espresso.accessibility.AccessibilityChecks": "androidx.test.espresso.accessibility.AccessibilityChecks",
+ "android.support.test.espresso.action.AdapterDataLoaderAction": "androidx.test.espresso.action.AdapterDataLoaderAction",
+ "android.support.test.espresso.action.AdapterDataLoaderActionRemoteMsg": "androidx.test.espresso.action.AdapterDataLoaderActionRemoteMsg",
+ "android.support.test.espresso.action.AdapterViewProtocol": "androidx.test.espresso.action.AdapterViewProtocol",
+ "android.support.test.espresso.action.AdapterViewProtocols": "androidx.test.espresso.action.AdapterViewProtocols",
+ "android.support.test.espresso.action.CloseKeyboardAction": "androidx.test.espresso.action.CloseKeyboardAction",
+ "android.support.test.espresso.action.CoordinatesProvider": "androidx.test.espresso.action.CoordinatesProvider",
+ "android.support.test.espresso.action.EditorAction": "androidx.test.espresso.action.EditorAction",
+ "android.support.test.espresso.action.EspressoKey": "androidx.test.espresso.action.EspressoKey",
+ "android.support.test.espresso.action.GeneralClickAction": "androidx.test.espresso.action.GeneralClickAction",
+ "android.support.test.espresso.action.GeneralClickActionRemoteMessage": "androidx.test.espresso.action.GeneralClickActionRemoteMessage",
+ "android.support.test.espresso.action.GeneralLocation": "androidx.test.espresso.action.GeneralLocation",
+ "android.support.test.espresso.action.GeneralLocationRemoteMessage": "androidx.test.espresso.action.GeneralLocationRemoteMessage",
+ "android.support.test.espresso.action.GeneralSwipeAction": "androidx.test.espresso.action.GeneralSwipeAction",
+ "android.support.test.espresso.action.GeneralSwipeActionRemoteMessage": "androidx.test.espresso.action.GeneralSwipeActionRemoteMessage",
+ "android.support.test.espresso.action.KeyEventAction": "androidx.test.espresso.action.KeyEventAction",
+ "android.support.test.espresso.action.KeyEventActionBase": "androidx.test.espresso.action.KeyEventActionBase",
+ "android.support.test.espresso.action.MotionEvents": "androidx.test.espresso.action.MotionEvents",
+ "android.support.test.espresso.action.OpenLinkAction": "androidx.test.espresso.action.OpenLinkAction",
+ "android.support.test.espresso.action.PrecisionDescriber": "androidx.test.espresso.action.PrecisionDescriber",
+ "android.support.test.espresso.action.Press": "androidx.test.espresso.action.Press",
+ "android.support.test.espresso.action.PressBackAction": "androidx.test.espresso.action.PressBackAction",
+ "android.support.test.espresso.action.PressRemoteMessage": "androidx.test.espresso.action.PressRemoteMessage",
+ "android.support.test.espresso.action.RemoteViewActions": "androidx.test.espresso.action.RemoteViewActions",
+ "android.support.test.espresso.action.RepeatActionUntilViewState": "androidx.test.espresso.action.RepeatActionUntilViewState",
+ "android.support.test.espresso.action.ReplaceTextAction": "androidx.test.espresso.action.ReplaceTextAction",
+ "android.support.test.espresso.action.ScrollToAction": "androidx.test.espresso.action.ScrollToAction",
+ "android.support.test.espresso.action.Swipe": "androidx.test.espresso.action.Swipe",
+ "android.support.test.espresso.action.Swiper": "androidx.test.espresso.action.Swiper",
+ "android.support.test.espresso.action.SwipeRemoteMessage": "androidx.test.espresso.action.SwipeRemoteMessage",
+ "android.support.test.espresso.action.Tap": "androidx.test.espresso.action.Tap",
+ "android.support.test.espresso.action.Tapper": "androidx.test.espresso.action.Tapper",
+ "android.support.test.espresso.action.TapRemoteMessage": "androidx.test.espresso.action.TapRemoteMessage",
+ "android.support.test.espresso.action.TranslatedCoordinatesProvider": "androidx.test.espresso.action.TranslatedCoordinatesProvider",
+ "android.support.test.espresso.action.TranslatedCoordinatesProviderRemoteMessage": "androidx.test.espresso.action.TranslatedCoordinatesProviderRemoteMessage",
+ "android.support.test.espresso.action.TypeTextAction": "androidx.test.espresso.action.TypeTextAction",
+ "android.support.test.espresso.action.ViewActions": "androidx.test.espresso.action.ViewActions",
+ "android.support.test.espresso.AmbiguousViewMatcherException": "androidx.test.espresso.AmbiguousViewMatcherException",
+ "android.support.test.espresso.AppNotIdleException": "androidx.test.espresso.AppNotIdleException",
+ "android.support.test.espresso.assertion.LayoutAssertions": "androidx.test.espresso.assertion.LayoutAssertions",
+ "android.support.test.espresso.assertion.PositionAssertions": "androidx.test.espresso.assertion.PositionAssertions",
+ "android.support.test.espresso.assertion.RemoteViewAssertions": "androidx.test.espresso.assertion.RemoteViewAssertions",
+ "android.support.test.espresso.assertion.ViewAssertions": "androidx.test.espresso.assertion.ViewAssertions",
+ "android.support.test.espresso.base.ActiveRootLister": "androidx.test.espresso.base.ActiveRootLister",
+ "android.support.test.espresso.base.AsyncTaskPoolMonitor": "androidx.test.espresso.base.AsyncTaskPoolMonitor",
+ "android.support.test.espresso.base.BaseLayerModule_FailureHandlerHolder_Factory": "androidx.test.espresso.base.BaseLayerModule_FailureHandlerHolder_Factory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideActiveRootListerFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideActiveRootListerFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideCompatAsyncTaskMonitorFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideCompatAsyncTaskMonitorFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideDynamicNotiferFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideDynamicNotiferFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideEventInjectorFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideEventInjectorFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideFailureHanderFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideFailureHanderFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideFailureHandlerFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideFailureHandlerFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideLifecycleMonitorFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideLifecycleMonitorFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideMainLooperFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideMainLooperFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideMainThreadExecutorFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideMainThreadExecutorFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideRemoteExecutorFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideRemoteExecutorFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideSdkAsyncTaskMonitorFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideSdkAsyncTaskMonitorFactory",
+ "android.support.test.espresso.base.BaseLayerModule_ProvideTargetContextFactory": "androidx.test.espresso.base.BaseLayerModule_ProvideTargetContextFactory",
+ "android.support.test.espresso.base.BaseLayerModule": "androidx.test.espresso.base.BaseLayerModule",
+ "android.support.test.espresso.base.CompatAsyncTask": "androidx.test.espresso.base.CompatAsyncTask",
+ "android.support.test.espresso.base.Default": "androidx.test.espresso.base.Default",
+ "android.support.test.espresso.base.DefaultFailureHandler": "androidx.test.espresso.base.DefaultFailureHandler",
+ "android.support.test.espresso.base.EventInjectionStrategy": "androidx.test.espresso.base.EventInjectionStrategy",
+ "android.support.test.espresso.base.EventInjector": "androidx.test.espresso.base.EventInjector",
+ "android.support.test.espresso.base.IdleNotifier": "androidx.test.espresso.base.IdleNotifier",
+ "android.support.test.espresso.base.IdlingResourceRegistry_Factory": "androidx.test.espresso.base.IdlingResourceRegistry_Factory",
+ "android.support.test.espresso.base.IdlingResourceRegistry": "androidx.test.espresso.base.IdlingResourceRegistry",
+ "android.support.test.espresso.base.IdlingUiController": "androidx.test.espresso.base.IdlingUiController",
+ "android.support.test.espresso.base.InputManagerEventInjectionStrategy": "androidx.test.espresso.base.InputManagerEventInjectionStrategy",
+ "android.support.test.espresso.base.Interrogator": "androidx.test.espresso.base.Interrogator",
+ "android.support.test.espresso.base.InterruptableUiController": "androidx.test.espresso.base.InterruptableUiController",
+ "android.support.test.espresso.base.LooperIdlingResourceInterrogationHandler": "androidx.test.espresso.base.LooperIdlingResourceInterrogationHandler",
+ "android.support.test.espresso.base.MainThread": "androidx.test.espresso.base.MainThread",
+ "android.support.test.espresso.base.NoopIdleNotificationCallbackIdleNotifierProvider": "androidx.test.espresso.base.NoopIdleNotificationCallbackIdleNotifierProvider",
+ "android.support.test.espresso.base.NoopRunnableIdleNotifier": "androidx.test.espresso.base.NoopRunnableIdleNotifier",
+ "android.support.test.espresso.base.RootsOracle_Factory": "androidx.test.espresso.base.RootsOracle_Factory",
+ "android.support.test.espresso.base.RootsOracle": "androidx.test.espresso.base.RootsOracle",
+ "android.support.test.espresso.base.RootViewPicker_Factory": "androidx.test.espresso.base.RootViewPicker_Factory",
+ "android.support.test.espresso.base.RootViewPicker_RootResultFetcher_Factory": "androidx.test.espresso.base.RootViewPicker_RootResultFetcher_Factory",
+ "android.support.test.espresso.base.RootViewPicker": "androidx.test.espresso.base.RootViewPicker",
+ "android.support.test.espresso.base.RootViewPickerScope": "androidx.test.espresso.base.RootViewPickerScope",
+ "android.support.test.espresso.base.SdkAsyncTask": "androidx.test.espresso.base.SdkAsyncTask",
+ "android.support.test.espresso.base.ThreadPoolExecutorExtractor_Factory": "androidx.test.espresso.base.ThreadPoolExecutorExtractor_Factory",
+ "android.support.test.espresso.base.ThreadPoolExecutorExtractor": "androidx.test.espresso.base.ThreadPoolExecutorExtractor",
+ "android.support.test.espresso.base.UiControllerImpl_Factory": "androidx.test.espresso.base.UiControllerImpl_Factory",
+ "android.support.test.espresso.base.UiControllerImpl": "androidx.test.espresso.base.UiControllerImpl",
+ "android.support.test.espresso.base.UiControllerModule": "androidx.test.espresso.base.UiControllerModule",
+ "android.support.test.espresso.base.ViewFinderImpl_Factory": "androidx.test.espresso.base.ViewFinderImpl_Factory",
+ "android.support.test.espresso.base.ViewFinderImpl": "androidx.test.espresso.base.ViewFinderImpl",
+ "android.support.test.espresso.base.WindowManagerEventInjectionStrategy": "androidx.test.espresso.base.WindowManagerEventInjectionStrategy",
+ "android.support.test.espresso.BaseLayerComponent": "androidx.test.espresso.BaseLayerComponent",
+ "android.support.test.espresso.contrib.AccessibilityChecks": "androidx.test.espresso.contrib.AccessibilityChecks",
+ "android.support.test.espresso.contrib.ActivityResultMatchers": "androidx.test.espresso.contrib.ActivityResultMatchers",
+ "android.support.test.espresso.contrib.Checks": "androidx.test.espresso.contrib.Checks",
+ "android.support.test.espresso.contrib.DrawerActions": "androidx.test.espresso.contrib.DrawerActions",
+ "android.support.test.espresso.contrib.DrawerMatchers": "androidx.test.espresso.contrib.DrawerMatchers",
+ "android.support.test.espresso.contrib.NavigationViewActions": "androidx.test.espresso.contrib.NavigationViewActions",
+ "android.support.test.espresso.contrib.PickerActions": "androidx.test.espresso.contrib.PickerActions",
+ "android.support.test.espresso.contrib.RecyclerViewActions": "androidx.test.espresso.contrib.RecyclerViewActions",
+ "android.support.test.espresso.contrib.ViewPagerActions": "androidx.test.espresso.contrib.ViewPagerActions",
+ "android.support.test.espresso.DaggerBaseLayerComponent": "androidx.test.espresso.DaggerBaseLayerComponent",
+ "android.support.test.espresso.DataInteraction": "androidx.test.espresso.DataInteraction",
+ "android.support.test.espresso.DataInteractionRemote": "androidx.test.espresso.DataInteractionRemote",
+ "android.support.test.espresso.Espresso": "androidx.test.espresso.Espresso",
+ "android.support.test.espresso.EspressoException": "androidx.test.espresso.EspressoException",
+ "android.support.test.espresso.FailureHandler": "androidx.test.espresso.FailureHandler",
+ "android.support.test.espresso.GraphHolder": "androidx.test.espresso.GraphHolder",
+ "android.support.test.espresso.idling.concurrent.IdlingScheduledThreadPoolExecutor": "androidx.test.espresso.idling.concurrent.IdlingScheduledThreadPoolExecutor",
+ "android.support.test.espresso.idling.concurrent.IdlingThreadPoolExecutor": "androidx.test.espresso.idling.concurrent.IdlingThreadPoolExecutor",
+ "android.support.test.espresso.idling.CountingIdlingResource": "androidx.test.espresso.idling.CountingIdlingResource",
+ "android.support.test.espresso.idling.net.UriIdlingResource": "androidx.test.espresso.idling.net.UriIdlingResource",
+ "android.support.test.espresso.IdlingPolicies": "androidx.test.espresso.IdlingPolicies",
+ "android.support.test.espresso.IdlingPolicy": "androidx.test.espresso.IdlingPolicy",
+ "android.support.test.espresso.IdlingRegistry": "androidx.test.espresso.IdlingRegistry",
+ "android.support.test.espresso.IdlingResource": "androidx.test.espresso.IdlingResource",
+ "android.support.test.espresso.IdlingResourceTimeoutException": "androidx.test.espresso.IdlingResourceTimeoutException",
+ "android.support.test.espresso.InjectEventSecurityException": "androidx.test.espresso.InjectEventSecurityException",
+ "android.support.test.espresso.intent.ActivityResultFunction": "androidx.test.espresso.intent.ActivityResultFunction",
+ "android.support.test.espresso.intent.Checks": "androidx.test.espresso.intent.Checks",
+ "android.support.test.espresso.intent.Intents": "androidx.test.espresso.intent.Intents",
+ "android.support.test.espresso.intent.matcher.BundleMatchers": "androidx.test.espresso.intent.matcher.BundleMatchers",
+ "android.support.test.espresso.intent.matcher.ComponentNameMatchers": "androidx.test.espresso.intent.matcher.ComponentNameMatchers",
+ "android.support.test.espresso.intent.matcher.IntentMatchers": "androidx.test.espresso.intent.matcher.IntentMatchers",
+ "android.support.test.espresso.intent.matcher.UriMatchers": "androidx.test.espresso.intent.matcher.UriMatchers",
+ "android.support.test.espresso.intent.OngoingStubbing": "androidx.test.espresso.intent.OngoingStubbing",
+ "android.support.test.espresso.intent.ResettingStubber": "androidx.test.espresso.intent.ResettingStubber",
+ "android.support.test.espresso.intent.ResettingStubberImpl": "androidx.test.espresso.intent.ResettingStubberImpl",
+ "android.support.test.espresso.intent.ResolvedIntent": "androidx.test.espresso.intent.ResolvedIntent",
+ "android.support.test.espresso.intent.ResolvedIntentImpl": "androidx.test.espresso.intent.ResolvedIntentImpl",
+ "android.support.test.espresso.intent.rule.IntentsTestRule": "androidx.test.espresso.intent.rule.IntentsTestRule",
+ "android.support.test.espresso.intent.VerifiableIntent": "androidx.test.espresso.intent.VerifiableIntent",
+ "android.support.test.espresso.intent.VerifiableIntentImpl": "androidx.test.espresso.intent.VerifiableIntentImpl",
+ "android.support.test.espresso.intent.VerificationMode": "androidx.test.espresso.intent.VerificationMode",
+ "android.support.test.espresso.intent.VerificationModes": "androidx.test.espresso.intent.VerificationModes",
+ "android.support.test.espresso.InteractionResultsHandler": "androidx.test.espresso.InteractionResultsHandler",
+ "android.support.test.espresso.matcher.BoundedMatcher": "androidx.test.espresso.matcher.BoundedMatcher",
+ "android.support.test.espresso.matcher.CursorMatchers": "androidx.test.espresso.matcher.CursorMatchers",
+ "android.support.test.espresso.matcher.HasBackgroundMatcher": "androidx.test.espresso.matcher.HasBackgroundMatcher",
+ "android.support.test.espresso.matcher.LayoutMatchers": "androidx.test.espresso.matcher.LayoutMatchers",
+ "android.support.test.espresso.matcher.PreferenceMatchers": "androidx.test.espresso.matcher.PreferenceMatchers",
+ "android.support.test.espresso.matcher.RemoteHamcrestCoreMatchers13": "androidx.test.espresso.matcher.RemoteHamcrestCoreMatchers13",
+ "android.support.test.espresso.matcher.RemoteRootMatchers": "androidx.test.espresso.matcher.RemoteRootMatchers",
+ "android.support.test.espresso.matcher.RemoteViewMatchers": "androidx.test.espresso.matcher.RemoteViewMatchers",
+ "android.support.test.espresso.matcher.RootMatchers": "androidx.test.espresso.matcher.RootMatchers",
+ "android.support.test.espresso.matcher.ViewMatchers": "androidx.test.espresso.matcher.ViewMatchers",
+ "android.support.test.espresso.NoActivityResumedException": "androidx.test.espresso.NoActivityResumedException",
+ "android.support.test.espresso.NoMatchingRootException": "androidx.test.espresso.NoMatchingRootException",
+ "android.support.test.espresso.NoMatchingViewException": "androidx.test.espresso.NoMatchingViewException",
+ "android.support.test.espresso.PerformException": "androidx.test.espresso.PerformException",
+ "android.support.test.espresso.proto.action.ViewActions": "androidx.test.espresso.proto.action.ViewActions",
+ "android.support.test.espresso.proto.assertion.ViewAssertions": "androidx.test.espresso.proto.assertion.ViewAssertions",
+ "android.support.test.espresso.proto.matcher.RootMatchers": "androidx.test.espresso.proto.matcher.RootMatchers",
+ "android.support.test.espresso.proto.matcher.ViewMatchers": "androidx.test.espresso.proto.matcher.ViewMatchers",
+ "android.support.test.espresso.proto.matcher13.HamcrestMatchersv13": "androidx.test.espresso.proto.matcher13.HamcrestMatchersv13",
+ "android.support.test.espresso.proto.UiInteraction": "androidx.test.espresso.proto.UiInteraction",
+ "android.support.test.espresso.remote.annotation.RemoteMsgConstructor": "androidx.test.espresso.remote.annotation.RemoteMsgConstructor",
+ "android.support.test.espresso.remote.annotation.RemoteMsgField": "androidx.test.espresso.remote.annotation.RemoteMsgField",
+ "android.support.test.espresso.remote.AnyToTypeConverter": "androidx.test.espresso.remote.AnyToTypeConverter",
+ "android.support.test.espresso.remote.Bindable": "androidx.test.espresso.remote.Bindable",
+ "android.support.test.espresso.remote.BuilderReflector": "androidx.test.espresso.remote.BuilderReflector",
+ "android.support.test.espresso.remote.ByteStringToParcelableConverter": "androidx.test.espresso.remote.ByteStringToParcelableConverter",
+ "android.support.test.espresso.remote.ByteStringToTypeConverter": "androidx.test.espresso.remote.ByteStringToTypeConverter",
+ "android.support.test.espresso.remote.ConstructorInvocation": "androidx.test.espresso.remote.ConstructorInvocation",
+ "android.support.test.espresso.remote.Converter": "androidx.test.espresso.remote.Converter",
+ "android.support.test.espresso.remote.EspressoRemote": "androidx.test.espresso.remote.EspressoRemote",
+ "android.support.test.espresso.remote.EspressoRemoteMessage": "androidx.test.espresso.remote.EspressoRemoteMessage",
+ "android.support.test.espresso.remote.FieldDescriptor": "androidx.test.espresso.remote.FieldDescriptor",
+ "android.support.test.espresso.remote.GenericRemoteMessage": "androidx.test.espresso.remote.GenericRemoteMessage",
+ "android.support.test.espresso.remote.IInteractionExecutionStatus": "androidx.test.espresso.remote.IInteractionExecutionStatus",
+ "android.support.test.espresso.remote.InteractionRequest": "androidx.test.espresso.remote.InteractionRequest",
+ "android.support.test.espresso.remote.InteractionResponse": "androidx.test.espresso.remote.InteractionResponse",
+ "android.support.test.espresso.remote.MethodInvocation": "androidx.test.espresso.remote.MethodInvocation",
+ "android.support.test.espresso.remote.NoopRemoteInteraction": "androidx.test.espresso.remote.NoopRemoteInteraction",
+ "android.support.test.espresso.remote.NoRemoteEspressoInstanceException": "androidx.test.espresso.remote.NoRemoteEspressoInstanceException",
+ "android.support.test.espresso.remote.ParcelableToByteStringConverter": "androidx.test.espresso.remote.ParcelableToByteStringConverter",
+ "android.support.test.espresso.remote.ProtoReflector": "androidx.test.espresso.remote.ProtoReflector",
+ "android.support.test.espresso.remote.ProtoUtils": "androidx.test.espresso.remote.ProtoUtils",
+ "android.support.test.espresso.remote.RemoteDescriptor": "androidx.test.espresso.remote.RemoteDescriptor",
+ "android.support.test.espresso.remote.RemoteDescriptorRegistry": "androidx.test.espresso.remote.RemoteDescriptorRegistry",
+ "android.support.test.espresso.remote.RemoteEspressoException": "androidx.test.espresso.remote.RemoteEspressoException",
+ "android.support.test.espresso.remote.RemoteInteraction": "androidx.test.espresso.remote.RemoteInteraction",
+ "android.support.test.espresso.remote.RemoteInteractionRegistry": "androidx.test.espresso.remote.RemoteInteractionRegistry",
+ "android.support.test.espresso.remote.RemoteMessageDeserializer": "androidx.test.espresso.remote.RemoteMessageDeserializer",
+ "android.support.test.espresso.remote.RemoteMessageSerializer": "androidx.test.espresso.remote.RemoteMessageSerializer",
+ "android.support.test.espresso.remote.RemoteProtocolException": "androidx.test.espresso.remote.RemoteProtocolException",
+ "android.support.test.espresso.remote.TypeProtoConverters": "androidx.test.espresso.remote.TypeProtoConverters",
+ "android.support.test.espresso.remote.TypeToAnyConverter": "androidx.test.espresso.remote.TypeToAnyConverter",
+ "android.support.test.espresso.remote.TypeToByteStringConverter": "androidx.test.espresso.remote.TypeToByteStringConverter",
+ "android.support.test.espresso.Root": "androidx.test.espresso.Root",
+ "android.support.test.espresso.UiController": "androidx.test.espresso.UiController",
+ "android.support.test.espresso.util.ActivityLifecycles": "androidx.test.espresso.util.ActivityLifecycles",
+ "android.support.test.espresso.util.EspressoOptional": "androidx.test.espresso.util.EspressoOptional",
+ "android.support.test.espresso.util.HumanReadables": "androidx.test.espresso.util.HumanReadables",
+ "android.support.test.espresso.util.TreeIterables": "androidx.test.espresso.util.TreeIterables",
+ "android.support.test.espresso.ViewAction": "androidx.test.espresso.ViewAction",
+ "android.support.test.espresso.ViewAssertion": "androidx.test.espresso.ViewAssertion",
+ "android.support.test.espresso.ViewFinder": "androidx.test.espresso.ViewFinder",
+ "android.support.test.espresso.ViewInteraction_Factory": "androidx.test.espresso.ViewInteraction_Factory",
+ "android.support.test.espresso.ViewInteraction": "androidx.test.espresso.ViewInteraction",
+ "android.support.test.espresso.ViewInteractionComponent": "androidx.test.espresso.ViewInteractionComponent",
+ "android.support.test.espresso.ViewInteractionModule_ProvideNeedsActivityFactory": "androidx.test.espresso.ViewInteractionModule_ProvideNeedsActivityFactory",
+ "android.support.test.espresso.ViewInteractionModule_ProvideRemoteInteractionFactory": "androidx.test.espresso.ViewInteractionModule_ProvideRemoteInteractionFactory",
+ "android.support.test.espresso.ViewInteractionModule_ProvideRootMatcherFactory": "androidx.test.espresso.ViewInteractionModule_ProvideRootMatcherFactory",
+ "android.support.test.espresso.ViewInteractionModule_ProvideRootViewFactory": "androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory",
+ "android.support.test.espresso.ViewInteractionModule_ProvideViewFinderFactory": "androidx.test.espresso.ViewInteractionModule_ProvideViewFinderFactory",
+ "android.support.test.espresso.ViewInteractionModule_ProvideViewMatcherFactory": "androidx.test.espresso.ViewInteractionModule_ProvideViewMatcherFactory",
+ "android.support.test.espresso.ViewInteractionModule": "androidx.test.espresso.ViewInteractionModule",
+ "android.support.test.espresso.web.action.AtomAction": "androidx.test.espresso.web.action.AtomAction",
+ "android.support.test.espresso.web.action.AtomActionRemoteMessage": "androidx.test.espresso.web.action.AtomActionRemoteMessage",
+ "android.support.test.espresso.web.action.EnableJavascriptAction": "androidx.test.espresso.web.action.EnableJavascriptAction",
+ "android.support.test.espresso.web.action.EvaluationAtom": "androidx.test.espresso.web.action.EvaluationAtom",
+ "android.support.test.espresso.web.action.IAtomActionResultPropagator": "androidx.test.espresso.web.action.IAtomActionResultPropagator",
+ "android.support.test.espresso.web.action.JavascriptEvaluation": "androidx.test.espresso.web.action.JavascriptEvaluation",
+ "android.support.test.espresso.web.action.RemoteWebActions": "androidx.test.espresso.web.action.RemoteWebActions",
+ "android.support.test.espresso.web.assertion.ByteStringToDocumentConverter": "androidx.test.espresso.web.assertion.ByteStringToDocumentConverter",
+ "android.support.test.espresso.web.assertion.CheckResultWebAssertionRemoteMessage": "androidx.test.espresso.web.assertion.CheckResultWebAssertionRemoteMessage",
+ "android.support.test.espresso.web.assertion.CompressorDecompressor": "androidx.test.espresso.web.assertion.CompressorDecompressor",
+ "android.support.test.espresso.web.assertion.DocumentProtoConverters": "androidx.test.espresso.web.assertion.DocumentProtoConverters",
+ "android.support.test.espresso.web.assertion.DocumentToByteStringConverter": "androidx.test.espresso.web.assertion.DocumentToByteStringConverter",
+ "android.support.test.espresso.web.assertion.RemoteWebViewAssertions": "androidx.test.espresso.web.assertion.RemoteWebViewAssertions",
+ "android.support.test.espresso.web.assertion.TagSoupDocumentParser": "androidx.test.espresso.web.assertion.TagSoupDocumentParser",
+ "android.support.test.espresso.web.assertion.WebAssertion": "androidx.test.espresso.web.assertion.WebAssertion",
+ "android.support.test.espresso.web.assertion.WebViewAssertions": "androidx.test.espresso.web.assertion.WebViewAssertions",
+ "android.support.test.espresso.web.matcher.AmbiguousElementMatcherException": "androidx.test.espresso.web.matcher.AmbiguousElementMatcherException",
+ "android.support.test.espresso.web.matcher.DomMatchers": "androidx.test.espresso.web.matcher.DomMatchers",
+ "android.support.test.espresso.web.matcher.RemoteWebMatchers": "androidx.test.espresso.web.matcher.RemoteWebMatchers",
+ "android.support.test.espresso.web.model.Atom": "androidx.test.espresso.web.model.Atom",
+ "android.support.test.espresso.web.model.Atoms": "androidx.test.espresso.web.model.Atoms",
+ "android.support.test.espresso.web.model.ElementReference": "androidx.test.espresso.web.model.ElementReference",
+ "android.support.test.espresso.web.model.Evaluation": "androidx.test.espresso.web.model.Evaluation",
+ "android.support.test.espresso.web.model.JSONAble": "androidx.test.espresso.web.model.JSONAble",
+ "android.support.test.espresso.web.model.ModelCodec": "androidx.test.espresso.web.model.ModelCodec",
+ "android.support.test.espresso.web.model.RemoteWebModelAtoms": "androidx.test.espresso.web.model.RemoteWebModelAtoms",
+ "android.support.test.espresso.web.model.ScriptWithArgsSimpleAtomRemoteMessage": "androidx.test.espresso.web.model.ScriptWithArgsSimpleAtomRemoteMessage",
+ "android.support.test.espresso.web.model.SimpleAtom": "androidx.test.espresso.web.model.SimpleAtom",
+ "android.support.test.espresso.web.model.TransformingAtom": "androidx.test.espresso.web.model.TransformingAtom",
+ "android.support.test.espresso.web.model.WindowReference": "androidx.test.espresso.web.model.WindowReference",
+ "android.support.test.espresso.web.proto.action.WebActions": "androidx.test.espresso.web.proto.action.WebActions",
+ "android.support.test.espresso.web.proto.assertion.WebAssertions": "androidx.test.espresso.web.proto.assertion.WebAssertions",
+ "android.support.test.espresso.web.proto.matcher.RemoteWebMatchers": "androidx.test.espresso.web.proto.matcher.RemoteWebMatchers",
+ "android.support.test.espresso.web.proto.model.WebModelAtoms": "androidx.test.espresso.web.proto.model.WebModelAtoms",
+ "android.support.test.espresso.web.proto.sugar.WebSugar": "androidx.test.espresso.web.proto.sugar.WebSugar",
+ "android.support.test.espresso.web.proto.webdriver.WebWebdriverAtoms": "androidx.test.espresso.web.proto.webdriver.WebWebdriverAtoms",
+ "android.support.test.espresso.web.sugar.RemoteWebSugar": "androidx.test.espresso.web.sugar.RemoteWebSugar",
+ "android.support.test.espresso.web.sugar.Web": "androidx.test.espresso.web.sugar.Web",
+ "android.support.test.espresso.web.webdriver.DriverAtoms": "androidx.test.espresso.web.webdriver.DriverAtoms",
+ "android.support.test.espresso.web.webdriver.Locator": "androidx.test.espresso.web.webdriver.Locator",
+ "android.support.test.espresso.web.webdriver.RemoteWebDriverAtoms": "androidx.test.espresso.web.webdriver.RemoteWebDriverAtoms",
+ "android.support.test.espresso.web.webdriver.WebDriverAtomScripts": "androidx.test.espresso.web.webdriver.WebDriverAtomScripts",
+ "android.support.test.filters.FlakyTest": "androidx.test.filters.FlakyTest",
+ "android.support.test.filters.LargeTest": "androidx.test.filters.LargeTest",
+ "android.support.test.filters.MediumTest": "androidx.test.filters.MediumTest",
+ "android.support.test.filters.RequiresDevice": "androidx.test.filters.RequiresDevice",
+ "android.support.test.filters.SdkSuppress": "androidx.test.filters.SdkSuppress",
+ "android.support.test.filters.SmallTest": "androidx.test.filters.SmallTest",
+ "android.support.test.filters.Suppress": "androidx.test.filters.Suppress",
+ "android.support.test.InstrumentationRegistry": "androidx.test.InstrumentationRegistry",
+ "android.support.test.jank.GfxMonitor": "androidx.test.jank.GfxMonitor",
+ "android.support.test.jank.JankTest": "androidx.test.jank.JankTest",
+ "android.support.test.jank.JankTestBase": "androidx.test.jank.JankTestBase",
+ "android.support.test.jank.WindowAnimationFrameStatsMonitor": "androidx.test.jank.WindowAnimationFrameStatsMonitor",
+ "android.support.test.jank.WindowContentFrameStatsMonitor": "androidx.test.jank.WindowContentFrameStatsMonitor",
+ "android.support.test.orchestrator.callback.OrchestratorCallback": "androidx.test.orchestrator.callback.OrchestratorCallback",
+ "android.support.test.orchestrator.instrumentationlistener.OrchestratedInstrumentationListener": "androidx.test.orchestrator.instrumentationlistener.OrchestratedInstrumentationListener",
+ "android.support.test.orchestrator.junit.BundleJUnitUtils": "androidx.test.orchestrator.junit.BundleJUnitUtils",
+ "android.support.test.orchestrator.junit.ParcelableDescription": "androidx.test.orchestrator.junit.ParcelableDescription",
+ "android.support.test.orchestrator.junit.ParcelableFailure": "androidx.test.orchestrator.junit.ParcelableFailure",
+ "android.support.test.orchestrator.junit.ParcelableResult": "androidx.test.orchestrator.junit.ParcelableResult",
+ "android.support.test.orchestrator.listeners.OrchestrationListenerManager": "androidx.test.orchestrator.listeners.OrchestrationListenerManager",
+ "android.support.test.orchestrator.listeners.OrchestrationRunListener": "androidx.test.orchestrator.listeners.OrchestrationRunListener",
+ "android.support.test.orchestrator.listeners.result.ITestRunListener": "androidx.test.orchestrator.listeners.result.ITestRunListener",
+ "android.support.test.orchestrator.listeners.result.TestIdentifier": "androidx.test.orchestrator.listeners.result.TestIdentifier",
+ "android.support.test.orchestrator.listeners.result.TestResult": "androidx.test.orchestrator.listeners.result.TestResult",
+ "android.support.test.orchestrator.listeners.result.TestRunResult": "androidx.test.orchestrator.listeners.result.TestRunResult",
+ "android.support.test.rule.ActivityTestRule": "androidx.test.rule.ActivityTestRule",
+ "android.support.test.rule.DisableOnAndroidDebug": "androidx.test.rule.DisableOnAndroidDebug",
+ "android.support.test.rule.GrantPermissionRule": "androidx.test.rule.GrantPermissionRule",
+ "android.support.test.rule.logging.AtraceLogger": "androidx.test.rule.logging.AtraceLogger",
+ "android.support.test.rule.PortForwardingRule": "androidx.test.rule.PortForwardingRule",
+ "android.support.test.rule.provider.DatabaseArgs": "androidx.test.rule.provider.DatabaseArgs",
+ "android.support.test.rule.provider.DelegatingContext": "androidx.test.rule.provider.DelegatingContext",
+ "android.support.test.rule.provider.ProviderArgs": "androidx.test.rule.provider.ProviderArgs",
+ "android.support.test.rule.provider.ProviderTestRule": "androidx.test.rule.provider.ProviderTestRule",
+ "android.support.test.rule.ServiceTestRule": "androidx.test.rule.ServiceTestRule",
+ "android.support.test.rule.UiThreadTestRule": "androidx.test.rule.UiThreadTestRule",
+ "android.support.test.runner.AndroidJUnit4": "androidx.test.runner.AndroidJUnit4",
+ "android.support.test.runner.AndroidJUnitRunner": "androidx.test.runner.AndroidJUnitRunner",
+ "android.support.test.runner.intent.IntentCallback": "androidx.test.runner.intent.IntentCallback",
+ "android.support.test.runner.intent.IntentMonitor": "androidx.test.runner.intent.IntentMonitor",
+ "android.support.test.runner.intent.IntentMonitorRegistry": "androidx.test.runner.intent.IntentMonitorRegistry",
+ "android.support.test.runner.intent.IntentStubber": "androidx.test.runner.intent.IntentStubber",
+ "android.support.test.runner.intent.IntentStubberRegistry": "androidx.test.runner.intent.IntentStubberRegistry",
+ "android.support.test.runner.intercepting.InterceptingActivityFactory": "androidx.test.runner.intercepting.InterceptingActivityFactory",
+ "android.support.test.runner.intercepting.SingleActivityFactory": "androidx.test.runner.intercepting.SingleActivityFactory",
+ "android.support.test.runner.lifecycle.ActivityLifecycleCallback": "androidx.test.runner.lifecycle.ActivityLifecycleCallback",
+ "android.support.test.runner.lifecycle.ActivityLifecycleMonitor": "androidx.test.runner.lifecycle.ActivityLifecycleMonitor",
+ "android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry": "androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry",
+ "android.support.test.runner.lifecycle.ApplicationLifecycleCallback": "androidx.test.runner.lifecycle.ApplicationLifecycleCallback",
+ "android.support.test.runner.lifecycle.ApplicationLifecycleMonitor": "androidx.test.runner.lifecycle.ApplicationLifecycleMonitor",
+ "android.support.test.runner.lifecycle.ApplicationLifecycleMonitorRegistry": "androidx.test.runner.lifecycle.ApplicationLifecycleMonitorRegistry",
+ "android.support.test.runner.lifecycle.ApplicationStage": "androidx.test.runner.lifecycle.ApplicationStage",
+ "android.support.test.runner.lifecycle.Stage": "androidx.test.runner.lifecycle.Stage",
+ "android.support.test.runner.MonitoringInstrumentation": "androidx.test.runner.MonitoringInstrumentation",
+ "android.support.test.runner.permission.GrantPermissionCallable": "androidx.test.runner.permission.GrantPermissionCallable",
+ "android.support.test.runner.permission.PermissionRequester": "androidx.test.runner.permission.PermissionRequester",
+ "android.support.test.runner.permission.RequestPermissionCallable": "androidx.test.runner.permission.RequestPermissionCallable",
+ "android.support.test.runner.permission.ShellCommand": "androidx.test.runner.permission.ShellCommand",
+ "android.support.test.runner.permission.UiAutomationShellCommand": "androidx.test.runner.permission.UiAutomationShellCommand",
+ "android.support.test.runner.screenshot.BasicScreenCaptureProcessor": "androidx.test.runner.screenshot.BasicScreenCaptureProcessor",
+ "android.support.test.runner.screenshot.ScreenCapture": "androidx.test.runner.screenshot.ScreenCapture",
+ "android.support.test.runner.screenshot.ScreenCaptureProcessor": "androidx.test.runner.screenshot.ScreenCaptureProcessor",
+ "android.support.test.runner.screenshot.Screenshot": "androidx.test.runner.screenshot.Screenshot",
+ "android.support.test.runner.screenshot.TakeScreenshotCallable": "androidx.test.runner.screenshot.TakeScreenshotCallable",
+ "android.support.test.runner.screenshot.UiAutomationWrapper": "androidx.test.runner.screenshot.UiAutomationWrapper",
+ "android.support.test.runner.UsageTrackerFacilitator": "androidx.test.runner.UsageTrackerFacilitator",
+ "android.support.test.uiautomator.AccessibilityNodeInfoDumper": "androidx.test.uiautomator.AccessibilityNodeInfoDumper",
+ "android.support.test.uiautomator.AccessibilityNodeInfoHelper": "androidx.test.uiautomator.AccessibilityNodeInfoHelper",
+ "android.support.test.uiautomator.By": "androidx.test.uiautomator.By",
+ "android.support.test.uiautomator.ByMatcher": "androidx.test.uiautomator.ByMatcher",
+ "android.support.test.uiautomator.BySelector": "androidx.test.uiautomator.BySelector",
+ "android.support.test.uiautomator.Condition": "androidx.test.uiautomator.Condition",
+ "android.support.test.uiautomator.Configurator": "androidx.test.uiautomator.Configurator",
+ "android.support.test.uiautomator.Direction": "androidx.test.uiautomator.Direction",
+ "android.support.test.uiautomator.EventCondition": "androidx.test.uiautomator.EventCondition",
+ "android.support.test.uiautomator.GestureController": "androidx.test.uiautomator.GestureController",
+ "android.support.test.uiautomator.Gestures": "androidx.test.uiautomator.Gestures",
+ "android.support.test.uiautomator.IAutomationSupport": "androidx.test.uiautomator.IAutomationSupport",
+ "android.support.test.uiautomator.InstrumentationAutomationSupport": "androidx.test.uiautomator.InstrumentationAutomationSupport",
+ "android.support.test.uiautomator.InteractionController": "androidx.test.uiautomator.InteractionController",
+ "android.support.test.uiautomator.PointerGesture": "androidx.test.uiautomator.PointerGesture",
+ "android.support.test.uiautomator.QueryController": "androidx.test.uiautomator.QueryController",
+ "android.support.test.uiautomator.Searchable": "androidx.test.uiautomator.Searchable",
+ "android.support.test.uiautomator.SearchCondition": "androidx.test.uiautomator.SearchCondition",
+ "android.support.test.uiautomator.StaleObjectException": "androidx.test.uiautomator.StaleObjectException",
+ "android.support.test.uiautomator.Tracer": "androidx.test.uiautomator.Tracer",
+ "android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner": "androidx.test.uiautomator.UiAutomatorInstrumentationTestRunner",
+ "android.support.test.uiautomator.UiAutomatorTestCase": "androidx.test.uiautomator.UiAutomatorTestCase",
+ "android.support.test.uiautomator.UiCollection": "androidx.test.uiautomator.UiCollection",
+ "android.support.test.uiautomator.UiDevice": "androidx.test.uiautomator.UiDevice",
+ "android.support.test.uiautomator.UiObject2": "androidx.test.uiautomator.UiObject2",
+ "android.support.test.uiautomator.UiObject2Condition": "androidx.test.uiautomator.UiObject2Condition",
+ "android.support.test.uiautomator.UiObject": "androidx.test.uiautomator.UiObject",
+ "android.support.test.uiautomator.UiObjectNotFoundException": "androidx.test.uiautomator.UiObjectNotFoundException",
+ "android.support.test.uiautomator.UiScrollable": "androidx.test.uiautomator.UiScrollable",
+ "android.support.test.uiautomator.UiSelector": "androidx.test.uiautomator.UiSelector",
+ "android.support.test.uiautomator.UiWatcher": "androidx.test.uiautomator.UiWatcher",
+ "android.support.test.uiautomator.Until": "androidx.test.uiautomator.Until",
+ "android.support.test.uiautomator.WaitMixin": "androidx.test.uiautomator.WaitMixin",
+ "android.support.text.emoji.bundled.BundledEmojiCompatConfig": "androidx.emoji.bundled.BundledEmojiCompatConfig",
+ "android.support.text.emoji.EmojiCompat": "androidx.emoji.text.EmojiCompat",
+ "android.support.text.emoji.EmojiMetadata": "androidx.emoji.text.EmojiMetadata",
+ "android.support.text.emoji.EmojiProcessor": "androidx.emoji.text.EmojiProcessor",
+ "android.support.text.emoji.EmojiSpan": "androidx.emoji.text.EmojiSpan",
+ "android.support.text.emoji.FontRequestEmojiCompatConfig": "androidx.emoji.text.FontRequestEmojiCompatConfig",
+ "android.support.text.emoji.MetadataListReader": "androidx.emoji.text.MetadataListReader",
+ "android.support.text.emoji.MetadataRepo": "androidx.emoji.text.MetadataRepo",
+ "android.support.text.emoji.R": "androidx.emoji.R",
+ "android.support.text.emoji.TypefaceEmojiSpan": "androidx.emoji.text.TypefaceEmojiSpan",
+ "android.support.text.emoji.widget.EditTextAttributeHelper": "androidx.emoji.widget.EditTextAttributeHelper",
+ "android.support.text.emoji.widget.EmojiAppCompatButton": "androidx.emoji.widget.EmojiAppCompatButton",
+ "android.support.text.emoji.widget.EmojiAppCompatEditText": "androidx.emoji.widget.EmojiAppCompatEditText",
+ "android.support.text.emoji.widget.EmojiAppCompatTextView": "androidx.emoji.widget.EmojiAppCompatTextView",
+ "android.support.text.emoji.widget.EmojiButton": "androidx.emoji.widget.EmojiButton",
+ "android.support.text.emoji.widget.EmojiEditableFactory": "androidx.emoji.widget.EmojiEditableFactory",
+ "android.support.text.emoji.widget.EmojiEditText": "androidx.emoji.widget.EmojiEditText",
+ "android.support.text.emoji.widget.EmojiEditTextHelper": "androidx.emoji.widget.EmojiEditTextHelper",
+ "android.support.text.emoji.widget.EmojiExtractEditText": "androidx.emoji.widget.EmojiExtractEditText",
+ "android.support.text.emoji.widget.EmojiExtractTextLayout": "androidx.emoji.widget.EmojiExtractTextLayout",
+ "android.support.text.emoji.widget.EmojiInputConnection": "androidx.emoji.widget.EmojiInputConnection",
+ "android.support.text.emoji.widget.EmojiInputFilter": "androidx.emoji.widget.EmojiInputFilter",
+ "android.support.text.emoji.widget.EmojiKeyListener": "androidx.emoji.widget.EmojiKeyListener",
+ "android.support.text.emoji.widget.EmojiTextView": "androidx.emoji.widget.EmojiTextView",
+ "android.support.text.emoji.widget.EmojiTextViewHelper": "androidx.emoji.widget.EmojiTextViewHelper",
+ "android.support.text.emoji.widget.EmojiTextWatcher": "androidx.emoji.widget.EmojiTextWatcher",
+ "android.support.text.emoji.widget.EmojiTransformationMethod": "androidx.emoji.widget.EmojiTransformationMethod",
+ "android.support.text.emoji.widget.ExtractButtonCompat": "androidx.emoji.widget.ExtractButtonCompat",
+ "android.support.text.emoji.widget.SpannableBuilder": "androidx.emoji.widget.SpannableBuilder",
+ "android.support.transition.AnimatorUtils": "androidx.transition.AnimatorUtils",
+ "android.support.transition.ArcMotion": "androidx.transition.ArcMotion",
+ "android.support.transition.AutoTransition": "androidx.transition.AutoTransition",
+ "android.support.transition.ChangeBounds": "androidx.transition.ChangeBounds",
+ "android.support.transition.ChangeClipBounds": "androidx.transition.ChangeClipBounds",
+ "android.support.transition.ChangeImageTransform": "androidx.transition.ChangeImageTransform",
+ "android.support.transition.ChangeScroll": "androidx.transition.ChangeScroll",
+ "android.support.transition.ChangeTransform": "androidx.transition.ChangeTransform",
+ "android.support.transition.CircularPropagation": "androidx.transition.CircularPropagation",
+ "android.support.transition.Explode": "androidx.transition.Explode",
+ "android.support.transition.Fade": "androidx.transition.Fade",
+ "android.support.transition.FloatArrayEvaluator": "androidx.transition.FloatArrayEvaluator",
+ "android.support.transition.FragmentTransitionSupport": "androidx.transition.FragmentTransitionSupport",
+ "android.support.transition.GhostViewApi14": "androidx.transition.GhostViewApi14",
+ "android.support.transition.GhostViewApi21": "androidx.transition.GhostViewApi21",
+ "android.support.transition.GhostViewImpl": "androidx.transition.GhostViewImpl",
+ "android.support.transition.GhostViewUtils": "androidx.transition.GhostViewUtils",
+ "android.support.transition.ImageViewUtils": "androidx.transition.ImageViewUtils",
+ "android.support.transition.MatrixUtils": "androidx.transition.MatrixUtils",
+ "android.support.transition.ObjectAnimatorUtils": "androidx.transition.ObjectAnimatorUtils",
+ "android.support.transition.PathMotion": "androidx.transition.PathMotion",
+ "android.support.transition.PathProperty": "androidx.transition.PathProperty",
+ "android.support.transition.PatternPathMotion": "androidx.transition.PatternPathMotion",
+ "android.support.transition.PropertyValuesHolderUtils": "androidx.transition.PropertyValuesHolderUtils",
+ "android.support.transition.R": "androidx.transition.R",
+ "android.support.transition.RectEvaluator": "androidx.transition.RectEvaluator",
+ "android.support.transition.Scene": "androidx.transition.Scene",
+ "android.support.transition.SidePropagation": "androidx.transition.SidePropagation",
+ "android.support.transition.Slide": "androidx.transition.Slide",
+ "android.support.transition.Styleable": "androidx.transition.Styleable",
+ "android.support.transition.Transition": "androidx.transition.Transition",
+ "android.support.transition.TransitionInflater": "androidx.transition.TransitionInflater",
+ "android.support.transition.TransitionListenerAdapter": "androidx.transition.TransitionListenerAdapter",
+ "android.support.transition.TransitionManager": "androidx.transition.TransitionManager",
+ "android.support.transition.TransitionPropagation": "androidx.transition.TransitionPropagation",
+ "android.support.transition.TransitionSet": "androidx.transition.TransitionSet",
+ "android.support.transition.TransitionUtils": "androidx.transition.TransitionUtils",
+ "android.support.transition.TransitionValues": "androidx.transition.TransitionValues",
+ "android.support.transition.TransitionValuesMaps": "androidx.transition.TransitionValuesMaps",
+ "android.support.transition.TranslationAnimationCreator": "androidx.transition.TranslationAnimationCreator",
+ "android.support.transition.ViewGroupOverlayApi14": "androidx.transition.ViewGroupOverlayApi14",
+ "android.support.transition.ViewGroupOverlayApi18": "androidx.transition.ViewGroupOverlayApi18",
+ "android.support.transition.ViewGroupOverlayImpl": "androidx.transition.ViewGroupOverlayImpl",
+ "android.support.transition.ViewGroupUtils": "androidx.transition.ViewGroupUtils",
+ "android.support.transition.ViewGroupUtilsApi14": "androidx.transition.ViewGroupUtilsApi14",
+ "android.support.transition.ViewGroupUtilsApi18": "androidx.transition.ViewGroupUtilsApi18",
+ "android.support.transition.ViewOverlayApi14": "androidx.transition.ViewOverlayApi14",
+ "android.support.transition.ViewOverlayApi18": "androidx.transition.ViewOverlayApi18",
+ "android.support.transition.ViewOverlayImpl": "androidx.transition.ViewOverlayImpl",
+ "android.support.transition.ViewUtils": "androidx.transition.ViewUtils",
+ "android.support.transition.ViewUtilsApi19": "androidx.transition.ViewUtilsApi19",
+ "android.support.transition.ViewUtilsApi21": "androidx.transition.ViewUtilsApi21",
+ "android.support.transition.ViewUtilsApi22": "androidx.transition.ViewUtilsApi22",
+ "android.support.transition.ViewUtilsBase": "androidx.transition.ViewUtilsBase",
+ "android.support.transition.Visibility": "androidx.transition.Visibility",
+ "android.support.transition.VisibilityPropagation": "androidx.transition.VisibilityPropagation",
+ "android.support.transition.WindowIdApi14": "androidx.transition.WindowIdApi14",
+ "android.support.transition.WindowIdApi18": "androidx.transition.WindowIdApi18",
+ "android.support.transition.WindowIdImpl": "androidx.transition.WindowIdImpl",
+ "android.support.v13.app.ActivityCompat": "androidx.legacy.app.ActivityCompat",
+ "android.support.v13.app.FragmentCompat": "androidx.legacy.app.FragmentCompat",
+ "android.support.v13.app.FragmentPagerAdapter": "androidx.legacy.app.FragmentPagerAdapter",
+ "android.support.v13.app.FragmentStatePagerAdapter": "androidx.legacy.app.FragmentStatePagerAdapter",
+ "android.support.v13.app.FragmentTabHost": "androidx.legacy.app.FragmentTabHost",
+ "android.support.v13.view.DragAndDropPermissionsCompat": "androidx.core.view.DragAndDropPermissionsCompat",
+ "android.support.v13.view.DragStartHelper": "androidx.core.view.DragStartHelper",
+ "android.support.v13.view.inputmethod.EditorInfoCompat": "androidx.core.view.inputmethod.EditorInfoCompat",
+ "android.support.v13.view.inputmethod.InputConnectionCompat": "androidx.core.view.inputmethod.InputConnectionCompat",
+ "android.support.v13.view.inputmethod.InputContentInfoCompat": "androidx.core.view.inputmethod.InputContentInfoCompat",
+ "android.support.v13.view.ViewCompat": "androidx.legacy.view.ViewCompat",
+ "android.support.v14.preference.EditTextPreferenceDialogFragment": "androidx.preference.EditTextPreferenceDialogFragment",
+ "android.support.v14.preference.ListPreferenceDialogFragment": "androidx.preference.ListPreferenceDialogFragment",
+ "android.support.v14.preference.MultiSelectListPreference": "androidx.preference.MultiSelectListPreference",
+ "android.support.v14.preference.MultiSelectListPreferenceDialogFragment": "androidx.preference.MultiSelectListPreferenceDialogFragment",
+ "android.support.v14.preference.PreferenceDialogFragment": "androidx.preference.PreferenceDialogFragment",
+ "android.support.v14.preference.PreferenceFragment": "androidx.preference.PreferenceFragment",
+ "android.support.v14.preference.SwitchPreference": "androidx.preference.SwitchPreference",
+ "android.support.v17.internal.widget.OutlineOnlyWithChildrenFrameLayout": "androidx.leanback.preference.internal.OutlineOnlyWithChildrenFrameLayout",
+ "android.support.v17.leanback.animation.LogAccelerateInterpolator": "androidx.leanback.animation.LogAccelerateInterpolator",
+ "android.support.v17.leanback.animation.LogDecelerateInterpolator": "androidx.leanback.animation.LogDecelerateInterpolator",
+ "android.support.v17.leanback.app.BackgroundFragment": "androidx.leanback.app.BackgroundFragment",
+ "android.support.v17.leanback.app.BackgroundManager": "androidx.leanback.app.BackgroundManager",
+ "android.support.v17.leanback.app.BaseFragment": "androidx.leanback.app.BaseFragment",
+ "android.support.v17.leanback.app.BaseRowFragment": "androidx.leanback.app.BaseRowFragment",
+ "android.support.v17.leanback.app.BaseRowSupportFragment": "androidx.leanback.app.BaseRowSupportFragment",
+ "android.support.v17.leanback.app.BaseSupportFragment": "androidx.leanback.app.BaseSupportFragment",
+ "android.support.v17.leanback.app.BrandedFragment": "androidx.leanback.app.BrandedFragment",
+ "android.support.v17.leanback.app.BrandedSupportFragment": "androidx.leanback.app.BrandedSupportFragment",
+ "android.support.v17.leanback.app.BrowseFragment": "androidx.leanback.app.BrowseFragment",
+ "android.support.v17.leanback.app.BrowseSupportFragment": "androidx.leanback.app.BrowseSupportFragment",
+ "android.support.v17.leanback.app.DetailsBackgroundVideoHelper": "androidx.leanback.app.DetailsBackgroundVideoHelper",
+ "android.support.v17.leanback.app.DetailsFragment": "androidx.leanback.app.DetailsFragment",
+ "android.support.v17.leanback.app.DetailsFragmentBackgroundController": "androidx.leanback.app.DetailsFragmentBackgroundController",
+ "android.support.v17.leanback.app.DetailsSupportFragment": "androidx.leanback.app.DetailsSupportFragment",
+ "android.support.v17.leanback.app.DetailsSupportFragmentBackgroundController": "androidx.leanback.app.DetailsSupportFragmentBackgroundController",
+ "android.support.v17.leanback.app.ErrorFragment": "androidx.leanback.app.ErrorFragment",
+ "android.support.v17.leanback.app.ErrorSupportFragment": "androidx.leanback.app.ErrorSupportFragment",
+ "android.support.v17.leanback.app.FragmentUtil": "androidx.leanback.app.FragmentUtil",
+ "android.support.v17.leanback.app.GuidedStepFragment": "androidx.leanback.app.GuidedStepFragment",
+ "android.support.v17.leanback.app.GuidedStepRootLayout": "androidx.leanback.app.GuidedStepRootLayout",
+ "android.support.v17.leanback.app.GuidedStepSupportFragment": "androidx.leanback.app.GuidedStepSupportFragment",
+ "android.support.v17.leanback.app.HeadersFragment": "androidx.leanback.app.HeadersFragment",
+ "android.support.v17.leanback.app.HeadersSupportFragment": "androidx.leanback.app.HeadersSupportFragment",
+ "android.support.v17.leanback.app.ListRowDataAdapter": "androidx.leanback.app.ListRowDataAdapter",
+ "android.support.v17.leanback.app.OnboardingFragment": "androidx.leanback.app.OnboardingFragment",
+ "android.support.v17.leanback.app.OnboardingSupportFragment": "androidx.leanback.app.OnboardingSupportFragment",
+ "android.support.v17.leanback.app.PermissionHelper": "androidx.leanback.app.PermissionHelper",
+ "android.support.v17.leanback.app.PlaybackFragment": "androidx.leanback.app.PlaybackFragment",
+ "android.support.v17.leanback.app.PlaybackFragmentGlueHost": "androidx.leanback.app.PlaybackFragmentGlueHost",
+ "android.support.v17.leanback.app.PlaybackSupportFragment": "androidx.leanback.app.PlaybackSupportFragment",
+ "android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost": "androidx.leanback.app.PlaybackSupportFragmentGlueHost",
+ "android.support.v17.leanback.app.ProgressBarManager": "androidx.leanback.app.ProgressBarManager",
+ "android.support.v17.leanback.app.RowsFragment": "androidx.leanback.app.RowsFragment",
+ "android.support.v17.leanback.app.RowsSupportFragment": "androidx.leanback.app.RowsSupportFragment",
+ "android.support.v17.leanback.app.SearchFragment": "androidx.leanback.app.SearchFragment",
+ "android.support.v17.leanback.app.SearchSupportFragment": "androidx.leanback.app.SearchSupportFragment",
+ "android.support.v17.leanback.app.VerticalGridFragment": "androidx.leanback.app.VerticalGridFragment",
+ "android.support.v17.leanback.app.VerticalGridSupportFragment": "androidx.leanback.app.VerticalGridSupportFragment",
+ "android.support.v17.leanback.app.VideoFragment": "androidx.leanback.app.VideoFragment",
+ "android.support.v17.leanback.app.VideoFragmentGlueHost": "androidx.leanback.app.VideoFragmentGlueHost",
+ "android.support.v17.leanback.app.VideoSupportFragment": "androidx.leanback.app.VideoSupportFragment",
+ "android.support.v17.leanback.app.VideoSupportFragmentGlueHost": "androidx.leanback.app.VideoSupportFragmentGlueHost",
+ "android.support.v17.leanback.database.CursorMapper": "androidx.leanback.database.CursorMapper",
+ "android.support.v17.leanback.graphics.BoundsRule": "androidx.leanback.graphics.BoundsRule",
+ "android.support.v17.leanback.graphics.ColorFilterCache": "androidx.leanback.graphics.ColorFilterCache",
+ "android.support.v17.leanback.graphics.ColorFilterDimmer": "androidx.leanback.graphics.ColorFilterDimmer",
+ "android.support.v17.leanback.graphics.ColorOverlayDimmer": "androidx.leanback.graphics.ColorOverlayDimmer",
+ "android.support.v17.leanback.graphics.CompositeDrawable": "androidx.leanback.graphics.CompositeDrawable",
+ "android.support.v17.leanback.graphics.FitWidthBitmapDrawable": "androidx.leanback.graphics.FitWidthBitmapDrawable",
+ "android.support.v17.leanback.media.MediaControllerAdapter": "androidx.leanback.media.MediaControllerAdapter",
+ "android.support.v17.leanback.media.MediaControllerGlue": "androidx.leanback.media.MediaControllerGlue",
+ "android.support.v17.leanback.media.MediaPlayerAdapter": "androidx.leanback.media.MediaPlayerAdapter",
+ "android.support.v17.leanback.media.MediaPlayerGlue": "androidx.leanback.media.MediaPlayerGlue",
+ "android.support.v17.leanback.media.PlaybackBannerControlGlue": "androidx.leanback.media.PlaybackBannerControlGlue",
+ "android.support.v17.leanback.media.PlaybackBaseControlGlue": "androidx.leanback.media.PlaybackBaseControlGlue",
+ "android.support.v17.leanback.media.PlaybackControlGlue": "androidx.leanback.media.PlaybackControlGlue",
+ "android.support.v17.leanback.media.PlaybackGlue": "androidx.leanback.media.PlaybackGlue",
+ "android.support.v17.leanback.media.PlaybackGlueHost": "androidx.leanback.media.PlaybackGlueHost",
+ "android.support.v17.leanback.media.PlaybackTransportControlGlue": "androidx.leanback.media.PlaybackTransportControlGlue",
+ "android.support.v17.leanback.media.PlayerAdapter": "androidx.leanback.media.PlayerAdapter",
+ "android.support.v17.leanback.media.SurfaceHolderGlueHost": "androidx.leanback.media.SurfaceHolderGlueHost",
+ "android.support.v17.leanback.R": "androidx.leanback.R",
+ "android.support.v17.leanback.system.Settings": "androidx.leanback.system.Settings",
+ "android.support.v17.leanback.transition.CustomChangeBounds": "androidx.leanback.transition.CustomChangeBounds",
+ "android.support.v17.leanback.transition.FadeAndShortSlide": "androidx.leanback.transition.FadeAndShortSlide",
+ "android.support.v17.leanback.transition.LeanbackTransitionHelper": "androidx.leanback.transition.LeanbackTransitionHelper",
+ "android.support.v17.leanback.transition.ParallaxTransition": "androidx.leanback.transition.ParallaxTransition",
+ "android.support.v17.leanback.transition.Scale": "androidx.leanback.transition.Scale",
+ "android.support.v17.leanback.transition.SlideKitkat": "androidx.leanback.transition.SlideKitkat",
+ "android.support.v17.leanback.transition.SlideNoPropagation": "androidx.leanback.transition.SlideNoPropagation",
+ "android.support.v17.leanback.transition.TransitionEpicenterCallback": "androidx.leanback.transition.TransitionEpicenterCallback",
+ "android.support.v17.leanback.transition.TransitionHelper": "androidx.leanback.transition.TransitionHelper",
+ "android.support.v17.leanback.transition.TransitionListener": "androidx.leanback.transition.TransitionListener",
+ "android.support.v17.leanback.transition.TranslationAnimationCreator": "androidx.leanback.transition.TranslationAnimationCreator",
+ "android.support.v17.leanback.util.MathUtil": "androidx.leanback.util.MathUtil",
+ "android.support.v17.leanback.util.StateMachine": "androidx.leanback.util.StateMachine",
+ "android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter": "androidx.leanback.widget.AbstractDetailsDescriptionPresenter",
+ "android.support.v17.leanback.widget.AbstractMediaItemPresenter": "androidx.leanback.widget.AbstractMediaItemPresenter",
+ "android.support.v17.leanback.widget.AbstractMediaListHeaderPresenter": "androidx.leanback.widget.AbstractMediaListHeaderPresenter",
+ "android.support.v17.leanback.widget.Action": "androidx.leanback.widget.Action",
+ "android.support.v17.leanback.widget.ActionPresenterSelector": "androidx.leanback.widget.ActionPresenterSelector",
+ "android.support.v17.leanback.widget.ArrayObjectAdapter": "androidx.leanback.widget.ArrayObjectAdapter",
+ "android.support.v17.leanback.widget.BackgroundHelper": "androidx.leanback.widget.BackgroundHelper",
+ "android.support.v17.leanback.widget.BaseCardView": "androidx.leanback.widget.BaseCardView",
+ "android.support.v17.leanback.widget.BaseGridView": "androidx.leanback.widget.BaseGridView",
+ "android.support.v17.leanback.widget.BaseOnItemViewClickedListener": "androidx.leanback.widget.BaseOnItemViewClickedListener",
+ "android.support.v17.leanback.widget.BaseOnItemViewSelectedListener": "androidx.leanback.widget.BaseOnItemViewSelectedListener",
+ "android.support.v17.leanback.widget.BrowseFrameLayout": "androidx.leanback.widget.BrowseFrameLayout",
+ "android.support.v17.leanback.widget.BrowseRowsFrameLayout": "androidx.leanback.widget.BrowseRowsFrameLayout",
+ "android.support.v17.leanback.widget.CheckableImageView": "androidx.leanback.widget.CheckableImageView",
+ "android.support.v17.leanback.widget.ClassPresenterSelector": "androidx.leanback.widget.ClassPresenterSelector",
+ "android.support.v17.leanback.widget.ControlBar": "androidx.leanback.widget.ControlBar",
+ "android.support.v17.leanback.widget.ControlBarPresenter": "androidx.leanback.widget.ControlBarPresenter",
+ "android.support.v17.leanback.widget.ControlButtonPresenterSelector": "androidx.leanback.widget.ControlButtonPresenterSelector",
+ "android.support.v17.leanback.widget.CursorObjectAdapter": "androidx.leanback.widget.CursorObjectAdapter",
+ "android.support.v17.leanback.widget.DetailsOverviewLogoPresenter": "androidx.leanback.widget.DetailsOverviewLogoPresenter",
+ "android.support.v17.leanback.widget.DetailsOverviewRow": "androidx.leanback.widget.DetailsOverviewRow",
+ "android.support.v17.leanback.widget.DetailsOverviewRowPresenter": "androidx.leanback.widget.DetailsOverviewRowPresenter",
+ "android.support.v17.leanback.widget.DetailsOverviewSharedElementHelper": "androidx.leanback.widget.DetailsOverviewSharedElementHelper",
+ "android.support.v17.leanback.widget.DetailsParallax": "androidx.leanback.widget.DetailsParallax",
+ "android.support.v17.leanback.widget.DetailsParallaxDrawable": "androidx.leanback.widget.DetailsParallaxDrawable",
+ "android.support.v17.leanback.widget.DiffCallback": "androidx.leanback.widget.DiffCallback",
+ "android.support.v17.leanback.widget.DividerPresenter": "androidx.leanback.widget.DividerPresenter",
+ "android.support.v17.leanback.widget.DividerRow": "androidx.leanback.widget.DividerRow",
+ "android.support.v17.leanback.widget.FacetProvider": "androidx.leanback.widget.FacetProvider",
+ "android.support.v17.leanback.widget.FacetProviderAdapter": "androidx.leanback.widget.FacetProviderAdapter",
+ "android.support.v17.leanback.widget.FocusHighlight": "androidx.leanback.widget.FocusHighlight",
+ "android.support.v17.leanback.widget.FocusHighlightHandler": "androidx.leanback.widget.FocusHighlightHandler",
+ "android.support.v17.leanback.widget.FocusHighlightHelper": "androidx.leanback.widget.FocusHighlightHelper",
+ "android.support.v17.leanback.widget.ForegroundHelper": "androidx.leanback.widget.ForegroundHelper",
+ "android.support.v17.leanback.widget.FragmentAnimationProvider": "androidx.leanback.widget.FragmentAnimationProvider",
+ "android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter": "androidx.leanback.widget.FullWidthDetailsOverviewRowPresenter",
+ "android.support.v17.leanback.widget.FullWidthDetailsOverviewSharedElementHelper": "androidx.leanback.widget.FullWidthDetailsOverviewSharedElementHelper",
+ "android.support.v17.leanback.widget.Grid": "androidx.leanback.widget.Grid",
+ "android.support.v17.leanback.widget.GridLayoutManager": "androidx.leanback.widget.GridLayoutManager",
+ "android.support.v17.leanback.widget.GuidanceStylingRelativeLayout": "androidx.leanback.widget.GuidanceStylingRelativeLayout",
+ "android.support.v17.leanback.widget.GuidanceStylist": "androidx.leanback.widget.GuidanceStylist",
+ "android.support.v17.leanback.widget.GuidedAction": "androidx.leanback.widget.GuidedAction",
+ "android.support.v17.leanback.widget.GuidedActionAdapter": "androidx.leanback.widget.GuidedActionAdapter",
+ "android.support.v17.leanback.widget.GuidedActionAdapterGroup": "androidx.leanback.widget.GuidedActionAdapterGroup",
+ "android.support.v17.leanback.widget.GuidedActionAutofillSupport": "androidx.leanback.widget.GuidedActionAutofillSupport",
+ "android.support.v17.leanback.widget.GuidedActionDiffCallback": "androidx.leanback.widget.GuidedActionDiffCallback",
+ "android.support.v17.leanback.widget.GuidedActionEditText": "androidx.leanback.widget.GuidedActionEditText",
+ "android.support.v17.leanback.widget.GuidedActionItemContainer": "androidx.leanback.widget.GuidedActionItemContainer",
+ "android.support.v17.leanback.widget.GuidedActionsRelativeLayout": "androidx.leanback.widget.GuidedActionsRelativeLayout",
+ "android.support.v17.leanback.widget.GuidedActionsStylist": "androidx.leanback.widget.GuidedActionsStylist",
+ "android.support.v17.leanback.widget.GuidedDatePickerAction": "androidx.leanback.widget.GuidedDatePickerAction",
+ "android.support.v17.leanback.widget.HeaderItem": "androidx.leanback.widget.HeaderItem",
+ "android.support.v17.leanback.widget.HorizontalGridView": "androidx.leanback.widget.HorizontalGridView",
+ "android.support.v17.leanback.widget.HorizontalHoverCardSwitcher": "androidx.leanback.widget.HorizontalHoverCardSwitcher",
+ "android.support.v17.leanback.widget.ImageCardView": "androidx.leanback.widget.ImageCardView",
+ "android.support.v17.leanback.widget.ImeKeyMonitor": "androidx.leanback.widget.ImeKeyMonitor",
+ "android.support.v17.leanback.widget.InvisibleRowPresenter": "androidx.leanback.widget.InvisibleRowPresenter",
+ "android.support.v17.leanback.widget.ItemAlignment": "androidx.leanback.widget.ItemAlignment",
+ "android.support.v17.leanback.widget.ItemAlignmentFacet": "androidx.leanback.widget.ItemAlignmentFacet",
+ "android.support.v17.leanback.widget.ItemAlignmentFacetHelper": "androidx.leanback.widget.ItemAlignmentFacetHelper",
+ "android.support.v17.leanback.widget.ItemBridgeAdapter": "androidx.leanback.widget.ItemBridgeAdapter",
+ "android.support.v17.leanback.widget.ItemBridgeAdapterShadowOverlayWrapper": "androidx.leanback.widget.ItemBridgeAdapterShadowOverlayWrapper",
+ "android.support.v17.leanback.widget.ListRow": "androidx.leanback.widget.ListRow",
+ "android.support.v17.leanback.widget.ListRowHoverCardView": "androidx.leanback.widget.ListRowHoverCardView",
+ "android.support.v17.leanback.widget.ListRowPresenter": "androidx.leanback.widget.ListRowPresenter",
+ "android.support.v17.leanback.widget.ListRowView": "androidx.leanback.widget.ListRowView",
+ "android.support.v17.leanback.widget.MediaItemActionPresenter": "androidx.leanback.widget.MediaItemActionPresenter",
+ "android.support.v17.leanback.widget.MediaNowPlayingView": "androidx.leanback.widget.MediaNowPlayingView",
+ "android.support.v17.leanback.widget.MediaRowFocusView": "androidx.leanback.widget.MediaRowFocusView",
+ "android.support.v17.leanback.widget.MultiActionsProvider": "androidx.leanback.widget.MultiActionsProvider",
+ "android.support.v17.leanback.widget.NonOverlappingFrameLayout": "androidx.leanback.widget.NonOverlappingFrameLayout",
+ "android.support.v17.leanback.widget.NonOverlappingLinearLayout": "androidx.leanback.widget.NonOverlappingLinearLayout",
+ "android.support.v17.leanback.widget.NonOverlappingLinearLayoutWithForeground": "androidx.leanback.widget.NonOverlappingLinearLayoutWithForeground",
+ "android.support.v17.leanback.widget.NonOverlappingRelativeLayout": "androidx.leanback.widget.NonOverlappingRelativeLayout",
+ "android.support.v17.leanback.widget.NonOverlappingView": "androidx.leanback.widget.NonOverlappingView",
+ "android.support.v17.leanback.widget.ObjectAdapter": "androidx.leanback.widget.ObjectAdapter",
+ "android.support.v17.leanback.widget.OnActionClickedListener": "androidx.leanback.widget.OnActionClickedListener",
+ "android.support.v17.leanback.widget.OnChildLaidOutListener": "androidx.leanback.widget.OnChildLaidOutListener",
+ "android.support.v17.leanback.widget.OnChildSelectedListener": "androidx.leanback.widget.OnChildSelectedListener",
+ "android.support.v17.leanback.widget.OnChildViewHolderSelectedListener": "androidx.leanback.widget.OnChildViewHolderSelectedListener",
+ "android.support.v17.leanback.widget.OnItemViewClickedListener": "androidx.leanback.widget.OnItemViewClickedListener",
+ "android.support.v17.leanback.widget.OnItemViewSelectedListener": "androidx.leanback.widget.OnItemViewSelectedListener",
+ "android.support.v17.leanback.widget.PageRow": "androidx.leanback.widget.PageRow",
+ "android.support.v17.leanback.widget.PagingIndicator": "androidx.leanback.widget.PagingIndicator",
+ "android.support.v17.leanback.widget.Parallax": "androidx.leanback.widget.Parallax",
+ "android.support.v17.leanback.widget.ParallaxEffect": "androidx.leanback.widget.ParallaxEffect",
+ "android.support.v17.leanback.widget.ParallaxTarget": "androidx.leanback.widget.ParallaxTarget",
+ "android.support.v17.leanback.widget.PersistentFocusWrapper": "androidx.leanback.widget.PersistentFocusWrapper",
+ "android.support.v17.leanback.widget.picker.DatePicker": "androidx.leanback.widget.picker.DatePicker",
+ "android.support.v17.leanback.widget.picker.Picker": "androidx.leanback.widget.picker.Picker",
+ "android.support.v17.leanback.widget.picker.PickerColumn": "androidx.leanback.widget.picker.PickerColumn",
+ "android.support.v17.leanback.widget.picker.PickerUtility": "androidx.leanback.widget.picker.PickerUtility",
+ "android.support.v17.leanback.widget.picker.TimePicker": "androidx.leanback.widget.picker.TimePicker",
+ "android.support.v17.leanback.widget.PlaybackControlsPresenter": "androidx.leanback.widget.PlaybackControlsPresenter",
+ "android.support.v17.leanback.widget.PlaybackControlsRow": "androidx.leanback.widget.PlaybackControlsRow",
+ "android.support.v17.leanback.widget.PlaybackControlsRowPresenter": "androidx.leanback.widget.PlaybackControlsRowPresenter",
+ "android.support.v17.leanback.widget.PlaybackControlsRowView": "androidx.leanback.widget.PlaybackControlsRowView",
+ "android.support.v17.leanback.widget.PlaybackRowPresenter": "androidx.leanback.widget.PlaybackRowPresenter",
+ "android.support.v17.leanback.widget.PlaybackSeekDataProvider": "androidx.leanback.widget.PlaybackSeekDataProvider",
+ "android.support.v17.leanback.widget.PlaybackSeekUi": "androidx.leanback.widget.PlaybackSeekUi",
+ "android.support.v17.leanback.widget.PlaybackTransportRowPresenter": "androidx.leanback.widget.PlaybackTransportRowPresenter",
+ "android.support.v17.leanback.widget.PlaybackTransportRowView": "androidx.leanback.widget.PlaybackTransportRowView",
+ "android.support.v17.leanback.widget.Presenter": "androidx.leanback.widget.Presenter",
+ "android.support.v17.leanback.widget.PresenterSelector": "androidx.leanback.widget.PresenterSelector",
+ "android.support.v17.leanback.widget.PresenterSwitcher": "androidx.leanback.widget.PresenterSwitcher",
+ "android.support.v17.leanback.widget.RecyclerViewParallax": "androidx.leanback.widget.RecyclerViewParallax",
+ "android.support.v17.leanback.widget.ResizingTextView": "androidx.leanback.widget.ResizingTextView",
+ "android.support.v17.leanback.widget.RoundedRectHelper": "androidx.leanback.widget.RoundedRectHelper",
+ "android.support.v17.leanback.widget.RoundedRectHelperApi21": "androidx.leanback.widget.RoundedRectHelperApi21",
+ "android.support.v17.leanback.widget.Row": "androidx.leanback.widget.Row",
+ "android.support.v17.leanback.widget.RowContainerView": "androidx.leanback.widget.RowContainerView",
+ "android.support.v17.leanback.widget.RowHeaderPresenter": "androidx.leanback.widget.RowHeaderPresenter",
+ "android.support.v17.leanback.widget.RowHeaderView": "androidx.leanback.widget.RowHeaderView",
+ "android.support.v17.leanback.widget.RowPresenter": "androidx.leanback.widget.RowPresenter",
+ "android.support.v17.leanback.widget.ScaleFrameLayout": "androidx.leanback.widget.ScaleFrameLayout",
+ "android.support.v17.leanback.widget.SearchBar": "androidx.leanback.widget.SearchBar",
+ "android.support.v17.leanback.widget.SearchEditText": "androidx.leanback.widget.SearchEditText",
+ "android.support.v17.leanback.widget.SearchOrbView": "androidx.leanback.widget.SearchOrbView",
+ "android.support.v17.leanback.widget.SectionRow": "androidx.leanback.widget.SectionRow",
+ "android.support.v17.leanback.widget.SeekBar": "androidx.leanback.widget.SeekBar",
+ "android.support.v17.leanback.widget.ShadowHelper": "androidx.leanback.widget.ShadowHelper",
+ "android.support.v17.leanback.widget.ShadowHelperApi21": "androidx.leanback.widget.ShadowHelperApi21",
+ "android.support.v17.leanback.widget.ShadowOverlayContainer": "androidx.leanback.widget.ShadowOverlayContainer",
+ "android.support.v17.leanback.widget.ShadowOverlayHelper": "androidx.leanback.widget.ShadowOverlayHelper",
+ "android.support.v17.leanback.widget.SinglePresenterSelector": "androidx.leanback.widget.SinglePresenterSelector",
+ "android.support.v17.leanback.widget.SingleRow": "androidx.leanback.widget.SingleRow",
+ "android.support.v17.leanback.widget.SparseArrayObjectAdapter": "androidx.leanback.widget.SparseArrayObjectAdapter",
+ "android.support.v17.leanback.widget.SpeechOrbView": "androidx.leanback.widget.SpeechOrbView",
+ "android.support.v17.leanback.widget.SpeechRecognitionCallback": "androidx.leanback.widget.SpeechRecognitionCallback",
+ "android.support.v17.leanback.widget.StaggeredGrid": "androidx.leanback.widget.StaggeredGrid",
+ "android.support.v17.leanback.widget.StaggeredGridDefault": "androidx.leanback.widget.StaggeredGridDefault",
+ "android.support.v17.leanback.widget.StaticShadowHelper": "androidx.leanback.widget.StaticShadowHelper",
+ "android.support.v17.leanback.widget.StreamingTextView": "androidx.leanback.widget.StreamingTextView",
+ "android.support.v17.leanback.widget.ThumbsBar": "androidx.leanback.widget.ThumbsBar",
+ "android.support.v17.leanback.widget.TitleHelper": "androidx.leanback.widget.TitleHelper",
+ "android.support.v17.leanback.widget.TitleView": "androidx.leanback.widget.TitleView",
+ "android.support.v17.leanback.widget.TitleViewAdapter": "androidx.leanback.widget.TitleViewAdapter",
+ "android.support.v17.leanback.widget.Util": "androidx.leanback.widget.Util",
+ "android.support.v17.leanback.widget.VerticalGridPresenter": "androidx.leanback.widget.VerticalGridPresenter",
+ "android.support.v17.leanback.widget.VerticalGridView": "androidx.leanback.widget.VerticalGridView",
+ "android.support.v17.leanback.widget.VideoSurfaceView": "androidx.leanback.widget.VideoSurfaceView",
+ "android.support.v17.leanback.widget.ViewHolderTask": "androidx.leanback.widget.ViewHolderTask",
+ "android.support.v17.leanback.widget.ViewsStateBundle": "androidx.leanback.widget.ViewsStateBundle",
+ "android.support.v17.leanback.widget.Visibility": "androidx.leanback.widget.Visibility",
+ "android.support.v17.leanback.widget.WindowAlignment": "androidx.leanback.widget.WindowAlignment",
+ "android.support.v17.preference.BaseLeanbackPreferenceFragment": "androidx.leanback.preference.BaseLeanbackPreferenceFragment",
+ "android.support.v17.preference.LeanbackListPreferenceDialogFragment": "androidx.leanback.preference.LeanbackListPreferenceDialogFragment",
+ "android.support.v17.preference.LeanbackPreferenceDialogFragment": "androidx.leanback.preference.LeanbackPreferenceDialogFragment",
+ "android.support.v17.preference.LeanbackPreferenceFragment": "androidx.leanback.preference.LeanbackPreferenceFragment",
+ "android.support.v17.preference.LeanbackPreferenceFragmentTransitionHelperApi21": "androidx.leanback.preference.LeanbackPreferenceFragmentTransitionHelperApi21",
+ "android.support.v17.preference.LeanbackSettingsFragment": "androidx.leanback.preference.LeanbackSettingsFragment",
+ "android.support.v17.preference.LeanbackSettingsRootView": "androidx.leanback.preference.LeanbackSettingsRootView",
+ "android.support.v17.preference.R": "androidx.leanback.preference.R",
+ "android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat": "androidx.core.accessibilityservice.AccessibilityServiceInfoCompat",
+ "android.support.v4.app.ActionBarDrawerToggle": "androidx.legacy.app.ActionBarDrawerToggle",
+ "android.support.v4.app.ActivityCompat": "androidx.core.app.ActivityCompat",
+ "android.support.v4.app.ActivityManagerCompat": "androidx.core.app.ActivityManagerCompat",
+ "android.support.v4.app.ActivityOptionsCompat": "androidx.core.app.ActivityOptionsCompat",
+ "android.support.v4.app.AlarmManagerCompat": "androidx.core.app.AlarmManagerCompat",
+ "android.support.v4.app.AppComponentFactory": "androidx.core.app.AppComponentFactory",
+ "android.support.v4.app.AppLaunchChecker": "androidx.core.app.AppLaunchChecker",
+ "android.support.v4.app.AppOpsManagerCompat": "androidx.core.app.AppOpsManagerCompat",
+ "android.support.v4.app.BackStackRecord": "androidx.fragment.app.BackStackRecord",
+ "android.support.v4.app.BackStackState": "androidx.fragment.app.BackStackState",
+ "android.support.v4.app.BundleCompat": "androidx.core.app.BundleCompat",
+ "android.support.v4.app.CoreComponentFactory": "androidx.core.app.CoreComponentFactory",
+ "android.support.v4.app.DialogFragment": "androidx.fragment.app.DialogFragment",
+ "android.support.v4.app.Fragment": "androidx.fragment.app.Fragment",
+ "android.support.v4.app.FragmentActivity": "androidx.fragment.app.FragmentActivity",
+ "android.support.v4.app.FragmentContainer": "androidx.fragment.app.FragmentContainer",
+ "android.support.v4.app.FragmentController": "androidx.fragment.app.FragmentController",
+ "android.support.v4.app.FragmentHostCallback": "androidx.fragment.app.FragmentHostCallback",
+ "android.support.v4.app.FragmentManager": "androidx.fragment.app.FragmentManager",
+ "android.support.v4.app.FragmentManagerImpl": "androidx.fragment.app.FragmentManagerImpl",
+ "android.support.v4.app.FragmentManagerNonConfig": "androidx.fragment.app.FragmentManagerNonConfig",
+ "android.support.v4.app.FragmentManagerState": "androidx.fragment.app.FragmentManagerState",
+ "android.support.v4.app.FragmentPagerAdapter": "androidx.fragment.app.FragmentPagerAdapter",
+ "android.support.v4.app.FragmentState": "androidx.fragment.app.FragmentState",
+ "android.support.v4.app.FragmentStatePagerAdapter": "androidx.fragment.app.FragmentStatePagerAdapter",
+ "android.support.v4.app.FragmentTabHost": "androidx.fragment.app.FragmentTabHost",
+ "android.support.v4.app.FragmentTransaction": "androidx.fragment.app.FragmentTransaction",
+ "android.support.v4.app.FragmentTransition": "androidx.fragment.app.FragmentTransition",
+ "android.support.v4.app.FragmentTransitionCompat21": "androidx.fragment.app.FragmentTransitionCompat21",
+ "android.support.v4.app.FragmentTransitionImpl": "androidx.fragment.app.FragmentTransitionImpl",
+ "android.support.v4.app.FrameMetricsAggregator": "androidx.core.app.FrameMetricsAggregator",
+ "android.support.v4.app.INotificationSideChannel": "androidx.core.app.INotificationSideChannel",
+ "android.support.v4.app.JobIntentService": "androidx.core.app.JobIntentService",
+ "android.support.v4.app.ListFragment": "androidx.fragment.app.ListFragment",
+ "android.support.v4.app.LoaderManager": "androidx.loader.app.LoaderManager",
+ "android.support.v4.app.LoaderManagerImpl": "androidx.loader.app.LoaderManagerImpl",
+ "android.support.v4.app.NavUtils": "androidx.core.app.NavUtils",
+ "android.support.v4.app.NotificationBuilderWithBuilderAccessor": "androidx.core.app.NotificationBuilderWithBuilderAccessor",
+ "android.support.v4.app.NotificationCompat": "androidx.core.app.NotificationCompat",
+ "android.support.v4.app.NotificationCompatBuilder": "androidx.core.app.NotificationCompatBuilder",
+ "android.support.v4.app.NotificationCompatExtras": "androidx.core.app.NotificationCompatExtras",
+ "android.support.v4.app.NotificationCompatJellybean": "androidx.core.app.NotificationCompatJellybean",
+ "android.support.v4.app.NotificationCompatSideChannelService": "androidx.core.app.NotificationCompatSideChannelService",
+ "android.support.v4.app.NotificationManagerCompat": "androidx.core.app.NotificationManagerCompat",
+ "android.support.v4.app.OneShotPreDrawListener": "androidx.fragment.app.OneShotPreDrawListener",
+ "android.support.v4.app.Person": "androidx.core.app.Person",
+ "android.support.v4.app.RemoteInput": "androidx.core.app.RemoteInput",
+ "android.support.v4.app.ServiceCompat": "androidx.core.app.ServiceCompat",
+ "android.support.v4.app.ShareCompat": "androidx.core.app.ShareCompat",
+ "android.support.v4.app.SharedElementCallback": "androidx.core.app.SharedElementCallback",
+ "android.support.v4.app.SuperNotCalledException": "androidx.fragment.app.SuperNotCalledException",
+ "android.support.v4.app.SupportActivity": "androidx.core.app.ComponentActivity",
+ "android.support.v4.app.TaskStackBuilder": "androidx.core.app.TaskStackBuilder",
+ "android.support.v4.content.AsyncTaskLoader": "androidx.loader.content.AsyncTaskLoader",
+ "android.support.v4.content.ContentResolverCompat": "androidx.core.content.ContentResolverCompat",
+ "android.support.v4.content.ContextCompat": "androidx.core.content.ContextCompat",
+ "android.support.v4.content.CursorLoader": "androidx.loader.content.CursorLoader",
+ "android.support.v4.content.FileProvider": "androidx.core.content.FileProvider",
+ "android.support.v4.content.IntentCompat": "androidx.core.content.IntentCompat",
+ "android.support.v4.content.Loader": "androidx.loader.content.Loader",
+ "android.support.v4.content.LocalBroadcastManager": "androidx.localbroadcastmanager.content.LocalBroadcastManager",
+ "android.support.v4.content.MimeTypeFilter": "androidx.core.content.MimeTypeFilter",
+ "android.support.v4.content.ModernAsyncTask": "androidx.loader.content.ModernAsyncTask",
+ "android.support.v4.content.PermissionChecker": "androidx.core.content.PermissionChecker",
+ "android.support.v4.content.pm.ActivityInfoCompat": "androidx.core.content.pm.ActivityInfoCompat",
+ "android.support.v4.content.pm.PackageInfoCompat": "androidx.core.content.pm.PackageInfoCompat",
+ "android.support.v4.content.pm.PermissionInfoCompat": "androidx.core.content.pm.PermissionInfoCompat",
+ "android.support.v4.content.pm.ShortcutInfoCompat": "androidx.core.content.pm.ShortcutInfoCompat",
+ "android.support.v4.content.pm.ShortcutManagerCompat": "androidx.core.content.pm.ShortcutManagerCompat",
+ "android.support.v4.content.res.ColorStateListInflaterCompat": "androidx.core.content.res.ColorStateListInflaterCompat",
+ "android.support.v4.content.res.ComplexColorCompat": "androidx.core.content.res.ComplexColorCompat",
+ "android.support.v4.content.res.ConfigurationHelper": "androidx.core.content.res.ConfigurationHelper",
+ "android.support.v4.content.res.FontResourcesParserCompat": "androidx.core.content.res.FontResourcesParserCompat",
+ "android.support.v4.content.res.GradientColorInflaterCompat": "androidx.core.content.res.GradientColorInflaterCompat",
+ "android.support.v4.content.res.GrowingArrayUtils": "androidx.core.content.res.GrowingArrayUtils",
+ "android.support.v4.content.res.ResourcesCompat": "androidx.core.content.res.ResourcesCompat",
+ "android.support.v4.content.res.TypedArrayUtils": "androidx.core.content.res.TypedArrayUtils",
+ "android.support.v4.content.SharedPreferencesCompat": "androidx.core.content.SharedPreferencesCompat",
+ "android.support.v4.content.WakefulBroadcastReceiver": "androidx.legacy.content.WakefulBroadcastReceiver",
+ "android.support.v4.database.CursorWindowCompat": "androidx.core.database.CursorWindowCompat",
+ "android.support.v4.database.DatabaseUtilsCompat": "androidx.core.database.DatabaseUtilsCompat",
+ "android.support.v4.database.sqlite.SQLiteCursorCompat": "androidx.core.database.sqlite.SQLiteCursorCompat",
+ "android.support.v4.graphics.BitmapCompat": "androidx.core.graphics.BitmapCompat",
+ "android.support.v4.graphics.ColorUtils": "androidx.core.graphics.ColorUtils",
+ "android.support.v4.graphics.drawable.DrawableCompat": "androidx.core.graphics.drawable.DrawableCompat",
+ "android.support.v4.graphics.drawable.IconCompat": "androidx.core.graphics.drawable.IconCompat",
+ "android.support.v4.graphics.drawable.IconCompatParcelizer": "android.support.v4.graphics.drawable.IconCompatParcelizer",
+ "android.support.v4.graphics.drawable.RoundedBitmapDrawable21": "androidx.core.graphics.drawable.RoundedBitmapDrawable21",
+ "android.support.v4.graphics.drawable.RoundedBitmapDrawable": "androidx.core.graphics.drawable.RoundedBitmapDrawable",
+ "android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory": "androidx.core.graphics.drawable.RoundedBitmapDrawableFactory",
+ "android.support.v4.graphics.drawable.TintAwareDrawable": "androidx.core.graphics.drawable.TintAwareDrawable",
+ "android.support.v4.graphics.drawable.WrappedDrawable": "androidx.core.graphics.drawable.WrappedDrawable",
+ "android.support.v4.graphics.drawable.WrappedDrawableApi14": "androidx.core.graphics.drawable.WrappedDrawableApi14",
+ "android.support.v4.graphics.drawable.WrappedDrawableApi21": "androidx.core.graphics.drawable.WrappedDrawableApi21",
+ "android.support.v4.graphics.PaintCompat": "androidx.core.graphics.PaintCompat",
+ "android.support.v4.graphics.PathParser": "androidx.core.graphics.PathParser",
+ "android.support.v4.graphics.PathSegment": "androidx.core.graphics.PathSegment",
+ "android.support.v4.graphics.PathUtils": "androidx.core.graphics.PathUtils",
+ "android.support.v4.graphics.TypefaceCompat": "androidx.core.graphics.TypefaceCompat",
+ "android.support.v4.graphics.TypefaceCompatApi21Impl": "androidx.core.graphics.TypefaceCompatApi21Impl",
+ "android.support.v4.graphics.TypefaceCompatApi24Impl": "androidx.core.graphics.TypefaceCompatApi24Impl",
+ "android.support.v4.graphics.TypefaceCompatApi26Impl": "androidx.core.graphics.TypefaceCompatApi26Impl",
+ "android.support.v4.graphics.TypefaceCompatApi28Impl": "androidx.core.graphics.TypefaceCompatApi28Impl",
+ "android.support.v4.graphics.TypefaceCompatBaseImpl": "androidx.core.graphics.TypefaceCompatBaseImpl",
+ "android.support.v4.graphics.TypefaceCompatUtil": "androidx.core.graphics.TypefaceCompatUtil",
+ "android.support.v4.hardware.display.DisplayManagerCompat": "androidx.core.hardware.display.DisplayManagerCompat",
+ "android.support.v4.hardware.fingerprint.FingerprintManagerCompat": "androidx.core.hardware.fingerprint.FingerprintManagerCompat",
+ "android.support.v4.internal.view.SupportMenu": "androidx.core.internal.view.SupportMenu",
+ "android.support.v4.internal.view.SupportMenuItem": "androidx.core.internal.view.SupportMenuItem",
+ "android.support.v4.internal.view.SupportSubMenu": "androidx.core.internal.view.SupportSubMenu",
+ "android.support.v4.math.MathUtils": "androidx.core.math.MathUtils",
+ "android.support.v4.media.app.NotificationCompat": "androidx.media.app.NotificationCompat",
+ "android.support.v4.media.AudioAttributesCompat": "androidx.media.AudioAttributesCompat",
+ "android.support.v4.media.AudioAttributesImpl": "android.support.v4.media.AudioAttributesImpl",
+ "android.support.v4.media.AudioAttributesImplApi21": "android.support.v4.media.AudioAttributesImplApi21",
+ "android.support.v4.media.AudioAttributesImplBase": "android.support.v4.media.AudioAttributesImplBase",
+ "android.support.v4.media.MediaBrowserCompat": "android.support.v4.media.MediaBrowserCompat",
+ "android.support.v4.media.MediaBrowserCompatApi21": "android.support.v4.media.MediaBrowserCompatApi21",
+ "android.support.v4.media.MediaBrowserCompatApi23": "android.support.v4.media.MediaBrowserCompatApi23",
+ "android.support.v4.media.MediaBrowserCompatApi26": "android.support.v4.media.MediaBrowserCompatApi26",
+ "android.support.v4.media.MediaBrowserCompatUtils": "androidx.media.MediaBrowserCompatUtils",
+ "android.support.v4.media.MediaBrowserProtocol": "androidx.media.MediaBrowserProtocol",
+ "android.support.v4.media.MediaBrowserServiceCompat": "androidx.media.MediaBrowserServiceCompat",
+ "android.support.v4.media.MediaBrowserServiceCompatApi21": "androidx.media.MediaBrowserServiceCompatApi21",
+ "android.support.v4.media.MediaBrowserServiceCompatApi23": "androidx.media.MediaBrowserServiceCompatApi23",
+ "android.support.v4.media.MediaBrowserServiceCompatApi26": "androidx.media.MediaBrowserServiceCompatApi26",
+ "android.support.v4.media.MediaDescriptionCompat": "android.support.v4.media.MediaDescriptionCompat",
+ "android.support.v4.media.MediaDescriptionCompatApi21": "android.support.v4.media.MediaDescriptionCompatApi21",
+ "android.support.v4.media.MediaDescriptionCompatApi23": "android.support.v4.media.MediaDescriptionCompatApi23",
+ "android.support.v4.media.MediaMetadataCompat": "android.support.v4.media.MediaMetadataCompat",
+ "android.support.v4.media.MediaMetadataCompatApi21": "android.support.v4.media.MediaMetadataCompatApi21",
+ "android.support.v4.media.MediaSessionManager": "android.support.v4.media.MediaSessionManager",
+ "android.support.v4.media.MediaSessionManagerImplApi21": "android.support.v4.media.MediaSessionManagerImplApi21",
+ "android.support.v4.media.MediaSessionManagerImplApi28": "android.support.v4.media.MediaSessionManagerImplApi28",
+ "android.support.v4.media.MediaSessionManagerImplBase": "android.support.v4.media.MediaSessionManagerImplBase",
+ "android.support.v4.media.ParceledListSliceAdapterApi21": "android.support.v4.media.ParceledListSliceAdapterApi21",
+ "android.support.v4.media.RatingCompat": "android.support.v4.media.RatingCompat",
+ "android.support.v4.media.session.IMediaControllerCallback": "android.support.v4.media.session.IMediaControllerCallback",
+ "android.support.v4.media.session.IMediaSession": "android.support.v4.media.session.IMediaSession",
+ "android.support.v4.media.session.MediaButtonReceiver": "androidx.media.session.MediaButtonReceiver",
+ "android.support.v4.media.session.MediaControllerCompat": "android.support.v4.media.session.MediaControllerCompat",
+ "android.support.v4.media.session.MediaControllerCompatApi21": "android.support.v4.media.session.MediaControllerCompatApi21",
+ "android.support.v4.media.session.MediaControllerCompatApi23": "android.support.v4.media.session.MediaControllerCompatApi23",
+ "android.support.v4.media.session.MediaControllerCompatApi24": "android.support.v4.media.session.MediaControllerCompatApi24",
+ "android.support.v4.media.session.MediaSessionCompat": "android.support.v4.media.session.MediaSessionCompat",
+ "android.support.v4.media.session.MediaSessionCompatApi21": "android.support.v4.media.session.MediaSessionCompatApi21",
+ "android.support.v4.media.session.MediaSessionCompatApi22": "android.support.v4.media.session.MediaSessionCompatApi22",
+ "android.support.v4.media.session.MediaSessionCompatApi23": "android.support.v4.media.session.MediaSessionCompatApi23",
+ "android.support.v4.media.session.MediaSessionCompatApi24": "android.support.v4.media.session.MediaSessionCompatApi24",
+ "android.support.v4.media.session.ParcelableVolumeInfo": "android.support.v4.media.session.ParcelableVolumeInfo",
+ "android.support.v4.media.session.PlaybackStateCompat": "android.support.v4.media.session.PlaybackStateCompat",
+ "android.support.v4.media.session.PlaybackStateCompatApi21": "android.support.v4.media.session.PlaybackStateCompatApi21",
+ "android.support.v4.media.session.PlaybackStateCompatApi22": "android.support.v4.media.session.PlaybackStateCompatApi22",
+ "android.support.v4.media.VolumeProviderCompat": "androidx.media.VolumeProviderCompat",
+ "android.support.v4.media.VolumeProviderCompatApi21": "androidx.media.VolumeProviderCompatApi21",
+ "android.support.v4.net.ConnectivityManagerCompat": "androidx.core.net.ConnectivityManagerCompat",
+ "android.support.v4.net.DatagramSocketWrapper": "androidx.core.net.DatagramSocketWrapper",
+ "android.support.v4.net.TrafficStatsCompat": "androidx.core.net.TrafficStatsCompat",
+ "android.support.v4.os.BuildCompat": "androidx.core.os.BuildCompat",
+ "android.support.v4.os.CancellationSignal": "androidx.core.os.CancellationSignal",
+ "android.support.v4.os.ConfigurationCompat": "androidx.core.os.ConfigurationCompat",
+ "android.support.v4.os.EnvironmentCompat": "androidx.core.os.EnvironmentCompat",
+ "android.support.v4.os.HandlerCompat": "androidx.core.os.HandlerCompat",
+ "android.support.v4.os.IResultReceiver": "androidx.core.os.IResultReceiver",
+ "android.support.v4.os.LocaleHelper": "androidx.core.os.LocaleHelper",
+ "android.support.v4.os.LocaleListCompat": "androidx.core.os.LocaleListCompat",
+ "android.support.v4.os.LocaleListHelper": "androidx.core.os.LocaleListHelper",
+ "android.support.v4.os.LocaleListInterface": "androidx.core.os.LocaleListInterface",
+ "android.support.v4.os.OperationCanceledException": "androidx.core.os.OperationCanceledException",
+ "android.support.v4.os.ParcelableCompat": "androidx.core.os.ParcelableCompat",
+ "android.support.v4.os.ParcelableCompatCreatorCallbacks": "androidx.core.os.ParcelableCompatCreatorCallbacks",
+ "android.support.v4.os.ParcelCompat": "androidx.core.os.ParcelCompat",
+ "android.support.v4.os.ResultReceiver": "androidx.core.os.ResultReceiver",
+ "android.support.v4.os.TraceCompat": "androidx.core.os.TraceCompat",
+ "android.support.v4.os.UserManagerCompat": "androidx.core.os.UserManagerCompat",
+ "android.support.v4.print.PrintHelper": "androidx.print.PrintHelper",
+ "android.support.v4.provider.DocumentFile": "androidx.documentfile.provider.DocumentFile",
+ "android.support.v4.provider.DocumentsContractApi19": "androidx.documentfile.provider.DocumentsContractApi19",
+ "android.support.v4.provider.FontRequest": "androidx.core.provider.FontRequest",
+ "android.support.v4.provider.FontsContractCompat": "androidx.core.provider.FontsContractCompat",
+ "android.support.v4.provider.RawDocumentFile": "androidx.documentfile.provider.RawDocumentFile",
+ "android.support.v4.provider.SelfDestructiveThread": "androidx.core.provider.SelfDestructiveThread",
+ "android.support.v4.provider.SingleDocumentFile": "androidx.documentfile.provider.SingleDocumentFile",
+ "android.support.v4.provider.TreeDocumentFile": "androidx.documentfile.provider.TreeDocumentFile",
+ "android.support.v4.text.BidiFormatter": "androidx.core.text.BidiFormatter",
+ "android.support.v4.text.HtmlCompat": "androidx.core.text.HtmlCompat",
+ "android.support.v4.text.ICUCompat": "androidx.core.text.ICUCompat",
+ "android.support.v4.text.PrecomputedTextCompat": "androidx.core.text.PrecomputedTextCompat",
+ "android.support.v4.text.TextDirectionHeuristicCompat": "androidx.core.text.TextDirectionHeuristicCompat",
+ "android.support.v4.text.TextDirectionHeuristicsCompat": "androidx.core.text.TextDirectionHeuristicsCompat",
+ "android.support.v4.text.TextUtilsCompat": "androidx.core.text.TextUtilsCompat",
+ "android.support.v4.text.util.FindAddress": "androidx.core.text.util.FindAddress",
+ "android.support.v4.text.util.LinkifyCompat": "androidx.core.text.util.LinkifyCompat",
+ "android.support.v4.util.ArrayMap": "androidx.collection.ArrayMap",
+ "android.support.v4.util.ArraySet": "androidx.collection.ArraySet",
+ "android.support.v4.util.AtomicFile": "androidx.core.util.AtomicFile",
+ "android.support.v4.util.CircularArray": "androidx.collection.CircularArray",
+ "android.support.v4.util.CircularIntArray": "androidx.collection.CircularIntArray",
+ "android.support.v4.util.Consumer": "androidx.core.util.Consumer",
+ "android.support.v4.util.ContainerHelpers": "androidx.collection.ContainerHelpers",
+ "android.support.v4.util.DebugUtils": "androidx.core.util.DebugUtils",
+ "android.support.v4.util.LogWriter": "androidx.core.util.LogWriter",
+ "android.support.v4.util.LongSparseArray": "androidx.collection.LongSparseArray",
+ "android.support.v4.util.LruCache": "androidx.collection.LruCache",
+ "android.support.v4.util.MapCollections": "androidx.collection.MapCollections",
+ "android.support.v4.util.ObjectsCompat": "androidx.core.util.ObjectsCompat",
+ "android.support.v4.util.Pair": "androidx.core.util.Pair",
+ "android.support.v4.util.PatternsCompat": "androidx.core.util.PatternsCompat",
+ "android.support.v4.util.Pools": "androidx.core.util.Pools",
+ "android.support.v4.util.Preconditions": "androidx.core.util.Preconditions",
+ "android.support.v4.util.SimpleArrayMap": "androidx.collection.SimpleArrayMap",
+ "android.support.v4.util.SparseArrayCompat": "androidx.collection.SparseArrayCompat",
+ "android.support.v4.util.TimeUtils": "androidx.core.util.TimeUtils",
+ "android.support.v4.view.AbsSavedState": "androidx.customview.view.AbsSavedState",
+ "android.support.v4.view.accessibility.AccessibilityEventCompat": "androidx.core.view.accessibility.AccessibilityEventCompat",
+ "android.support.v4.view.accessibility.AccessibilityManagerCompat": "androidx.core.view.accessibility.AccessibilityManagerCompat",
+ "android.support.v4.view.accessibility.AccessibilityNodeInfoCompat": "androidx.core.view.accessibility.AccessibilityNodeInfoCompat",
+ "android.support.v4.view.accessibility.AccessibilityNodeProviderCompat": "androidx.core.view.accessibility.AccessibilityNodeProviderCompat",
+ "android.support.v4.view.accessibility.AccessibilityRecordCompat": "androidx.core.view.accessibility.AccessibilityRecordCompat",
+ "android.support.v4.view.accessibility.AccessibilityWindowInfoCompat": "androidx.core.view.accessibility.AccessibilityWindowInfoCompat",
+ "android.support.v4.view.AccessibilityDelegateCompat": "androidx.core.view.AccessibilityDelegateCompat",
+ "android.support.v4.view.ActionProvider": "androidx.core.view.ActionProvider",
+ "android.support.v4.view.animation.FastOutLinearInInterpolator": "androidx.interpolator.view.animation.FastOutLinearInInterpolator",
+ "android.support.v4.view.animation.FastOutSlowInInterpolator": "androidx.interpolator.view.animation.FastOutSlowInInterpolator",
+ "android.support.v4.view.animation.LinearOutSlowInInterpolator": "androidx.interpolator.view.animation.LinearOutSlowInInterpolator",
+ "android.support.v4.view.animation.LookupTableInterpolator": "androidx.interpolator.view.animation.LookupTableInterpolator",
+ "android.support.v4.view.animation.PathInterpolatorApi14": "androidx.core.view.animation.PathInterpolatorApi14",
+ "android.support.v4.view.animation.PathInterpolatorCompat": "androidx.core.view.animation.PathInterpolatorCompat",
+ "android.support.v4.view.AsyncLayoutInflater": "androidx.asynclayoutinflater.view.AsyncLayoutInflater",
+ "android.support.v4.view.DisplayCutoutCompat": "androidx.core.view.DisplayCutoutCompat",
+ "android.support.v4.view.GestureDetectorCompat": "androidx.core.view.GestureDetectorCompat",
+ "android.support.v4.view.GravityCompat": "androidx.core.view.GravityCompat",
+ "android.support.v4.view.InputDeviceCompat": "androidx.core.view.InputDeviceCompat",
+ "android.support.v4.view.KeyEventDispatcher": "androidx.core.view.KeyEventDispatcher",
+ "android.support.v4.view.LayoutInflaterCompat": "androidx.core.view.LayoutInflaterCompat",
+ "android.support.v4.view.LayoutInflaterFactory": "androidx.core.view.LayoutInflaterFactory",
+ "android.support.v4.view.MarginLayoutParamsCompat": "androidx.core.view.MarginLayoutParamsCompat",
+ "android.support.v4.view.MenuCompat": "androidx.core.view.MenuCompat",
+ "android.support.v4.view.MenuItemCompat": "androidx.core.view.MenuItemCompat",
+ "android.support.v4.view.MotionEventCompat": "androidx.core.view.MotionEventCompat",
+ "android.support.v4.view.NestedScrollingChild2": "androidx.core.view.NestedScrollingChild2",
+ "android.support.v4.view.NestedScrollingChild": "androidx.core.view.NestedScrollingChild",
+ "android.support.v4.view.NestedScrollingChildHelper": "androidx.core.view.NestedScrollingChildHelper",
+ "android.support.v4.view.NestedScrollingParent2": "androidx.core.view.NestedScrollingParent2",
+ "android.support.v4.view.NestedScrollingParent": "androidx.core.view.NestedScrollingParent",
+ "android.support.v4.view.NestedScrollingParentHelper": "androidx.core.view.NestedScrollingParentHelper",
+ "android.support.v4.view.OnApplyWindowInsetsListener": "androidx.core.view.OnApplyWindowInsetsListener",
+ "android.support.v4.view.PagerAdapter": "androidx.viewpager.widget.PagerAdapter",
+ "android.support.v4.view.PagerTabStrip": "androidx.viewpager.widget.PagerTabStrip",
+ "android.support.v4.view.PagerTitleStrip": "androidx.viewpager.widget.PagerTitleStrip",
+ "android.support.v4.view.PointerIconCompat": "androidx.core.view.PointerIconCompat",
+ "android.support.v4.view.ScaleGestureDetectorCompat": "androidx.core.view.ScaleGestureDetectorCompat",
+ "android.support.v4.view.ScrollingView": "androidx.core.view.ScrollingView",
+ "android.support.v4.view.TintableBackgroundView": "androidx.core.view.TintableBackgroundView",
+ "android.support.v4.view.VelocityTrackerCompat": "androidx.core.view.VelocityTrackerCompat",
+ "android.support.v4.view.ViewCompat": "androidx.core.view.ViewCompat",
+ "android.support.v4.view.ViewConfigurationCompat": "androidx.core.view.ViewConfigurationCompat",
+ "android.support.v4.view.ViewGroupCompat": "androidx.core.view.ViewGroupCompat",
+ "android.support.v4.view.ViewPager": "androidx.viewpager.widget.ViewPager",
+ "android.support.v4.view.ViewParentCompat": "androidx.core.view.ViewParentCompat",
+ "android.support.v4.view.ViewPropertyAnimatorCompat": "androidx.core.view.ViewPropertyAnimatorCompat",
+ "android.support.v4.view.ViewPropertyAnimatorListener": "androidx.core.view.ViewPropertyAnimatorListener",
+ "android.support.v4.view.ViewPropertyAnimatorListenerAdapter": "androidx.core.view.ViewPropertyAnimatorListenerAdapter",
+ "android.support.v4.view.ViewPropertyAnimatorUpdateListener": "androidx.core.view.ViewPropertyAnimatorUpdateListener",
+ "android.support.v4.view.WindowCompat": "androidx.core.view.WindowCompat",
+ "android.support.v4.view.WindowInsetsCompat": "androidx.core.view.WindowInsetsCompat",
+ "android.support.v4.widget.AutoScrollHelper": "androidx.core.widget.AutoScrollHelper",
+ "android.support.v4.widget.AutoSizeableTextView": "androidx.core.widget.AutoSizeableTextView",
+ "android.support.v4.widget.CircleImageView": "androidx.swiperefreshlayout.widget.CircleImageView",
+ "android.support.v4.widget.CircularProgressDrawable": "androidx.swiperefreshlayout.widget.CircularProgressDrawable",
+ "android.support.v4.widget.CompoundButtonCompat": "androidx.core.widget.CompoundButtonCompat",
+ "android.support.v4.widget.ContentLoadingProgressBar": "androidx.core.widget.ContentLoadingProgressBar",
+ "android.support.v4.widget.CursorAdapter": "androidx.cursoradapter.widget.CursorAdapter",
+ "android.support.v4.widget.CursorFilter": "androidx.cursoradapter.widget.CursorFilter",
+ "android.support.v4.widget.DirectedAcyclicGraph": "androidx.coordinatorlayout.widget.DirectedAcyclicGraph",
+ "android.support.v4.widget.DrawerLayout": "androidx.drawerlayout.widget.DrawerLayout",
+ "android.support.v4.widget.EdgeEffectCompat": "androidx.core.widget.EdgeEffectCompat",
+ "android.support.v4.widget.ExploreByTouchHelper": "androidx.customview.widget.ExploreByTouchHelper",
+ "android.support.v4.widget.FocusStrategy": "androidx.customview.widget.FocusStrategy",
+ "android.support.v4.widget.ImageViewCompat": "androidx.core.widget.ImageViewCompat",
+ "android.support.v4.widget.ListPopupWindowCompat": "androidx.core.widget.ListPopupWindowCompat",
+ "android.support.v4.widget.ListViewAutoScrollHelper": "androidx.core.widget.ListViewAutoScrollHelper",
+ "android.support.v4.widget.ListViewCompat": "androidx.core.widget.ListViewCompat",
+ "android.support.v4.widget.NestedScrollView": "androidx.core.widget.NestedScrollView",
+ "android.support.v4.widget.PopupMenuCompat": "androidx.core.widget.PopupMenuCompat",
+ "android.support.v4.widget.PopupWindowCompat": "androidx.core.widget.PopupWindowCompat",
+ "android.support.v4.widget.ResourceCursorAdapter": "androidx.cursoradapter.widget.ResourceCursorAdapter",
+ "android.support.v4.widget.ScrollerCompat": "androidx.core.widget.ScrollerCompat",
+ "android.support.v4.widget.SimpleCursorAdapter": "androidx.cursoradapter.widget.SimpleCursorAdapter",
+ "android.support.v4.widget.SlidingPaneLayout": "androidx.slidingpanelayout.widget.SlidingPaneLayout",
+ "android.support.v4.widget.Space": "androidx.legacy.widget.Space",
+ "android.support.v4.widget.SwipeRefreshLayout": "androidx.swiperefreshlayout.widget.SwipeRefreshLayout",
+ "android.support.v4.widget.TextViewCompat": "androidx.core.widget.TextViewCompat",
+ "android.support.v4.widget.TintableCompoundButton": "androidx.core.widget.TintableCompoundButton",
+ "android.support.v4.widget.TintableImageSourceView": "androidx.core.widget.TintableImageSourceView",
+ "android.support.v4.widget.ViewDragHelper": "androidx.customview.widget.ViewDragHelper",
+ "android.support.v4.widget.ViewGroupUtils": "androidx.coordinatorlayout.widget.ViewGroupUtils",
+ "android.support.v7.app.ActionBar": "androidx.appcompat.app.ActionBar",
+ "android.support.v7.app.ActionBarDrawerToggle": "androidx.appcompat.app.ActionBarDrawerToggle",
+ "android.support.v7.app.ActionBarDrawerToggleHoneycomb": "androidx.appcompat.app.ActionBarDrawerToggleHoneycomb",
+ "android.support.v7.app.AlertController": "androidx.appcompat.app.AlertController",
+ "android.support.v7.app.AlertDialog": "androidx.appcompat.app.AlertDialog",
+ "android.support.v7.app.AppCompatActivity": "androidx.appcompat.app.AppCompatActivity",
+ "android.support.v7.app.AppCompatCallback": "androidx.appcompat.app.AppCompatCallback",
+ "android.support.v7.app.AppCompatDelegate": "androidx.appcompat.app.AppCompatDelegate",
+ "android.support.v7.app.AppCompatDelegateImpl": "androidx.appcompat.app.AppCompatDelegateImpl",
+ "android.support.v7.app.AppCompatDialog": "androidx.appcompat.app.AppCompatDialog",
+ "android.support.v7.app.AppCompatDialogFragment": "androidx.appcompat.app.AppCompatDialogFragment",
+ "android.support.v7.app.AppCompatViewInflater": "androidx.appcompat.app.AppCompatViewInflater",
+ "android.support.v7.app.MediaRouteActionProvider": "androidx.mediarouter.app.MediaRouteActionProvider",
+ "android.support.v7.app.MediaRouteButton": "androidx.mediarouter.app.MediaRouteButton",
+ "android.support.v7.app.MediaRouteCastDialog": "androidx.mediarouter.app.MediaRouteCastDialog",
+ "android.support.v7.app.MediaRouteChooserDialog": "androidx.mediarouter.app.MediaRouteChooserDialog",
+ "android.support.v7.app.MediaRouteChooserDialogFragment": "androidx.mediarouter.app.MediaRouteChooserDialogFragment",
+ "android.support.v7.app.MediaRouteControllerDialog": "androidx.mediarouter.app.MediaRouteControllerDialog",
+ "android.support.v7.app.MediaRouteControllerDialogFragment": "androidx.mediarouter.app.MediaRouteControllerDialogFragment",
+ "android.support.v7.app.MediaRouteDevicePickerDialog": "androidx.mediarouter.app.MediaRouteDevicePickerDialog",
+ "android.support.v7.app.MediaRouteDialogFactory": "androidx.mediarouter.app.MediaRouteDialogFactory",
+ "android.support.v7.app.MediaRouteDialogHelper": "androidx.mediarouter.app.MediaRouteDialogHelper",
+ "android.support.v7.app.MediaRouteDiscoveryFragment": "androidx.mediarouter.app.MediaRouteDiscoveryFragment",
+ "android.support.v7.app.MediaRouteExpandCollapseButton": "androidx.mediarouter.app.MediaRouteExpandCollapseButton",
+ "android.support.v7.app.MediaRouterThemeHelper": "androidx.mediarouter.app.MediaRouterThemeHelper",
+ "android.support.v7.app.MediaRouteVolumeSlider": "androidx.mediarouter.app.MediaRouteVolumeSlider",
+ "android.support.v7.app.NavItemSelectedListener": "androidx.appcompat.app.NavItemSelectedListener",
+ "android.support.v7.app.OverlayListView": "androidx.mediarouter.app.OverlayListView",
+ "android.support.v7.app.ResourcesFlusher": "androidx.appcompat.app.ResourcesFlusher",
+ "android.support.v7.app.ToolbarActionBar": "androidx.appcompat.app.ToolbarActionBar",
+ "android.support.v7.app.TwilightCalculator": "androidx.appcompat.app.TwilightCalculator",
+ "android.support.v7.app.TwilightManager": "androidx.appcompat.app.TwilightManager",
+ "android.support.v7.app.WindowDecorActionBar": "androidx.appcompat.app.WindowDecorActionBar",
+ "android.support.v7.appcompat.R": "androidx.appcompat.R",
+ "android.support.v7.cardview.R": "androidx.cardview.R",
+ "android.support.v7.content.res.AppCompatResources": "androidx.appcompat.content.res.AppCompatResources",
+ "android.support.v7.graphics.ColorCutQuantizer": "androidx.palette.graphics.ColorCutQuantizer",
+ "android.support.v7.graphics.drawable.AnimatedStateListDrawableCompat": "androidx.appcompat.graphics.drawable.AnimatedStateListDrawableCompat",
+ "android.support.v7.graphics.drawable.DrawableContainer": "androidx.appcompat.graphics.drawable.DrawableContainer",
+ "android.support.v7.graphics.drawable.DrawableWrapper": "androidx.appcompat.graphics.drawable.DrawableWrapper",
+ "android.support.v7.graphics.drawable.DrawerArrowDrawable": "androidx.appcompat.graphics.drawable.DrawerArrowDrawable",
+ "android.support.v7.graphics.drawable.StateListDrawable": "androidx.appcompat.graphics.drawable.StateListDrawable",
+ "android.support.v7.graphics.Palette": "androidx.palette.graphics.Palette",
+ "android.support.v7.graphics.Target": "androidx.palette.graphics.Target",
+ "android.support.v7.gridlayout.R": "androidx.gridlayout.R",
+ "android.support.v7.internal.widget.PreferenceImageView": "androidx.preference.internal.PreferenceImageView",
+ "android.support.v7.media.MediaControlIntent": "androidx.mediarouter.media.MediaControlIntent",
+ "android.support.v7.media.MediaItemMetadata": "androidx.mediarouter.media.MediaItemMetadata",
+ "android.support.v7.media.MediaItemStatus": "androidx.mediarouter.media.MediaItemStatus",
+ "android.support.v7.media.MediaRouteDescriptor": "androidx.mediarouter.media.MediaRouteDescriptor",
+ "android.support.v7.media.MediaRouteDiscoveryRequest": "androidx.mediarouter.media.MediaRouteDiscoveryRequest",
+ "android.support.v7.media.MediaRouteProvider": "androidx.mediarouter.media.MediaRouteProvider",
+ "android.support.v7.media.MediaRouteProviderDescriptor": "androidx.mediarouter.media.MediaRouteProviderDescriptor",
+ "android.support.v7.media.MediaRouteProviderProtocol": "androidx.mediarouter.media.MediaRouteProviderProtocol",
+ "android.support.v7.media.MediaRouteProviderService": "androidx.mediarouter.media.MediaRouteProviderService",
+ "android.support.v7.media.MediaRouter": "androidx.mediarouter.media.MediaRouter",
+ "android.support.v7.media.MediaRouterApi24": "androidx.mediarouter.media.MediaRouterApi24",
+ "android.support.v7.media.MediaRouterJellybean": "androidx.mediarouter.media.MediaRouterJellybean",
+ "android.support.v7.media.MediaRouterJellybeanMr1": "androidx.mediarouter.media.MediaRouterJellybeanMr1",
+ "android.support.v7.media.MediaRouterJellybeanMr2": "androidx.mediarouter.media.MediaRouterJellybeanMr2",
+ "android.support.v7.media.MediaRouteSelector": "androidx.mediarouter.media.MediaRouteSelector",
+ "android.support.v7.media.MediaSessionStatus": "androidx.mediarouter.media.MediaSessionStatus",
+ "android.support.v7.media.RegisteredMediaRouteProvider": "androidx.mediarouter.media.RegisteredMediaRouteProvider",
+ "android.support.v7.media.RegisteredMediaRouteProviderWatcher": "androidx.mediarouter.media.RegisteredMediaRouteProviderWatcher",
+ "android.support.v7.media.RemoteControlClientCompat": "androidx.mediarouter.media.RemoteControlClientCompat",
+ "android.support.v7.media.RemotePlaybackClient": "androidx.mediarouter.media.RemotePlaybackClient",
+ "android.support.v7.media.RouteMediaPlayerConnector": "androidx.mediarouter.media.RouteMediaPlayerConnector",
+ "android.support.v7.media.SystemMediaRouteProvider": "androidx.mediarouter.media.SystemMediaRouteProvider",
+ "android.support.v7.mediarouter.R": "androidx.mediarouter.R",
+ "android.support.v7.preference.AndroidResources": "androidx.preference.AndroidResources",
+ "android.support.v7.preference.CheckBoxPreference": "androidx.preference.CheckBoxPreference",
+ "android.support.v7.preference.CollapsiblePreferenceGroupController": "androidx.preference.CollapsiblePreferenceGroupController",
+ "android.support.v7.preference.DialogPreference": "androidx.preference.DialogPreference",
+ "android.support.v7.preference.DropDownPreference": "androidx.preference.DropDownPreference",
+ "android.support.v7.preference.EditTextPreference": "androidx.preference.EditTextPreference",
+ "android.support.v7.preference.EditTextPreferenceDialogFragmentCompat": "androidx.preference.EditTextPreferenceDialogFragmentCompat",
+ "android.support.v7.preference.internal.AbstractMultiSelectListPreference": "androidx.preference.internal.AbstractMultiSelectListPreference",
+ "android.support.v7.preference.ListPreference": "androidx.preference.ListPreference",
+ "android.support.v7.preference.ListPreferenceDialogFragmentCompat": "androidx.preference.ListPreferenceDialogFragmentCompat",
+ "android.support.v7.preference.MultiSelectListPreferenceDialogFragmentCompat": "androidx.preference.MultiSelectListPreferenceDialogFragmentCompat",
+ "android.support.v7.preference.Preference": "androidx.preference.Preference",
+ "android.support.v7.preference.PreferenceCategory": "androidx.preference.PreferenceCategory",
+ "android.support.v7.preference.PreferenceDataStore": "androidx.preference.PreferenceDataStore",
+ "android.support.v7.preference.PreferenceDialogFragmentCompat": "androidx.preference.PreferenceDialogFragmentCompat",
+ "android.support.v7.preference.PreferenceFragmentCompat": "androidx.preference.PreferenceFragmentCompat",
+ "android.support.v7.preference.PreferenceGroup": "androidx.preference.PreferenceGroup",
+ "android.support.v7.preference.PreferenceGroupAdapter": "androidx.preference.PreferenceGroupAdapter",
+ "android.support.v7.preference.PreferenceInflater": "androidx.preference.PreferenceInflater",
+ "android.support.v7.preference.PreferenceManager": "androidx.preference.PreferenceManager",
+ "android.support.v7.preference.PreferenceRecyclerViewAccessibilityDelegate": "androidx.preference.PreferenceRecyclerViewAccessibilityDelegate",
+ "android.support.v7.preference.PreferenceScreen": "androidx.preference.PreferenceScreen",
+ "android.support.v7.preference.PreferenceViewHolder": "androidx.preference.PreferenceViewHolder",
+ "android.support.v7.preference.R": "androidx.preference.R",
+ "android.support.v7.preference.SeekBarPreference": "androidx.preference.SeekBarPreference",
+ "android.support.v7.preference.SwitchPreferenceCompat": "androidx.preference.SwitchPreferenceCompat",
+ "android.support.v7.preference.TwoStatePreference": "androidx.preference.TwoStatePreference",
+ "android.support.v7.preference.UnPressableLinearLayout": "androidx.preference.UnPressableLinearLayout",
+ "android.support.v7.recyclerview.extensions.AsyncDifferConfig": "androidx.recyclerview.widget.AsyncDifferConfig",
+ "android.support.v7.recyclerview.extensions.AsyncListDiffer": "androidx.recyclerview.widget.AsyncListDiffer",
+ "android.support.v7.recyclerview.extensions.ListAdapter": "androidx.recyclerview.widget.ListAdapter",
+ "android.support.v7.recyclerview.R": "androidx.recyclerview.R",
+ "android.support.v7.text.AllCapsTransformationMethod": "androidx.appcompat.text.AllCapsTransformationMethod",
+ "android.support.v7.util.AdapterListUpdateCallback": "androidx.recyclerview.widget.AdapterListUpdateCallback",
+ "android.support.v7.util.AsyncListUtil": "androidx.recyclerview.widget.AsyncListUtil",
+ "android.support.v7.util.BatchingListUpdateCallback": "androidx.recyclerview.widget.BatchingListUpdateCallback",
+ "android.support.v7.util.DiffUtil": "androidx.recyclerview.widget.DiffUtil",
+ "android.support.v7.util.ListUpdateCallback": "androidx.recyclerview.widget.ListUpdateCallback",
+ "android.support.v7.util.MessageThreadUtil": "androidx.recyclerview.widget.MessageThreadUtil",
+ "android.support.v7.util.SortedList": "androidx.recyclerview.widget.SortedList",
+ "android.support.v7.util.ThreadUtil": "androidx.recyclerview.widget.ThreadUtil",
+ "android.support.v7.util.TileList": "androidx.recyclerview.widget.TileList",
+ "android.support.v7.view.ActionBarPolicy": "androidx.appcompat.view.ActionBarPolicy",
+ "android.support.v7.view.ActionMode": "androidx.appcompat.view.ActionMode",
+ "android.support.v7.view.CollapsibleActionView": "androidx.appcompat.view.CollapsibleActionView",
+ "android.support.v7.view.ContextThemeWrapper": "androidx.appcompat.view.ContextThemeWrapper",
+ "android.support.v7.view.menu.ActionMenuItem": "androidx.appcompat.view.menu.ActionMenuItem",
+ "android.support.v7.view.menu.ActionMenuItemView": "androidx.appcompat.view.menu.ActionMenuItemView",
+ "android.support.v7.view.menu.BaseMenuPresenter": "androidx.appcompat.view.menu.BaseMenuPresenter",
+ "android.support.v7.view.menu.BaseMenuWrapper": "androidx.appcompat.view.menu.BaseMenuWrapper",
+ "android.support.v7.view.menu.BaseWrapper": "androidx.appcompat.view.menu.BaseWrapper",
+ "android.support.v7.view.menu.CascadingMenuPopup": "androidx.appcompat.view.menu.CascadingMenuPopup",
+ "android.support.v7.view.menu.ExpandedMenuView": "androidx.appcompat.view.menu.ExpandedMenuView",
+ "android.support.v7.view.menu.ListMenuItemView": "androidx.appcompat.view.menu.ListMenuItemView",
+ "android.support.v7.view.menu.ListMenuPresenter": "androidx.appcompat.view.menu.ListMenuPresenter",
+ "android.support.v7.view.menu.MenuAdapter": "androidx.appcompat.view.menu.MenuAdapter",
+ "android.support.v7.view.menu.MenuBuilder": "androidx.appcompat.view.menu.MenuBuilder",
+ "android.support.v7.view.menu.MenuDialogHelper": "androidx.appcompat.view.menu.MenuDialogHelper",
+ "android.support.v7.view.menu.MenuHelper": "androidx.appcompat.view.menu.MenuHelper",
+ "android.support.v7.view.menu.MenuItemImpl": "androidx.appcompat.view.menu.MenuItemImpl",
+ "android.support.v7.view.menu.MenuItemWrapperICS": "androidx.appcompat.view.menu.MenuItemWrapperICS",
+ "android.support.v7.view.menu.MenuItemWrapperJB": "androidx.appcompat.view.menu.MenuItemWrapperJB",
+ "android.support.v7.view.menu.MenuPopup": "androidx.appcompat.view.menu.MenuPopup",
+ "android.support.v7.view.menu.MenuPopupHelper": "androidx.appcompat.view.menu.MenuPopupHelper",
+ "android.support.v7.view.menu.MenuPresenter": "androidx.appcompat.view.menu.MenuPresenter",
+ "android.support.v7.view.menu.MenuView": "androidx.appcompat.view.menu.MenuView",
+ "android.support.v7.view.menu.MenuWrapperFactory": "androidx.appcompat.view.menu.MenuWrapperFactory",
+ "android.support.v7.view.menu.MenuWrapperICS": "androidx.appcompat.view.menu.MenuWrapperICS",
+ "android.support.v7.view.menu.ShowableListMenu": "androidx.appcompat.view.menu.ShowableListMenu",
+ "android.support.v7.view.menu.StandardMenuPopup": "androidx.appcompat.view.menu.StandardMenuPopup",
+ "android.support.v7.view.menu.SubMenuBuilder": "androidx.appcompat.view.menu.SubMenuBuilder",
+ "android.support.v7.view.menu.SubMenuWrapperICS": "androidx.appcompat.view.menu.SubMenuWrapperICS",
+ "android.support.v7.view.StandaloneActionMode": "androidx.appcompat.view.StandaloneActionMode",
+ "android.support.v7.view.SupportActionModeWrapper": "androidx.appcompat.view.SupportActionModeWrapper",
+ "android.support.v7.view.SupportMenuInflater": "androidx.appcompat.view.SupportMenuInflater",
+ "android.support.v7.view.ViewPropertyAnimatorCompatSet": "androidx.appcompat.view.ViewPropertyAnimatorCompatSet",
+ "android.support.v7.view.WindowCallbackWrapper": "androidx.appcompat.view.WindowCallbackWrapper",
+ "android.support.v7.widget.AbsActionBarView": "androidx.appcompat.widget.AbsActionBarView",
+ "android.support.v7.widget.ActionBarBackgroundDrawable": "androidx.appcompat.widget.ActionBarBackgroundDrawable",
+ "android.support.v7.widget.ActionBarContainer": "androidx.appcompat.widget.ActionBarContainer",
+ "android.support.v7.widget.ActionBarContextView": "androidx.appcompat.widget.ActionBarContextView",
+ "android.support.v7.widget.ActionBarOverlayLayout": "androidx.appcompat.widget.ActionBarOverlayLayout",
+ "android.support.v7.widget.ActionMenuPresenter": "androidx.appcompat.widget.ActionMenuPresenter",
+ "android.support.v7.widget.ActionMenuView": "androidx.appcompat.widget.ActionMenuView",
+ "android.support.v7.widget.ActivityChooserModel": "androidx.appcompat.widget.ActivityChooserModel",
+ "android.support.v7.widget.ActivityChooserView": "androidx.appcompat.widget.ActivityChooserView",
+ "android.support.v7.widget.AdapterHelper": "androidx.recyclerview.widget.AdapterHelper",
+ "android.support.v7.widget.AlertDialogLayout": "androidx.appcompat.widget.AlertDialogLayout",
+ "android.support.v7.widget.AppCompatAutoCompleteTextView": "androidx.appcompat.widget.AppCompatAutoCompleteTextView",
+ "android.support.v7.widget.AppCompatBackgroundHelper": "androidx.appcompat.widget.AppCompatBackgroundHelper",
+ "android.support.v7.widget.AppCompatButton": "androidx.appcompat.widget.AppCompatButton",
+ "android.support.v7.widget.AppCompatCheckBox": "androidx.appcompat.widget.AppCompatCheckBox",
+ "android.support.v7.widget.AppCompatCheckedTextView": "androidx.appcompat.widget.AppCompatCheckedTextView",
+ "android.support.v7.widget.AppCompatCompoundButtonHelper": "androidx.appcompat.widget.AppCompatCompoundButtonHelper",
+ "android.support.v7.widget.AppCompatDrawableManager": "androidx.appcompat.widget.AppCompatDrawableManager",
+ "android.support.v7.widget.AppCompatEditText": "androidx.appcompat.widget.AppCompatEditText",
+ "android.support.v7.widget.AppCompatHintHelper": "androidx.appcompat.widget.AppCompatHintHelper",
+ "android.support.v7.widget.AppCompatImageButton": "androidx.appcompat.widget.AppCompatImageButton",
+ "android.support.v7.widget.AppCompatImageHelper": "androidx.appcompat.widget.AppCompatImageHelper",
+ "android.support.v7.widget.AppCompatImageView": "androidx.appcompat.widget.AppCompatImageView",
+ "android.support.v7.widget.AppCompatMultiAutoCompleteTextView": "androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView",
+ "android.support.v7.widget.AppCompatPopupWindow": "androidx.appcompat.widget.AppCompatPopupWindow",
+ "android.support.v7.widget.AppCompatProgressBarHelper": "androidx.appcompat.widget.AppCompatProgressBarHelper",
+ "android.support.v7.widget.AppCompatRadioButton": "androidx.appcompat.widget.AppCompatRadioButton",
+ "android.support.v7.widget.AppCompatRatingBar": "androidx.appcompat.widget.AppCompatRatingBar",
+ "android.support.v7.widget.AppCompatSeekBar": "androidx.appcompat.widget.AppCompatSeekBar",
+ "android.support.v7.widget.AppCompatSeekBarHelper": "androidx.appcompat.widget.AppCompatSeekBarHelper",
+ "android.support.v7.widget.AppCompatSpinner": "androidx.appcompat.widget.AppCompatSpinner",
+ "android.support.v7.widget.AppCompatTextHelper": "androidx.appcompat.widget.AppCompatTextHelper",
+ "android.support.v7.widget.AppCompatTextView": "androidx.appcompat.widget.AppCompatTextView",
+ "android.support.v7.widget.AppCompatTextViewAutoSizeHelper": "androidx.appcompat.widget.AppCompatTextViewAutoSizeHelper",
+ "android.support.v7.widget.ButtonBarLayout": "androidx.appcompat.widget.ButtonBarLayout",
+ "android.support.v7.widget.CardView": "androidx.cardview.widget.CardView",
+ "android.support.v7.widget.CardViewApi17Impl": "androidx.cardview.widget.CardViewApi17Impl",
+ "android.support.v7.widget.CardViewApi21Impl": "androidx.cardview.widget.CardViewApi21Impl",
+ "android.support.v7.widget.CardViewBaseImpl": "androidx.cardview.widget.CardViewBaseImpl",
+ "android.support.v7.widget.CardViewDelegate": "androidx.cardview.widget.CardViewDelegate",
+ "android.support.v7.widget.CardViewImpl": "androidx.cardview.widget.CardViewImpl",
+ "android.support.v7.widget.ChildHelper": "androidx.recyclerview.widget.ChildHelper",
+ "android.support.v7.widget.ContentFrameLayout": "androidx.appcompat.widget.ContentFrameLayout",
+ "android.support.v7.widget.DecorContentParent": "androidx.appcompat.widget.DecorContentParent",
+ "android.support.v7.widget.DecorToolbar": "androidx.appcompat.widget.DecorToolbar",
+ "android.support.v7.widget.DefaultItemAnimator": "androidx.recyclerview.widget.DefaultItemAnimator",
+ "android.support.v7.widget.DialogTitle": "androidx.appcompat.widget.DialogTitle",
+ "android.support.v7.widget.DividerItemDecoration": "androidx.recyclerview.widget.DividerItemDecoration",
+ "android.support.v7.widget.DrawableUtils": "androidx.appcompat.widget.DrawableUtils",
+ "android.support.v7.widget.DropDownListView": "androidx.appcompat.widget.DropDownListView",
+ "android.support.v7.widget.FastScroller": "androidx.recyclerview.widget.FastScroller",
+ "android.support.v7.widget.FitWindowsFrameLayout": "androidx.appcompat.widget.FitWindowsFrameLayout",
+ "android.support.v7.widget.FitWindowsLinearLayout": "androidx.appcompat.widget.FitWindowsLinearLayout",
+ "android.support.v7.widget.FitWindowsViewGroup": "androidx.appcompat.widget.FitWindowsViewGroup",
+ "android.support.v7.widget.ForwardingListener": "androidx.appcompat.widget.ForwardingListener",
+ "android.support.v7.widget.GapWorker": "androidx.recyclerview.widget.GapWorker",
+ "android.support.v7.widget.GridLayout": "androidx.gridlayout.widget.GridLayout",
+ "android.support.v7.widget.GridLayoutManager": "androidx.recyclerview.widget.GridLayoutManager",
+ "android.support.v7.widget.helper.ItemTouchHelper": "androidx.recyclerview.widget.ItemTouchHelper",
+ "android.support.v7.widget.helper.ItemTouchUIUtil": "androidx.recyclerview.widget.ItemTouchUIUtil",
+ "android.support.v7.widget.helper.ItemTouchUIUtilImpl": "androidx.recyclerview.widget.ItemTouchUIUtilImpl",
+ "android.support.v7.widget.LayoutState": "androidx.recyclerview.widget.LayoutState",
+ "android.support.v7.widget.LinearLayoutCompat": "androidx.appcompat.widget.LinearLayoutCompat",
+ "android.support.v7.widget.LinearLayoutManager": "androidx.recyclerview.widget.LinearLayoutManager",
+ "android.support.v7.widget.LinearSmoothScroller": "androidx.recyclerview.widget.LinearSmoothScroller",
+ "android.support.v7.widget.LinearSnapHelper": "androidx.recyclerview.widget.LinearSnapHelper",
+ "android.support.v7.widget.ListPopupWindow": "androidx.appcompat.widget.ListPopupWindow",
+ "android.support.v7.widget.MenuItemHoverListener": "androidx.appcompat.widget.MenuItemHoverListener",
+ "android.support.v7.widget.MenuPopupWindow": "androidx.appcompat.widget.MenuPopupWindow",
+ "android.support.v7.widget.OpReorderer": "androidx.recyclerview.widget.OpReorderer",
+ "android.support.v7.widget.OrientationHelper": "androidx.recyclerview.widget.OrientationHelper",
+ "android.support.v7.widget.PagerSnapHelper": "androidx.recyclerview.widget.PagerSnapHelper",
+ "android.support.v7.widget.PopupMenu": "androidx.appcompat.widget.PopupMenu",
+ "android.support.v7.widget.RecyclerView": "androidx.recyclerview.widget.RecyclerView",
+ "android.support.v7.widget.RecyclerViewAccessibilityDelegate": "androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate",
+ "android.support.v7.widget.ResourcesWrapper": "androidx.appcompat.widget.ResourcesWrapper",
+ "android.support.v7.widget.RoundRectDrawable": "androidx.cardview.widget.RoundRectDrawable",
+ "android.support.v7.widget.RoundRectDrawableWithShadow": "androidx.cardview.widget.RoundRectDrawableWithShadow",
+ "android.support.v7.widget.RtlSpacingHelper": "androidx.appcompat.widget.RtlSpacingHelper",
+ "android.support.v7.widget.ScrollbarHelper": "androidx.recyclerview.widget.ScrollbarHelper",
+ "android.support.v7.widget.ScrollingTabContainerView": "androidx.appcompat.widget.ScrollingTabContainerView",
+ "android.support.v7.widget.SearchView": "androidx.appcompat.widget.SearchView",
+ "android.support.v7.widget.ShareActionProvider": "androidx.appcompat.widget.ShareActionProvider",
+ "android.support.v7.widget.SimpleItemAnimator": "androidx.recyclerview.widget.SimpleItemAnimator",
+ "android.support.v7.widget.SnapHelper": "androidx.recyclerview.widget.SnapHelper",
+ "android.support.v7.widget.StaggeredGridLayoutManager": "androidx.recyclerview.widget.StaggeredGridLayoutManager",
+ "android.support.v7.widget.SuggestionsAdapter": "androidx.appcompat.widget.SuggestionsAdapter",
+ "android.support.v7.widget.SwitchCompat": "androidx.appcompat.widget.SwitchCompat",
+ "android.support.v7.widget.ThemedSpinnerAdapter": "androidx.appcompat.widget.ThemedSpinnerAdapter",
+ "android.support.v7.widget.ThemeUtils": "androidx.appcompat.widget.ThemeUtils",
+ "android.support.v7.widget.TintContextWrapper": "androidx.appcompat.widget.TintContextWrapper",
+ "android.support.v7.widget.TintInfo": "androidx.appcompat.widget.TintInfo",
+ "android.support.v7.widget.TintResources": "androidx.appcompat.widget.TintResources",
+ "android.support.v7.widget.TintTypedArray": "androidx.appcompat.widget.TintTypedArray",
+ "android.support.v7.widget.Toolbar": "androidx.appcompat.widget.Toolbar",
+ "android.support.v7.widget.ToolbarWidgetWrapper": "androidx.appcompat.widget.ToolbarWidgetWrapper",
+ "android.support.v7.widget.TooltipCompat": "androidx.appcompat.widget.TooltipCompat",
+ "android.support.v7.widget.TooltipCompatHandler": "androidx.appcompat.widget.TooltipCompatHandler",
+ "android.support.v7.widget.TooltipPopup": "androidx.appcompat.widget.TooltipPopup",
+ "android.support.v7.widget.util.SortedListAdapterCallback": "androidx.recyclerview.widget.SortedListAdapterCallback",
+ "android.support.v7.widget.VectorEnabledTintResources": "androidx.appcompat.widget.VectorEnabledTintResources",
+ "android.support.v7.widget.ViewBoundsCheck": "androidx.recyclerview.widget.ViewBoundsCheck",
+ "android.support.v7.widget.ViewInfoStore": "androidx.recyclerview.widget.ViewInfoStore",
+ "android.support.v7.widget.ViewStubCompat": "androidx.appcompat.widget.ViewStubCompat",
+ "android.support.v7.widget.ViewUtils": "androidx.appcompat.widget.ViewUtils",
+ "android.support.v7.widget.WithHint": "androidx.appcompat.widget.WithHint",
+ "android.support.wear.activity.ConfirmationActivity": "androidx.wear.activity.ConfirmationActivity",
+ "android.support.wear.ambient.AmbientDelegate": "androidx.wear.ambient.AmbientDelegate",
+ "android.support.wear.ambient.AmbientMode": "androidx.wear.ambient.AmbientMode",
+ "android.support.wear.ambient.AmbientModeSupport": "androidx.wear.ambient.AmbientModeSupport",
+ "android.support.wear.ambient.SharedLibraryVersion": "androidx.wear.ambient.SharedLibraryVersion",
+ "android.support.wear.ambient.WearableControllerProvider": "androidx.wear.ambient.WearableControllerProvider",
+ "android.support.wear.internal.widget.drawer.MultiPagePresenter": "androidx.wear.internal.widget.drawer.MultiPagePresenter",
+ "android.support.wear.internal.widget.drawer.MultiPageUi": "androidx.wear.internal.widget.drawer.MultiPageUi",
+ "android.support.wear.internal.widget.drawer.SinglePagePresenter": "androidx.wear.internal.widget.drawer.SinglePagePresenter",
+ "android.support.wear.internal.widget.drawer.SinglePageUi": "androidx.wear.internal.widget.drawer.SinglePageUi",
+ "android.support.wear.internal.widget.drawer.WearableNavigationDrawerPresenter": "androidx.wear.internal.widget.drawer.WearableNavigationDrawerPresenter",
+ "android.support.wear.internal.widget.ResourcesUtil": "androidx.wear.internal.widget.ResourcesUtil",
+ "android.support.wear.R": "androidx.wear.R",
+ "android.support.wear.utils.MetadataConstants": "androidx.wear.utils.MetadataConstants",
+ "android.support.wear.widget.BezierSCurveInterpolator": "androidx.wear.widget.BezierSCurveInterpolator",
+ "android.support.wear.widget.BoxInsetLayout": "androidx.wear.widget.BoxInsetLayout",
+ "android.support.wear.widget.CircledImageView": "androidx.wear.widget.CircledImageView",
+ "android.support.wear.widget.CircularProgressLayout": "androidx.wear.widget.CircularProgressLayout",
+ "android.support.wear.widget.CircularProgressLayoutController": "androidx.wear.widget.CircularProgressLayoutController",
+ "android.support.wear.widget.ConfirmationOverlay": "androidx.wear.widget.ConfirmationOverlay",
+ "android.support.wear.widget.CurvingLayoutCallback": "androidx.wear.widget.CurvingLayoutCallback",
+ "android.support.wear.widget.drawer.AbsListViewFlingWatcher": "androidx.wear.widget.drawer.AbsListViewFlingWatcher",
+ "android.support.wear.widget.drawer.FlingWatcherFactory": "androidx.wear.widget.drawer.FlingWatcherFactory",
+ "android.support.wear.widget.drawer.NestedScrollViewFlingWatcher": "androidx.wear.widget.drawer.NestedScrollViewFlingWatcher",
+ "android.support.wear.widget.drawer.PageIndicatorView": "androidx.wear.widget.drawer.PageIndicatorView",
+ "android.support.wear.widget.drawer.RecyclerViewFlingWatcher": "androidx.wear.widget.drawer.RecyclerViewFlingWatcher",
+ "android.support.wear.widget.drawer.ScrollViewFlingWatcher": "androidx.wear.widget.drawer.ScrollViewFlingWatcher",
+ "android.support.wear.widget.drawer.WearableActionDrawerMenu": "androidx.wear.widget.drawer.WearableActionDrawerMenu",
+ "android.support.wear.widget.drawer.WearableActionDrawerView": "androidx.wear.widget.drawer.WearableActionDrawerView",
+ "android.support.wear.widget.drawer.WearableDrawerController": "androidx.wear.widget.drawer.WearableDrawerController",
+ "android.support.wear.widget.drawer.WearableDrawerLayout": "androidx.wear.widget.drawer.WearableDrawerLayout",
+ "android.support.wear.widget.drawer.WearableDrawerView": "androidx.wear.widget.drawer.WearableDrawerView",
+ "android.support.wear.widget.drawer.WearableNavigationDrawerView": "androidx.wear.widget.drawer.WearableNavigationDrawerView",
+ "android.support.wear.widget.ProgressDrawable": "androidx.wear.widget.ProgressDrawable",
+ "android.support.wear.widget.ResourcesUtil": "androidx.wear.widget.ResourcesUtil",
+ "android.support.wear.widget.RoundedDrawable": "androidx.wear.widget.RoundedDrawable",
+ "android.support.wear.widget.ScrollManager": "androidx.wear.widget.ScrollManager",
+ "android.support.wear.widget.SimpleAnimatorListener": "androidx.wear.widget.SimpleAnimatorListener",
+ "android.support.wear.widget.SwipeDismissFrameLayout": "androidx.wear.widget.SwipeDismissFrameLayout",
+ "android.support.wear.widget.SwipeDismissLayout": "androidx.wear.widget.SwipeDismissLayout",
+ "android.support.wear.widget.WearableLinearLayoutManager": "androidx.wear.widget.WearableLinearLayoutManager",
+ "android.support.wear.widget.WearableRecyclerView": "androidx.wear.widget.WearableRecyclerView"
+}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-androidx-adapter/package.json b/StoneIsland/plugins/cordova-plugin-androidx-adapter/package.json new file mode 100644 index 00000000..5e4f1441 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx-adapter/package.json @@ -0,0 +1,41 @@ +{ + "_from": "cordova-plugin-androidx-adapter@^1.1.1", + "_id": "cordova-plugin-androidx-adapter@1.1.1", + "_inBundle": false, + "_integrity": "sha512-ePt0WG7Y8jOFx2x3A6oXQyxzavis2ANw2hFlm7MU/H7ez1QKPXmWjA1zIIx4T/QdKWM5D8fLH60t2PyJmKSsOg==", + "_location": "/cordova-plugin-androidx-adapter", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "cordova-plugin-androidx-adapter@^1.1.1", + "name": "cordova-plugin-androidx-adapter", + "escapedName": "cordova-plugin-androidx-adapter", + "rawSpec": "^1.1.1", + "saveSpec": null, + "fetchSpec": "^1.1.1" + }, + "_requiredBy": [ + "#DEV:/", + "#USER" + ], + "_resolved": "https://registry.npmjs.org/cordova-plugin-androidx-adapter/-/cordova-plugin-androidx-adapter-1.1.1.tgz", + "_shasum": "67c1553b4358a54827b5930d2590569749ad0f47", + "_spec": "cordova-plugin-androidx-adapter@^1.1.1", + "_where": "/Users/user/work/stone-island/StoneIsland", + "author": { + "name": "Dave Alden" + }, + "bundleDependencies": false, + "dependencies": { + "performance-now": "^2.1.0", + "q": "^1.4.1", + "recursive-readdir": "^2.2.2" + }, + "deprecated": false, + "description": "Cordova/Phonegap plugin to migrate any code which references the legacy Android Support Library to the new AndroidX mappings in a Cordova Android platform project.", + "devDependencies": {}, + "license": "MIT", + "name": "cordova-plugin-androidx-adapter", + "version": "1.1.1" +} diff --git a/StoneIsland/plugins/cordova-plugin-androidx-adapter/plugin.xml b/StoneIsland/plugins/cordova-plugin-androidx-adapter/plugin.xml new file mode 100644 index 00000000..9b00b7ed --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx-adapter/plugin.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" + xmlns:android="http://schemas.android.com/apk/res/android" + id="cordova-plugin-androidx-adapter" + version="1.1.1"> + + <name>cordova-plugin-androidx-adapter</name> + <description>Cordova/Phonegap plugin to migrate any code which references the legacy Android Support Library to the new AndroidX mappings in a Cordova Android platform project.</description> + <author>Dave Alden</author> + + <engines> + <engine name="cordova" version=">=8.0.0" /> + <engine name="cordova-android" version=">=8.0.0" /> + </engines> + + <platform name="android"> + <hook type="after_prepare" src="apply.js" /> + </platform> + +</plugin> diff --git a/StoneIsland/plugins/cordova-plugin-androidx/README.md b/StoneIsland/plugins/cordova-plugin-androidx/README.md new file mode 100644 index 00000000..d830b246 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx/README.md @@ -0,0 +1,55 @@ +cordova-plugin-androidx +======================= + +This Cordova/Phonegap plugin enables AndroidX in a Cordova project ([AndroidX](https://developer.android.com/jetpack/androidx/migrate) is the successor to the [Android Support Library](https://developer.android.com/topic/libraries/support-library/index)). + +This plugin is useful if your project contains plugins which have migrated to AndroidX or if you otherwise want to enable AndroidX in your Cordova Android platform project. + +<!-- DONATE --> +[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZRD3W47HQ3EMJ) + +I dedicate a considerable amount of my free time to developing and maintaining this Cordova plugin, along with my other Open Source software. +To help ensure this plugin is kept updated, new features are added and bugfixes are implemented quickly, please donate a couple of dollars (or a little more if you can stretch) as this will help me to afford to dedicate time to its maintenance. Please consider donating if you're using this plugin in an app that makes you money, if you're being paid to make the app, if you're asking for new features or priority bug fixes. +<!-- END DONATE --> + + +# Requirements + +This plugin requires a minimum of [`cordova@8`](https://github.com/apache/cordova-cli) and [`cordova-android@8`](https://github.com/apache/cordova-android). + +# Installation + + $ cordova plugin add cordova-plugin-androidx + +**IMPORTANT:** This plugin relies on [Cordova hook scripts](https://cordova.apache.org/docs/en/latest/guide/appdev/hooks/) so will not work in Cloud Build environments such as Phonegap Build which do not support Cordova hook scripts. + +# Usage + +Once the plugin is installed it will persistently enable AndroidX by editing the `gradle.properties` file in your Cordova Android platform project. + +If you encounter build failures after installing this plugin (or after manually enabling AndroidX) try installing [cordova-plugin-androidx-adapter](https://github.com/dpa99c/cordova-plugin-androidx-adapter) into your Cordova project; it will migrate any references to the legacy Android Support library in the Gradle config or Java source to use the new AndroidX mappings which should resolve build failures due to referencing legacy Support Library assets. + +License +================ + +The MIT License + +Copyright (c) 2019 Dave Alden / Working Edge Ltd. + +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/StoneIsland/plugins/cordova-plugin-androidx/package.json b/StoneIsland/plugins/cordova-plugin-androidx/package.json new file mode 100644 index 00000000..598c1639 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx/package.json @@ -0,0 +1,45 @@ +{ + "_from": "cordova-plugin-androidx@^2.0.0", + "_id": "cordova-plugin-androidx@2.0.0", + "_inBundle": false, + "_integrity": "sha512-n5QA1LJ/wT9qpDCHAw2GwqVXVlEajRPnDH5CKZGpv90M1FYVMydYlFwCEbpp263e5I5QloPjyoyWagiKLB+JMg==", + "_location": "/cordova-plugin-androidx", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "cordova-plugin-androidx@^2.0.0", + "name": "cordova-plugin-androidx", + "escapedName": "cordova-plugin-androidx", + "rawSpec": "^2.0.0", + "saveSpec": null, + "fetchSpec": "^2.0.0" + }, + "_requiredBy": [ + "#DEV:/", + "#USER" + ], + "_resolved": "https://registry.npmjs.org/cordova-plugin-androidx/-/cordova-plugin-androidx-2.0.0.tgz", + "_shasum": "ac7bd51ba0ae42dbfe4090a3cd4b8fac32f35ad1", + "_spec": "cordova-plugin-androidx@^2.0.0", + "_where": "/Users/user/work/stone-island/StoneIsland", + "author": { + "name": "Dave Alden" + }, + "bugs": { + "url": "https://github.com/dpa99c/cordova-plugin-androidx/issues" + }, + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "Cordova/Phonegap plugin to enable AndroidX", + "devDependencies": {}, + "homepage": "https://github.com/dpa99c/cordova-plugin-androidx#readme", + "license": "MIT", + "name": "cordova-plugin-androidx", + "repository": { + "type": "git", + "url": "git+https://github.com/dpa99c/cordova-plugin-androidx.git" + }, + "version": "2.0.0" +} diff --git a/StoneIsland/plugins/cordova-plugin-androidx/plugin.xml b/StoneIsland/plugins/cordova-plugin-androidx/plugin.xml new file mode 100644 index 00000000..4676a460 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx/plugin.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" + xmlns:android="http://schemas.android.com/apk/res/android" + id="cordova-plugin-androidx" + version="2.0.0"> + + <name>cordova-plugin-androidx</name> + <description>Cordova/Phonegap plugin to enable AndroidX</description> + <author>Dave Alden</author> + + <engines> + <engine name="cordova" version=">=8.0.0" /> + <engine name="cordova-android" version=">=8.0.0" /> + </engines> + + <platform name="android"> + <hook type="after_prepare" src="scripts/apply-to-gradle.properties.js" /> + </platform> + +</plugin> diff --git a/StoneIsland/plugins/cordova-plugin-androidx/scripts/apply-to-gradle.properties.js b/StoneIsland/plugins/cordova-plugin-androidx/scripts/apply-to-gradle.properties.js new file mode 100644 index 00000000..4ba3bca7 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-androidx/scripts/apply-to-gradle.properties.js @@ -0,0 +1,49 @@ +const fs = require('fs'); + +const PLUGIN_NAME = "cordova-plugin-androidx"; +const enableAndroidX = "android.useAndroidX=true"; +const enableJetifier = "android.enableJetifier=true"; +const gradlePropertiesPath = "./platforms/android/gradle.properties"; + +function log(message) { + console.log(PLUGIN_NAME + ": " + message); +} + +function onError(error) { + log("ERROR: " + error); +} + +function run() { + let gradleProperties = fs.readFileSync(gradlePropertiesPath); + + if (gradleProperties) { + let updatedGradleProperties = false; + gradleProperties = gradleProperties.toString(); + if (!gradleProperties.match(enableAndroidX)) { + gradleProperties += "\n" + enableAndroidX; + updatedGradleProperties = true; + } + if (!gradleProperties.match(enableJetifier)) { + gradleProperties += "\n" + enableJetifier; + updatedGradleProperties = true; + } + if (updatedGradleProperties) { + fs.writeFileSync(gradlePropertiesPath, gradleProperties, 'utf8'); + log("Updated gradle.properties to enable AndroidX"); + } + } else { + log("gradle.properties file not found!") + } +} + +module.exports = function () { + return new Promise((resolve, reject) => { + try { + run(); + resolve(); + } catch (e) { + onError("EXCEPTION: " + e.toString()); + reject(e); + } + }); +}; diff --git a/StoneIsland/plugins/cordova-plugin-compat/README.md b/StoneIsland/plugins/cordova-plugin-compat/README.md deleted file mode 100644 index 095c384b..00000000 --- a/StoneIsland/plugins/cordova-plugin-compat/README.md +++ /dev/null @@ -1,31 +0,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. -# ---> - -cordova-plugin-compat ------------------------- - -This repo is for remaining backwards compatible with previous versions of Cordova. - -## USAGE - -Your plugin can depend on this plugin and use it to handle the new run time permissions Android 6.0.0 (cordova-android 5.0.0) introduced. - -View [this commit](https://github.com/apache/cordova-plugin-camera/commit/a9c18710f23e86f5b7f8918dfab7c87a85064870) to see how to depend on `cordova-plugin-compat`. View [this file](https://github.com/apache/cordova-plugin-camera/blob/master/src/android/CameraLauncher.java) to see how `PermissionHelper` is being used to request and store permissions. Read more about Android permissions at http://cordova.apache.org/docs/en/latest/guide/platforms/android/plugin.html#android-permissions. diff --git a/StoneIsland/plugins/cordova-plugin-compat/RELEASENOTES.md b/StoneIsland/plugins/cordova-plugin-compat/RELEASENOTES.md deleted file mode 100644 index b7aa1293..00000000 --- a/StoneIsland/plugins/cordova-plugin-compat/RELEASENOTES.md +++ /dev/null @@ -1,29 +0,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. -# ---> -# Release Notes - -### 1.1.0 (Nov 02, 2016) -* [CB-11625](https://issues.apache.org/jira/browse/CB-11625) Adding the `BuildConfig` fetching code as a backup to using a new preference -* Add github pull request template - -### 1.0.0 (Apr 15, 2016) -* Initial release -* Moved `PermissionHelper.java` into `src` diff --git a/StoneIsland/plugins/cordova-plugin-compat/package.json b/StoneIsland/plugins/cordova-plugin-compat/package.json deleted file mode 100644 index f31174d1..00000000 --- a/StoneIsland/plugins/cordova-plugin-compat/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "cordova-plugin-compat", - "description": "This repo is for remaining backwards compatible with previous versions of Cordova.", - "version": "1.1.0", - "homepage": "http://github.com/apache/cordova-plugin-compat#readme", - "repository": { - "type": "git", - "url": "git://github.com/apache/cordova-plugin-compat.git" - }, - "bugs": { - "url": "https://github.com/apache/cordova-plugin-compat/issues" - }, - "cordova": { - "id": "cordova-plugin-compat", - "platforms": [ - "android" - ] - }, - "keywords": [ - "ecosystem:cordova", - "ecosystem:phonegap", - "cordova-android" - ], - "engines": [ - { - "name": "cordova", - "version": ">=5.0.0" - } - ], - "author": "Apache Software Foundation", - "license": "Apache-2.0" -} diff --git a/StoneIsland/plugins/cordova-plugin-compat/plugin.xml b/StoneIsland/plugins/cordova-plugin-compat/plugin.xml deleted file mode 100644 index 40b45ccd..00000000 --- a/StoneIsland/plugins/cordova-plugin-compat/plugin.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- - 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. ---> - -<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0" - id="cordova-plugin-compat" - version="1.1.0"> - <name>Compat</name> - <description>Cordova Compatibility Plugin</description> - <license>Apache 2.0</license> - <keywords>cordova,compat</keywords> - <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-compat.git</repo> - - <!-- android --> - <platform name="android"> - <source-file src="src/android/PermissionHelper.java" target-dir="src/org/apache/cordova" /> - <source-file src="src/android/BuildHelper.java" target-dir="src/org/apache/cordova" /> - </platform> - -</plugin> diff --git a/StoneIsland/plugins/cordova-plugin-compat/src/android/BuildHelper.java b/StoneIsland/plugins/cordova-plugin-compat/src/android/BuildHelper.java deleted file mode 100644 index d9b18aa2..00000000 --- a/StoneIsland/plugins/cordova-plugin-compat/src/android/BuildHelper.java +++ /dev/null @@ -1,70 +0,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. -*/ - -package org.apache.cordova; - -/* - * This is a utility class that allows us to get the BuildConfig variable, which is required - * for the use of different providers. This is not guaranteed to work, and it's better for this - * to be set in the build step in config.xml - * - */ - -import android.app.Activity; -import android.content.Context; - -import java.lang.reflect.Field; - - -public class BuildHelper { - - - private static String TAG="BuildHelper"; - - /* - * This needs to be implemented if you wish to use the Camera Plugin or other plugins - * that read the Build Configuration. - * - * Thanks to Phil@Medtronic and Graham Borland for finding the answer and posting it to - * StackOverflow. This is annoying as hell! However, this method does not work with - * ProGuard, and you should use the config.xml to define the application_id - * - */ - - public static Object getBuildConfigValue(Context ctx, String key) - { - try - { - Class<?> clazz = Class.forName(ctx.getPackageName() + ".BuildConfig"); - Field field = clazz.getField(key); - return field.get(null); - } catch (ClassNotFoundException e) { - LOG.d(TAG, "Unable to get the BuildConfig, is this built with ANT?"); - e.printStackTrace(); - } catch (NoSuchFieldException e) { - LOG.d(TAG, key + " is not a valid field. Check your build.gradle"); - } catch (IllegalAccessException e) { - LOG.d(TAG, "Illegal Access Exception: Let's print a stack trace."); - e.printStackTrace(); - } - - return null; - } - -} diff --git a/StoneIsland/plugins/cordova-plugin-compat/src/android/PermissionHelper.java b/StoneIsland/plugins/cordova-plugin-compat/src/android/PermissionHelper.java deleted file mode 100644 index bbd79112..00000000 --- a/StoneIsland/plugins/cordova-plugin-compat/src/android/PermissionHelper.java +++ /dev/null @@ -1,138 +0,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. -*/ -package org.apache.cordova; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; - -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.LOG; - -import android.content.pm.PackageManager; - -/** - * This class provides reflective methods for permission requesting and checking so that plugins - * written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions. - */ -public class PermissionHelper { - private static final String LOG_TAG = "CordovaPermissionHelper"; - - /** - * Requests a "dangerous" permission for the application at runtime. This is a helper method - * alternative to cordovaInterface.requestPermission() that does not require the project to be - * built with cordova-android 5.0.0+ - * - * @param plugin The plugin the permission is being requested for - * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult() - * along with the result of the permission request - * @param permission The permission to be requested - */ - public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) { - PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission}); - } - - /** - * Requests "dangerous" permissions for the application at runtime. This is a helper method - * alternative to cordovaInterface.requestPermissions() that does not require the project to be - * built with cordova-android 5.0.0+ - * - * @param plugin The plugin the permissions are being requested for - * @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult() - * along with the result of the permissions request - * @param permissions The permissions to be requested - */ - public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) { - try { - Method requestPermission = CordovaInterface.class.getDeclaredMethod( - "requestPermissions", CordovaPlugin.class, int.class, String[].class); - - // If there is no exception, then this is cordova-android 5.0.0+ - requestPermission.invoke(plugin.cordova, plugin, requestCode, permissions); - } catch (NoSuchMethodException noSuchMethodException) { - // cordova-android version is less than 5.0.0, so permission is implicitly granted - LOG.d(LOG_TAG, "No need to request permissions " + Arrays.toString(permissions)); - - // Notify the plugin that all were granted by using more reflection - deliverPermissionResult(plugin, requestCode, permissions); - } catch (IllegalAccessException illegalAccessException) { - // Should never be caught; this is a public method - LOG.e(LOG_TAG, "IllegalAccessException when requesting permissions " + Arrays.toString(permissions), illegalAccessException); - } catch(InvocationTargetException invocationTargetException) { - // This method does not throw any exceptions, so this should never be caught - LOG.e(LOG_TAG, "invocationTargetException when requesting permissions " + Arrays.toString(permissions), invocationTargetException); - } - } - - /** - * Checks at runtime to see if the application has been granted a permission. This is a helper - * method alternative to cordovaInterface.hasPermission() that does not require the project to - * be built with cordova-android 5.0.0+ - * - * @param plugin The plugin the permission is being checked against - * @param permission The permission to be checked - * - * @return True if the permission has already been granted and false otherwise - */ - public static boolean hasPermission(CordovaPlugin plugin, String permission) { - try { - Method hasPermission = CordovaInterface.class.getDeclaredMethod("hasPermission", String.class); - - // If there is no exception, then this is cordova-android 5.0.0+ - return (Boolean) hasPermission.invoke(plugin.cordova, permission); - } catch (NoSuchMethodException noSuchMethodException) { - // cordova-android version is less than 5.0.0, so permission is implicitly granted - LOG.d(LOG_TAG, "No need to check for permission " + permission); - return true; - } catch (IllegalAccessException illegalAccessException) { - // Should never be caught; this is a public method - LOG.e(LOG_TAG, "IllegalAccessException when checking permission " + permission, illegalAccessException); - } catch(InvocationTargetException invocationTargetException) { - // This method does not throw any exceptions, so this should never be caught - LOG.e(LOG_TAG, "invocationTargetException when checking permission " + permission, invocationTargetException); - } - return false; - } - - private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) { - // Generate the request results - int[] requestResults = new int[permissions.length]; - Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED); - - try { - Method onRequestPermissionResult = CordovaPlugin.class.getDeclaredMethod( - "onRequestPermissionResult", int.class, String[].class, int[].class); - - onRequestPermissionResult.invoke(plugin, requestCode, permissions, requestResults); - } catch (NoSuchMethodException noSuchMethodException) { - // Should never be caught since the plugin must be written for cordova-android 5.0.0+ if it - // made it to this point - LOG.e(LOG_TAG, "NoSuchMethodException when delivering permissions results", noSuchMethodException); - } catch (IllegalAccessException illegalAccessException) { - // Should never be caught; this is a public method - LOG.e(LOG_TAG, "IllegalAccessException when delivering permissions results", illegalAccessException); - } catch(InvocationTargetException invocationTargetException) { - // This method may throw a JSONException. We are just duplicating cordova-android's - // exception handling behavior here; all it does is log the exception in CordovaActivity, - // print the stacktrace, and ignore it - LOG.e(LOG_TAG, "InvocationTargetException when delivering permissions results", invocationTargetException); - } - } -} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.editorconfig b/StoneIsland/plugins/cordova-plugin-firebasex/.editorconfig new file mode 100644 index 00000000..e255fddd --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.editorconfig @@ -0,0 +1,17 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[{package.json,.travis.yml}] +indent_style = space +indent_size = 2 + +[{plugin.xml,Makefile}] +indent_style = tab diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.github/FUNDING.yml b/StoneIsland/plugins/cordova-plugin-firebasex/.github/FUNDING.yml new file mode 100644 index 00000000..c3f3e5bf --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.github/FUNDING.yml @@ -0,0 +1,6 @@ +# These are supported funding model platforms + +github: [ dpa99c ] +custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZRD3W47HQ3EMJ&source=url +patreon: dpa99c +ko_fi: davealden
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/bug_report.md b/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..c16abb50 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,125 @@ +--- +name: Bug report +about: Report a problem +title: '' +labels: '' +assignees: '' + +--- + +<!-- +IMPORTANT: PLEASE READ + +WARNING: Failure to follow the issue template guidelines below will result in the issue being immediately closed. +--> + +<!-- Fill out the relevant sections below and delete irrelevant sections. --> + +# Bug report + +<!-- COMPLETE THIS CHECKLIST --> +**CHECKLIST** +- [ ] I have read the [issue reporting guidelines](https://github.com/dpa99c/cordova-plugin-firebasex#reporting-issues) + +- [ ] I confirm this is a suspected bug or issue that will affect other users +<!-- i.e. this is not a request for support in using/integrating the plugin into your specific project --> + +- [ ] I have reproduced the issue using the [example project](https://github.com/dpa99c/cordova-plugin-firebasex-test) or provided the necessary information to reproduce the issue. +<!-- necessary information e.g. exact steps, FCM notification message content, test case project repo --> + +- [ ] I have read [the documentation](https://github.com/dpa99c/cordova-plugin-firebasex) thoroughly and it does not help solve my issue. +<!-- e.g. if you're having a build issue ensure you've read through the build environment notes --> + +- [ ] I have checked that no similar issues (open or closed) already exist. +<!-- Duplicates or near-duplicates will be closed immediately. --> + + + +**Current behavior:** + +<!-- Describe how the bug manifests. --> + +<!-- Explain how you're sure there is an issue with this plugin rather than your own code: + - If this plugin has an example project, have you been able to reproduce the issue within it? + - Have you created a clean test Cordova project containing only this plugin to eliminate the potential for interference with other plugins/code? + --> + +**Expected behavior:** +<!-- Describe what the behavior should be without the bug. --> + +**Steps to reproduce:** +<!-- If you are able to illustrate the bug with an example, please provide steps to reproduce. --> + +**Screenshots** +<!-- If applicable, add screenshots to help explain your problem. --> + +**Environment information** +<!-- Please supply full details of your development environment including: --> +- Cordova CLI version + - `cordova -v` +- Cordova platform version + - `cordova platform ls` +- Plugins & versions installed in project (including this plugin) + - `cordova plugin ls` +- Dev machine OS and version, e.g. + - OSX + - `sw_vers` + - Windows 10 + - `winver` + +_Runtime issue_ +- Device details + - _e.g. iPhone X, Samsung Galaxy S8, iPhone X Simulator, Pixel XL Emulator_ +- OS details + - _e.g. iOS 12.2, Android 9.0_ + +_Android build issue:_ +- Node JS version + - `node -v` +- Gradle version + - `ls platforms/android/.gradle` +- Target Android SDK version + - `android:targetSdkVersion` in `AndroidManifest.xml` +- Android SDK details + - `sdkmanager --list | sed -e '/Available Packages/q'` + +_iOS build issue:_ +- Node JS version + - `node -v` +- XCode version + + +**Related code:** +``` +insert any relevant code here such as plugin API calls / input parameters +``` + +**Console output** +<details> +<summary>console output</summary> + +``` + +// Paste any relevant JS/native console output here + +``` + +</details><br/><br/> + +**Other information:** + +<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. --> + + + + + +<!-- +A POLITE REMINDER + +- This is free, open-source software. +- Although the author makes every effort to maintain it, no guarantees are made as to the quality or reliability, and reported issues will be addressed if and when the author has time. +- Help/support will not be given by the author, so forums (e.g. Ionic) or Stack Overflow should be used. Any issues requesting help/support will be closed immediately. +- If you have urgent need of a bug fix/feature, the author can be engaged for PAID contract work to do so: please contact dave@workingedge.co.uk +- Rude or abusive comments/issues will not be tolerated, nor will opening multiple issues if those previously closed are deemed unsuitable. Any of the above will result in you being BANNED from ALL of my Github repositories. +--> diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/documentation-issue.md b/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/documentation-issue.md new file mode 100644 index 00000000..f8d8d819 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/documentation-issue.md @@ -0,0 +1,36 @@ +--- +name: Documentation issue +about: Describe an issue with the documentation +title: '' +labels: '' +assignees: '' + +--- +<!-- +WARNING: Failure to follow the issue template guidelines below will result in the issue being immediately closed. + +Only documentation issues should be opened here. + +Before opening an issue, please read [Reporting issues](https://github.com/dpa99c/cordova-plugin-firebasex#reporting-issues) +--> + + +# Documentation issue +<!-- +Describe the issue with the documentation or the request for documentation changes. +- Please give reasons why the change is necessary. +- If the change is trivial or you are able to make it, please consider making a Pull Request containing the necessary changes. +--> + + + + +<!-- +A POLITE REMINDER + +- This is free, open-source software. +- Although the author makes every effort to maintain it, no guarantees are made as to the quality or reliability, and reported issues will be addressed if and when the author has time. +- Help/support will not be given by the author, so forums (e.g. Ionic) or Stack Overflow should be used. Any issues requesting help/support will be closed immediately. +- If you have urgent need of a bug fix/feature, the author can be engaged for PAID contract work to do so: please contact dave@workingedge.co.uk +- Rude or abusive comments/issues will not be tolerated, nor will opening multiple issues if those previously closed are deemed unsuitable. Any of the above will result in you being BANNED from ALL of my Github repositories. +--> diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/feature_request.md b/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..539d7766 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,43 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- +<!-- +WARNING: Failure to follow the issue template guidelines below will result in the issue being immediately closed. + +Only feature requests should be opened here. + +Before opening an issue, please read [Reporting issues](https://github.com/dpa99c/cordova-plugin-firebasex#reporting-issues) + +--> + + +# Feature request +<!-- +Feature requests should include as much detail as possible: + +- A descriptive title +- A description of the problem you're trying to solve, including why you think this is a problem +- An overview of the suggested solution +- Use case: why should this be implemented? +- If the feature changes current behavior, reasons why your solution is better +- Relevant links, e.g. + - Stack Overflow post illustrating a solution + - Code within a Github repo that illustrates a solution + - Native API documentation for proposed feature +--> + + +<!-- +A POLITE REMINDER + +- This is free, open-source software. +- Although the author makes every effort to maintain it, no guarantees are made as to the quality or reliability, and reported issues will be addressed if and when the author has time. +- Help/support will not be given by the author, so forums (e.g. Ionic) or Stack Overflow should be used. Any issues requesting help/support will be closed immediately. +- If you have urgent need of a bug fix/feature, the author can be engaged for PAID contract work to do so: please contact dave@workingedge.co.uk +- Rude or abusive comments/issues will not be tolerated, nor will opening multiple issues if those previously closed are deemed unsuitable. Any of the above will result in you being BANNED from ALL of my Github repositories. +--> diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.github/PULL_REQUEST_TEMPLATE.md b/StoneIsland/plugins/cordova-plugin-firebasex/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..fa6ad932 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ +## PR Type +What kind of change does this PR introduce? + +<!-- Please check the one that applies to this PR using "x". --> +- [ ] Bugfix +- [ ] Feature +- [ ] Code style update (formatting, local variables) +- [ ] Refactoring (no functional changes, no api changes) +- [ ] Documentation changes +- [ ] Other... Please describe: + +<!-- Fill out the relevant sections below and delete irrelevant sections. --> + +## PR Checklist +For bug fixes / features, please check if your PR fulfills the following requirements: + +- [ ] Testing has been carried out for the changes have been added +- [ ] Regression testing has been carried out for existing functionality +- [ ] Docs have been added / updated + +## What is the purpose of this PR? +<!-- Describe any current behavior that you are modifying, or link to a relevant issue. --> +<!-- Describe the new behaviour added/modified and its purpose. --> + +## Does this PR introduce a breaking change? +- [ ] Yes +- [ ] No + +<!-- If this PR contains a breaking change, please describe the impact and migration path for existing plugin versions. --> + +## What testing has been done on the changes in the PR? +<!-- e.g. if an example project exists for this plugin, has it been updated to test the new functionality? --> + +## What testing has been done on existing functionality? +<!-- e.g. if an example project exists for this plugin, has been it been tested to ensure no regression bugs have been introduced? --> + +## Other information
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/.travis.yml b/StoneIsland/plugins/cordova-plugin-firebasex/.travis.yml new file mode 100644 index 00000000..44e115c4 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/.travis.yml @@ -0,0 +1,108 @@ +env: + global: + - JAVA_HOME=/usr/lib/jvm/java-8-oracle + - LANG=en_US.UTF-8 + +matrix: + include: + - os: linux + sudo: false + language: android + android: + components: + - tools-26.0.0 + - platform-tools-26.0.0 + - build-tools-26.0.0 + - android-26.0.0 + - extra-google-google_play_services + - extra-google-m2repository + - extra-android-m2repository + addons: + apt: + packages: + - oracle-java8-installer + - oracle-java8-set-default + licenses: + - android-sdk-preview-license-.+ + - android-sdk-license-.+ + - google-gdk-license-.+ + env: CORDOVA_VERSION="6.5.0" CORDOVA_PLATFORM="android" CORDOVA_PLATFORM_VERSION="6.4.0" + + - os: linux + sudo: false + language: android + android: + components: + - tools-26.0.0 + - platform-tools-26.0.0 + - build-tools-26.0.0 + - android-26.0.0 + - extra-google-google_play_services + - extra-google-m2repository + - extra-android-m2repository + addons: + apt: + packages: + - oracle-java8-installer + - oracle-java8-set-default + licenses: + - android-sdk-preview-license-.+ + - android-sdk-license-.+ + - google-gdk-license-.+ + env: CORDOVA_VERSION="7.1.0" CORDOVA_PLATFORM="android" CORDOVA_PLATFORM_VERSION="7.1.0" + + - os: linux + sudo: false + language: android + android: + components: + - tools-26.0.0 + - platform-tools-26.0.0 + - build-tools-26.0.0 + - android-26.0.0 + - extra-google-google_play_services + - extra-google-m2repository + - extra-android-m2repository + addons: + apt: + packages: + - oracle-java8-installer + - oracle-java8-set-default + licenses: + - android-sdk-preview-license-.+ + - android-sdk-license-.+ + - google-gdk-license-.+ + env: CORDOVA_VERSION="8.0.0" CORDOVA_PLATFORM="android" CORDOVA_PLATFORM_VERSION="7.1.0" + + - os: osx + language: objective-c + osx_image: xcode9.4 + env: CORDOVA_VERSION="6.5.0" CORDOVA_PLATFORM="ios" CORDOVA_PLATFORM_VERSION="4.5.4" + + - os: osx + language: objective-c + osx_image: xcode9.4 + env: CORDOVA_VERSION="7.1.0" CORDOVA_PLATFORM="ios" CORDOVA_PLATFORM_VERSION="4.5.4" + + - os: osx + language: objective-c + osx_image: xcode9.4 + env: CORDOVA_VERSION="8.0.0" CORDOVA_PLATFORM="ios" CORDOVA_PLATFORM_VERSION="4.5.4" + + - os: linux + env: CORDOVA_VERSION="6.5.0" CORDOVA_PLATFORM="browser" CORDOVA_PLATFORM_VERSION="5.0.3" + + - os: linux + env: CORDOVA_VERSION="7.1.0" CORDOVA_PLATFORM="browser" CORDOVA_PLATFORM_VERSION="5.0.3" + + - os: linux + env: CORDOVA_VERSION="8.0.0" CORDOVA_PLATFORM="browser" CORDOVA_PLATFORM_VERSION="5.0.3" + +before_install: +- nvm install 8 +- PATH=$TRAVIS_BUILD_DIR/node_modules/.bin:$PATH ; export PATH +- if [[ "$CORDOVA_PLATFORM" == "android" ]]; then yes | sdkmanager "build-tools;26.0.0" "platforms;android-26" ; fi + +script: +- bash ./test/test-default.sh $CORDOVA_VERSION $CORDOVA_PLATFORM $CORDOVA_PLATFORM_VERSION +- if [[ "$CORDOVA_PLATFORM" == "android" ]]; then bash ./test/test-with-3-plugins.sh $CORDOVA_VERSION $CORDOVA_PLATFORM $CORDOVA_PLATFORM_VERSION cordova-plugin-request-location-accuracy cordova-android-play-services-gradle-release cordova-android-firebase-gradle-release; fi diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/CHANGELOG.md b/StoneIsland/plugins/cordova-plugin-firebasex/CHANGELOG.md new file mode 100644 index 00000000..c3b4d5f3 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/CHANGELOG.md @@ -0,0 +1,458 @@ +# Version 10.2.0-cli +* (iOS) Fix crashes on receiving push notifications on iOS due to delegate chaining. +** Resolves [#385](https://github.com/dpa99c/cordova-plugin-firebasex/issues/385). +** Reverts commit 4e9a0f4a1fd4ceb871af40629e1ddf146f287ca8 "co-existence with cordova-plugin-local-notification on iOS" +** Since upon testing, this plugin does not work with `cordova-plugin-local-notification` present in the same project even with this code in place. +** And the conflict between the 2 plugins will need to be addressed separately under [#230](https://github.com/dpa99c/cordova-plugin-firebasex/issues/230). +* (iOS) Add support for iOS actionable notifications + * Merged from PR [#482](https://github.com/dpa99c/cordova-plugin-firebasex/pull/482). +* (Android): Handle task outcomes where task is not successful but exception is null. + * Resolves [#473](https://github.com/dpa99c/cordova-plugin-firebasex/issues/473). +* (iOS): Bump minimum required Cocoapods version to v1.9.1 due to requirement by Firestore v6.28.1 +* (Android) (Bug fix) Fix all cases where task outcomes are being incorrectly handled. +* (iOS) Update remote config to use `activateWithCompletion` instead of deprecated `activateWithCompletionHandler` for activating remote config. +* (iOS) (Bug fix) Use regex to extract cocoapods from stdout when verifying cocoapods version during plugin install. + * Resolves [#462](https://github.com/dpa99c/cordova-plugin-firebasex/issues/462). +* (Android, iOS): Support custom locations for Firebase config files + * Merged from PR [#465](https://github.com/dpa99c/cordova-plugin-firebasex/pull/465). + * Resolves [#452](https://github.com/dpa99c/cordova-plugin-firebasex/issues/452). + +# Version 10.1.2-cli +* (iOS): Bump Firebase SDK versions to v6.28.1 to resolve build freeze issue. + * Resolves [#460](https://github.com/dpa99c/cordova-plugin-firebasex/issues/460). + +# Version 10.1.1-cli +* (iOS) Fix regression bug in `getToken()` introduced by [35a2a68e8db3808723c9f2fcb6aa176021f6c77a](https://github.com/dpa99c/cordova-plugin-firebasex/commit/35a2a68e8db3808723c9f2fcb6aa176021f6c77a). + * Resolves [#456](https://github.com/dpa99c/cordova-plugin-firebasex/issues/456). +* (iOS) Update to use Firebase SDK v6.28.0 + * Resolves [#453](https://github.com/dpa99c/cordova-plugin-firebasex/issues/453). + +# Version 10.1.0-cli +* (iOS) Use precompiled pod for Firestore to reduce build times. + * *BREAKING CHANGE:* Requires `cocoapods>=1.9` (previously `cocoapods>=1.8`). + * Adds hook script to check local cocoapods version during plugin install. + * Based on PR [#440](https://github.com/dpa99c/cordova-plugin-firebasex/pull/440). + * Resolves [#407](https://github.com/dpa99c/cordova-plugin-firebasex/issues/407). +* (Android) Fixed regression bug related to default Crashlytics permission. + * See [this comment](https://github.com/dpa99c/cordova-plugin-firebasex/issues/335#issuecomment-651218052). +* (iOS) Bump pinned Firebase SDK versions to latest 6.27.0 + * See [release notes](https://firebase.google.com/support/release-notes/ios#version_6270_-_june_16_2020) +* (Android): Bump Firebase SDK versions to latest for Analytics & Inapp Messaging. +# Version 10.0.0-cli +* *BREAKING CHANGE:* (Android, iOS) Migrate from Fabric Crashlytics SDK to Firebase Crashlytics SDK. +** Based on [this commit](https://github.com/vickydlion/cordova-plugin-firebasex/commit/0dfb5753edcd9fc19a0e7a52fdd4fc79d6d976ea) in [PR #432](https://github.com/dpa99c/cordova-plugin-firebasex/pull/432). +** Resolves [#335](https://github.com/dpa99c/cordova-plugin-firebasex/issues/335). +** Removes `isCrashlyticsCollectionCurrentlyEnabled()` as it's no longer necessary to manually init Crashlytics and a runtime method exists to enable/disable it. +** For more info see the [Firebase Crashlytics SDK upgrade documentation](https://firebase.google.com/docs/crashlytics/upgrade-sdk). +* (iOS) Fix exception raised if another plugin as already configured Firebase + * Merged from PR [#419](https://github.com/dpa99c/cordova-plugin-firebasex/pull/419). +* (iOS) Handle case where LD_RUNPATH_SEARCH_PATHS is an array. Resolves [#344](https://github.com/dpa99c/cordova-plugin-firebasex/issues/344). +* (Android, iOS): Avoid collection state getting out of sync & remove restriction to override config defaults. + * Merged from PR [#423](https://github.com/dpa99c/cordova-plugin-firebasex/pull/423). +* (iOS) Fix escaping already escaped json. + * Merged from PR [#430](https://github.com/dpa99c/cordova-plugin-firebasex/pull/430). + * Further resolves [#401](https://github.com/dpa99c/cordova-plugin-firebasex/issues/401). +* (Android): Fix parsing of existing `colors.xml` when it contains multiple existing `<color>` to prevent overwriting the existing values. + * Resolves [#436](https://github.com/dpa99c/cordova-plugin-firebasex/issues/436). +* (Android, iOS): Return success/failure result when subscribing/unsubscribing from topics. + * Resolves [#422](https://github.com/dpa99c/cordova-plugin-firebasex/issues/422). + +# Version 9.1.2-cli +* (Android) Fix retrieval of auth provider ID - [see here for more info](https://github.com/firebase/FirebaseUI-Android/issues/329#issuecomment-564409912) +* (iOS) Align retrieval of auth provider ID with Android. +* (Typing): correct return type of a method + * Merged from PR [#390](https://github.com/dpa99c/cordova-plugin-firebasex/pull/390). +* (Documentation) Update guidance and requirements when opening issues +* (iOS): Fix escaping of line endings in multi-line log messages being sent from native iOS implementation to JS console. + * Resolves [#401](https://github.com/dpa99c/cordova-plugin-firebasex/issues/401). +* (iOS): Set shouldEstablishDirectChannel via a plugin variable which defaults to false. + Resolves [#406](https://github.com/dpa99c/cordova-plugin-firebasex/issues/406). +* Bump androidx plugin version dependencies. + Resolves [#418](https://github.com/dpa99c/cordova-plugin-firebasex/issues/418). + +# Version 9.1.1-cli +* (iOS): Bump Firebase SDK components to v6.23.0. + * Relates to [#373](https://github.com/dpa99c/cordova-plugin-firebasex/issues/373). + * See https://firebase.google.com/support/release-notes/ios#version_6230_-_april_21_2020. +* (Android) Bump Firebase SDK (and other Gradle dependencies) to latest versions. + * See https://firebase.google.com/support/release-notes/android#2020-04-23 + +# Version 9.1.0-cli +* (Android & iOS) *BREAKING CHANGE*: Add support for filters to `fetchDocumentInFirestoreCollection()` + * *BREAKING CHANGE* to function signature. + * Merged from PR [#367](https://github.com/dpa99c/cordova-plugin-firebasex/pull/367). +* (Android) Fix regression bug which causes CLI builds to fail on Android. +Resolves [#369](https://github.com/dpa99c/cordova-plugin-firebasex/issues/369). + +# Version 9.0.3-cli +* (Android & iOS) Add `reloadCurrentUser()` +* (Doc) `createChannel()` suggestion for multiple sounds + * Merged from PR [#225](https://github.com/dpa99c/cordova-plugin-firebasex/pull/225). +* (iOS) Implement `getInfo()` for iOS. + * Merged from PR [#363](https://github.com/dpa99c/cordova-plugin-firebasex/pull/363). +* (Android & iOS) Add `signInUserWithCustomToken()` AND `signInUserAnonymously()` auth methods + * Merged from PR [#359](https://github.com/dpa99c/cordova-plugin-firebasex/pull/359). + +# Version 9.0.2-cli + +* (Android): Don't display app icon for large notification icon on Android. Resolves [#343](https://github.com/dpa99c/cordova-plugin-firebasex/issues/343). +* (Android & iOS) Sign out of Google signing out of Firebase. Resolves [#353](https://github.com/dpa99c/cordova-plugin-firebasex/issues/353). +* (Android & iOS) Add `documentExistsInFirestoreCollection()` and fix resolution of `fetchDocumentInFirestoreCollection()`. + +# Version 9.0.1-cli +* Document `cli_build` branch. +* *BREAKING CHANGE*: Remove Firebase Inapp Messaging and Google Tag Manager SDK components due to causing Cordova CLI build issues. + * Resolves [#326](https://github.com/dpa99c/cordova-plugin-firebasex/issues/326). + +# Version 9.0.0 +* *BREAKING CHANGE*: Change method signature of `setCrashlyticsCollectionEnabled()` to `(enabled, success, error)` (from `()`) to allow enabling/disabling of Crashlytics at runtime and align it with `setPerformanceCollectionEnabled()` and `setAnalyticsCollectionEnabled()` +* Add `isCrashlyticsCollectionEnabled()` and `isCrashlyticsCollectionCurrentlyEnabled()` to respectively check if persistent Crashlytics setting is enabled and if Crashlytics is enabling during the current app session. +* Add `isAnalyticsCollectionEnabled()` and `isPerformanceCollectionEnabled()` to check if persistent settings are enabled. +* *BREAKING CHANGE*: Remove Firebase Inapp Messaging SDK component due to causing Cordova CLI build issues. + * Resolves [#326](https://github.com/dpa99c/cordova-plugin-firebasex/issues/326). +* (iOS) Override CDVPlugin class abstract method `handleOpenURL` instead of implementing app delegate method `application:openURL:options` to prevent conflicts with other plugins. + * Resolves [#328](https://github.com/dpa99c/cordova-plugin-firebasex/issues/328). +* (Android) Fix parsing of existing `colors.xml` when it only contains a single `<color>` to prevent overwriting the existing value. + * Fixes [#284](https://github.com/dpa99c/cordova-plugin-firebasex/issues/284). + +# Version 8.1.1 +* (Doc) Document custom FCM message handling. +* (Doc) Rationalise heading levels. +* (iOS) Implement message receiver mechanism (equivalent to existing Android mechanism) to enable custom handling of specific message types. +* (Android) Extend custom receiver to handle payload obtained from system notification message bundle received while in background/not running. +* (Android) Ignore invocation of auth state change listener at app start (same as on iOS) to prevent error due to race condition with plugin initialisation. + + +# Version 8.1.0 +* Add support for Firebase inapp messaging + * Merged from PR [#312](https://github.com/dpa99c/cordova-plugin-firebasex/pull/312). +* Add support for Firestore realtime database. Resolves [#190](https://github.com/dpa99c/cordova-plugin-firebasex/issues/190). +* (Doc) Add note regarding persistence of data collection settings. Resolves [#315](https://github.com/dpa99c/cordova-plugin-firebasex/issues/315). +* (iOS) Added missing Google Tag Manager Pod for iOS. + * Merged from PR [#318](https://github.com/dpa99c/cordova-plugin-firebasex/pull/318). +* (iOS) Don't set `FirebaseScreenReportEnabled=false` in app list when `FIREBASE_ANALYTICS_COLLECTION_ENABLE=false`. Resolves [#317](https://github.com/dpa99c/cordova-plugin-firebasex/issues/317). +* (Android) Disable strict version check in Google Services plugin for Gradle as it causes erroneous build failures. + +# Version 8.0.1 +* Add `registerAuthStateChangeListener()` to support invocation of a callback function on the Firebase Authentication state changing. +Resolves [#311](https://github.com/dpa99c/cordova-plugin-firebasex/issues/311). +* (Android) Bump Firebase SDK dependency versions to latest releases. Resolves [#279](https://github.com/dpa99c/cordova-plugin-firebasex/issues/279). +* (iOS) Bump podspec versions for Firebase SDK components to [latest release (v6.17.0)](https://firebase.google.com/support/release-notes/ios#version_6170_-_february_11_2020) + +# Version 8.0.0 +* *BREAKING CHANGE*: Rework `verifyPhoneNumber()` to preserve and reference the native credentials object (rather than attempting to extract and parse its properties to JS). Fixes [#176](https://github.com/dpa99c/cordova-plugin-firebasex/issues/176). +* Add other Firebase Authentication methods: Google Sign In, Sign In with Apple, email/password sign in, and authentication utility methods. Partially resolves [#208](https://github.com/dpa99c/cordova-plugin-firebasex/issues/208). +* (Android) Add check `google-services` plugin does not already exist. Fixes [#282](https://github.com/dpa99c/cordova-plugin-firebasex/issues/282). +* (iOS) Update pinned Firebase SDK versions to latest v6.13.0. Resolves [#232](https://github.com/dpa99c/cordova-plugin-firebasex/issues/232). + +# Version 7.0.2 +* (Android) Fix error caused by local variable + * Merged from PR [#229](https://github.com/dpa99c/cordova-plugin-firebasex/pull/229). +* (iOS Hook) Fix retrieving Xcode project path + * Merged from PR [#234](https://github.com/dpa99c/cordova-plugin-firebasex/pull/234). +* (Android) Check google-services plugin doesn't already exist in Gradle script + * Merged from PR [#281](https://github.com/dpa99c/cordova-plugin-firebasex/pull/281). + +# Version 7.0.1 +* (Android) Replace references to cordovaActivity with applicationContext when app is not running and therefore cordovaActivity doesn't exist. +Resolves [#165](https://github.com/dpa99c/cordova-plugin-firebasex/issues/165). +* Fix .forEach is not a function. +Merged from PR [#219](https://github.com/dpa99c/cordova-plugin-firebasex/pull/219). +Resolves [#213](https://github.com/dpa99c/cordova-plugin-firebasex/issues/213). +* (Android) Parse this plugin's `plugin.xml` to extract default values for plugin variables not explicitly set at plugin install time. +Fixes [#218](https://github.com/dpa99c/cordova-plugin-firebasex/issues/218). +* (iOS) Fix after_prepare hook to run on multiple platforms so if they are added in one operation using `cordova prepare`, both platforms are processed. +Fixes [#221](https://github.com/dpa99c/cordova-plugin-firebasex/issues/221). +* (Typedef) Update the typedef for recent plugin API changes. + +# Version 7.0.0 +* (iOS) Update Firebase SDK to [v6.11.0 released 22 Oct 2019](https://firebase.google.com/support/release-notes/ios#version_6110_-_october_22_2019) +* (Android) Update pinned Firebase SDK versions to latest as of [25 Oct 2019](https://firebase.google.com/support/release-notes/android#2019-10-25) +Resolves [#207](https://github.com/dpa99c/cordova-plugin-firebasex/issues/207) +* (Doc) Document parameter types in API functions. +Resolves [#140](https://github.com/dpa99c/cordova-plugin-firebasex/issues/140) +* (Doc) fix `onMessageReceived()` code sample. +Merged from PR [#142](https://github.com/dpa99c/cordova-plugin-firebasex/pull/142). +* (Doc) Example sound name for custom Android notification sound. +Resolves [#160](https://github.com/dpa99c/cordova-plugin-firebasex/issues/160) +* (Feat): add Typescript declaration +Merged from PR [#166](https://github.com/dpa99c/cordova-plugin-firebasex/pull/166). +* (Doc) Fix `createChannel()` examples. +Merged from PR [#167](https://github.com/dpa99c/cordova-plugin-firebasex/pull/167). +* (Android) Expose `description` notification channel field. +Merged from PR [#168](https://github.com/dpa99c/cordova-plugin-firebasex/pull/168). +* (iOS) Update CocoaPods spec url to new CDN. +Merged from PR [#173](https://github.com/dpa99c/cordova-plugin-firebasex/pull/173). +* (Doc) Fix code example for default android icon. +Merged from PR [#174](https://github.com/dpa99c/cordova-plugin-firebasex/pull/174). +* (iOS) Support iOS 13 APNS format token change. +Merged from PR [#177](https://github.com/dpa99c/cordova-plugin-firebasex/pull/177). +* (Hook) Remove check for presence of platform in `config.xml` +Merged from PR [#185](https://github.com/dpa99c/cordova-plugin-firebasex/pull/185). +* (Feat) Expose Firebase Messaging autoinit API functions to allow enabling/disabling/checking of autoinit. + * If disabled and `unregister()` is called, a new token will not be automatically allocated. + * Resolves [#147](https://github.com/dpa99c/cordova-plugin-firebasex/issues/147). +* (iOS) Fix `logEvent()` so it doesn't generated warning message in console. Fixes [#154](https://github.com/dpa99c/cordova-plugin-firebasex/issues/154). +* (iOS) Handle notification messages that contain `"content-available":1` which wakes up the app while in the background to deliver the message payload immediately when the message arrives (without requiring user interaction by tapping the system notification). +Fixes [#158](https://github.com/dpa99c/cordova-plugin-firebasex/issues/158). +* (Android)(Do) Clarify Android custom notification icons example. Resolves [#183](https://github.com/dpa99c/cordova-plugin-firebasex/issues/183). +* (Doc) Add example of using stacktrace.js with `logError()`. +Clarifies [#118](https://github.com/dpa99c/cordova-plugin-firebasex/issues/118). +* (Doc) Add link to [cordova-plugin-firebasex-ionic3-test](https://github.com/dpa99c/cordova-plugin-firebasex-ionic3-test) Ionic 3 example project +* Add `signInWithCredential()` to sign user into Firebase account and `linkUserWithCredential()` to link user account with credentials obtained via `verifyPhoneNumber()`. +* (Android) *BREAKING CHANGE* Rework `verifyPhoneNumber()` + * Remove redundant `verified` in returned credentials object. + * Support mocking of instant verification for `verifyPhoneNumber()` on Android for integration testing. +* (iOS) *BREAKING CHANGE* Rework `verifyPhoneNumber()` + * Return the same credential object structure as Android. +* (iOS) Add `SETUP_RECAPTCHA_VERIFICATION` plugin variable to automatically set up reCAPTURE verification for phone auth. +* (Doc) Add section to explicitly document all supported plugin variables. +* (iOS) Add `onApnsTokenReceived()` to register a callback function to be invoked when the APNS token is allocated. +Resolves [#201](https://github.com/dpa99c/cordova-plugin-firebasex/issues/201). +* (Android) Tweak default empty values when sending stacktrace using `logError()` +* (Doc) Better example of using `logError()` to track unhandled JS exceptions vs logging a non-fatal logical error. +* (iOS) Modify `logError()` to send stacktrace.js output as an actual stacktrace instead of custom keys. +Resolves [#118](https://github.com/dpa99c/cordova-plugin-firebasex/issues/118). +* (Hook) Fix parsing of `config.xml` to extract app name. +Fixes [#139](https://github.com/dpa99c/cordova-plugin-firebasex/issues/139). +* (Android) Ensure functions which return a boolean result return an actual boolean type rather than a binary integer. +Fixes [#153](https://github.com/dpa99c/cordova-plugin-firebasex/issues/153). +* (Hook) Rework hook scripts to: + * be fully synchronous to eliminate race conditions (remove q dependency) + * use [xml-js](https://github.com/nashwaan/xml-js) (instead of [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js)) to convert XML>JSON and JSON>XML + * (Android) handle existing `colors.xml`. + Resolves [#132](https://github.com/dpa99c/cordova-plugin-firebasex/issues/132). + + +# Version 6.1.0 +* (iOS) Add `getAPNSToken()` plugin API method to get the APNS token on iOS. Derived from merging PR [#100](https://github.com/dpa99c/cordova-plugin-firebasex/pull/100). +* Merge PR [#103](https://github.com/dpa99c/cordova-plugin-firebasex/pull/103) - fix for app name containing an ampersand. +* Merge PR [#115](https://github.com/dpa99c/cordova-plugin-firebasex/pull/115) - fix for short attribute in app name. +* Merge PR [#121](https://github.com/dpa99c/cordova-plugin-firebasex/pull/121) - fixes missing resolution of promise in after_prepare hook which caused other plugins to not run their after_prepare script (a bug introduced in v6.0.7) +* (Android) Merge PR [#64](https://github.com/dpa99c/cordova-plugin-firebasex/pull/64) - replace Android hooks scripts to configure Gradle with actual Gradle configuration. +* (iOS) Add missing `tap` property for notification messages received while app is running in background. + * Based on https://github.com/arnesson/cordova-plugin-firebase/pull/1104 + * Resolves [#96](https://github.com/dpa99c/cordova-plugin-firebasex/issues/96) +* (iOS) Fix issues causing foreground notifications not to display on first run. Fixes [#109](https://github.com/dpa99c/cordova-plugin-firebasex/issues/109). +* (iOS) Update string format when subscribing/unsubscribing topics. Resolves [#110](https://github.com/dpa99c/cordova-plugin-firebasex/issues/110]). +* Support disabling of data collection (analytics/performance/crashlytics) at app startup and manual enabling of these at runtime. + * Resolves [#116](https://github.com/dpa99c/cordova-plugin-firebasex/issues/116]) and [#79](https://github.com/dpa99c/cordova-plugin-firebasex/issues/79]). +* Remove Android implementation of `getBadgeNumber()`/`setBadgeNumber()` as it doesn't work on Android 8+. + * Resolves [#124](https://github.com/dpa99c/cordova-plugin-firebasex/issues/124]). + +# Version 6.0.7 +* Merge PR [#93](https://github.com/dpa99c/cordova-plugin-firebasex/pull/93): Update Fabric dependencies +* Port code to apply IOS_STRIP_DEBUG plugin variable to Podfile into this plugin's hook scripts (from cordova-plugin-cocoapod-supportx). + * Fixes [#89](https://github.com/dpa99c/cordova-plugin-firebasex/issues/89). + +# Version 6.0.6 +* Fix parameter type passed to hasPermission success callback for Android. Fixes [#83](https://github.com/dpa99c/cordova-plugin-firebasex/issues/83). + +# Version 6.0.5 +* Fix `hasPermission()` to return boolean result on Android (same as iOS). + * Update docs to flag this as a breaking change from `cordova-plugin-firebase`. + * Resolves [#81](https://github.com/dpa99c/cordova-plugin-firebasex/issues/81). + +# Version 6.0.4 +* Replace dependency on `cordova-lib` with `xml2js`. +* (iOS) Restore placeholder GoogleService-Info.plist. + * Partially reverts a9c66746ca3592f0eec217f7701d5835f33b43c5 + * See [#74](https://github.com/dpa99c/cordova-plugin-firebasex/issues/74) +* (iOS) Handle and report native logical errors. + +# Version 6.0.3 +* (iOS) If grantPermission() is called when permission is already granted, return an error (rather than attempting to grant permission again which causes issues). + * See [#61](https://github.com/dpa99c/cordova-plugin-firebasex/issues/61) +* (iOS) Run badge number operations on UI thread (instead of background thread). + * Resolves [#72](https://github.com/dpa99c/cordova-plugin-firebasex/issues/72) +* (iOS) Handle situation where value of sound is not an NSString. + * See [#61](https://github.com/dpa99c/cordova-plugin-firebasex/issues/61) +* (iOS) Add try/catch handlers at all code entry points to handle unexpected exceptions in order to prevent app crashes. Log native exceptions to native and JS consoles. + * See [#61](https://github.com/dpa99c/cordova-plugin-firebasex/issues/61) +* Remove `google-services.json` and `GoogleService-Info.plist` placeholders. + * See [#63](https://github.com/dpa99c/cordova-plugin-firebasex/issues/63) + + +# Version 6.0.2 +* (Android) Improved exception handling to prevent app crashes due to plugin exceptions. +Document caveats of received message payload when notification message is received while app is not running on Android. +Further resolves [#52](https://github.com/dpa99c/cordova-plugin-firebasex/issues/52). + +# Version 6.0.1 +* (Android) Expose notification message properties in message object sent to onMessageReceived(). +Ensure message is always sent to onMessageReceived(), regardless if it was tapped. +Resolves [#52](https://github.com/dpa99c/cordova-plugin-firebasex/issues/52). + + +# Version 6.0.0 +* *BREAKING CHANGES* + * `onMessageReceived()` is now called when a message is received (data or notification) AND when a system notification is tapped (whether app is running or not) + * Resolves [#48](https://github.com/dpa99c/cordova-plugin-firebasex/issues/48). + * The `tap` parameter passed to `onMessageReceived()` is only set if a system notification is tapped + * If the system notification was tapped while the app is running in the foreground, the value will be `tap: "foreground"` + * If the system notification was tapped while the app is not running / in the background, the value will be `tap: "background"` + +# Version 5.0.0 +* *BREAKING CHANGES* + * `onNotificationOpen()` renamed to `onMessageReceived()` + * Changed key names for custom notification properties in FCM data messages to display system notifications in foreground. + * Message payload is always delivered to `onMessageReceived()` for both data and notification messages. + * `messageType` key indicates type of FCM message: `notification` or `data` + * `tap` is only set when `messageType` is `notification` + * Explicit dependency on `cordova-plugin-androidx-adapter` since Android implementation uses AndroidX so is incompatible with Android Support Library. + * Set `remote-notification` background mode in native Xcode project for iOS. + * Reworked plugin documentation. +* Support customisable display of system notifications while app is in foreground for both notification and data messages (both Android & iOS). +* Set default color accent and notification channel for FCM notifications. +* Add support for default and custom notification channels for Android 8+ + * Customise importance, visibility, LED light, badge number, notification sound and vibration pattern +* Calling `logError()` on Android now also logs to native logcat (as well as a non-fatal error to remote Crashlytics service). +* Fix `logError()` on iOS to log non-fatal error to remote Crashyltics service. +* Implement stubs for `hasPermission()` and `grantPermission()` on Android so they both return true in to the success callback. +* Rationalise permission check/request on iOS. +* Remove legacy support for iOS 9 and below. +* Support overridable default color accent for Android notification icons via `ANDROID_ICON_ACCENT` plugin variable. + +# Version 4.0.0 +* *BREAKING CHANGE:* set min supported versions to `cordova@9` and `cordova-ios@5`. + * Drop dependency on cordova-plugin-cocoapodsx to install pod dependencies. + * Instead update plugin.xml to use podspec formatting as required by cordova-ios@5. + * Remove iOS plugin variables as these are not (currently) supported by cordova-ios@5 + * Resolves [#22](https://github.com/dpa99c/cordova-plugin-firebasex/issues/22). + +# Version 3.0.8 +* \[iOS\] Add support for stripping debug symbols for libraries included via Cocoapods. Resolves [#28](https://github.com/dpa99c/cordova-plugin-firebasex/issues/28). + +# Version 3.0.7 +* \[iOS\] Ensure runpath search path contains `$(inherited)` to avoid build warnings/issues. Resolves [#25](https://github.com/dpa99c/cordova-plugin-firebasex/issues/25). + +# Version 3.0.6 +* Update iOS to Firebase SDK v6.3.0 (from v5.20.2) - major version increment so update source code for breaking changes to API. Resolves [#9](https://github.com/dpa99c/cordova-plugin-firebasex/issues/9). +* Add support for NDK crashlytics on Android. Resolves [#17](https://github.com/dpa99c/cordova-plugin-firebasex/issues/17). + +# Version 3.0.5 +* Bump min version of cordova-plugin-cocoapod-supportx to 1.7.2 which fixes bug when using a plugin variable to specify the `ios-min-version` in `<pods-config>` + +# Version 3.0.4 +* Bump min version of cordova-plugin-cocoapod-supportx to 1.7.1 which supports using a plugin variable to specify the `ios-min-version` in `<pods-config>` + +# Version 3.0.3 +* Implement didReceiveRegistrationToken delegate for iOS. Resolves [#16](https://github.com/dpa99c/cordova-plugin-firebasex/issues/16). +* Document dependency on Cocoapods. Resolves [#15](https://github.com/dpa99c/cordova-plugin-firebasex/issues/15). +* Make min iOS version configurable. Resolves [#14](https://github.com/dpa99c/cordova-plugin-firebasex/issues/14). + + +# Version 3.0.2 +* Update legacy Xpath reference to `<application>` element in `AndroidManifest.xml` + +# Version 3.0.1 +* Bump default iOS Firebase SDK version to 5.20.2 (https://firebase.google.com/support/release-notes/ios#version_5202_-_april_10_2019). Resolves [#8](https://github.com/dpa99c/cordova-plugin-firebasex/issues/8). + +# Version 3.0.0 +* Reapply: Support user-overriding of default Android Gradle & iOS Cocoapods versions using plugin variables. + +# Version 2.1.2 +* Revert: Support user-overriding of default Android Gradle & iOS Cocoapods versions using plugin variables. + * Since it's not working on iOS due to Cocoapods plugin dependency. + * Need to fix that plugin to handle plugin variables then reinstate this change in a major version release. + +# Version 2.1.1 +* Support user-overriding of default Android Gradle & iOS Cocoapods versions using plugin variables. + +# Version 2.1.0 +* Update Android source to use AndroidX class names and adds dependency on [cordova-plugin-androidx](https://github.com/dpa99c/cordova-plugin-androidx) for forward compatibility with future versions of Firebase libraries on Android. + * Note: if you include other plugins in your project which reference the legacy Android Support Library, you'll still need to include [cordova-plugin-androidx-adapter](https://github.com/dpa99c/cordova-plugin-androidx-adapter) in your project to dynamically patch them. +* Pins Firebase and Crashlytics Gradle dependencies to latest major version (to prevent build failures due to unexpected changes in subsequent major versions). +* Set minimum supported versions to `cordova@8+`, `cordova-android@8+`, `cordova-ios@4+`. + +# Version 2.0.7 +* Merge [PR #7](https://github.com/dpa99c/cordova-plugin-firebasex/pull/7): use `<pod>` instead of deprecated `<<framework type="podspec">`. Resolves [#5](https://github.com/dpa99c/cordova-plugin-firebasex/issues/5). + +# Version 2.0.6 +* Use Cocoapods to satisfy iOS Firebase SDK (rather than bundling with plugin). See https://github.com/arnesson/cordova-plugin-firebase/pull/972. +* Add support for logMessage() and sendCrash() functions (ported from cordova-fabric-plugin) +* Bump version of Crashlytics library on Android to current latest (v2.9.8 - Dec 2018) +* Bump Firebase SDK versions in iOS PodSpecs to latest version (v5.15.0) +* Remove redundant build-extras.gradle +* Set minimum iOS version to 9.0 in podspec +* Remove unnecessary extra <config-file> block which can lead to race condition +* Fixes issues cause by Firebase SDK updates on 5 April 2019 (https://firebase.google.com/support/release-notes/android#update_-_april_05_2019) which removed deprecated API features causing Android build failures. +See https://github.com/arnesson/cordov +* Fix compatibility with cordova@9 CLI +* Add explicit dependency on cordova-lib to prevent build error on iOS. Fixes #2. + +---> **FORKED FROM `cordova-plugin-firebase` AS `cordova-plugin-firebasex`** <--- + +# Version 2.0.5 + +### Bug Fixes +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/897">#897</a>: Fixed issue with after_prepare hook not copying required files + +# Version 2.0.4 + +### Bug Fixes +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/866">#866</a>: Fixed issue with loading .plist file on some iOS devices + +# Version 2.0.3 + +### Features +- <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/874">#874</a>: Added new api `setCrashlyticsUserId` which allows setting Crashlytics user identifier +- <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/861">#861</a>: Updated `verifyPhoneNumber` api on android to add the following properties to the returned object: + - `code` - sms code + - `verified` - whether or not the verification was successful + +### Bug Fixes +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/869">#869</a>: Replace add/remove hooks with install/uninstall hooks to ensure proper configuration of the plugin +- <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/870">#870</a>: Add error handling to `fetch` api on iOS + +# Version 2.0.2 + +### Bug Fixes +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/837">#837</a>: Fixed android build + +# Version 2.0.1 + +### Bug Fixes +- <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/836">#836</a>: Fixed Crashlytics on iOS +- <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/830">#830</a>: Fixed initialization of firebase services + +# Version 2.0.0 + +### Features +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/796">#796</a>: Update Firebase SDK Version to 5.x + +### Bug Fixes +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/822">#822</a>: Can't use initFirebase() on 1.1.3 [Firebase isn't initialized] +- <a href="https://github.com/arnesson/cordova-plugin-firebase/issues/827">#827</a>: doc missing: initFirebase call needed before anything +- <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/824">#824</a>: Removed initRemoteConfig method + +# Version 1.1.4 (deprecated) + +This version has been deprecated due to complications with PR <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/784">#784</a> + +# Version 1.1.3 (deprecated) + +This version has been deprecated due to complications with PR <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/784">#784</a> + +# Version 1.1.2 (deprecated) + +This version has been deprecated due to complications with PR <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/784">#784</a> + +# Version 1.1.1 (deprecated) + +This version has been deprecated due to complications with PR <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/784">#784</a> + +# Version 1.1.0 (deprecated) + +This version has been deprecated due to complications with PR <a href="https://github.com/arnesson/cordova-plugin-firebase/pull/784">#784</a> + +# Version 1.0.5 + +To force cordova to use this version, add the following to your project's config.xml: +``` +<plugin name="cordova-plugin-firebase" spec="1.0.5" /> +``` +or by running: +``` +cordova plugin add cordova-plugin-firebase@1.0.5 --save +``` diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/CODE_OF_CONDUCT.md b/StoneIsland/plugins/cordova-plugin-firebasex/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..3017b5b0 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at bsoumakian@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/CONTRIBUTING.md b/StoneIsland/plugins/cordova-plugin-firebasex/CONTRIBUTING.md new file mode 100644 index 00000000..8c1cac74 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/CONTRIBUTING.md @@ -0,0 +1,65 @@ +# Contribution Guidelines + +# Find a bug? + +No one is perfect and we aren't any different. If you find an issue, please take a few minutes to let us know. + +1. Take a look at the current issues (there's a handy search feature) to see if someone already reported the issue. If they have, there might be work arounds or proposed fixes posted in the issue which could save you time. +2. If the issue have not been reported, please open an issue. +3. Look for questions or updates to your issue as we might need additioanl information. The faster we get the information, the faster we can resolve your issue. +4. The fastest way to fix your issue is to fix the bug yourself. See the "Have a fix or want to get your hands dirty?" section below to find out how to show off your awesome developer skills! + +## Help Wanted flag + +This plugin is maintained by a community of developers. We do this in our spare time and don't have unlimited time to implement features or fix bugs. As such, we look to others who can submit pull requests to fix bugs or make enhancements. + +# Have a fix or want to get your hands dirty? + +It's really not that hard! If you have questions please don't hesitate to ask in an issue as we can try to help point you in the right direction. + +## Where is the code? + +### Javascript APIs + +You can find the Javscipt APIs in [firebase.js](www/firebase.js) file. This file typically redirects calls to the FirebasePlugin implementation for the platform, but if you need to add APIs, this is where you do it. + +### Android + +There are a number of files that make up the Android platform code, but the main file is [Firebase.java](src/android/FirebasePlugin.java). That is the best place to start. + +### iOS + +Again, there are multiple files that make up the iOS platform, but most of the code is split between [FirebasePlugin.m](src/ios/FirebasePlugin.m) and [AppDelegate+FirebasePlugin.m](src/ios/AppDelegate+FirebasePlugin.m). + +## I found the code, but now what? + +Submitting a bug fix or feature takes only a few minutes. + +1. Fork the repository. +2. Create a new branch. +3. Make the code change. +4. Create a commit and push it to your repo. +5. See the Pull Request section to let us know your code is ready to be merged into the main repo. + +MAKE SURE THE CODE WORKS WITHOUT MODIFYING OR CHECKING IN ANY PLATFORM FILES. Any changes to platform files (like build scripts, config files or anything in the /platform directory) should be made by the plugin. Since Cordova 4.3.0, the [platform management feature](https://cordova.apache.org/docs/en/latest/platform_plugin_versioning_ref/) allows you to build your project without checking in any platform files. + +# Pull Requests + +* Fill in [the required template](PULL_REQUEST_TEMPLATE.md) +* Include one feature/bug fix per Pull Request. Multiple issues in one PR can increase the complexity of the review and could delay the merging of your code. +* Maintain the formatting (specifically white spacing) in the files you are modifying +* Reference the Issue number in the PR if there's a related issue +* If you are adding new APIs or changing behavior, include entries in the README.md so new users know how to interact with the new features. We want everyone to use your work! + +## Need to test a PR? +We rely on the community to help test out fixes and enhancements to this plugin. You can test out a PR by running the following commands: +1. `cordova plugin remove cordova-plugin-firebase` +2. `cordova plugin add https://github.com/<username>/cordova-plugin-firebase.git#<branch>` + * replace `<username>` with the name of user/org where the branch resides + * replace `<branch>` with the name of the branch used to create the PR +3. `cordova prepare` + +For example, to test the fix made by PR [#832](https://github.com/arnesson/cordova-plugin-firebase/pull/832#issuecomment-420386486), you would use the url `https://github.com/briantq/cordova-plugin-firebase.git#revert-lazy-init` since `briantq` is the name of the user and `revert-lazy-init` is the name of the branch. This information is available at the top of each PR. For this specific PR, the following information is displayed: +* briantq wants to merge 2 commits into arnesson:master from briantq:revert-lazy-init + +The last part being the vital information as it tells you exactly what to use in the url. diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/LICENSE b/StoneIsland/plugins/cordova-plugin-firebasex/LICENSE new file mode 100644 index 00000000..40d6a7d0 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Dave Alden + +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/StoneIsland/plugins/cordova-plugin-firebasex/README.md b/StoneIsland/plugins/cordova-plugin-firebasex/README.md new file mode 100644 index 00000000..befafcec --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/README.md @@ -0,0 +1,3051 @@ +cordova-plugin-firebasex [](https://www.npmjs.com/package/cordova-plugin-firebasex) [](https://npm-stat.com/charts.html?package=cordova-plugin-firebasex) +======================== + +Brings push notifications, analytics, event tracking, crash reporting and more from Google Firebase to your Cordova project. + +Supported platforms: Android and iOS + +**IMPORTANT:** Before opening an issue against this plugin, please read [Reporting issues](#reporting-issues). + +# cli_build branch +This branch of the plugin is specifically intended for those building (directly or indirectly) via the Cordova CLI. +It removes the Firebase Inapp Messaging and Google Tag Manager SDK components due to these causing CLI builds to fail (see [#326](https://github.com/dpa99c/cordova-plugin-firebasex/issues/326)). + +To use it, install an npm release with the `-cli` suffix, e.g.: + + cordova plugin add cordova-plugin-firebasex@9.0.1-cli + +Or install it directly from this branch: + + cordova plugin add https://github.com/dpa99c/cordova-plugin-firebasex#cli_build + +If you wish to use either of these components, please use the [master](https://github.com/dpa99c/cordova-plugin-firebasex) branch or install a major plugin release via the NPM registry and build using Xcode. + +<!-- DONATE --> +[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZRD3W47HQ3EMJ) + +I dedicate a considerable amount of my free time to developing and maintaining this Cordova plugin, along with my other Open Source software. +To help ensure this plugin is kept updated, new features are added and bugfixes are implemented quickly, please donate a couple of dollars (or a little more if you can stretch) as this will help me to afford to dedicate time to its maintenance. Please consider donating if you're using this plugin in an app that makes you money, if you're being paid to make the app, if you're asking for new features or priority bug fixes. +<!-- END DONATE --> + + +<!-- START doctoc generated TOC please keep comment here to allow auto update --> +<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> +**Table of Contents** + +- [Installation](#installation) + - [Plugin variables](#plugin-variables) + - [Android & iOS](#android--ios) + - [Android only](#android-only) + - [iOS only](#ios-only) + - [Supported Cordova Versions](#supported-cordova-versions) + - [Supported Mobile Platform Versions](#supported-mobile-platform-versions) + - [Migrating from cordova-plugin-firebase](#migrating-from-cordova-plugin-firebase) + - [Breaking API changes](#breaking-api-changes) + - [Ionic 4+](#ionic-4) + - [Ionic 3](#ionic-3) +- [Build environment notes](#build-environment-notes) + - [PhoneGap Build](#phonegap-build) + - [Android-specific](#android-specific) + - [Specifying Android library versions](#specifying-android-library-versions) + - [AndroidX](#androidx) + - [Google Play Services and Firebase libraries](#google-play-services-and-firebase-libraries) + - [iOS-specific](#ios-specific) + - [Specifying iOS library versions](#specifying-ios-library-versions) + - [Cocoapods](#cocoapods) + - [Out-of-date pods](#out-of-date-pods) + - [Strip debug symbols](#strip-debug-symbols) + - [Cordova CLI builds](#cordova-cli-builds) +- [Firebase config setup](#firebase-config-setup) +- [Disable data collection on startup](#disable-data-collection-on-startup) +- [Example project](#example-project) +- [Reporting issues](#reporting-issues) + - [Reporting a bug or problem](#reporting-a-bug-or-problem) + - [Requesting a new feature](#requesting-a-new-feature) +- [Cloud messaging](#cloud-messaging) + - [Background notifications](#background-notifications) + - [Foreground notifications](#foreground-notifications) + - [Android notifications](#android-notifications) + - [Android background notifications](#android-background-notifications) + - [Android foreground notifications](#android-foreground-notifications) + - [Android Notification Channels](#android-notification-channels) + - [Android 7 and below](#android-7-and-below) + - [Android Notification Icons](#android-notification-icons) + - [Android Default Notification Icon](#android-default-notification-icon) + - [Android Large Notification Icon](#android-large-notification-icon) + - [Android Custom Notification Icons](#android-custom-notification-icons) + - [Android Notification Color](#android-notification-color) + - [Android Notification Sound](#android-notification-sound) + - [Android 8.0 and above](#android-80-and-above) + - [On Android 7 and below](#on-android-7-and-below) + - [iOS notifications](#ios-notifications) + - [iOS background notifications](#ios-background-notifications) + - [iOS notification sound](#ios-notification-sound) + - [iOS badge number](#ios-badge-number) + - [iOS actionable notifications](#ios-actionable-notifications) + - [Data messages](#data-messages) + - [Data message notifications](#data-message-notifications) + - [Android data message notifications](#android-data-message-notifications) + - [iOS data message notifications](#ios-data-message-notifications) + - [Custom FCM message handling](#custom-fcm-message-handling) + - [Android](#android) + - [iOS](#ios) + - [Example](#example) +- [InApp Messaging](#inapp-messaging) +- [Google Tag Manager](#google-tag-manager) + - [Android](#android-1) + - [iOS](#ios-1) +- [API](#api) + - [Notifications and data messages](#notifications-and-data-messages) + - [getToken](#gettoken) + - [getId](#getid) + - [onTokenRefresh](#ontokenrefresh) + - [getAPNSToken](#getapnstoken) + - [onApnsTokenReceived](#onapnstokenreceived) + - [onMessageReceived](#onmessagereceived) + - [grantPermission](#grantpermission) + - [hasPermission](#haspermission) + - [unregister](#unregister) + - [isAutoInitEnabled](#isautoinitenabled) + - [setAutoInitEnabled](#setautoinitenabled) + - [setBadgeNumber](#setbadgenumber) + - [getBadgeNumber](#getbadgenumber) + - [clearAllNotifications](#clearallnotifications) + - [subscribe](#subscribe) + - [unsubscribe](#unsubscribe) + - [createChannel](#createchannel) + - [setDefaultChannel](#setdefaultchannel) + - [Default Android Channel Properties](#default-android-channel-properties) + - [deleteChannel](#deletechannel) + - [listChannels](#listchannels) + - [Analytics](#analytics) + - [setAnalyticsCollectionEnabled](#setanalyticscollectionenabled) + - [isAnalyticsCollectionEnabled](#isanalyticscollectionenabled) + - [logEvent](#logevent) + - [setScreenName](#setscreenname) + - [setUserId](#setuserid) + - [setUserProperty](#setuserproperty) + - [Crashlytics](#crashlytics) + - [setCrashlyticsCollectionEnabled](#setcrashlyticscollectionenabled) + - [isCrashlyticsCollectionEnabled](#iscrashlyticscollectionenabled) + - [setCrashlyticsUserId](#setcrashlyticsuserid) + - [sendCrash](#sendcrash) + - [logMessage](#logmessage) + - [logError](#logerror) + - [Authentication](#authentication) + - [isUserSignedIn](#isusersignedin) + - [signOutUser](#signoutuser) + - [getCurrentUser](#getcurrentuser) + - [reloadCurrentUser](#reloadcurrentuser) + - [updateUserProfile](#updateuserprofile) + - [updateUserEmail](#updateuseremail) + - [sendUserEmailVerification](#senduseremailverification) + - [updateUserPassword](#updateuserpassword) + - [sendUserPasswordResetEmail](#senduserpasswordresetemail) + - [deleteUser](#deleteuser) + - [createUserWithEmailAndPassword](#createuserwithemailandpassword) + - [signInUserWithEmailAndPassword](#signinuserwithemailandpassword) + - [signInUserWithCustomToken](#signinuserwithcustomtoken) + - [signInUserAnonymously](#signinuseranonymously) + - [verifyPhoneNumber](#verifyphonenumber) + - [Android](#android-2) + - [iOS](#ios-2) + - [authenticateUserWithGoogle](#authenticateuserwithgoogle) + - [Android](#android-3) + - [authenticateUserWithApple](#authenticateuserwithapple) + - [iOS](#ios-3) + - [Android](#android-4) + - [signInWithCredential](#signinwithcredential) + - [linkUserWithCredential](#linkuserwithcredential) + - [reauthenticateWithCredential](#reauthenticatewithcredential) + - [registerAuthStateChangeListener](#registerauthstatechangelistener) + - [Remote Config](#remote-config) + - [fetch](#fetch) + - [activateFetched](#activatefetched) + - [getValue](#getvalue) + - [getByteArray](#getbytearray) + - [getInfo](#getinfo) + - [setConfigSettings](#setconfigsettings) + - [setDefaults](#setdefaults) + - [Performance](#performance) + - [setPerformanceCollectionEnabled](#setperformancecollectionenabled) + - [isPerformanceCollectionEnabled](#isperformancecollectionenabled) + - [startTrace](#starttrace) + - [incrementCounter](#incrementcounter) + - [stopTrace](#stoptrace) + - [Firestore](#firestore) + - [addDocumentToFirestoreCollection](#adddocumenttofirestorecollection) + - [setDocumentInFirestoreCollection](#setdocumentinfirestorecollection) + - [updateDocumentInFirestoreCollection](#updatedocumentinfirestorecollection) + - [deleteDocumentFromFirestoreCollection](#deletedocumentfromfirestorecollection) + - [documentExistsInFirestoreCollection](#documentexistsinfirestorecollection) + - [fetchDocumentInFirestoreCollection](#fetchdocumentinfirestorecollection) + - [fetchFirestoreCollection](#fetchfirestorecollection) +- [Credits](#credits) + +<!-- END doctoc generated TOC please keep comment here to allow auto update --> + +# Installation +Install the plugin by adding it to your project's config.xml: +```xml +<plugin name="cordova-plugin-firebasex" spec="latest" /> +``` +or by running: +``` +cordova plugin add cordova-plugin-firebasex +``` + +## Plugin variables +The following Cordova plugin variables are supported by the plugin. +Note that these must be set at plugin installation time. If you wish to change plugin variables, you'll need to uninstall the plugin and reinstall it with the new variable values. + +### Android & iOS +- `FIREBASE_ANALYTICS_COLLECTION_ENABLED` - whether to automatically enable Firebase Analytics data collection on app startup +- `FIREBASE_PERFORMANCE_COLLECTION_ENABLED` - whether to automatically enable Firebase Performance data collection on app startup +- `FIREBASE_CRASHLYTICS_COLLECTION_ENABLED` - whether to automatically enable Firebase Crashlytics data collection on app startup +See [Disable data collection on startup](#disable-data-collection-on-startup) for more info. + +### Android only +The following plugin variables are used to specify the Firebase SDK versions as Gradle dependencies on Android: +- `ANDROID_PLAY_SERVICES_TAGMANAGER_VERSION` +- `ANDROID_PLAY_SERVICES_AUTH_VERSION` +- `ANDROID_FIREBASE_ANALYTICS_VERSION` +- `ANDROID_FIREBASE_MESSAGING_VERSION` +- `ANDROID_FIREBASE_CONFIG_VERSION` +- `ANDROID_FIREBASE_PERF_VERSION` +- `ANDROID_FIREBASE_AUTH_VERSION` +- `ANDROID_FIREBASE_FIRESTORE_VERSION` +- `ANDROID_FIREBASE_CRASHLYTICS_VERSION` +- `ANDROID_FIREBASE_CRASHLYTICS_NDK_VERSION` +- `ANDROID_GSON_VERSION` +See [Specifying Android library versions](#specifying-android-library-versions) for more info. + +- `ANDROID_ICON_ACCENT` - sets the default accent color for system notifications. See [Android Notification Color](#android-notification-color) for more info. +- `ANDROID_FIREBASE_CONFIG_FILEPATH` - sets a custom filepath to `google-services.json` file as a path relative to the project root + - e.g. `--variable ANDROID_FIREBASE_CONFIG_FILEPATH="resources/android/google-services.json"` + +### iOS only +- `IOS_STRIP_DEBUG` - prevents symbolification of all libraries included via Cocoapods. See [Strip debug symbols](#strip-debug-symbols) for more info. + - e.g. `--variable IOS_STRIP_DEBUG=true` + - Defaults to `false` if not specified. +- `SETUP_RECAPTCHA_VERIFICATION` - automatically sets up reCAPTCHA verification for phone authentication on iOS. See [verifyPhoneNumber](#verifyphonenumber) for more info. + - e.g. `--variable IOS_STRIP_DEBUG=true` + - Defaults to `false` if not specified. +- `IOS_SHOULD_ESTABLISH_DIRECT_CHANNEL` - If `true` Firebase Messaging will automatically establish a socket-based, direct channel to the FCM server. + - e.g. `--variable IOS_SHOULD_ESTABLISH_DIRECT_CHANNEL=true` + - Defaults to `false` if not specified. + - See [`shouldEstablishDirectChannel`](https://firebase.google.com/docs/reference/ios/firebasemessaging/api/reference/Classes/FIRMessaging#/c:objc(cs)FIRMessaging(py)shouldEstablishDirectChannel) + - Note: Firebase Messaging iOS SDK version 7.0 will be a breaking change where the SDK will no longer support iOS Direct Channel API. +- `IOS_FIREBASE_CONFIG_FILEPATH` - sets a custom filepath to `GoogleService-Info.plist` file as a path relative to the project root + - e.g. `--variable IOS_FIREBASE_CONFIG_FILEPATH="resources/ios/GoogleService-Info.plist"` + +## Supported Cordova Versions +- cordova: `>= 9` +- cordova-android: `>= 8` +- cordova-ios: `>= 5` + +## Supported Mobile Platform Versions +- Android `>= 4.1` +- iOS `>= 10.0` + +## Migrating from cordova-plugin-firebase +This plugin is a fork of [cordova-plugin-firebase](https://github.com/arnesson/cordova-plugin-firebase) which has been reworked to fix issues and add new functionality. +If you already have [cordova-plugin-firebase](https://github.com/arnesson/cordova-plugin-firebase) installed in your Cordova project, you need to completely remove it before installing this plugin otherwise they will conflict and cause build errors in your project. The safest way of doing this is as follows: + + rm -Rf platforms/android + cordova plugin rm cordova-plugin-firebase + rm -Rf plugins/ node_modules/ + npm install + cordova plugin add cordova-plugin-firebasex + cordova platform add android + +### Breaking API changes +**IMPORTANT:** Recent versions of `cordova-plugin-firebasex` have made breaking changes to the plugin API in order to fix bugs or add more functionality. +Therefore you can no longer directly substitute `cordova-plugin-firebasex` in place of `cordova-plugin-firebase` without making code changes. + +You should be aware of the following breaking changes compared with `cordova-plugin-firebase`: +* Minimum supported Cordova versions + * `cordova@9` (CLI) + * `cordova-android@8` (Android platform) + * `cordova-ios@5` (iOS platform) +* Migrated to AndroidX from legacy Android Support Library + * add dependency on [cordova-plugin-androidx](https://github.com/dpa99c/cordova-plugin-androidx) and [cordova-plugin-androidx-adapter](https://github.com/dpa99c/cordova-plugin-androidx-adapter) +* Migrated to Cocoapods to satisfy Firebase SDK dependencies on iOS +* `onNotificationOpen()` renamed to `onMessageReceived()` + * `tap` parameter is only set when user taps on a notification (not when a message is received from FCM) + * `tap=foreground|background` instead of `tap=true|false` +* `hasPermission()` receives argument as a boolean (rather than an object with `isEnabled` key) + * e.g. `FirebasePlugin.hasPermission(function(hasPermission){ + console.log("Permission is " + (hasPermission ? "granted" : "denied")); + });` +* Adds support for foreground notifications and data notification messages + +### Ionic 4+ +Ionic Native provides a [FirebaseX Typescript wrapper](https://ionicframework.com/docs/native/firebase-x) for using `cordova-plugin-firebasex` with Ionic v4, v5 and above. +Please see their documentation for usage. + +First install the package. + +``` +ionic cordova plugin add cordova-plugin-firebasex +npm install @ionic-native/firebase-x +``` + +If you're using Angular, register it in your component/service's `NgModule` (for example, app.module.ts) as a provider. + +```typescript +import { FirebaseX } from "@ionic-native/firebase-x/ngx"; + +@NgModule({ + //declarations, imports... + providers: [ + FirebaseX, + //other providers... + ] +}) +``` + +Then you're good to go. +```typescript +import { FirebaseX } from "@ionic-native/firebase-x/ngx"; + +//... + +constructor(private firebase: FirebaseX) + +this.firebase.getToken().then(token => console.log(`The token is ${token}`)) +this.firebase.onMessageReceived().subscribe(data => console.log(`FCM message: ${data}`)); +``` + +**NOTE:** +- This plugin provides only the Javascript API as documented below. +- The Typescript wrapper is owned and maintain by Ionic. +- Please [report any issues](https://github.com/ionic-team/ionic-native/issues) against the [Ionic Native repo](https://github.com/ionic-team/ionic-native/), not this one. +- Any issues opened against this repo which relate to the Typescript wrapper **will be closed immediately**. + + +### Ionic 3 +The above PR does not work for Ionic 3 so you (currently) can't use the [Ionic Native Firebase](https://ionicframework.com/docs/native/firebase) Typescript wrapper with Ionic 3. +(i.e. `import { Firebase } from "@ionic-native/firebase"` will not work). + +To use `cordova-plugin-firebasex` with Ionic 3, you'll need to call its Javascript API directly from your Typescript app code, for example: + +```typescript +(<any>window).FirebasePlugin.getToken(token => console.log(`token: ${token}`)) + +(<any>window).FirebasePlugin.onMessageReceived((message) => { + if (message.tap) { console.log(`Notification was tapped in the ${message.tap}`); } +}) +``` + +If you want to make the `onMessageReceived()` JS API behave like the Ionic Native wrapper: + +```javascript +onNotificationOpen() { + return new Observable(observer => { + (window as any).FirebasePlugin.onMessageReceived((response) => { + observer.next(response); + }); + }); +} +... +this.onNotificationOpen().subscribe(data => console.log(`FCM message: ${data}`)); +``` + +See the [cordova-plugin-firebasex-ionic3-test](https://github.com/dpa99c/cordova-plugin-firebasex-ionic3-test) example project for a demonstration of how to use the plugin with Ionic 3. + +# Build environment notes + +## PhoneGap Build +This plugin will not work with Phonegap Build (and other remote cloud build envs) do not support Cordova hook scripts as they are used by this plugin to configure the native platform projects. + +## Android-specific + +### Specifying Android library versions +This plugin depends on various components such as the Firebase SDK which are pulled in at build-time by Gradle on Android. +By default this plugin pins specific versions of these in [its `plugin.xml`](https://github.com/dpa99c/cordova-plugin-firebase/blob/master/plugin.xml) where you can find the currently pinned versions as `<preference>`'s, for example: + +```xml +<preference name="ANDROID_FIREBASE_ANALYTICS_VERSION" default="17.0.0" /> +``` + +The Android defaults can be overridden at plugin installation time by specifying plugin variables as command-line arguments, for example: + + cordova plugin add cordova-plugin-firebasex --variable ANDROID_FIREBASE_ANALYTICS_VERSION=17.0.0 + +Or you can specify them as plugin variables in your `config.xml`, for example: + +```xml +<plugin name="cordova-plugin-firebasex" spec="latest"> + <variable name="ANDROID_FIREBASE_ANALYTICS_VERSION" value="17.0.0" /> +</plugin> +``` + +The following plugin variables are used to specify the following Gradle dependency versions on Android: + +- `ANDROID_PLAY_SERVICES_TAGMANAGER_VERSION` => `com.google.android.gms:play-services-tagmanager` +- `ANDROID_PLAY_SERVICES_AUTH_VERSION` => `com.google.android.gms:play-services-auth` +- `ANDROID_FIREBASE_ANALYTICS_VERSION` => `com.google.firebase:firebase-analytics` +- `ANDROID_FIREBASE_MESSAGING_VERSION` => `com.google.firebase:firebase-messaging` +- `ANDROID_FIREBASE_CONFIG_VERSION` => `com.google.firebase:firebase-config` +- `ANDROID_FIREBASE_PERF_VERSION` => `com.google.firebase:firebase-perf` +- `ANDROID_FIREBASE_AUTH_VERSION` => `com.google.firebase:firebase-auth` +- `ANDROID_FIREBASE_FIRESTORE_VERSION` => `com.google.firebase:firebase-firestore` +- `ANDROID_FIREBASE_CRASHLYTICS_VERSION` => `com.google.firebase:firebase-crashlytics` +- `ANDROID_FIREBASE_CRASHLYTICS_NDK_VERSION` => `com.google.firebase:firebase-crashlytics-ndk` +- `ANDROID_GSON_VERSION` => `com.google.code.gson:gson` + +For example: + + cordova plugin add cordova-plugin-firebasex \ + --variable ANDROID_PLAY_SERVICES_TAGMANAGER_VERSION=17.0.0 \ + --variable ANDROID_PLAY_SERVICES_AUTH_VERSION=17.0.0 \ + --variable ANDROID_FIREBASE_ANALYTICS_VERSION=17.0.0 \ + --variable ANDROID_FIREBASE_MESSAGING_VERSION=19.0.0 \ + --variable ANDROID_FIREBASE_CONFIG_VERSION=18.0.0 \ + --variable ANDROID_FIREBASE_PERF_VERSION=18.0.0 \ + --variable ANDROID_FIREBASE_AUTH_VERSION=18.0.0 \ + --variable ANDROID_FIREBASE_CRASHLYTICS_VERSION=17.0.1 \ + --variable ANDROID_FIREBASE_CRASHLYTICS_NDK_VERSION=17.0.1 \ + +### AndroidX +This plugin has been migrated to use [AndroidX (Jetpack)](https://developer.android.com/jetpack/androidx/migrate) which is the successor to the [Android Support Library](https://developer.android.com/topic/libraries/support-library/index). +This is implemented by adding a dependency on [cordova-plugin-androidx](https://github.com/dpa99c/cordova-plugin-androidx) which enables AndroidX in the Android platform of a Cordova project. + +This is because the [major release of the Firebase and Play Services libraries on 17 June 2019](https://developers.google.com/android/guides/releases#june_17_2019) were migrated to AndroidX. + +Therefore if your project includes any plugins which are dependent on the legacy Android Support Library, you should add [cordova-plugin-androidx-adapter](https://github.com/dpa99c/cordova-plugin-androidx-adapter) to your project. +This plugin will dynamically migrate any plugin code from the Android Support Library to AndroidX equivalents. + +## Google Play Services and Firebase libraries +Your Android build may fail if you are installing multiple plugins that use the Google Play Services library. +This is caused by plugins installing different versions of the Google Play Services library. +This can be resolved by installing [cordova-android-play-services-gradle-release](https://github.com/dpa99c/cordova-android-play-services-gradle-release) which enables you to override the versions specified by other plugins in order to align them. + +Similarly, if your build is failing because multiple plugins are installing different versions of the Firebase library, +you can try installing [cordova-android-firebase-gradle-release](https://github.com/dpa99c/cordova-android-firebase-gradle-release) to align these. + +## iOS-specific +Please ensure you have the latest Xcode release version installed to build your app - direct download links can be [found here](https://stackoverflow.com/a/10335943/777265). + +### Specifying iOS library versions +This plugin depends on various components such as the Firebase SDK which are pulled in at build-time by Cocoapods on iOS. +This plugin pins specific versions of these in [its `plugin.xml`](https://github.com/dpa99c/cordova-plugin-firebase/blob/master/plugin.xml) where you can find the currently pinned iOS versions in the `<pod>`'s, for example: + + <pod name="Firebase/Core" spec="6.3.0"/> + +**It is currently not possible to override these at plugin installation time** because `cordova@9`/`cordova-ios@5` does not support the use of plugin variables in the `<pod>`'s `spec` attribute. +Therefore if you need to change the specified versions, you'll currently need to do this by forking the plugin and editing the `plugin.xml` to change the specified `spec` values. + +### Cocoapods +This plugin relies on `cordova@9`/`cordova-ios@5` support for the [CocoaPods dependency manager]( https://cocoapods.org/) in order to satisfy the iOS Firebase SDK library dependencies. + +Therefore please make sure you have `cocoapods@>=1.9` installed in your iOS build environment - setup instructions can be found [here](https://cocoapods.org/). + +If building your project in Xcode, you need to open `YourProject.xcworkspace` (not `YourProject.xcodeproj`) so both your Cordova app project and the Pods project will be loaded into Xcode. + +You can list the pod dependencies in your Cordova iOS project by installing [cocoapods-dependencies](https://github.com/segiddins/cocoapods-dependencies): + + sudo gem install cocoapods-dependencies + cd platforms/ios/ + pod dependencies + +### Out-of-date pods +If you receive a build error such as this: + + None of your spec sources contain a spec satisfying the dependencies: `Firebase/Analytics (~> 6.1.0), Firebase/Analytics (= 6.1.0, ~> 6.1.0)`. + +Make sure your local Cocoapods repo is up-to-date by running `pod repo update` then run `pod install` in `/your_project/platforms/ios/`. + +### Strip debug symbols +If your iOS app build contains too many debug symbols (i.e. because you include lots of libraries via a Cocoapods), you might get an error (e.g. [issue #28](https://github.com/dpa99c/cordova-plugin-firebase/issues/28)) when you upload your binary to App Store Connect, e.g.: + + ITMS-90381: Too many symbol files - These symbols have no corresponding slice in any binary [16EBC8AC-DAA9-39CF-89EA-6A58EB5A5A2F.symbols, 1B105D69-2039-36A4-A04D-96C1C5BAF235.symbols, 476EACDF-583B-3B29-95B9-253CB41097C8.symbols, 9789B03B-6774-3BC9-A8F0-B9D44B08DCCB.symbols, 983BAE60-D245-3291-9F9C-D25E610846AC.symbols]. + +To prevent this, you can set the `IOS_STRIP_DEBUG` plugin variable which prevents symbolification of all libraries included via Cocoapods ([see here for more information](https://stackoverflow.com/a/48518656/777265)): + + cordova plugin add cordova-plugin-firebasex --variable IOS_STRIP_DEBUG=true + +By default this preference is set to `false`. + +Note: if you enable this setting, any crashes that occur within libraries included via Cocopods will not be recorded in Crashlytics or other crash reporting services. + +### Cordova CLI builds +If you are building (directly or indirectly) via the Cordova CLI and a build failures on iOS such as the one below: + + error: Resource "/Build/Products/Debug-iphonesimulator/FirebaseInAppMessaging/InAppMessagingDisplayResources.bundle" not found. Run 'pod install' to update the copy resources script. + + +This is likely due to [an issue with Cordova CLI builds for iOS](https://github.com/apache/cordova-ios/issues/659) when including certain pods into the build (see [#326](https://github.com/dpa99c/cordova-plugin-firebasex/issues/326)): + +Note that building from Xcode works fine, so if you are able then do this. + +Otherwise (e.g. if building via a CI) then you'll need to switch to using the [cli_build branch](https://github.com/dpa99c/cordova-plugin-firebasex/tree/cli_build) of this plugin: + + cordova plugin rm cordova-plugin-firebasex && cordova plugin add cordova-plugin-firebasex@latest-cli + +This removes the Firebase Inapp Messaging and Google Tag Manager SDK components that are causing the build issues. +The `cli_build` branch is kept in sync with `master` but without the above components. + +You can validate your CLI build environment using [this publicly-available `GoogleService-Info.plist`](https://github.coventry.ac.uk/301CEM-1920OCTJAN/301CEM-6957713/raw/master/CanaryApparel/GoogleService-Info.plist): + + cordova create test com.canary.CanaryApparel && cd test + curl https://github.coventry.ac.uk/raw/301CEM-1920OCTJAN/301CEM-6957713/master/CanaryApparel/GoogleService-Info.plist -o GoogleService-Info.plist + cordova plugin add cordova-plugin-firebasex@latest-cli + cordova platform add ios + cordova build ios --emulator + #build succeeds + +Following the installation steps above, modify the `package.json` file to pin the `cli` variant of this package by removing the `^` or `~` prefix from the package declaration. Failure to do this will result in build issues the next time the `cordova prepare` steps are performed as the non-cli version of the package will replace the cli variant. +``` + "dependencies": { + "cordova-android": "~8.1.0", + "cordova-ios": "^6.1.0", + "cordova-plugin-androidx": "^2.0.0", + "cordova-plugin-androidx-adapter": "^1.1.1", + "cordova-plugin-firebasex": "^10.1.2-cli" --> Change to "10.1.2-cli" + }, +``` + +# Firebase config setup +There's a handy [installation and setup guide on medium.com](https://medium.com/@felipepucinelli/how-to-add-push-notifications-in-your-cordova-application-using-firebase-69fac067e821). +However, if using this, remember this forked plugin is `cordova-plugin-firebasex` (not `cordova-plugin-firebase`). + +Download your Firebase configuration files, `GoogleService-Info.plist` for iOS and `google-services.json` for android, and place them in the root folder of your cordova project. +Check out this [firebase article](https://support.google.com/firebase/answer/7015592) for details on how to download the files. + +``` +- My Project/ + platforms/ + plugins/ + www/ + config.xml + google-services.json <-- + GoogleService-Info.plist <-- + ... +``` + +Or you can set custom location for your platform configuration files using plugin variables in your `config.xml`: + +``` +<plugin name="cordova-plugin-firebasex"> + <variable name="ANDROID_FIREBASE_CONFIG_FILEPATH" value="resources/android/google-services.json" /> + <variable name="IOS_FIREBASE_CONFIG_FILEPATH" value="resources/ios/GoogleService-Info.plist" /> +</plugin> +``` + +IMPORTANT: The Firebase SDK requires the configuration files to be present and valid, otherwise your app will crash on boot or Firebase features won't work. + +# Disable data collection on startup +By default, analytics, performance and Crashlytics data will begin being collected as soon as the app starts up. +However, for data protection or privacy reasons, you may wish to disable data collection until such time as the user has granted their permission. + +To do this, set the following plugin variables to `false` at plugin install time: + +* `FIREBASE_ANALYTICS_COLLECTION_ENABLED` +* `FIREBASE_PERFORMANCE_COLLECTION_ENABLED` +* `FIREBASE_CRASHLYTICS_COLLECTION_ENABLED` + + + cordova plugin add cordova-plugin-firebasex \ + --variable FIREBASE_ANALYTICS_COLLECTION_ENABLED=false \ + --variable FIREBASE_PERFORMANCE_COLLECTION_ENABLED=false \ + --variable FIREBASE_CRASHLYTICS_COLLECTION_ENABLED=false + +This will disable data collection (on both Android & iOS) until you call [setAnalyticsCollectionEnabled](#setanalyticscollectionenabled), [setPerformanceCollectionEnabled](#setperformancecollectionenabled) and [setCrashlyticsCollectionEnabled](#setcrashlyticscollectionenabled): + + FirebasePlugin.setAnalyticsCollectionEnabled(true); + FirebasePlugin.setPerformanceCollectionEnabled(true); + FirebasePlugin.setCrashlyticsCollectionEnabled(true); + +Notes: +- Calling `setXCollectionEnabled()` will have no effect if the corresponding `FIREBASE_X_COLLECTION_ENABLED` variable is set to `true`. +- Calling `setXCollectionEnabled(true|false)` will enable/disable data collection during the current app session and across subsequent app sessions until such time as the same method is called again with a different value. + +# Example project +An example project repo exists to demonstrate and validate the functionality of this plugin: +https://github.com/dpa99c/cordova-plugin-firebasex-test + +Please use this as a working reference. + +Before reporting any issues, please (if possible) test against the example project to rule out causes external to this plugin. + +# Reporting issues +**IMPORTANT:** Please read the following carefully. +Failure to follow the issue template guidelines below will result in the issue being immediately closed. + +## Reporting a bug or problem +Before [opening a bug issue](https://github.com/dpa99c/cordova-plugin-firebasex/issues/new?assignees=&labels=&template=bug_report.md&title=), please do the following: +- *DO NOT* open issues asking for support in using/integrating the plugin into your project + - Only open issues for suspected bugs/issues with the plugin that are generic and will affect other users + - I don't have time to offer free technical support: this is free open-source software + - Ask for help on StackOverflow, Ionic Forums, etc. + - Use the [example project](https://github.com/dpa99c/cordova-plugin-firebasex-test) as a known working reference + - Any issues requesting support will be closed immediately. +- *DO NOT* open issues related to the [Ionic Typescript wrapper for this plugin](https://github.com/ionic-team/ionic-native/blob/master/src/%40ionic-native/plugins/firebase-x/index.ts) + - This is owned/maintained by [Ionic](https://github.com/ionic-team) and is not part of this plugin + - Please raise such issues/PRs against [Ionic Native](https://github.com/ionic-team/ionic-native/) instead. + - To verify an if an issue is caused by this plugin or its Typescript wrapper, please re-test using the vanilla Javascript plugin interface (without the Ionic Native wrapper). + - Any issue opened here which is obviously an Ionic Typescript wrapper issue will be closed immediately. +- If you are migrating from [cordova-plugin-firebase](https://github.com/arnesson/cordova-plugin-firebase) to `cordova-plugin-firebasex` please make sure you have read the [Migrating from cordova-plugin-firebase](#migrating-from-cordova-plugin-firebase) section. +- Read the above documentation thoroughly + - For example, if you're having a build issue ensure you've read through the [build environment notes](#build-environment-notes) + - If an iOS CLI build is failing, ensure you've read the [Cordova CLI builds](#cordova-cli-builds) section +- Check the [CHANGELOG](https://github.com/dpa99c/cordova-plugin-firebasex/blob/master/CHANGELOG.md) for any breaking changes that may be causing your issue. +- Check a similar issue (open or closed) does not already exist against this plugin. + - Duplicates or near-duplicates will be closed immediately. +- When [creating a new issue](https://github.com/dpa99c/cordova-plugin-firebasex/issues/new/choose) + - Choose the "Bug report" template + - Fill out the relevant sections of the template and delete irrelevant sections + - *WARNING:* Failure to complete the issue template will result in the issue being closed immediately. +- Reproduce the issue using the [example project](https://github.com/dpa99c/cordova-plugin-firebasex-test) + - This will eliminate bugs in your code or conflicts with other code as possible causes of the issue + - This will also validate your development environment using a known working codebase + - If reproducing the issue using the example project is not possible, create an isolated test project that you are able to share +- Include full verbose console output when reporting build issues + - If the full console output is too large to insert directly into the Github issue, then post it on an external site such as [Pastebin](https://pastebin.com/) and link to it from the issue + - Often the details of an error causing a build failure is hidden away when building with the CLI + - To get the full detailed console output, append the `--verbose` flag to CLI build commands + - e.g. `cordova build ios --verbose` + - Failure to include the full console output will result in the issue being closed immediately +- If the issue relates to the plugin documentation (and not the code), please of a [documentation issue](https://github.com/dpa99c/cordova-plugin-firebasex/issues/new?assignees=&labels=&template=documentation-issue.md&title=) + +## Requesting a new feature +Before [opening a feature request issue](https://github.com/dpa99c/cordova-plugin-firebasex/issues/new?assignees=&labels=&template=feature_request.md&title=), please do the following: +- Check the above documentation to ensure the feature you are requesting doesn't already exist +- Check the list if open/closed issues to check if there's a reason that feature hasn't been included already +- Ensure the feature you are requesting is actually possible to implement and generically useful to other users than yourself +- Where possible, post a link to the documentation related to the feature you are requesting +- Include other relevant links, e.g. + - Stack Overflow post illustrating a solution + - Code within another Github repo that illustrates a solution + +# Cloud messaging + +<p align="center"> + <a href="https://youtu.be/qLPhan9YUhQ"><img src="https://media.giphy.com/media/U70vu02o9yCFEffidf/200w_d.gif" /></a> + <span> </span> + <a href="https://youtu.be/35feCmGYSR4"><img src="https://media.giphy.com/media/Y4oFG0Awhd3TpnggHz/200w_d.gif" /></a> +</p> + +There are 2 distinct types of messages that can be sent by Firebase Cloud Messaging (FCM): + +- [Notification messages](https://firebase.google.com/docs/cloud-messaging/concept-options#notifications) + - automatically displayed to the user by the operating system on behalf of the client app **while your app is not running or is in the background** + - **if your app is in the foreground when the notification message arrives**, it is passed to the client app and it is the responsibility of the client app to display it. + - have a predefined set of user-visible keys and an optional data payload of custom key-value pairs. +- [Data messages](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages) + - Client app is responsible for processing data messages. + - Data messages have only custom key-value pairs. + +Note: only notification messages can be sent via the Firebase Console - data messages must be sent via the [FCM APIs](https://firebase.google.com/docs/cloud-messaging/server). + +## Background notifications +If the notification message arrives while the app is in the background/not running, it will be displayed as a system notification. + +By default, no callback is made to the plugin when the message arrives while the app is not in the foreground, since the display of the notification is entirely handled by the operating system. +However, there are platform-specific circumstances where a callback can be made when the message arrives and the app is in the background that don't require user interaction to receive the message payload - see [Android background notifications](#android-background-notifications) and [iOS background notifications](#ios-background-notifications) for details. + +If the user taps the system notification, this launches/resumes the app and the notification title, body and optional data payload is passed to the [onMessageReceived](#onMessageReceived) callback. + +When the `onMessageReceived` is called in response to a user tapping a system notification while the app is in the background/not running, it will be passed the property `tap: "background"`. + + +## Foreground notifications +If the notification message arrives while the app is in running in the foreground, by default **it will NOT be displayed as a system notification**. +Instead the notification message payload will be passed to the [onMessageReceived](#onMessageReceived) callback for the plugin to handle (`tap` will not be set). + +If you include the `notification_foreground` key in the `data` payload, the plugin will also display a system notification upon receiving the notification messages while the app is running in the foreground. +For example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "data": { + "notification_foreground": "true", + } +} +``` + +When the `onMessageReceived` is called in response to a user tapping a system notification while the app is in the foreground, it will be passed the property `tap: "foreground"`. + +You can set additional properties of the foreground notification using the same key names as for [Data Message Notifications](#data-message-notification-keys). + +## Android notifications +Notifications on Android can be customised to specify the sound, icon, LED colour, etc. that's displayed when the notification arrives. + +### Android background notifications +If the notification message arrives while the app is in the background/not running, it will be displayed as a system notification. + +If a notification message arrives while the app is in the background but is still running (i.e. has not been task-killed) and the device is not in power-saving mode, the `onMessageReceived` callback will be invoked without the `tap` property, indicating the message was received without user interaction. + +If the user then taps the system notification, the app will be brought to the foreground and `onMessageReceived` will be invoked **again**, this time with `tap: "background"` indicating that the user tapped the system notification while the app was in the background. + +In addition to the title and body of the notification message, Android system notifications support specification of the following notification settings: +- [Icon](#android-notification-icons) +- [Sound](#android-notification-sound) +- [Color accent](#android-notification-color) +- [Channel ID](#android-notification-channels) (Android 8.0 (O) and above) + - This channel configuration enables you to specify: + - Sound + - Vibration + - LED light + - Badge + - Importance + - Visibility + - See [createChannel](#createchannel) for details. + +Note: on tapping a background notification, if your app is not running, only the `data` section of the notification message payload will be delivered to [onMessageReceived](#onMessageReceived). +i.e. the notification title, body, etc. will not. Therefore if you need the properties of the notification message itself (e.g. title & body) to be delivered to [onMessageReceived](#onMessageReceived), you must duplicate these in the `data` section, e.g.: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "data": { + "notification_body": "Notification body", + "notification_title": "Notification title" + } +} +``` + +### Android foreground notifications +If the notification message arrives while the app is in the foreground, by default a system notification won't be displayed and the data will be passed to [onMessageReceived](#onMessageReceived). + +However, if you set the `notification_foreground` key in the `data` section of the notification message payload, this will cause the plugin to display system notification when the message is received while your app is in the foreground. You can customise the notification using the same keys as for [Android data message notifications](#android-data-message-notifications). + +### Android Notification Channels +- Android 8 (O) introduced [notification channels](https://developer.android.com/training/notify-user/channels). +- Notification channels are configured by the app and used to determine the **sound/lights/vibration** settings of system notifications. +- By default, this plugin creates a default channel with [default properties](#default-android-channel-properties) + - These can be overridden via the [setDefaultChannel](#setdefaultchannel) function. +- The plugin enables the creation of additional custom channels via the [createChannel](#createchannel) function. + +First you need to create a custom channel with the desired settings, for example: + +```javascript +var channel = { + id: "my_channel_id", + sound: "mysound", + vibration: true, + light: true, + lightColor: parseInt("FF0000FF", 16).toString(), + importance: 4, + badge: true, + visibility: 1 +}; + +FirebasePlugin.createChannel(channel, +function(){ + console.log('Channel created: ' + channel.id); +}, +function(error){ + console.log('Create channel error: ' + error); +}); +``` + +Then reference it from your message payload: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "android": { + "notification": { + "channel_id": "my_channel_id" + } + } +} +``` + +#### Android 7 and below +- the channel referenced in the message payload will be ignored +- the sound setting of system notifications is specified in the notification message itself - see [Android Notification Sound](#android-notification-sound). + + +### Android Notification Icons +By default the plugin will use the default app icon for notification messages. + +#### Android Default Notification Icon +To define a custom default notification icon, you need to create the images and deploy them to the `<projectroot>/platforms/android/app/src/main/res/<drawable-DPI>` folders. +The easiest way to create the images is using the [Image Asset Studio in Android Studio](https://developer.android.com/studio/write/image-asset-studio#create-notification) or using the [Android Asset Studio webapp](https://romannurik.github.io/AndroidAssetStudio/icons-notification.html#source.type=clipart&source.clipart=ac_unit&source.space.trim=1&source.space.pad=0&name=notification_icon). + +The icons should be monochrome transparent PNGs with the following sizes: + +- mdpi: 24x24 +- hdpi: 36x36 +- xhdpi: 48x48 +- xxhdpi: 72x72 +- xxxhdpi: 96x96 + +Once you've created the images, you need to deploy them from your Cordova project to the native Android project. +To do this, copy the `drawable-DPI` image directories into your Cordova project and add `<resource-file>` entries to the `<platform name="android">` section of your `config.xml`, where `src` specifies the relative path to the images files within your Cordova project directory. + +For example, copy the`drawable-DPI` image directories to `<projectroot>/res/android/` and add the following to your `config.xml`: + +```xml +<platform name="android"> + <resource-file src="res/android/drawable-mdpi/notification_icon.png" target="app/src/main/res/drawable-mdpi/notification_icon.png" /> + <resource-file src="res/android/drawable-hdpi/notification_icon.png" target="app/src/main/res/drawable-hdpi/notification_icon.png" /> + <resource-file src="res/android/drawable-xhdpi/notification_icon.png" target="app/src/main/res/drawable-xhdpi/notification_icon.png" /> + <resource-file src="res/android/drawable-xxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxhdpi/notification_icon.png" /> + <resource-file src="res/android/drawable-xxxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxxhdpi/notification_icon.png" /> +</platform> +``` + +The default notification icon images **must** be named `notification_icon.png`. + +You then need to add a `<config-file>` block to the `config.xml` which will instruct Firebase to use your icon as the default for notifications: + +```xml +<platform name="android"> + <config-file target="AndroidManifest.xml" parent="/manifest/application"> + <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" /> + </config-file> +</platform> +``` + + +#### Android Large Notification Icon +The default notification icons above are monochrome, however you can additionally define a larger multi-coloured icon. + +**NOTE:** FCM currently does not support large icons in system notifications displayed for notification messages received in the while the app is in the background (or not running). +So the large icon will currently only be used if specified in [data messages](#android-data-messages) or [foreground notifications](#foreground-notifications). + +The large icon image should be a PNG-24 that's 256x256 pixels and must be named `notification_icon_large.png` and should be placed in the `drawable-xxxhdpi` resource directory. +As with the small icons, you'll need to add a `<resource-file>` entry to the `<platform name="android">` section of your `config.xml`: + +```xml +<platform name="android"> + <resource-file src="res/android/drawable-xxxhdpi/notification_icon_large.png" target="app/src/main/res/drawable-xxxhdpi/notification_icon_large.png" /> +</platform> +``` + + +#### Android Custom Notification Icons +You can define additional sets of notification icons in the same manner as above. +These can be specified in notification or data messages. + +For example: + +```xml + <resource-file src="res/android/drawable-mdpi/my_icon.png" target="app/src/main/res/drawable-mdpi/my_icon.png" /> + <resource-file src="res/android/drawable-hdpi/my_icon.png" target="app/src/main/res/drawable-hdpi/my_icon.png" /> + <resource-file src="res/android/drawable-xhdpi/my_icon.png" target="app/src/main/res/drawable-xhdpi/my_icon.png" /> + <resource-file src="res/android/drawable-xxhdpi/my_icon.png" target="app/src/main/res/drawable-xxhdpi/my_icon.png" /> + <resource-file src="res/android/drawable-xxxhdpi/my_icon.png" target="app/src/main/res/drawable-xxxhdpi/my_icon.png" /> + <resource-file src="res/android/drawable-xxxhdpi/my_icon_large.png" target="app/src/main/res/drawable-xxxhdpi/my_icon_large.png" /> +``` + +When sending an FCM notification message, you will then specify the icon name in the `android.notification` section, for example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "android": { + "notification": { + "icon": "my_icon", + } + }, + "data": { + "notification_foreground": "true", + } +} +``` + +You can also reference these icons in [data messages](#android-data-messages), for example: + +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_android_icon": "my_icon", + } +} +``` + + +### Android Notification Color +On Android Lollipop (5.0/API 21) and above you can set the default accent color for the notification by adding a color setting. +This is defined as an [ARGB colour](https://en.wikipedia.org/wiki/RGBA_color_space#ARGB_(word-order)) which the plugin sets by default to `#FF00FFFF` (cyan). +Note: On Android 7 and above, the accent color can only be set for the notification displayed in the system tray area - the icon in the statusbar is always white. + +You can override this default by specifying a value using the `ANDROID_ICON_ACCENT` plugin variable during plugin installation, for example: + + cordova plugin add cordova-plugin-firebasex --variable ANDROID_ICON_ACCENT=#FF123456 + +You can override the default color accent by specifying the `colour` key as an RGB value in a notification message, e.g.: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "android": { + "notification": { + "color": "#00ff00" + } + } +} +``` + +And in a data message: + +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_android_color": "#00ff00" + } +} +``` + +### Android Notification Sound +You can specify custom sounds for notifications or play the device default notification sound. + +Custom sound files must be in `.mp3` format and deployed to the `/res/raw` directory in the Android project. +To do this, you can add `<resource-file>` tags to your `config.xml` to deploy the files, for example: + +```xml +<platform name="android"> + <resource-file src="res/android/raw/my_sound.mp3" target="app/src/main/res/raw/my_sound.mp3" /> +</platform> +``` + +To ensure your custom sounds works on all versions of Android, be sure to include both the channel name and sound name in your message payload (see below for details), for example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "android": { + "notification": { + "channel_id": "my_channel_id", + "sound": "my_sound" + } + } +} +``` + +#### Android 8.0 and above +On Android 8.0 and above, the notification sound is specified by which [Android notification channel](#android-notification-channels) is referenced in the notification message payload. +First create a channel that references your sound, for example: + +```javascript +var channel = { + id: "my_channel_id", + sound: "my_sound" +}; + +FirebasePlugin.createChannel(channel, +function(){ + console.log('Channel created: ' + channel.id); +}, +function(error){ + console.log('Create channel error: ' + error); +}); +``` + +Then reference that channel in your message payload: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "android": { + "notification": { + "channel_id": "my_channel_id" + } + } +} +``` + +#### On Android 7 and below +On Android 7 and below, you need to specify the sound file name in the `android.notification` section of the message payload. +For example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "android": { + "notification": { + "sound": "my_sound" + } + } +} +``` + +And in a data message by specifying it in the `data` section: + +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_android_sound": "my_sound" + } +} +``` + +- To play the default notification sound, set `"sound": "default"`. +- To display a silent notification (no sound), omit the `sound` key from the message. + +## iOS notifications +Notifications on iOS can be customised to specify the sound and badge number that's displayed when the notification arrives. + +Notification settings are specified in the `apns.payload.aps` key of the notification message payload. +For example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "apns": { + "payload": { + "aps": { + "sound": "default", + "badge": 1, + "content-available": 1 + } + } + } +} +``` + +### iOS background notifications +If the app is in the background but is still running (i.e. has not been task-killed) and the device is not in power-saving mode, the `onMessageReceived` callback can be invoked when the message arrives without requiring user interaction (i.e. tapping the system notification). +To do this you must specify `"content-available": 1` in the `apns.payload.aps` section of the message payload - see the [Apple documentation](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW8) for more information. +When the message arrives, the `onMessageReceived` callback will be invoked without the `tap` property, indicating the message was received without user interaction. +If the user then taps the system notification, the app will be brought to the foreground and `onMessageReceived` will be invoked **again**, this time with `tap: "background"` indicating that the user tapped the system notification while the app was in the background. + +### iOS notification sound +You can specify custom sounds for notifications or play the device default notification sound. + +Custom sound files must be in a supported audio format (see [this Apple documentation](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SupportingNotificationsinYourApp.html#//apple_ref/doc/uid/TP40008194-CH4-SW10) for supported formats). +For example to convert an `.mp3` file to the supported `.caf` format run: + + afconvert my_sound.mp3 my_sound.caf -d ima4 -f caff -v + +Sound files must be deployed with the iOS application bundle. +To do this, you can add `<resource-file>` tags to your `config.xml` to deploy the files, for example: + +```xml +<platform name="ios"> + <resource-file src="res/ios/sound/my_sound.caf" /> +</platform> +``` + +In a notification message, specify the `sound` key in the `apns.payload.aps` section, for example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "apns": { + "payload": { + "aps": { + "sound": "my_sound.caf" + } + } + } +} +``` + +- To play the default notification sound, set `"sound": "default"`. +- To display a silent notification (no sound), omit the `sound` key from the message. + +In a data message, specify the `notification_ios_sound` key in the `data` section: + +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_ios_sound": "my_sound.caf" + } +} +``` + +### iOS badge number +In a notification message, specify the `badge` key in the `apns.payload.aps` section, for example: + +```json +{ + "name": "my_notification", + "notification": { + "body": "Notification body", + "title": "Notification title" + }, + "apns": { + "payload": { + "aps": { + "badge": 1 + } + } + } +} +``` + +In a data message, specify the `notification_ios_badge` key in the `data` section: + +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_ios_badge": 1 + } +} +``` + +### iOS actionable notifications +[Actionable notifications](https://developer.apple.com/documentation/usernotifications/declaring_your_actionable_notification_types) are supported on iOS: + +<img width="300" src="https://user-images.githubusercontent.com/2345062/90025071-88c0a180-dcad-11ea-86f7-033f84601a56.png"/> +<img width="300" src="https://user-images.githubusercontent.com/2345062/90028234-531db780-dcb1-11ea-9df3-6bfcf8f2e9d8.png"/> + +To use them in your app you must do the following: + +1. Add a `pn-actions.json` file to your Cordova project which defines categories and actions, for example: + +```json + { + "PushNotificationActions": [ + { + "category": "news", + "actions": [ + { + "id": "read", "title": "Read" + }, + { + "id": "skip", "title": "Skip" + }, + { + "id": "add", "title": "Add to list" + } + ] + } + ] + } +``` + +2. Reference it as a resource file in your `config.xml`: + +```xml + <platform name="ios"> + ... + <resource-file src="relative/path/to/pn-actions.json" /> + </platform> +``` + +3. Add a category entry to your FCM message payload which references one of your categories: + +```json +{ + "notification": { + "title": "iOS Actionable Notification", + "body": "With custom buttons" + }, + "apns": { + "payload": { + "aps": { + "category": "news" + } + } + } +} +``` + +When the notification arrives, if the user presses an action button the [`onMessageReceived()`](#onmessagereceived) function is invoked with the notification message payload, including the corresponding action ID. +For example: + +```json +{ + "action": "read", + "google.c.a.e": "1", + "notification_foreground": "true", + "aps": { + "alert": { + "title": "iOS Actionable Notification", + "body": "With custom buttons" + }, + "category": "news" + }, + "gcm.message_id": "1597240847657854", + "tap": "background", + "messageType": "notification" +} +``` + +So you can obtain the category with `message.aps.category` and the action with `message.action` and handle this appropriately in your app code. + +Notes: +- Actionable notifications are currently only available for iOS - not Android +- To reveal the notification action buttons, the user must drag downwards on the notification dialog +- Actionable notifications work with both foreground and background (system) notifications +- If your app is in the background/not running when the notification message arrives and a system notification is displayed, if the user chooses an action (instead of tapping the notification dialog body), your app will not be launched/foregrounded but [`onMessageReceived()`](#onmessagereceived) will be invoked, enabling your app code to handle the user's action selection silently in the background. +- You can test out actionable notifications by building and running [example project](https://github.com/dpa99c/cordova-plugin-firebasex-test) app and sending the [ios_notification_actionable.json](https://github.com/dpa99c/cordova-plugin-firebasex-test/blob/master/messages/ios_notification_actionable.json) FCM message using the [built-in FCM v1 HTTP API client](https://github.com/dpa99c/cordova-plugin-firebasex-test#messaging-client) which contains a category defined in the example [pn-actions.json](https://github.com/dpa99c/cordova-plugin-firebasex-test/blob/master/res/ios/pn-actions.json). + +## Data messages +FCM data messages are sent as an arbitrary k/v structure and by default are passed to the app for it to handle them. + +**NOTE:** FCM data messages **cannot** be sent from the Firebase Console - they can only be sent via the FCM APIs. + +### Data message notifications +This plugin enables a data message to be displayed as a system notification. +To have the app display a notification when the data message arrives, you need to set the `notification_foreground` key in the `data` section. +You can then set a `notification_title` and `notification_body`, for example: + +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "foo" : "bar" + } +} +``` + +Additional platform-specific notification options can be set using the additional keys below (which are only relevant if the `notification_foreground` key is set). + +Note: [foreground notification messages](#foreground-notifications) can also make use of these keys. + +#### Android data message notifications +On Android: +- Data messages that arrive while your app is running in the foreground or running in the background will be immediately passed to the `onMessageReceived()` Javascript handler in the Webview. +- Data messages (not containing notification keys) that arrive while your app is **not running** will be passed to the `onMessageReceived()` Javascript handler when the app is next launched. +- Data messages containing notification keys that arrive while your app is running or **not running** will be displayed as a system notification. + +The following Android-specific keys are supported and should be placed inside the `data` section: + +- `notification_android_icon` - name of a [custom notification icon](#android-custom-notification-icons) in the drawable resources + - if not specified, the plugin will use the default `notification_icon` if it exists; otherwise the default app icon will be displayed + - if a [large icon](#android-large-notification-icon) has been defined, it will also be displayed in the system notification. +- `notification_android_color` - the [color accent](#android-notification-color) to use for the small notification icon + - if not specified, the default color accent will be used +- `notification_android_channel_id` - ID of the [notification channel](#android-notification-channels) to use to display the notification + - Only applies to Android 8.0 and above + - If not specified, the [default notification channel](#default-android-channel-properties) will be used. + - You can override the default configuration for the default notification channel using [setDefaultChannel](#setdefaultchannel). + - You can create additional channels using [createChannel](#createchannel). +- `notification_android_priority` - Specifies the notification priority + - Possible values: + - `2` - Highest notification priority for your application's most important items that require the user's prompt attention or input. + - `1` - Higher notification priority for more important notifications or alerts. + - `0` - Default notification priority. + - `-1` - Lower notification priority for items that are less important. + - `-2` - Lowest notification priority. These items might not be shown to the user except under special circumstances, such as detailed notification logs. + - Defaults to `2` if not specified. +- `notification_android_visibility` - Specifies the notification visibility + - Possible values: + - `1` - Show this notification in its entirety on all lockscreens. + - `0` - Show this notification on all lockscreens, but conceal sensitive or private information on secure lockscreens. + - `-1` - Do not reveal any part of this notification on a secure lockscreen. + - Defaults to `1` if not specified. + +The following keys only apply to Android 7 and below. +On Android 8 and above they will be ignored - the `notification_android_channel_id` property should be used to specify a [notification channel](#android-notification-channels) with equivalent settings. + +- `notification_android_sound` - name of a sound resource to play as the [notification sound](#android-notification-sound) + - if not specified, no sound is played + - `default` plays the default device notification sound + - otherwise should be the name of an `.mp3` file in the `/res/raw` directory, e.g. `my_sound.mp3` => `"sounds": "my_sound"` +- `notification_android_lights` - color and pattern to use to blink the LED light + - if not defined, LED will not blink + - in the format `ARGB, time_on_ms, time_off_ms` where + - `ARGB` is an ARGB color definition e.g. `#ffff0000` + - `time_on_ms` is the time in milliseconds to turn the LED on for + - `time_off_ms` is the time in milliseconds to turn the LED off for + - e.g. `"lights": "#ffff0000, 250, 250"` +- `notification_android_vibrate` - pattern of vibrations to use when the message arrives + - if not specified, device will not vibrate + - an array of numbers specifying the time in milliseconds to vibrate + - e.g. `"vibrate": "500, 200, 500"` + +Example data message with Android notification keys: + +```json +{ + "name": "my_data_message", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_android_channel_id": "my_channel", + "notification_android_priority": "2", + "notification_android_visibility": "1", + "notification_android_color": "#ff0000", + "notification_android_icon": "coffee", + "notification_android_sound": "my_sound", + "notification_android_vibrate": "500, 200, 500", + "notification_android_lights": "#ffff0000, 250, 250" + } +} +``` + +#### iOS data message notifications +On iOS: +- Data messages that arrive while your app is running in the foreground or running in the background will be immediately passed to the `onMessageReceived()` Javascript handler in the Webview. +- Data messages that arrive while your app is **not running** will **NOT be received by your app!** + +The following iOS-specific keys are supported and should be placed inside the `data` section: + +- `notification_ios_sound` - Sound to play when the notification is displayed + - To play a custom sound, set the name of the sound file bundled with your app, e.g. `"sound": "my_sound.caf"` - see [iOS notification sound](#ios-notification-sound) for more info. + - To play the default notification sound, set `"sound": "default"`. + - To display a silent notification (no sound), omit the `sound` key from the message. +- `notification_ios_badge` - Badge number to display on app icon on home screen. + +For example: +```json +{ + "name": "my_data", + "data" : { + "notification_foreground": "true", + "notification_body" : "Notification body", + "notification_title": "Notification title", + "notification_ios_sound": "my_sound.caf", + "notification_ios_badge": 1 + } +} +``` + +## Custom FCM message handling +In some cases you may want to handle certain incoming FCM messages differently rather than with the default behaviour of this plugin. +Therefore this plugin provides a mechanism by which you can implement your own custom FCM message handling for specific FCM messages which bypasses handling of those messages by this plugin. +To do this requires you to write native handlers for Android & iOS which hook into the native code of this plugin. + +### Android +You'll need to add a native class which extends the [`FirebasePluginMessageReceiver` abstract class](src/android/FirebasePluginMessageReceiver.java) and implements the `onMessageReceived()` and `sendMessage()` abstract methods. + +### iOS +You'll need to add a native class which extends the [`FirebasePluginMessageReceiver` abstract class](src/ios/FirebasePluginMessageReceiver.h) and implements the `sendNotification()` abstract method. + +### Example +The [example project](https://github.com/dpa99c/cordova-plugin-firebasex-test) contains an [example plugin](https://github.com/dpa99c/cordova-plugin-firebasex-test/tree/master/plugins/cordova-plugin-customfcmreceiver) which implements a custom receiver class for both platforms. +You can test this by building and running the example project app, and sending the [notification_custom_receiver](https://github.com/dpa99c/cordova-plugin-firebasex-test/blob/master/messages/notification_custom_receiver.json) and [data_custom_receiver](https://github.com/dpa99c/cordova-plugin-firebasex-test/blob/master/messages/data_custom_receiver.json) test messages using the [built-in FCM client](https://github.com/dpa99c/cordova-plugin-firebasex-test#messaging-client). + +# InApp Messaging +The Firebase Inapp Messaging SDK component has been removed from this [cli_build](https://github.com/dpa99c/cordova-plugin-firebasex/tree/cli_build) branch of the plugin due to the iOS component causing CLI builds to fail (see [#326](https://github.com/dpa99c/cordova-plugin-firebasex/issues/326)). +If you wish to use Firebase Inapp Messaging, please use the [master](https://github.com/dpa99c/cordova-plugin-firebasex) branch or install a plugin release via the NPM registry and build using Xcode. + +# Google Tag Manager +The Google Tag Manager component has been removed from this [cli_build](https://github.com/dpa99c/cordova-plugin-firebasex/tree/cli_build) branch of the plugin due to the iOS component causing CLI builds to fail (see [#326](https://github.com/dpa99c/cordova-plugin-firebasex/issues/326)). +If you wish to use Google Tag Manager, please use the [master](https://github.com/dpa99c/cordova-plugin-firebasex) branch or install a plugin release via the NPM registry and build using Xcode. + +# API +The list of available methods for this plugin is described below. + +## Notifications and data messages +The plugin is capable of receiving push notifications and FCM data messages. + +See [Cloud messaging](#cloud-messaging) section for more. + +### getToken +Get the current FCM token. +Null if the token has not been allocated yet by the Firebase SDK. + +**Parameters**: +- {function} success - callback function which will be passed the {string} token as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.getToken(function(fcmToken) { + console.log(fcmToken); +}, function(error) { + console.error(error); +}); +``` +Note that token will be null if it has not been established yet. + +### getId +Get the app instance ID (an constant ID which persists as long as the app is not uninstalled/reinstalled). +Null if the ID has not been allocated yet by the Firebase SDK. + +**Parameters**: +- {function} success - callback function which will be passed the {string} ID as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.getId(function(appInstanceId) { + console.log(appInstanceId); +}, function(error) { + console.error(error); +}); +``` +Note that token will be null if it has not been established yet. + +### onTokenRefresh +Registers a handler to call when the FCM token changes. +This is the best way to get the token as soon as it has been allocated. +This will be called on the first run after app install when a token is first allocated. +It may also be called again under other circumstances, e.g. if `unregister()` is called or Firebase allocates a new token for other reasons. +You can use this callback to return the token to you server to keep the FCM token associated with a given user up-to-date. + +**Parameters**: +- {function} success - callback function which will be passed the {string} token as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.onTokenRefresh(function(fcmToken) { + console.log(fcmToken); +}, function(error) { + console.error(error); +}); +``` + +### getAPNSToken +iOS only. +Get the APNS token allocated for this app install. +Note that token will be null if it has not been allocated yet. + +**Parameters**: +- {function} success - callback function which will be passed the {string} APNS token as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.getAPNSToken(function(apnsToken) { + console.log(apnsToken); +}, function(error) { + console.error(error); +}); +``` + +### onApnsTokenReceived +iOS only. +Registers a handler to call when the APNS token is allocated. +This will be called once when remote notifications permission has been granted by the user at runtime. + +**Parameters**: +- {function} success - callback function which will be passed the {string} token as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.onApnsTokenReceived(function(apnsToken) { + console.log(apnsToken); +}, function(error) { + console.error(error); +}); +``` + +### onMessageReceived +Registers a callback function to invoke when: +- a notification or data message is received by the app +- a system notification is tapped by the user + +**Parameters**: +- {function} success - callback function which will be passed the {object} message as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.onMessageReceived(function(message) { + console.log("Message type: " + message.messageType); + if(message.messageType === "notification"){ + console.log("Notification message received"); + if(message.tap){ + console.log("Tapped in " + message.tap); + } + } + console.dir(message); +}, function(error) { + console.error(error); +}); +``` + +The `message` object passed to the callback function will contain the platform-specific FCM message payload along with the following keys: +- `messageType=notification|data` - indicates if received message is a notification or data message +- `tap=foreground|background` - set if the call to `onMessageReceived()` was initiated by user tapping on a system notification. + - indicates if the system notification was tapped while the app was in the foreground or background. + - not set if no system notification was tapped (i.e. message was received directly from FCM rather than via a user tap on a system notification). + +Notification message flow: + +1. App is in foreground: + a. By default, when a notification message arrives the app receives the notification message payload in the `onMessageReceived` JavaScript callback without any system notification on the device itself. + b. If the `data` section contains the `notification_foreground` key, the plugin will display a system notification while in the foreground. +2. App is in background: + a. User receives the notification message as a system notification in the device notification bar + b. User taps the system notification which launches the app + b. User receives the notification message payload in the `onMessageReceived` JavaScript callback + +Data message flow: + +1. App is in foreground: + a. By default, when a data message arrives the app receives the data message payload in the `onMessageReceived` JavaScript callback without any system notification on the device itself. + b. If the `data` section contains the `notification_foreground` key, the plugin will display a system notification while in the foreground. +2. App is in background: + a. The app receives the data message in the `onMessageReceived` JavaScript callback while in the background + b. If the data message contains the [data message notification keys](#data-message-notifications), the plugin will display a system notification for the data message while in the background. + +### grantPermission +Grant permission to receive push notifications (will trigger prompt) and return `hasPermission: true`. +iOS only (Android will always return true). + +**Parameters**: +- {function} success - callback function which will be passed the {boolean} permission result as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.grantPermission(function(hasPermission){ + console.log("Permission was " + (hasPermission ? "granted" : "denied")); +}); +``` +### hasPermission +Check permission to receive push notifications and return the result to a callback function as boolean. +On iOS, returns true is runtime permission for remote notifications is granted and enabled in Settings. +On Android, returns true if remote notifications are enabled. + +**Parameters**: +- {function} success - callback function which will be passed the {boolean} permission result as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.hasPermission(function(hasPermission){ + console.log("Permission is " + (hasPermission ? "granted" : "denied")); +}); +``` + +### unregister +Unregisters from Firebase by deleting the current device token. +Use this to stop receiving push notifications associated with the current token. +e.g. call this when you logout user from your app. +By default, a new token will be generated as soon as the old one is removed. +To prevent a new token being generated, by sure to disable autoinit using [`setAutoInitEnabled()`](#setautoinitenabled) before calling [`unregister()`](#unregister). + +**Parameters**: None + +```javascript +FirebasePlugin.unregister(); +``` + +### isAutoInitEnabled +Indicates whether autoinit is currently enabled. +If so, new FCM tokens will be automatically generated. + +**Parameters**: +- {function} success - callback function which will be passed the {boolean} result as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + + +```javascript +FirebasePlugin.isAutoInitEnabled(function(enabled){ + console.log("Auto init is " + (enabled ? "enabled" : "disabled")); +}); + +``` + +### setAutoInitEnabled +Sets whether to autoinit new FCM tokens. +By default, a new token will be generated as soon as the old one is removed. +To prevent a new token being generated, by sure to disable autoinit using [`setAutoInitEnabled()`](#setautoinitenabled) before calling [`unregister()`](#unregister). + +**Parameters**: +- {boolean} enabled - set true to enable, false to disable +- {function} success - callback function to call on successful execution of operation. +- {function} error - callback function which will be passed a {string} error message as an argument + + +```javascript +FirebasePlugin.setAutoInitEnabled(false, function(){ + console.log("Auto init has been disabled "); + FirebasePlugin.unregister(); +}); + +``` + +### setBadgeNumber +iOS only. +Set a number on the icon badge: + +**Parameters**: +- {integer} badgeNumber - number to set for the app badge + +```javascript +FirebasePlugin.setBadgeNumber(3); +``` + +Set 0 to clear the badge +```javascript +FirebasePlugin.setBadgeNumber(0); +``` + +Note: this function is no longer available on Android (see [#124](https://github.com/dpa99c/cordova-plugin-firebasex/issues/124)) + +### getBadgeNumber +iOS only. +Get icon badge number: + +**Parameters**: +- {function} success - callback function which will be passed the {integer} current badge number as an argument + +```javascript +FirebasePlugin.getBadgeNumber(function(n) { + console.log(n); +}); +``` + +Note: this function is no longer available on Android (see [#124](https://github.com/dpa99c/cordova-plugin-firebasex/issues/124)) + +### clearAllNotifications +Clear all pending notifications from the drawer: + +**Parameters**: None + +```javascript +FirebasePlugin.clearAllNotifications(); +``` + +### subscribe +Subscribe to a topic. + +Topic messaging allows you to send a message to multiple devices that have opted in to a particular topic. + +**Parameters**: +- {string} topicName - name of topic to subscribe to +- {function} success - callback function which will be call on successful subscription +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.subscribe("latest_news", function(){ + console.log("Subscribed to topic"); +}, function(error){ + console.error("Error subscribing to topic: " + error); +}); +``` + +### unsubscribe +Unsubscribe from a topic. + +This will stop you receiving messages for that topic + +**Parameters**: +- {string} topicName - name of topic to unsubscribe from +- {function} success - callback function which will be call on successful unsubscription +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.unsubscribe("latest_news", function(){ + console.log("Unsubscribed from topic"); +}, function(error){ + console.error("Error unsubscribing from topic: " + error); +}); +``` + +### createChannel +Android 8+ only. +Creates a custom channel to be used by notification messages which have the channel property set in the message payload to the `id` of the created channel: +- For background (system) notifications: `android.notification.channel_id` +- For foreground/data notifications: `data.notification_android_channel_id` + +For each channel you may set the sound to be played, the color of the phone LED (if supported by the device), whether to vibrate and set vibration pattern (if supported by the device), importance and visibility. +Channels should be created as soon as possible (on program start) so notifications can work as expected. +A default channel is created by the plugin at app startup; the properties of this can be overridden see [setDefaultChannel](#setdefaultchannel) + +Calling on Android 7 or below or another platform will have no effect. + +**Parameters**: +- {object} - channel configuration object (see below for object keys/values) +- {function} success - callback function which will be call on successful channel creation +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +// Define custom channel - all keys are except 'id' are optional. +var channel = { + // channel ID - must be unique per app package + id: "my_channel_id", + + // Channel description. Default: empty string + description: "Channel description", + + // Channel name. Default: empty string + name: "Channel name", + + //The sound to play once a push comes. Default value: 'default' + //Values allowed: + //'default' - plays the default notification sound + //'ringtone' - plays the currently set ringtone + //'false' - silent; don't play any sound + //filename - the filename of the sound file located in '/res/raw' without file extension (mysound.mp3 -> mysound) + sound: "mysound", + + //Vibrate on new notification. Default value: true + //Possible values: + //Boolean - vibrate or not + //Array - vibration pattern - e.g. [500, 200, 500] - milliseconds vibrate, milliseconds pause, vibrate, pause, etc. + vibration: true, + + // Whether to blink the LED + light: true, + + //LED color in ARGB format - this example BLUE color. If set to -1, light color will be default. Default value: -1. + lightColor: parseInt("FF0000FF", 16).toString(), + + //Importance - integer from 0 to 4. Default value: 4 + //0 - none - no sound, does not show in the shade + //1 - min - no sound, only shows in the shade, below the fold + //2 - low - no sound, shows in the shade, and potentially in the status bar + //3 - default - shows everywhere, makes noise, but does not visually intrude + //4 - high - shows everywhere, makes noise and peeks + importance: 4, + + //Show badge over app icon when non handled pushes are present. Default value: true + badge: true, + + //Show message on locked screen. Default value: 1 + //Possible values (default 1): + //-1 - secret - Do not reveal any part of the notification on a secure lockscreen. + //0 - private - Show the notification on all lockscreens, but conceal sensitive or private information on secure lockscreens. + //1 - public - Show the notification in its entirety on all lockscreens. + visibility: 1 +}; + +// Create the channel +FirebasePlugin.createChannel(channel, +function(){ + console.log('Channel created: ' + channel.id); +}, +function(error){ + console.log('Create channel error: ' + error); +}); +``` + +Example FCM v1 API notification message payload for invoking the above example channel: + +```json + +{ + "notification": + { + "title":"Notification title", + "body":"Notification body" + }, + "android": { + "notification": { + "channel_id": "my_channel_id" + } + } +} + +``` + +If your Android app plays multiple sounds or effects, it's a good idea to create a channel for each likely combination. This is because once a channel is created you cannot override sounds/effects. +IE, expanding on the createChannel example: +```javascript +let soundList = ["train","woop","clock","radar","sonar"]; +for (let key of soundList) { + let name = "yourchannelprefix_" + key; + channel.id = name; + channel.sound = key; + channel.name = "Your description " + key; + + // Create the channel + window.FirebasePlugin.createChannel(channel, + function(){ + console.log('Notification Channel created: ' + channel.id + " " + JSON.stringify(channel)); + }, + function(error){ + console.log('Create notification channel error: ' + error); + }); +} +``` + +Note, if you just have one sound / effect combination that the user can customise, just use setDefaultChannel when any changes are made. + + +### setDefaultChannel +Android 8+ only. +Overrides the properties for the default channel. +The default channel is used if no other channel exists or is specified in the notification. +Any options not specified will not be overridden. +Should be called as soon as possible (on app start) so default notifications will work as expected. +Calling on Android 7 or below or another platform will have no effect. + +**Parameters**: +- {object} - channel configuration object +- {function} success - callback function which will be call on successfully setting default channel +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +var channel = { + id: "my_default_channel", + name: "My Default Name", + description: "My Default Description", + sound: "ringtone", + vibration: [500, 200, 500], + light: true, + lightColor: parseInt("FF0000FF", 16).toString(), + importance: 4, + badge: false, + visibility: -1 +}; + +FirebasePlugin.setDefaultChannel(channel, +function(){ + console.log('Default channel set'); +}, +function(error){ + console.log('Set default channel error: ' + error); +}); +``` + +### Default Android Channel Properties +The default channel is initialised at app startup with the following default settings: + +```json +{ + id: "fcm_default_channel", + name: "Default", + description: "", + sound: "default", + vibration: true, + light: true, + lightColor: -1, + importance: 4, + badge: true, + visibility: 1 +} +``` + +### deleteChannel +Android 8+ only. +Removes a previously defined channel. +Calling on Android 7 or below or another platform will have no effect. + +**Parameters**: +- {string} - id of channel to delete +- {function} success - callback function which will be call on successfully deleting channel +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.deleteChannel("my_channel_id", +function(){ + console.log('Channel deleted'); +}, +function(error){ + console.log('Delete channel error: ' + error); +}); + +``` + +### listChannels +Android 8+ only. +Gets a list of all channels. +Calling on Android 7 or below or another platform will have no effect. + +**Parameters**: +- {function} success - callback function which will be passed the {array} of channel objects as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.listChannels( +function(channels){ + if(typeof channels == "undefined") + return; + + for(var i=0;i<channels.length;i++) + { + console.log("ID: " + channels[i].id + ", Name: " + channels[i].name); + } +}, +function(error){ + alert('List channels error: ' + error); +}); + +``` + +## Analytics +Firebase Analytics enables you to log events in order to track use and behaviour of your apps. + +By default, Firebase does not store fine-grain analytics data - only a sample is taken and detailed event data is then discarded. +The Firebase Analytics console is designed to give you a coarse overview of analytics data. + +If you want to analyse detailed, event-level analytics you should consider [exporting Firebase Analytics data to BigQuery](https://firebase.google.com/docs/projects/bigquery-export). +The easiest way to set this up is by [streaming Firebase Analytics data into BigQuery](https://cloud.google.com/bigquery/streaming-data-into-bigquery). +Note that until you set this up, all fine-grain event-level data is discarded by Firebase. + +### setAnalyticsCollectionEnabled +Manually enable/disable analytics data collection, e.g. if [disabled on app startup](#disable-data-collection-on-startup). + +**Parameters**: +- {boolean} setEnabled - whether to enable or disable analytics data collection + +```javascript +FirebasePlugin.setAnalyticsCollectionEnabled(true); // Enables analytics data collection + +FirebasePlugin.setAnalyticsCollectionEnabled(false); // Disables analytics data collection +``` + +### isAnalyticsCollectionEnabled +Indicates whether analytics data collection is enabled. + +Notes: +- This value applies both to the current app session and subsequent app sessions until such time as it is changed. +- It returns the value set by [setAnalyticsCollectionEnabled()](#setanalyticscollectionenabled). +- If automatic data collection was not [disabled on app startup](#disable-data-collection-on-startup), this will always return `true`. + +**Parameters**: +- {function} success - callback function which will be invoked on success. +Will be passed a {boolean} indicating if the setting is enabled. +- {function} error - (optional) callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.isAnalyticsCollectionEnabled(function(enabled){ + console.log("Analytics data collection is "+(enabled ? "enabled" : "disabled")); +}, function(error){ + console.error("Error getting Analytics data collection setting: "+error); +}); +``` + +### logEvent +Log an event using Analytics: + +**Parameters**: +- {string} eventName - name of event to log to Firebase Analytics +- {object} eventProperties - key/value object of event properties (must be serializable) + +```javascript +FirebasePlugin.logEvent("select_content", {content_type: "page_view", item_id: "home"}); +``` + +### setScreenName +Set the name of the current screen in Analytics: + +**Parameters**: +- {string} screenName - name of screen to log to Firebase Analytics + +```javascript +FirebasePlugin.setScreenName("Home"); +``` + +### setUserId +Set a user id for use in Analytics: + +**Parameters**: +- {string} userName - name of user to set in Firebase Analytics + +```javascript +FirebasePlugin.setUserId("user_id"); +``` + +### setUserProperty +Set a user property for use in Analytics: + +**Parameters**: +- {string} userName - name of user property to set in Firebase Analytics +- {string} userName - value of user property to set in Firebase Analytics + +```javascript +FirebasePlugin.setUserProperty("name", "value"); +``` + +## Crashlytics +By default this plugin will ensure fatal native crashes in your apps are reported to Firebase via the Firebase (not Fabric) Crashlytics SDK. + +### setCrashlyticsCollectionEnabled +Manually enable/disable Crashlytics data collection, e.g. if [disabled on app startup](#disable-data-collection-on-startup). + +**Parameters**: +- {boolean} setEnabled - whether to enable or disable Crashlytics data collection. +- {function} success - (optional) callback function which will be invoked on success +- {function} error - (optional) callback function which will be passed a {string} error message as an argument + +```javascript +var shouldSetEnabled = true; +FirebasePlugin.setCrashlyticsCollectionEnabled(shouldSetEnabled, function(){ + console.log("Crashlytics data collection is enabled"); +}, function(error){ + console.error("Crashlytics data collection couldn't be enabled: "+error); +}); +``` + +### isCrashlyticsCollectionEnabled +Indicates whether Crashlytics collection setting is currently enabled. + +**Parameters**: +- {function} success - callback function which will be invoked on success. +Will be passed a {boolean} indicating if the setting is enabled. +- {function} error - (optional) callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.isCrashlyticsCollectionEnabled(function(enabled){ + console.log("Crashlytics data collection is "+(enabled ? "enabled" : "disabled")); +}, function(error){ + console.error("Error getting Crashlytics data collection setting: "+error); +}); +``` + + +### setCrashlyticsUserId +Set Crashlytics user identifier. + +To diagnose an issue, it’s often helpful to know which of your users experienced a given crash. Crashlytics includes a way to anonymously identify users in your crash reports. +To add user IDs to your reports, assign each user a unique identifier in the form of an ID number, token, or hashed value. + +See [the Firebase docs for more](https://firebase.google.com/docs/crashlytics/customize-crash-reports?authuser=0#set_user_ids). + +**Parameters**: +- {string} userId - User ID to associate with Crashlytics reports + +```javascript +FirebasePlugin.setCrashlyticsUserId("user_id"); +``` + + +### sendCrash +Simulates (causes) a fatal native crash which causes a crash event to be sent to Crashlytics (useful for testing). +See [the Firebase documentation](https://firebase.google.com/docs/crashlytics/force-a-crash?authuser=0#force_a_crash_to_test_your_implementation) regarding crash testing. +Crashes will appear under `Event type = "Crashes"` in the Crashlytics console. + +**Parameters**: None + +```javascript +FirebasePlugin.sendCrash(); +``` + +### logMessage +Sends a crash-related log message that will appear in the `Logs` section of the next native crash event. +Note: if you don't then crash, the message won't be sent! +Also logs the message to the native device console. + +**Parameters**: +- {string} message - message to associate with next native crash event + +```javascript +FirebasePlugin.logMessage("about to send a crash for testing!"); +FirebasePlugin.sendCrash(); +``` + +### logError +Sends a non-fatal error event to Crashlytics. +In a Cordova app, you may use this to log unhandled Javascript exceptions, for example. + +The event will appear under `Event type = "Non-fatals"` in the Crashlytics console. +The error message will appear in the `Logs` section of the non-fatal error event. +Also logs the error message to the native device console. + +**Parameters**: +- {string} errorMessage - non-fatal error message to log to Crashlytics +- {object} stackTrace - (optional) a stack trace generated by [stacktrace.js](http://www.stacktracejs.com/) +- {function} success - (optional) callback function which will be invoked on success +- {function} error - (optional) callback function which will be passed a {string} error message as an argument + +```javascript + // Send an unhandled JS exception + var appRootURL = window.location.href.replace("index.html",''); + window.onerror = function(errorMsg, url, line, col, error) { + var logMessage = errorMsg; + var stackTrace = null; + + var sendError = function(){ + FirebasePlugin.logError(logMessage, stackTrace, function(){ + console.log("Sent JS exception"); + },function(error){ + console.error("Failed to send JS exception", error); + }); + }; + + logMessage += ': url='+url.replace(appRootURL, '')+'; line='+line+'; col='+col; + + if(typeof error === 'object'){ + StackTrace.fromError(error).then(function(trace){ + stackTrace = trace; + sendError() + }); + }else{ + sendError(); + } + }; + + // Send a non-fatal error + FirebasePlugin.logError("A non-fatal error", function(){ + console.log("Sent non-fatal error"); + },function(error){ + console.error("Failed to send non-fatal error", error); + }); +``` + +An example of how the error entry will appear in the Crashlytics console: +<br/> +<b>Android</b> +<br/> +<img src="https://user-images.githubusercontent.com/2345062/68016874-5e0cdb80-fc8d-11e9-9a26-97b448039cf5.png"/> + +<br/><br/> +<b>iOS</b> +<br/> +<img src="https://user-images.githubusercontent.com/2345062/68041597-d1800e80-fcc8-11e9-90e1-eeeedf9cc43f.png"/> + + + +## Authentication + +### isUserSignedIn +Checks if there is a current Firebase user signed into the app. + +**Parameters**: +- {function} success - callback function to pass {boolean} result to as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.isUserSignedIn(function(isSignedIn) { + console.log("User "+(isSignedIn ? "is" : "is not") + " signed in"); + }, function(error) { + console.error("Failed to check if user is signed in: " + error); + }); +``` + +### signOutUser +Signs current Firebase user out of the app. + +**Parameters**: +- {function} success - callback function to pass {boolean} result to as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.signOutUser(function() { + console.log("User signed out"); + }, function(error) { + console.error("Failed to sign out user: " + error); + }); +``` + +### getCurrentUser +Returns details of the currently logged in user from local Firebase SDK. +Note that some user properties will be empty is they are not defined in Firebase for the current user. + +**Parameters**: +- {function} success - callback function to pass user {object} to as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.getCurrentUser(function(user) { + console.log("Name: "+user.name); + console.log("Email: "+user.email); + console.log("Is email verified?: "+user.emailIsVerified); + console.log("Phone number: "+user.phoneNumber); + console.log("Photo URL: "+user.photoUrl); + console.log("UID: "+user.uid); + console.log("Provider ID: "+user.providerId); + console.log("ID token: "+user.idToken); + }, function(error) { + console.error("Failed to get current user data: " + error); + }); +``` + +### reloadCurrentUser +Loads details of the currently logged in user from remote Firebase server. +This differs from `getCurrentUser()` which loads the locally cached details which may be stale. +For example, if you want to check if a user has verified their email address, this method will guarantee the reported verified state is up-to-date. + +**Parameters**: +- {function} success - callback function to pass user {object} to as an argument +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.reloadCurrentUser(function(user) { + console.log("Name: "+user.name); + console.log("Email: "+user.email); + console.log("Is email verified?: "+user.emailIsVerified); + console.log("Phone number: "+user.phoneNumber); + console.log("Photo URL: "+user.photoUrl); + console.log("UID: "+user.uid); + console.log("Provider ID: "+user.providerId); + console.log("ID token: "+user.idToken); + }, function(error) { + console.error("Failed to reload current user data: " + error); + }); +``` + +### updateUserProfile +Updates the display name and/or photo URL of the current Firebase user signed into the app. + +**Parameters**: +- {object} profile - new profile details: + - {string} name - display name of user + - {string} photoUri - URL of user profile photo +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.updateUserProfile({ + name: "Homer Simpson", + photoUri: "http://homer.simpson.com/photo.png" + },function() { + console.log("User profile successfully updated"); + }, function(error) { + console.error("Failed to update user profile: " + error); + }); +``` + +### updateUserEmail +Updates/sets the email address of the current Firebase user signed into the app. + +**Parameters**: +- {string} email - email address of user +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.updateUserEmail("user@somewhere.com",function() { + console.log("User email successfully updated"); + }, function(error) { + console.error("Failed to update user email: " + error); + }); +``` + +### sendUserEmailVerification +Sends a verification email to the currently configured email address of the current Firebase user signed into the app. +When the user opens the contained link, their email address will have been verified. + +**Parameters**: +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.sendUserEmailVerification(function() { + console.log("User verification email successfully sent"); + }, function(error) { + console.error("Failed to send user verification email: " + error); + }); +``` + +### updateUserPassword +Updates/sets the account password for the current Firebase user signed into the app. + +**Parameters**: +- {string} password - user-defined password +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.updateUserPassword("mypassword",function() { + console.log("User password successfully updated"); + }, function(error) { + console.error("Failed to update user password: " + error); + }); +``` + +### sendUserPasswordResetEmail +Sends a password reset email to the specified user email address. +Note: doesn't require the Firebase user to be signed in to the app. + +**Parameters**: +- {string} email - email address of user +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.sendUserPasswordResetEmail("user@somewhere.com",function() { + console.log("User password reset email sent successfully"); + }, function(error) { + console.error("Failed to send user password reset email: " + error); + }); +``` + +### deleteUser +Deletes the account of the current Firebase user signed into the app. + +**Parameters**: +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript + FirebasePlugin.deleteUser(function() { + console.log("User account deleted"); + }, function(error) { + console.error("Failed to delete current user account: " + error); + }); +``` + +### createUserWithEmailAndPassword +Creates a new email/password-based user account. +If account creation is successful, user will be automatically signed in. + +**Parameters**: +- {string} email - user email address. It is the responsibility of the app to ensure this is a valid email address. +- {string} password - user password. It is the responsibility of the app to ensure the password is suitable. +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript + FirebasePlugin.createUserWithEmailAndPassword(email, password, function() { + console.log("Successfully created email/password-based user account"); + // User is now signed in + }, function(error) { + console.error("Failed to create email/password-based user account", error); + }); +``` + +### signInUserWithEmailAndPassword +Signs in to an email/password-based user account. + +**Parameters**: +- {string} email - user email address +- {string} password - user password +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript + FirebasePlugin.signInUserWithEmailAndPassword(email, password, function() { + console.log("Successfully signed in"); + // User is now signed in + }, function(error) { + console.error("Failed to sign in", error); + }); +``` + +### signInUserWithCustomToken +Signs in user with custom token. + +**Parameters**: +- {string} customToken - the custom token +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript + FirebasePlugin.signInUserWithCustomToken(customToken, function() { + console.log("Successfully signed in"); + // User is now signed in + }, function(error) { + console.error("Failed to sign in", error); + }); +``` + +### signInUserAnonymously +Signs in user anonymously. + +**Parameters**: +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript + FirebasePlugin.signInUserAnonymously(function() { + console.log("Successfully signed in"); + // User is now signed in + }, function(error) { + console.error("Failed to sign in", error); + }); +``` + +### verifyPhoneNumber +Requests verification of a phone number. +The resulting credential can be used to create/sign in to a phone number-based user account in your app or to link the phone number to an existing user account + +**NOTE: This will only work on physical devices with a SIM card (not iOS Simulator or Android Emulator)** + +In response to your request, you'll receive a verification ID which you can use in conjunction with the verification code to sign the user in. + +There are 3 verification scenarios: +- Some Android devices support "instant verification" where the phone number can be instantly verified without sending or receiving an SMS. + - In this case, the user doesn't need to do anything in order for you to sign them in and you don't need to provide any additional credentials in order to sign the user in or link the user account to an existing Firebase user account. +- Some Android devices support "auto-retrieval" where Google Play services is able to detect the incoming verification SMS and perform verification with no user action required. + - As above, the user doesn't need to do anything in order for you to sign them in. +- For other Android devices and all iOS devices, the user must manually enter the verification code received in the SMS into your app. + - This code be used, along with the accompanying verification ID, to sign the user in or link phone number to an existing Firebase user account. + +**Parameters**: +- {function} success - callback function to pass {object} credentials to as an argument +- {function} error - callback function which will be passed a {string} error message as an argument +- {string} phoneNumber - phone number to verify +- {integer} timeOutDuration - (optional) time to wait in seconds before timing out +- {string} fakeVerificationCode - (optional) to test instant verification on Android ,specify a fake verification code to return for whitelisted phone numbers. + - See [Firebase SDK Phone Auth Android Integration Testing](https://firebase.google.com/docs/auth/android/phone-auth#integration-testing) for more info. + +The success callback will be passed a credential object with the following possible properties: +- {boolean} instantVerification - `true` if the Android device used instant verification to instantly verify the user without sending an SMS +or used auto-retrieval to automatically read an incoming SMS. +If this is `false`, the device will be sent an SMS containing the verification code. +If the Android device supports auto-retrieval, on the device receiving the SMS, this success callback will be immediately invoked again with `instantVerification: true` and no user action will be required for verification since Google Play services will extract and submit the verification code. +Otherwise the user must manually enter the verification code from the SMS into your app. +Always `false` on iOS. +- {string} id - the identifier of a native credential object which can be used for signing in the user. +Will only be present if `instantVerification` is `true`. +- {string} verificationId - the verification ID to be passed along with the verification code sent via SMS to sign the user in. +Will only be present if `instantVerification` is `false`. + +Example usage: + +```javascript +var number = '+441234567890'; +var timeOutDuration = 60; +var fakeVerificationCode = '123456'; +var awaitingSms = false; + +FirebasePlugin.verifyPhoneNumber(function(credential) { + + if(credential.instantVerification){ + if(awaitingSms){ + awaitingSms = false; + // the Android device used auto-retrieval to extract and submit the verification code in the SMS so dismiss user input UI + dismissUserPromptToInputCode(); + } + signInWithCredential(credential); + }else{ + awaitingSms = true; + promptUserToInputCode() // you need to implement this + .then(function(userEnteredCode){ + awaitingSms = false; + credential.code = userEnteredCode; // set the user-entered verification code on the credential object + signInWithCredential(credential); + }); + } +}, function(error) { + console.error("Failed to verify phone number: " + JSON.stringify(error)); +}, number, timeOutDuration, fakeVerificationCode); + +function signInWithCredential(credential){ + FirebasePlugin.signInWithCredential(credential, function() { + console.log("Successfully signed in"); + }, function(error) { + console.error("Failed to sign in", error); + }); +} +``` + +#### Android +To use phone auth with your Android app, you need to configure your app SHA-1 hash in the android app configuration in the Firebase console. +See [this guide](https://developers.google.com/android/guides/client-auth) to find how to your SHA-1 app hash. +See the [Firebase phone auth integration guide for native Android](https://firebase.google.com/docs/auth/android/phone-auth) for more information. + +#### iOS +When you call this method on iOS, FCM sends a silent push notification to the iOS device to verify it. +So to use phone auth with your iOS app, you need to: +- [setup your iOS app for push notifications](https://firebase.google.com/docs/cloud-messaging/ios/certs) +- Verify that push notifications are arriving on your physical device +- [Upload your APNs auth key to the Firebase console](https://firebase.google.com/docs/cloud-messaging/ios/client#upload_your_apns_authentication_key). + +You can [set up reCAPTCHA verification for iOS](https://firebase.google.com/docs/auth/ios/phone-auth#set-up-recaptcha-verification) automatically by specifying the `SETUP_RECAPTCHA_VERIFICATION` plugin variable at plugin install time: + + cordova plugin add cordova-plugin-firebasex --variable SETUP_RECAPTCHA_VERIFICATION=true + +This adds the `REVERSED_CLIENT_ID` from the `GoogleService-Info.plist` to the list of custom URL schemes in your Xcode project, so you don't need to do this manually. + +### authenticateUserWithGoogle +Authenticates the user with a Google account to obtain a credential that can be used to sign the user in/link to an existing user account/reauthenticate the user. + +**Parameters**: +- {string} clientId - your OAuth 2.0 client ID - [see here](https://developers.google.com/identity/sign-in/android/start-integrating#get_your_backend_servers_oauth_20_client_id) how to obtain it. +- {function} success - callback function to pass {object} credentials to as an argument. The credential object has the following properties: + - {string} id - the identifier of a native credential object which can be used for signing in the user. +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript +FirebasePlugin.authenticateUserWithGoogle(clientId, function(credential) { + FirebasePlugin.signInWithCredential(credential, function() { + console.log("Successfully signed in"); + }, function(error) { + console.error("Failed to sign in", error); + }); +}, function(error) { + console.error("Failed to authenticate with Google: " + error); +}); +``` + +#### Android +To use Google Sign-in in your Android app you need to do the following: +- Add the SHA-1 fingerprint of your app's signing key to your Firebase project +- Enable Google Sign-in in the Firebase console + +For details how to do the above, see the [Google Sign-In on Android page](https://firebase.google.com/docs/auth/android/google-signin) in the Firebase documentation. + +### authenticateUserWithApple +Authenticates the user with an Apple account using Sign In with Apple to obtain a credential that can be used to sign the user in/link to an existing user account/reauthenticate the user. + +**Parameters**: +- {function} success - callback function to pass {object} credentials to as an argument. The credential object has the following properties: + - {string} id - the identifier of a native credential object which can be used for signing in the user. +- {function} error - callback function which will be passed a {string} error message as an argument + - {string} locale - (Android only) the language to display Apple's Sign-in screen in. + - Defaults to "en" (English) if not specified. + - See [the Apple documentation](https://developer.apple.com/documentation/signinwithapplejs/incorporating_sign_in_with_apple_into_other_platforms###2112) for a list of supported locales. + - The value is ignored on iOS which uses the locale of the device to determine the display language. + +Example usage: + +```javascript + +FirebasePlugin.authenticateUserWithApple(function(credential) { + FirebasePlugin.signInWithCredential(credential, function() { + console.log("Successfully signed in"); + }, function(error) { + console.error("Failed to sign in", error); + }); +}, function(error) { + console.error("Failed to authenticate with Apple: " + error); +}, 'en_GB'); +``` +#### iOS +To use Sign In with Apple in your iOS app you need to do the following: +- Configure your app for Sign In with Apple as outlined in the [Firebase documentation's "Before you begin" section](https://firebase.google.com/docs/auth/ios/apple#before-you-begin) +- After adding the `cordova-ios` platform, open the project workspace in Xcode (`platforms/ios/YourApp.xcworkspace`) and add the "Sign In with Apple" capability in the "Signing & Capabilities section" + - Note: AFAIK there is currently no way to automate the addition of this capability + +#### Android +To use Sign In with Apple in your Android app you need to do the following: +- Configure your app for Sign In with Apple as outlined in the [Firebase documentation's "Before you begin" section](https://firebase.google.com/docs/auth/android/apple#before-you-begin) + +### signInWithCredential +Signs the user into Firebase with credentials obtained via an authentication method such as `verifyPhoneNumber()` or `authenticateUserWithGoogle()`. +See the [Android-](https://firebase.google.com/docs/auth/android/phone-auth#sign-in-the-user) and [iOS](https://firebase.google.com/docs/auth/ios/phone-auth#sign-in-the-user-with-the-verification-code)-specific Firebase documentation for more info. + +**Parameters**: +- {object} credential - a credential object returned by the success callback of an authentication method; may have the following keys: + - {string} id - the identifier of a native credential object which can be used for signing in the user. + Present if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `true`, or if another authentication method was used such as `authenticateUserWithGoogle()`. + - {boolean} instantVerification - true if an Android device and instant verification or auto-retrieval was used to verify the user. + If true, you do not need to provide a user-entered verification. + - Only present if the credential was obtained via `verifyPhoneNumber()` + - {string} verificationId - the verification ID to accompany the user-entered verification code from the SMS. + - Only present if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `false`. + - {string} code - if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `false`, you must set this to the activation code value as entered by the user from the received SMS message. +- {function} success - callback function to call on successful sign-in using credentials +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript +function signInWithCredential(credential){ + FirebasePlugin.signInWithCredential(credential, function() { + console.log("Successfully signed in"); + }, function(error) { + console.error("Failed to sign in", error); + }); +} + +``` + +### linkUserWithCredential +Links an existing Firebase user account with credentials obtained via an authentication method such as `verifyPhoneNumber()` or `authenticateUserWithGoogle()`. +See the [Android-](https://firebase.google.com/docs/auth/android/account-linking) and [iOS](https://firebase.google.com/docs/auth/ios/account-linking)-specific Firebase documentation for more info. + +**Parameters**: +- {object} credential - a credential object returned by the success callback of an authentication method; may have the following keys: + - {string} id - the identifier of a native credential object which can be used for signing in the user. + Present if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `true`, or if another authentication method was used such as `authenticateUserWithGoogle()`. + - {boolean} instantVerification - true if an Android device and instant verification or auto-retrieval was used to verify the user. + If true, you do not need to provide a user-entered verification. + - Only present if the credential was obtained via `verifyPhoneNumber()` + - {string} verificationId - the verification ID to accompany the user-entered verification code from the SMS. + - Only present if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `false`. + - {string} code - if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `false`, you must set this to the activation code value as entered by the user from the received SMS message. +- {function} success - callback function to call on successful linking using credentials +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript +function linkUserWithCredential(credential){ + FirebasePlugin.linkUserWithCredential(credential, function() { + console.log("Successfully linked"); + }, function(error) { + console.error("Failed to link", error); + }); +} + +``` + +### reauthenticateWithCredential +Reauthenticates the currently signed in user with credentials obtained via an authentication method such as `verifyPhoneNumber()` or `authenticateUserWithGoogle()`. + +**Parameters**: +- {object} credential - a credential object returned by the success callback of an authentication method; may have the following keys: + - {string} id - the identifier of a native credential object which can be used for signing in the user. + Present if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `true`, or if another authentication method was used such as `authenticateUserWithGoogle()`. + - {boolean} instantVerification - true if an Android device and instant verification or auto-retrieval was used to verify the user. + If true, you do not need to provide a user-entered verification. + - Only present if the credential was obtained via `verifyPhoneNumber()` + - {string} verificationId - the verification ID to accompany the user-entered verification code from the SMS. + - Only present if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `false`. + - {string} code - if the credential was obtained via `verifyPhoneNumber()` and `instantVerification` is `false`, you must set this to the activation code value as entered by the user from the received SMS message. +- {function} success - callback function to call on success +- {function} error - callback function which will be passed a {string} error message as an argument + +Example usage: + +```javascript + FirebasePlugin.reauthenticateWithCredential(credential, function() { + console.log("Successfully reauthenticated"); + }, function(error) { + console.error("Failed to reauthenticate", error); + }); +``` + +### registerAuthStateChangeListener +Registers a Javascript function to invoke when Firebase Authentication state changes between user signed in/signed out. + +**Parameters**: +- {function} fn - callback function to invoke when authentication state changes + - Will be a passed a single boolean argument which is `true` if user just signed in and `false` if user just signed out. + +Example usage: + +```javascript + FirebasePlugin.registerAuthStateChangeListener(function(userSignedIn){ + console.log("Auth state changed: User signed " + (userSignedIn ? "in" : "out")); + }); +``` + +## Remote Config + +### fetch +Fetch Remote Config parameter values for your app: + +**Parameters**: +- {integer} cacheExpirationSeconds (optional) - cache expiration in seconds +- {function} success - callback function on successfully fetching remote config +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.fetch(function () { + // success callback +}, function () { + // error callback +}); +// or, specify the cacheExpirationSeconds +FirebasePlugin.fetch(600, function () { + // success callback +}, function () { + // error callback +}); +``` + +### activateFetched +Activate the Remote Config fetched config: + +**Parameters**: +- {function} success - callback function which will be passed a {boolean} argument indicating whether fetched config was successfully activated +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.activateFetched(function(activated) { + // activated will be true if there was a fetched config activated, + // or false if no fetched config was found, or the fetched config was already activated. + console.log(activated); +}, function(error) { + console.error(error); +}); +``` + +### getValue +Retrieve a Remote Config value: + +**Parameters**: +- {string} key - key for which to fetch associated value +- {function} success - callback function which will be passed a {any} argument containing the value stored against the specified key. +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.getValue("key", function(value) { + console.log(value); +}, function(error) { + console.error(error); +}); +``` + +### getByteArray +Android only. +Retrieve a Remote Config byte array: + +**Parameters**: +- {string} key - key for which to fetch associated value +- {function} success - callback function which will be passed a {string} argument containing the Base64 encoded string that represents the value stored against the specified key. +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.getByteArray("key", function(bytes) { + // a Base64 encoded string that represents the value for "key" + console.log(bytes.base64); + // a numeric array containing the values of the byte array (i.e. [0xFF, 0x00]) + console.log(bytes.array); +}, function(error) { + console.error(error); +}); +``` + +### getInfo +Get the current state of the FirebaseRemoteConfig singleton object: + +**Parameters**: +- {function} success - callback function which will be passed an {object} argument containing the state info +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.getInfo(function(info) { + // the status of the developer mode setting (true/false) + console.log(info.configSettings.developerModeEnabled); + // (iOS only) for how much (secs) fetch cache is valid and data will not be refetched + console.log(info.configSettings.minimumFetchInterval); + // (iOS only) value in seconds to abandon a pending fetch request made to the backend + console.log(info.configSettings.fetchTimeout); + // the timestamp (milliseconds since epoch) of the last successful fetch + console.log(info.fetchTimeMillis); + // the status of the most recent fetch attempt (int) + // 0 = Config has never been fetched. + // 1 = Config fetch succeeded. + // 2 = Config fetch failed. + // 3 = Config fetch was throttled. + console.log(info.lastFetchStatus); +}, function(error) { + console.error(error); +}); +``` + +### setConfigSettings +Android only. +Change the settings for the FirebaseRemoteConfig object's operations: + +**Parameters**: +- {object} configSettings - object specifying the remote config settings +- {function} success - callback function to be call on successfully setting the remote config settings +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +var settings = { + developerModeEnabled: true +} +FirebasePlugin.setConfigSettings(settings); +``` + +### setDefaults +Android only. +Set defaults in the Remote Config: + +**Parameters**: +- {object} defaultSettings - object specifying the default remote config settings +- {function} success - callback function to be call on successfully setting the remote config setting defaults +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +// define defaults +var defaults = { + // map property name to value in Remote Config defaults + mLong: 1000, + mString: 'hello world', + mDouble: 3.14, + mBoolean: true, + // map "mBase64" to a Remote Config byte array represented by a Base64 string + // Note: the Base64 string is in an array in order to differentiate from a string config value + mBase64: ["SGVsbG8gV29ybGQ="], + // map "mBytes" to a Remote Config byte array represented by a numeric array + mBytes: [0xFF, 0x00] +} +// set defaults +FirebasePlugin.setDefaults(defaults); + +``` + +## Performance + +### setPerformanceCollectionEnabled +Manually enable/disable performance data collection, e.g. if [disabled on app startup](#disable-data-collection-on-startup). + +**Parameters**: +- {boolean} setEnabled - whether to enable or disable performance data collection + +```javascript +FirebasePlugin.setPerformanceCollectionEnabled(true); // Enables performance data collection + +FirebasePlugin.setPerformanceCollectionEnabled(false); // Disables performance data collection +``` + +### isPerformanceCollectionEnabled +Indicates whether performance data collection is enabled. + +Notes: +- This value applies both to the current app session and subsequent app sessions until such time as it is changed. +- It returns the value set by [setPerformanceCollectionEnabled()](#setperformancecollectionenabled). +- If automatic data collection was not [disabled on app startup](#disable-data-collection-on-startup), this will always return `true`. + +**Parameters**: +- {function} success - callback function which will be invoked on success. +Will be passed a {boolean} indicating if the setting is enabled. +- {function} error - (optional) callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.isPerformanceCollectionEnabled(function(enabled){ + console.log("Performance data collection is "+(enabled ? "enabled" : "disabled")); +}, function(error){ + console.error("Error getting Performance data collection setting: "+error); +}); +``` + +### startTrace + +Start a trace. + +**Parameters**: +- {string} name - name of trace to start +- {function} success - callback function to call on successfully starting trace +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.startTrace("test trace", success, error); +``` + +### incrementCounter + +To count the performance-related events that occur in your app (such as cache hits or retries), add a line of code similar to the following whenever the event occurs, using a string other than retry to name that event if you are counting a different type of event: + +**Parameters**: +- {string} name - name of trace +- {string} counterName - name of counter to increment +- {function} success - callback function to call on successfully incrementing counter +- {function} error - callback function which will be passed a {string} error message as an argument + + +```javascript +FirebasePlugin.incrementCounter("test trace", "retry", success, error); +``` + +### stopTrace + +Stop the trace + +**Parameters**: +- {string} name - name of trace to stop +- {function} success - callback function to call on successfully stopping trace +- {function} error - callback function which will be passed a {string} error message as an argument + +```javascript +FirebasePlugin.stopTrace("test trace"); +``` + +## Firestore +These plugin API functions provide CRUD operations for working with documents in Firestore collections. + +Notes: +- Only top-level Firestore collections are currently supported - [subcollections](https://firebase.google.com/docs/firestore/manage-data/structure-data#subcollections) (nested collections within documents) are currently not supported due to the complexity of mapping the native objects into the plugin's JS API layer. +- A document object may contain values of primitive Javascript types `string`, `number`, `boolean`, `array` or `object`. +Arrays and objects may contain nested structures of these types. +- If a collection name referenced in a document write operation does not already exist, it will be created by the first write operation referencing it. + +### addDocumentToFirestoreCollection +Adds a new document to a Firestore collection, which will be allocated an auto-generated document ID. + +**Parameters**: +- {object} document - document object to add to collection +- {string} collection - name of top-level collection to add document to. +- {function} success - callback function to call on successfully adding the document. +Will be passed a {string} argument containing the auto-generated document ID that the document was stored against. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var document = { + "a_string": "foo", + "a_list": [1, 2, 3], + "an_object": { + "an_integer": 1, + } +}; +var collection = "my_collection"; +FirebasePlugin.addDocumentToFirestoreCollection(document, collection, function(documentId){ + console.log("Successfully added document with id="+documentId); +}, function(error){ + console.error("Error adding document: "+error); +}); +``` + +### setDocumentInFirestoreCollection +Sets (adds/replaces) a document with the given ID in a Firestore collection. + +**Parameters**: +- {string} documentId - document ID to use when setting document in the collection. +- {object} document - document object to set in collection. +- {string} collection - name of top-level collection to set document in. +- {function} success - callback function to call on successfully setting the document. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var documentId = "my_doc"; +var document = { + "a_string": "foo", + "a_list": [1, 2, 3], + "an_object": { + "an_integer": 1, + } +}; +var collection = "my_collection"; +FirebasePlugin.setDocumentInFirestoreCollection(documentId, document, collection, function(){ + console.log("Successfully set document with id="+documentId); +}, function(error){ + console.error("Error setting document: "+error); +}); +``` + +### updateDocumentInFirestoreCollection +Updates an existing document with the given ID in a Firestore collection. +This is a non-destructive update that will only overwrite existing keys in the existing document or add new ones if they don't already exist. +If the no document with the specified ID exists in the collection, an error will be raised. + +**Parameters**: +- {string} documentId - document ID of the document to update. +- {object} document - entire document or document fragment to update existing document with. +- {string} collection - name of top-level collection to update document in. +- {function} success - callback function to call on successfully updating the document. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var documentId = "my_doc"; +var documentFragment = { + "a_string": "new value", + "a_new_string": "bar" +}; +var collection = "my_collection"; +FirebasePlugin.updateDocumentInFirestoreCollection(documentId, documentFragment, collection, function(){ + console.log("Successfully updated document with id="+documentId); +}, function(error){ + console.error("Error updating document: "+error); +}); +``` + +### deleteDocumentFromFirestoreCollection +Deletes an existing document with the given ID in a Firestore collection. + +Note: If the no document with the specified ID exists in the collection, the Firebase SDK will still return a successful outcome. + +**Parameters**: +- {string} documentId - document ID of the document to delete. +- {string} collection - name of top-level collection to delete document in. +- {function} success - callback function to call on successfully deleting the document. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var documentId = "my_doc"; +var collection = "my_collection"; +FirebasePlugin.deleteDocumentFromFirestoreCollection(documentId, collection, function(){ + console.log("Successfully deleted document with id="+documentId); +}, function(error){ + console.error("Error deleting document: "+error); +}); +``` + +### documentExistsInFirestoreCollection +Indicates if a document with the given ID exists in a Firestore collection. + +**Parameters**: +- {string} documentId - document ID of the document. +- {string} collection - name of top-level collection to check for document. +- {function} success - callback function to call pass result. +Will be passed an {boolean} which is `true` if a document exists. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var documentId = "my_doc"; +var collection = "my_collection"; +FirebasePlugin.documentExistsInFirestoreCollection(documentId, collection, function(exists){ + console.log("Document " + (exists ? "exists" : "doesn't exist")); +}, function(error){ + console.error("Error fetching document: "+error); +}); +``` + +### fetchDocumentInFirestoreCollection +Fetches an existing document with the given ID from a Firestore collection. + +Note: If the no document with the specified ID exists in the collection, the error callback will be invoked. + +**Parameters**: +- {string} documentId - document ID of the document to fetch. +- {string} collection - name of top-level collection to fetch document from. +- {function} success - callback function to call on successfully fetching the document. +Will be passed an {object} contain the document contents. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var documentId = "my_doc"; +var collection = "my_collection"; +FirebasePlugin.fetchDocumentInFirestoreCollection(documentId, collection, function(document){ + console.log("Successfully fetched document: "+JSON.stringify(document)); +}, function(error){ + console.error("Error fetching document: "+error); +}); +``` + +### fetchFirestoreCollection +Fetches all the documents in the specific collection. + +**Parameters**: +- {string} collection - name of top-level collection to fetch. +- {array} filters - a list of filters to sort/filter the documents returned from your collection. + - Supports `where`, `orderBy`, `startAt`, `endAt` and `limit` filters. + - See the [Firestore documentation](https://firebase.google.com/docs/firestore/query-data/queries) for more details. +- {function} success - callback function to call on successfully deleting the document. +Will be passed an {object} containing all the documents in the collection, indexed by document ID. +If a Firebase collection with that name does not exist or it contains no documents, the object will be empty. +- {function} error - callback function which will be passed a {string} error message as an argument. + +```javascript +var collection = "my_collection"; +var filters = [ + ['where', 'field', '==', 'value'], + ['orderBy', 'field', 'desc'] +]; +FirebasePlugin.fetchFirestoreCollection(collection, filters, function(documents){ + console.log("Successfully fetched collection: "+JSON.stringify(documents)); +}, function(error){ + console.error("Error fetching collection: "+error); +}); +``` + + + +# Credits +- [@robertarnesson](https://github.com/robertarnesson) for the original [cordova-plugin-firebase](https://github.com/arnesson/cordova-plugin-firebase) from which this plugin is forked. +- [@sagrawal31](https://github.com/sagrawal31) and [Wiz Panda](https://github.com/wizpanda) for contributions via [cordova-plugin-firebase-lib](https://github.com/wizpanda/cordova-plugin-firebase-lib). +- [Full list of contributors](https://github.com/dpa99c/cordova-plugin-firebasex/graphs/contributors) diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/_config.yml b/StoneIsland/plugins/cordova-plugin-firebasex/_config.yml new file mode 100644 index 00000000..c4192631 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/bump-version.js b/StoneIsland/plugins/cordova-plugin-firebasex/bump-version.js new file mode 100644 index 00000000..8e4d075f --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/bump-version.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const version = require('./package.json').version; + +let data = fs.readFileSync('./plugin.xml', "utf8"); +data = data.replace(/plugin id="cordova-plugin-firebase" version="[^"]+"/, `plugin id="cordova-plugin-firebase" version="${version}"`); +fs.writeFileSync('./plugin.xml', data); diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/package.json b/StoneIsland/plugins/cordova-plugin-firebasex/package.json new file mode 100644 index 00000000..3bdc2292 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/package.json @@ -0,0 +1,73 @@ +{ + "_from": "cordova-plugin-firebasex", + "_id": "cordova-plugin-firebasex@10.2.0-cli", + "_inBundle": false, + "_integrity": "sha512-EQWsbVHlr5jHrmi0WCdnkYpV/6BNBhhNIpD0gOIMFrHIETjCPSkV1epeW5nvISRW23OZqd4LAZTQeByFa7AcNQ==", + "_location": "/cordova-plugin-firebasex", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "cordova-plugin-firebasex", + "name": "cordova-plugin-firebasex", + "escapedName": "cordova-plugin-firebasex", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#DEV:/", + "#USER" + ], + "_resolved": "https://registry.npmjs.org/cordova-plugin-firebasex/-/cordova-plugin-firebasex-10.2.0-cli.tgz", + "_shasum": "c1cdeb6d957a35e84977106f0db74c3a129e49ec", + "_spec": "cordova-plugin-firebasex", + "_where": "/Users/user/work/stone-island/StoneIsland", + "author": { + "name": "Dave Alden" + }, + "bugs": { + "url": "https://github.com/dpa99c/cordova-plugin-firebase/issues" + }, + "bundleDependencies": false, + "cordova": { + "id": "cordova-plugin-firebase", + "platforms": [ + "android", + "ios" + ] + }, + "dependencies": { + "plist": "^3.0.1", + "semver": "^7.3.2", + "xcode": "^3.0.1", + "xml-js": "^1.6.11" + }, + "deprecated": false, + "description": "Cordova plugin for Google Firebase", + "homepage": "https://github.com/dpa99c/cordova-plugin-firebase#readme", + "keywords": [ + "ecosystem:cordova", + "cordova-android", + "cordova-ios", + "firebase", + "push", + "notifications", + "phone auth" + ], + "license": "MIT", + "name": "cordova-plugin-firebasex", + "repository": { + "type": "git", + "url": "git+https://github.com/dpa99c/cordova-plugin-firebase.git" + }, + "scripts": { + "postversion": "git push && git push --tags && npm publish --verbose", + "test": "npm run test:ios && npm run test:android", + "test:android": "bash ./test/test-default.sh 9.0.0 android 8.1.0 && bash ./test/test-with-3-plugins.sh 9.0.0 android 8.1.0 cordova-plugin-request-location-accuracy cordova-android-play-services-gradle-release cordova-android-firebase-gradle-release", + "test:ios": "bash ./test/test-default.sh 9.0.0 ios 5.0.1", + "version": "node ./bump-version.js && git add -A plugin.xml" + }, + "types": "./types/index.d.ts", + "version": "10.2.0-cli" +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/plugin.xml b/StoneIsland/plugins/cordova-plugin-firebasex/plugin.xml new file mode 100644 index 00000000..934d49ca --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/plugin.xml @@ -0,0 +1,145 @@ +<?xml version='1.0' encoding='utf-8'?> +<plugin id="cordova-plugin-firebasex" version="10.2.0-cli" + xmlns="http://apache.org/cordova/ns/plugins/1.0" + xmlns:android="http://schemas.android.com/apk/res/android"> + <name>Google Firebase Plugin</name> + + <license>MIT</license> + + <dependency id="cordova-plugin-androidx" version="^2.0.0" /> + <dependency id="cordova-plugin-androidx-adapter" version="^1.1.1" /> + + <engines> + <engine name="cordova" version=">=9" /> + <engine name="cordova-android" version=">=8" /> + <engine name="cordova-ios" version=">=5" /> + </engines> + + <preference name="FIREBASE_ANALYTICS_COLLECTION_ENABLED" default="true" /> + <preference name="FIREBASE_PERFORMANCE_COLLECTION_ENABLED" default="true" /> + <preference name="FIREBASE_CRASHLYTICS_COLLECTION_ENABLED" default="true" /> + + <platform name="android"> + <preference name="ANDROID_ICON_ACCENT" default="#FF00FFFF" /> + + <js-module name="FirebasePlugin" src="www/firebase.js"> + <clobbers target="FirebasePlugin" /> + </js-module> + <config-file parent="/*" target="res/xml/config.xml"> + <feature name="FirebasePlugin"> + <param name="android-package" value="org.apache.cordova.firebase.FirebasePlugin" /> + <param name="onload" value="true" /> + </feature> + </config-file> + <config-file target="AndroidManifest.xml" parent="/*"> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + </config-file> + <config-file target="AndroidManifest.xml" parent="application"> + <service android:enabled="true" android:exported="false" android:name="com.google.android.gms.measurement.AppMeasurementService" /> + <service android:name="org.apache.cordova.firebase.FirebasePluginMessagingService"> + <intent-filter> + <action android:name="com.google.firebase.MESSAGING_EVENT"/> + </intent-filter> + </service> + <receiver android:name="org.apache.cordova.firebase.OnNotificationOpenReceiver"/> + <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/accent" /> + <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/default_notification_channel_id"/> + <meta-data android:name="firebase_analytics_collection_enabled" android:value="$FIREBASE_ANALYTICS_COLLECTION_ENABLED" /> + <meta-data android:name="firebase_performance_collection_enabled" android:value="$FIREBASE_PERFORMANCE_COLLECTION_ENABLED" /> + <meta-data android:name="firebase_crashlytics_collection_enabled" android:value="$FIREBASE_CRASHLYTICS_COLLECTION_ENABLED" /> + </config-file> + <resource-file src="src/android/cordova-plugin-firebase-strings.xml" target="res/values/cordova-plugin-firebase-strings.xml" /> + <source-file src="src/android/FirebasePlugin.java" target-dir="src/org/apache/cordova/firebase" /> + <source-file src="src/android/OnNotificationOpenReceiver.java" target-dir="src/org/apache/cordova/firebase" /> + <source-file src="src/android/FirebasePluginMessagingService.java" target-dir="src/org/apache/cordova/firebase" /> + <source-file src="src/android/FirebasePluginMessageReceiver.java" target-dir="src/org/apache/cordova/firebase" /> + <source-file src="src/android/FirebasePluginMessageReceiverManager.java" target-dir="src/org/apache/cordova/firebase" /> + <source-file src="src/android/JavaScriptException.java" target-dir="src/org/apache/cordova/firebase"/> + + <framework src="src/android/build.gradle" custom="true" type="gradleReference" /> + + <!-- Default versions for Gradle dependencies --> + <preference name="ANDROID_PLAY_SERVICES_AUTH_VERSION" default="18.0.0" /> + <preference name="ANDROID_FIREBASE_ANALYTICS_VERSION" default="17.4.3" /> + <preference name="ANDROID_FIREBASE_MESSAGING_VERSION" default="20.2.1" /> + <preference name="ANDROID_FIREBASE_CONFIG_VERSION" default="19.1.4" /> + <preference name="ANDROID_FIREBASE_PERF_VERSION" default="19.0.7" /> + <preference name="ANDROID_FIREBASE_AUTH_VERSION" default="19.3.1" /> + <preference name="ANDROID_FIREBASE_FIRESTORE_VERSION" default="21.4.3" /> + <preference name="ANDROID_FIREBASE_CRASHLYTICS_VERSION" default="17.0.1" /> + <preference name="ANDROID_FIREBASE_CRASHLYTICS_NDK_VERSION" default="17.0.1" /> + <preference name="ANDROID_GSON_VERSION" default="2.8.6" /> + + <framework src="com.google.android.gms:play-services-auth:$ANDROID_PLAY_SERVICES_AUTH_VERSION" /> + <framework src="com.google.firebase:firebase-analytics:$ANDROID_FIREBASE_ANALYTICS_VERSION" /> + <framework src="com.google.firebase:firebase-messaging:$ANDROID_FIREBASE_MESSAGING_VERSION" /> + <framework src="com.google.firebase:firebase-config:$ANDROID_FIREBASE_CONFIG_VERSION" /> + <framework src="com.google.firebase:firebase-perf:$ANDROID_FIREBASE_PERF_VERSION" /> + <framework src="com.google.firebase:firebase-auth:$ANDROID_FIREBASE_AUTH_VERSION" /> + <framework src="com.google.firebase:firebase-firestore:$ANDROID_FIREBASE_FIRESTORE_VERSION" /> + <framework src="com.google.firebase:firebase-crashlytics:$ANDROID_FIREBASE_CRASHLYTICS_VERSION" /> + <framework src="com.google.firebase:firebase-crashlytics-ndk:$ANDROID_FIREBASE_CRASHLYTICS_NDK_VERSION" /> + <framework src="com.google.code.gson:gson:$ANDROID_GSON_VERSION" /> + </platform> + + <platform name="ios"> + <hook type="before_plugin_install" src="scripts/ios/before_plugin_install.js" /> + <hook type="after_plugin_install" src="scripts/ios/after_plugin_install.js" /> + <hook type="before_plugin_uninstall" src="scripts/ios/before_plugin_uninstall.js" /> + + <js-module name="FirebasePlugin" src="www/firebase.js"> + <clobbers target="FirebasePlugin" /> + </js-module> + <config-file parent="/*" target="config.xml"> + <feature name="FirebasePlugin"> + <param name="ios-package" value="FirebasePlugin" /> + <param name="onload" value="true" /> + </feature> + </config-file> + <config-file parent="aps-environment" target="*/Entitlements-Debug.plist"> + <string>development</string> + </config-file> + <config-file parent="aps-environment" target="*/Entitlements-Release.plist"> + <string>production</string> + </config-file> + <config-file target="*-Info.plist" parent="UIBackgroundModes"> + <array> + <string>remote-notification</string> + </array> + </config-file> + + <resource-file src="src/ios/GoogleService-Info.plist" /> + + <header-file src="src/ios/AppDelegate+FirebasePlugin.h" /> + <source-file src="src/ios/AppDelegate+FirebasePlugin.m" /> + <header-file src="src/ios/FirebasePlugin.h" /> + <source-file src="src/ios/FirebasePlugin.m" /> + <header-file src="src/ios/FirebasePluginMessageReceiver.h" /> + <source-file src="src/ios/FirebasePluginMessageReceiver.m" /> + <header-file src="src/ios/FirebasePluginMessageReceiverManager.h" /> + <source-file src="src/ios/FirebasePluginMessageReceiverManager.m" /> + + <framework src="AuthenticationServices.framework" /> + + <podspec> + <config> + <source url="https://cdn.cocoapods.org/"/> + </config> + <pods use-frameworks="true"> + <pod name="Firebase/Core" spec="6.28.1"/> + <pod name="Firebase/Auth" spec="6.28.1"/> + <pod name="Firebase/Messaging" spec="6.28.1"/> + <pod name="Firebase/Performance" spec="6.28.1"/> + <pod name="Firebase/RemoteConfig" spec="6.28.1"/> + <pod name="FirebaseFirestore" git="https://github.com/invertase/firestore-ios-sdk-frameworks.git" tag="6.28.1"/> + <pod name="Firebase/Crashlytics" spec="6.28.1"/> + <pod name="GoogleSignIn" spec="5.0.2"/> + </pods> + </podspec> + + </platform> + + <hook type="after_prepare" src="scripts/after_prepare.js" /> +</plugin> diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/after_prepare.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/after_prepare.js new file mode 100644 index 00000000..b3a7ab59 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/after_prepare.js @@ -0,0 +1,164 @@ +#!/usr/bin/env node + +'use strict'; + +/** + * This hook makes sure projects using [cordova-plugin-firebase](https://github.com/arnesson/cordova-plugin-firebase) + * will build properly and have the required key files copied to the proper destinations when the app is build on Ionic Cloud using the package command. + * Credits: https://github.com/arnesson. + */ +var fs = require('fs'); +var path = require("path"); +var Utilities = require("./lib/utilities"); + +var appName = Utilities.getAppName(); +var pluginVariables = {}; + +var IOS_DIR = 'platforms/ios'; +var ANDROID_DIR = 'platforms/android'; +var PLUGIN_ID = 'cordova-plugin-firebasex'; + +var PLATFORM = { + IOS: { + dest: IOS_DIR + '/' + appName + '/Resources/GoogleService-Info.plist', + src: [ + 'GoogleService-Info.plist', + IOS_DIR + '/www/GoogleService-Info.plist', + 'www/GoogleService-Info.plist' + ], + appPlist: IOS_DIR + '/' + appName + '/'+appName+'-Info.plist', + }, + ANDROID: { + dest: ANDROID_DIR + '/app/google-services.json', + src: [ + 'google-services.json', + ANDROID_DIR + '/assets/www/google-services.json', + 'www/google-services.json', + ANDROID_DIR + '/app/src/main/google-services.json' + ], + colorsXml:{ + src: './plugins/' + Utilities.getPluginId() +'/src/android/colors.xml', + target: ANDROID_DIR + '/app/src/main/res/values/colors.xml' + } + } +}; + + +var parsePluginVariables = function(){ + // Parse plugin.xml + var plugin = Utilities.parsePluginXml(); + var prefs = []; + if(plugin.plugin.preference){ + prefs = prefs.concat(plugin.plugin.preference); + } + plugin.plugin.platform.forEach(function(platform){ + if(platform.preference){ + prefs = prefs.concat(platform.preference); + } + }); + prefs.forEach(function(pref){ + pluginVariables[pref._attributes.name] = pref._attributes.default; + }); + + // Parse config.xml + var config = Utilities.parseConfigXml(); + (config.widget.plugin ? [].concat(config.widget.plugin) : []).forEach(function(plugin){ + (plugin.variable ? [].concat(plugin.variable) : []).forEach(function(variable){ + if((plugin._attributes.name === PLUGIN_ID || plugin._attributes.id === PLUGIN_ID) && variable._attributes.name && variable._attributes.value){ + pluginVariables[variable._attributes.name] = variable._attributes.value; + } + }); + }); + + // Parse package.json + var packageJSON = Utilities.parsePackageJson(); + if(packageJSON.cordova && packageJSON.cordova.plugins){ + for(const pluginId in packageJSON.cordova.plugins){ + if(pluginId === PLUGIN_ID){ + for(const varName in packageJSON.cordova.plugins[pluginId]){ + var varValue = packageJSON.cordova.plugins[pluginId][varName]; + pluginVariables[varName] = varValue; + } + } + } + } + + // set platform key path from plugin variable + if (pluginVariables.ANDROID_FIREBASE_CONFIG_FILEPATH) PLATFORM.ANDROID.src = [pluginVariables.ANDROID_FIREBASE_CONFIG_FILEPATH]; + if (pluginVariables.IOS_FIREBASE_CONFIG_FILEPATH) PLATFORM.IOS.src = [pluginVariables.IOS_FIREBASE_CONFIG_FILEPATH]; +}; + +module.exports = function (context) { + + //get platform from the context supplied by cordova + var platforms = context.opts.platforms; + parsePluginVariables(); + + // Copy key files to their platform specific folders + if (platforms.indexOf('android') !== -1 && Utilities.directoryExists(ANDROID_DIR)) { + Utilities.log('Preparing Firebase on Android'); + Utilities.copyKey(PLATFORM.ANDROID); + + if(!fs.existsSync(path.resolve(PLATFORM.ANDROID.colorsXml.target))){ + fs.copyFileSync(path.resolve(PLATFORM.ANDROID.colorsXml.src), path.resolve(PLATFORM.ANDROID.colorsXml.target)); + } + + const $colorsXml = Utilities.parseXmlFileToJson(PLATFORM.ANDROID.colorsXml.target, {compact: true}); + var accentColor = pluginVariables.ANDROID_ICON_ACCENT, + $resources = $colorsXml.resources, + existingAccent = false, + writeChanges = false; + + if($resources.color){ + var $colors = $resources.color.length ? $resources.color : [$resources.color]; + $colors.forEach(function($color){ + if($color._attributes.name === 'accent'){ + existingAccent = true; + if($color._text !== accentColor){ + $color._text = accentColor; + writeChanges = true; + } + } + }); + }else{ + $resources.color = {}; + } + + if(!existingAccent){ + var $accentColor = { + _attributes: { + name: 'accent' + }, + _text: accentColor + }; + if($resources.color && Object.keys($resources.color).length){ + if(typeof $resources.color.length === 'undefined'){ + $resources.color = [$resources.color]; + } + $resources.color.push($accentColor) + }else{ + $resources.color = $accentColor; + } + writeChanges = true; + } + + if(writeChanges){ + Utilities.writeJsonToXmlFile($colorsXml, PLATFORM.ANDROID.colorsXml.target); + Utilities.log('Updated colors.xml with accent color'); + } + } + + if (platforms.indexOf('ios') !== -1 && Utilities.directoryExists(IOS_DIR)){ + Utilities.log('Preparing Firebase on iOS'); + Utilities.copyKey(PLATFORM.IOS); + + var helper = require("./ios/helper"); + var xcodeProjectPath = helper.getXcodeProjectPath(); + helper.ensureRunpathSearchPath(context, xcodeProjectPath); + + if(pluginVariables['IOS_STRIP_DEBUG'] && pluginVariables['IOS_STRIP_DEBUG'] === 'true'){ + helper.stripDebugSymbols(); + } + helper.applyPluginVarsToPlists(PLATFORM.IOS.dest, PLATFORM.IOS.appPlist, pluginVariables); + } +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/after_plugin_install.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/after_plugin_install.js new file mode 100644 index 00000000..3384f75b --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/after_plugin_install.js @@ -0,0 +1,10 @@ +var helper = require("./helper"); + +module.exports = function(context) { + + // Add a build phase which runs a shell script that executes the Crashlytics + // run command line tool which uploads the debug symbols at build time. + var xcodeProjectPath = helper.getXcodeProjectPath(); + helper.removeShellScriptBuildPhase(context, xcodeProjectPath); + helper.addShellScriptBuildPhase(context, xcodeProjectPath); +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_install.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_install.js new file mode 100644 index 00000000..9b860005 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_install.js @@ -0,0 +1,23 @@ +var execSync = require('child_process').execSync; +var semver = require('semver'); + +var minCocoapodsVersion = "^1.9.1"; + +module.exports = function(context) { + checkCocoapodsVersion(); +}; + +function checkCocoapodsVersion(){ + var version; + try{ + version = execSync('pod --version', {encoding: 'utf8'}).match(/(\d+\.\d+\.\d+)/)[1]; + }catch(err){ + throw new Error("cocoapods not found - please install cocoapods >="+minCocoapodsVersion); + } + + if(!semver.valid(version)){ + throw new Error("cocoapods version is invalid - please reinstall cocoapods@"+minCocoapodsVersion + ": "+version); + }else if(!semver.satisfies(version, minCocoapodsVersion)){ + throw new Error("cocoapods version is out-of-date - please update to cocoapods@"+minCocoapodsVersion + " - current version: "+version); + } +}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_uninstall.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_uninstall.js new file mode 100644 index 00000000..783512a6 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_uninstall.js @@ -0,0 +1,8 @@ +var helper = require("./helper"); + +module.exports = function(context) { + + // Remove the build script that was added when the plugin was installed. + var xcodeProjectPath = helper.getXcodeProjectPath(); + helper.removeShellScriptBuildPhase(context, xcodeProjectPath); +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/helper.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/helper.js new file mode 100644 index 00000000..be12ae06 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/helper.js @@ -0,0 +1,238 @@ +var fs = require("fs"); +var path = require("path"); +var utilities = require("../lib/utilities"); +var xcode = require("xcode"); +var plist = require('plist'); + +/** + * This is used as the display text for the build phase block in XCode as well as the + * inline comments inside of the .pbxproj file for the build script phase block. + */ +var comment = "\"Crashlytics\""; + +module.exports = { + + /** + * Used to get the path to the XCode project's .pbxproj file. + */ + getXcodeProjectPath: function () { + var appName = utilities.getAppName(); + return path.join("platforms", "ios", appName + ".xcodeproj", "project.pbxproj"); + }, + + /** + * This helper is used to add a build phase to the XCode project which runs a shell + * script during the build process. The script executes Crashlytics run command line + * tool with the API and Secret keys. This tool is used to upload the debug symbols + * (dSYMs) so that Crashlytics can display stack trace information in it's web console. + */ + addShellScriptBuildPhase: function (context, xcodeProjectPath) { + + // Read and parse the XCode project (.pxbproj) from disk. + // File format information: http://www.monobjc.net/xcode-project-file-format.html + var xcodeProject = xcode.project(xcodeProjectPath); + xcodeProject.parseSync(); + + // Build the body of the script to be executed during the build phase. + var script = '"' + '\\"${PODS_ROOT}/FirebaseCrashlytics/run\\"' + '"'; + + // Generate a unique ID for our new build phase. + var id = xcodeProject.generateUuid(); + // Create the build phase. + xcodeProject.hash.project.objects.PBXShellScriptBuildPhase[id] = { + isa: "PBXShellScriptBuildPhase", + buildActionMask: 2147483647, + files: [], + inputPaths: ['"' + '$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)' + '"'], + name: comment, + outputPaths: [], + runOnlyForDeploymentPostprocessing: 0, + shellPath: "/bin/sh", + shellScript: script, + showEnvVarsInLog: 0 + }; + + // Add a comment to the block (viewable in the source of the pbxproj file). + xcodeProject.hash.project.objects.PBXShellScriptBuildPhase[id + "_comment"] = comment; + + // Add this new shell script build phase block to the targets. + for (var nativeTargetId in xcodeProject.hash.project.objects.PBXNativeTarget) { + + // Skip over the comment blocks. + if (nativeTargetId.indexOf("_comment") !== -1) { + continue; + } + + var nativeTarget = xcodeProject.hash.project.objects.PBXNativeTarget[nativeTargetId]; + + nativeTarget.buildPhases.push({ + value: id, + comment: comment + }); + } + + // Finally, write the .pbxproj back out to disk. + fs.writeFileSync(path.resolve(xcodeProjectPath), xcodeProject.writeSync()); + }, + + /** + * This helper is used to remove the build phase from the XCode project that was added + * by the addShellScriptBuildPhase() helper method. + */ + removeShellScriptBuildPhase: function (context, xcodeProjectPath) { + + // Read and parse the XCode project (.pxbproj) from disk. + // File format information: http://www.monobjc.net/xcode-project-file-format.html + var xcodeProject = xcode.project(xcodeProjectPath); + xcodeProject.parseSync(); + + // First, we want to delete the build phase block itself. + + var buildPhases = xcodeProject.hash.project.objects.PBXShellScriptBuildPhase; + + var commentTest = comment.replace(/"/g, ''); + for (var buildPhaseId in buildPhases) { + + var buildPhase = xcodeProject.hash.project.objects.PBXShellScriptBuildPhase[buildPhaseId]; + var shouldDelete = false; + + if (buildPhaseId.indexOf("_comment") === -1) { + // Dealing with a build phase block. + + // If the name of this block matches ours, then we want to delete it. + shouldDelete = buildPhase.name && buildPhase.name.indexOf(commentTest) !== -1; + } else { + // Dealing with a comment block. + + // If this is a comment block that matches ours, then we want to delete it. + shouldDelete = buildPhase === commentTest; + } + + if (shouldDelete) { + delete buildPhases[buildPhaseId]; + } + } + + // Second, we want to delete the native target reference to the block. + + var nativeTargets = xcodeProject.hash.project.objects.PBXNativeTarget; + + for (var nativeTargetId in nativeTargets) { + + // Skip over the comment blocks. + if (nativeTargetId.indexOf("_comment") !== -1) { + continue; + } + + var nativeTarget = nativeTargets[nativeTargetId]; + + // We remove the reference to the block by filtering out the the ones that match. + nativeTarget.buildPhases = nativeTarget.buildPhases.filter(function (buildPhase) { + return buildPhase.comment !== commentTest; + }); + } + + // Finally, write the .pbxproj back out to disk. + fs.writeFileSync(path.resolve(xcodeProjectPath), xcodeProject.writeSync()); + }, + + ensureRunpathSearchPath: function(context, xcodeProjectPath){ + + function addRunpathSearchBuildProperty(proj, build) { + let LD_RUNPATH_SEARCH_PATHS = proj.getBuildProperty("LD_RUNPATH_SEARCH_PATHS", build); + + if (!Array.isArray(LD_RUNPATH_SEARCH_PATHS)) { + LD_RUNPATH_SEARCH_PATHS = [LD_RUNPATH_SEARCH_PATHS]; + } + + LD_RUNPATH_SEARCH_PATHS.forEach(LD_RUNPATH_SEARCH_PATH => { + if (!LD_RUNPATH_SEARCH_PATH) { + proj.addBuildProperty("LD_RUNPATH_SEARCH_PATHS", "\"$(inherited) @executable_path/Frameworks\"", build); + } + if (LD_RUNPATH_SEARCH_PATH.indexOf("@executable_path/Frameworks") == -1) { + var newValue = LD_RUNPATH_SEARCH_PATH.substr(0, LD_RUNPATH_SEARCH_PATH.length - 1); + newValue += ' @executable_path/Frameworks\"'; + proj.updateBuildProperty("LD_RUNPATH_SEARCH_PATHS", newValue, build); + } + if (LD_RUNPATH_SEARCH_PATH.indexOf("$(inherited)") == -1) { + var newValue = LD_RUNPATH_SEARCH_PATH.substr(0, LD_RUNPATH_SEARCH_PATH.length - 1); + newValue += ' $(inherited)\"'; + proj.updateBuildProperty("LD_RUNPATH_SEARCH_PATHS", newValue, build); + } + }); + } + + // Read and parse the XCode project (.pxbproj) from disk. + // File format information: http://www.monobjc.net/xcode-project-file-format.html + var xcodeProject = xcode.project(xcodeProjectPath); + xcodeProject.parseSync(); + + // Add search paths build property + addRunpathSearchBuildProperty(xcodeProject, "Debug"); + addRunpathSearchBuildProperty(xcodeProject, "Release"); + + // Finally, write the .pbxproj back out to disk. + fs.writeFileSync(path.resolve(xcodeProjectPath), xcodeProject.writeSync()); + }, + stripDebugSymbols: function(){ + var podFilePath = 'platforms/ios/Podfile', + podFile = fs.readFileSync(path.resolve(podFilePath)).toString(); + if(!podFile.match('DEBUG_INFORMATION_FORMAT')){ + podFile += "\npost_install do |installer|\n" + + " installer.pods_project.targets.each do |target|\n" + + " target.build_configurations.each do |config|\n" + + " config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'\n" + + " end\n" + + " end\n" + + "end"; + fs.writeFileSync(path.resolve(podFilePath), podFile); + console.log('cordova-plugin-firebasex: Applied IOS_STRIP_DEBUG to Podfile'); + } + }, + applyPluginVarsToPlists: function(googlePlistPath, appPlistPath, pluginVariables){ + var googlePlist = plist.parse(fs.readFileSync(path.resolve(googlePlistPath), 'utf8')), + appPlist = plist.parse(fs.readFileSync(path.resolve(appPlistPath), 'utf8')), + googlePlistModified = false, + appPlistModified = false; + + if(typeof pluginVariables['FIREBASE_ANALYTICS_COLLECTION_ENABLED'] !== 'undefined'){ + googlePlist["FIREBASE_ANALYTICS_COLLECTION_ENABLED"] = (pluginVariables['FIREBASE_ANALYTICS_COLLECTION_ENABLED'] !== "false" ? "true" : "false") ; + googlePlistModified = true; + } + if(typeof pluginVariables['FIREBASE_PERFORMANCE_COLLECTION_ENABLED'] !== 'undefined'){ + googlePlist["FIREBASE_PERFORMANCE_COLLECTION_ENABLED"] = (pluginVariables['FIREBASE_PERFORMANCE_COLLECTION_ENABLED'] !== "false" ? "true" : "false") ; + googlePlistModified = true; + } + if(typeof pluginVariables['FIREBASE_CRASHLYTICS_COLLECTION_ENABLED'] !== 'undefined'){ + googlePlist["FirebaseCrashlyticsCollectionEnabled"] = (pluginVariables['FIREBASE_CRASHLYTICS_COLLECTION_ENABLED'] !== "false" ? "true" : "false") ; + googlePlistModified = true; + } + if(typeof pluginVariables['IOS_SHOULD_ESTABLISH_DIRECT_CHANNEL'] !== 'undefined'){ + appPlist["shouldEstablishDirectChannel"] = (pluginVariables['IOS_SHOULD_ESTABLISH_DIRECT_CHANNEL'] === "true") ; + appPlistModified = true; + } + if(pluginVariables['SETUP_RECAPTCHA_VERIFICATION'] === 'true'){ + var reversedClientId = googlePlist['REVERSED_CLIENT_ID']; + + if(!appPlist['CFBundleURLTypes']) appPlist['CFBundleURLTypes'] = []; + var entry, i; + for(i=0; i<appPlist['CFBundleURLTypes'].length; i++){ + if(typeof appPlist['CFBundleURLTypes'][i] === 'object' && appPlist['CFBundleURLTypes'][i]['CFBundleURLSchemes']){ + entry = appPlist['CFBundleURLTypes'][i]; + break; + } + } + if(!entry) entry = {}; + if(!entry['CFBundleTypeRole']) entry['CFBundleTypeRole'] = 'Editor'; + if(!entry['CFBundleURLSchemes']) entry['CFBundleURLSchemes'] = []; + if(entry['CFBundleURLSchemes'].indexOf(reversedClientId) === -1){ + entry['CFBundleURLSchemes'].push(reversedClientId) + } + appPlist['CFBundleURLTypes'][i] = entry; + appPlistModified = true; + } + + if(googlePlistModified) fs.writeFileSync(path.resolve(googlePlistPath), plist.build(googlePlist)); + if(appPlistModified) fs.writeFileSync(path.resolve(appPlistPath), plist.build(appPlist)); + } +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/lib/utilities.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/lib/utilities.js new file mode 100644 index 00000000..837ff459 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/lib/utilities.js @@ -0,0 +1,109 @@ +/** + * Utilities and shared functionality for the build hooks. + */ +var fs = require('fs'); +var path = require("path"); +var parser = require('xml-js'); + +var _configXml, _pluginXml; + +var Utilities = {}; + +fs.ensureDirSync = function(dir){ + if(!fs.existsSync(dir)){ + dir.split(path.sep).reduce(function(currentPath, folder){ + currentPath += folder + path.sep; + if(!fs.existsSync(currentPath)){ + fs.mkdirSync(currentPath); + } + return currentPath; + }, ''); + } +}; + +Utilities.parsePackageJson = function(){ + return JSON.parse(fs.readFileSync(path.resolve('./package.json'))); +}; + +Utilities.parseConfigXml = function(){ + if(_configXml) return _configXml; + _configXml = Utilities.parseXmlFileToJson("config.xml"); + return _configXml; +}; + +Utilities.parsePluginXml = function(){ + if(_pluginXml) return _pluginXml; + _pluginXml = Utilities.parseXmlFileToJson("plugins/"+Utilities.getPluginId()+"/plugin.xml"); + return _pluginXml; +}; + +Utilities.parseXmlFileToJson = function(filepath, parseOpts){ + parseOpts = parseOpts || {compact: true}; + return JSON.parse(parser.xml2json(fs.readFileSync(path.resolve(filepath), 'utf-8'), parseOpts)); +}; + +Utilities.writeJsonToXmlFile = function(jsonObj, filepath, parseOpts){ + parseOpts = parseOpts || {compact: true, spaces: 4}; + var xmlStr = parser.json2xml(JSON.stringify(jsonObj), parseOpts); + fs.writeFileSync(path.resolve(filepath), xmlStr); +}; + +/** + * Used to get the name of the application as defined in the config.xml. + */ +Utilities.getAppName = function(){ + return Utilities.parseConfigXml().widget.name._text.toString().trim(); +}; + +/** + * The ID of the plugin; this should match the ID in plugin.xml. + */ +Utilities.getPluginId = function(){ + return "cordova-plugin-firebasex"; +}; + +Utilities.copyKey = function(platform){ + for(var i = 0; i < platform.src.length; i++){ + var file = platform.src[i]; + if(this.fileExists(file)){ + try{ + var contents = fs.readFileSync(path.resolve(file)).toString(); + + try{ + var destinationPath = platform.dest; + var folder = destinationPath.substring(0, destinationPath.lastIndexOf('/')); + fs.ensureDirSync(folder); + fs.writeFileSync(path.resolve(destinationPath), contents); + }catch(e){ + // skip + } + }catch(err){ + console.log(err); + } + + break; + } + } +}; + +Utilities.fileExists = function(filePath){ + try{ + return fs.statSync(path.resolve(filePath)).isFile(); + }catch(e){ + return false; + } +}; + +Utilities.directoryExists = function(dirPath){ + try{ + return fs.statSync(path.resolve(dirPath)).isDirectory(); + }catch(e){ + return false; + } +}; + +Utilities.log = function(msg){ + console.log(Utilities.getPluginId()+': '+msg); +}; + +module.exports = Utilities; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePlugin.java b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePlugin.java new file mode 100644 index 00000000..d81419e9 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePlugin.java @@ -0,0 +1,2441 @@ +package org.apache.cordova.firebase; + +import android.app.Activity; +import android.app.NotificationManager; +import android.app.NotificationChannel; +import android.content.ContentResolver; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.media.RingtoneManager; +import android.net.Uri; +import android.media.AudioAttributes; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; + +import android.util.Base64; +import android.util.Log; + +import com.google.firebase.crashlytics.FirebaseCrashlytics; + +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.signin.GoogleSignIn; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInClient; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.FirebaseApp; +import com.google.firebase.analytics.FirebaseAnalytics; +import com.google.firebase.auth.AuthCredential; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; +import com.google.firebase.auth.GetTokenResult; +import com.google.firebase.auth.GoogleAuthProvider; +import com.google.firebase.auth.OAuthProvider; +import com.google.firebase.auth.UserProfileChangeRequest; +import com.google.firebase.firestore.CollectionReference; +import com.google.firebase.firestore.DocumentReference; +import com.google.firebase.firestore.DocumentSnapshot; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Query; +import com.google.firebase.firestore.QueryDocumentSnapshot; +import com.google.firebase.firestore.QuerySnapshot; +import com.google.firebase.firestore.Query.Direction; +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.remoteconfig.FirebaseRemoteConfig; +import com.google.firebase.remoteconfig.FirebaseRemoteConfigInfo; +import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings; +import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue; +import com.google.firebase.perf.FirebasePerformance; +import com.google.firebase.perf.metrics.Trace; + + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.PluginResult; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Random; +import java.util.Set; +import java.util.List; + +// Firebase PhoneAuth +import java.util.concurrent.TimeUnit; + +import com.google.firebase.FirebaseException; +import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException; +import com.google.firebase.FirebaseTooManyRequestsException; +import com.google.firebase.auth.PhoneAuthCredential; +import com.google.firebase.auth.PhoneAuthProvider; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import static android.content.Context.MODE_PRIVATE; + +public class FirebasePlugin extends CordovaPlugin { + + protected static FirebasePlugin instance = null; + private FirebaseAnalytics mFirebaseAnalytics; + private FirebaseCrashlytics firebaseCrashlytics; + private FirebaseFirestore firestore; + private Gson gson; + private FirebaseAuth.AuthStateListener authStateListener; + private boolean authStateChangeListenerInitialized = false; + private static CordovaInterface cordovaInterface = null; + protected static Context applicationContext = null; + private static Activity cordovaActivity = null; + + protected static final String TAG = "FirebasePlugin"; + protected static final String JS_GLOBAL_NAMESPACE = "FirebasePlugin."; + protected static final String KEY = "badge"; + protected static final int GOOGLE_SIGN_IN = 0x1; + protected static final String SETTINGS_NAME = "settings"; + private static final String CRASHLYTICS_COLLECTION_ENABLED = "firebase_crashlytics_collection_enabled"; + private static final String ANALYTICS_COLLECTION_ENABLED = "firebase_analytics_collection_enabled"; + private static final String PERFORMANCE_COLLECTION_ENABLED = "firebase_performance_collection_enabled"; + + private static boolean inBackground = true; + private static ArrayList<Bundle> notificationStack = null; + private static CallbackContext notificationCallbackContext; + private static CallbackContext tokenRefreshCallbackContext; + private static CallbackContext activityResultCallbackContext; + private static CallbackContext authResultCallbackContext; + + private static NotificationChannel defaultNotificationChannel = null; + public static String defaultChannelId = null; + public static String defaultChannelName = null; + + private Map<String, AuthCredential> authCredentials = new HashMap<String, AuthCredential>(); + private Map<String, OAuthProvider> authProviders = new HashMap<String, OAuthProvider>(); + + @Override + protected void pluginInitialize() { + instance = this; + cordovaActivity = this.cordova.getActivity(); + applicationContext = cordovaActivity.getApplicationContext(); + final Bundle extras = cordovaActivity.getIntent().getExtras(); + FirebasePlugin.cordovaInterface = this.cordova; + firebaseCrashlytics = FirebaseCrashlytics.getInstance(); + this.cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + Log.d(TAG, "Starting Firebase plugin"); + + if(getMetaDataFromManifest(CRASHLYTICS_COLLECTION_ENABLED)){ + setPreference(CRASHLYTICS_COLLECTION_ENABLED, true); + } + + if(getMetaDataFromManifest(ANALYTICS_COLLECTION_ENABLED)){ + setPreference(ANALYTICS_COLLECTION_ENABLED, true); + } + + if(getMetaDataFromManifest(PERFORMANCE_COLLECTION_ENABLED)){ + setPreference(PERFORMANCE_COLLECTION_ENABLED, true); + } + + FirebaseApp.initializeApp(applicationContext); + mFirebaseAnalytics = FirebaseAnalytics.getInstance(applicationContext); + + authStateListener = new AuthStateListener(); + FirebaseAuth.getInstance().addAuthStateListener(authStateListener); + + firestore = FirebaseFirestore.getInstance(); + gson = new Gson(); + + if (extras != null && extras.size() > 1) { + if (FirebasePlugin.notificationStack == null) { + FirebasePlugin.notificationStack = new ArrayList<Bundle>(); + } + if (extras.containsKey("google.message_id")) { + extras.putString("messageType", "notification"); + extras.putString("tap", "background"); + notificationStack.add(extras); + Log.d(TAG, "Notification message found on init: " + extras.toString()); + } + } + defaultChannelId = getStringResource("default_notification_channel_id"); + defaultChannelName = getStringResource("default_notification_channel_name"); + createDefaultChannel(); + }catch (Exception e){ + handleExceptionWithoutContext(e); + } + } + }); + } + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + try{ + if (action.equals("getId")) { + this.getId(callbackContext); + return true; + } else if (action.equals("getToken")) { + this.getToken(callbackContext); + return true; + } else if (action.equals("hasPermission")) { + this.hasPermission(callbackContext); + return true; + }else if (action.equals("subscribe")) { + this.subscribe(callbackContext, args.getString(0)); + return true; + } else if (action.equals("unsubscribe")) { + this.unsubscribe(callbackContext, args.getString(0)); + return true; + } else if (action.equals("isAutoInitEnabled")) { + isAutoInitEnabled(callbackContext); + return true; + } else if (action.equals("setAutoInitEnabled")) { + setAutoInitEnabled(callbackContext, args.getBoolean(0)); + return true; + } else if (action.equals("unregister")) { + this.unregister(callbackContext); + return true; + } else if (action.equals("onMessageReceived")) { + this.onMessageReceived(callbackContext); + return true; + } else if (action.equals("onTokenRefresh")) { + this.onTokenRefresh(callbackContext); + return true; + } else if (action.equals("logEvent")) { + this.logEvent(callbackContext, args.getString(0), args.getJSONObject(1)); + return true; + } else if (action.equals("logError")) { + this.logError(callbackContext, args); + return true; + }else if(action.equals("setCrashlyticsUserId")){ + this.setCrashlyticsUserId(callbackContext, args.getString(0)); + return true; + } else if (action.equals("setScreenName")) { + this.setScreenName(callbackContext, args.getString(0)); + return true; + } else if (action.equals("setUserId")) { + this.setUserId(callbackContext, args.getString(0)); + return true; + } else if (action.equals("setUserProperty")) { + this.setUserProperty(callbackContext, args.getString(0), args.getString(1)); + return true; + } else if (action.equals("activateFetched")) { + this.activateFetched(callbackContext); + return true; + } else if (action.equals("fetch")) { + if (args.length() > 0) { + this.fetch(callbackContext, args.getLong(0)); + } else { + this.fetch(callbackContext); + } + return true; + } else if (action.equals("getByteArray")) { + this.getByteArray(callbackContext, args.getString(0)); + return true; + } else if (action.equals("getValue")) { + this.getValue(callbackContext, args.getString(0)); + return true; + } else if (action.equals("getInfo")) { + this.getInfo(callbackContext); + return true; + } else if (action.equals("setConfigSettings")) { + this.setConfigSettings(callbackContext, args.getJSONObject(0)); + return true; + } else if (action.equals("setDefaults")) { + this.setDefaults(callbackContext, args.getJSONObject(0)); + return true; + } else if (action.equals("verifyPhoneNumber")) { + this.verifyPhoneNumber(callbackContext, args); + return true; + } else if (action.equals("authenticateUserWithGoogle")) { + this.authenticateUserWithGoogle(callbackContext, args); + return true; + } else if (action.equals("authenticateUserWithApple")) { + this.authenticateUserWithApple(callbackContext, args); + return true; + } else if (action.equals("createUserWithEmailAndPassword")) { + this.createUserWithEmailAndPassword(callbackContext, args); + return true; + } else if (action.equals("signInUserWithEmailAndPassword")) { + this.signInUserWithEmailAndPassword(callbackContext, args); + return true; + } else if (action.equals("signInUserWithCustomToken")) { + this.signInUserWithCustomToken(callbackContext, args); + return true; + } else if (action.equals("signInUserAnonymously")) { + this.signInUserAnonymously(callbackContext); + return true; + } else if (action.equals("signInWithCredential")) { + this.signInWithCredential(callbackContext, args); + return true; + } else if (action.equals("linkUserWithCredential")) { + this.linkUserWithCredential(callbackContext, args); + return true; + } else if (action.equals("reauthenticateWithCredential")) { + this.reauthenticateWithCredential(callbackContext, args); + return true; + } else if (action.equals("isUserSignedIn")) { + this.isUserSignedIn(callbackContext, args); + return true; + } else if (action.equals("signOutUser")) { + this.signOutUser(callbackContext, args); + return true; + } else if (action.equals("getCurrentUser")) { + this.getCurrentUser(callbackContext, args); + return true; + } else if (action.equals("reloadCurrentUser")) { + this.reloadCurrentUser(callbackContext, args); + return true; + } else if (action.equals("updateUserProfile")) { + this.updateUserProfile(callbackContext, args); + return true; + } else if (action.equals("updateUserEmail")) { + this.updateUserEmail(callbackContext, args); + return true; + } else if (action.equals("sendUserEmailVerification")) { + this.sendUserEmailVerification(callbackContext, args); + return true; + } else if (action.equals("updateUserPassword")) { + this.updateUserPassword(callbackContext, args); + return true; + } else if (action.equals("sendUserPasswordResetEmail")) { + this.sendUserPasswordResetEmail(callbackContext, args); + return true; + } else if (action.equals("deleteUser")) { + this.deleteUser(callbackContext, args); + return true; + } else if (action.equals("startTrace")) { + this.startTrace(callbackContext, args.getString(0)); + return true; + } else if (action.equals("incrementCounter")) { + this.incrementCounter(callbackContext, args.getString(0), args.getString(1)); + return true; + } else if (action.equals("stopTrace")) { + this.stopTrace(callbackContext, args.getString(0)); + return true; + } else if (action.equals("setAnalyticsCollectionEnabled")) { + this.setAnalyticsCollectionEnabled(callbackContext, args.getBoolean(0)); + return true; + } else if (action.equals("isAnalyticsCollectionEnabled")) { + this.isAnalyticsCollectionEnabled(callbackContext); + return true; + } else if (action.equals("setPerformanceCollectionEnabled")) { + this.setPerformanceCollectionEnabled(callbackContext, args.getBoolean(0)); + return true; + } else if (action.equals("isPerformanceCollectionEnabled")) { + this.isPerformanceCollectionEnabled(callbackContext); + return true; + } else if (action.equals("setCrashlyticsCollectionEnabled")) { + this.setCrashlyticsCollectionEnabled(callbackContext, args.getBoolean(0)); + return true; + } else if (action.equals("isCrashlyticsCollectionEnabled")) { + this.isCrashlyticsCollectionEnabled(callbackContext); + return true; + } else if (action.equals("clearAllNotifications")) { + this.clearAllNotifications(callbackContext); + return true; + } else if (action.equals("logMessage")) { + logMessage(args, callbackContext); + return true; + } else if (action.equals("sendCrash")) { + sendCrash(args, callbackContext); + return true; + } else if (action.equals("createChannel")) { + this.createChannel(callbackContext, args.getJSONObject(0)); + return true; + } else if (action.equals("deleteChannel")) { + this.deleteChannel(callbackContext, args.getString(0)); + return true; + } else if (action.equals("listChannels")) { + this.listChannels(callbackContext); + return true; + } else if (action.equals("setDefaultChannel")) { + this.setDefaultChannel(callbackContext, args.getJSONObject(0)); + return true; + } else if (action.equals("addDocumentToFirestoreCollection")) { + this.addDocumentToFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("setDocumentInFirestoreCollection")) { + this.setDocumentInFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("updateDocumentInFirestoreCollection")) { + this.updateDocumentInFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("deleteDocumentFromFirestoreCollection")) { + this.deleteDocumentFromFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("documentExistsInFirestoreCollection")) { + this.documentExistsInFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("fetchDocumentInFirestoreCollection")) { + this.fetchDocumentInFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("fetchFirestoreCollection")) { + this.fetchFirestoreCollection(args, callbackContext); + return true; + } else if (action.equals("grantPermission") + || action.equals("setBadgeNumber") + || action.equals("getBadgeNumber") + ) { + // Stubs for other platform methods + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, true)); + return true; + }else{ + callbackContext.error("Invalid action: " + action); + return false; + } + }catch(Exception e){ + handleExceptionWithContext(e, callbackContext); + } + return false; + } + + @Override + public void onPause(boolean multitasking) { + FirebasePlugin.inBackground = true; + } + + @Override + public void onResume(boolean multitasking) { + FirebasePlugin.inBackground = false; + } + + @Override + public void onReset() { + FirebasePlugin.notificationCallbackContext = null; + FirebasePlugin.tokenRefreshCallbackContext = null; + FirebasePlugin.activityResultCallbackContext = null; + FirebasePlugin.authResultCallbackContext = null; + } + + @Override + public void onDestroy() { + FirebaseAuth.getInstance().removeAuthStateListener(authStateListener); + instance = null; + cordovaActivity = null; + cordovaInterface = null; + applicationContext = null; + super.onDestroy(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + try { + switch (requestCode) { + case GOOGLE_SIGN_IN: + Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); + GoogleSignInAccount acct; + try{ + acct = task.getResult(ApiException.class); + }catch (ApiException ae){ + if(ae.getStatusCode() == 10){ + throw new Exception("Unknown server client ID"); + }else{ + throw new Exception(CommonStatusCodes.getStatusCodeString(ae.getStatusCode())); + } + } + AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null); + String id = FirebasePlugin.instance.saveAuthCredential(credential); + + JSONObject returnResults = new JSONObject(); + returnResults.put("instantVerification", true); + returnResults.put("id", id); + FirebasePlugin.activityResultCallbackContext.success(returnResults); + break; + } + } catch (Exception e) { + handleExceptionWithContext(e, FirebasePlugin.activityResultCallbackContext); + } + } + + /** + * Get a string from resources without importing the .R package + * + * @param name Resource Name + * @return Resource + */ + private String getStringResource(String name) { + return applicationContext.getString( + applicationContext.getResources().getIdentifier( + name, "string", applicationContext.getPackageName() + ) + ); + } + + private void onMessageReceived(final CallbackContext callbackContext) { + FirebasePlugin.notificationCallbackContext = callbackContext; + if (FirebasePlugin.notificationStack != null) { + for (Bundle bundle : FirebasePlugin.notificationStack) { + FirebasePlugin.sendMessage(bundle, applicationContext); + } + FirebasePlugin.notificationStack.clear(); + } + } + + private void onTokenRefresh(final CallbackContext callbackContext) { + FirebasePlugin.tokenRefreshCallbackContext = callbackContext; + + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String currentToken = FirebaseInstanceId.getInstance().getToken(); + if (currentToken != null) { + FirebasePlugin.sendToken(currentToken); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public static void sendMessage(Bundle bundle, Context context) { + if (!FirebasePlugin.hasNotificationsCallback()) { + String packageName = context.getPackageName(); + if (FirebasePlugin.notificationStack == null) { + FirebasePlugin.notificationStack = new ArrayList<Bundle>(); + } + notificationStack.add(bundle); + + return; + } + + final CallbackContext callbackContext = FirebasePlugin.notificationCallbackContext; + if(bundle != null){ + // Pass the message bundle to the receiver manager so any registered receivers can decide to handle it + boolean wasHandled = FirebasePluginMessageReceiverManager.sendMessage(bundle); + if (wasHandled) { + Log.d(TAG, "Message bundle was handled by a registered receiver"); + }else if (callbackContext != null) { + JSONObject json = new JSONObject(); + Set<String> keys = bundle.keySet(); + for (String key : keys) { + try { + json.put(key, bundle.get(key)); + } catch (JSONException e) { + handleExceptionWithContext(e, callbackContext); + return; + } + } + + PluginResult pluginresult = new PluginResult(PluginResult.Status.OK, json); + pluginresult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginresult); + } + } + } + + public static void sendToken(String token) { + if (FirebasePlugin.tokenRefreshCallbackContext == null) { + return; + } + + final CallbackContext callbackContext = FirebasePlugin.tokenRefreshCallbackContext; + if (callbackContext != null && token != null) { + PluginResult pluginresult = new PluginResult(PluginResult.Status.OK, token); + pluginresult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginresult); + } + } + + public static boolean inBackground() { + return FirebasePlugin.inBackground; + } + + public static boolean hasNotificationsCallback() { + return FirebasePlugin.notificationCallbackContext != null; + } + + @Override + public void onNewIntent(Intent intent) { + try { + super.onNewIntent(intent); + final Bundle data = intent.getExtras(); + if (data != null && data.containsKey("google.message_id")) { + data.putString("messageType", "notification"); + data.putString("tap", "background"); + Log.d(TAG, "Notification message on new intent: " + data.toString()); + FirebasePlugin.sendMessage(data, applicationContext); + } + }catch (Exception e){ + handleExceptionWithoutContext(e); + } + } + + + private void getId(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String id = FirebaseInstanceId.getInstance().getId(); + callbackContext.success(id); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void getToken(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String token = FirebaseInstanceId.getInstance().getToken(); + callbackContext.success(token); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void hasPermission(final CallbackContext callbackContext) { + if(cordovaActivity == null) return; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(cordovaActivity); + boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled(); + callbackContext.success(areNotificationsEnabled ? 1 : 0); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void subscribe(final CallbackContext callbackContext, final String topic) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + handleTaskOutcome(FirebaseMessaging.getInstance().subscribeToTopic(topic), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void unsubscribe(final CallbackContext callbackContext, final String topic) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + handleTaskOutcome(FirebaseMessaging.getInstance().unsubscribeFromTopic(topic), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void unregister(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseInstanceId.getInstance().deleteInstanceId(); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void isAutoInitEnabled(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + boolean isEnabled = FirebaseMessaging.getInstance().isAutoInitEnabled(); + callbackContext.success(isEnabled ? 1 : 0); + } catch (Exception e) { + logExceptionToCrashlytics(e); + callbackContext.error(e.getMessage()); + } + } + }); + } + + private void setAutoInitEnabled(final CallbackContext callbackContext, final boolean enabled) { + final FirebasePlugin self = this; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseMessaging.getInstance().setAutoInitEnabled(enabled); + callbackContext.success(); + } catch (Exception e) { + logExceptionToCrashlytics(e); + e.printStackTrace(); + callbackContext.error(e.getMessage()); + } + } + }); + } + + private void logEvent(final CallbackContext callbackContext, final String name, final JSONObject params) + throws JSONException { + final Bundle bundle = new Bundle(); + Iterator iter = params.keys(); + while (iter.hasNext()) { + String key = (String) iter.next(); + Object value = params.get(key); + + if (value instanceof Integer || value instanceof Double) { + bundle.putFloat(key, ((Number) value).floatValue()); + } else { + bundle.putString(key, value.toString()); + } + } + + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + mFirebaseAnalytics.logEvent(name, bundle); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void logError(final CallbackContext callbackContext, final JSONArray args) throws JSONException { + final String message = args.getString(0); + + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + if(isCrashlyticsEnabled()) { + // We can optionally be passed a stack trace generated by stacktrace.js. + if (args.length() == 2) { + JSONArray stackTrace = args.getJSONArray(1); + StackTraceElement[] trace = new StackTraceElement[stackTrace.length()]; + for (int i = 0; i < stackTrace.length(); i++) { + JSONObject elem = stackTrace.getJSONObject(i); + trace[i] = new StackTraceElement( + "", + elem.optString("functionName", "(anonymous function)"), + elem.optString("fileName", "(unknown file)"), + elem.optInt("lineNumber", -1) + ); + } + + Exception e = new JavaScriptException(message); + e.setStackTrace(trace); + logExceptionToCrashlytics(e); + } else { + logExceptionToCrashlytics(new JavaScriptException(message)); + } + + Log.e(TAG, message); + callbackContext.success(1); + }else{ + callbackContext.error("Cannot log error - Crashlytics collection is disabled"); + } + } catch (Exception e) { + logExceptionToCrashlytics(e); + callbackContext.error(e.getMessage()); + } + } + }); + } + + private void logMessage(final JSONArray data, + final CallbackContext callbackContext) { + + if(isCrashlyticsEnabled()){ + String message = data.optString(0); + logMessageToCrashlytics(message); + callbackContext.success(); + }else{ + callbackContext.error("Cannot log message - Crashlytics collection is disabled"); + } + } + + private void sendCrash(final JSONArray data, + final CallbackContext callbackContext) { + + cordovaActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + throw new RuntimeException("This is a crash"); + } + }); + } + + + private void setCrashlyticsUserId(final CallbackContext callbackContext, final String userId) { + cordovaActivity.runOnUiThread(new Runnable() { + public void run() { + try { + if(isCrashlyticsEnabled()){ + firebaseCrashlytics.setUserId(userId); + callbackContext.success(); + }else{ + callbackContext.error("Cannot set Crashlytics user ID - Crashlytics collection is disabled"); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void setScreenName(final CallbackContext callbackContext, final String name) { + // This must be called on the main thread + cordovaActivity.runOnUiThread(new Runnable() { + public void run() { + try { + mFirebaseAnalytics.setCurrentScreen(cordovaActivity, name, null); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void setUserId(final CallbackContext callbackContext, final String id) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + mFirebaseAnalytics.setUserId(id); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void setUserProperty(final CallbackContext callbackContext, final String name, final String value) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + mFirebaseAnalytics.setUserProperty(name, value); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void activateFetched(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + final boolean activated = FirebaseRemoteConfig.getInstance().activateFetched(); + callbackContext.success(String.valueOf(activated)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void fetch(CallbackContext callbackContext) { + fetch(callbackContext, FirebaseRemoteConfig.getInstance().fetch()); + } + + private void fetch(CallbackContext callbackContext, long cacheExpirationSeconds) { + fetch(callbackContext, FirebaseRemoteConfig.getInstance().fetch(cacheExpirationSeconds)); + } + + private void fetch(final CallbackContext callbackContext, final Task<Void> task) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + handleTaskOutcome(task, callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void getByteArray(final CallbackContext callbackContext, final String key) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + byte[] bytes = FirebaseRemoteConfig.getInstance().getByteArray(key); + JSONObject object = new JSONObject(); + object.put("base64", Base64.encodeToString(bytes, Base64.DEFAULT)); + object.put("array", new JSONArray(bytes)); + callbackContext.success(object); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void getValue(final CallbackContext callbackContext, final String key) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseRemoteConfigValue value = FirebaseRemoteConfig.getInstance().getValue(key); + callbackContext.success(value.asString()); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void getInfo(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseRemoteConfigInfo remoteConfigInfo = FirebaseRemoteConfig.getInstance().getInfo(); + JSONObject info = new JSONObject(); + + JSONObject settings = new JSONObject(); + settings.put("developerModeEnabled", remoteConfigInfo.getConfigSettings().isDeveloperModeEnabled()); + info.put("configSettings", settings); + + info.put("fetchTimeMillis", remoteConfigInfo.getFetchTimeMillis()); + info.put("lastFetchStatus", remoteConfigInfo.getLastFetchStatus()); + + callbackContext.success(info); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void setConfigSettings(final CallbackContext callbackContext, final JSONObject config) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + boolean devMode = config.getBoolean("developerModeEnabled"); + FirebaseRemoteConfigSettings.Builder settings = new FirebaseRemoteConfigSettings.Builder() + .setDeveloperModeEnabled(devMode); + FirebaseRemoteConfig.getInstance().setConfigSettings(settings.build()); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void setDefaults(final CallbackContext callbackContext, final JSONObject defaults) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseRemoteConfig.getInstance().setDefaults(defaultsToMap(defaults)); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private static Map<String, Object> defaultsToMap(JSONObject object) throws JSONException { + final Map<String, Object> map = new HashMap<String, Object>(); + + for (Iterator<String> keys = object.keys(); keys.hasNext(); ) { + String key = keys.next(); + Object value = object.get(key); + + if (value instanceof Integer) { + //setDefaults() should take Longs + value = new Long((Integer) value); + } else if (value instanceof JSONArray) { + JSONArray array = (JSONArray) value; + if (array.length() == 1 && array.get(0) instanceof String) { + //parse byte[] as Base64 String + value = Base64.decode(array.getString(0), Base64.DEFAULT); + } else { + //parse byte[] as numeric array + byte[] bytes = new byte[array.length()]; + for (int i = 0; i < array.length(); i++) + bytes[i] = (byte) array.getInt(i); + value = bytes; + } + } + + map.put(key, value); + } + return map; + } + + + public void isUserSignedIn(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + boolean isSignedIn = FirebaseAuth.getInstance().getCurrentUser() != null; + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, isSignedIn)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void signOutUser(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + // Sign out of Firebase + FirebaseAuth.getInstance().signOut(); + + // Try to sign out of Google + try{ + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build(); + GoogleSignInClient mGoogleSignInClient = GoogleSignIn.getClient(cordovaActivity, gso); + handleTaskOutcome(mGoogleSignInClient.signOut(), callbackContext); + }catch(Exception googleSignOutException){ + callbackContext.success(); + } + + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void getCurrentUser(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + extractAndReturnUserInfo(callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void reloadCurrentUser(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + user.reload() + .addOnSuccessListener(new OnSuccessListener<Void>() { + @Override + public void onSuccess(Void aVoid) { + try { + extractAndReturnUserInfo(callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void extractAndReturnUserInfo(final CallbackContext callbackContext) throws Exception{ + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + JSONObject returnResults = new JSONObject(); + returnResults.put("name", user.getDisplayName()); + returnResults.put("email", user.getEmail()); + returnResults.put("emailIsVerified", user.isEmailVerified()); + returnResults.put("phoneNumber", user.getPhoneNumber()); + returnResults.put("photoUrl", user.getPhotoUrl() == null ? null : user.getPhotoUrl().toString()); + returnResults.put("uid", user.getUid()); + returnResults.put("providerId", user.getIdToken(false).getResult().getSignInProvider()); + returnResults.put("isAnonymous", user.isAnonymous()); + + user.getIdToken(true).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() { + @Override + public void onSuccess(GetTokenResult result) { + try { + String idToken = result.getToken(); + returnResults.put("idToken", idToken); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, returnResults)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void updateUserProfile(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + + JSONObject profile = args.getJSONObject(0); + UserProfileChangeRequest profileUpdates; + if(profile.has("name") && profile.has("photoUri")){ + profileUpdates = new UserProfileChangeRequest.Builder() + .setDisplayName(profile.getString("name")) + .setPhotoUri(Uri.parse(profile.getString("photoUri"))) + .build(); + }else if(profile.has("name")){ + profileUpdates = new UserProfileChangeRequest.Builder() + .setDisplayName(profile.getString("name")) + .build(); + }else if(profile.has("photoUri")){ + profileUpdates = new UserProfileChangeRequest.Builder() + .setPhotoUri(Uri.parse(profile.getString("photoUri"))) + .build(); + }else{ + callbackContext.error("'name' and/or 'photoUri' keys must be specified in the profile object"); + return; + } + + handleTaskOutcome(user.updateProfile(profileUpdates), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void updateUserEmail(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + + String email = args.getString(0); + handleTaskOutcome(user.updateEmail(email), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void sendUserEmailVerification(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + + handleTaskOutcome(user.sendEmailVerification(), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void updateUserPassword(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + + String password = args.getString(0); + handleTaskOutcome(user.updatePassword(password), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void sendUserPasswordResetEmail(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseAuth auth = FirebaseAuth.getInstance(); + String email = args.getString(0); + handleTaskOutcome(auth.sendPasswordResetEmail(email), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void deleteUser(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + handleTaskOutcome(user.delete(), callbackContext); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void reauthenticateWithCredential(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser(); + if(user == null){ + callbackContext.error("No user is currently signed"); + return; + } + + JSONObject jsonCredential = args.getJSONObject(0); + if(!FirebasePlugin.instance.isValidJsonCredential(jsonCredential)){ + callbackContext.error("No auth credentials specified"); + return; + } + + AuthCredential authCredential = FirebasePlugin.instance.obtainAuthCredential(jsonCredential); + if(authCredential != null){ + handleTaskOutcome(user.reauthenticate(authCredential), callbackContext); + return; + } + + OAuthProvider authProvider = FirebasePlugin.instance.obtainAuthProvider(jsonCredential); + if(authProvider != null){ + FirebasePlugin.instance.authResultCallbackContext = callbackContext; + user.startActivityForReauthenticateWithProvider(FirebasePlugin.cordovaActivity, authProvider) + .addOnSuccessListener(new AuthResultOnSuccessListener()) + .addOnFailureListener(new AuthResultOnFailureListener()); + return; + } + + //ELSE + callbackContext.error("Specified native auth credential id does not exist"); + + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + + + public void signInWithCredential(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + JSONObject jsonCredential = args.getJSONObject(0); + if(!FirebasePlugin.instance.isValidJsonCredential(jsonCredential)){ + callbackContext.error("No auth credentials specified"); + return; + } + + AuthCredential authCredential = FirebasePlugin.instance.obtainAuthCredential(jsonCredential); + if(authCredential != null){ + FirebaseAuth.getInstance().signInWithCredential(authCredential).addOnCompleteListener(cordova.getActivity(), new AuthResultOnCompleteListener(callbackContext)); + return; + } + + OAuthProvider authProvider = FirebasePlugin.instance.obtainAuthProvider(jsonCredential); + if(authProvider != null){ + FirebasePlugin.instance.authResultCallbackContext = callbackContext; + FirebaseAuth.getInstance().startActivityForSignInWithProvider(FirebasePlugin.cordovaActivity, authProvider) + .addOnSuccessListener(new AuthResultOnSuccessListener()) + .addOnFailureListener(new AuthResultOnFailureListener()); + return; + } + + //ELSE + callbackContext.error("Specified native auth credential id does not exist"); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void linkUserWithCredential(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + JSONObject jsonCredential = args.getJSONObject(0); + if(!FirebasePlugin.instance.isValidJsonCredential(jsonCredential)){ + callbackContext.error("No auth credentials specified"); + return; + } + + AuthCredential authCredential = FirebasePlugin.instance.obtainAuthCredential(jsonCredential); + if(authCredential != null){ + FirebaseAuth.getInstance().getCurrentUser().linkWithCredential(authCredential).addOnCompleteListener(cordova.getActivity(), new AuthResultOnCompleteListener(callbackContext)); + return; + } + + //ELSE + callbackContext.error("Specified native auth credential id does not exist"); + + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private boolean isValidJsonCredential(JSONObject jsonCredential) throws JSONException{ + return jsonCredential.has("id") || (jsonCredential.has("verificationId") && jsonCredential.has("code")); + } + + private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks; + + public void verifyPhoneNumber( + final CallbackContext callbackContext, + final JSONArray args + ) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() { + @Override + public void onVerificationCompleted(PhoneAuthCredential credential) { + // This callback will be invoked in two situations: + // 1 - Instant verification. In some cases the phone number can be instantly + // verified without needing to send or enter a verification code. + // 2 - Auto-retrieval. On some devices Google Play services can automatically + // detect the incoming verification SMS and perform verificaiton without + // user action. + Log.d(TAG, "success: verifyPhoneNumber.onVerificationCompleted"); + + String id = FirebasePlugin.instance.saveAuthCredential((AuthCredential) credential); + + JSONObject returnResults = new JSONObject(); + try { + returnResults.put("instantVerification", true); + returnResults.put("id", id); + } catch(JSONException e){ + handleExceptionWithContext(e, callbackContext); + return; + } + PluginResult pluginresult = new PluginResult(PluginResult.Status.OK, returnResults); + pluginresult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginresult); + } + + @Override + public void onVerificationFailed(FirebaseException e) { + // This callback is invoked in an invalid request for verification is made, + // for instance if the the phone number format is not valid. + Log.w(TAG, "failed: verifyPhoneNumber.onVerificationFailed ", e); + + String errorMsg; + if (e instanceof FirebaseAuthInvalidCredentialsException) { + // Invalid request + errorMsg = "Invalid phone number"; + } else if (e instanceof FirebaseTooManyRequestsException) { + // The SMS quota for the project has been exceeded + errorMsg = "The SMS quota for the project has been exceeded"; + }else{ + errorMsg = e.getMessage(); + } + callbackContext.error(errorMsg); + } + + @Override + public void onCodeSent(String verificationId, PhoneAuthProvider.ForceResendingToken token) { + // The SMS verification code has been sent to the provided phone number, we + // now need to ask the user to enter the code and then construct a credential + // by combining the code with a verification ID [(in app)]. + Log.d(TAG, "success: verifyPhoneNumber.onCodeSent"); + + JSONObject returnResults = new JSONObject(); + try { + returnResults.put("verificationId", verificationId); + returnResults.put("instantVerification", false); + } catch (JSONException e) { + handleExceptionWithContext(e, callbackContext); + return; + } + PluginResult pluginresult = new PluginResult(PluginResult.Status.OK, returnResults); + pluginresult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginresult); + } + }; + + String number = args.getString(0); + int timeOutDuration = args.getInt(1); + String smsCode = args.getString(2); + + if(smsCode != null && smsCode != "null"){ + FirebaseAuth.getInstance().getFirebaseAuthSettings().setAutoRetrievedSmsCodeForPhoneNumber(number, smsCode); + } + + PhoneAuthProvider.getInstance().verifyPhoneNumber(number, // Phone number to verify + timeOutDuration, // Timeout duration + TimeUnit.SECONDS, // Unit of timeout + cordovaActivity, // Activity (for callback binding) + mCallbacks); // OnVerificationStateChangedCallbacks + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void createUserWithEmailAndPassword(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String email = args.getString(0); + String password = args.getString(1); + + if(email == null || email.equals("")){ + callbackContext.error("User email address must be specified"); + return; + } + + if(password == null || password.equals("")){ + callbackContext.error("User password must be specified"); + return; + } + + FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password).addOnCompleteListener(cordova.getActivity(), new AuthResultOnCompleteListener(callbackContext)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void signInUserWithEmailAndPassword(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String email = args.getString(0); + String password = args.getString(1); + + if(email == null || email.equals("")){ + callbackContext.error("User email address must be specified"); + return; + } + + if(password == null || password.equals("")){ + callbackContext.error("User password must be specified"); + return; + } + + FirebaseAuth.getInstance().signInWithEmailAndPassword(email, password).addOnCompleteListener(cordova.getActivity(), new AuthResultOnCompleteListener(callbackContext)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + + public void authenticateUserWithGoogle(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String clientId = args.getString(0); + + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(clientId) + .requestEmail() + .build(); + + GoogleSignInClient mGoogleSignInClient = GoogleSignIn.getClient(FirebasePlugin.instance.cordovaActivity, gso); + Intent signInIntent = mGoogleSignInClient.getSignInIntent(); + FirebasePlugin.activityResultCallbackContext = callbackContext; + FirebasePlugin.instance.cordovaInterface.startActivityForResult(FirebasePlugin.instance, signInIntent, GOOGLE_SIGN_IN); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void authenticateUserWithApple(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String locale = args.getString(0); + OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com"); + if(locale != null){ + provider.addCustomParameter("locale", locale); + } + Task<AuthResult> pending = FirebaseAuth.getInstance().getPendingAuthResult(); + if (pending != null) { + callbackContext.error("Auth result is already pending"); + pending + .addOnSuccessListener(new AuthResultOnSuccessListener()) + .addOnFailureListener(new AuthResultOnFailureListener()); + } else { + String id = FirebasePlugin.instance.saveAuthProvider(provider.build());; + JSONObject returnResults = new JSONObject(); + returnResults.put("instantVerification", true); + returnResults.put("id", id); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, returnResults)); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void signInUserWithCustomToken(final CallbackContext callbackContext, final JSONArray args){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String customToken = args.getString(0); + + if(customToken == null || customToken.equals("")){ + callbackContext.error("Custom token must be specified"); + return; + } + + FirebaseAuth.getInstance().signInWithCustomToken(customToken).addOnCompleteListener(cordova.getActivity(), new AuthResultOnCompleteListener(callbackContext)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void signInUserAnonymously(final CallbackContext callbackContext){ + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebaseAuth.getInstance().signInAnonymously().addOnCompleteListener(cordova.getActivity(), new AuthResultOnCompleteListener(callbackContext)); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + // + // Firebase Performace + // + + private HashMap<String, Trace> traces = new HashMap<String, Trace>(); + + private void startTrace(final CallbackContext callbackContext, final String name) { + final FirebasePlugin self = this; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + + Trace myTrace = null; + if (self.traces.containsKey(name)) { + myTrace = self.traces.get(name); + } + + if (myTrace == null) { + myTrace = FirebasePerformance.getInstance().newTrace(name); + myTrace.start(); + self.traces.put(name, myTrace); + } + + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void incrementCounter(final CallbackContext callbackContext, final String name, final String counterNamed) { + final FirebasePlugin self = this; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + + Trace myTrace = null; + if (self.traces.containsKey(name)) { + myTrace = self.traces.get(name); + } + + if (myTrace != null && myTrace instanceof Trace) { + myTrace.incrementMetric(counterNamed, 1); + callbackContext.success(); + } else { + callbackContext.error("Trace not found"); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void stopTrace(final CallbackContext callbackContext, final String name) { + final FirebasePlugin self = this; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + + Trace myTrace = null; + if (self.traces.containsKey(name)) { + myTrace = self.traces.get(name); + } + + if (myTrace != null && myTrace instanceof Trace) { // + myTrace.stop(); + self.traces.remove(name); + callbackContext.success(); + } else { + callbackContext.error("Trace not found"); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void setAnalyticsCollectionEnabled(final CallbackContext callbackContext, final boolean enabled) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + mFirebaseAnalytics.setAnalyticsCollectionEnabled(enabled); + setPreference(ANALYTICS_COLLECTION_ENABLED, enabled); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void isAnalyticsCollectionEnabled(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + callbackContext.success(getPreference(ANALYTICS_COLLECTION_ENABLED) ? 1 : 0); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void setPerformanceCollectionEnabled(final CallbackContext callbackContext, final boolean enabled) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + FirebasePerformance.getInstance().setPerformanceCollectionEnabled(enabled); + setPreference(PERFORMANCE_COLLECTION_ENABLED, enabled); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void isPerformanceCollectionEnabled(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + callbackContext.success(getPreference(PERFORMANCE_COLLECTION_ENABLED) ? 1 : 0); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void setCrashlyticsCollectionEnabled(final CallbackContext callbackContext, final boolean enabled) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + firebaseCrashlytics.setCrashlyticsCollectionEnabled(enabled); + setPreference(CRASHLYTICS_COLLECTION_ENABLED, enabled); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private void isCrashlyticsCollectionEnabled(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + callbackContext.success(isCrashlyticsEnabled() ? 1 : 0); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + e.printStackTrace(); + } + } + }); + } + + private boolean isCrashlyticsEnabled(){ + return getPreference(CRASHLYTICS_COLLECTION_ENABLED); + } + + public void clearAllNotifications(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + NotificationManager nm = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE); + nm.cancelAll(); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void createChannel(final CallbackContext callbackContext, final JSONObject options) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + createChannel(options); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + protected static NotificationChannel createChannel(final JSONObject options) throws JSONException { + NotificationChannel channel = null; + // only call on Android O and above + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String id = options.getString("id"); + Log.i(TAG, "Creating channel id="+id); + + if(channelExists(id)){ + deleteChannel(id); + } + + NotificationManager nm = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE); + String packageName = cordovaActivity.getPackageName(); + + String name = options.optString("name", ""); + Log.d(TAG, "Channel "+id+" - name="+name); + + int importance = options.optInt("importance", NotificationManager.IMPORTANCE_HIGH); + Log.d(TAG, "Channel "+id+" - importance="+importance); + + channel = new NotificationChannel(id, + name, + importance); + + // Description + String description = options.optString("description", ""); + Log.d(TAG, "Channel "+id+" - description="+description); + channel.setDescription(description); + + // Light + boolean light = options.optBoolean("light", true); + Log.d(TAG, "Channel "+id+" - light="+light); + channel.enableLights(light); + + int lightColor = options.optInt("lightColor", -1); + if (lightColor != -1) { + Log.d(TAG, "Channel "+id+" - lightColor="+lightColor); + channel.setLightColor(lightColor); + } + + // Visibility + int visibility = options.optInt("visibility", NotificationCompat.VISIBILITY_PUBLIC); + Log.d(TAG, "Channel "+id+" - visibility="+visibility); + channel.setLockscreenVisibility(visibility); + + // Badge + boolean badge = options.optBoolean("badge", true); + Log.d(TAG, "Channel "+id+" - badge="+badge); + channel.setShowBadge(badge); + + // Sound + String sound = options.optString("sound", "default"); + AudioAttributes audioAttributes = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build(); + if ("ringtone".equals(sound)) { + channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE), audioAttributes); + Log.d(TAG, "Channel "+id+" - sound=ringtone"); + } else if (sound != null && !sound.contentEquals("default")) { + Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + packageName + "/raw/" + sound); + channel.setSound(soundUri, audioAttributes); + Log.d(TAG, "Channel "+id+" - sound="+sound); + } else if (sound != "false"){ + channel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), audioAttributes); + Log.d(TAG, "Channel "+id+" - sound=default"); + }else{ + Log.d(TAG, "Channel "+id+" - sound=none"); + } + + // Vibration: if vibration setting is an array set vibration pattern, else set enable vibration. + JSONArray pattern = options.optJSONArray("vibration"); + if (pattern != null) { + int patternLength = pattern.length(); + long[] patternArray = new long[patternLength]; + for (int i = 0; i < patternLength; i++) { + patternArray[i] = pattern.optLong(i); + } + channel.enableVibration(true); + channel.setVibrationPattern(patternArray); + Log.d(TAG, "Channel "+id+" - vibrate="+pattern); + } else { + boolean vibrate = options.optBoolean("vibration", true); + channel.enableVibration(vibrate); + Log.d(TAG, "Channel "+id+" - vibrate="+vibrate); + } + + // Create channel + nm.createNotificationChannel(channel); + } + return channel; + } + + protected static void createDefaultChannel() throws JSONException { + JSONObject options = new JSONObject(); + options.put("id", defaultChannelId); + options.put("name", defaultChannelName); + createDefaultChannel(options); + } + + protected static void createDefaultChannel(final JSONObject options) throws JSONException { + defaultNotificationChannel = createChannel(options); + } + + public void setDefaultChannel(final CallbackContext callbackContext, final JSONObject options) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + deleteChannel(defaultChannelId); + + String id = options.optString("id", null); + if(id != null){ + defaultChannelId = id; + } + + String name = options.optString("name", null); + if(name != null){ + defaultChannelName = name; + } + createDefaultChannel(options); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public void deleteChannel(final CallbackContext callbackContext, final String channelID) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + deleteChannel(channelID); + callbackContext.success(); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + protected static void deleteChannel(final String channelID){ + // only call on Android O and above + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager nm = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE); + nm.deleteNotificationChannel(channelID); + } + } + + public void listChannels(final CallbackContext callbackContext) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + List<NotificationChannel> notificationChannels = listChannels(); + JSONArray channels = new JSONArray(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + for (NotificationChannel notificationChannel : notificationChannels) { + JSONObject channel = new JSONObject(); + channel.put("id", notificationChannel.getId()); + channel.put("name", notificationChannel.getName()); + channels.put(channel); + } + } + callbackContext.success(channels); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + public static List<NotificationChannel> listChannels(){ + List<NotificationChannel> notificationChannels = null; + // only call on Android O and above + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager nm = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE); + notificationChannels = nm.getNotificationChannels(); + } + return notificationChannels; + } + + public static boolean channelExists(String channelId){ + boolean exists = false; + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + List<NotificationChannel> notificationChannels = FirebasePlugin.listChannels(); + if(notificationChannels != null){ + for (NotificationChannel notificationChannel : notificationChannels) { + if(notificationChannel.getId().equals(channelId)){ + exists = true; + } + } + } + } + return exists; + } + + // + // Firestore + // + private void addDocumentToFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String jsonDoc = args.getString(0); + String collection = args.getString(1); + + firestore.collection(collection) + .add(jsonStringToMap(jsonDoc)) + .addOnSuccessListener(new OnSuccessListener<DocumentReference>() { + @Override + public void onSuccess(DocumentReference documentReference) { + callbackContext.success(documentReference.getId()); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void setDocumentInFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String documentId = args.getString(0); + String jsonDoc = args.getString(1); + String collection = args.getString(2); + + firestore.collection(collection).document(documentId) + .set(jsonStringToMap(jsonDoc)) + .addOnSuccessListener(new OnSuccessListener<Void>() { + @Override + public void onSuccess(Void aVoid) { + callbackContext.success(); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void updateDocumentInFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String documentId = args.getString(0); + String jsonDoc = args.getString(1); + String collection = args.getString(2); + + firestore.collection(collection).document(documentId) + .update(jsonStringToMap(jsonDoc)) + .addOnSuccessListener(new OnSuccessListener<Void>() { + @Override + public void onSuccess(Void aVoid) { + callbackContext.success(); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void deleteDocumentFromFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String documentId = args.getString(0); + String collection = args.getString(1); + + firestore.collection(collection).document(documentId) + .delete() + .addOnSuccessListener(new OnSuccessListener<Void>() { + @Override + public void onSuccess(Void aVoid) { + callbackContext.success(); + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void documentExistsInFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String documentId = args.getString(0); + String collection = args.getString(1); + + firestore.collection(collection).document(documentId) + .get() + .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() { + @Override + public void onComplete(@NonNull Task<DocumentSnapshot> task) { + try { + if (task.isSuccessful()) { + DocumentSnapshot document = task.getResult(); + callbackContext.success(document != null && document.getData() != null ? 1 : 0); + } else { + Exception e = task.getException(); + if(e != null){ + handleExceptionWithContext(e, callbackContext); + } + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void fetchDocumentInFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String documentId = args.getString(0); + String collection = args.getString(1); + + firestore.collection(collection).document(documentId) + .get() + .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() { + @Override + public void onComplete(@NonNull Task<DocumentSnapshot> task) { + try { + if (task.isSuccessful()) { + DocumentSnapshot document = task.getResult(); + if (document != null && document.getData() != null) { + JSONObject jsonDoc = mapToJsonObject(document.getData()); + callbackContext.success(jsonDoc); + } else { + callbackContext.error("No document found in collection"); + } + } else { + Exception e = task.getException(); + if(e != null){ + handleExceptionWithContext(e, callbackContext); + } + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }) + .addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + private void fetchFirestoreCollection(JSONArray args, CallbackContext callbackContext) throws JSONException { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String collection = args.getString(0); + JSONArray filters = args.getJSONArray(1); + Query query = firestore.collection(collection); + + for(int i = 0; i < filters.length(); i++) { + JSONArray filter = filters.getJSONArray(i); + switch(filter.getString(0)) { + case "where": + if (Objects.equals(filter.getString(2), new String("=="))) { + query = query.whereEqualTo(filter.getString(1), filter.getString(3)); + } + if (Objects.equals(filter.getString(2), new String("<"))) { + query = query.whereLessThan(filter.getString(1), filter.getString(3)); + } + if (Objects.equals(filter.getString(2), new String(">"))) { + query = query.whereGreaterThan(filter.getString(1), filter.getString(3)); + } + if (Objects.equals(filter.getString(2), new String("<="))) { + query = query.whereLessThanOrEqualTo(filter.getString(1), filter.getString(3)); + } + if (Objects.equals(filter.getString(2), new String(">="))) { + query = query.whereGreaterThanOrEqualTo(filter.getString(1), filter.getString(3)); + } + if (Objects.equals(filter.getString(2), new String("array-contains"))) { + query = query.whereArrayContains(filter.getString(1), filter.getString(3)); + } + break; + case "orderBy": + Direction direction = Direction.ASCENDING; + if (Objects.equals(filter.getString(2), new String("desc"))) { + direction = Direction.DESCENDING; + } + query = query.orderBy(filter.getString(1), direction); + break; + case "startAt": + query = query.startAt(filter.getString(1)); + break; + case "endAt": + query = query.endAt(filter.getString(1)); + break; + case "limit": + query = query.limit(filter.getLong(1)); + break; + } + } + + query.get() + .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { + @Override + public void onComplete(@NonNull Task<QuerySnapshot> task) { + try { + if (task.isSuccessful()) { + JSONObject jsonDocs = new JSONObject(); + for (QueryDocumentSnapshot document : task.getResult()) { + jsonDocs.put(document.getId(), mapToJsonObject(document.getData())); + } + callbackContext.success(jsonDocs); + } else { + handleExceptionWithContext(task.getException(), callbackContext); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + }); + } + + + protected static void handleExceptionWithContext(Exception e, CallbackContext context) { + String msg = e.toString(); + Log.e(TAG, msg); + instance.logExceptionToCrashlytics(e); + context.error(msg); + } + + protected static void handleExceptionWithoutContext(Exception e){ + String msg = e.toString(); + Log.e(TAG, msg); + if (instance != null) { + instance.logExceptionToCrashlytics(e); + instance.logErrorToWebview(msg); + } + } + + protected void logErrorToWebview(String msg){ + Log.e(TAG, msg); + executeGlobalJavascript("console.error(\""+TAG+"[native]: "+escapeDoubleQuotes(msg)+"\")"); + } + + private String escapeDoubleQuotes(String string){ + String escapedString = string.replace("\"", "\\\""); + escapedString = escapedString.replace("%22", "\\%22"); + return escapedString; + } + + private void executeGlobalJavascript(final String jsString){ + if(cordovaActivity == null) return; + cordovaActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + webView.loadUrl("javascript:" + jsString); + } + }); + } + + private String saveAuthCredential(AuthCredential authCredential){ + String id = this.generateId(); + this.authCredentials.put(id, authCredential); + return id; + } + + private String saveAuthProvider(OAuthProvider authProvider){ + String id = this.generateId(); + this.authProviders.put(id, authProvider); + return id; + } + + private String generateId(){ + Random r = new Random(); + return Integer.toString(r.nextInt(1000+1)); + } + + private boolean getMetaDataFromManifest(String name) throws Exception{ + return applicationContext.getPackageManager().getApplicationInfo(applicationContext.getPackageName(), PackageManager.GET_META_DATA).metaData.getBoolean(name); + } + + private void setPreference(String name, boolean value){ + SharedPreferences settings = cordovaActivity.getSharedPreferences(SETTINGS_NAME, MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putBoolean(name, value); + editor.apply(); + } + + private boolean getPreference(String name){ + SharedPreferences settings = cordovaActivity.getSharedPreferences(SETTINGS_NAME, MODE_PRIVATE); + return settings.getBoolean(name, false); + } + + private void handleTaskOutcome(@NonNull Task<Void> task, CallbackContext callbackContext) { + try { + task.addOnCompleteListener(new OnCompleteListener<Void>() { + @Override + public void onComplete(@NonNull Task<Void> task) { + try { + if (task.isSuccessful() || task.getException() == null) { + callbackContext.success(); + }else if(task.getException() != null){ + callbackContext.error(task.getException().getMessage()); + }else{ + callbackContext.error("Task failed for unknown reason"); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + }; + }); + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + + private void handleAuthTaskOutcome(@NonNull Task<AuthResult> task, CallbackContext callbackContext) { + try { + if (task.isSuccessful() || task.getException() == null) { + callbackContext.success(); + }else{ + String errMessage = task.getException().getMessage(); + if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) { + errMessage = "Invalid verification code"; + } + callbackContext.error(errMessage); + } + } catch (Exception e) { + handleExceptionWithContext(e, callbackContext); + } + } + + private AuthCredential obtainAuthCredential(JSONObject jsonCredential) throws JSONException { + AuthCredential authCredential = null; + if(jsonCredential.has("verificationId") && jsonCredential.has("code")){ + Log.d(TAG, "Using specified verificationId and code to authenticate"); + authCredential = (AuthCredential) PhoneAuthProvider.getCredential(jsonCredential.getString("verificationId"), jsonCredential.getString("code")); + }else if(jsonCredential.has("id") && FirebasePlugin.instance.authCredentials.containsKey(jsonCredential.getString("id"))){ + Log.d(TAG, "Using native auth credential to authenticate"); + authCredential = FirebasePlugin.instance.authCredentials.get(jsonCredential.getString("id")); + } + return authCredential; + } + + private OAuthProvider obtainAuthProvider(JSONObject jsonCredential) throws JSONException{ + OAuthProvider authProvider = null; + if(jsonCredential.has("id") && FirebasePlugin.instance.authProviders.containsKey(jsonCredential.getString("id"))){ + Log.d(TAG, "Using native auth provider to authenticate"); + authProvider = FirebasePlugin.instance.authProviders.get(jsonCredential.getString("id")); + } + return authProvider; + } + + + private static class AuthResultOnSuccessListener implements OnSuccessListener<AuthResult> { + @Override + public void onSuccess(AuthResult authResult) { + Log.d(TAG, "AuthResult:onSuccess:" + authResult); + if(FirebasePlugin.instance.authResultCallbackContext != null){ + FirebasePlugin.instance.authResultCallbackContext.success(); + } + } + } + + private static class AuthResultOnFailureListener implements OnFailureListener { + @Override + public void onFailure(@NonNull Exception e) { + Log.w(TAG, "AuthResult:onFailure", e); + if(FirebasePlugin.instance.authResultCallbackContext != null){ + FirebasePlugin.instance.authResultCallbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, e.getMessage())); + } + } + } + + private static class AuthResultOnCompleteListener implements OnCompleteListener<AuthResult> { + private final CallbackContext callbackContext; + + public AuthResultOnCompleteListener(CallbackContext callbackContext) { + this.callbackContext = callbackContext; + } + + @Override + public void onComplete(@NonNull Task<AuthResult> task) { + FirebasePlugin.instance.handleAuthTaskOutcome(task, callbackContext); + } + } + + private static class AuthStateListener implements FirebaseAuth.AuthStateListener { + @Override + public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { + try { + if(!FirebasePlugin.instance.authStateChangeListenerInitialized){ + FirebasePlugin.instance.authStateChangeListenerInitialized = true; + }else{ + FirebaseUser user = firebaseAuth.getCurrentUser(); + FirebasePlugin.instance.executeGlobalJavascript(JS_GLOBAL_NAMESPACE+"_onAuthStateChange("+(user != null ? "true" : "false")+")"); + } + } catch (Exception e) { + handleExceptionWithoutContext(e); + } + } + } + + private Map<String, Object> jsonStringToMap(String jsonString) throws JSONException { + Type type = new TypeToken<Map<String, Object>>(){}.getType(); + return gson.fromJson(jsonString, type); + } + + + private JSONObject mapToJsonObject(Map<String, Object> map) throws JSONException { + String jsonString = gson.toJson(map); + return new JSONObject(jsonString); + } + + private void logMessageToCrashlytics(String message){ + if(isCrashlyticsEnabled()){ + try{ + firebaseCrashlytics.log(message); + }catch (Exception e){ + Log.e(TAG, e.getMessage()); + } + }else{ + Log.e(TAG, "Cannot log message - Crashlytics collection is disabled"); + } + } + + private void logExceptionToCrashlytics(Exception exception){ + if(isCrashlyticsEnabled()){ + try{ + firebaseCrashlytics.recordException(exception); + }catch (Exception e){ + Log.e(TAG, e.getMessage()); + } + }else{ + Log.e(TAG, "Cannot log exception - Crashlytics collection is disabled"); + } + } +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessageReceiver.java b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessageReceiver.java new file mode 100644 index 00000000..1bb76d08 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessageReceiver.java @@ -0,0 +1,28 @@ +package org.apache.cordova.firebase; + +import android.os.Bundle; + +import com.google.firebase.messaging.RemoteMessage; + +public abstract class FirebasePluginMessageReceiver { + + public FirebasePluginMessageReceiver() { + FirebasePluginMessageReceiverManager.register(this); + } + + /** + * Concrete subclasses should override this and return true if they handle the received message. + * + * @param remoteMessage + * @return true if the received message was handled by the receiver so should not be handled by FirebasePluginMessagingService.onMessageReceived() + */ + public abstract boolean onMessageReceived(RemoteMessage remoteMessage); + + /** + * Concrete subclasses should override this and return true if they handle the message bundle before it's sent to FirebasePlugin.sendMessage(). + * + * @param bundle + * @return true if the received bundle was handled by the receiver so should not be handled by FirebasePlugin. + */ + public abstract boolean sendMessage(Bundle bundle); +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessageReceiverManager.java b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessageReceiverManager.java new file mode 100644 index 00000000..299e5cda --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessageReceiverManager.java @@ -0,0 +1,41 @@ +package org.apache.cordova.firebase; + +import android.os.Bundle; + +import com.google.firebase.messaging.RemoteMessage; + +import java.util.ArrayList; +import java.util.List; + +public class FirebasePluginMessageReceiverManager { + + private static List<FirebasePluginMessageReceiver> receivers = new ArrayList<FirebasePluginMessageReceiver>(); + + public static void register(FirebasePluginMessageReceiver receiver) { + receivers.add(receiver); + } + + public static boolean onMessageReceived(RemoteMessage remoteMessage) { + boolean handled = false; + for (FirebasePluginMessageReceiver receiver : receivers) { + boolean wasHandled = receiver.onMessageReceived(remoteMessage); + if (wasHandled) { + handled = true; + } + } + + return handled; + } + + public static boolean sendMessage(Bundle bundle) { + boolean handled = false; + for (FirebasePluginMessageReceiver receiver : receivers) { + boolean wasHandled = receiver.sendMessage(bundle); + if (wasHandled) { + handled = true; + } + } + + return handled; + } +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessagingService.java b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessagingService.java new file mode 100644 index 00000000..92e6aafb --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/FirebasePluginMessagingService.java @@ -0,0 +1,348 @@ +package org.apache.cordova.firebase; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import androidx.core.app.NotificationCompat; +import android.util.Log; +import android.app.Notification; +import android.text.TextUtils; +import android.content.ContentResolver; +import android.graphics.Color; + +import com.google.firebase.crashlytics.FirebaseCrashlytics; +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +import java.util.Map; +import java.util.Random; + +public class FirebasePluginMessagingService extends FirebaseMessagingService { + + private static final String TAG = "FirebasePlugin"; + + static final String defaultSmallIconName = "notification_icon"; + static final String defaultLargeIconName = "notification_icon_large"; + + + /** + * Called if InstanceID token is updated. This may occur if the security of + * the previous token had been compromised. Note that this is called when the InstanceID token + * is initially generated so this is where you would retrieve the token. + */ + @Override + public void onNewToken(String refreshedToken) { + try{ + super.onNewToken(refreshedToken); + Log.d(TAG, "Refreshed token: " + refreshedToken); + FirebasePlugin.sendToken(refreshedToken); + }catch (Exception e){ + FirebasePlugin.handleExceptionWithoutContext(e); + } + } + + + /** + * Called when message is received. + * Called IF message is a data message (i.e. NOT sent from Firebase console) + * OR if message is a notification message (e.g. sent from Firebase console) AND app is in foreground. + * Notification messages received while app is in background will not be processed by this method; + * they are handled internally by the OS. + * + * @param remoteMessage Object representing the message received from Firebase Cloud Messaging. + */ + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + try{ + // [START_EXCLUDE] + // There are two types of messages data messages and notification messages. Data messages are handled + // here in onMessageReceived whether the app is in the foreground or background. Data messages are the type + // traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app + // is in the foreground. When the app is in the background an automatically generated notification is displayed. + // When the user taps on the notification they are returned to the app. Messages containing both notification + // and data payloads are treated as notification messages. The Firebase console always sends notification + // messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options + // [END_EXCLUDE] + + // Pass the message to the receiver manager so any registered receivers can decide to handle it + boolean wasHandled = FirebasePluginMessageReceiverManager.onMessageReceived(remoteMessage); + if (wasHandled) { + Log.d(TAG, "Message was handled by a registered receiver"); + + // Don't process the message in this method. + return; + } + + if(FirebasePlugin.applicationContext == null){ + FirebasePlugin.applicationContext = this.getApplicationContext(); + } + + // TODO(developer): Handle FCM messages here. + // Not getting messages here? See why this may be: https://goo.gl/39bRNJ + String messageType; + String title = null; + String body = null; + String id = null; + String sound = null; + String vibrate = null; + String light = null; + String color = null; + String icon = null; + String channelId = null; + String visibility = null; + String priority = null; + boolean foregroundNotification = false; + + Map<String, String> data = remoteMessage.getData(); + + if (remoteMessage.getNotification() != null) { + // Notification message payload + Log.i(TAG, "Received message: notification"); + messageType = "notification"; + id = remoteMessage.getMessageId(); + RemoteMessage.Notification notification = remoteMessage.getNotification(); + title = notification.getTitle(); + body = notification.getBody(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + channelId = notification.getChannelId(); + } + sound = notification.getSound(); + color = notification.getColor(); + icon = notification.getIcon(); + }else{ + Log.i(TAG, "Received message: data"); + messageType = "data"; + } + + if (data != null) { + // Data message payload + if(data.containsKey("notification_foreground")){ + foregroundNotification = true; + } + if(data.containsKey("notification_title")) title = data.get("notification_title"); + if(data.containsKey("notification_body")) body = data.get("notification_body"); + if(data.containsKey("notification_android_channel_id")) channelId = data.get("notification_android_channel_id"); + if(data.containsKey("notification_android_id")) id = data.get("notification_android_id"); + if(data.containsKey("notification_android_sound")) sound = data.get("notification_android_sound"); + if(data.containsKey("notification_android_vibrate")) vibrate = data.get("notification_android_vibrate"); + if(data.containsKey("notification_android_light")) light = data.get("notification_android_light"); //String containing hex ARGB color, miliseconds on, miliseconds off, example: '#FFFF00FF,1000,3000' + if(data.containsKey("notification_android_color")) color = data.get("notification_android_color"); + if(data.containsKey("notification_android_icon")) icon = data.get("notification_android_icon"); + if(data.containsKey("notification_android_visibility")) visibility = data.get("notification_android_visibility"); + if(data.containsKey("notification_android_priority")) priority = data.get("notification_android_priority"); + } + + if (TextUtils.isEmpty(id)) { + Random rand = new Random(); + int n = rand.nextInt(50) + 1; + id = Integer.toString(n); + } + + Log.d(TAG, "From: " + remoteMessage.getFrom()); + Log.d(TAG, "Id: " + id); + Log.d(TAG, "Title: " + title); + Log.d(TAG, "Body: " + body); + Log.d(TAG, "Sound: " + sound); + Log.d(TAG, "Vibrate: " + vibrate); + Log.d(TAG, "Light: " + light); + Log.d(TAG, "Color: " + color); + Log.d(TAG, "Icon: " + icon); + Log.d(TAG, "Channel Id: " + channelId); + Log.d(TAG, "Visibility: " + visibility); + Log.d(TAG, "Priority: " + priority); + + + if (!TextUtils.isEmpty(body) || !TextUtils.isEmpty(title) || (data != null && !data.isEmpty())) { + boolean showNotification = (FirebasePlugin.inBackground() || !FirebasePlugin.hasNotificationsCallback() || foregroundNotification) && (!TextUtils.isEmpty(body) || !TextUtils.isEmpty(title)); + sendMessage(remoteMessage, data, messageType, id, title, body, showNotification, sound, vibrate, light, color, icon, channelId, priority, visibility); + } + }catch (Exception e){ + FirebasePlugin.handleExceptionWithoutContext(e); + } + } + + private void sendMessage(RemoteMessage remoteMessage, Map<String, String> data, String messageType, String id, String title, String body, boolean showNotification, String sound, String vibrate, String light, String color, String icon, String channelId, String priority, String visibility) { + Log.d(TAG, "sendMessage(): messageType="+messageType+"; showNotification="+showNotification+"; id="+id+"; title="+title+"; body="+body+"; sound="+sound+"; vibrate="+vibrate+"; light="+light+"; color="+color+"; icon="+icon+"; channel="+channelId+"; data="+data.toString()); + Bundle bundle = new Bundle(); + for (String key : data.keySet()) { + bundle.putString(key, data.get(key)); + } + bundle.putString("messageType", messageType); + this.putKVInBundle("id", id, bundle); + this.putKVInBundle("title", title, bundle); + this.putKVInBundle("body", body, bundle); + this.putKVInBundle("sound", sound, bundle); + this.putKVInBundle("vibrate", vibrate, bundle); + this.putKVInBundle("light", light, bundle); + this.putKVInBundle("color", color, bundle); + this.putKVInBundle("icon", icon, bundle); + this.putKVInBundle("channel_id", channelId, bundle); + this.putKVInBundle("priority", priority, bundle); + this.putKVInBundle("visibility", visibility, bundle); + this.putKVInBundle("show_notification", String.valueOf(showNotification), bundle); + this.putKVInBundle("from", remoteMessage.getFrom(), bundle); + this.putKVInBundle("collapse_key", remoteMessage.getCollapseKey(), bundle); + this.putKVInBundle("sent_time", String.valueOf(remoteMessage.getSentTime()), bundle); + this.putKVInBundle("ttl", String.valueOf(remoteMessage.getTtl()), bundle); + + if (showNotification) { + Intent intent = new Intent(this, OnNotificationOpenReceiver.class); + intent.putExtras(bundle); + PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT); + + // Channel + if(channelId == null || !FirebasePlugin.channelExists(channelId)){ + channelId = FirebasePlugin.defaultChannelId; + } + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ + Log.d(TAG, "Channel ID: "+channelId); + } + + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId); + notificationBuilder + .setContentTitle(title) + .setContentText(body) + .setStyle(new NotificationCompat.BigTextStyle().bigText(body)) + .setAutoCancel(true) + .setContentIntent(pendingIntent); + + // On Android O+ the sound/lights/vibration are determined by the channel ID + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.O){ + // Sound + if (sound == null) { + Log.d(TAG, "Sound: none"); + }else if (sound.equals("default")) { + notificationBuilder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); + Log.d(TAG, "Sound: default"); + }else{ + Uri soundPath = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName() + "/raw/" + sound); + Log.d(TAG, "Sound: custom=" + sound+"; path="+soundPath.toString()); + notificationBuilder.setSound(soundPath); + } + + // Light + if (light != null) { + try { + String[] lightsComponents = color.replaceAll("\\s", "").split(","); + if (lightsComponents.length == 3) { + int lightArgb = Color.parseColor(lightsComponents[0]); + int lightOnMs = Integer.parseInt(lightsComponents[1]); + int lightOffMs = Integer.parseInt(lightsComponents[2]); + notificationBuilder.setLights(lightArgb, lightOnMs, lightOffMs); + Log.d(TAG, "Lights: color="+lightsComponents[0]+"; on(ms)="+lightsComponents[2]+"; off(ms)="+lightsComponents[3]); + } + + } catch (Exception e) {} + } + + // Vibrate + if (vibrate != null){ + try { + String[] sVibrations = vibrate.replaceAll("\\s", "").split(","); + long[] lVibrations = new long[sVibrations.length]; + int i=0; + for(String sVibration: sVibrations){ + lVibrations[i] = Integer.parseInt(sVibration.trim()); + i++; + } + notificationBuilder.setVibrate(lVibrations); + Log.d(TAG, "Vibrate: "+vibrate); + } catch (Exception e) { + Log.e(TAG, e.getMessage()); + } + } + } + + + // Icon + int defaultSmallIconResID = getResources().getIdentifier(defaultSmallIconName, "drawable", getPackageName()); + int customSmallIconResID = 0; + if(icon != null){ + customSmallIconResID = getResources().getIdentifier(icon, "drawable", getPackageName()); + } + + if (customSmallIconResID != 0) { + notificationBuilder.setSmallIcon(customSmallIconResID); + Log.d(TAG, "Small icon: custom="+icon); + }else if (defaultSmallIconResID != 0) { + Log.d(TAG, "Small icon: default="+defaultSmallIconName); + notificationBuilder.setSmallIcon(defaultSmallIconResID); + } else { + Log.d(TAG, "Small icon: application"); + notificationBuilder.setSmallIcon(getApplicationInfo().icon); + } + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + int defaultLargeIconResID = getResources().getIdentifier(defaultLargeIconName, "drawable", getPackageName()); + int customLargeIconResID = 0; + if(icon != null){ + customLargeIconResID = getResources().getIdentifier(icon+"_large", "drawable", getPackageName()); + } + + int largeIconResID; + if (customLargeIconResID != 0 || defaultLargeIconResID != 0) { + if (customLargeIconResID != 0) { + largeIconResID = customLargeIconResID; + Log.d(TAG, "Large icon: custom="+icon); + }else{ + Log.d(TAG, "Large icon: default="+defaultLargeIconName); + largeIconResID = defaultLargeIconResID; + } + notificationBuilder.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), largeIconResID)); + } + } + + // Color + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + int defaultColor = getResources().getColor(getResources().getIdentifier("accent", "color", getPackageName()), null); + if(color != null){ + notificationBuilder.setColor(Color.parseColor(color)); + Log.d(TAG, "Color: custom="+color); + }else{ + Log.d(TAG, "Color: default"); + notificationBuilder.setColor(defaultColor); + } + } + + // Visibility + int iVisibility = NotificationCompat.VISIBILITY_PUBLIC; + if(visibility != null){ + iVisibility = Integer.parseInt(visibility); + } + Log.d(TAG, "Visibility: " + iVisibility); + notificationBuilder.setVisibility(iVisibility); + + // Priority + int iPriority = NotificationCompat.PRIORITY_MAX; + if(priority != null){ + iPriority = Integer.parseInt(priority); + } + Log.d(TAG, "Priority: " + iPriority); + notificationBuilder.setPriority(iPriority); + + + // Build notification + Notification notification = notificationBuilder.build(); + + // Display notification + NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + Log.d(TAG, "show notification: "+notification.toString()); + notificationManager.notify(id.hashCode(), notification); + } + // Send to plugin + FirebasePlugin.sendMessage(bundle, this.getApplicationContext()); + } + + private void putKVInBundle(String k, String v, Bundle b){ + if(v != null && !b.containsKey(k)){ + b.putString(k, v); + } + } +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/JavaScriptException.java b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/JavaScriptException.java new file mode 100644 index 00000000..3d423fa3 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/JavaScriptException.java @@ -0,0 +1,45 @@ +package org.apache.cordova.firebase; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * Exception class to log Javascript based exceptions with stacktrace. + * + * Picked from https://github.com/wizpanda/cordova-plugin-firebase-lib/pull/8/files + * + * @author https://github.com/sagrawal31/ + */ +public class JavaScriptException extends Exception { + + public JavaScriptException(String message) { + super(message); + } + + public JavaScriptException(String message, JSONArray stackTrace) throws JSONException { + super(message); + this.handleStacktrace(stackTrace); + } + + private void handleStacktrace(JSONArray stackTrace) throws JSONException { + if (stackTrace == null) { + return; + } + + StackTraceElement[] trace = new StackTraceElement[stackTrace.length()]; + + for (int i = 0; i < stackTrace.length(); i++) { + JSONObject elem = stackTrace.getJSONObject(i); + + trace[i] = new StackTraceElement( + "undefined", + elem.optString("functionName", "undefined"), + elem.optString("fileName", "undefined"), + elem.optInt("lineNumber", -1) + ); + } + + this.setStackTrace(trace); + } +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/OnNotificationOpenReceiver.java b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/OnNotificationOpenReceiver.java new file mode 100644 index 00000000..818382ef --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/OnNotificationOpenReceiver.java @@ -0,0 +1,36 @@ +package org.apache.cordova.firebase; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.Log; + +public class OnNotificationOpenReceiver extends BroadcastReceiver { + + // Called on tapping foreground notification + @Override + public void onReceive(Context context, Intent intent) { + try{ + PackageManager pm = context.getPackageManager(); + + Intent launchIntent = pm.getLaunchIntentForPackage(context.getPackageName()); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + + Bundle data = intent.getExtras(); + if(!data.containsKey("messageType")) data.putString("messageType", "notification"); + data.putString("tap", FirebasePlugin.inBackground() ? "background" : "foreground"); + + Log.d(FirebasePlugin.TAG, "OnNotificationOpenReceiver.onReceive(): "+data.toString()); + + FirebasePlugin.sendMessage(data, context); + + launchIntent.putExtras(data); + context.startActivity(launchIntent); + }catch (Exception e){ + FirebasePlugin.handleExceptionWithoutContext(e); + } + } +} diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/build.gradle b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/build.gradle new file mode 100644 index 00000000..89c743f1 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/build.gradle @@ -0,0 +1,48 @@ +buildscript { + repositories { + google() + mavenCentral() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.4.1' + classpath 'com.google.gms:google-services:4.3.3' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1' + } +} +repositories { + mavenCentral() + maven { + url "https://maven.google.com" + } +} + +apply plugin: com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsPlugin +android { + buildTypes { + debug { + firebaseCrashlytics { + mappingFileUploadEnabled false + } + } + release { + firebaseCrashlytics { + nativeSymbolUploadEnabled true + unstrippedNativeLibsDir "obj/local" + strippedNativeLibsDir "build/intermediates/jniLibs/release" + } + } + } +} + +cdvPluginPostBuildExtras.add({ + rootProject.subprojects { + if (name == "app") { + if (!plugins.hasPlugin('com.google.gms.google-services')) { + apply plugin: com.google.gms.googleservices.GoogleServicesPlugin + } + } + } +}) + + diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/colors.xml b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/colors.xml new file mode 100644 index 00000000..045e125f --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/colors.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> +</resources> diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/android/cordova-plugin-firebase-strings.xml b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/cordova-plugin-firebase-strings.xml new file mode 100644 index 00000000..1f1d32cc --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/android/cordova-plugin-firebase-strings.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='utf-8'?> +<resources> + <string name="default_notification_channel_id">fcm_default_channel</string> + <string name="default_notification_channel_name">Default</string> +</resources>
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/AppDelegate+FirebasePlugin.h b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/AppDelegate+FirebasePlugin.h new file mode 100644 index 00000000..461b17e4 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/AppDelegate+FirebasePlugin.h @@ -0,0 +1,11 @@ +#import "AppDelegate.h"
+#import <GoogleSignIn/GoogleSignIn.h>
+
+@import UserNotifications;
+@import AuthenticationServices;
+
+@interface AppDelegate (FirebasePlugin) <UIApplicationDelegate, GIDSignInDelegate, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding>
++ (AppDelegate *) instance;
+@property (nonatomic, strong) NSNumber * _Nonnull applicationInBackground;
+@property (NS_NONATOMIC_IOSONLY, nullable, weak) id <UNUserNotificationCenterDelegate> delegate;
+@end
diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/AppDelegate+FirebasePlugin.m b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/AppDelegate+FirebasePlugin.m new file mode 100644 index 00000000..a14c6569 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/AppDelegate+FirebasePlugin.m @@ -0,0 +1,557 @@ +#import "AppDelegate+FirebasePlugin.h" +#import "FirebasePlugin.h" +#import "Firebase.h" +#import <objc/runtime.h> + + +@import UserNotifications; +@import FirebaseFirestore; + +// Implement UNUserNotificationCenterDelegate to receive display notification via APNS for devices running iOS 10 and above. +// Implement FIRMessagingDelegate to receive data message via FCM for devices running iOS 10 and above. +@interface AppDelegate () <UNUserNotificationCenterDelegate, FIRMessagingDelegate> +@end + +#define kApplicationInBackgroundKey @"applicationInBackground" + +@implementation AppDelegate (FirebasePlugin) + +static AppDelegate* instance; + ++ (AppDelegate*) instance { + return instance; +} + +static NSDictionary* mutableUserInfo; +static FIRAuthStateDidChangeListenerHandle authStateChangeListener; +static bool authStateChangeListenerInitialized = false; +static bool shouldEstablishDirectChannel = false; + ++ (void)load { + Method original = class_getInstanceMethod(self, @selector(application:didFinishLaunchingWithOptions:)); + Method swizzled = class_getInstanceMethod(self, @selector(application:swizzledDidFinishLaunchingWithOptions:)); + method_exchangeImplementations(original, swizzled); +} + +- (void)setApplicationInBackground:(NSNumber *)applicationInBackground { + objc_setAssociatedObject(self, kApplicationInBackgroundKey, applicationInBackground, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSNumber *)applicationInBackground { + return objc_getAssociatedObject(self, kApplicationInBackgroundKey); +} + +- (BOOL)application:(UIApplication *)application swizzledDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [self application:application swizzledDidFinishLaunchingWithOptions:launchOptions]; + + @try{ + instance = self; + + bool isFirebaseInitializedWithPlist = false; + if(![FIRApp defaultApp]) { + // get GoogleService-Info.plist file path + NSString *filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]; + + // if file is successfully found, use it + if(filePath){ + [FirebasePlugin.firebasePlugin _logMessage:@"GoogleService-Info.plist found, setup: [FIRApp configureWithOptions]"]; + // create firebase configure options passing .plist as content + FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; + + // configure FIRApp with options + [FIRApp configureWithOptions:options]; + + isFirebaseInitializedWithPlist = true; + }else{ + // no .plist found, try default App + [FirebasePlugin.firebasePlugin _logError:@"GoogleService-Info.plist NOT FOUND, setup: [FIRApp defaultApp]"]; + [FIRApp configure]; + } + }else{ + // Firebase SDK has already been initialised: + // Assume that another call (probably from another plugin) did so with the plist + isFirebaseInitializedWithPlist = true; + } + + + + shouldEstablishDirectChannel = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"shouldEstablishDirectChannel"] boolValue]; + + // Set FCM messaging delegate + [FIRMessaging messaging].delegate = self; + [FIRMessaging messaging].shouldEstablishDirectChannel = shouldEstablishDirectChannel; + + // Setup Firestore + [FirebasePlugin setFirestore:[FIRFirestore firestore]]; + + // Setup Google SignIn + [GIDSignIn sharedInstance].clientID = [FIRApp defaultApp].options.clientID; + [GIDSignIn sharedInstance].delegate = self; + + authStateChangeListener = [[FIRAuth auth] addAuthStateDidChangeListener:^(FIRAuth * _Nonnull auth, FIRUser * _Nullable user) { + @try { + if(!authStateChangeListenerInitialized){ + authStateChangeListenerInitialized = true; + }else{ + [FirebasePlugin.firebasePlugin executeGlobalJavascript:[NSString stringWithFormat:@"FirebasePlugin._onAuthStateChange(%@)", (user != nil ? @"true": @"false")]]; + } + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } + }]; + + // Set NSNotificationCenter observer + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshNotification:) + name:kFIRInstanceIDTokenRefreshNotification object:nil]; + + self.applicationInBackground = @(YES); + + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } + + return YES; +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + self.applicationInBackground = @(NO); + [FIRMessaging messaging].shouldEstablishDirectChannel = shouldEstablishDirectChannel; + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"Enter foreground: FCM direct channel = %@", shouldEstablishDirectChannel ? @"true" : @"false"]]; +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + self.applicationInBackground = @(YES); + [FIRMessaging messaging].shouldEstablishDirectChannel = false; + [FirebasePlugin.firebasePlugin _logMessage:@"Enter background: FCM direct channel = false"]; +} + +# pragma mark - Google SignIn +- (void)signIn:(GIDSignIn *)signIn +didSignInForUser:(GIDGoogleUser *)user + withError:(NSError *)error { + @try{ + CDVPluginResult* pluginResult; + if (error == nil) { + GIDAuthentication *authentication = user.authentication; + FIRAuthCredential *credential = + [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken + accessToken:authentication.accessToken]; + + int key = [[FirebasePlugin firebasePlugin] saveAuthCredential:credential]; + NSMutableDictionary* result = [[NSMutableDictionary alloc] init]; + [result setValue:@"true" forKey:@"instantVerification"]; + [result setValue:[NSNumber numberWithInt:key] forKey:@"id"]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result]; + } else { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description]; + } + if ([FirebasePlugin firebasePlugin].googleSignInCallbackId != nil) { + [[FirebasePlugin firebasePlugin].commandDelegate sendPluginResult:pluginResult callbackId:[FirebasePlugin firebasePlugin].googleSignInCallbackId]; + } + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +- (void)signIn:(GIDSignIn *)signIn +didDisconnectWithUser:(GIDGoogleUser *)user + withError:(NSError *)error { + NSString* msg = @"Google SignIn delegate: didDisconnectWithUser"; + if(error != nil){ + [FirebasePlugin.firebasePlugin _logError:[NSString stringWithFormat:@"%@: %@", msg, error]]; + }else{ + [FirebasePlugin.firebasePlugin _logMessage:msg]; + } +} + +# pragma mark - FIRMessagingDelegate +- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken { + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"didReceiveRegistrationToken: %@", fcmToken]]; + @try{ + [FirebasePlugin.firebasePlugin sendToken:fcmToken]; + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +- (void)tokenRefreshNotification:(NSNotification *)notification { + // Note that this callback will be fired everytime a new token is generated, including the first + // time. So if you need to retrieve the token as soon as it is available this is where that + // should be done. + @try{ + [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result, + NSError * _Nullable error) { + @try{ + if (error == nil) { + NSString *refreshedToken = result.token; + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"tokenRefreshNotification: %@", refreshedToken]]; + [FirebasePlugin.firebasePlugin sendToken:refreshedToken]; + }else{ + [FirebasePlugin.firebasePlugin _logError:[NSString stringWithFormat:@"tokenRefreshNotification: %@", error.description]]; + } + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } + }]; + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + [FIRMessaging messaging].APNSToken = deviceToken; + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken]]; + [FirebasePlugin.firebasePlugin sendApnsToken:[FirebasePlugin.firebasePlugin hexadecimalStringFromData:deviceToken]]; + + // Set UNUserNotificationCenter delegate + [UNUserNotificationCenter currentNotificationCenter].delegate = self; +} + +//Tells the app that a remote notification arrived that indicates there is data to be fetched. +// Called when a message arrives in the foreground and remote notifications permission has been granted +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + + @try{ + [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; + mutableUserInfo = [userInfo mutableCopy]; + NSDictionary* aps = [mutableUserInfo objectForKey:@"aps"]; + bool isContentAvailable = false; + if([aps objectForKey:@"alert"] != nil){ + isContentAvailable = [[aps objectForKey:@"content-available"] isEqualToNumber:[NSNumber numberWithInt:1]]; + [mutableUserInfo setValue:@"notification" forKey:@"messageType"]; + NSString* tap; + if([self.applicationInBackground isEqual:[NSNumber numberWithBool:YES]] && !isContentAvailable){ + tap = @"background"; + } + [mutableUserInfo setValue:tap forKey:@"tap"]; + }else{ + [mutableUserInfo setValue:@"data" forKey:@"messageType"]; + } + + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"didReceiveRemoteNotification: %@", mutableUserInfo]]; + + completionHandler(UIBackgroundFetchResultNewData); + if([self.applicationInBackground isEqual:[NSNumber numberWithBool:YES]] && isContentAvailable){ + [FirebasePlugin.firebasePlugin _logError:@"didReceiveRemoteNotification: omitting foreground notification as content-available:1 so system notification will be shown"]; + }else{ + [self processMessageForForegroundNotification:mutableUserInfo]; + } + if([self.applicationInBackground isEqual:[NSNumber numberWithBool:YES]] || !isContentAvailable){ + [FirebasePlugin.firebasePlugin sendNotification:mutableUserInfo]; + } + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +// Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground. +// Called when a data message is arrives in the foreground and remote notifications permission has been NOT been granted +- (void)messaging:(FIRMessaging *)messaging didReceiveMessage:(FIRMessagingRemoteMessage *)remoteMessage { + @try{ + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"didReceiveMessage: %@", remoteMessage.appData]]; + + NSDictionary* appData = [remoteMessage.appData mutableCopy]; + [appData setValue:@"data" forKey:@"messageType"]; + [self processMessageForForegroundNotification:appData]; + + // This will allow us to handle FCM data-only push messages even if the permission for push + // notifications is yet missing. This will only work when the app is in the foreground. + [FirebasePlugin.firebasePlugin sendNotification:appData]; + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +// Scans a message for keys which indicate a notification should be shown. +// If found, extracts relevant keys and uses then to display a local notification +-(void)processMessageForForegroundNotification:(NSDictionary*)messageData { + bool showForegroundNotification = [messageData objectForKey:@"notification_foreground"]; + if(!showForegroundNotification){ + return; + } + + NSString* title = nil; + NSString* body = nil; + NSString* sound = nil; + NSNumber* badge = nil; + + // Extract APNS notification keys + NSDictionary* aps = [messageData objectForKey:@"aps"]; + if([aps objectForKey:@"alert"] != nil){ + NSDictionary* alert = [aps objectForKey:@"alert"]; + if([alert objectForKey:@"title"] != nil){ + title = [alert objectForKey:@"title"]; + } + if([alert objectForKey:@"body"] != nil){ + body = [alert objectForKey:@"body"]; + } + if([aps objectForKey:@"sound"] != nil){ + sound = [aps objectForKey:@"sound"]; + } + if([aps objectForKey:@"badge"] != nil){ + badge = [aps objectForKey:@"badge"]; + } + } + + // Extract data notification keys + if([messageData objectForKey:@"notification_title"] != nil){ + title = [messageData objectForKey:@"notification_title"]; + } + if([messageData objectForKey:@"notification_body"] != nil){ + body = [messageData objectForKey:@"notification_body"]; + } + if([messageData objectForKey:@"notification_ios_sound"] != nil){ + sound = [messageData objectForKey:@"notification_ios_sound"]; + } + if([messageData objectForKey:@"notification_ios_badge"] != nil){ + badge = [messageData objectForKey:@"notification_ios_badge"]; + } + + if(title == nil || body == nil){ + return; + } + + [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { + @try{ + if (settings.alertSetting == UNNotificationSettingEnabled) { + UNMutableNotificationContent *objNotificationContent = [[UNMutableNotificationContent alloc] init]; + objNotificationContent.title = [NSString localizedUserNotificationStringForKey:title arguments:nil]; + objNotificationContent.body = [NSString localizedUserNotificationStringForKey:body arguments:nil]; + + NSDictionary* alert = [[NSDictionary alloc] initWithObjectsAndKeys: + title, @"title", + body, @"body" + , nil]; + NSMutableDictionary* aps = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + alert, @"alert", + nil]; + + if(![sound isKindOfClass:[NSString class]] || [sound isEqualToString:@"default"]){ + objNotificationContent.sound = [UNNotificationSound defaultSound]; + [aps setValue:sound forKey:@"sound"]; + }else if(sound != nil){ + objNotificationContent.sound = [UNNotificationSound soundNamed:sound]; + [aps setValue:sound forKey:@"sound"]; + } + + if(badge != nil){ + [aps setValue:badge forKey:@"badge"]; + } + + NSString* messageType = @"data"; + if([mutableUserInfo objectForKey:@"messageType"] != nil){ + messageType = [mutableUserInfo objectForKey:@"messageType"]; + } + + NSDictionary* userInfo = [[NSDictionary alloc] initWithObjectsAndKeys: + @"true", @"notification_foreground", + messageType, @"messageType", + aps, @"aps" + , nil]; + + objNotificationContent.userInfo = userInfo; + + UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1f repeats:NO]; + UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"local_notification" content:objNotificationContent trigger:trigger]; + [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { + if (!error) { + [FirebasePlugin.firebasePlugin _logMessage:@"Local Notification succeeded"]; + } else { + [FirebasePlugin.firebasePlugin _logError:[NSString stringWithFormat:@"Local Notification failed: %@", error.description]]; + } + }]; + }else{ + [FirebasePlugin.firebasePlugin _logError:@"processMessageForForegroundNotification: cannot show notification as permission denied"]; + } + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } + }]; +} + +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + [FirebasePlugin.firebasePlugin _logError:[NSString stringWithFormat:@"didFailToRegisterForRemoteNotificationsWithError: %@", error.description]]; +} + +// Asks the delegate how to handle a notification that arrived while the app was running in the foreground +// Called when an APS notification arrives when app is in foreground +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + willPresentNotification:(UNNotification *)notification + withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler { + + @try{ + + if (![notification.request.trigger isKindOfClass:UNPushNotificationTrigger.class] && ![notification.request.trigger isKindOfClass:UNTimeIntervalNotificationTrigger.class]){ + [FirebasePlugin.firebasePlugin _logError:@"willPresentNotification: aborting as not a supported UNNotificationTrigger"]; + return; + } + + [[FIRMessaging messaging] appDidReceiveMessage:notification.request.content.userInfo]; + + mutableUserInfo = [notification.request.content.userInfo mutableCopy]; + + NSString* messageType = [mutableUserInfo objectForKey:@"messageType"]; + if(![messageType isEqualToString:@"data"]){ + [mutableUserInfo setValue:@"notification" forKey:@"messageType"]; + } + + // Print full message. + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"willPresentNotification: %@", mutableUserInfo]]; + + + NSDictionary* aps = [mutableUserInfo objectForKey:@"aps"]; + bool isContentAvailable = [[aps objectForKey:@"content-available"] isEqualToNumber:[NSNumber numberWithInt:1]]; + if(isContentAvailable){ + [FirebasePlugin.firebasePlugin _logError:@"willPresentNotification: aborting as content-available:1 so system notification will be shown"]; + return; + } + + bool showForegroundNotification = [mutableUserInfo objectForKey:@"notification_foreground"]; + bool hasAlert = [aps objectForKey:@"alert"] != nil; + bool hasBadge = [aps objectForKey:@"badge"] != nil; + bool hasSound = [aps objectForKey:@"sound"] != nil; + + if(showForegroundNotification){ + [FirebasePlugin.firebasePlugin _logMessage:[NSString stringWithFormat:@"willPresentNotification: foreground notification alert=%@, badge=%@, sound=%@", hasAlert ? @"YES" : @"NO", hasBadge ? @"YES" : @"NO", hasSound ? @"YES" : @"NO"]]; + if(hasAlert && hasBadge && hasSound){ + completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionBadge + UNNotificationPresentationOptionSound); + }else if(hasAlert && hasBadge){ + completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionBadge); + }else if(hasAlert && hasSound){ + completionHandler(UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound); + }else if(hasBadge && hasSound){ + completionHandler(UNNotificationPresentationOptionBadge + UNNotificationPresentationOptionSound); + }else if(hasAlert){ + completionHandler(UNNotificationPresentationOptionAlert); + }else if(hasBadge){ + completionHandler(UNNotificationPresentationOptionBadge); + }else if(hasSound){ + completionHandler(UNNotificationPresentationOptionSound); + } + }else{ + [FirebasePlugin.firebasePlugin _logMessage:@"willPresentNotification: foreground notification not set"]; + } + + if(![messageType isEqualToString:@"data"]){ + [FirebasePlugin.firebasePlugin sendNotification:mutableUserInfo]; + } + + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +// Asks the delegate to process the user's response to a delivered notification. +// Called when user taps on system notification +- (void) userNotificationCenter:(UNUserNotificationCenter *)center + didReceiveNotificationResponse:(UNNotificationResponse *)response + withCompletionHandler:(void (^)(void))completionHandler +{ + @try{ + + if (![response.notification.request.trigger isKindOfClass:UNPushNotificationTrigger.class] && ![response.notification.request.trigger isKindOfClass:UNTimeIntervalNotificationTrigger.class]){ + [FirebasePlugin.firebasePlugin _logMessage:@"didReceiveNotificationResponse: aborting as not a supported UNNotificationTrigger"]; + return; + } + + [[FIRMessaging messaging] appDidReceiveMessage:response.notification.request.content.userInfo]; + + mutableUserInfo = [response.notification.request.content.userInfo mutableCopy]; + + NSString* tap; + if([self.applicationInBackground isEqual:[NSNumber numberWithBool:YES]]){ + tap = @"background"; + }else{ + tap = @"foreground"; + + } + [mutableUserInfo setValue:tap forKey:@"tap"]; + if([mutableUserInfo objectForKey:@"messageType"] == nil){ + [mutableUserInfo setValue:@"notification" forKey:@"messageType"]; + } + + // Dynamic Actions + if (response.actionIdentifier && ![response.actionIdentifier isEqual:UNNotificationDefaultActionIdentifier]) { + [mutableUserInfo setValue:response.actionIdentifier forKey:@"action"]; + } + + // Print full message. + [FirebasePlugin.firebasePlugin _logInfo:[NSString stringWithFormat:@"didReceiveNotificationResponse: %@", mutableUserInfo]]; + + [FirebasePlugin.firebasePlugin sendNotification:mutableUserInfo]; + + completionHandler(); + + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +// Receive data message on iOS 10 devices. +- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { + // Print full message + [FirebasePlugin.firebasePlugin _logInfo:[NSString stringWithFormat:@"applicationReceivedRemoteMessage: %@", [remoteMessage appData]]]; +} + +// Apple Sign In +- (void)authorizationController:(ASAuthorizationController *)controller + didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) { + @try{ + CDVPluginResult* pluginResult; + NSString* errorMessage = nil; + FIROAuthCredential *credential; + + if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) { + ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential; + NSString *rawNonce = [FirebasePlugin appleSignInNonce]; + if(rawNonce == nil){ + errorMessage = @"Invalid state: A login callback was received, but no login request was sent."; + }else if (appleIDCredential.identityToken == nil) { + errorMessage = @"Unable to fetch identity token."; + }else{ + NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken + encoding:NSUTF8StringEncoding]; + if (idToken == nil) { + errorMessage = [NSString stringWithFormat:@"Unable to serialize id token from data: %@", appleIDCredential.identityToken]; + }else{ + // Initialize a Firebase credential. + credential = [FIROAuthProvider credentialWithProviderID:@"apple.com" + IDToken:idToken + rawNonce:rawNonce]; + + int key = [[FirebasePlugin firebasePlugin] saveAuthCredential:credential]; + NSMutableDictionary* result = [[NSMutableDictionary alloc] init]; + [result setValue:@"true" forKey:@"instantVerification"]; + [result setValue:[NSNumber numberWithInt:key] forKey:@"id"]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result]; + } + } + if(errorMessage != nil){ + [FirebasePlugin.firebasePlugin _logError:errorMessage]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage]; + } + if ([FirebasePlugin firebasePlugin].appleSignInCallbackId != nil) { + [[FirebasePlugin firebasePlugin].commandDelegate sendPluginResult:pluginResult callbackId:[FirebasePlugin firebasePlugin].appleSignInCallbackId]; + } + } + }@catch (NSException *exception) { + [FirebasePlugin.firebasePlugin handlePluginExceptionWithoutContext:exception]; + } +} + +- (void)authorizationController:(ASAuthorizationController *)controller + didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) { + NSString* errorMessage = [NSString stringWithFormat:@"Sign in with Apple errored: %@", error]; + [FirebasePlugin.firebasePlugin _logError:errorMessage]; + if ([FirebasePlugin firebasePlugin].appleSignInCallbackId != nil) { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage]; + [[FirebasePlugin firebasePlugin].commandDelegate sendPluginResult:pluginResult callbackId:[FirebasePlugin firebasePlugin].appleSignInCallbackId]; + } +} + +- (nonnull ASPresentationAnchor)presentationAnchorForAuthorizationController:(nonnull ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){ + return self.viewController.view.window; +} + +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePlugin.h b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePlugin.h new file mode 100644 index 00000000..2a65108d --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePlugin.h @@ -0,0 +1,119 @@ +#import <Cordova/CDV.h> +#import "AppDelegate.h" +#import "Firebase.h" +@import FirebaseFirestore; + +@interface FirebasePlugin : CDVPlugin + +- (void)setAutoInitEnabled:(CDVInvokedUrlCommand*)command; +- (void)isAutoInitEnabled:(CDVInvokedUrlCommand*)command; + +// Authentication +- (void)verifyPhoneNumber:(CDVInvokedUrlCommand*)command; +- (void)createUserWithEmailAndPassword:(CDVInvokedUrlCommand*)command; +- (void)signInUserWithEmailAndPassword:(CDVInvokedUrlCommand*)command; +- (void)signInUserWithCustomToken:(CDVInvokedUrlCommand*)command; +- (void)signInUserAnonymously:(CDVInvokedUrlCommand*)command; +- (void)authenticateUserWithGoogle:(CDVInvokedUrlCommand*)command; +- (void)authenticateUserWithApple:(CDVInvokedUrlCommand*)command; +- (void)signInWithCredential:(CDVInvokedUrlCommand*)command; +- (void)linkUserWithCredential:(CDVInvokedUrlCommand*)command; +- (void)reauthenticateWithCredential:(CDVInvokedUrlCommand*)command; +- (void)isUserSignedIn:(CDVInvokedUrlCommand*)command; +- (void)signOutUser:(CDVInvokedUrlCommand*)command; +- (void)getCurrentUser:(CDVInvokedUrlCommand*)command; +- (void)reloadCurrentUser:(CDVInvokedUrlCommand*)command; +- (void)updateUserProfile:(CDVInvokedUrlCommand*)command; +- (void)updateUserEmail:(CDVInvokedUrlCommand*)command; +- (void)sendUserEmailVerification:(CDVInvokedUrlCommand*)command; +- (void)updateUserPassword:(CDVInvokedUrlCommand*)command; +- (void)sendUserPasswordResetEmail:(CDVInvokedUrlCommand*)command; +- (void)deleteUser:(CDVInvokedUrlCommand*)command; + +// Remote notifications +- (void)getId:(CDVInvokedUrlCommand*)command; +- (void)getToken:(CDVInvokedUrlCommand*)command; +- (void)getAPNSToken:(CDVInvokedUrlCommand*)command; +- (NSString *)hexadecimalStringFromData:(NSData *)data; +- (void)grantPermission:(CDVInvokedUrlCommand*)command; +- (void)hasPermission:(CDVInvokedUrlCommand*)command; +- (void)setBadgeNumber:(CDVInvokedUrlCommand*)command; +- (void)getBadgeNumber:(CDVInvokedUrlCommand*)command; +- (void)subscribe:(CDVInvokedUrlCommand*)command; +- (void)unsubscribe:(CDVInvokedUrlCommand*)command; +- (void)unregister:(CDVInvokedUrlCommand*)command; +- (void)onMessageReceived:(CDVInvokedUrlCommand*)command; +- (void)onTokenRefresh:(CDVInvokedUrlCommand*)command; +- (void)onApnsTokenReceived:(CDVInvokedUrlCommand *)command; +- (void)sendNotification:(NSDictionary*)userInfo; +- (void)sendToken:(NSString*)token; +- (void)sendApnsToken:(NSString*)token; +- (void)clearAllNotifications:(CDVInvokedUrlCommand *)command; + +// Analytics +- (void)setAnalyticsCollectionEnabled:(CDVInvokedUrlCommand*)command; +- (void)isAnalyticsCollectionEnabled:(CDVInvokedUrlCommand*)command; +- (void)logEvent:(CDVInvokedUrlCommand*)command; +- (void)setScreenName:(CDVInvokedUrlCommand*)command; +- (void)setUserId:(CDVInvokedUrlCommand*)command; +- (void)setUserProperty:(CDVInvokedUrlCommand*)command; + +// Crashlytics +- (void)setCrashlyticsCollectionEnabled:(CDVInvokedUrlCommand*)command; +- (void)isCrashlyticsCollectionEnabled:(CDVInvokedUrlCommand*)command; +- (void)logError:(CDVInvokedUrlCommand*)command; +- (void)logMessage:(CDVInvokedUrlCommand*)command; +- (void)sendCrash:(CDVInvokedUrlCommand*)command; +- (void)setCrashlyticsUserId:(CDVInvokedUrlCommand*)command; + +// Remote config +- (void)fetch:(CDVInvokedUrlCommand*)command; +- (void)activateFetched:(CDVInvokedUrlCommand*)command; +- (void)getValue:(CDVInvokedUrlCommand*)command; +- (void)getInfo:(CDVInvokedUrlCommand*)command; + +// Performance +- (void)setPerformanceCollectionEnabled:(CDVInvokedUrlCommand*)command; +- (void)isPerformanceCollectionEnabled:(CDVInvokedUrlCommand*)command; +- (void)startTrace:(CDVInvokedUrlCommand*)command; +- (void)incrementCounter:(CDVInvokedUrlCommand*)command; +- (void)stopTrace:(CDVInvokedUrlCommand*)command; + +// Firestore +- (void)addDocumentToFirestoreCollection:(CDVInvokedUrlCommand*)command; +- (void)setDocumentInFirestoreCollection:(CDVInvokedUrlCommand*)command; +- (void)updateDocumentInFirestoreCollection:(CDVInvokedUrlCommand*)command; +- (void)deleteDocumentFromFirestoreCollection:(CDVInvokedUrlCommand*)command; +- (void)documentExistsInFirestoreCollection:(CDVInvokedUrlCommand*)command; +- (void)fetchDocumentInFirestoreCollection:(CDVInvokedUrlCommand*)command; +- (void)fetchFirestoreCollection:(CDVInvokedUrlCommand*)command; + + +// Internals ++ (FirebasePlugin *) firebasePlugin; ++ (NSString*) appleSignInNonce; ++ (void) setFirestore:(FIRFirestore*) firestoreInstance; +- (void) handlePluginExceptionWithContext: (NSException*) exception :(CDVInvokedUrlCommand*)command; +- (void) handlePluginExceptionWithoutContext: (NSException*) exception; +- (void) _logError: (NSString*)msg; +- (void) _logInfo: (NSString*)msg; +- (void) _logMessage: (NSString*)msg; +- (BOOL) _shouldEnableCrashlytics; +- (int) saveAuthCredential: (FIRAuthCredential *) authCredential; +- (void)executeGlobalJavascript: (NSString*)jsString; + +- (void)createChannel:(CDVInvokedUrlCommand *)command; +- (void)setDefaultChannel:(CDVInvokedUrlCommand *)command; +- (void)deleteChannel:(CDVInvokedUrlCommand *)command; +- (void)listChannels:(CDVInvokedUrlCommand *)command; + +@property (nonatomic, copy) NSString *notificationCallbackId; +@property (nonatomic, copy) NSString *tokenRefreshCallbackId; +@property (nonatomic, copy) NSString *apnsTokenRefreshCallbackId; +@property (nonatomic, copy) NSString *googleSignInCallbackId; +@property (nonatomic, copy) NSString *appleSignInCallbackId; + +@property (nonatomic, retain) NSMutableArray *notificationStack; +@property (nonatomic, readwrite) NSMutableDictionary* traces; + +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePlugin.m b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePlugin.m new file mode 100644 index 00000000..e72514c0 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePlugin.m @@ -0,0 +1,1757 @@ +#import "FirebasePlugin.h" +#import "FirebasePluginMessageReceiverManager.h" +#import "AppDelegate+FirebasePlugin.h" +#import <Cordova/CDV.h> +#import "AppDelegate.h" +#import <GoogleSignIn/GoogleSignIn.h> +@import FirebaseInstanceID; +@import FirebaseMessaging; +@import FirebaseAnalytics; +@import FirebaseRemoteConfig; +@import FirebasePerformance; +@import FirebaseAuth; +@import UserNotifications; +@import CommonCrypto; +@import AuthenticationServices; + +@implementation FirebasePlugin + +@synthesize notificationCallbackId; +@synthesize tokenRefreshCallbackId; +@synthesize apnsTokenRefreshCallbackId; +@synthesize googleSignInCallbackId; +@synthesize appleSignInCallbackId; +@synthesize notificationStack; +@synthesize traces; + +static NSString*const LOG_TAG = @"FirebasePlugin[native]"; +static NSInteger const kNotificationStackSize = 10; +static NSString*const FIREBASE_CRASHLYTICS_COLLECTION_ENABLED = @"FIREBASE_CRASHLYTICS_COLLECTION_ENABLED"; //preference +static NSString*const FirebaseCrashlyticsCollectionEnabled = @"FirebaseCrashlyticsCollectionEnabled"; //plist +static NSString*const FIREBASE_ANALYTICS_COLLECTION_ENABLED = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED"; +static NSString*const FIREBASE_PERFORMANCE_COLLECTION_ENABLED = @"FIREBASE_PERFORMANCE_COLLECTION_ENABLED"; + +static FirebasePlugin* firebasePlugin; +static BOOL registeredForRemoteNotifications = NO; +static NSMutableDictionary* authCredentials; +static NSString* currentNonce; // used for Apple Sign In +static FIRFirestore* firestore; +static NSUserDefaults* preferences; +static NSDictionary* googlePlist; + + ++ (FirebasePlugin*) firebasePlugin { + return firebasePlugin; +} + ++ (NSString*) appleSignInNonce { + return currentNonce; +} + ++ (void) setFirestore:(FIRFirestore*) firestoreInstance{ + firestore = firestoreInstance; +} + +// @override abstract +- (void)pluginInitialize { + NSLog(@"Starting Firebase plugin"); + firebasePlugin = self; + + @try { + preferences = [NSUserDefaults standardUserDefaults]; + googlePlist = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]]; + + if([self getGooglePlistFlagWithDefaultValue:FirebaseCrashlyticsCollectionEnabled defaultValue:YES]){ + [self setPreferenceFlag:FIREBASE_CRASHLYTICS_COLLECTION_ENABLED flag:YES]; + } + + if([self getGooglePlistFlagWithDefaultValue:FIREBASE_ANALYTICS_COLLECTION_ENABLED defaultValue:YES]){ + [self setPreferenceFlag:FIREBASE_ANALYTICS_COLLECTION_ENABLED flag:YES]; + } + + if([self getGooglePlistFlagWithDefaultValue:FIREBASE_PERFORMANCE_COLLECTION_ENABLED defaultValue:YES]){ + [self setPreferenceFlag:FIREBASE_PERFORMANCE_COLLECTION_ENABLED flag:YES]; + } + + // Set actionable categories if pn-actions.json exist in bundle + [self setActionableNotifications]; + + // Check for permission and register for remote notifications if granted + [self _hasPermission:^(BOOL result) {}]; + + [GIDSignIn sharedInstance].presentingViewController = self.viewController; + + authCredentials = [[NSMutableDictionary alloc] init]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithoutContext:exception]; + } +} + + +// Dynamic actions from pn-actions.json +- (void)setActionableNotifications { + + // Parse JSON + NSString *path = [[NSBundle mainBundle] pathForResource:@"pn-actions" ofType:@"json"]; + NSData *data = [NSData dataWithContentsOfFile:path]; + NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; + + // Assign actions for categories + NSMutableSet *categories = [[NSMutableSet alloc] init]; + NSArray *actionsArray = [dict objectForKey:@"PushNotificationActions"]; + for (NSDictionary *item in actionsArray) { + NSMutableArray *buttons = [NSMutableArray new]; + NSString *category = [item objectForKey:@"category"]; + + NSArray *actions = [item objectForKey:@"actions"]; + for (NSDictionary *action in actions) { + NSString *actionId = [action objectForKey:@"id"]; + NSString *actionTitle = [action objectForKey:@"title"]; + + [buttons addObject:[UNNotificationAction actionWithIdentifier:actionId + title:NSLocalizedString(actionTitle, nil) options:UNNotificationActionOptionNone]]; + } + + [categories addObject:[UNNotificationCategory categoryWithIdentifier:category + actions:buttons intentIdentifiers:@[] options:UNNotificationCategoryOptionNone]]; + } + + // Initialize categories + [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories]; +} + +// @override abstract +- (void)handleOpenURL:(NSNotification*)notification{ + NSURL* url = [notification object]; + [[GIDSignIn sharedInstance] handleURL:url]; +} + +- (void)setAutoInitEnabled:(CDVInvokedUrlCommand *)command { + @try { + bool enabled = [[command.arguments objectAtIndex:0] boolValue]; + [self runOnMainThread:^{ + @try { + [FIRMessaging messaging].autoInitEnabled = enabled; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)isAutoInitEnabled:(CDVInvokedUrlCommand *)command { + @try { + + [self runOnMainThread:^{ + @try { + bool enabled =[FIRMessaging messaging].isAutoInitEnabled; + + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:enabled]; + [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +/* + * Remote notifications + */ + +- (void)getId:(CDVInvokedUrlCommand *)command { + __block CDVPluginResult *pluginResult; + + FIRInstanceIDHandler handler = ^(NSString *_Nullable instID, NSError *_Nullable error) { + @try { + [self handleStringResultWithPotentialError:error command:command result:instID]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }; + + @try { + [[FIRInstanceID instanceID] getIDWithHandler:handler]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)getToken:(CDVInvokedUrlCommand *)command { + @try { + [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result, + NSError * _Nullable error) { + NSString* token = nil; + if (error == nil && result != nil && result.token != nil) { + token = result.token; + } + [self handleStringResultWithPotentialError:error command:command result:token]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)getAPNSToken:(CDVInvokedUrlCommand *)command { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[self getAPNSToken]]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; +} + +- (NSString *)getAPNSToken { + NSString* hexToken = nil; + NSData* apnsToken = [FIRMessaging messaging].APNSToken; + if (apnsToken) { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + // [deviceToken description] Starting with iOS 13 device token is like "{length = 32, bytes = 0xd3d997af 967d1f43 b405374a 13394d2f ... 28f10282 14af515f }" + hexToken = [self hexadecimalStringFromData:apnsToken]; +#else + hexToken = [[apnsToken.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""]; +#endif + } + return hexToken; +} + +- (NSString *)hexadecimalStringFromData:(NSData *)data +{ + NSUInteger dataLength = data.length; + if (dataLength == 0) { + return nil; + } + + const unsigned char *dataBuffer = data.bytes; + NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; + for (int i = 0; i < dataLength; ++i) { + [hexString appendFormat:@"%02x", dataBuffer[i]]; + } + return [hexString copy]; +} + +- (void)hasPermission:(CDVInvokedUrlCommand *)command { + @try { + [self _hasPermission:^(BOOL enabled) { + CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:enabled]; + [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +-(void)_hasPermission:(void (^)(BOOL result))completeBlock { + @try { + [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { + @try { + BOOL enabled = NO; + if (settings.alertSetting == UNNotificationSettingEnabled) { + enabled = YES; + [self registerForRemoteNotifications]; + } + NSLog(@"_hasPermission: %@", enabled ? @"YES" : @"NO"); + completeBlock(enabled); + }@catch (NSException *exception) { + [self handlePluginExceptionWithoutContext:exception]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithoutContext:exception]; + } +} + +- (void)grantPermission:(CDVInvokedUrlCommand *)command { + NSLog(@"grantPermission"); + @try { + [self _hasPermission:^(BOOL enabled) { + @try { + if(enabled){ + NSString* message = @"Permission is already granted - call hasPermission() to check before calling grantPermission()"; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:message]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }else{ + [UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate> _Nullable) self; + UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert|UNAuthorizationOptionSound|UNAuthorizationOptionBadge; + [[UNUserNotificationCenter currentNotificationCenter] + requestAuthorizationWithOptions:authOptions + completionHandler:^(BOOL granted, NSError * _Nullable error) { + @try { + NSLog(@"requestAuthorizationWithOptions: granted=%@", granted ? @"YES" : @"NO"); + if (error == nil && granted) { + [self registerForRemoteNotifications]; + } + [self handleBoolResultWithPotentialError:error command:command result:granted]; + + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + } + ]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)registerForRemoteNotifications { + NSLog(@"registerForRemoteNotifications"); + if(registeredForRemoteNotifications) return; + + [self runOnMainThread:^{ + @try { + [[UIApplication sharedApplication] registerForRemoteNotifications]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithoutContext:exception]; + } + registeredForRemoteNotifications = YES; + }]; +} + +- (void)setBadgeNumber:(CDVInvokedUrlCommand *)command { + @try { + int number = [[command.arguments objectAtIndex:0] intValue]; + [self runOnMainThread:^{ + @try { + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:number]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)getBadgeNumber:(CDVInvokedUrlCommand *)command { + [self runOnMainThread:^{ + @try { + long badge = [[UIApplication sharedApplication] applicationIconBadgeNumber]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:badge]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)subscribe:(CDVInvokedUrlCommand *)command { + @try { + NSString* topic = [NSString stringWithFormat:@"%@", [command.arguments objectAtIndex:0]]; + + [[FIRMessaging messaging] subscribeToTopic: topic completion:^(NSError * _Nullable error) { + [self handleEmptyResultWithPotentialError:error command:command]; + }]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)unsubscribe:(CDVInvokedUrlCommand *)command { + @try { + NSString* topic = [NSString stringWithFormat:@"%@", [command.arguments objectAtIndex:0]]; + + [[FIRMessaging messaging] unsubscribeFromTopic: topic completion:^(NSError * _Nullable error) { + [self handleEmptyResultWithPotentialError:error command:command]; + }]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)unregister:(CDVInvokedUrlCommand *)command { + @try { + [[FIRInstanceID instanceID] deleteIDWithHandler:^void(NSError *_Nullable error) { + [self handleEmptyResultWithPotentialError:error command:command]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + + + +- (void)onMessageReceived:(CDVInvokedUrlCommand *)command { + @try { + self.notificationCallbackId = command.callbackId; + + if (self.notificationStack != nil && [self.notificationStack count]) { + for (NSDictionary *userInfo in self.notificationStack) { + [self sendNotification:userInfo]; + } + [self.notificationStack removeAllObjects]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)onTokenRefresh:(CDVInvokedUrlCommand *)command { + self.tokenRefreshCallbackId = command.callbackId; + @try { + [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result, + NSError * _Nullable error) { + @try { + if (result.token != nil && error == nil) { + [self sendToken:result.token]; + }else{ + [self handleStringResultWithPotentialError:error command:command result:result.token]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)onApnsTokenReceived:(CDVInvokedUrlCommand *)command { + self.apnsTokenRefreshCallbackId = command.callbackId; + @try { + NSString* apnsToken = [self getAPNSToken]; + if(apnsToken != nil){ + [self sendApnsToken:apnsToken]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)sendNotification:(NSDictionary *)userInfo { + @try { + if([FirebasePluginMessageReceiverManager sendNotification:userInfo]){ + [self _logMessage:@"Message handled by custom receiver"]; + return; + } + if (self.notificationCallbackId != nil) { + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:userInfo]; + [pluginResult setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.notificationCallbackId]; + } else { + if (!self.notificationStack) { + self.notificationStack = [[NSMutableArray alloc] init]; + } + + // stack notifications until a callback has been registered + [self.notificationStack addObject:userInfo]; + + if ([self.notificationStack count] >= kNotificationStackSize) { + [self.notificationStack removeLastObject]; + } + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :self.commandDelegate]; + } +} + +- (void)sendToken:(NSString *)token { + @try { + if (self.tokenRefreshCallbackId != nil) { + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:token]; + [pluginResult setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.tokenRefreshCallbackId]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :self.commandDelegate]; + } +} + +- (void)sendApnsToken:(NSString *)token { + @try { + if (self.apnsTokenRefreshCallbackId != nil) { + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:token]; + [pluginResult setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:self.apnsTokenRefreshCallbackId]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :self.commandDelegate]; + } +} + +- (void)clearAllNotifications:(CDVInvokedUrlCommand *)command { + [self runOnMainThread:^{ + @try { + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]; + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +/* + * Authentication + */ +- (void)verifyPhoneNumber:(CDVInvokedUrlCommand *)command { + NSString* number = [command.arguments objectAtIndex:0]; + + @try { + [[FIRPhoneAuthProvider provider] + verifyPhoneNumber:number + UIDelegate:nil + completion:^(NSString *_Nullable verificationID, NSError *_Nullable error) { + + @try { + CDVPluginResult* pluginResult; + if (error) { + // Verification code not sent. + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description]; + } else { + // Successful. + NSMutableDictionary* result = [[NSMutableDictionary alloc] init]; + [result setValue:@"false" forKey:@"instantVerification"]; + [result setValue:verificationID forKey:@"verificationId"]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result]; + } + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)createUserWithEmailAndPassword:(CDVInvokedUrlCommand*)command { + @try { + NSString* email = [command.arguments objectAtIndex:0]; + NSString* password = [command.arguments objectAtIndex:1]; + [[FIRAuth auth] createUserWithEmail:email + password:password + completion:^(FIRAuthDataResult * _Nullable authResult, + NSError * _Nullable error) { + @try { + [self handleAuthResult:authResult error:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)signInUserWithEmailAndPassword:(CDVInvokedUrlCommand*)command { + @try { + NSString* email = [command.arguments objectAtIndex:0]; + NSString* password = [command.arguments objectAtIndex:1]; + [[FIRAuth auth] signInWithEmail:email + password:password + completion:^(FIRAuthDataResult * _Nullable authResult, + NSError * _Nullable error) { + @try { + [self handleAuthResult:authResult error:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)signInUserWithCustomToken:(CDVInvokedUrlCommand*)command { + @try { + NSString* customToken = [command.arguments objectAtIndex:0]; + [[FIRAuth auth] signInWithCustomToken:customToken + completion:^(FIRAuthDataResult * _Nullable authResult, + NSError * _Nullable error) { + @try { + [self handleAuthResult:authResult error:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)signInUserAnonymously:(CDVInvokedUrlCommand*)command { + @try { + [[FIRAuth auth] signInAnonymouslyWithCompletion:^(FIRAuthDataResult * _Nullable authResult, + NSError * _Nullable error) { + @try { + [self handleAuthResult:authResult error:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)authenticateUserWithGoogle:(CDVInvokedUrlCommand*)command{ + @try { + self.googleSignInCallbackId = command.callbackId; + [[GIDSignIn sharedInstance] signIn]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT]; + [pluginResult setKeepCallbackAsBool:YES]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)authenticateUserWithApple:(CDVInvokedUrlCommand*)command{ + @try { + CDVPluginResult *pluginResult; + if (@available(iOS 13.0, *)) { + self.appleSignInCallbackId = command.callbackId; + [self startSignInWithAppleFlow]; + + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_NO_RESULT]; + [pluginResult setKeepCallbackAsBool:YES]; + } else { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"OS version is too low - Apple Sign In requires iOS 13.0+"]; + } + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)signInWithCredential:(CDVInvokedUrlCommand*)command { + @try { + FIRAuthCredential* credential = [self obtainAuthCredential:[command.arguments objectAtIndex:0] command:command]; + if(credential == nil) return; + + [[FIRAuth auth] signInWithCredential:credential + completion:^(FIRAuthDataResult * _Nullable authResult, + NSError * _Nullable error) { + [self handleAuthResult:authResult error:error command:command]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)reauthenticateWithCredential:(CDVInvokedUrlCommand*)command{ + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + FIRAuthCredential* credential = [self obtainAuthCredential:[command.arguments objectAtIndex:0] command:command]; + if(credential == nil) return; + + [user reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { + [self handleAuthResult:authResult error:error command:command]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)linkUserWithCredential:(CDVInvokedUrlCommand*)command { + @try { + FIRAuthCredential* credential = [self obtainAuthCredential:[command.arguments objectAtIndex:0] command:command]; + if(credential == nil) return; + + [[FIRAuth auth].currentUser linkWithCredential:credential + completion:^(FIRAuthDataResult * _Nullable authResult, + NSError * _Nullable error) { + [self handleAuthResult:authResult error:error command:command]; + }]; + + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)isUserSignedIn:(CDVInvokedUrlCommand*)command { + @try { + bool isSignedIn = [FIRAuth auth].currentUser ? true : false; + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:isSignedIn] callbackId:command.callbackId]; + + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)signOutUser:(CDVInvokedUrlCommand*)command { + @try { + bool isSignedIn = [FIRAuth auth].currentUser ? true : false; + if(!isSignedIn){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + // Sign out of Google + if([[GIDSignIn sharedInstance] currentUser] != nil){ + [[GIDSignIn sharedInstance] signOut]; + } + + // Sign out of Firebase + NSError *signOutError; + BOOL status = [[FIRAuth auth] signOut:&signOutError]; + if (!status) { + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"Error signing out: %@", signOutError]] callbackId:command.callbackId]; + }else{ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)getCurrentUser:(CDVInvokedUrlCommand *)command { + + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + [self extractAndReturnUserInfo:command]; + + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)reloadCurrentUser:(CDVInvokedUrlCommand *)command { + + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + [user reloadWithCompletion:^(NSError * _Nullable error) { + if (error != nil) { + [self handleEmptyResultWithPotentialError:error command:command]; + }else { + [self extractAndReturnUserInfo:command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void) extractAndReturnUserInfo:(CDVInvokedUrlCommand *)command { + FIRUser* user = [FIRAuth auth].currentUser; + NSMutableDictionary* userInfo = [NSMutableDictionary new]; + [userInfo setValue:user.displayName forKey:@"name"]; + [userInfo setValue:user.email forKey:@"email"]; + [userInfo setValue:@(user.isEmailVerified ? true : false) forKey:@"emailIsVerified"]; + [userInfo setValue:user.phoneNumber forKey:@"phoneNumber"]; + [userInfo setValue:user.photoURL ? user.photoURL.absoluteString : nil forKey:@"photoUrl"]; + [userInfo setValue:user.uid forKey:@"uid"]; + [userInfo setValue:@(user.isAnonymous ? true : false) forKey:@"isAnonymous"]; + [user getIDTokenWithCompletion:^(NSString * _Nullable token, NSError * _Nullable error) { + [userInfo setValue:token forKey:@"idToken"]; + [user getIDTokenResultWithCompletion:^(FIRAuthTokenResult * _Nullable tokenResult, NSError * _Nullable error) { + [userInfo setValue:tokenResult.signInProvider forKey:@"providerId"]; + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:userInfo] callbackId:command.callbackId]; + }]; + }]; +} + +- (void)updateUserProfile:(CDVInvokedUrlCommand*)command { + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + NSDictionary* profile = [command.arguments objectAtIndex:0]; + + FIRUserProfileChangeRequest* changeRequest = [user profileChangeRequest]; + if([profile objectForKey:@"name"] != nil){ + changeRequest.displayName = [profile objectForKey:@"name"]; + } + if([profile objectForKey:@"photoUri"] != nil){ + changeRequest.photoURL = [NSURL URLWithString:[profile objectForKey:@"photoUri"]]; + } + + [changeRequest commitChangesWithCompletion:^(NSError *_Nullable error) { + @try { + [self handleEmptyResultWithPotentialError:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)updateUserEmail:(CDVInvokedUrlCommand*)command { + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + NSString* email = [command.arguments objectAtIndex:0]; + [user updateEmail:email completion:^(NSError *_Nullable error) { + @try { + [self handleEmptyResultWithPotentialError:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)sendUserEmailVerification:(CDVInvokedUrlCommand*)command{ + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + [user sendEmailVerificationWithCompletion:^(NSError *_Nullable error) { + @try { + [self handleEmptyResultWithPotentialError:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)updateUserPassword:(CDVInvokedUrlCommand*)command{ + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + NSString* password = [command.arguments objectAtIndex:0]; + [user updatePassword:password completion:^(NSError *_Nullable error) { + @try { + [self handleEmptyResultWithPotentialError:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)sendUserPasswordResetEmail:(CDVInvokedUrlCommand*)command{ + @try { + NSString* email = [command.arguments objectAtIndex:0]; + [[FIRAuth auth] sendPasswordResetWithEmail:email completion:^(NSError *_Nullable error) { + @try { + [self handleEmptyResultWithPotentialError:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)deleteUser:(CDVInvokedUrlCommand*)command{ + @try { + FIRUser* user = [FIRAuth auth].currentUser; + if(!user){ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"No user is currently signed"] callbackId:command.callbackId]; + return; + } + + [user deleteWithCompletion:^(NSError *_Nullable error) { + @try { + [self handleEmptyResultWithPotentialError:error command:command]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)startSignInWithAppleFlow API_AVAILABLE(ios(13.0)){ + NSString *nonce = [self randomNonce:32]; + currentNonce = nonce; + ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; + ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest]; + request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; + request.nonce = [self stringBySha256HashingString:nonce]; + + ASAuthorizationController *authorizationController = + [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; + authorizationController.delegate = [AppDelegate instance]; + authorizationController.presentationContextProvider = [AppDelegate instance]; + [authorizationController performRequests]; +} + +- (NSString *)stringBySha256HashingString:(NSString *)input { + const char *string = [input UTF8String]; + unsigned char result[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(string, (CC_LONG)strlen(string), result); + + NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; + for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { + [hashed appendFormat:@"%02x", result[i]]; + } + return hashed; +} + +// Generates random nonce for Apple Sign In +- (NSString *)randomNonce:(NSInteger)length { + NSAssert(length > 0, @"Expected nonce to have positive length"); + NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._"; + NSMutableString *result = [NSMutableString string]; + NSInteger remainingLength = length; + + while (remainingLength > 0) { + NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16]; + for (NSInteger i = 0; i < 16; i++) { + uint8_t random = 0; + int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random); + NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode); + + [randoms addObject:@(random)]; + } + + for (NSNumber *random in randoms) { + if (remainingLength == 0) { + break; + } + + if (random.unsignedIntValue < characterSet.length) { + unichar character = [characterSet characterAtIndex:random.unsignedIntValue]; + [result appendFormat:@"%C", character]; + remainingLength--; + } + } + } + + return result; +} + +/* + * Analytics + */ +- (void)setAnalyticsCollectionEnabled:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + BOOL enabled = [[command argumentAtIndex:0] boolValue]; + CDVPluginResult* pluginResult; + [FIRAnalytics setAnalyticsCollectionEnabled:enabled]; + [self setPreferenceFlag:FIREBASE_ANALYTICS_COLLECTION_ENABLED flag:enabled]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)isAnalyticsCollectionEnabled:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate runInBackground:^{ + @try { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[self getPreferenceFlag:FIREBASE_ANALYTICS_COLLECTION_ENABLED]]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)logEvent:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* name = [command.arguments objectAtIndex:0]; + NSDictionary *parameters = [command argumentAtIndex:1]; + + [FIRAnalytics logEventWithName:name parameters:parameters]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)setScreenName:(CDVInvokedUrlCommand *)command { + @try { + NSString* name = [command.arguments objectAtIndex:0]; + + [FIRAnalytics setScreenName:name screenClass:NULL]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (void)setUserId:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* id = [command.arguments objectAtIndex:0]; + + [FIRAnalytics setUserID:id]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)setUserProperty:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* name = [command.arguments objectAtIndex:0]; + NSString* value = [command.arguments objectAtIndex:1]; + + [FIRAnalytics setUserPropertyString:value forName:name]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +/* + * Crashlytics + */ + +- (void)setCrashlyticsCollectionEnabled:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + BOOL enabled = [[command argumentAtIndex:0] boolValue]; + CDVPluginResult* pluginResult; + [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:enabled]; + [self setPreferenceFlag:FIREBASE_CRASHLYTICS_COLLECTION_ENABLED flag:enabled]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)isCrashlyticsCollectionEnabled:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate runInBackground:^{ + @try { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[self isCrashlyticsEnabled]]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +-(BOOL)isCrashlyticsEnabled{ + return [self getPreferenceFlag:FIREBASE_CRASHLYTICS_COLLECTION_ENABLED]; +} + +- (void)logError:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + NSString* errorMessage = [command.arguments objectAtIndex:0]; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + @try { + if(![self isCrashlyticsEnabled]){ + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot log error - Crashlytics collection is disabled"]; + } + // We can optionally be passed a stack trace from stackTrace.js which we'll put in userInfo. + else if ([command.arguments count] > 1) { + NSArray* stackFrames = [command.arguments objectAtIndex:1]; + + NSString* message = errorMessage; + NSString* name = @"Uncaught Javascript exception"; + NSMutableArray *customFrames = [[NSMutableArray alloc] init]; + FIRExceptionModel *exceptionModel = [FIRExceptionModel exceptionModelWithName:name reason:message]; + + for (NSDictionary* stackFrame in stackFrames) { + FIRStackFrame *customFrame = [FIRStackFrame stackFrameWithSymbol:stackFrame[@"functionName"] file:stackFrame[@"fileName"] line:(uint32_t) [stackFrame[@"lineNumber"] intValue]]; + [customFrames addObject:customFrame]; + } + exceptionModel.stackTrace = customFrames; + [[FIRCrashlytics crashlytics] recordExceptionModel:exceptionModel]; + }else{ + //TODO detect and handle non-stack userInfo and pass to recordError + NSMutableDictionary* userInfo = [[NSMutableDictionary alloc] init]; + NSError *error = [NSError errorWithDomain:errorMessage code:0 userInfo:userInfo]; + [[FIRCrashlytics crashlytics] recordError:error]; + } + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + } @catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + + }]; +} + +- (void)logMessage:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate runInBackground:^{ + @try { + NSString* message = [command argumentAtIndex:0 withDefault:@""]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + if(![self isCrashlyticsEnabled]){ + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot log message - Crashlytics collection is disabled"]; + }else if(message){ + [[FIRCrashlytics crashlytics] logWithFormat:@"%@", message]; + } + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)sendCrash:(CDVInvokedUrlCommand*)command{ + assert(NO); +} + +- (void)setCrashlyticsUserId:(CDVInvokedUrlCommand *)command { + @try { + NSString* userId = [command.arguments objectAtIndex:0]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + if(![self isCrashlyticsEnabled]){ + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot set user ID - Crashlytics collection is disabled"]; + }else{ + [[FIRCrashlytics crashlytics] setUserID:userId]; + } + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +/* + * Remote config + */ +- (void)fetch:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + FIRRemoteConfig* remoteConfig = [FIRRemoteConfig remoteConfig]; + + if ([command.arguments count] > 0) { + int expirationDuration = [[command.arguments objectAtIndex:0] intValue]; + + [remoteConfig fetchWithExpirationDuration:expirationDuration completionHandler:^(FIRRemoteConfigFetchStatus status, NSError * _Nullable error) { + if (status == FIRRemoteConfigFetchStatusSuccess && error == nil){ + [self sendPluginSuccess:command]; + }else if (error != nil) { + [self handleEmptyResultWithPotentialError:error command:command]; + } else { + [self sendPluginError:command]; + } + }]; + } else { + [remoteConfig fetchWithCompletionHandler:^(FIRRemoteConfigFetchStatus status, NSError * _Nullable error) { + if (status == FIRRemoteConfigFetchStatusSuccess && error == nil){ + [self sendPluginSuccess:command]; + }else if (error != nil) { + [self handleEmptyResultWithPotentialError:error command:command]; + } else { + [self sendPluginError:command]; + } + }]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)activateFetched:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + FIRRemoteConfig* remoteConfig = [FIRRemoteConfig remoteConfig]; + [remoteConfig activateWithCompletion:^(BOOL changed, NSError* _Nullable error) { + [self handleBoolResultWithPotentialError:error command:command result:true]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)getValue:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* key = [command.arguments objectAtIndex:0]; + FIRRemoteConfig* remoteConfig = [FIRRemoteConfig remoteConfig]; + NSString* value = remoteConfig[key].stringValue; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:value]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)getInfo:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + FIRRemoteConfig* remoteConfig = [FIRRemoteConfig remoteConfig]; + NSInteger minimumFetchInterval = remoteConfig.configSettings.minimumFetchInterval; + NSInteger fetchTimeout = remoteConfig.configSettings.fetchTimeout; + NSDate* lastFetchTime = remoteConfig.lastFetchTime; + FIRRemoteConfigFetchStatus lastFetchStatus = remoteConfig.lastFetchStatus; + // isDeveloperModeEnabled is deprecated new recommnded way to check is minimumFetchInterval == 0 + BOOL isDeveloperModeEnabled = minimumFetchInterval == 0 ? true : false; + + NSDictionary* configSettings = @{ + @"developerModeEnabled": [NSNumber numberWithBool:isDeveloperModeEnabled], + @"minimumFetchInterval": [NSNumber numberWithInteger:minimumFetchInterval], + @"fetchTimeout": [NSNumber numberWithInteger:fetchTimeout], + }; + + NSDictionary* infoObject = @{ + @"configSettings": configSettings, + @"fetchTimeMillis": (lastFetchTime ? [NSNumber numberWithInteger:(lastFetchTime.timeIntervalSince1970 * 1000)] : [NSNull null]), + @"lastFetchStatus": [NSNumber numberWithInteger:(lastFetchStatus)], + }; + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:infoObject]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +/* + * Performance + */ +- (void)setPerformanceCollectionEnabled:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + BOOL enabled = [[command argumentAtIndex:0] boolValue]; + CDVPluginResult* pluginResult; + [[FIRPerformance sharedInstance] setDataCollectionEnabled:enabled]; + [self setPreferenceFlag:FIREBASE_PERFORMANCE_COLLECTION_ENABLED flag:enabled]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)isPerformanceCollectionEnabled:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate runInBackground:^{ + @try { + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[self getPreferenceFlag:FIREBASE_PERFORMANCE_COLLECTION_ENABLED]]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)startTrace:(CDVInvokedUrlCommand *)command { + + [self.commandDelegate runInBackground:^{ + @try { + NSString* traceName = [command.arguments objectAtIndex:0]; + FIRTrace *trace = [self.traces objectForKey:traceName]; + + if ( self.traces == nil) { + self.traces = [NSMutableDictionary new]; + } + + if (trace == nil) { + trace = [FIRPerformance startTraceWithName:traceName]; + [self.traces setObject:trace forKey:traceName ]; + + } + + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)incrementCounter:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* traceName = [command.arguments objectAtIndex:0]; + NSString* counterNamed = [command.arguments objectAtIndex:1]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + FIRTrace *trace = (FIRTrace*)[self.traces objectForKey:traceName]; + + if (trace != nil) { + [trace incrementMetric:counterNamed byInt:1]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + } else { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Trace not found"]; + } + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)stopTrace:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* traceName = [command.arguments objectAtIndex:0]; + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + FIRTrace *trace = [self.traces objectForKey:traceName]; + + if (trace != nil) { + [trace stop]; + [self.traces removeObjectForKey:traceName]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + } else { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Trace not found"]; + } + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +/* +* Firestore +*/ + +- (void)addDocumentToFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSDictionary* document = [command.arguments objectAtIndex:0]; + NSString* collection = [command.arguments objectAtIndex:1]; + __block FIRDocumentReference *ref = + [[firestore collectionWithPath:collection] addDocumentWithData:document completion:^(NSError * _Nullable error) { + [self handleStringResultWithPotentialError:error command:command result:ref.documentID]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)setDocumentInFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* documentId = [command.arguments objectAtIndex:0]; + NSDictionary* document = [command.arguments objectAtIndex:1]; + NSString* collection = [command.arguments objectAtIndex:2]; + + [[[firestore collectionWithPath:collection] documentWithPath:documentId] setData:document completion:^(NSError * _Nullable error) { + [self handleEmptyResultWithPotentialError:error command:command]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)updateDocumentInFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* documentId = [command.arguments objectAtIndex:0]; + NSDictionary* document = [command.arguments objectAtIndex:1]; + NSString* collection = [command.arguments objectAtIndex:2]; + + FIRDocumentReference* docRef = [[firestore collectionWithPath:collection] documentWithPath:documentId]; + if(docRef != nil){ + [docRef updateData:document completion:^(NSError * _Nullable error) { + [self handleEmptyResultWithPotentialError:error command:command]; + }]; + }else{ + [self sendPluginErrorWithMessage:@"Document not found in collection":command]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)deleteDocumentFromFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* documentId = [command.arguments objectAtIndex:0]; + NSString* collection = [command.arguments objectAtIndex:1]; + + [[[firestore collectionWithPath:collection] documentWithPath:documentId] + deleteDocumentWithCompletion:^(NSError * _Nullable error) { + [self handleEmptyResultWithPotentialError:error command:command]; + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)documentExistsInFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* documentId = [command.arguments objectAtIndex:0]; + NSString* collection = [command.arguments objectAtIndex:1]; + + FIRDocumentReference* docRef = [[firestore collectionWithPath:collection] documentWithPath:documentId]; + if(docRef != nil){ + [docRef getDocumentWithCompletion:^(FIRDocumentSnapshot * _Nullable snapshot, NSError * _Nullable error) { + BOOL docExists = snapshot.data != nil; + [self handleBoolResultWithPotentialError:error command:command result:docExists]; + }]; + }else{ + [self sendPluginErrorWithMessage:@"Collection not found":command]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)fetchDocumentInFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* documentId = [command.arguments objectAtIndex:0]; + NSString* collection = [command.arguments objectAtIndex:1]; + + FIRDocumentReference* docRef = [[firestore collectionWithPath:collection] documentWithPath:documentId]; + if(docRef != nil){ + [docRef getDocumentWithCompletion:^(FIRDocumentSnapshot * _Nullable snapshot, NSError * _Nullable error) { + if (error != nil) { + [self sendPluginErrorWithMessage:error.localizedDescription:command]; + } else if(snapshot.data != nil) { + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:snapshot.data] callbackId:command.callbackId]; + }else{ + [self sendPluginErrorWithMessage:@"Document not found in collection":command]; + } + }]; + }else{ + [self sendPluginErrorWithMessage:@"Collection not found":command]; + } + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +- (void)fetchFirestoreCollection:(CDVInvokedUrlCommand*)command { + [self.commandDelegate runInBackground:^{ + @try { + NSString* collection = [command.arguments objectAtIndex:0]; + NSArray* filters = [command.arguments objectAtIndex:1]; + FIRQuery* query = [firestore collectionWithPath:collection]; + + for (int i = 0; i < [filters count]; i++) { + NSArray* filter = [filters objectAtIndex:i]; + if ([[filter objectAtIndex:0] isEqualToString:@"where"]) { + if ([[filter objectAtIndex:2] isEqualToString:@"=="]) { + query = [query queryWhereField:[filter objectAtIndex:1] isEqualTo:[filter objectAtIndex:3]]; + } + if ([[filter objectAtIndex:2] isEqualToString:@"<"]) { + query = [query queryWhereField:[filter objectAtIndex:1] isLessThan:[filter objectAtIndex:3]]; + } + if ([[filter objectAtIndex:2] isEqualToString:@">"]) { + query = [query queryWhereField:[filter objectAtIndex:1] isGreaterThan:[filter objectAtIndex:3]]; + } + if ([[filter objectAtIndex:2] isEqualToString:@"<="]) { + query = [query queryWhereField:[filter objectAtIndex:1] isLessThanOrEqualTo:[filter objectAtIndex:3]]; + } + if ([[filter objectAtIndex:2] isEqualToString:@">="]) { + query = [query queryWhereField:[filter objectAtIndex:1] isGreaterThanOrEqualTo:[filter objectAtIndex:3]]; + } + if ([[filter objectAtIndex:2] isEqualToString:@"array-contains"]) { + query = [query queryWhereField:[filter objectAtIndex:1] arrayContains:[filter objectAtIndex:3]]; + } + continue; + } + if ([[filter objectAtIndex:0] isEqualToString:@"orderBy"]) { + query = [query queryOrderedByField:[filter objectAtIndex:1] descending:([[filter objectAtIndex:2] isEqualToString:@"desc"])]; + continue; + } + if ([[filter objectAtIndex:0] isEqualToString:@"startAt"]) { + query = [query queryStartingAtValues:[filter objectAtIndex:1]]; + continue; + } + if ([[filter objectAtIndex:0] isEqualToString:@"endAt"]) { + query = [query queryEndingAtValues:[filter objectAtIndex:1]]; + continue; + } + if ([[filter objectAtIndex:0] isEqualToString:@"limit"]) { + query = [query queryLimitedTo:[(NSNumber *)[filter objectAtIndex:1] integerValue]]; + continue; + } + } + + [query getDocumentsWithCompletion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) { + if (error != nil) { + [self sendPluginErrorWithMessage:error.localizedDescription:command]; + } else { + NSMutableDictionary* documents = [[NSMutableDictionary alloc] init];; + for (FIRDocumentSnapshot *document in snapshot.documents) { + [documents setObject:document.data forKey:document.documentID]; + } + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:documents] callbackId:command.callbackId]; + } + }]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } + }]; +} + +/********************************/ +#pragma mark - utility functions +/********************************/ +- (void) sendPluginSuccess:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId]; +} + +- (void) sendPluginError:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR] callbackId:command.callbackId]; +} + +- (void) sendPluginErrorWithMessage: (NSString*) errorMessage :(CDVInvokedUrlCommand*)command +{ + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage]; + [self _logError:errorMessage]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; +} + +- (void) sendPluginErrorWithError:(NSError*)error command:(CDVInvokedUrlCommand*)command{ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description] callbackId:command.callbackId]; +} + +- (void) handleEmptyResultWithPotentialError:(NSError*) error command:(CDVInvokedUrlCommand*)command { + if (error) { + [self sendPluginErrorWithError:error command:command]; + }else{ + [self sendPluginSuccess:command]; + } +} + +- (void) handleStringResultWithPotentialError:(NSError*) error command:(CDVInvokedUrlCommand*)command result:(NSString*)result { + if (error) { + [self sendPluginErrorWithError:error command:command]; + }else{ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:result] callbackId:command.callbackId]; + } +} + +- (void) handleBoolResultWithPotentialError:(NSError*) error command:(CDVInvokedUrlCommand*)command result:(BOOL)result { + if (error) { + [self sendPluginErrorWithError:error command:command]; + }else{ + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:result] callbackId:command.callbackId]; + } +} + +- (void) handlePluginExceptionWithContext: (NSException*) exception :(CDVInvokedUrlCommand*)command +{ + [self handlePluginExceptionWithoutContext:exception]; + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:exception.reason]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; +} + +- (void) handlePluginExceptionWithoutContext: (NSException*) exception +{ + [self _logError:[NSString stringWithFormat:@"EXCEPTION: %@", exception.reason]]; +} + +- (void)executeGlobalJavascript: (NSString*)jsString +{ + [self.commandDelegate evalJs:jsString]; +} + +- (void)_logError: (NSString*)msg +{ + NSLog(@"%@ ERROR: %@", LOG_TAG, msg); + NSString* jsString = [NSString stringWithFormat:@"console.error(\"%@: %@\")", LOG_TAG, [self escapeJavascriptString:msg]]; + [self executeGlobalJavascript:jsString]; +} + +- (void)_logInfo: (NSString*)msg +{ + NSLog(@"%@ INFO: %@", LOG_TAG, msg); + NSString* jsString = [NSString stringWithFormat:@"console.info(\"%@: %@\")", LOG_TAG, [self escapeJavascriptString:msg]]; + [self executeGlobalJavascript:jsString]; +} + +- (void)_logMessage: (NSString*)msg +{ + NSLog(@"%@ LOG: %@", LOG_TAG, msg); + NSString* jsString = [NSString stringWithFormat:@"console.log(\"%@: %@\")", LOG_TAG, [self escapeJavascriptString:msg]]; + [self executeGlobalJavascript:jsString]; +} + +- (NSString*)escapeJavascriptString: (NSString*)str +{ + NSString* result = [str stringByReplacingOccurrencesOfString: @"\\\"" withString: @"\""]; + result = [result stringByReplacingOccurrencesOfString: @"\"" withString: @"\\\""]; + result = [result stringByReplacingOccurrencesOfString: @"\n" withString: @"\\\n"]; + return result; +} + +- (void)runOnMainThread:(void (^)(void))completeBlock { + if (![NSThread isMainThread]) { + dispatch_sync(dispatch_get_main_queue(), ^{ + @try { + completeBlock(); + }@catch (NSException *exception) { + [self handlePluginExceptionWithoutContext:exception]; + } + }); + } else { + @try { + completeBlock(); + }@catch (NSException *exception) { + [self handlePluginExceptionWithoutContext:exception]; + } + } +} + +- (FIRAuthCredential*)obtainAuthCredential:(NSDictionary*)credential command:(CDVInvokedUrlCommand *)command { + FIRAuthCredential* authCredential = nil; + + if(credential == nil){ + NSString* errMsg = @"credential object must be passed as first and only argument"; + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errMsg] callbackId:command.callbackId]; + return authCredential; + } + + NSString* key = [credential objectForKey:@"id"]; + NSString* verificationId = [credential objectForKey:@"verificationId"]; + NSString* code = [credential objectForKey:@"code"]; + + if(key != nil){ + authCredential = [authCredentials objectForKey:key]; + if(authCredential == nil){ + NSString* errMsg = [NSString stringWithFormat:@"no native auth credential exists for specified id '%@'", key]; + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errMsg] callbackId:command.callbackId]; + } + }else if(verificationId != nil && code != nil){ + authCredential = [[FIRPhoneAuthProvider provider] + credentialWithVerificationID:verificationId + verificationCode:code]; + }else{ + NSString* errMsg = @"credential object must either specify the id key of an existing native auth credential or the verificationId/code keys must be specified for a phone number authentication"; + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errMsg] callbackId:command.callbackId]; + } + + return authCredential; +} + +- (void) handleAuthResult:(FIRAuthDataResult*) authResult error:(NSError*) error command:(CDVInvokedUrlCommand*)command { + @try { + CDVPluginResult* pluginResult; + if (error) { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description]; + }else if (authResult == nil) { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"User not signed in"]; + }else{ + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + } + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }@catch (NSException *exception) { + [self handlePluginExceptionWithContext:exception :command]; + } +} + +- (int) saveAuthCredential: (FIRAuthCredential*) authCredential { + int key = -1; + while (key < 0 || [authCredentials objectForKey:[NSNumber numberWithInt:key]] != nil) { + key = arc4random_uniform(100000); + } + + [authCredentials setObject:authCredential forKey:[NSNumber numberWithInt:key]]; + + return key; +} + +- (void) setPreferenceFlag:(NSString*) name flag:(BOOL)flag { + [preferences setBool:flag forKey:name]; + [preferences synchronize]; +} + +- (BOOL) getPreferenceFlag:(NSString*) name { + if([preferences objectForKey:name] == nil){ + return false; + } + return [preferences boolForKey:name]; +} + +- (BOOL) getGooglePlistFlagWithDefaultValue:(NSString*) name defaultValue:(BOOL)defaultValue { + if([googlePlist objectForKey:name] == nil){ + return defaultValue; + } + return [[googlePlist objectForKey:name] isEqualToString:@"true"]; +} + + +# pragma mark - Stubs +- (void)createChannel:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (void)setDefaultChannel:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (void)deleteChannel:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (void)listChannels:(CDVInvokedUrlCommand *)command { + [self.commandDelegate runInBackground:^{ + CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiver.h b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiver.h new file mode 100644 index 00000000..639de9ba --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiver.h @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> + +@interface FirebasePluginMessageReceiver : NSObject {} +- (bool) sendNotification:(NSDictionary *)userInfo; +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiver.m b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiver.m new file mode 100644 index 00000000..0990d8c1 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiver.m @@ -0,0 +1,17 @@ +#import "FirebasePluginMessageReceiver.h" +#import "FirebasePluginMessageReceiverManager.h" + +@implementation FirebasePluginMessageReceiver + +- (id) init { + [FirebasePluginMessageReceiverManager register:self]; + return self; +} + +// Concrete subclasses should override this and return true if they handle the received message. +- (bool) sendNotification:(NSDictionary *)userInfo { + NSAssert(false, @"You cannot call sendNotification on the FirebasePluginMessageReceiver class directly. Instead, you must override it using a subclass."); + return false; +} + +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiverManager.h b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiverManager.h new file mode 100644 index 00000000..96dac9d8 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiverManager.h @@ -0,0 +1,6 @@ +#import "FirebasePluginMessageReceiver.h" + +@interface FirebasePluginMessageReceiverManager ++ (void) register:(FirebasePluginMessageReceiver *)receiver; ++ (bool) sendNotification:(NSDictionary *)userInfo; +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiverManager.m b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiverManager.m new file mode 100644 index 00000000..7d463265 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/FirebasePluginMessageReceiverManager.m @@ -0,0 +1,24 @@ +#import "FirebasePluginMessageReceiverManager.h" + +@implementation FirebasePluginMessageReceiverManager + +static NSMutableArray* receivers; + ++ (void) register:(FirebasePluginMessageReceiver*)receiver { + if(receivers == nil){ + receivers = [[NSMutableArray alloc] init]; + } + [receivers addObject:receiver]; +} + ++ (bool) sendNotification:(NSDictionary *)userInfo { + bool handled = false; + for(FirebasePluginMessageReceiver* receiver in receivers){ + bool wasHandled = [receiver sendNotification:userInfo]; + if(wasHandled){ + handled = true; + } + } + return handled; +} +@end diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/GoogleService-Info.plist b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/GoogleService-Info.plist new file mode 100644 index 00000000..5516ebf3 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/src/ios/GoogleService-Info.plist @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> +</dict> +</plist>
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/types/index.d.ts b/StoneIsland/plugins/cordova-plugin-firebasex/types/index.d.ts new file mode 100644 index 00000000..6dd26472 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/types/index.d.ts @@ -0,0 +1,315 @@ +interface IChannelOptions { + id: string + name?: string + description?: string + sound?: string + vibration?: boolean | number[] + light?: boolean + lightColor?: string + importance?: 0 | 1 | 2 | 3 | 4 + badge?: boolean + visibility?: -1 | 0 | 1 +} + +interface FirebasePlugin { + getId( + success: (value: string) => void, + error: (err: string) => void + ): void + getToken( + success: (value: string) => void, + error: (err: string) => void + ): void + onTokenRefresh( + success: (value: string) => void, + error: (err: string) => void): void + getAPNSToken( + success: (value: string) => void, + error: (err: string) => void + ): void + onApnsTokenReceived( + success: (value: string) => void, + error: (err: string) => void + ): void + onMessageReceived( + success: (value: object) => void, + error: (err: string) => void + ): void + grantPermission( + success: (value: boolean) => void, + error: (err: string) => void + ): void + hasPermission( + success: (value: boolean) => void, + error: (err: string) => void + ): void + unregister(): void + setBadgeNumber( + badgeNumber: number + ): void + getBadgeNumber( + success: (badgeNumber: number) => void, + error: (err: string) => void + ): void + clearAllNotifications(): void + subscribe( + topic: string, + success?: () => void, + error?: (err: string) => void + ): void + unsubscribe( + topic: string, + success?: () => void, + error?: (err: string) => void + ): void + isAutoInitEnabled( + success: (enabled: boolean) => void, + error?: (err: string) => void + ): void + setAutoInitEnabled( + enabled: boolean, + success?: () => void, + error?: (err: string) => void + ): void + createChannel( + channel: IChannelOptions, + success: () => void, + error: (err: string) => void + ): void + setDefaultChannel( + channel: IChannelOptions, + success: () => void, + error: (err: string) => void + ): void + deleteChannel( + channel: string, + success: () => void, + error: (err: string) => void + ): void + listChannels( + success: (list: { id: string; name: string }[]) => void, + error: (err: string) => void + ): void + setAnalyticsCollectionEnabled( + setEnabled: boolean + ): void + logEvent( + eventName: string, + eventProperties: object + ): void + setScreenName( + screenName: string + ): void + setUserId( + userId: string + ): void + setUserProperty( + userName: string, + userValue: string + ): void + setCrashlyticsCollectionEnabled(): void + setCrashlyticsUserId( + userId: string + ): void + sendCrash(): void + logMessage( + message: string + ): void + logError( + errorMessage: string, + stackTrace?: object, + success?: () => void, + error?: (err: string) => void + ): void + verifyPhoneNumber( + success: (value: object) => void, + error: (err: string) => void, + phoneNumber: string, + timeOutDuration: number, + fakeVerificationCode?: string + ): void + createUserWithEmailAndPassword( + email: string, + password: string, + success?: () => void, + error?: (err: string) => void + ): void + signInUserWithEmailAndPassword( + email: string, + password: string, + success?: () => void, + error?: (err: string) => void + ): void + signInUserWithCustomToken( + customToken: string, + success?: () => void, + error?: (err: string) => void + ): void + signInUserAnonymously( + success?: () => void, + error?: (err: string) => void + ): void + authenticateUserWithGoogle( + clientId: string, + success?: () => void, + error?: (err: string) => void + ): void + authenticateUserWithApple( + success?: () => void, + error?: (err: string) => void, + locale?: string, + ): void + signInWithCredential( + credential: object, + success?: () => void, + error?: (err: string) => void + ): void + linkUserWithCredential( + credential: object, + success?: () => void, + error?: (err: string) => void + ): void + reauthenticateWithCredential( + credential: object, + success?: () => void, + error?: (err: string) => void + ): void + isUserSignedIn( + success: (isSignedIn: boolean) => void, + error?: (err: string) => void + ): void + signOutUser( + success?: () => void, + error?: (err: string) => void + ): void + getCurrentUser( + success: (user: object) => void, + error?: (err: string) => void + ): void + updateUserProfile( + profile: { + name: string, + photoUri: string + }, + success?: () => void, + error?: (err: string) => void + ): void + updateUserEmail( + email: string, + success?: () => void, + error?: (err: string) => void + ): void + sendUserEmailVerification( + success?: () => void, + error?: (err: string) => void + ): void + updateUserPassword( + password: string, + success?: () => void, + error?: (err: string) => void + ): void + sendUserPasswordResetEmail( + email: string, + success?: () => void, + error?: (err: string) => void + ): void + deleteUser( + success?: () => void, + error?: (err: string) => void + ): void + registerAuthStateChangeListener( + fn: (userSignedIn: boolean) => void, + ): void + fetch( + cacheExpirationSeconds: number, + success: () => void, + error: (err: string) => void + ): void + fetch( + success: () => void, + error: (err: string) => void + ): void + activateFetched( + success: (activated: boolean) => void, + error: (err: string) => void + ): void + getValue( + key: string, + success: (value: string) => void, + error: (err: string) => void + ): void + getByteArray( + key: string, + success: (value: object) => void, + error: (err: string) => void + ): void + getInfo( + success: (info: object) => void, + error: (err: string) => void + ): void + setConfigSettings( + configSettings: object, + success: (info: object) => void, + error: (err: string) => void + ): void + setDefaults( + defaultSettings: object, + success: (info: object) => void, + error: (err: string) => void + ): void + setPerformanceCollectionEnabled( + setEnabled: boolean + ): void + startTrace( + name: string, + success: () => void, + error: (err: string) => void + ): void + incrementCounter( + name: string, + counterName: string, + success: () => void, + error: (err: string) => void + ): void + stopTrace( + name: string + ): void + addDocumentToFirestoreCollection( + document: object, + collection: string, + success: () => void, + error: (err: string) => void + ): void + setDocumentInFirestoreCollection( + documentId: string, + document: object, + collection: string, + success: () => void, + error: (err: string) => void + ): void + updateDocumentInFirestoreCollection( + documentId: string, + document: object, + collection: string, + success: () => void, + error: (err: string) => void + ): void + deleteDocumentFromFirestoreCollection( + documentId: string, + collection: string, + success: () => void, + error: (err: string) => void + ): void + fetchDocumentInFirestoreCollection( + documentId: string, + collection: string, + success: (document: object) => void, + error: (err: string) => void + ): void + fetchFirestoreCollection( + collection: string, + success: (collection: object) => void, + error: (err: string) => void + ): void +} +declare var FirebasePlugin: FirebasePlugin; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/www/firebase.js b/StoneIsland/plugins/cordova-plugin-firebasex/www/firebase.js new file mode 100644 index 00000000..ac2e2d75 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/www/firebase.js @@ -0,0 +1,385 @@ +var exec = require('cordova/exec'); + +var ensureBooleanFn = function (callback){ + return function(result){ + callback(ensureBoolean(result)); + } +}; + +var ensureBoolean = function(value){ + if(value === "true"){ + value = true; + }else if(value === "false"){ + value = false; + } + return !!value; +}; + +var onAuthStateChangeCallback = function(){}; + +/*********************** + * Protected internals + ***********************/ +exports._onAuthStateChange = function(userSignedIn){ + onAuthStateChangeCallback(userSignedIn); +}; + +/************** + * Public API + **************/ + +// Notifications +exports.getId = function (success, error) { + exec(success, error, "FirebasePlugin", "getId", []); +}; + +exports.getToken = function (success, error) { + exec(success, error, "FirebasePlugin", "getToken", []); +}; + +exports.getAPNSToken = function (success, error) { + exec(success, error, "FirebasePlugin", "getAPNSToken", []); +}; + +exports.onMessageReceived = function (success, error) { + exec(success, error, "FirebasePlugin", "onMessageReceived", []); +}; + +exports.onTokenRefresh = function (success, error) { + exec(success, error, "FirebasePlugin", "onTokenRefresh", []); +}; + +exports.onApnsTokenReceived = function (success, error) { + exec(success, error, "FirebasePlugin", "onApnsTokenReceived", []); +}; + +exports.subscribe = function (topic, success, error) { + exec(success, error, "FirebasePlugin", "subscribe", [topic]); +}; + +exports.unsubscribe = function (topic, success, error) { + exec(success, error, "FirebasePlugin", "unsubscribe", [topic]); +}; + +exports.unregister = function (success, error) { + exec(success, error, "FirebasePlugin", "unregister", []); +}; + +exports.isAutoInitEnabled = function (success, error) { + exec(success, error, "FirebasePlugin", "isAutoInitEnabled", []); +}; + +exports.setAutoInitEnabled = function (enabled, success, error) { + exec(success, error, "FirebasePlugin", "setAutoInitEnabled", [!!enabled]); +}; + +// Notifications - iOS-only +exports.setBadgeNumber = function (number, success, error) { + exec(success, error, "FirebasePlugin", "setBadgeNumber", [number]); +}; + +exports.getBadgeNumber = function (success, error) { + exec(success, error, "FirebasePlugin", "getBadgeNumber", []); +}; + +exports.grantPermission = function (success, error) { + exec(ensureBooleanFn(success), error, "FirebasePlugin", "grantPermission", []); +}; + +exports.hasPermission = function (success, error) { + exec(ensureBooleanFn(success), error, "FirebasePlugin", "hasPermission", []); +}; + +// Notifications - Android-only +exports.setDefaultChannel = function (options, success, error) { + exec(success, error, "FirebasePlugin", "setDefaultChannel", [options]); +}; + +exports.createChannel = function (options, success, error) { + exec(success, error, "FirebasePlugin", "createChannel", [options]); +}; + +exports.deleteChannel = function (channelID, success, error) { + exec(success, error, "FirebasePlugin", "deleteChannel", [channelID]); +}; + +exports.listChannels = function (success, error) { + exec(success, error, "FirebasePlugin", "listChannels", []); +}; + +// Analytics +exports.setAnalyticsCollectionEnabled = function (enabled, success, error) { + exec(success, error, "FirebasePlugin", "setAnalyticsCollectionEnabled", [!!enabled]); +}; + +exports.isAnalyticsCollectionEnabled = function (success, error) { + exec(success, error, "FirebasePlugin", "isAnalyticsCollectionEnabled", []); +}; + +exports.logEvent = function (name, params, success, error) { + exec(success, error, "FirebasePlugin", "logEvent", [name, params]); +}; + +exports.setScreenName = function (name, success, error) { + exec(success, error, "FirebasePlugin", "setScreenName", [name]); +}; + +exports.setUserId = function (id, success, error) { + exec(success, error, "FirebasePlugin", "setUserId", [id]); +}; + +exports.setUserProperty = function (name, value, success, error) { + exec(success, error, "FirebasePlugin", "setUserProperty", [name, value]); +}; + +exports.activateFetched = function (success, error) { + exec(ensureBooleanFn(success), error, "FirebasePlugin", "activateFetched", []); +}; + +exports.fetch = function (cacheExpirationSeconds, success, error) { + var args = []; + if (typeof cacheExpirationSeconds === 'number') { + args.push(cacheExpirationSeconds); + } else { + error = success; + success = cacheExpirationSeconds; + } + exec(success, error, "FirebasePlugin", "fetch", args); +}; + +exports.getByteArray = function (key, success, error) { + exec(success, error, "FirebasePlugin", "getByteArray", [key]); +}; + +exports.getValue = function (key, success, error) { + exec(success, error, "FirebasePlugin", "getValue", [key]); +}; + +exports.getInfo = function (success, error) { + exec(success, error, "FirebasePlugin", "getInfo", []); +}; + +exports.setConfigSettings = function (settings, success, error) { + exec(success, error, "FirebasePlugin", "setConfigSettings", [settings]); +}; + +exports.setDefaults = function (defaults, success, error) { + exec(success, error, "FirebasePlugin", "setDefaults", [defaults]); +}; + +exports.startTrace = function (name, success, error) { + exec(success, error, "FirebasePlugin", "startTrace", [name]); +}; + +exports.incrementCounter = function (name, counterNamed, success, error) { + exec(success, error, "FirebasePlugin", "incrementCounter", [name, counterNamed]); +}; + +exports.stopTrace = function (name, success, error) { + exec(success, error, "FirebasePlugin", "stopTrace", [name]); +}; + +exports.setPerformanceCollectionEnabled = function (enabled, success, error) { + exec(success, error, "FirebasePlugin", "setPerformanceCollectionEnabled", [!!enabled]); +}; + +exports.isPerformanceCollectionEnabled = function (success, error) { + exec(success, error, "FirebasePlugin", "isPerformanceCollectionEnabled", []); +}; + +exports.clearAllNotifications = function (success, error) { + exec(success, error, "FirebasePlugin", "clearAllNotifications", []); +}; + + +// Crashlytics +exports.setCrashlyticsCollectionEnabled = function (enabled, success, error) { + exec(success, error, "FirebasePlugin", "setCrashlyticsCollectionEnabled", [!!enabled]); +}; + +exports.isCrashlyticsCollectionEnabled = function (success, error) { + exec(success, error, "FirebasePlugin", "isCrashlyticsCollectionEnabled", []); +}; + +exports.logMessage = function (message, success, error) { + exec(success, error, "FirebasePlugin", "logMessage", [message]); +}; + +exports.sendCrash = function (success, error) { + exec(success, error, "FirebasePlugin", "sendCrash", []); +}; + +exports.logError = function (message, stackTrace, success, error) { + var args = [message]; + // "stackTrace" is an optional arg that's an array of objects. + if (stackTrace) { + if (typeof stackTrace === 'function') { + error = success; + success = stackTrace; + } else { + args.push(stackTrace); + } + } + exec(success, error, "FirebasePlugin", "logError", args); +}; + +exports.setCrashlyticsUserId = function (userId, success, error) { + exec(success, error, "FirebasePlugin", "setCrashlyticsUserId", [userId]); +}; + + +// Authentication +exports.verifyPhoneNumber = function (success, error, number, timeOutDuration, fakeVerificationCode) { + exec(function(credential){ + if(typeof credential === 'object'){ + credential.instantVerification = ensureBoolean(credential.instantVerification); + } + success(credential); + }, error, "FirebasePlugin", "verifyPhoneNumber", [number, timeOutDuration, fakeVerificationCode]); +}; + +exports.createUserWithEmailAndPassword = function (email, password, success, error) { + exec(success, error, "FirebasePlugin", "createUserWithEmailAndPassword", [email, password]); +}; + +exports.signInUserWithEmailAndPassword = function (email, password, success, error) { + exec(success, error, "FirebasePlugin", "signInUserWithEmailAndPassword", [email, password]); +}; + +exports.signInUserWithCustomToken = function (customToken, success, error) { + exec(success, error, "FirebasePlugin", "signInUserWithCustomToken", [customToken]); +}; + +exports.signInUserAnonymously = function (success, error) { + exec(success, error, "FirebasePlugin", "signInUserAnonymously"); +}; + +exports.authenticateUserWithGoogle = function (clientId, success, error) { + exec(success, error, "FirebasePlugin", "authenticateUserWithGoogle", [clientId]); +}; + +exports.authenticateUserWithApple = function (success, error, locale) { + exec(success, error, "FirebasePlugin", "authenticateUserWithApple", [locale]); +}; + +exports.signInWithCredential = function (credential, success, error) { + if(typeof credential !== 'object') return error("'credential' must be an object"); + exec(success, error, "FirebasePlugin", "signInWithCredential", [credential]); +}; + +exports.linkUserWithCredential = function (credential, success, error) { + if(typeof credential !== 'object') return error("'credential' must be an object"); + exec(success, error, "FirebasePlugin", "linkUserWithCredential", [credential]); +}; + +exports.reauthenticateWithCredential = function (credential, success, error) { + if(typeof credential !== 'object') return error("'credential' must be an object"); + exec(success, error, "FirebasePlugin", "reauthenticateWithCredential", [credential]); +}; + +exports.isUserSignedIn = function (success, error) { + exec(ensureBooleanFn(success), error, "FirebasePlugin", "isUserSignedIn", []); +}; + +exports.signOutUser = function (success, error) { + exec(ensureBooleanFn(success), error, "FirebasePlugin", "signOutUser", []); +}; + + +exports.getCurrentUser = function (success, error) { + exec(function(user){ + user.emailIsVerified = ensureBoolean(user.emailIsVerified); + success(user); + }, error, "FirebasePlugin", "getCurrentUser", []); +}; + +exports.reloadCurrentUser = function (success, error) { + exec(function(user){ + user.emailIsVerified = ensureBoolean(user.emailIsVerified); + success(user); + }, error, "FirebasePlugin", "reloadCurrentUser", []); +}; + +exports.updateUserProfile = function (profile, success, error) { + if(typeof profile !== 'object') return error("'profile' must be an object with keys 'name' and/or 'photoUri'"); + exec(success, error, "FirebasePlugin", "updateUserProfile", [profile]); +}; + +exports.updateUserEmail = function (email, success, error) { + if(typeof email !== 'string' || !email) return error("'email' must be a valid email address"); + exec(success, error, "FirebasePlugin", "updateUserEmail", [email]); +}; + +exports.sendUserEmailVerification = function (success, error) { + exec(success, error, "FirebasePlugin", "sendUserEmailVerification", []); +}; + +exports.updateUserPassword = function (password, success, error) { + if(typeof password !== 'string' || !password) return error("'password' must be a valid string"); + exec(success, error, "FirebasePlugin", "updateUserPassword", [password]); +}; + +exports.sendUserPasswordResetEmail = function (email, success, error) { + if(typeof email !== 'string' || !email) return error("'email' must be a valid email address"); + exec(success, error, "FirebasePlugin", "sendUserPasswordResetEmail", [email]); +}; + +exports.deleteUser = function (success, error) { + exec(success, error, "FirebasePlugin", "deleteUser", []); +}; + +exports.registerAuthStateChangeListener = function(fn){ + if(typeof fn !== "function") throw "The specified argument must be a function"; + onAuthStateChangeCallback = fn; +}; + +// Firestore +exports.addDocumentToFirestoreCollection = function (document, collection, success, error) { + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + if(typeof document !== 'object' || typeof document.length === 'number') return error("'document' must be an object specifying record data"); + + exec(success, error, "FirebasePlugin", "addDocumentToFirestoreCollection", [document, collection]); +}; + +exports.setDocumentInFirestoreCollection = function (documentId, document, collection, success, error) { + if(typeof documentId !== 'string' && typeof documentId !== 'number') return error("'documentId' must be a string or number specifying the Firestore document identifier"); + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + if(typeof document !== 'object' || typeof document.length === 'number') return error("'document' must be an object specifying record data"); + + exec(success, error, "FirebasePlugin", "setDocumentInFirestoreCollection", [documentId.toString(), document, collection]); +}; + +exports.updateDocumentInFirestoreCollection = function (documentId, document, collection, success, error) { + if(typeof documentId !== 'string' && typeof documentId !== 'number') return error("'documentId' must be a string or number specifying the Firestore document identifier"); + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + if(typeof document !== 'object' || typeof document.length === 'number') return error("'document' must be an object specifying record data"); + + exec(success, error, "FirebasePlugin", "updateDocumentInFirestoreCollection", [documentId.toString(), document, collection]); +}; + +exports.deleteDocumentFromFirestoreCollection = function (documentId, collection, success, error) { + if(typeof documentId !== 'string' && typeof documentId !== 'number') return error("'documentId' must be a string or number specifying the Firestore document identifier"); + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + + exec(success, error, "FirebasePlugin", "deleteDocumentFromFirestoreCollection", [documentId.toString(), collection]); +}; + +exports.documentExistsInFirestoreCollection = function (documentId, collection, success, error) { + if(typeof documentId !== 'string' && typeof documentId !== 'number') return error("'documentId' must be a string or number specifying the Firestore document identifier"); + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + + exec(ensureBooleanFn(success), error, "FirebasePlugin", "documentExistsInFirestoreCollection", [documentId.toString(), collection]); +}; + +exports.fetchDocumentInFirestoreCollection = function (documentId, collection, success, error) { + if(typeof documentId !== 'string' && typeof documentId !== 'number') return error("'documentId' must be a string or number specifying the Firestore document identifier"); + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + + exec(success, error, "FirebasePlugin", "fetchDocumentInFirestoreCollection", [documentId.toString(), collection]); +}; + +exports.fetchFirestoreCollection = function (collection, filters, success, error) { + if(typeof collection !== 'string') return error("'collection' must be a string specifying the Firestore collection name"); + if(filters && (typeof filters !== 'object' || typeof filters.length === 'undefined')) return error("'filters' must be a array specifying a list of filters to apply to documents in the Firestore collection"); + exec(success, error, "FirebasePlugin", "fetchFirestoreCollection", [collection, filters || []]); +}; diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/README.md index 77a3c9a7..5fa8dee6 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/README.md +++ b/StoneIsland/plugins/cordova-plugin-geolocation/README.md @@ -21,9 +21,9 @@ description: Access GPS data. # under the License. --> -|Android|iOS| Windows 8.1 Store | Windows 8.1 Phone | Windows 10 Store | Travis CI | -|:-:|:-:|:-:|:-:|:-:|:-:| -|[](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=android,PLUGIN=cordova-plugin-geolocation/)|[](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=ios,PLUGIN=cordova-plugin-geolocation/)|[](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-8.1-store,PLUGIN=cordova-plugin-geolocation/)|[](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-8.1-phone,PLUGIN=cordova-plugin-geolocation/)|[](http://cordova-ci.cloudapp.net:8080/job/cordova-periodic-build/PLATFORM=windows-10-store,PLUGIN=cordova-plugin-geolocation/)|[](https://travis-ci.org/apache/cordova-plugin-geolocation)| +|AppVeyor|Travis CI| +|:-:|:-:| +|[](https://ci.appveyor.com/project/ApacheSoftwareFoundation/cordova-plugin-geolocation)|[](https://travis-ci.org/apache/cordova-plugin-geolocation)| # cordova-plugin-geolocation @@ -71,7 +71,7 @@ are not available until after the `deviceready` event. } ``` -## <a id="reference"></a>Reference + ## Installation This requires cordova 5.0+ ( current stable 1.0.0 ) @@ -88,13 +88,8 @@ It is also possible to install via repo url directly ( unstable ) ## Supported Platforms -- Amazon Fire OS - Android -- BlackBerry 10 -- Firefox OS - iOS -- Tizen -- Windows Phone 7 and 8 - Windows ## Methods @@ -159,6 +154,22 @@ error, the `geolocationError` callback is passed a ``` +### iOS Quirks + + Since iOS 10 it's mandatory to provide an usage description in the `info.plist` if trying to access privacy-sensitive data. When the system prompts the user to allow access, this usage description string will displayed as part of the permission dialog box, but if you didn't provide the usage description, the app will crash before showing the dialog. Also, Apple will reject apps that access private data but don't provide an usage description. + + This plugins requires the following usage description: + + * `NSLocationWhenInUseUsageDescription` describes the reason that the app accesses the user's location. + + To add this entry into the `info.plist`, you can use the `edit-config` tag in the `config.xml` like this: + +``` +<edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge"> + <string>need location access to find things nearby</string> +</edit-config> +``` + ### Android Quirks If Geolocation service is turned off the `onError` callback is invoked after `timeout` interval (if specified). @@ -294,10 +305,6 @@ It contains a set of properties that describe the geographic coordinates of a po * __speed__: Current ground speed of the device, specified in meters per second. _(Number)_ -### Amazon Fire OS Quirks - -__altitudeAccuracy__: Not supported by Android devices, returning `null`. - ### Android Quirks __altitudeAccuracy__: Not supported by Android devices, returning `null`. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/RELEASENOTES.md b/StoneIsland/plugins/cordova-plugin-geolocation/RELEASENOTES.md index f622086b..4336fe81 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/RELEASENOTES.md +++ b/StoneIsland/plugins/cordova-plugin-geolocation/RELEASENOTES.md @@ -7,9 +7,9 @@ # 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 @@ -20,6 +20,52 @@ --> # Release Notes +### 4.0.2 (Jun 27, 2019) + +- chore: fix repo and issue urls and license in package.json and plugin.xml ([`4d2e901`](https://github.com/apache/cordova-plugin-geolocation/commit/4d2e901)) +- build: add `.gitattributes` to force LF (instead of possible CRLF on Windows) ([`74417bb`](https://github.com/apache/cordova-plugin-geolocation/commit/74417bb)) +- build: add `.npmignore` to remove unneeded files from npm package ([`d4a1ac5`](https://github.com/apache/cordova-plugin-geolocation/commit/d4a1ac5)) +- ci(travis): Update Travis CI configuration for new paramedic ([#154](https://github.com/apache/cordova-plugin-geolocation/issues/154)) ([`1636d98`](https://github.com/apache/cordova-plugin-geolocation/commit/1636d98)) +- chore(github): Add or update GitHub pull request and issue template ([`6fd7847`](https://github.com/apache/cordova-plugin-geolocation/commit/6fd7847)) +- docs: remove JIRA link ([`2fc992b`](https://github.com/apache/cordova-plugin-geolocation/commit/2fc992b)) +- docs: Remove outdated docs translations ([#117](https://github.com/apache/cordova-plugin-geolocation/issues/117)) ([`9408fdd`](https://github.com/apache/cordova-plugin-geolocation/commit/9408fdd)) +- ci(travis): add android-27 to `android update sdk -u --filter` ([`3b1f63a`](https://github.com/apache/cordova-plugin-geolocation/commit/3b1f63a)) +- fix(ios): CB-14020: (ios) Fix "Collection was mutated while being enumerated" crash ([#104](https://github.com/apache/cordova-plugin-geolocation/issues/104)) ([`ba45595`](https://github.com/apache/cordova-plugin-geolocation/commit/ba45595)) +- docs: Add Apache Cordova issue tracker link to Readme ([#107](https://github.com/apache/cordova-plugin-geolocation/issues/107)) ([`91c7313`](https://github.com/apache/cordova-plugin-geolocation/commit/91c7313)) +- ci(travis): CB-13748: Add build-tools-26.0.2 to travis ([#103](https://github.com/apache/cordova-plugin-geolocation/issues/103)) ([`a6cbe40`](https://github.com/apache/cordova-plugin-geolocation/commit/a6cbe40), [`e74c87a`](https://github.com/apache/cordova-plugin-geolocation/commit/e74c87a)) +- docs: Fix release notes ([#102](https://github.com/apache/cordova-plugin-geolocation/issues/102)) ([`e679a5d`](https://github.com/apache/cordova-plugin-geolocation/commit/e679a5d)) + + +### 4.0.1 (Dec 27, 2017) +* [CB-13705](https://issues.apache.org/jira/browse/CB-13705) Fix to allow 4.0.0 version install + +### 4.0.0 (Dec 15, 2017) +* [CB-13664](https://issues.apache.org/jira/browse/CB-13664) remove deprecated platforms + +### 3.0.0 (Nov 06, 2017) +* [CB-13267](https://issues.apache.org/jira/browse/CB-13267) (iOS): Remove **iOS** usage descriptions +* [CB-13516](https://issues.apache.org/jira/browse/CB-13516) (all): Add 'protective' entry to `cordovaDependencies` +* [CB-13472](https://issues.apache.org/jira/browse/CB-13472) (CI) Fixed Travis **Android** builds again +* [CB-13294](https://issues.apache.org/jira/browse/CB-13294) Remove `cordova-plugin-compat` +* [CB-13299](https://issues.apache.org/jira/browse/CB-13299) (CI) Fix **Android** builds +* [CB-12895](https://issues.apache.org/jira/browse/CB-12895) added `eslint` and removed `jshint` +* [CB-12847](https://issues.apache.org/jira/browse/CB-12847) added `bugs` entry to `package.json`. + +### 2.4.3 (Apr 27, 2017) +* [CB-12622](https://issues.apache.org/jira/browse/CB-12622) Added **Android 6.0** build badge to `README` +* [CB-12685](https://issues.apache.org/jira/browse/CB-12685) added `package.json` to tests folder + +### 2.4.2 (Feb 28, 2017) +* [CB-12363](https://issues.apache.org/jira/browse/CB-12363) Added build badges for **iOS 9.3** and **iOS 10.0** +* [CB-12230](https://issues.apache.org/jira/browse/CB-12230) Removed **Windows 8.1** build badges + +### 2.4.1 (Dec 07, 2016) +* [CB-12224](https://issues.apache.org/jira/browse/CB-12224) Updated version and RELEASENOTES.md for release 2.4.1 +* corrected KCLAuthorizationStatus error, changed to always removed user of [manager locationServicesEnabled]. Must return [CLLocationManager locationServicesEnabled] or 'none' +* [CB-11962](https://issues.apache.org/jira/browse/CB-11962) (ios) Added variable for setting NSLocationWhenInUseUsageDescription +* [CB-11917](https://issues.apache.org/jira/browse/CB-11917) - Remove pull request template checklist item: "iCLA has been submitted…" +* [CB-11904](https://issues.apache.org/jira/browse/CB-11904) Incremented plugin version. + ### 2.4.0 (Sep 26, 2016) * **Ubuntu** Fix altitude & accuracies retrieval * [CB-11875](https://issues.apache.org/jira/browse/CB-11875) added `android.hardware.location.gps` `uses-feature`. @@ -102,8 +148,8 @@ * [CB-7158](https://issues.apache.org/jira/browse/CB-7158) Fix geolocation for ios 8 * Revert [CB-6911](https://issues.apache.org/jira/browse/CB-6911) partially (keeping Info.plist key installation for iOS 8) * [CB-6911](https://issues.apache.org/jira/browse/CB-6911) Geolocation fails in iOS 8 -* [CB-5114](https://issues.apache.org/jira/browse/CB-5114) Windows 8.1 - Use a new proxy as old geolocation methods is deprecated -* [CB-5114](https://issues.apache.org/jira/browse/CB-5114) Append Windows 8.1 into plugin.xml + Optimize Windows 8 Geolocation proxy +* [CB-5114](https://issues.apache.org/jira/browse/CB-5114) **Windows 8.1** - Use a new proxy as old geolocation methods is deprecated +* [CB-5114](https://issues.apache.org/jira/browse/CB-5114) Append **Windows 8.1** into plugin.xml + Optimize Windows 8 Geolocation proxy * Renamed test dir, added nested plugin.xml * added documentation for manual tests * [CB-7146](https://issues.apache.org/jira/browse/CB-7146) Added manual tests diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/de/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/de/README.md deleted file mode 100644 index 17e14a53..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/de/README.md +++ /dev/null @@ -1,268 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -Dieses Plugin bietet Informationen über das Gerät an den Speicherort, z. B. breiten- und Längengrad. Gemeinsame Quellen von Standortinformationen sind Global Positioning System (GPS) und Lage von Netzwerk-Signale wie IP-Adresse, RFID, WLAN und Bluetooth MAC-Adressen und GSM/CDMA Zelle IDs abgeleitet. Es gibt keine Garantie, dass die API des Geräts tatsächliche Position zurückgibt. - -Diese API basiert auf der [W3C Geolocation API-Spezifikation](http://dev.w3.org/geo/api/spec-source.html), und nur auf Geräten, die nicht bereits eine Implementierung bieten führt. - -**Warnung**: Erhebung und Nutzung von Geolocation-Daten wichtige Privatsphäre wirft. Wie die app benutzt Geolocation-Daten, Ihre app-Datenschutzrichtlinien zu diskutieren, ob es mit allen anderen Parteien und das Niveau der Genauigkeit der Daten (z. B. grob, fein, Postleitzahl, etc..) freigegeben ist. Geolocation-Daten gilt allgemein als empfindlich, weil es den Aufenthaltsort des Benutzers erkennen lässt und wenn gespeichert, die Geschichte von ihren Reisen. Daher neben der app-Privacy Policy sollten stark Sie Bereitstellung einer just-in-Time-Bekanntmachung, bevor die app Geolocation-Daten zugreift (wenn das Betriebssystem des Geräts bereits tun nicht). Diese Benachrichtigung sollte der gleichen Informationen, die vorstehend, sowie die Zustimmung des Benutzers (z.B. durch Präsentation Entscheidungen für das **OK** und **Nein danke**). Weitere Informationen finden Sie in der Datenschutz-Guide. - -Dieses Plugin definiert eine globale `navigator.geolocation`-Objekt (für Plattformen, bei denen es sonst fehlt). - -Obwohl das Objekt im globalen Gültigkeitsbereich ist, stehen Features von diesem Plugin nicht bis nach dem `deviceready`-Ereignis. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Installation - -Dies erfordert Cordova 5.0 + (aktuelle stabile 1.0.0) - - cordova plugin add cordova-plugin-geolocation - - -Ältere Versionen von Cordova können noch über die veraltete Id (veraltete 0.3.12) installieren. - - cordova plugin add org.apache.cordova.geolocation - - -Es ist auch möglich, über Repo Url direkt zu installieren (unstable) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## Unterstützte Plattformen - - * Amazon Fire OS - * Android - * BlackBerry 10 - * Firefox OS - * iOS - * Tizen - * Windows Phone 7 und 8 - * Windows 8 - * Windows - -## Methoden - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## Objekte (schreibgeschützt) - - * Position - * Positionsfehler - * Coordinates - -## navigator.geolocation.getCurrentPosition - -Gibt das Gerät aktuelle Position an den `geolocationSuccess`-Rückruf mit einem `Position`-Objekt als Parameter zurück. Wenn ein Fehler vorliegt, wird der Rückruf `geolocationError` ein `PositionError`-Objekt übergeben. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parameter - - * **GeolocationSuccess**: der Rückruf, der die aktuelle Position übergeben wird. - - * **GeolocationError**: *(Optional)* der Rückruf, der ausgeführt wird, wenn ein Fehler auftritt. - - * **GeolocationOptions**: *(Optional)* die Geolocation-Optionen. - -### Beispiel - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Gibt das Gerät aktuelle Position zurück, wenn eine Änderung erkannt wird. Wenn das Gerät einen neuen Speicherort abgerufen hat, führt der `geolocationSuccess`-Rückruf mit einer `Position`-Objekt als Parameter. Wenn ein Fehler vorliegt, führt der `geolocationError`-Rückruf mit einem `PositionError`-Objekt als Parameter. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parameter - - * **GeolocationSuccess**: der Rückruf, der die aktuelle Position übergeben wird. - - * **GeolocationError**: (Optional) der Rückruf, der ausgeführt wird, wenn ein Fehler auftritt. - - * **GeolocationOptions**: (Optional) die Geolocation-Optionen. - -### Gibt - - * **String**: gibt eine Uhr-Id, die das Uhr Position Intervall verweist zurück. Die Uhr-Id sollte verwendet werden, mit `navigator.geolocation.clearWatch` , gerade für Änderungen zu stoppen. - -### Beispiel - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Optionalen Parametern, um das Abrufen von Geolocation `Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Optionen - - * **EnableHighAccuracy**: stellt einen Hinweis, dass die Anwendung die bestmöglichen Ergebnisse benötigt. Standardmäßig versucht das Gerät abzurufen ein `Position` mit netzwerkbasierte Methoden. Wenn diese Eigenschaft auf `true` erzählt den Rahmenbedingungen genauere Methoden, z. B. Satellitenortung verwenden. *(Boolean)* - - * **Timeout**: die maximale Länge der Zeit (in Millisekunden), die zulässig ist, übergeben Sie den Aufruf von `navigator.geolocation.getCurrentPosition` oder `geolocation.watchPosition` bis zu den entsprechenden `geolocationSuccess` Rückruf führt. Wenn die `geolocationSuccess` Rückruf wird nicht aufgerufen, in dieser Zeit die `geolocationError` Rückruf wird übergeben ein `PositionError.TIMEOUT` Fehlercode. (Beachten Sie, dass in Verbindung mit `geolocation.watchPosition` , die `geolocationError` Rückruf könnte auf ein Intervall aufgerufen werden alle `timeout` Millisekunden!) *(Anzahl)* - - * **MaximumAge**: eine zwischengespeicherte Position, deren Alter nicht größer als die angegebene Zeit in Millisekunden ist, zu akzeptieren. *(Anzahl)* - -### Android Eigenarten - -Android 2.x-Emulatoren geben ein Geolocation-Ergebnis nicht zurück, es sei denn, die `EnableHighAccuracy`-Option auf `true` festgelegt ist. - -## navigator.geolocation.clearWatch - -Stoppen Sie, gerade für Änderungen an dem Gerät Speicherort verweist mithilfe des Parameters `watchID`. - - navigator.geolocation.clearWatch(watchID); - - -### Parameter - - * **WatchID**: die Id der `watchPosition` Intervall löschen. (String) - -### Beispiel - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Enthält `Position` koordinaten und Timestamp, erstellt von der Geolocation API. - -### Eigenschaften - - * **coords**: eine Reihe von geographischen Koordinaten. *(Coordinates)* - - * **timestamp**: Zeitstempel der Erstellung für `coords` . *(DOMTimeStamp)* - -## Coordinates - -Ein `Coordinates`-Objekt ist ein `Position`-Objekt zugeordnet, die Callback-Funktionen in Anforderungen für die aktuelle Position zur Verfügung steht. Es enthält eine Reihe von Eigenschaften, die die geographischen Koordinaten von einer Position zu beschreiben. - -### Eigenschaften - - * **latitude**: Latitude in Dezimalgrad. *(Anzahl)* - - * **longitude**: Länge in Dezimalgrad. *(Anzahl)* - - * **altitude**: Höhe der Position in Meter über dem Ellipsoid. *(Anzahl)* - - * **accuracy**: Genauigkeit der breiten- und Längengrad Koordinaten in Metern. *(Anzahl)* - - * **AltitudeAccuracy**: Genauigkeit der Koordinate Höhe in Metern. *(Anzahl)* - - * **heading**: Fahrtrichtung, angegeben in Grad relativ zu den Norden im Uhrzeigersinn gezählt. *(Anzahl)* - - * **speed**: aktuelle Geschwindigkeit über Grund des Geräts, in Metern pro Sekunde angegeben. *(Anzahl)* - -### Amazon Fire OS Macken - -**altitudeAccuracy**: von Android-Geräten, Rückgabe `null` nicht unterstützt. - -### Android Eigenarten - -**altitudeAccuracy**: von Android-Geräten, Rückgabe `null` nicht unterstützt. - -## Positionsfehler - -Das `PositionError`-Objekt wird an die `geolocationError`-Callback-Funktion übergeben, tritt ein Fehler mit navigator.geolocation. - -### Eigenschaften - - * **Code**: einer der vordefinierten Fehlercodes aufgeführt. - - * **Nachricht**: Fehlermeldung, die die Informationen über den aufgetretenen Fehler beschreibt. - -### Konstanten - - * `PositionError.PERMISSION_DENIED` - * Zurückgegeben, wenn Benutzer erlauben nicht die app Positionsinformationen abgerufen werden. Dies ist abhängig von der Plattform. - * `PositionError.POSITION_UNAVAILABLE` - * Zurückgegeben, wenn das Gerät nicht in der Lage, eine Position abzurufen ist. Im Allgemeinen bedeutet dies, dass das Gerät nicht mit einem Netzwerk verbunden ist oder ein Satelliten-Update kann nicht abgerufen werden. - * `PositionError.TIMEOUT` - * Zurückgegeben, wenn das Gerät nicht in der Lage, eine Position innerhalb der festgelegten Zeit abzurufen ist die `timeout` enthalten `geolocationOptions` . Bei Verwendung mit `navigator.geolocation.watchPosition` , könnte dieser Fehler wiederholt übergeben werden, zu der `geolocationError` Rückruf jedes `timeout` Millisekunden.
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/de/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/de/index.md deleted file mode 100644 index 92b2079b..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/de/index.md +++ /dev/null @@ -1,255 +0,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. ---> - -# cordova-plugin-geolocation - -Dieses Plugin bietet Informationen über das Gerät an den Speicherort, z. B. breiten- und Längengrad. Gemeinsame Quellen von Standortinformationen sind Global Positioning System (GPS) und Lage von Netzwerk-Signale wie IP-Adresse, RFID, WLAN und Bluetooth MAC-Adressen und GSM/CDMA Zelle IDs abgeleitet. Es gibt keine Garantie, dass die API des Geräts tatsächliche Position zurückgibt. - -Diese API basiert auf der [W3C Geolocation API-Spezifikation][1], und nur auf Geräten, die nicht bereits eine Implementierung bieten führt. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**Warnung**: Erhebung und Nutzung von Geolocation-Daten wichtige Privatsphäre wirft. Wie die app benutzt Geolocation-Daten, Ihre app-Datenschutzrichtlinien zu diskutieren, ob es mit allen anderen Parteien und das Niveau der Genauigkeit der Daten (z. B. grob, fein, Postleitzahl, etc..) freigegeben ist. Geolocation-Daten gilt allgemein als empfindlich, weil es den Aufenthaltsort des Benutzers erkennen lässt und wenn gespeichert, die Geschichte von ihren Reisen. Daher neben der app-Privacy Policy sollten stark Sie Bereitstellung einer just-in-Time-Bekanntmachung, bevor die app Geolocation-Daten zugreift (wenn das Betriebssystem des Geräts bereits tun nicht). Diese Benachrichtigung sollte der gleichen Informationen, die vorstehend, sowie die Zustimmung des Benutzers (z.B. durch Präsentation Entscheidungen für das **OK** und **Nein danke**). Weitere Informationen finden Sie in der Datenschutz-Guide. - -Dieses Plugin definiert eine globale `navigator.geolocation`-Objekt (für Plattformen, bei denen es sonst fehlt). - -Obwohl das Objekt im globalen Gültigkeitsbereich ist, stehen Features von diesem Plugin nicht bis nach dem `deviceready`-Ereignis. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Installation - - cordova plugin add cordova-plugin-geolocation - - -## Unterstützte Plattformen - -* Amazon Fire OS -* Android -* BlackBerry 10 -* Firefox OS -* iOS -* Tizen -* Windows Phone 7 und 8 -* Windows 8 - -## Methoden - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## Objekte (schreibgeschützt) - -* Position -* Positionsfehler -* Coordinates - -## navigator.geolocation.getCurrentPosition - -Gibt das Gerät aktuelle Position an den `geolocationSuccess`-Rückruf mit einem `Position`-Objekt als Parameter zurück. Wenn ein Fehler vorliegt, wird der Rückruf `geolocationError` ein `PositionError`-Objekt übergeben. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parameter - -* **GeolocationSuccess**: der Rückruf, der die aktuelle Position übergeben wird. - -* **GeolocationError**: *(Optional)* der Rückruf, der ausgeführt wird, wenn ein Fehler auftritt. - -* **GeolocationOptions**: *(Optional)* die Geolocation-Optionen. - -### Beispiel - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Gibt das Gerät aktuelle Position zurück, wenn eine Änderung erkannt wird. Wenn das Gerät einen neuen Speicherort abgerufen hat, führt der `geolocationSuccess`-Rückruf mit einer `Position`-Objekt als Parameter. Wenn ein Fehler vorliegt, führt der `geolocationError`-Rückruf mit einem `PositionError`-Objekt als Parameter. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parameter - -* **GeolocationSuccess**: der Rückruf, der die aktuelle Position übergeben wird. - -* **GeolocationError**: (Optional) der Rückruf, der ausgeführt wird, wenn ein Fehler auftritt. - -* **GeolocationOptions**: (Optional) die Geolocation-Optionen. - -### Gibt - -* **String**: gibt eine Uhr-Id, die das Uhr Position Intervall verweist zurück. Die Uhr-Id sollte verwendet werden, mit `navigator.geolocation.clearWatch` , gerade für Änderungen zu stoppen. - -### Beispiel - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Optionalen Parametern, um das Abrufen von Geolocation `Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Optionen - -* **EnableHighAccuracy**: stellt einen Hinweis, dass die Anwendung die bestmöglichen Ergebnisse benötigt. Standardmäßig versucht das Gerät abzurufen ein `Position` mit netzwerkbasierte Methoden. Wenn diese Eigenschaft auf `true` erzählt den Rahmenbedingungen genauere Methoden, z. B. Satellitenortung verwenden. *(Boolean)* - -* **Timeout**: die maximale Länge der Zeit (in Millisekunden), die zulässig ist, übergeben Sie den Aufruf von `navigator.geolocation.getCurrentPosition` oder `geolocation.watchPosition` bis zu den entsprechenden `geolocationSuccess` Rückruf führt. Wenn die `geolocationSuccess` Rückruf wird nicht aufgerufen, in dieser Zeit die `geolocationError` Rückruf wird übergeben ein `PositionError.TIMEOUT` Fehlercode. (Beachten Sie, dass in Verbindung mit `geolocation.watchPosition` , die `geolocationError` Rückruf könnte auf ein Intervall aufgerufen werden alle `timeout` Millisekunden!) *(Anzahl)* - -* **MaximumAge**: eine zwischengespeicherte Position, deren Alter nicht größer als die angegebene Zeit in Millisekunden ist, zu akzeptieren. *(Anzahl)* - -### Android Eigenarten - -Android 2.x-Emulatoren geben ein Geolocation-Ergebnis nicht zurück, es sei denn, die `EnableHighAccuracy`-Option auf `true` festgelegt ist. - -## navigator.geolocation.clearWatch - -Stoppen Sie, gerade für Änderungen an dem Gerät Speicherort verweist mithilfe des Parameters `watchID`. - - navigator.geolocation.clearWatch(watchID); - - -### Parameter - -* **WatchID**: die Id der `watchPosition` Intervall löschen. (String) - -### Beispiel - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Enthält `Position` koordinaten und Timestamp, erstellt von der Geolocation API. - -### Eigenschaften - -* **coords**: eine Reihe von geographischen Koordinaten. *(Coordinates)* - -* **timestamp**: Zeitstempel der Erstellung für `coords` . *(DOMTimeStamp)* - -## Coordinates - -Ein `Coordinates`-Objekt ist ein `Position`-Objekt zugeordnet, die Callback-Funktionen in Anforderungen für die aktuelle Position zur Verfügung steht. Es enthält eine Reihe von Eigenschaften, die die geographischen Koordinaten von einer Position zu beschreiben. - -### Eigenschaften - -* **latitude**: Latitude in Dezimalgrad. *(Anzahl)* - -* **longitude**: Länge in Dezimalgrad. *(Anzahl)* - -* **altitude**: Höhe der Position in Meter über dem Ellipsoid. *(Anzahl)* - -* **accuracy**: Genauigkeit der breiten- und Längengrad Koordinaten in Metern. *(Anzahl)* - -* **AltitudeAccuracy**: Genauigkeit der Koordinate Höhe in Metern. *(Anzahl)* - -* **heading**: Fahrtrichtung, angegeben in Grad relativ zu den Norden im Uhrzeigersinn gezählt. *(Anzahl)* - -* **speed**: aktuelle Geschwindigkeit über Grund des Geräts, in Metern pro Sekunde angegeben. *(Anzahl)* - -### Amazon Fire OS Macken - -**altitudeAccuracy**: von Android-Geräten, Rückgabe `null` nicht unterstützt. - -### Android Eigenarten - -**altitudeAccuracy**: von Android-Geräten, Rückgabe `null` nicht unterstützt. - -## Positionsfehler - -Das `PositionError`-Objekt wird an die `geolocationError`-Callback-Funktion übergeben, tritt ein Fehler mit navigator.geolocation. - -### Eigenschaften - -* **Code**: einer der vordefinierten Fehlercodes aufgeführt. - -* **Nachricht**: Fehlermeldung, die die Informationen über den aufgetretenen Fehler beschreibt. - -### Konstanten - -* `PositionError.PERMISSION_DENIED` - * Zurückgegeben, wenn Benutzer erlauben nicht die app Positionsinformationen abgerufen werden. Dies ist abhängig von der Plattform. -* `PositionError.POSITION_UNAVAILABLE` - * Zurückgegeben, wenn das Gerät nicht in der Lage, eine Position abzurufen ist. Im Allgemeinen bedeutet dies, dass das Gerät nicht mit einem Netzwerk verbunden ist oder ein Satelliten-Update kann nicht abgerufen werden. -* `PositionError.TIMEOUT` - * Zurückgegeben, wenn das Gerät nicht in der Lage, eine Position innerhalb der festgelegten Zeit abzurufen ist die `timeout` enthalten `geolocationOptions` . Bei Verwendung mit `navigator.geolocation.watchPosition` , könnte dieser Fehler wiederholt übergeben werden, zu der `geolocationError` Rückruf jedes `timeout` Millisekunden. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/es/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/es/README.md deleted file mode 100644 index 7808a0e3..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/es/README.md +++ /dev/null @@ -1,266 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -Este plugin proporciona información sobre la ubicación del dispositivo, tales como la latitud y longitud. Fuentes comunes de información de localización incluyen el sistema de posicionamiento Global (GPS) y ubicación deducido de las señales de la red como dirección IP, direcciones de RFID, WiFi y Bluetooth MAC y celulares GSM/CDMA IDs. No hay ninguna garantÃa de que la API devuelve la ubicación real del dispositivo. - -Esta API se basa en la [Especificación de API de geolocalización W3C](http://dev.w3.org/geo/api/spec-source.html) y sólo se ejecuta en dispositivos que ya no proporcionan una implementación. - -**ADVERTENCIA**: recopilación y uso de datos de geolocalización plantea cuestiones de privacidad importante. PolÃtica de privacidad de su aplicación debe discutir cómo la aplicación utiliza los datos de geolocalización, si se comparte con cualquiera de las partes y el nivel de precisión de los datos (por ejemplo, código postal grueso, fino, nivel, etc.). Datos de geolocalización es generalmente considerados sensibles porque puede revelar paradero del usuario y, si está almacenado, la historia de sus viajes. Por lo tanto, además de polÃtica de privacidad de la app, fuertemente considere dar un aviso de just-in-time antes de la aplicación tiene acceso a datos de geolocalización (si el sistema operativo del dispositivo ya no hacerlo). Que el aviso debe proporcionar la misma información mencionada, además de obtener un permiso del usuario (por ejemplo, presentando opciones para **Aceptar** y **No gracias**). Para obtener más información, por favor consulte a la guÃa de privacidad. - -Este plugin define un global `navigator.geolocation` objeto (para plataformas donde falta lo contrario). - -Aunque el objeto está en el ámbito global, caracterÃsticas proporcionadas por este plugin no están disponibles hasta después de la `deviceready` evento. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Instalación - -Esto requiere cordova 5.0 + (1.0.0 estable actual) - - cordova plugin add cordova-plugin-geolocation - - -Las versiones más antiguas de Córdoba todavÃa pueden instalar mediante el id obsoleto (0.3.12 rancio) - - Cordova plugin agregar org.apache.cordova.geolocation - - -También es posible instalar directamente vÃa url repo (inestable) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## Plataformas soportadas - - * Amazon fire OS - * Android - * BlackBerry 10 - * Firefox OS - * iOS - * Tizen - * Windows Phone 7 y 8 - * Windows 8 - * Windows - -## Métodos - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## Objetos (sólo lectura) - - * Position - * PositionError - * Coordinates - -## navigator.geolocation.getCurrentPosition - -Devuelve la posición actual del dispositivo a la `geolocationSuccess` "callback" con un `Position` objeto como parámetro. Si hay un error, el `geolocationError` "callback" pasa un `PositionError` objeto. - - navigator.geolocation.getCurrentPosition (geolocationSuccess, [geolocationError], [geolocationOptions]); - - -### Parámetros - - * **geolocationSuccess**: la devolución de llamada que se pasa a la posición actual. - - * **geolocationError**: *(opcional)* la devolución de llamada que se ejecuta si se produce un error. - - * **geolocationOptions**: *(opcional)* las opciones de geolocalización. - -### Ejemplo - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Devuelve la posición actual del dispositivo cuando se detecta un cambio de posición. Cuando el dispositivo recupera una nueva ubicación, el `geolocationSuccess` devolución de llamada se ejecuta con un `Position` objeto como parámetro. Si hay un error, el `geolocationError` devolución de llamada se ejecuta con un `PositionError` objeto como parámetro. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parámetros - - * **geolocationSuccess**: la devolución de llamada que se pasa a la posición actual. - - * **geolocationError**: (opcional) la devolución de llamada que se ejecuta si se produce un error. - - * **geolocationOptions**: opciones (opcional) la geolocalización. - -### Devoluciones - - * **Cadena**: devuelve un identificador de reloj que hace referencia el intervalo de posición del reloj. El id del reloj debe ser utilizado con `navigator.geolocation.clearWatch` para dejar de ver a los cambios de posición. - -### Ejemplo - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Parámetros opcionales para personalizar la recuperación de la geolocalización`Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Opciones - - * **enableHighAccuracy**: proporciona una pista que la aplicación necesita los mejores resultados posibles. De forma predeterminada, el dispositivo intentará recuperar un `Position` usando métodos basados en red. Al establecer esta propiedad en `true` dice el marco a utilizar métodos más precisos, como el posicionamiento satelital. *(Boolean)* - - * **tiempo de espera**: la longitud máxima de tiempo (en milisegundos) que está permitido el paso de la llamada a `navigator.geolocation.getCurrentPosition` o `geolocation.watchPosition` hasta el correspondiente `geolocationSuccess` devolución de llamada se ejecuta. Si el `geolocationSuccess` no se invoque "callback" dentro de este tiempo, el `geolocationError` devolución de llamada se pasa un `PositionError.TIMEOUT` código de error. (Tenga en cuenta que cuando se utiliza en conjunción con `geolocation.watchPosition` , el `geolocationError` "callback" podrÃa ser llamado en un intervalo cada `timeout` milisegundos!) *(Número)* - - * **maximumAge**: aceptar un puesto en la memoria caché, cuya edad no es mayor que el tiempo especificado en milisegundos. *(Número)* - -### Rarezas Android - -Emuladores Android 2.x no devuelva un resultado de geolocalización a menos que el `enableHighAccuracy` opción se establece en`true`. - -## navigator.geolocation.clearWatch - -Deja de ver cambios en la ubicación del dispositivo al que hace referencia el `watchID` parámetro. - - navigator.geolocation.clearWatch(watchID); - - -### Parámetros - - * **watchID**: el id del intervalo `watchPosition` para despejar. (String) - -### Ejemplo - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Contiene `Position` coordenadas y timestamp, creado por la API de geolocalización. - -### Propiedades - - * **coordenadas**: un conjunto de coordenadas geográficas. *(Coordenadas)* - - * **timestamp**: fecha y hora de creación `coords` . *(DOMTimeStamp)* - -## Coordinates - -A `Coordinates` objeto está unido a un `Position` que está disponible para funciones de retrollamada en las solicitudes para la posición actual del objeto. Contiene un conjunto de propiedades que describen las coordenadas geográficas de posición. - -### Propiedades - - * **Latitude**: latitud en grados decimales. *(Número)* - - * **longitud**: longitud en grados decimales. *(Número)* - - * **altitud**: altura de la posición en metros por encima del elipsoide. *(Número)* - - * **exactitud**: nivel de precisión de las coordenadas de latitud y longitud en metros. *(Número)* - - * **altitudeAccuracy**: nivel de precisión de las coordenadas de altitud en metros. *(Número)* - - * **Dirección**: dirección del recorrido, especificado en grados contando hacia la derecha en relación con el norte verdadero. *(Número)* - - * **velocidad**: velocidad actual del dispositivo especificado en metros por segundo. *(Número)* - -### Amazon fuego OS rarezas - -**altitudeAccuracy**: no compatible con dispositivos Android, regresando`null`. - -### Rarezas Android - -**altitudeAccuracy**: no compatible con dispositivos Android, regresando`null`. - -## PositionError - -El `PositionError` objeto se pasa a la `geolocationError` función de devolución de llamada cuando se produce un error con navigator.geolocation. - -### Propiedades - - * **code**: uno de los códigos de error predefinido enumerados a continuación. - - * **mensaje**: mensaje de Error que describe los detalles del error encontrado. - -### Constantes - - * `PositionError.PERMISSION_DENIED` - * Regresó cuando los usuarios no permiten la aplicación recuperar información de la posición. Esto depende de la plataforma. - * `PositionError.POSITION_UNAVAILABLE` - * Regresó cuando el dispositivo es capaz de recuperar una posición. En general, esto significa que el dispositivo no está conectado a una red o no puede obtener una solución vÃa satélite. - * `PositionError.TIMEOUT` - * Cuando el dispositivo es capaz de recuperar una posición dentro del tiempo especificado por el `timeout` incluido en `geolocationOptions` . Cuando se utiliza con `navigator.geolocation.watchPosition` , este error podrÃa pasar repetidamente a la `geolocationError` "callback" cada `timeout` milisegundos.
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/es/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/es/index.md deleted file mode 100644 index 041f3f82..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/es/index.md +++ /dev/null @@ -1,214 +0,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. ---> - -# cordova-plugin-geolocation - -Este plugin proporciona información sobre la ubicación del dispositivo, tales como la latitud y longitud. Fuentes comunes de información de localización incluyen el sistema de posicionamiento Global (GPS) y ubicación deducido de las señales de la red como dirección IP, direcciones de RFID, WiFi y Bluetooth MAC y celulares GSM/CDMA IDs. No hay ninguna garantÃa de que la API devuelve la ubicación real del dispositivo. - -Esta API se basa en la [Especificación de API de geolocalización W3C][1] y sólo se ejecuta en dispositivos que ya no proporcionan una implementación. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**ADVERTENCIA**: recopilación y uso de datos de geolocalización plantea cuestiones de privacidad importante. PolÃtica de privacidad de su aplicación debe discutir cómo la aplicación utiliza los datos de geolocalización, si se comparte con cualquiera de las partes y el nivel de precisión de los datos (por ejemplo, código postal grueso, fino, nivel, etc.). Datos de geolocalización es generalmente considerados sensibles porque puede revelar paradero del usuario y, si está almacenado, la historia de sus viajes. Por lo tanto, además de polÃtica de privacidad de la app, fuertemente considere dar un aviso de just-in-time antes de la aplicación tiene acceso a datos de geolocalización (si el sistema operativo del dispositivo ya no hacerlo). Que el aviso debe proporcionar la misma información mencionada, además de obtener un permiso del usuario (por ejemplo, presentando opciones para **Aceptar** y **No gracias**). Para obtener más información, por favor consulte a la guÃa de privacidad. - -Este plugin define un global `navigator.geolocation` objeto (para plataformas donde falta lo contrario). - -Aunque el objeto está en el ámbito global, caracterÃsticas proporcionadas por este plugin no están disponibles hasta después de la `deviceready` evento. - - document.addEventListener ("deviceready", onDeviceReady, false); - function onDeviceReady() {console.log ("navigator.geolocation funciona bien");} - - -## Instalación - - Cordova plugin agregar cordova-plugin-geolocation - - -## Plataformas soportadas - -* Amazon fire OS -* Android -* BlackBerry 10 -* Firefox OS -* iOS -* Tizen -* Windows Phone 7 y 8 -* Windows 8 - -## Métodos - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## Objetos (sólo lectura) - -* Position -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -Devuelve la posición actual del dispositivo a la `geolocationSuccess` "callback" con un `Position` objeto como parámetro. Si hay un error, el `geolocationError` "callback" pasa un `PositionError` objeto. - - navigator.geolocation.getCurrentPosition (geolocationSuccess, [geolocationError], [geolocationOptions]); - - -### Parámetros - -* **geolocationSuccess**: la devolución de llamada que se pasa a la posición actual. - -* **geolocationError**: *(opcional)* la devolución de llamada que se ejecuta si se produce un error. - -* **geolocationOptions**: *(opcional)* las opciones de geolocalización. - -### Ejemplo - - onSuccess Callback / / este método acepta un objeto Position, que contiene el / / coordenadas GPS actual / / var onSuccess = function(position) {alert (' latitud: ' + position.coords.latitude + '\n' + ' longitud: ' + position.coords.longitude + '\n' + ' altitud: ' + position.coords.altitude + '\n' + ' exactitud: ' + position.coords.accuracy + '\n' + ' altitud exactitud: ' + position.coords.altitudeAccuracy + '\n' + ' hacia: ' + position.coords.heading + '\n' + ' velocidad: ' + position.coords.speed + '\n' + ' Timestamp: ' + position.timestamp + '\n');}; - - onError Callback recibe un objeto PositionError / / function onError(error) {alert (' código: ' + error.code + '\n' + ' mensaje: ' + error.message + '\n');} - - navigator.geolocation.getCurrentPosition (onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Devuelve la posición actual del dispositivo cuando se detecta un cambio de posición. Cuando el dispositivo recupera una nueva ubicación, el `geolocationSuccess` devolución de llamada se ejecuta con un `Position` objeto como parámetro. Si hay un error, el `geolocationError` devolución de llamada se ejecuta con un `PositionError` objeto como parámetro. - - var watchId = navigator.geolocation.watchPosition (geolocationSuccess, [geolocationError], [geolocationOptions]); - - -### Parámetros - -* **geolocationSuccess**: la devolución de llamada que se pasa a la posición actual. - -* **geolocationError**: (opcional) la devolución de llamada que se ejecuta si se produce un error. - -* **geolocationOptions**: opciones (opcional) la geolocalización. - -### Devoluciones - -* **Cadena**: devuelve un identificador de reloj que hace referencia el intervalo de posición del reloj. El id del reloj debe ser utilizado con `navigator.geolocation.clearWatch` para dejar de ver a los cambios de posición. - -### Ejemplo - - onSuccess Callback / / este método acepta un objeto 'Position', que contiene / / coordenadas GPS de la corriente / / function onSuccess(position) {var elemento = document.getElementById('geolocation'); - element.innerHTML = ' latitud: ' + position.coords.latitude + ' < br / >' + ' longitud: ' + position.coords.longitude + ' < br / >' + ' < hr / >' + element.innerHTML; - } / / onError Callback recibe un objeto PositionError / / function onError(error) {alert (' código: ' + error.code + '\n' + ' mensaje: ' + error.message + '\n');} - - Opciones: tira un error si no se recibe ninguna actualización cada 30 segundos. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Parámetros opcionales para personalizar la recuperación de la geolocalización`Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Opciones - -* **enableHighAccuracy**: proporciona una pista que la aplicación necesita los mejores resultados posibles. De forma predeterminada, el dispositivo intentará recuperar un `Position` usando métodos basados en red. Al establecer esta propiedad en `true` dice el marco a utilizar métodos más precisos, como el posicionamiento satelital. *(Boolean)* - -* **tiempo de espera**: la longitud máxima de tiempo (en milisegundos) que está permitido el paso de la llamada a `navigator.geolocation.getCurrentPosition` o `geolocation.watchPosition` hasta el correspondiente `geolocationSuccess` devolución de llamada se ejecuta. Si el `geolocationSuccess` no se invoque "callback" dentro de este tiempo, el `geolocationError` devolución de llamada se pasa un `PositionError.TIMEOUT` código de error. (Tenga en cuenta que cuando se utiliza en conjunción con `geolocation.watchPosition` , el `geolocationError` "callback" podrÃa ser llamado en un intervalo cada `timeout` milisegundos!) *(Número)* - -* **maximumAge**: aceptar un puesto en la memoria caché, cuya edad no es mayor que el tiempo especificado en milisegundos. *(Número)* - -### Rarezas Android - -Emuladores Android 2.x no devuelva un resultado de geolocalización a menos que el `enableHighAccuracy` opción se establece en`true`. - -## navigator.geolocation.clearWatch - -Deja de ver cambios en la ubicación del dispositivo al que hace referencia el `watchID` parámetro. - - navigator.geolocation.clearWatch(watchID); - - -### Parámetros - -* **watchID**: el id del intervalo `watchPosition` para despejar. (String) - -### Ejemplo - - Opciones: ver los cambios en la posición y usar más / / exacta posición disponible del método de adquisición. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, { enableHighAccuracy: true }); - - ... después de... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Contiene `Position` coordenadas y timestamp, creado por la API de geolocalización. - -### Propiedades - -* **coordenadas**: un conjunto de coordenadas geográficas. *(Coordenadas)* - -* **timestamp**: fecha y hora de creación `coords` . *(DOMTimeStamp)* - -## Coordinates - -A `Coordinates` objeto está unido a un `Position` que está disponible para funciones de retrollamada en las solicitudes para la posición actual del objeto. Contiene un conjunto de propiedades que describen las coordenadas geográficas de posición. - -### Propiedades - -* **Latitude**: latitud en grados decimales. *(Número)* - -* **longitud**: longitud en grados decimales. *(Número)* - -* **altitud**: altura de la posición en metros por encima del elipsoide. *(Número)* - -* **exactitud**: nivel de precisión de las coordenadas de latitud y longitud en metros. *(Número)* - -* **altitudeAccuracy**: nivel de precisión de las coordenadas de altitud en metros. *(Número)* - -* **Dirección**: dirección del recorrido, especificado en grados contando hacia la derecha en relación con el norte verdadero. *(Número)* - -* **velocidad**: velocidad actual del dispositivo especificado en metros por segundo. *(Número)* - -### Amazon fuego OS rarezas - -**altitudeAccuracy**: no compatible con dispositivos Android, regresando`null`. - -### Rarezas Android - -**altitudeAccuracy**: no compatible con dispositivos Android, regresando`null`. - -## PositionError - -El `PositionError` objeto se pasa a la `geolocationError` función de devolución de llamada cuando se produce un error con navigator.geolocation. - -### Propiedades - -* **code**: uno de los códigos de error predefinido enumerados a continuación. - -* **mensaje**: mensaje de Error que describe los detalles del error encontrado. - -### Constantes - -* `PositionError.PERMISSION_DENIED` - * Regresó cuando los usuarios no permiten la aplicación recuperar información de la posición. Esto depende de la plataforma. -* `PositionError.POSITION_UNAVAILABLE` - * Regresó cuando el dispositivo es capaz de recuperar una posición. En general, esto significa que el dispositivo no está conectado a una red o no puede obtener una solución vÃa satélite. -* `PositionError.TIMEOUT` - * Cuando el dispositivo es capaz de recuperar una posición dentro del tiempo especificado por el `timeout` incluido en `geolocationOptions` . Cuando se utiliza con `navigator.geolocation.watchPosition` , este error podrÃa pasar repetidamente a la `geolocationError` "callback" cada `timeout` milisegundos. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/fr/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/fr/README.md deleted file mode 100644 index 775a487f..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/fr/README.md +++ /dev/null @@ -1,227 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -Ce plugin fournit des informations sur l'emplacement de l'appareil, tels que la latitude et la longitude. Les sources habituelles d'information incluent le Système de Positionnement Global (GPS) et la position déduite de signaux des réseaux tels que l'adresse IP, RFID, les adresses MAC WiFi et Bluetooth et les IDs cellulaires GSM/CDMA. Il n'y a cependant aucune garantie que cette API renvoie la position réelle de l'appareil. - -Cette API est basée sur la [Spécification de l'API Geolocation du W3C](http://dev.w3.org/geo/api/spec-source.html) et s'exécute uniquement sur les appareils qui n'en proposent pas déjà une implémentation. - -**Avertissement**: collecte et utilisation des données de géolocalisation soulève des questions importantes de la vie privée. La politique de confidentialité de votre application devrait traiter de la manière dont l'application utilise les données de géolocalisation, si elle les partage avec d'autres parties ou non et définir le niveau de précision de celles-ci (par exemple grossier, fin, restreint au code postal, etc.). Données de géolocalisation sont généralement considéré comme sensibles car elle peut révéler la localisation de l'utilisateur et, si stocké, l'histoire de leurs voyages. Par conséquent, en plus de la politique de confidentialité de l'application, vous devez envisager fortement fournissant un avis juste-à -temps, avant que l'application accède aux données de géolocalisation (si le système d'exploitation de périphérique n'est pas faire déjà ). Cette notice devrait contenir les informations susmentionnées, ainsi que permettre de recueillir l'autorisation de l'utilisateur (par exemple, en offrant les possibilités **OK** et **Non merci**). Pour plus d'informations, veuillez vous référer à la section "Guide du respect de la vie privée". - -Ce plugin définit un global `navigator.geolocation` objet (pour les plateformes où il est autrement manquant). - -Bien que l'objet est dans la portée globale, les fonctions offertes par ce plugin ne sont pas disponibles jusqu'après la `deviceready` événement. - - document.addEventListener (« deviceready », onDeviceReady, false) ; - function onDeviceReady() {console.log ("navigator.geolocation fonctionne bien");} - - -## Installation - -Pour cela, cordova 5.0 + (1.0.0 stable actuelle) - - cordova plugin add cordova-plugin-geolocation - - -Anciennes versions de cordova peuvent toujours installer via l'id obsolète (rassis 0.3.12) - - Cordova plugin ajouter org.apache.cordova.geolocation - - -Il est également possible d'installer directement via l'url de repo (instable) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## Plates-formes supportées - - * Amazon Fire OS - * Android - * BlackBerry 10 - * Firefox OS - * iOS - * Paciarelli - * Windows Phone 7 et 8 - * Windows 8 - * Windows - -## Méthodes - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## Objets (lecture seule) - - * Position - * PositionError - * Coordonnées - -## navigator.geolocation.getCurrentPosition - -Retourne la position actuelle de l'appareil à la `geolocationSuccess` rappel avec un `Position` objet comme paramètre. Si une erreur se produit, le `geolocationError` rappel est passé un `PositionError` objet. - - navigator.geolocation.getCurrentPosition (geolocationSuccess, [geolocationError], [geolocationOptions]) ; - - -### Paramètres - - * **geolocationSuccess** : la fonction callback à laquelle est transmise la position actuelle. - - * **geolocationError** : *(facultative)* la fonction callback s'exécutant si une erreur survient. - - * **geolocationOptions** : *(facultatives)* des préférences de géolocalisation. - -### Exemple - - onSuccess rappel / / cette méthode accepte un objet de Position, qui contient le / / coordonnées GPS actuel / / var onSuccess = function(position) {alert ('Latitude: ' + position.coords.latitude + « \n » + ' Longitude: ' + position.coords.longitude + « \n » + ' Altitude: ' + position.coords.altitude + « \n » + ' précision: ' + position.coords.accuracy + « \n » + ' Altitude précision: ' + position.coords.altitudeAccuracy + « \n » + ' rubrique: ' + position.coords.heading + « \n » + ' vitesse: ' + position.coords.speed + « \n » + ' Timestamp: ' + position.timestamp + « \n »);} ; - - onError rappel reçoit un objet PositionError / / function onError(error) {alert ('code: "+ error.code + « \n » + ' message: ' + error.message + « \n »);} - - navigator.geolocation.getCurrentPosition (onSuccess, onError) ; - - -## navigator.geolocation.watchPosition - -Retourne la position actuelle de l'appareil lorsqu'un changement de position est détecté. Lorsque l'appareil récupère un nouvel emplacement, le `geolocationSuccess` rappel s'exécute avec un `Position` objet comme paramètre. Si une erreur se produit, le `geolocationError` rappel s'exécute avec un `PositionError` objet comme paramètre. - - var watchId = navigator.geolocation.watchPosition (geolocationSuccess, [geolocationError], [geolocationOptions]) ; - - -### Paramètres - - * **geolocationSuccess** : la fonction callback à laquelle est transmise la position actuelle. - - * **geolocationError** : (facultative) la fonction callback s'exécutant lorsqu'une erreur survient. - - * **geolocationOptions** : (facultatives) options de personnalisation de la géolocalisation. - -### Retours - - * **Chaîne**: retourne un id de montre qui fait référence à l'intervalle de position montre. L'id de la montre doit être utilisé avec `navigator.geolocation.clearWatch` d'arrêter de regarder pour les changements de position. - -### Exemple - - onSuccess rappel / / cette méthode accepte un objet « Position », qui contient / / coordonnées de GPS le courant / / function onSuccess(position) {var element = document.getElementById('geolocation') ; - element.innerHTML = ' Latitude: "+ position.coords.latitude + ' < br / >' + ' Longitude:" + position.coords.longitude + ' < br / >' + ' < hr / >' + element.innerHTML ; - } / / onError rappel reçoit un objet PositionError / / function onError(error) {alert ('code: ' + error.code + « \n » + "message: ' + error.message + « \n »);} - - Options : lever une erreur si aucune mise à jour n'est reçu toutes les 30 secondes. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, { timeout: 30000 }) ; - - -## geolocationOptions - -Paramètres optionnels pour personnaliser la récupération de la géolocalisation`Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true } ; - - -### Options - - * **enableHighAccuracy** : indique que l'application nécessite les meilleurs résultats possibles. Par défaut, l'appareil tente de récupérer une `Position` à l'aide de méthodes basées sur le réseau. Définir cette propriété à `true` demande à Cordova d'utiliser des méthodes plus précises, telles que la localisation par satellite. *(Boolean)* - - * **délai d'attente**: la longueur maximale de temps (en millisecondes) qui peut passer de l'appel à `navigator.geolocation.getCurrentPosition` ou `geolocation.watchPosition` jusqu'à ce que le correspondant `geolocationSuccess` rappel s'exécute. Si `geolocationSuccess` n'est pas appelée dans ce délai, le code d'erreur `PositionError.TIMEOUT` est transmis à la fonction callback `geolocationError`. (Notez que, dans le cas de `geolocation.watchPosition`, la fonction callback `geolocationError` pourrait être appelée à un intervalle régulier de `timeout` millisecondes !) *(Number)* - - * **maximumAge** : accepter une position mise en cache dont l'âge ne dépasse pas le délai spécifié en millisecondes. *(Number)* - -### Quirks Android - -Émulateurs Android 2.x ne pas retournent un résultat de géolocalisation, à moins que le `enableHighAccuracy` option est définie sur`true`. - -## navigator.geolocation.clearWatch - -Arrêter de regarder pour les modifications à l'emplacement de l'appareil référencé par le `watchID` paramètre. - - navigator.geolocation.clearWatch(watchID) ; - - -### Paramètres - - * **watchID** : l'identifiant de l'intervalle `watchPosition` à effacer. (String) - -### Exemple - - Options : suivi des modifications dans la position et utilise le plus / / exacte position méthode d'acquisition disponible. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, { enableHighAccuracy: true }) ; - - .. plus sur... - - navigator.geolocation.clearWatch(watchID) ; - - -## Position - -Contient `Position` coordonnées et timestamp, créé par l'API de géolocalisation. - -### Propriétés - - * **coords** : un ensemble de coordonnées géographiques. *(Coordinates)* - - * **timestamp** : horodatage de la création de `coords`. *(DOMTimeStamp)* - -## Coordonnées - -A `Coordinates` objet est attaché à un `Position` objet qui n'existe pas de fonctions de rappel dans les requêtes pour la position actuelle. Il contient un ensemble de propriétés qui décrivent les coordonnées géographiques d'une position. - -### Propriétés - - * **latitude** : latitude en degrés décimaux. *(Number)* - - * **longitude** : longitude en degrés décimaux. *(Number)* - - * **altitude** : hauteur de la position en mètres au-dessus de l'ellipsoïde. *(Number)* - - * **accuracy** : niveau de précision des valeurs de latitude et longitude, en mètres. *(Number)* - - * **altitudeAccuracy** : niveau de précision de la valeur d'altitude, en mètres. *(Number)* - - * **heading** : direction du trajet, indiquée en degrés comptés dans le sens horaire par rapport au vrai Nord. *(Number)* - - * **speed** : vitesse au sol actuelle de l'appareil, indiquée en mètres par seconde. *(Number)* - -### Amazon Fire OS Quirks - -**altitudeAccuracy**: ne pas pris en charge par les appareils Android, retour`null`. - -### Quirks Android - -**altitudeAccuracy**: ne pas pris en charge par les appareils Android, retour`null`. - -## PositionError - -Le `PositionError` objet est passé à la `geolocationError` fonction de rappel lorsqu'une erreur se produit avec navigator.geolocation. - -### Propriétés - - * **code**: l'un des codes d'erreur prédéfinis énumérés ci-dessous. - - * **message** : un message d'erreur détaillant l'erreur rencontrée. - -### Constantes - - * `PositionError.PERMISSION_DENIED` - * Retourné lorsque les utilisateurs ne permettent pas l'application extraire des informations de position. Cela dépend de la plate-forme. - * `PositionError.POSITION_UNAVAILABLE` - * Retourné lorsque le périphérique n'est pas en mesure de récupérer une position. En général, cela signifie que l'appareil n'est pas connecté à un réseau ou ne peut pas obtenir un correctif de satellite. - * `PositionError.TIMEOUT` - * Retourné lorsque le périphérique n'est pas en mesure de récupérer une position dans le délai précisé par le `timeout` inclus dans `geolocationOptions` . Lorsqu'il est utilisé avec `navigator.geolocation.watchPosition` , cette erreur pourrait être transmise à plusieurs reprises à la `geolocationError` rappel chaque `timeout` millisecondes.
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/fr/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/fr/index.md deleted file mode 100644 index 4d486375..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/fr/index.md +++ /dev/null @@ -1,214 +0,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. ---> - -# cordova-plugin-geolocation - -Ce plugin fournit des informations sur l'emplacement de l'appareil, tels que la latitude et la longitude. Les sources habituelles d'information incluent le Système de Positionnement Global (GPS) et la position déduite de signaux des réseaux tels que l'adresse IP, RFID, les adresses MAC WiFi et Bluetooth et les IDs cellulaires GSM/CDMA. Il n'y a cependant aucune garantie que cette API renvoie la position réelle de l'appareil. - -Cette API est basée sur la [Spécification de l'API Geolocation du W3C][1] et s'exécute uniquement sur les appareils qui n'en proposent pas déjà une implémentation. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**Avertissement**: collecte et utilisation des données de géolocalisation soulève des questions importantes de la vie privée. La politique de confidentialité de votre application devrait traiter de la manière dont l'application utilise les données de géolocalisation, si elle les partage avec d'autres parties ou non et définir le niveau de précision de celles-ci (par exemple grossier, fin, restreint au code postal, etc.). Données de géolocalisation sont généralement considéré comme sensibles car elle peut révéler la localisation de l'utilisateur et, si stocké, l'histoire de leurs voyages. Par conséquent, en plus de la politique de confidentialité de l'application, vous devez envisager fortement fournissant un avis juste-à -temps, avant que l'application accède aux données de géolocalisation (si le système d'exploitation de périphérique n'est pas faire déjà ). Cette notice devrait contenir les informations susmentionnées, ainsi que permettre de recueillir l'autorisation de l'utilisateur (par exemple, en offrant les possibilités **OK** et **Non merci**). Pour plus d'informations, veuillez vous référer à la section "Guide du respect de la vie privée". - -Ce plugin définit un global `navigator.geolocation` objet (pour les plateformes où il est autrement manquant). - -Bien que l'objet est dans la portée globale, les fonctions offertes par ce plugin ne sont pas disponibles jusqu'après la `deviceready` événement. - - document.addEventListener (« deviceready », onDeviceReady, false) ; - function onDeviceReady() {console.log ("navigator.geolocation fonctionne bien");} - - -## Installation - - Cordova plugin ajouter cordova-plugin-geolocation - - -## Plates-formes prises en charge - -* Amazon Fire OS -* Android -* BlackBerry 10 -* Firefox OS -* iOS -* Paciarelli -* Windows Phone 7 et 8 -* Windows 8 - -## Méthodes - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## Objets (lecture seule) - -* Position -* PositionError -* Coordonnées - -## navigator.geolocation.getCurrentPosition - -Retourne la position actuelle de l'appareil à la `geolocationSuccess` rappel avec un `Position` objet comme paramètre. Si une erreur se produit, le `geolocationError` rappel est passé un `PositionError` objet. - - navigator.geolocation.getCurrentPosition (geolocationSuccess, [geolocationError], [geolocationOptions]) ; - - -### Paramètres - -* **geolocationSuccess** : la fonction callback à laquelle est transmise la position actuelle. - -* **geolocationError** : *(facultative)* la fonction callback s'exécutant si une erreur survient. - -* **geolocationOptions** : *(facultatives)* des préférences de géolocalisation. - -### Exemple - - onSuccess rappel / / cette méthode accepte un objet de Position, qui contient le / / coordonnées GPS actuel / / var onSuccess = function(position) {alert ('Latitude: ' + position.coords.latitude + « \n » + ' Longitude: ' + position.coords.longitude + « \n » + ' Altitude: ' + position.coords.altitude + « \n » + ' précision: ' + position.coords.accuracy + « \n » + ' Altitude précision: ' + position.coords.altitudeAccuracy + « \n » + ' rubrique: ' + position.coords.heading + « \n » + ' vitesse: ' + position.coords.speed + « \n » + ' Timestamp: ' + position.timestamp + « \n »);} ; - - onError rappel reçoit un objet PositionError / / function onError(error) {alert ('code: "+ error.code + « \n » + ' message: ' + error.message + « \n »);} - - navigator.geolocation.getCurrentPosition (onSuccess, onError) ; - - -## navigator.geolocation.watchPosition - -Retourne la position actuelle de l'appareil lorsqu'un changement de position est détecté. Lorsque l'appareil récupère un nouvel emplacement, le `geolocationSuccess` rappel s'exécute avec un `Position` objet comme paramètre. Si une erreur se produit, le `geolocationError` rappel s'exécute avec un `PositionError` objet comme paramètre. - - var watchId = navigator.geolocation.watchPosition (geolocationSuccess, [geolocationError], [geolocationOptions]) ; - - -### Paramètres - -* **geolocationSuccess**: la fonction de rappel qui est passée de la position actuelle. - -* **geolocationError** : (facultative) la fonction callback s'exécutant lorsqu'une erreur survient. - -* **geolocationOptions** : (facultatives) options de personnalisation de la géolocalisation. - -### Retours - -* **Chaîne**: retourne un id de montre qui fait référence à l'intervalle de position montre. L'id de la montre doit être utilisé avec `navigator.geolocation.clearWatch` d'arrêter de regarder pour les changements de position. - -### Exemple - - onSuccess rappel / / cette méthode accepte un objet « Position », qui contient / / coordonnées de GPS le courant / / function onSuccess(position) {var element = document.getElementById('geolocation') ; - element.innerHTML = ' Latitude: "+ position.coords.latitude + ' < br / >' + ' Longitude:" + position.coords.longitude + ' < br / >' + ' < hr / >' + element.innerHTML ; - } / / onError rappel reçoit un objet PositionError / / function onError(error) {alert ('code: ' + error.code + « \n » + "message: ' + error.message + « \n »);} - - Options : lever une erreur si aucune mise à jour n'est reçu toutes les 30 secondes. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, { timeout: 30000 }) ; - - -## geolocationOptions - -Paramètres optionnels pour personnaliser la récupération de la géolocalisation`Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true } ; - - -### Options - -* **enableHighAccuracy** : indique que l'application nécessite les meilleurs résultats possibles. Par défaut, l'appareil tente de récupérer une `Position` à l'aide de méthodes basées sur le réseau. Définir cette propriété à `true` demande à Cordova d'utiliser des méthodes plus précises, telles que la localisation par satellite. *(Boolean)* - -* **délai d'attente**: la longueur maximale de temps (en millisecondes) qui peut passer de l'appel à `navigator.geolocation.getCurrentPosition` ou `geolocation.watchPosition` jusqu'à ce que le correspondant `geolocationSuccess` rappel s'exécute. Si `geolocationSuccess` n'est pas appelée dans ce délai, le code d'erreur `PositionError.TIMEOUT` est transmis à la fonction callback `geolocationError`. (Notez que, dans le cas de `geolocation.watchPosition`, la fonction callback `geolocationError` pourrait être appelée à un intervalle régulier de `timeout` millisecondes !) *(Number)* - -* **maximumAge** : accepter une position mise en cache dont l'âge ne dépasse pas le délai spécifié en millisecondes. *(Number)* - -### Quirks Android - -Émulateurs Android 2.x ne pas retournent un résultat de géolocalisation, à moins que le `enableHighAccuracy` option est définie sur`true`. - -## navigator.geolocation.clearWatch - -Arrêter de regarder pour les modifications à l'emplacement de l'appareil référencé par le `watchID` paramètre. - - navigator.geolocation.clearWatch(watchID) ; - - -### Paramètres - -* **watchID** : l'identifiant de l'intervalle `watchPosition` à effacer. (String) - -### Exemple - - Options : suivi des modifications dans la position et utilise le plus / / exacte position méthode d'acquisition disponible. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, { enableHighAccuracy: true }) ; - - .. plus sur... - - navigator.geolocation.clearWatch(watchID) ; - - -## Position - -Contient `Position` coordonnées et timestamp, créé par l'API de géolocalisation. - -### Propriétés - -* **coords** : un ensemble de coordonnées géographiques. *(Coordinates)* - -* **timestamp** : horodatage de la création de `coords`. *(DOMTimeStamp)* - -## Coordonnées - -A `Coordinates` objet est attaché à un `Position` objet qui n'existe pas de fonctions de rappel dans les requêtes pour la position actuelle. Il contient un ensemble de propriétés qui décrivent les coordonnées géographiques d'une position. - -### Propriétés - -* **latitude** : latitude en degrés décimaux. *(Number)* - -* **longitude** : longitude en degrés décimaux. *(Number)* - -* **altitude** : hauteur de la position en mètres au-dessus de l'ellipsoïde. *(Number)* - -* **accuracy** : niveau de précision des valeurs de latitude et longitude, en mètres. *(Number)* - -* **altitudeAccuracy** : niveau de précision de la valeur d'altitude, en mètres. *(Number)* - -* **heading** : direction du trajet, indiquée en degrés comptés dans le sens horaire par rapport au vrai Nord. *(Number)* - -* **speed** : vitesse au sol actuelle de l'appareil, indiquée en mètres par seconde. *(Number)* - -### Amazon Fire OS Quirks - -**altitudeAccuracy**: ne pas pris en charge par les appareils Android, retour`null`. - -### Quirks Android - -**altitudeAccuracy**: ne pas pris en charge par les appareils Android, retour`null`. - -## PositionError - -Le `PositionError` objet est passé à la `geolocationError` fonction de rappel lorsqu'une erreur se produit avec navigator.geolocation. - -### Propriétés - -* **code**: l'un des codes d'erreur prédéfinis énumérés ci-dessous. - -* **message** : un message d'erreur détaillant l'erreur rencontrée. - -### Constantes - -* `PositionError.PERMISSION_DENIED` - * Retourné lorsque les utilisateurs ne permettent pas l'application extraire des informations de position. Cela dépend de la plate-forme. -* `PositionError.POSITION_UNAVAILABLE` - * Retourné lorsque le périphérique n'est pas en mesure de récupérer une position. En général, cela signifie que l'appareil n'est pas connecté à un réseau ou ne peut pas obtenir un correctif de satellite. -* `PositionError.TIMEOUT` - * Retourné lorsque le périphérique n'est pas en mesure de récupérer une position dans le délai précisé par le `timeout` inclus dans `geolocationOptions` . Lorsqu'il est utilisé avec `navigator.geolocation.watchPosition` , cette erreur pourrait être transmise à plusieurs reprises à la `geolocationError` rappel chaque `timeout` millisecondes. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/it/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/it/README.md deleted file mode 100644 index ffa472b3..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/it/README.md +++ /dev/null @@ -1,268 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -Questo plugin fornisce informazioni sulla posizione del dispositivo, come latitudine e longitudine. Comuni fonti di informazioni sulla posizione comprendono Global Positioning System (GPS) e posizione dedotta dai segnali di rete come indirizzo IP, indirizzi, RFID, WiFi e Bluetooth MAC e cellulare GSM/CDMA IDs. Non non c'è alcuna garanzia che l'API restituisce la posizione effettiva del dispositivo. - -Questa API è basata sulla [Specifica di W3C Geolocation API](http://dev.w3.org/geo/api/spec-source.html)e viene eseguito solo su dispositivi che non già forniscono un'implementazione. - -**Avviso**: raccolta e utilizzo dei dati di geolocalizzazione solleva questioni di privacy importante. Politica sulla privacy dell'app dovrebbe discutere come app utilizza dati di geolocalizzazione, se è condiviso con altre parti e il livello di precisione dei dati (ad esempio, Cap grossolana, fine, livello, ecc.). Dati di geolocalizzazione sono generalmente considerati sensibili perché può rivelare la sorte dell'utente e, se conservati, la storia dei loro viaggi. Pertanto, oltre alla politica di privacy dell'app, è fortemente consigliabile fornendo un preavviso di just-in-time prima app accede ai dati di geolocalizzazione (se il sistema operativo del dispositivo non farlo già ). Tale comunicazione deve fornire le informazioni stesse notate sopra, oltre ad ottenere l'autorizzazione (ad esempio, presentando scelte per **OK** e **No grazie**). Per ulteriori informazioni, vedere la guida sulla Privacy. - -Questo plugin definisce un oggetto globale `navigator.geolocation` (per le piattaforme dove altrimenti è manca). - -Sebbene l'oggetto sia in ambito globale, funzionalità fornite da questo plugin non sono disponibili fino a dopo l'evento `deviceready`. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Installazione - -Ciò richiede cordova 5.0 + (attuale stabile 1.0.0) - - cordova plugin add cordova-plugin-geolocation - - -Versioni precedenti di cordova comunque possono installare tramite l'id deprecata (stantio 0.3.12) - - cordova plugin add org.apache.cordova.geolocation - - -È anche possibile installare direttamente tramite url di repo (instabile) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## Piattaforme supportate - - * Amazon fuoco OS - * Android - * BlackBerry 10 - * Firefox OS - * iOS - * Tizen - * Windows Phone 7 e 8 - * Windows 8 - * Windows - -## Metodi - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## Oggetti (sola lettura) - - * Position - * PositionError - * Coordinates - -## navigator.geolocation.getCurrentPosition - -Restituisce la posizione corrente del dispositivo il callback di `geolocationSuccess` con un `Position` di oggetto come parametro. Se c'è un errore, `geolocationError` callback viene passato un oggetto `PositionError`. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametri - - * **geolocationSuccess**: il callback passato alla posizione corrente. - - * **geolocationError**: *(facoltativo)* il callback che viene eseguito se si verifica un errore. - - * **geolocationOptions**: *(opzionale)* le opzioni di geolocalizzazione. - -### Esempio - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Restituisce la posizione corrente del dispositivo quando viene rilevata una modifica della posizione. Quando il dispositivo recupera una nuova posizione, il callback `geolocationSuccess` esegue con un `Position` di oggetto come parametro. Se c'è un errore, `geolocationError` callback viene eseguito con un oggetto `PositionError` come parametro. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametri - - * **geolocationSuccess**: il callback passato alla posizione corrente. - - * **geolocationError**: (facoltativo) il callback che viene eseguito se si verifica un errore. - - * **geolocationOptions**: opzioni (opzionale) la geolocalizzazione. - -### Restituisce - - * **Stringa**: restituisce un id di orologio che fa riferimento l'intervallo di posizione orologio. L'id dell'orologio deve essere usato con `navigator.geolocation.clearWatch` a smettere di guardare per cambiamenti di posizione. - -### Esempio - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Parametri opzionali per personalizzare il recupero di geolocalizzazione `Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Opzioni - - * **enableHighAccuracy**: fornisce un suggerimento che l'applicazione ha bisogno i migliori risultati possibili. Per impostazione predefinita, il dispositivo tenta di recuperare un `Position` usando metodi basati sulla rete. Impostando questa proprietà su `true` indica al framework di utilizzare metodi più accurati, come posizionamento satellitare. *(Boolean)* - - * **timeout**: la lunghezza massima di tempo (in millisecondi) che è consentito per passare dalla chiamata a `navigator.geolocation.getCurrentPosition` o `geolocation.watchPosition` fino a quando il corrispondente `geolocationSuccess` callback viene eseguito. Se il `geolocationSuccess` callback non viene richiamato entro questo tempo, il `geolocationError` callback viene passata una `PositionError.TIMEOUT` codice di errore. (Si noti che, quando utilizzato in combinazione con `geolocation.watchPosition` , il `geolocationError` callback potrebbe essere chiamato un intervallo ogni `timeout` millisecondi!) *(Numero)* - - * **maximumAge**: accettare una posizione memorizzata nella cache in cui età è minore il tempo specificato in millisecondi. *(Numero)* - -### Stranezze Android - -Emulatori Android 2. x non restituiscono un risultato di geolocalizzazione a meno che l'opzione `enableHighAccuracy` è impostata su `true`. - -## navigator.geolocation.clearWatch - -Smettere di guardare per le modifiche alla posizione del dispositivo a cui fa riferimento il parametro `watchID`. - - navigator.geolocation.clearWatch(watchID); - - -### Parametri - - * **watchID**: l'id del `watchPosition` intervallo per cancellare. (String) - -### Esempio - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Contiene le coordinate della `Position` e timestamp, creato da geolocation API. - -### Proprietà - - * **CoOrds**: un insieme di coordinate geografiche. *(Coordinate)* - - * **timestamp**: timestamp di creazione per `coords` . *(DOMTimeStamp)* - -## Coordinates - -Un oggetto `Coordinates` è associato a un oggetto `Position` disponibile per le funzioni di callback in richieste per la posizione corrente. Contiene un insieme di proprietà che descrivono le coordinate geografiche di una posizione. - -### Proprietà - - * **latitudine**: latitudine in gradi decimali. *(Numero)* - - * **longitudine**: longitudine in gradi decimali. *(Numero)* - - * **altitudine**: altezza della posizione in metri sopra l'ellissoide. *(Numero)* - - * **accuratezza**: livello di accuratezza delle coordinate latitudine e longitudine in metri. *(Numero)* - - * **altitudeAccuracy**: livello di accuratezza della coordinata altitudine in metri. *(Numero)* - - * **rubrica**: senso di marcia, specificata in gradi in senso orario rispetto al vero nord di conteggio. *(Numero)* - - * **velocità **: velocità attuale terra del dispositivo, specificato in metri al secondo. *(Numero)* - -### Amazon fuoco OS stranezze - -**altitudeAccuracy**: non supportato dai dispositivi Android, restituendo `null`. - -### Stranezze Android - -**altitudeAccuracy**: non supportato dai dispositivi Android, restituendo `null`. - -## PositionError - -L'oggetto `PositionError` viene passato alla funzione di callback `geolocationError` quando si verifica un errore con navigator.geolocation. - -### Proprietà - - * **codice**: uno dei codici di errore predefiniti elencati di seguito. - - * **messaggio**: messaggio di errore che descrive i dettagli dell'errore rilevato. - -### Costanti - - * `PositionError.PERMISSION_DENIED` - * Restituito quando gli utenti non consentono l'applicazione recuperare le informazioni di posizione. Questo è dipendente dalla piattaforma. - * `PositionError.POSITION_UNAVAILABLE` - * Restituito quando il dispositivo è in grado di recuperare una posizione. In generale, questo significa che il dispositivo non è connesso a una rete o non può ottenere un fix satellitare. - * `PositionError.TIMEOUT` - * Restituito quando il dispositivo è in grado di recuperare una posizione entro il tempo specificato dal `timeout` incluso `geolocationOptions` . Quando utilizzato con `navigator.geolocation.watchPosition` , questo errore potrebbe essere passato più volte per la `geolocationError` richiamata ogni `timeout` millisecondi.
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/it/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/it/index.md deleted file mode 100644 index 7ba7c5c6..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/it/index.md +++ /dev/null @@ -1,255 +0,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. ---> - -# cordova-plugin-geolocation - -Questo plugin fornisce informazioni sulla posizione del dispositivo, come latitudine e longitudine. Comuni fonti di informazioni sulla posizione comprendono Global Positioning System (GPS) e posizione dedotta dai segnali di rete come indirizzo IP, indirizzi, RFID, WiFi e Bluetooth MAC e cellulare GSM/CDMA IDs. Non non c'è alcuna garanzia che l'API restituisce la posizione effettiva del dispositivo. - -Questa API è basata sulla [Specifica di W3C Geolocation API][1]e viene eseguito solo su dispositivi che non già forniscono un'implementazione. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**Avviso**: raccolta e utilizzo dei dati di geolocalizzazione solleva questioni di privacy importante. Politica sulla privacy dell'app dovrebbe discutere come app utilizza dati di geolocalizzazione, se è condiviso con altre parti e il livello di precisione dei dati (ad esempio, Cap grossolana, fine, livello, ecc.). Dati di geolocalizzazione sono generalmente considerati sensibili perché può rivelare la sorte dell'utente e, se conservati, la storia dei loro viaggi. Pertanto, oltre alla politica di privacy dell'app, è fortemente consigliabile fornendo un preavviso di just-in-time prima app accede ai dati di geolocalizzazione (se il sistema operativo del dispositivo non farlo già ). Tale comunicazione deve fornire le informazioni stesse notate sopra, oltre ad ottenere l'autorizzazione (ad esempio, presentando scelte per **OK** e **No grazie**). Per ulteriori informazioni, vedere la guida sulla Privacy. - -Questo plugin definisce un oggetto globale `navigator.geolocation` (per le piattaforme dove altrimenti è manca). - -Sebbene l'oggetto sia in ambito globale, funzionalità fornite da questo plugin non sono disponibili fino a dopo l'evento `deviceready`. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Installazione - - cordova plugin add cordova-plugin-geolocation - - -## Piattaforme supportate - -* Amazon fuoco OS -* Android -* BlackBerry 10 -* Firefox OS -* iOS -* Tizen -* Windows Phone 7 e 8 -* Windows 8 - -## Metodi - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## Oggetti (sola lettura) - -* Position -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -Restituisce la posizione corrente del dispositivo il callback di `geolocationSuccess` con un `Position` di oggetto come parametro. Se c'è un errore, `geolocationError` callback viene passato un oggetto `PositionError`. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametri - -* **geolocationSuccess**: il callback passato alla posizione corrente. - -* **geolocationError**: *(facoltativo)* il callback che viene eseguito se si verifica un errore. - -* **geolocationOptions**: *(opzionale)* le opzioni di geolocalizzazione. - -### Esempio - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Restituisce la posizione corrente del dispositivo quando viene rilevata una modifica della posizione. Quando il dispositivo recupera una nuova posizione, il callback `geolocationSuccess` esegue con un `Position` di oggetto come parametro. Se c'è un errore, `geolocationError` callback viene eseguito con un oggetto `PositionError` come parametro. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametri - -* **geolocationSuccess**: il callback passato alla posizione corrente. - -* **geolocationError**: (facoltativo) il callback che viene eseguito se si verifica un errore. - -* **geolocationOptions**: opzioni (opzionale) la geolocalizzazione. - -### Restituisce - -* **Stringa**: restituisce un id di orologio che fa riferimento l'intervallo di posizione orologio. L'id dell'orologio deve essere usato con `navigator.geolocation.clearWatch` a smettere di guardare per cambiamenti di posizione. - -### Esempio - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Parametri opzionali per personalizzare il recupero di geolocalizzazione `Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Opzioni - -* **enableHighAccuracy**: fornisce un suggerimento che l'applicazione ha bisogno i migliori risultati possibili. Per impostazione predefinita, il dispositivo tenta di recuperare un `Position` usando metodi basati sulla rete. Impostando questa proprietà su `true` indica al framework di utilizzare metodi più accurati, come posizionamento satellitare. *(Boolean)* - -* **timeout**: la lunghezza massima di tempo (in millisecondi) che è consentito per passare dalla chiamata a `navigator.geolocation.getCurrentPosition` o `geolocation.watchPosition` fino a quando il corrispondente `geolocationSuccess` callback viene eseguito. Se il `geolocationSuccess` callback non viene richiamato entro questo tempo, il `geolocationError` callback viene passata una `PositionError.TIMEOUT` codice di errore. (Si noti che, quando utilizzato in combinazione con `geolocation.watchPosition` , il `geolocationError` callback potrebbe essere chiamato un intervallo ogni `timeout` millisecondi!) *(Numero)* - -* **maximumAge**: accettare una posizione memorizzata nella cache in cui età è minore il tempo specificato in millisecondi. *(Numero)* - -### Stranezze Android - -Emulatori Android 2. x non restituiscono un risultato di geolocalizzazione a meno che l'opzione `enableHighAccuracy` è impostata su `true`. - -## navigator.geolocation.clearWatch - -Smettere di guardare per le modifiche alla posizione del dispositivo a cui fa riferimento il parametro `watchID`. - - navigator.geolocation.clearWatch(watchID); - - -### Parametri - -* **watchID**: l'id del `watchPosition` intervallo per cancellare. (String) - -### Esempio - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Contiene le coordinate della `Position` e timestamp, creato da geolocation API. - -### Proprietà - -* **CoOrds**: un insieme di coordinate geografiche. *(Coordinate)* - -* **timestamp**: timestamp di creazione per `coords` . *(DOMTimeStamp)* - -## Coordinates - -Un oggetto `Coordinates` è associato a un oggetto `Position` disponibile per le funzioni di callback in richieste per la posizione corrente. Contiene un insieme di proprietà che descrivono le coordinate geografiche di una posizione. - -### Proprietà - -* **latitudine**: latitudine in gradi decimali. *(Numero)* - -* **longitudine**: longitudine in gradi decimali. *(Numero)* - -* **altitudine**: altezza della posizione in metri sopra l'ellissoide. *(Numero)* - -* **accuratezza**: livello di accuratezza delle coordinate latitudine e longitudine in metri. *(Numero)* - -* **altitudeAccuracy**: livello di accuratezza della coordinata altitudine in metri. *(Numero)* - -* **rubrica**: senso di marcia, specificata in gradi in senso orario rispetto al vero nord di conteggio. *(Numero)* - -* **velocità **: velocità attuale terra del dispositivo, specificato in metri al secondo. *(Numero)* - -### Amazon fuoco OS stranezze - -**altitudeAccuracy**: non supportato dai dispositivi Android, restituendo `null`. - -### Stranezze Android - -**altitudeAccuracy**: non supportato dai dispositivi Android, restituendo `null`. - -## PositionError - -L'oggetto `PositionError` viene passato alla funzione di callback `geolocationError` quando si verifica un errore con navigator.geolocation. - -### Proprietà - -* **codice**: uno dei codici di errore predefiniti elencati di seguito. - -* **messaggio**: messaggio di errore che descrive i dettagli dell'errore rilevato. - -### Costanti - -* `PositionError.PERMISSION_DENIED` - * Restituito quando gli utenti non consentono l'applicazione recuperare le informazioni di posizione. Questo è dipendente dalla piattaforma. -* `PositionError.POSITION_UNAVAILABLE` - * Restituito quando il dispositivo è in grado di recuperare una posizione. In generale, questo significa che il dispositivo non è connesso a una rete o non può ottenere un fix satellitare. -* `PositionError.TIMEOUT` - * Restituito quando il dispositivo è in grado di recuperare una posizione entro il tempo specificato dal `timeout` incluso `geolocationOptions` . Quando utilizzato con `navigator.geolocation.watchPosition` , questo errore potrebbe essere passato più volte per la `geolocationError` richiamata ogni `timeout` millisecondi. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ja/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/ja/README.md deleted file mode 100644 index 59c5ed6c..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ja/README.md +++ /dev/null @@ -1,268 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -ã“ã®ãƒ—ラグインã¯ç·¯åº¦ã‚„経度ãªã©ã®ãƒ‡ãƒã‚¤ã‚¹ã®å ´æ‰€ã«é–¢ã™ã‚‹æƒ…å ±ã‚’æä¾›ã—ã¾ã™ã€‚ ä½ç½®æƒ…å ±ã®å…±é€šã®ã‚½ãƒ¼ã‚¹ã¯ã‚°ãƒãƒ¼ãƒãƒ« ãƒã‚¸ã‚·ãƒ§ãƒ‹ãƒ³ã‚° システム(GPS) 㨠IP アドレスã€RFIDã€WiFi ãŠã‚ˆã³ Bluetooth ã® MAC アドレスã€ãŠã‚ˆã³ GSM/cdma æ–¹å¼æºå¸¯ Id ãªã©ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¿¡å·ã‹ã‚‰æŽ¨å®šã•ã‚Œã‚‹å ´æ‰€ã«ã‚‚ã‚りã¾ã™ã€‚ API ã¯ã€ãƒ‡ãƒã‚¤ã‚¹ã®å®Ÿéš›ã®å ´æ‰€ã‚’è¿”ã™ã“ã¨ã®ä¿è¨¼ã¯ã‚りã¾ã›ã‚“。 - -ã“ã® API ã¯[W3C 地ç†ä½ç½®æƒ…å ± API 仕様](http://dev.w3.org/geo/api/spec-source.html)ã«åŸºã¥ã„ã¦ãŠã‚Šã€æ—¢ã«å®Ÿè£…ã‚’æä¾›ã—ãªã„デãƒã‚¤ã‚¹ä¸Šã®ã¿ã§å®Ÿè¡Œã—ã¾ã™ã€‚ - -**è¦å‘Š**: 地ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã®åŽé›†ã¨åˆ©ç”¨ã‚’é‡è¦ãªãƒ—ライãƒã‚·ãƒ¼ã®å•題を発生ã•ã›ã¾ã™ã€‚ アプリã®ãƒ—ライãƒã‚·ãƒ¼ ãƒãƒªã‚·ãƒ¼ã¯ä»–ã®å½“事者ã¨ãƒ‡ãƒ¼ã‚¿ (ãŸã¨ãˆã°ã€ç²—ã„ã€ç½°é‡‘ã€éƒµä¾¿ç•ªå·ãƒ¬ãƒ™ãƒ«ã€ç‰) ã®ç²¾åº¦ã®ãƒ¬ãƒ™ãƒ«ã§ã¯å…±æœ‰ã•れã¦ã„ã‚‹ã‹ã©ã†ã‹ã€ã‚¢ãƒ—リãŒåœ°ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã‚’ä½¿ç”¨ã™ã‚‹æ–¹æ³•ã‚’è°è«–ã™ã¹ãã§ã™ã€‚ 地ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã¨ä¸€èˆ¬ã«è¦‹ãªã•ã‚Œã‚‹æ•æ„Ÿãªãƒ¦ãƒ¼ã‚¶ãƒ¼ã®å±…å ´æ‰€ã‚’é–‹ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã®ã§ã€å½¼ã‚‰ã®æ—…è¡Œã®æ´å²ä¿å˜ã•れã¦ã„ã‚‹å ´åˆã€‚ ã—ãŸãŒã£ã¦ã€ã‚¢ãƒ—リã®ãƒ—ライãƒã‚·ãƒ¼ ãƒãƒªã‚·ãƒ¼ã«åŠ ãˆã¦ã€å¼·ãã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ (デãƒã‚¤ã‚¹ オペレーティング システムã—ãªã„å ´åˆãã†æ—¢ã«)ã€ã‚¢ãƒ—リケーションã«åœ°ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã‚’ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å‰ã« - 時間ã®ãŠçŸ¥ã‚‰ã›ã‚’æä¾›ã—ã¾ã™ã€‚ ãã®é€šçŸ¥ã¯ã€ä¸Šè¨˜ã® (例ãˆã°ã€ **[ok]**ã‚’**ãŠã‹ã’ã§**é¸æŠžè‚¢ã‚’æç¤ºã™ã‚‹) ã«ã‚ˆã£ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã‚’å–å¾—ã™ã‚‹ã ã‘ã§ãªãã€åŒã˜æƒ…å ±ã‚’æä¾›ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ 詳細ã«ã¤ã„ã¦ã¯ã€ãƒ—ライãƒã‚·ãƒ¼ã«é–¢ã™ã‚‹ã‚¬ã‚¤ãƒ‰ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 - -ã“ã®ãƒ—ラグインã¯ã€ã‚°ãƒãƒ¼ãƒãƒ« `navigator.geolocation` オブジェクト (ãƒ—ãƒ©ãƒƒãƒˆãƒ•ã‚©ãƒ¼ãƒ è¡Œæ–¹ä¸æ˜Žã§ã™ãれ以外ã®å ´åˆ) を定義ã—ã¾ã™ã€‚ - -オブジェクトã¯ã€ã‚°ãƒãƒ¼ãƒãƒ« スコープã§ã§ã™ãŒã€ã“ã®ãƒ—ラグインã«ã‚ˆã£ã¦æä¾›ã•れる機能ã¯ã€`deviceready` イベントã®å¾Œã¾ã§ä½¿ç”¨ã§ãã¾ã›ã‚“。 - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## インストール - -ã“れã¯ã‚³ãƒ«ãƒ‰ãƒ 5.0 + (ç¾åœ¨å®‰å®š 1.0.0) ã‚’å¿…è¦ã¨ã—ã¾ã™ã€‚ - - cordova plugin add cordova-plugin-geolocation - - -コルドãƒã®å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ã‚‚éžæŽ¨å¥¨ id (å¤ã„ 0.3.12 ã¨) 経由ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™ã€‚ - - cordova plugin add org.apache.cordova.geolocation - - -ã¾ãŸã€ãƒ¬ãƒã® url 経由ã§ç›´æŽ¥ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã (ä¸å®‰å®š) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## サãƒãƒ¼ãƒˆã•れã¦ã„るプラットフォーム- - * ã‚¢ãƒžã‚¾ãƒ³ç« OS - * アンドãƒã‚¤ãƒ‰ - * ブラックベリー 10 - * Firefox ã® OS - * iOS - * Tizen - * Windows Phone 7 㨠8 - * Windows 8 - * Windows - -## メソッド - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## オブジェクト (èªã¿å–り専用) - - * Position - * PositionError - * Coordinates - -## navigator.geolocation.getCurrentPosition - -`Position` オブジェクトを `geolocationSuccess` コールãƒãƒƒã‚¯ã«ãƒ‘ラメーターã¨ã—ã¦ãƒ‡ãƒã‚¤ã‚¹ã®ç¾åœ¨ä½ç½®ã‚’è¿”ã—ã¾ã™ã€‚ エラーãŒã‚ã‚‹å ´åˆ `geolocationError` コールãƒãƒƒã‚¯ã«ã¯ã€`PositionError` ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæ¸¡ã•れã¾ã™ã€‚ - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### パラメーター - - * **geolocationSuccess**: ç¾åœ¨ã®ä½ç½®ã‚’渡ã•れるコールãƒãƒƒã‚¯ã€‚ - - * **geolocationError**: *(çœç•¥å¯èƒ½)*エラーãŒç™ºç”Ÿã—ãŸå ´åˆã«å®Ÿè¡Œã•れるコールãƒãƒƒã‚¯ã€‚ - - * **geolocationOptions**: *(オプション)*地ç†ä½ç½®æƒ…å ±ã®ã‚ªãƒ—ションã§ã™ã€‚ - -### 例 - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -ä½ç½®ã®å¤‰æ›´ãŒæ¤œå‡ºã•れãŸå ´åˆã¯ã€ãƒ‡ãƒã‚¤ã‚¹ã®ç¾åœ¨ä½ç½®ã‚’è¿”ã—ã¾ã™ã€‚ å–å¾—ã•れるã¨ã€ãƒ‡ãƒã‚¤ã‚¹ã®æ–°ã—ã„å ´æ‰€ã€`geolocationSuccess` コールãƒãƒƒã‚¯ パラメーターã¨ã—㦠`ä½ç½®` オブジェクトを実行ã—ã¾ã™ã€‚ エラーãŒã‚ã‚‹å ´åˆã€`geolocationError` コールãƒãƒƒã‚¯ パラメーターã¨ã—㦠`PositionError` オブジェクトã§å®Ÿè¡Œã—ã¾ã™ã€‚ - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### パラメーター - - * **geolocationSuccess**: ç¾åœ¨ã®ä½ç½®ã‚’渡ã•れるコールãƒãƒƒã‚¯ã€‚ - - * **geolocationError**: (çœç•¥å¯èƒ½) エラーãŒç™ºç”Ÿã—ãŸå ´åˆã«å®Ÿè¡Œã•れるコールãƒãƒƒã‚¯ã€‚ - - * **geolocationOptions**: (オプション) 地ç†ä½ç½®æƒ…å ±ã®ã‚ªãƒ—ションã§ã™ã€‚ - -### è¿”ã—ã¾ã™ - - * **æ–‡å—列**: 時計ã®ä½ç½®ã®é–“隔をå‚ç…§ã™ã‚‹æ™‚計 id ã‚’è¿”ã—ã¾ã™ã€‚ 時計 id ã§ä½¿ç”¨ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ `navigator.geolocation.clearWatch` åœæ¢ä½ç½®ã®å¤‰åŒ–を監視ã—ã¾ã™ã€‚ - -### 例 - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -地ç†ä½ç½®æƒ…å ± `ã®ä½ç½®` ã®æ¤œç´¢ã‚’カスタマイズã™ã‚‹ãŸã‚ã®çœç•¥å¯èƒ½ãªãƒ‘ラメーター. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### オプション - - * **enableHighAccuracy**: 最高ã®çµæžœãŒã€ã‚¢ãƒ—リケーションã«å¿…è¦ãŒã‚ã‚‹ã“ã¨ã®ãƒ’ントを示ã—ã¾ã™ã€‚ 既定ã§ã¯ã€ãƒ‡ãƒã‚¤ã‚¹ã®å–得を試ã¿ã¾ã™ã€ `Position` ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ ベースã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’使用ã—ã¾ã™ã€‚ ã“ã®ãƒ—ãƒãƒ‘ティをè¨å®šã™ã‚‹ `true` 衛星測ä½ãªã©ã®ã‚ˆã‚Šæ£ç¢ºãªæ–¹æ³•を使用ã™ã‚‹ãŸã‚ã«ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯ã«æŒ‡ç¤ºã—ã¾ã™ã€‚ *(ブール値)* - - * **タイムアウト**: ã¸ã®å‘¼ã³å‡ºã—ã‹ã‚‰é€šéŽãŒè¨±å¯ã•れる時間 (ミリ秒å˜ä½) ã®æœ€å¤§é•· `navigator.geolocation.getCurrentPosition` ã¾ãŸã¯ `geolocation.watchPosition` ã¾ã§å¯¾å¿œã™ã‚‹ã€ `geolocationSuccess` コールãƒãƒƒã‚¯ã‚’実行ã—ã¾ã™ã€‚ å ´åˆã¯ã€ `geolocationSuccess` ã“ã®æ™‚間内ã«ã€ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“〠`geolocationError` コールãƒãƒƒã‚¯ã«æ¸¡ã•れる〠`PositionError.TIMEOUT` ã®ã‚¨ãƒ©ãƒ¼ コード。 (ã¨çµ„ã¿åˆã‚ã›ã¦ä½¿ç”¨ã™ã‚‹ã¨ãã«æ³¨æ„ã—ã¦ãã ã•ã„ `geolocation.watchPosition` ã® `geolocationError` é–“éš”ã§ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã‚’呼ã³å‡ºã™ã“ã¨ãŒã§ãã¾ã™ã™ã¹ã¦ `timeout` ミリ秒 ï¼)*(æ•°)* - - * **maximumAge**: å¹´é½¢ãŒã‚るミリ秒å˜ä½ã§æŒ‡å®šã—ãŸæ™‚間よりも大ãããªã„ã‚ャッシュã•れãŸä½ç½®ã‚’å—ã‘入れã¾ã™ã€‚*(æ•°)* - -### Android ã®ç™– - -`enableHighAccuracy` オプション㌠`true` ã«è¨å®šã—ãªã„é™ã‚Šã€ã‚¢ãƒ³ãƒ‰ãƒã‚¤ãƒ‰ 2.x エミュレーター地ç†ä½ç½®æƒ…å ±ã®çµæžœã‚’è¿”ã•ãªã„. - -## navigator.geolocation.clearWatch - -`watchID` パラメーターã«ã‚ˆã£ã¦å‚ç…§ã•れるã€ãƒ‡ãƒã‚¤ã‚¹ã®å ´æ‰€ã¸ã®å¤‰æ›´ã‚’見ã¦åœæ¢ã—ã¾ã™ã€‚ - - navigator.geolocation.clearWatch(watchID); - - -### パラメーター - - * **watchID**: ã® id〠`watchPosition` をクリアã™ã‚‹é–“隔。(æ–‡å—列) - -### 例 - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -`Position` 座標ã¨åœ°ç†ä½ç½®æƒ…å ± API ã§ä½œæˆã•れãŸã‚¿ã‚¤ãƒ スタンプãŒå«ã¾ã‚Œã¾ã™ã€‚ - -### プãƒãƒ‘ティ - - * **coords**: 地ç†çš„座標ã®ã‚»ãƒƒãƒˆã€‚*(座標)* - - * **timestamp**: 作æˆã®ã‚¿ã‚¤ãƒ スタンプを `coords` 。*(DOMTimeStamp)* - -## Coordinates - -`Coordinates` ã®ã‚ªãƒ–ジェクトã¯ç¾åœ¨ã®ä½ç½®ã®ãŸã‚ã®è¦æ±‚ã§ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯é–¢æ•°ã«ä½¿ç”¨ã™ã‚‹ `Position` オブジェクトã«ã‚¢ã‚¿ãƒƒãƒã•れã¾ã™ã€‚ ä½ç½®ã®åœ°ç†åº§æ¨™ã‚’記述ã™ã‚‹ãƒ—ãƒãƒ‘ティã®ã‚»ãƒƒãƒˆãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ - -### プãƒãƒ‘ティ - - * **latitude**: 10 度緯度。*(æ•°)* - - * **longitude**: 10 進度ã®çµŒåº¦ã€‚*(æ•°)* - - * **altitude**: 楕円体上ã®ãƒ¡ãƒ¼ãƒˆãƒ«ã®ä½ç½®ã®é«˜ã•。*(æ•°)* - - * **accuracy**: メートルã®ç·¯åº¦ã¨çµŒåº¦åº§æ¨™ã®ç²¾åº¦ãƒ¬ãƒ™ãƒ«ã€‚*(æ•°)* - - * **altitudeAccuracy**: メートルã®é«˜åº¦åº§æ¨™ã®ç²¾åº¦ãƒ¬ãƒ™ãƒ«ã€‚*(æ•°)* - - * **headingã—**: 進行方å‘ã€ã‚«ã‚¦ãƒ³ãƒˆã€çœŸåŒ—ã‹ã‚‰æ™‚計回りã®è§’åº¦ã§æŒ‡å®šã—ã¾ã™ã€‚*(æ•°)* - - * **speed**: æ¯Žç§’ãƒ¡ãƒ¼ãƒˆãƒ«ã§æŒ‡å®šã•れãŸãƒ‡ãƒã‚¤ã‚¹ã®ç¾åœ¨ã®å¯¾åœ°é€Ÿåº¦ã€‚*(æ•°)* - -### ã‚¢ãƒžã‚¾ãƒ³ç« OS ç™– - -**altitudeAccuracy**: `null` ã‚’è¿”ã™ã“ã¨ã® Android デãƒã‚¤ã‚¹ã§ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“. - -### Android ã®ç™– - -**altitudeAccuracy**: `null` ã‚’è¿”ã™ã“ã¨ã® Android デãƒã‚¤ã‚¹ã§ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“. - -## PositionError - -`PositionError` オブジェクト navigator.geolocation ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã¨ãã« `geolocationError` コールãƒãƒƒã‚¯é–¢æ•°ã«æ¸¡ã•れã¾ã™ã€‚ - -### プãƒãƒ‘ティ - - * **コード**: 次ã®ã„ãšã‚Œã‹ã®å®šç¾©æ¸ˆã¿ã®ã‚¨ãƒ©ãƒ¼ コード。 - - * **message**: 発生ã—ãŸã‚¨ãƒ©ãƒ¼ã®è©³ç´°ã‚’説明ã™ã‚‹ã‚¨ãƒ©ãƒ¼ メッセージ。 - -### 定数 - - * `PositionError.PERMISSION_DENIED` - * ユーザーã®ä½ç½®æƒ…å ±ã‚’å–å¾—ã™ã‚‹ã‚¢ãƒ—リを許å¯ã—ãªã„å ´åˆã«è¿”ã•れã¾ã™ã€‚ã“れã¯ãƒ—ラットフォームã«ä¾å˜ã—ã¾ã™ã€‚ - * `PositionError.POSITION_UNAVAILABLE` - * デãƒã‚¤ã‚¹ãŒã€ä½ç½®ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™è¿”ã•れã¾ã™ã€‚一般ã«ã€ã¤ã¾ã‚Šã€ãƒ‡ãƒã‚¤ã‚¹ãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•れã¦ã„ãªã„ã¾ãŸã¯è¡›æ˜Ÿã®ä¿®æ£ã‚’å¾—ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 - * `PositionError.TIMEOUT` - * デãƒã‚¤ã‚¹ãŒã§æŒ‡å®šã•ã‚ŒãŸæ™‚間内ã®ä½ç½®ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã¨ãã«è¿”ã•れる〠`timeout` ã«å«ã¾ã‚Œã¦ã„ã‚‹ `geolocationOptions` 。 使用ã™ã‚‹ã¨ `navigator.geolocation.watchPosition` ã€ã“ã®ã‚¨ãƒ©ãƒ¼ãŒç¹°ã‚Šè¿”ã—ã«æ¸¡ã™ã“ã¨ãŒã€ `geolocationError` コールãƒãƒƒã‚¯ã”㨠`timeout` (ミリ秒å˜ä½)。
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ja/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/ja/index.md deleted file mode 100644 index 3a8b73a5..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ja/index.md +++ /dev/null @@ -1,255 +0,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. ---> - -# cordova-plugin-geolocation - -ã“ã®ãƒ—ラグインã¯ç·¯åº¦ã‚„経度ãªã©ã®ãƒ‡ãƒã‚¤ã‚¹ã®å ´æ‰€ã«é–¢ã™ã‚‹æƒ…å ±ã‚’æä¾›ã—ã¾ã™ã€‚ ä½ç½®æƒ…å ±ã®å…±é€šã®ã‚½ãƒ¼ã‚¹ã¯ã‚°ãƒãƒ¼ãƒãƒ« ãƒã‚¸ã‚·ãƒ§ãƒ‹ãƒ³ã‚° システム(GPS) 㨠IP アドレスã€RFIDã€WiFi ãŠã‚ˆã³ Bluetooth ã® MAC アドレスã€ãŠã‚ˆã³ GSM/cdma æ–¹å¼æºå¸¯ Id ãªã©ã®ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¿¡å·ã‹ã‚‰æŽ¨å®šã•ã‚Œã‚‹å ´æ‰€ã«ã‚‚ã‚りã¾ã™ã€‚ API ã¯ã€ãƒ‡ãƒã‚¤ã‚¹ã®å®Ÿéš›ã®å ´æ‰€ã‚’è¿”ã™ã“ã¨ã®ä¿è¨¼ã¯ã‚りã¾ã›ã‚“。 - -ã“ã® API ã¯[W3C 地ç†ä½ç½®æƒ…å ± API 仕様][1]ã«åŸºã¥ã„ã¦ãŠã‚Šã€æ—¢ã«å®Ÿè£…ã‚’æä¾›ã—ãªã„デãƒã‚¤ã‚¹ä¸Šã®ã¿ã§å®Ÿè¡Œã—ã¾ã™ã€‚ - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**è¦å‘Š**: 地ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã®åŽé›†ã¨åˆ©ç”¨ã‚’é‡è¦ãªãƒ—ライãƒã‚·ãƒ¼ã®å•題を発生ã•ã›ã¾ã™ã€‚ アプリã®ãƒ—ライãƒã‚·ãƒ¼ ãƒãƒªã‚·ãƒ¼ã¯ä»–ã®å½“事者ã¨ãƒ‡ãƒ¼ã‚¿ (ãŸã¨ãˆã°ã€ç²—ã„ã€ç½°é‡‘ã€éƒµä¾¿ç•ªå·ãƒ¬ãƒ™ãƒ«ã€ç‰) ã®ç²¾åº¦ã®ãƒ¬ãƒ™ãƒ«ã§ã¯å…±æœ‰ã•れã¦ã„ã‚‹ã‹ã©ã†ã‹ã€ã‚¢ãƒ—リãŒåœ°ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã‚’ä½¿ç”¨ã™ã‚‹æ–¹æ³•ã‚’è°è«–ã™ã¹ãã§ã™ã€‚ 地ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã¨ä¸€èˆ¬ã«è¦‹ãªã•ã‚Œã‚‹æ•æ„Ÿãªãƒ¦ãƒ¼ã‚¶ãƒ¼ã®å±…å ´æ‰€ã‚’é–‹ç¤ºã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã®ã§ã€å½¼ã‚‰ã®æ—…è¡Œã®æ´å²ä¿å˜ã•れã¦ã„ã‚‹å ´åˆã€‚ ã—ãŸãŒã£ã¦ã€ã‚¢ãƒ—リã®ãƒ—ライãƒã‚·ãƒ¼ ãƒãƒªã‚·ãƒ¼ã«åŠ ãˆã¦ã€å¼·ãã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ (デãƒã‚¤ã‚¹ オペレーティング システムã—ãªã„å ´åˆãã†æ—¢ã«)ã€ã‚¢ãƒ—リケーションã«åœ°ç†ä½ç½®æƒ…å ±ãƒ‡ãƒ¼ã‚¿ã‚’ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å‰ã« - 時間ã®ãŠçŸ¥ã‚‰ã›ã‚’æä¾›ã—ã¾ã™ã€‚ ãã®é€šçŸ¥ã¯ã€ä¸Šè¨˜ã® (例ãˆã°ã€ **[ok]**ã‚’**ãŠã‹ã’ã§**é¸æŠžè‚¢ã‚’æç¤ºã™ã‚‹) ã«ã‚ˆã£ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚¢ã‚¯ã‚»ã‚¹è¨±å¯ã‚’å–å¾—ã™ã‚‹ã ã‘ã§ãªãã€åŒã˜æƒ…å ±ã‚’æä¾›ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚ 詳細ã«ã¤ã„ã¦ã¯ã€ãƒ—ライãƒã‚·ãƒ¼ã«é–¢ã™ã‚‹ã‚¬ã‚¤ãƒ‰ã‚’å‚ç…§ã—ã¦ãã ã•ã„。 - -ã“ã®ãƒ—ラグインã¯ã€ã‚°ãƒãƒ¼ãƒãƒ« `navigator.geolocation` オブジェクト (ãƒ—ãƒ©ãƒƒãƒˆãƒ•ã‚©ãƒ¼ãƒ è¡Œæ–¹ä¸æ˜Žã§ã™ãれ以外ã®å ´åˆ) を定義ã—ã¾ã™ã€‚ - -オブジェクトã¯ã€ã‚°ãƒãƒ¼ãƒãƒ« スコープã§ã§ã™ãŒã€ã“ã®ãƒ—ラグインã«ã‚ˆã£ã¦æä¾›ã•れる機能ã¯ã€`deviceready` イベントã®å¾Œã¾ã§ä½¿ç”¨ã§ãã¾ã›ã‚“。 - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## インストール - - cordova plugin add cordova-plugin-geolocation - - -## サãƒãƒ¼ãƒˆã•れã¦ã„るプラットフォーム- -* ã‚¢ãƒžã‚¾ãƒ³ç« OS -* アンドãƒã‚¤ãƒ‰ -* ブラックベリー 10 -* Firefox ã® OS -* iOS -* Tizen -* Windows Phone 7 㨠8 -* Windows 8 - -## メソッド - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## オブジェクト (èªã¿å–り専用) - -* Position -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -`Position` オブジェクトを `geolocationSuccess` コールãƒãƒƒã‚¯ã«ãƒ‘ラメーターã¨ã—ã¦ãƒ‡ãƒã‚¤ã‚¹ã®ç¾åœ¨ä½ç½®ã‚’è¿”ã—ã¾ã™ã€‚ エラーãŒã‚ã‚‹å ´åˆ `geolocationError` コールãƒãƒƒã‚¯ã«ã¯ã€`PositionError` ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆãŒæ¸¡ã•れã¾ã™ã€‚ - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### パラメーター - -* **geolocationSuccess**: ç¾åœ¨ã®ä½ç½®ã‚’渡ã•れるコールãƒãƒƒã‚¯ã€‚ - -* **geolocationError**: *(çœç•¥å¯èƒ½)*エラーãŒç™ºç”Ÿã—ãŸå ´åˆã«å®Ÿè¡Œã•れるコールãƒãƒƒã‚¯ã€‚ - -* **geolocationOptions**: *(オプション)*地ç†ä½ç½®æƒ…å ±ã®ã‚ªãƒ—ションã§ã™ã€‚ - -### 例 - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -ä½ç½®ã®å¤‰æ›´ãŒæ¤œå‡ºã•れãŸå ´åˆã¯ã€ãƒ‡ãƒã‚¤ã‚¹ã®ç¾åœ¨ä½ç½®ã‚’è¿”ã—ã¾ã™ã€‚ å–å¾—ã•れるã¨ã€ãƒ‡ãƒã‚¤ã‚¹ã®æ–°ã—ã„å ´æ‰€ã€`geolocationSuccess` コールãƒãƒƒã‚¯ パラメーターã¨ã—㦠`ä½ç½®` オブジェクトを実行ã—ã¾ã™ã€‚ エラーãŒã‚ã‚‹å ´åˆã€`geolocationError` コールãƒãƒƒã‚¯ パラメーターã¨ã—㦠`PositionError` オブジェクトã§å®Ÿè¡Œã—ã¾ã™ã€‚ - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### パラメーター - -* **geolocationSuccess**: ç¾åœ¨ã®ä½ç½®ã‚’渡ã•れるコールãƒãƒƒã‚¯ã€‚ - -* **geolocationError**: (çœç•¥å¯èƒ½) エラーãŒç™ºç”Ÿã—ãŸå ´åˆã«å®Ÿè¡Œã•れるコールãƒãƒƒã‚¯ã€‚ - -* **geolocationOptions**: (オプション) 地ç†ä½ç½®æƒ…å ±ã®ã‚ªãƒ—ションã§ã™ã€‚ - -### è¿”ã—ã¾ã™ - -* **æ–‡å—列**: 時計ã®ä½ç½®ã®é–“隔をå‚ç…§ã™ã‚‹æ™‚計 id ã‚’è¿”ã—ã¾ã™ã€‚ 時計 id ã§ä½¿ç”¨ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ `navigator.geolocation.clearWatch` åœæ¢ä½ç½®ã®å¤‰åŒ–を監視ã—ã¾ã™ã€‚ - -### 例 - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -地ç†ä½ç½®æƒ…å ± `ã®ä½ç½®` ã®æ¤œç´¢ã‚’カスタマイズã™ã‚‹ãŸã‚ã®çœç•¥å¯èƒ½ãªãƒ‘ラメーター. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### オプション - -* **enableHighAccuracy**: 最高ã®çµæžœãŒã€ã‚¢ãƒ—リケーションã«å¿…è¦ãŒã‚ã‚‹ã“ã¨ã®ãƒ’ントを示ã—ã¾ã™ã€‚ 既定ã§ã¯ã€ãƒ‡ãƒã‚¤ã‚¹ã®å–得を試ã¿ã¾ã™ã€ `Position` ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ ベースã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’使用ã—ã¾ã™ã€‚ ã“ã®ãƒ—ãƒãƒ‘ティをè¨å®šã™ã‚‹ `true` 衛星測ä½ãªã©ã®ã‚ˆã‚Šæ£ç¢ºãªæ–¹æ³•を使用ã™ã‚‹ãŸã‚ã«ãƒ•ãƒ¬ãƒ¼ãƒ ãƒ¯ãƒ¼ã‚¯ã«æŒ‡ç¤ºã—ã¾ã™ã€‚ *(ブール値)* - -* **タイムアウト**: ã¸ã®å‘¼ã³å‡ºã—ã‹ã‚‰é€šéŽãŒè¨±å¯ã•れる時間 (ミリ秒å˜ä½) ã®æœ€å¤§é•· `navigator.geolocation.getCurrentPosition` ã¾ãŸã¯ `geolocation.watchPosition` ã¾ã§å¯¾å¿œã™ã‚‹ã€ `geolocationSuccess` コールãƒãƒƒã‚¯ã‚’実行ã—ã¾ã™ã€‚ å ´åˆã¯ã€ `geolocationSuccess` ã“ã®æ™‚間内ã«ã€ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã¯å‘¼ã³å‡ºã•れã¾ã›ã‚“〠`geolocationError` コールãƒãƒƒã‚¯ã«æ¸¡ã•れる〠`PositionError.TIMEOUT` ã®ã‚¨ãƒ©ãƒ¼ コード。 (ã¨çµ„ã¿åˆã‚ã›ã¦ä½¿ç”¨ã™ã‚‹ã¨ãã«æ³¨æ„ã—ã¦ãã ã•ã„ `geolocation.watchPosition` ã® `geolocationError` é–“éš”ã§ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯ã‚’呼ã³å‡ºã™ã“ã¨ãŒã§ãã¾ã™ã™ã¹ã¦ `timeout` ミリ秒 ï¼)*(æ•°)* - -* **maximumAge**: å¹´é½¢ãŒã‚るミリ秒å˜ä½ã§æŒ‡å®šã—ãŸæ™‚間よりも大ãããªã„ã‚ャッシュã•れãŸä½ç½®ã‚’å—ã‘入れã¾ã™ã€‚*(æ•°)* - -### Android ã®ç™– - -`enableHighAccuracy` オプション㌠`true` ã«è¨å®šã—ãªã„é™ã‚Šã€ã‚¢ãƒ³ãƒ‰ãƒã‚¤ãƒ‰ 2.x エミュレーター地ç†ä½ç½®æƒ…å ±ã®çµæžœã‚’è¿”ã•ãªã„. - -## navigator.geolocation.clearWatch - -`watchID` パラメーターã«ã‚ˆã£ã¦å‚ç…§ã•れるã€ãƒ‡ãƒã‚¤ã‚¹ã®å ´æ‰€ã¸ã®å¤‰æ›´ã‚’見ã¦åœæ¢ã—ã¾ã™ã€‚ - - navigator.geolocation.clearWatch(watchID); - - -### パラメーター - -* **watchID**: ã® id〠`watchPosition` をクリアã™ã‚‹é–“隔。(æ–‡å—列) - -### 例 - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -`Position` 座標ã¨åœ°ç†ä½ç½®æƒ…å ± API ã§ä½œæˆã•れãŸã‚¿ã‚¤ãƒ スタンプãŒå«ã¾ã‚Œã¾ã™ã€‚ - -### プãƒãƒ‘ティ - -* **coords**: 地ç†çš„座標ã®ã‚»ãƒƒãƒˆã€‚*(座標)* - -* **timestamp**: 作æˆã®ã‚¿ã‚¤ãƒ スタンプを `coords` 。*(日)* - -## Coordinates - -`Coordinates` ã®ã‚ªãƒ–ジェクトã¯ç¾åœ¨ã®ä½ç½®ã®ãŸã‚ã®è¦æ±‚ã§ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯é–¢æ•°ã«ä½¿ç”¨ã™ã‚‹ `Position` オブジェクトã«ã‚¢ã‚¿ãƒƒãƒã•れã¾ã™ã€‚ ä½ç½®ã®åœ°ç†åº§æ¨™ã‚’記述ã™ã‚‹ãƒ—ãƒãƒ‘ティã®ã‚»ãƒƒãƒˆãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ - -### プãƒãƒ‘ティ - -* **latitude**: 10 度緯度。*(æ•°)* - -* **longitude**: 10 進度ã®çµŒåº¦ã€‚*(æ•°)* - -* **altitude**: 楕円体上ã®ãƒ¡ãƒ¼ãƒˆãƒ«ã®ä½ç½®ã®é«˜ã•。*(æ•°)* - -* **accuracy**: メートルã®ç·¯åº¦ã¨çµŒåº¦åº§æ¨™ã®ç²¾åº¦ãƒ¬ãƒ™ãƒ«ã€‚*(æ•°)* - -* **altitudeAccuracy**: メートルã®é«˜åº¦åº§æ¨™ã®ç²¾åº¦ãƒ¬ãƒ™ãƒ«ã€‚*(æ•°)* - -* **headingã—**: 進行方å‘ã€ã‚«ã‚¦ãƒ³ãƒˆã€çœŸåŒ—ã‹ã‚‰æ™‚計回りã®è§’åº¦ã§æŒ‡å®šã—ã¾ã™ã€‚*(æ•°)* - -* **speed**: æ¯Žç§’ãƒ¡ãƒ¼ãƒˆãƒ«ã§æŒ‡å®šã•れãŸãƒ‡ãƒã‚¤ã‚¹ã®ç¾åœ¨ã®å¯¾åœ°é€Ÿåº¦ã€‚*(æ•°)* - -### ã‚¢ãƒžã‚¾ãƒ³ç« OS ç™– - -**altitudeAccuracy**: `null` ã‚’è¿”ã™ã“ã¨ã® Android デãƒã‚¤ã‚¹ã§ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“. - -### Android ã®ç™– - -**altitudeAccuracy**: `null` ã‚’è¿”ã™ã“ã¨ã® Android デãƒã‚¤ã‚¹ã§ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“. - -## PositionError - -`PositionError` オブジェクト navigator.geolocation ã§ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ãŸã¨ãã« `geolocationError` コールãƒãƒƒã‚¯é–¢æ•°ã«æ¸¡ã•れã¾ã™ã€‚ - -### プãƒãƒ‘ティ - -* **code**: 次ã®ã„ãšã‚Œã‹ã®å®šç¾©æ¸ˆã¿ã®ã‚¨ãƒ©ãƒ¼ コード。 - -* **message**: 発生ã—ãŸã‚¨ãƒ©ãƒ¼ã®è©³ç´°ã‚’説明ã™ã‚‹ã‚¨ãƒ©ãƒ¼ メッセージ。 - -### 定数 - -* `PositionError.PERMISSION_DENIED` - * ユーザーã®ä½ç½®æƒ…å ±ã‚’å–å¾—ã™ã‚‹ã‚¢ãƒ—リを許å¯ã—ãªã„å ´åˆã«è¿”ã•れã¾ã™ã€‚ã“れã¯ãƒ—ラットフォームã«ä¾å˜ã—ã¾ã™ã€‚ -* `PositionError.POSITION_UNAVAILABLE` - * デãƒã‚¤ã‚¹ãŒã€ä½ç½®ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™è¿”ã•れã¾ã™ã€‚一般ã«ã€ã¤ã¾ã‚Šã€ãƒ‡ãƒã‚¤ã‚¹ãŒãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã•れã¦ã„ãªã„ã¾ãŸã¯è¡›æ˜Ÿã®ä¿®æ£ã‚’å¾—ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。 -* `PositionError.TIMEOUT` - * デãƒã‚¤ã‚¹ãŒã§æŒ‡å®šã•ã‚ŒãŸæ™‚間内ã®ä½ç½®ã‚’å–å¾—ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã¨ãã«è¿”ã•れる〠`timeout` ã«å«ã¾ã‚Œã¦ã„ã‚‹ `geolocationOptions` 。 使用ã™ã‚‹ã¨ `navigator.geolocation.watchPosition` ã€ã“ã®ã‚¨ãƒ©ãƒ¼ãŒç¹°ã‚Šè¿”ã—ã«æ¸¡ã™ã“ã¨ãŒã€ `geolocationError` コールãƒãƒƒã‚¯ã”㨠`timeout` (ミリ秒å˜ä½)。 diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ko/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/ko/README.md deleted file mode 100644 index dab50057..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ko/README.md +++ /dev/null @@ -1,268 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -ì´ í”ŒëŸ¬ê·¸ì¸ ìœ„ë„ ë° ê²½ë„ ë“±ì˜ ì†Œìžì˜ ìœ„ì¹˜ì— ëŒ€ 한 ì •ë³´ë¥¼ ì œê³µí•©ë‹ˆë‹¤. ì¼ë°˜ì ì¸ ìœ„ì¹˜ ì •ë³´ 등 글로벌 í¬ì§€ì…”ë‹ ì‹œìŠ¤í…œ (GPS) ë° ìœ„ì¹˜ì™€ ê°™ì€ IP 주소, RFID, WiFi ë° ë¸”ë£¨íˆ¬ìŠ¤ MAC 주소 ë° GSM/CDMA ì…€ Id ë„¤íŠ¸ì›Œí¬ ì‹ í˜¸ì—서 ìœ ì¶” 합니다. ë³´ìž¥ì€ ì—†ë‹¤ëŠ” API 소ìžì˜ ì‹¤ì œ 위치를 반환 합니다. - -ì´ API [W3C Geolocation API 사양](http://dev.w3.org/geo/api/spec-source.html)ì— ê¸°ë°˜ 하 ê³ ì´ë¯¸ êµ¬í˜„ì„ ì œê³µ 하지 않는 장치ì—ë§Œ 실행 ë©ë‹ˆë‹¤. - -**ê²½ê³ **: 중요 한 ê°œì¸ ì •ë³´ 보호 ë¬¸ì œë¥¼ ì œê¸° 하는 위치 ì •ë³´ ë°ì´í„°ì˜ 수집 ë° ì‚¬ìš© 합니다. ì‘ìš© í”„ë¡œê·¸ëž¨ì˜ ê°œì¸ ì •ë³´ 보호 ì •ì±… 다른 당사ìžì™€ì˜ ë°ì´í„° (예를 들어, êµµê³ , ê´œ ì°® ì•„ ìš”, 우편 번호, 등)ì˜ ì •ë°€ë„ ìˆ˜ì¤€ì„ ê³µìœ ì—¬ë¶€ë¥¼ app 지리ì ë°ì´í„°ë¥¼ 사용 하는 방법 í† ë¡ í•´ì•¼ 한다. ê·¸ê²ƒì€ ì‚¬ìš©ìžì˜ í–‰ë°©ì„ ë°íž 수 있기 ë•Œë¬¸ì— ë° ì €ìž¥, ê·¸ë“¤ì˜ ì—¬í–‰ ì—사 지리ì 위치 ë°ì´í„°ëŠ” ì¼ë°˜ì 으로 민ê°í•œ 간주. ë”°ë¼ì„œ, ì• í”Œ 리 ì¼€ì´ ì…˜ì˜ ê°œì¸ ì •ë³´ 보호 ì •ì±… ë¿ë§Œ ì•„ë‹ˆë¼ ê°•ë ¥ 하 게 좋습니다 (해당 ë˜ëŠ” 경우 장치 ìš´ì˜ ì²´ì œ ì´ë ‡ê²Œ ì´ë¯¸ 하지 않는) ì‘ìš© 프로그램 위치 ì •ë³´ ë°ì´í„°ì— 액세스 하기 ì „ì— ê·¸ëƒ¥--시간 통지. ê·¸ 통지는 (예를 들어, **확ì¸** ë° **아니오**ì„ íƒ ì œì‹œ) 하 ì—¬ 사용ìžì˜ 허가 ì·¨ë“ ë¿ë§Œ 아니ë¼, 위ì—서 언급 ëœ ë™ì¼í•œ ì •ë³´ë¥¼ ì œê³µ 해야 합니다. ìžì„¸í•œ ë‚´ìš©ì€ ê°œì¸ ì •ë³´ 보호 ê°€ì´ë“œë¥¼ 참조 하ì‹ì‹œì˜¤. - -ì´ í”ŒëŸ¬ê·¸ì¸ (플랫í¼ì€ ê·¸ë ‡ì§€ 않으면 ëˆ„ë½ ëœ)ì— ëŒ€ 한 ì „ì— `navigator.geolocation` 개체를 ì •ì˜ í•©ë‹ˆë‹¤. - -개체가 ì „ì— ë²”ìœ„ì— ìžˆì§€ë§Œ,ì´ í”ŒëŸ¬ê·¸ì¸ì— ì˜í•´ ì œê³µ ë˜ëŠ” 기능 하지 ì‚¬ìš©í• ìˆ˜ 있습니다까지 `deviceready` ì´ë²¤íЏ 후. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## 설치 - -코르ë„ë°” 5.0 + (현재 ì•ˆì •ì ì¸ 1.0.0) í•„ìš” - - cordova plugin add cordova-plugin-geolocation - - -코르ë„ë°”ì˜ ì´ì „ ë²„ì „ 사용 ë˜ì§€ 않는 id (부실 0.3.12)를 통해 ì„¤ì¹˜í• ìˆ˜ 있습니다. - - cordova plugin add org.apache.cordova.geolocation - - -ê·¸ê²ƒì€ ë˜í•œ ë°°ìƒ ê³„ì•½ urlì„ í†µí•´ ì§ì ‘ ì„¤ì¹˜í• ìˆ˜ (ë¶ˆì•ˆì •) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## ì§€ì› ë˜ëŠ” í”Œëž«í¼ - - * 아마존 화재 ìš´ì˜ ì²´ì œ - * 안 드 로ì´ë“œ - * ë¸”ëž™ë² ë¦¬ 10 - * Firefox ìš´ì˜ ì²´ì œ - * iOS - * Tizen - * Windows Phone 7ê³¼ 8 - * 윈ë„ìš° 8 - * 윈ë„ìš° - -## 메서드 - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## (ì½ê¸° ì „ìš©) 개체 - - * Position - * PositionError - * Coordinates - -## navigator.geolocation.getCurrentPosition - -매개 변수 `Position` 개체와 `geolocationSuccess`를 디바ì´ìŠ¤ì˜ í˜„ìž¬ 위치를 반환합니다. 오류가 있는 경우ì—, `geolocationError` 콜백 `PositionError` ê°œì²´ì— ì „ë‹¬ ë©ë‹ˆë‹¤. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### 매개 변수 - - * **geolocationSuccess**: í˜„ìž¬ì˜ ìœ„ì¹˜ë¥¼ ì „ë‹¬ ë˜ëŠ” 콜백. - - * **geolocationError**: *(ì„ íƒ ì‚¬í•)* 오류가 ë°œìƒ í•˜ë©´ 실행 ë˜ëŠ” 콜백. - - * **geolocationOptions**: *(ì„ íƒ ì‚¬í•)* 위치 옵션. - -### 예를 들어 - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -ìœ„ì¹˜ì— ë³€í™”ë¥¼ íƒì§€í• 때 소ìžì˜ 현재 위치를 반환 합니다. 장치 새 위치를 검색 하는 경우 `geolocationSuccess` 콜백 매개 변수로 개체를 `Position`으로 실행 합니다. 오류가 있는 경우ì—, `geolocationError` 콜백 매개 변수로 `PositionError` 개체를 실행 합니다. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### 매개 변수 - - * **geolocationSuccess**: í˜„ìž¬ì˜ ìœ„ì¹˜ë¥¼ ì „ë‹¬ ë˜ëŠ” 콜백. - - * **geolocationError**: (ì„ íƒ ì‚¬í•) 오류가 ë°œìƒ í•˜ë©´ 실행 ë˜ëŠ” 콜백. - - * **geolocationOptions**: (ì„ íƒ ì‚¬í•)는 지리ì 위치 옵션. - -### 반환 - - * **문ìžì—´**: 시계 위치 ê°„ê²©ì„ ì°¸ì¡° 하는 시계 id를 반환 합니다. 시계 id와 함께 사용 해야 합니다 `navigator.geolocation.clearWatch` 위치 ë³€í™”ì— ëŒ€ 한 ë³´ê³ ì¤‘ì§€. - -### 예를 들어 - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -지리ì `Position` ê²€ìƒ‰ì„ ì‚¬ìš©ìž ì§€ì • 하는 ì„ íƒì 매개 변수. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### 옵션 - - * **enableHighAccuracy**: 힌트는 ì‘ìš© í”„ë¡œê·¸ëž¨ì— í•„ìš”í•œ 최ìƒì˜ ê²°ê³¼ ì œê³µ 합니다. 기본ì 으로 장치를 검색 í•˜ë ¤ê³ í•œ `Position` ë„¤íŠ¸ì›Œí¬ ê¸°ë°˜ ë°©ë²•ì„ ì‚¬ìš© 하 ì—¬. ì´ ì†ì„±ì„ ì„¤ì • `true` 위성 위치 등 보다 ì •í™•í•œ ë°©ë²•ì„ ì‚¬ìš© 하 ì—¬ í”„ë ˆìž„ 워í¬. *(부울)* - - * **시간 ì œí•œ**: 최대 ì‹œê°„ì˜ ê¸¸ì´ (밀리초) 호출ì—서 ì „ë‹¬í• ìˆ˜ 있는 `navigator.geolocation.getCurrentPosition` ë˜ëŠ” `geolocation.watchPosition` 해당까지 `geolocationSuccess` 콜백 실행. 경우는 `geolocationSuccess` 콜백ì´ì´ 시간 ë‚´ì—서 호출 ë˜ì§€ 않습니다는 `geolocationError` 콜백 ì „ë‹¬ ë˜ëŠ” `PositionError.TIMEOUT` 오류 코드. (함께 사용 하는 경우 `geolocation.watchPosition` , `geolocationError` 콜백 간격ì—서 호출 ë 수 있는 ëª¨ë“ `timeout` 밀리초!) *(수)* - - * **maximumAge**: 밀리초 단위로 ì§€ì • ëœ ì‹œê°„ 보다 ë” í° ë˜ëŠ” ìºì‹œ 위치를 ìˆ˜ë½ í•©ë‹ˆë‹¤. *(수)* - -### 안 드 로ì´ë“œ 단ì - -`EnableHighAccuracy` ì˜µì…˜ì„ `true`로 ì„¤ì • ë˜ì–´ 있지 않으면 안 드 로ì´ë“œ 2.x ì—ë®¬ë ˆì´í„° 위치 ê²°ê³¼ 반환 하지 않는. - -## navigator.geolocation.clearWatch - -`watchID` 매개 변수ì—서 참조 하는 소ìžì˜ 위치 ë³€ê²½ì— ëŒ€ 한 ë³´ê³ ì¤‘ì§€ 합니다. - - navigator.geolocation.clearWatch(watchID); - - -### 매개 변수 - - * **watchID**: id는 `watchPosition` ê°„ê²©ì„ ì·¨ì†Œ 합니다. (문ìžì—´) - -### 예를 들어 - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -`Position` 좌표 ë° ì§€ë¦¬ì 위치 APIì— ì˜í•´ ìƒì„± 하는 타임 스탬프를 í¬í•¨ 합니다. - -### ì†ì„± - - * **coords**: 지리ì 좌표 ì§‘í•©. *(좌표)* - - * **timestamp**: ìƒì„± 타임 ìŠ¤íƒ¬í”„ì— ëŒ€ 한 `coords` . *(DOMTimeStamp)* - -## Coordinates - -`Coordinates` 개체를 현재 ìœ„ì¹˜ì— ëŒ€ 한 ìš”ì²ì— 콜백 함수를 ì‚¬ìš©í• ìˆ˜ 있는 `Position` ê°œì²´ì— ì²¨ë¶€ ë©ë‹ˆë‹¤. ê·¸ê²ƒì€ ìœ„ì¹˜ì˜ ì§€ë¦¬ì 좌표를 설명 하는 ì†ì„± ì§‘í•©ì´ í¬í•¨ ë˜ì–´ 있습니다. - -### ì†ì„± - - * **latitude**: 소수ì ë„ ìœ„ë„. *(수)* - - * **longitude**: ê²½ë„ 10 진수 ê°ë„. *(수)* - - * **altitude**: 높ì´ì˜ íƒ€ì› ë©´ ë¯¸í„°ì— ìœ„ì¹˜. *(수)* - - * **ì •í™•ë„**: ì •í™•ë„ ë ˆë²¨ ë¯¸í„°ì— ìœ„ë„ ë° ê²½ë„ ì¢Œí‘œ. *(수)* - - * **altitudeAccuracy**: ë¯¸í„°ì— ê³ ë„ ì¢Œí‘œì˜ ì •í™•ë„ ìˆ˜ì¤€. *(수)* - - * **heading**: 여행, ì§„ ë¶ì„ 기준으로 시계 방향으로 세ë„ì— ì§€ì • ëœ ë°©í–¥ìœ¼ë¡œ. *(수)* - - * **speed**: 초당 ë¯¸í„°ì— ì§€ì • ëœ ë””ë°”ì´ìŠ¤ì˜ í˜„ìž¬ ë•… ì†ë„. *(수)* - -### 아마존 화재 OS 단ì - -**altitudeAccuracy**: `null` 반환 안 드 로ì´ë“œ ìž¥ì¹˜ì— ì˜í•´ ì§€ì› ë˜ì§€ 않습니다. - -### 안 드 로ì´ë“œ 단ì - -**altitudeAccuracy**: `null` 반환 안 드 로ì´ë“œ ìž¥ì¹˜ì— ì˜í•´ ì§€ì› ë˜ì§€ 않습니다. - -## PositionError - -`PositionError` 개체는 navigator.geolocation와 함께 오류가 ë°œìƒ í•˜ë©´ `geolocationError` 콜백 í•¨ìˆ˜ì— ì „ë‹¬ ë©ë‹ˆë‹¤. - -### ì†ì„± - - * **코드**: 미리 ì •ì˜ ëœ ì˜¤ë¥˜ 코드 중 하나가 ì•„ëž˜ì— ë‚˜ì—´ ëœ. - - * **message**: ë°œìƒ í•œ 오류 세부 ì •ë³´ë¥¼ 설명 하는 오류 메시지. - -### ìƒìˆ˜ - - * `PositionError.PERMISSION_DENIED` - * 사용ìžê°€ 위치 ì •ë³´ë¥¼ 검색 ì• í”Œ 리 ì¼€ì´ ì…˜ì„ í—ˆìš© 하지 않는 경우 반환 ë©ë‹ˆë‹¤. ì´ í”Œëž«í¼ì— ë”°ë¼ ë‹¬ë¼ ì§‘ë‹ˆë‹¤. - * `PositionError.POSITION_UNAVAILABLE` - * 장치 위치를 ê²€ìƒ‰í• ìˆ˜ ì—†ì„ ë•Œ 반환 합니다. ì¼ë°˜ì 으로,ì´ ìž¥ì¹˜ëŠ” 네트워í¬ì— ì—°ê²° ë˜ì–´ 있지 ì•Šì€ ë˜ëŠ” 위성 ìˆ˜ì • í”„ë¡œê·¸ëž¨ì„ ì–»ì„ ìˆ˜ 없습니다 ì˜ë¯¸ 합니다. - * `PositionError.TIMEOUT` - * ìž¥ì¹˜ì— ì§€ì • ëœ ì‹œê°„ ë‚´ì—서 위치를 ê²€ìƒ‰í• ìˆ˜ 없는 경우 반환 ë˜ëŠ” `timeout` ì— í¬í•¨ ëœ `geolocationOptions` . 함께 사용 ë 때 `navigator.geolocation.watchPosition` ,ì´ ì˜¤ë¥˜ë¥¼ 반복ì 으로 ì „ë‹¬ ë 수는 `geolocationError` 콜백 매 `timeout` 밀리초.
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ko/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/ko/index.md deleted file mode 100644 index 19f47c72..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ko/index.md +++ /dev/null @@ -1,255 +0,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. ---> - -# cordova-plugin-geolocation - -ì´ í”ŒëŸ¬ê·¸ì¸ ìœ„ë„ ë° ê²½ë„ ë“±ì˜ ì†Œìžì˜ ìœ„ì¹˜ì— ëŒ€ 한 ì •ë³´ë¥¼ ì œê³µí•©ë‹ˆë‹¤. ì¼ë°˜ì ì¸ ìœ„ì¹˜ ì •ë³´ 등 글로벌 í¬ì§€ì…”ë‹ ì‹œìŠ¤í…œ (GPS) ë° ìœ„ì¹˜ì™€ ê°™ì€ IP 주소, RFID, WiFi ë° ë¸”ë£¨íˆ¬ìŠ¤ MAC 주소 ë° GSM/CDMA ì…€ Id ë„¤íŠ¸ì›Œí¬ ì‹ í˜¸ì—서 ìœ ì¶” 합니다. ë³´ìž¥ì€ ì—†ë‹¤ëŠ” API 소ìžì˜ ì‹¤ì œ 위치를 반환 합니다. - -ì´ API [W3C Geolocation API 사양][1]ì— ê¸°ë°˜ 하 ê³ ì´ë¯¸ êµ¬í˜„ì„ ì œê³µ 하지 않는 장치ì—ë§Œ 실행 ë©ë‹ˆë‹¤. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**ê²½ê³ **: 중요 한 ê°œì¸ ì •ë³´ 보호 ë¬¸ì œë¥¼ ì œê¸° 하는 위치 ì •ë³´ ë°ì´í„°ì˜ 수집 ë° ì‚¬ìš© 합니다. ì‘ìš© í”„ë¡œê·¸ëž¨ì˜ ê°œì¸ ì •ë³´ 보호 ì •ì±… 다른 당사ìžì™€ì˜ ë°ì´í„° (예를 들어, êµµê³ , ê´œ ì°® ì•„ ìš”, 우편 번호, 등)ì˜ ì •ë°€ë„ ìˆ˜ì¤€ì„ ê³µìœ ì—¬ë¶€ë¥¼ app 지리ì ë°ì´í„°ë¥¼ 사용 하는 방법 í† ë¡ í•´ì•¼ 한다. ê·¸ê²ƒì€ ì‚¬ìš©ìžì˜ í–‰ë°©ì„ ë°íž 수 있기 ë•Œë¬¸ì— ë° ì €ìž¥, ê·¸ë“¤ì˜ ì—¬í–‰ ì—사 지리ì 위치 ë°ì´í„°ëŠ” ì¼ë°˜ì 으로 민ê°í•œ 간주. ë”°ë¼ì„œ, ì• í”Œ 리 ì¼€ì´ ì…˜ì˜ ê°œì¸ ì •ë³´ 보호 ì •ì±… ë¿ë§Œ ì•„ë‹ˆë¼ ê°•ë ¥ 하 게 좋습니다 (해당 ë˜ëŠ” 경우 장치 ìš´ì˜ ì²´ì œ ì´ë ‡ê²Œ ì´ë¯¸ 하지 않는) ì‘ìš© 프로그램 위치 ì •ë³´ ë°ì´í„°ì— 액세스 하기 ì „ì— ê·¸ëƒ¥--시간 통지. ê·¸ 통지는 (예를 들어, **확ì¸** ë° **아니오**ì„ íƒ ì œì‹œ) 하 ì—¬ 사용ìžì˜ 허가 ì·¨ë“ ë¿ë§Œ 아니ë¼, 위ì—서 언급 ëœ ë™ì¼í•œ ì •ë³´ë¥¼ ì œê³µ 해야 합니다. ìžì„¸í•œ ë‚´ìš©ì€ ê°œì¸ ì •ë³´ 보호 ê°€ì´ë“œë¥¼ 참조 하ì‹ì‹œì˜¤. - -ì´ í”ŒëŸ¬ê·¸ì¸ (플랫í¼ì€ ê·¸ë ‡ì§€ 않으면 ëˆ„ë½ ëœ)ì— ëŒ€ 한 ì „ì— `navigator.geolocation` 개체를 ì •ì˜ í•©ë‹ˆë‹¤. - -개체가 ì „ì— ë²”ìœ„ì— ìžˆì§€ë§Œ,ì´ í”ŒëŸ¬ê·¸ì¸ì— ì˜í•´ ì œê³µ ë˜ëŠ” 기능 하지 ì‚¬ìš©í• ìˆ˜ 있습니다까지 `deviceready` ì´ë²¤íЏ 후. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## 설치 - - cordova plugin add cordova-plugin-geolocation - - -## ì§€ì› ë˜ëŠ” í”Œëž«í¼ - -* 아마존 화재 ìš´ì˜ ì²´ì œ -* 안 드 로ì´ë“œ -* ë¸”ëž™ë² ë¦¬ 10 -* Firefox ìš´ì˜ ì²´ì œ -* iOS -* Tizen -* Windows Phone 7ê³¼ 8 -* 윈ë„ìš° 8 - -## 메서드 - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## (ì½ê¸° ì „ìš©) 개체 - -* Position -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -매개 변수 `Position` 개체와 `geolocationSuccess`를 디바ì´ìŠ¤ì˜ í˜„ìž¬ 위치를 반환합니다. 오류가 있는 경우ì—, `geolocationError` 콜백 `PositionError` ê°œì²´ì— ì „ë‹¬ ë©ë‹ˆë‹¤. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### 매개 변수 - -* **geolocationSuccess**: í˜„ìž¬ì˜ ìœ„ì¹˜ë¥¼ ì „ë‹¬ ë˜ëŠ” 콜백. - -* **geolocationError**: *(ì„ íƒ ì‚¬í•)* 오류가 ë°œìƒ í•˜ë©´ 실행 ë˜ëŠ” 콜백. - -* **geolocationOptions**: *(ì„ íƒ ì‚¬í•)* 위치 옵션. - -### 예를 들어 - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -ìœ„ì¹˜ì— ë³€í™”ë¥¼ íƒì§€í• 때 소ìžì˜ 현재 위치를 반환 합니다. 장치 새 위치를 검색 하는 경우 `geolocationSuccess` 콜백 매개 변수로 개체를 `Position`으로 실행 합니다. 오류가 있는 경우ì—, `geolocationError` 콜백 매개 변수로 `PositionError` 개체를 실행 합니다. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### 매개 변수 - -* **geolocationSuccess**: í˜„ìž¬ì˜ ìœ„ì¹˜ë¥¼ ì „ë‹¬ ë˜ëŠ” 콜백. - -* **geolocationError**: (ì„ íƒ ì‚¬í•) 오류가 ë°œìƒ í•˜ë©´ 실행 ë˜ëŠ” 콜백. - -* **geolocationOptions**: (ì„ íƒ ì‚¬í•)는 지리ì 위치 옵션. - -### 반환 - -* **문ìžì—´**: 시계 위치 ê°„ê²©ì„ ì°¸ì¡° 하는 시계 id를 반환 합니다. 시계 id와 함께 사용 해야 합니다 `navigator.geolocation.clearWatch` 위치 ë³€í™”ì— ëŒ€ 한 ë³´ê³ ì¤‘ì§€. - -### 예를 들어 - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -지리ì `Position` ê²€ìƒ‰ì„ ì‚¬ìš©ìž ì§€ì • 하는 ì„ íƒì 매개 변수. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### 옵션 - -* **enableHighAccuracy**: 힌트는 ì‘ìš© í”„ë¡œê·¸ëž¨ì— í•„ìš”í•œ 최ìƒì˜ ê²°ê³¼ ì œê³µ 합니다. 기본ì 으로 장치를 검색 í•˜ë ¤ê³ í•œ `Position` ë„¤íŠ¸ì›Œí¬ ê¸°ë°˜ ë°©ë²•ì„ ì‚¬ìš© 하 ì—¬. ì´ ì†ì„±ì„ ì„¤ì • `true` 위성 위치 등 보다 ì •í™•í•œ ë°©ë²•ì„ ì‚¬ìš© 하 ì—¬ í”„ë ˆìž„ 워í¬. *(부울)* - -* **시간 ì œí•œ**: 최대 ì‹œê°„ì˜ ê¸¸ì´ (밀리초) 호출ì—서 ì „ë‹¬í• ìˆ˜ 있는 `navigator.geolocation.getCurrentPosition` ë˜ëŠ” `geolocation.watchPosition` 해당까지 `geolocationSuccess` 콜백 실행. 경우는 `geolocationSuccess` 콜백ì´ì´ 시간 ë‚´ì—서 호출 ë˜ì§€ 않습니다는 `geolocationError` 콜백 ì „ë‹¬ ë˜ëŠ” `PositionError.TIMEOUT` 오류 코드. (함께 사용 하는 경우 `geolocation.watchPosition` , `geolocationError` 콜백 간격ì—서 호출 ë 수 있는 ëª¨ë“ `timeout` 밀리초!) *(수)* - -* **maximumAge**: 밀리초 단위로 ì§€ì • ëœ ì‹œê°„ 보다 ë” í° ë˜ëŠ” ìºì‹œ 위치를 ìˆ˜ë½ í•©ë‹ˆë‹¤. *(수)* - -### 안 드 로ì´ë“œ 단ì - -`EnableHighAccuracy` ì˜µì…˜ì„ `true`로 ì„¤ì • ë˜ì–´ 있지 않으면 안 드 로ì´ë“œ 2.x ì—ë®¬ë ˆì´í„° 위치 ê²°ê³¼ 반환 하지 않는. - -## navigator.geolocation.clearWatch - -`watchID` 매개 변수ì—서 참조 하는 소ìžì˜ 위치 ë³€ê²½ì— ëŒ€ 한 ë³´ê³ ì¤‘ì§€ 합니다. - - navigator.geolocation.clearWatch(watchID); - - -### 매개 변수 - -* **watchID**: id는 `watchPosition` ê°„ê²©ì„ ì·¨ì†Œ 합니다. (문ìžì—´) - -### 예를 들어 - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -`Position` 좌표 ë° ì§€ë¦¬ì 위치 APIì— ì˜í•´ ìƒì„± 하는 타임 스탬프를 í¬í•¨ 합니다. - -### ì†ì„± - -* **coords**: 지리ì 좌표 ì§‘í•©. *(좌표)* - -* **timestamp**: ìƒì„± 타임 ìŠ¤íƒ¬í”„ì— ëŒ€ 한 `coords` . *(DOMTimeStamp)* - -## Coordinates - -`Coordinates` 개체를 현재 ìœ„ì¹˜ì— ëŒ€ 한 ìš”ì²ì— 콜백 함수를 ì‚¬ìš©í• ìˆ˜ 있는 `Position` ê°œì²´ì— ì²¨ë¶€ ë©ë‹ˆë‹¤. ê·¸ê²ƒì€ ìœ„ì¹˜ì˜ ì§€ë¦¬ì 좌표를 설명 하는 ì†ì„± ì§‘í•©ì´ í¬í•¨ ë˜ì–´ 있습니다. - -### ì†ì„± - -* **latitude**: 소수ì ë„ ìœ„ë„. *(수)* - -* **longitude**: ê²½ë„ 10 진수 ê°ë„. *(수)* - -* **altitude**: 높ì´ì˜ íƒ€ì› ë©´ ë¯¸í„°ì— ìœ„ì¹˜. *(수)* - -* **ì •í™•ë„**: ì •í™•ë„ ë ˆë²¨ ë¯¸í„°ì— ìœ„ë„ ë° ê²½ë„ ì¢Œí‘œ. *(수)* - -* **altitudeAccuracy**: ë¯¸í„°ì— ê³ ë„ ì¢Œí‘œì˜ ì •í™•ë„ ìˆ˜ì¤€. *(수)* - -* **heading**: 여행, ì§„ ë¶ì„ 기준으로 시계 방향으로 세ë„ì— ì§€ì • ëœ ë°©í–¥ìœ¼ë¡œ. *(수)* - -* **speed**: 초당 ë¯¸í„°ì— ì§€ì • ëœ ë””ë°”ì´ìŠ¤ì˜ í˜„ìž¬ ë•… ì†ë„. *(수)* - -### 아마존 화재 OS 단ì - -**altitudeAccuracy**: `null` 반환 안 드 로ì´ë“œ ìž¥ì¹˜ì— ì˜í•´ ì§€ì› ë˜ì§€ 않습니다. - -### 안 드 로ì´ë“œ 단ì - -**altitudeAccuracy**: `null` 반환 안 드 로ì´ë“œ ìž¥ì¹˜ì— ì˜í•´ ì§€ì› ë˜ì§€ 않습니다. - -## PositionError - -`PositionError` 개체는 navigator.geolocation와 함께 오류가 ë°œìƒ í•˜ë©´ `geolocationError` 콜백 í•¨ìˆ˜ì— ì „ë‹¬ ë©ë‹ˆë‹¤. - -### ì†ì„± - -* **code**: 미리 ì •ì˜ ëœ ì˜¤ë¥˜ 코드 중 하나가 ì•„ëž˜ì— ë‚˜ì—´ ëœ. - -* **message**: ë°œìƒ í•œ 오류 세부 ì •ë³´ë¥¼ 설명 하는 오류 메시지. - -### ìƒìˆ˜ - -* `PositionError.PERMISSION_DENIED` - * 사용ìžê°€ 위치 ì •ë³´ë¥¼ 검색 ì• í”Œ 리 ì¼€ì´ ì…˜ì„ í—ˆìš© 하지 않는 경우 반환 ë©ë‹ˆë‹¤. ì´ í”Œëž«í¼ì— ë”°ë¼ ë‹¬ë¼ ì§‘ë‹ˆë‹¤. -* `PositionError.POSITION_UNAVAILABLE` - * 장치 위치를 ê²€ìƒ‰í• ìˆ˜ ì—†ì„ ë•Œ 반환 합니다. ì¼ë°˜ì 으로,ì´ ìž¥ì¹˜ëŠ” 네트워í¬ì— ì—°ê²° ë˜ì–´ 있지 ì•Šì€ ë˜ëŠ” 위성 ìˆ˜ì • í”„ë¡œê·¸ëž¨ì„ ì–»ì„ ìˆ˜ 없습니다 ì˜ë¯¸ 합니다. -* `PositionError.TIMEOUT` - * ìž¥ì¹˜ì— ì§€ì • ëœ ì‹œê°„ ë‚´ì—서 위치를 ê²€ìƒ‰í• ìˆ˜ 없는 경우 반환 ë˜ëŠ” `timeout` ì— í¬í•¨ ëœ `geolocationOptions` . 함께 사용 ë 때 `navigator.geolocation.watchPosition` ,ì´ ì˜¤ë¥˜ë¥¼ 반복ì 으로 ì „ë‹¬ ë 수는 `geolocationError` 콜백 매 `timeout` 밀리초. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/pl/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/pl/README.md deleted file mode 100644 index 0ef35c4e..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/pl/README.md +++ /dev/null @@ -1,268 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -Ten plugin zawiera informacje o lokalizacji urzÄ…dzenia, takie jak szerokość i dÅ‚ugość geograficznÄ…. NajczÄ™stsze źródÅ‚a informacji o lokalizacji obejmujÄ… Global Positioning System (GPS) i lokalizacji wywnioskować z sieci sygnaÅ‚y, takie jak adres IP, RFID, WiFi i Bluetooth MAC adresy, a komórki GSM/CDMA identyfikatorów. Nie ma żadnej gwarancji, że API zwraca rzeczywistej lokalizacji urzÄ…dzenia. - -Ten interfejs API jest oparty na [Specyfikacji W3C Geolocation API](http://dev.w3.org/geo/api/spec-source.html)i tylko wykonuje na urzÄ…dzeniach, które już nie zapewniajÄ… implementacja. - -**Ostrzeżenie**: zbierania i wykorzystywania danych geolokacyjnych podnosi kwestie prywatnoÅ›ci ważne. Polityka prywatnoÅ›ci danej aplikacji należy omówić, jak aplikacja używa danych, czy jest on dzielony z innych stron i poziom dokÅ‚adnoÅ›ci danych (na przykÅ‚ad, gruba, porzÄ…dku, kod pocztowy poziom, itp.). Danych geolokacyjnych ogólnie uznaje wrażliwych, bo to może ujawnić pobytu użytkownika i, jeÅ›li przechowywane, historii ich podróży. W zwiÄ…zku z tym oprócz aplikacji prywatnoÅ›ci, zdecydowanie warto powiadomienia just-in-time, zanim aplikacja uzyskuje dostÄ™p do danych (jeÅ›li urzÄ…dzenie system operacyjny nie robi już). Å»e ogÅ‚oszenie powinno zawierać te same informacje, o których wspomniano powyżej, jak również uzyskanie uprawnienia użytkownika (np. poprzez przedstawianie wyborów **OK** i **Nie dziÄ™ki**). Aby uzyskać wiÄ™cej informacji zobacz przewodnik prywatnoÅ›ci. - -Ten plugin definiuje obiekt globalny `navigator.geolocation` (dla platformy gdzie to inaczej brak). - -Mimo, że obiekt jest w globalnym zasiÄ™gu, funkcji oferowanych przez ten plugin nie sÄ… dostÄ™pne dopiero po turnieju `deviceready`. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Instalacja - -Wymaga to cordova 5.0 + (bieżącej stabilnej 1.0.0) - - cordova plugin add cordova-plugin-geolocation - - -Starsze wersje cordova nadal można zainstalować za pomocÄ… niezalecany identyfikator (starych 0.3.12) - - cordova plugin add org.apache.cordova.geolocation - - -Jest również możliwość instalacji za poÅ›rednictwem repo url bezpoÅ›rednio (niestabilny) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## ObsÅ‚ugiwane platformy - - * Amazon Fire OS - * Android - * BlackBerry 10 - * Firefox OS - * iOS - * Tizen - * Windows Phone 7 i 8 - * Windows 8 - * Windows - -## Metody - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## Obiekty (tylko do odczytu) - - * Position - * PositionError - * Coordinates - -## navigator.geolocation.getCurrentPosition - -Zwraca bieżącÄ… pozycjÄ™ urzÄ…dzenia do `geolocationSuccess` wywoÅ‚anie zwrotne z `Position` obiektu jako parametr. JeÅ›li wystÄ™puje błąd, wywoÅ‚ania zwrotnego `geolocationError` jest przekazywany obiekt `PositionError`. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametry - - * **geolocationSuccess**: wywoÅ‚ania zwrotnego, który jest przekazywany aktualnej pozycji. - - * **geolocationError**: *(opcjonalne)* wywoÅ‚ania zwrotnego, która wykonuje w przypadku wystÄ…pienia błędu. - - * **geolocationOptions**: *(opcjonalne)* opcji geolokalizacji. - -### PrzykÅ‚ad - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Zwraca bieżącÄ… pozycjÄ™ urzÄ…dzenia po wykryciu zmiany pozycji. Gdy urzÄ…dzenie pobiera nowÄ… lokalizacjÄ™, wywoÅ‚ania zwrotnego `geolocationSuccess` wykonuje siÄ™ z `Position` obiektu jako parametr. JeÅ›li wystÄ™puje błąd, wywoÅ‚ania zwrotnego `geolocationError` wykonuje siÄ™ z obiektem `PositionError` jako parametr. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametry - - * **geolocationSuccess**: wywoÅ‚ania zwrotnego, który jest przekazywany aktualnej pozycji. - - * **geolocationError**: (opcjonalne) wywoÅ‚ania zwrotnego, która wykonuje w przypadku wystÄ…pienia błędu. - - * **geolocationOptions**: (opcjonalne) geolocation opcje. - -### Zwraca - - * **Napis**: zwraca identyfikator zegarek, który odwoÅ‚uje siÄ™ oglÄ…dać pozycji interwaÅ‚. Identyfikator zegarek powinny być używane z `navigator.geolocation.clearWatch` Aby przestać oglÄ…dać do zmiany pozycji. - -### PrzykÅ‚ad - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Parametry opcjonalne dostosować pobierania geolocation `Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Opcje - - * **enableHighAccuracy**: stanowi wskazówkÄ™, że aplikacja musi możliwie najlepszych rezultatów. DomyÅ›lnie, urzÄ…dzenie próbuje pobrać `Position` przy użyciu metody oparte na sieci. Ustawienie tej wÅ‚aÅ›ciwoÅ›ci na `true` mówi ramach dokÅ‚adniejszych metod, takich jak pozycjonowanie satelitarne. *(Wartość logiczna)* - - * **Limit czasu**: maksymalna dÅ‚ugość czas (w milisekundach), który może przekazać wywoÅ‚anie `navigator.geolocation.getCurrentPosition` lub `geolocation.watchPosition` do odpowiednich `geolocationSuccess` wykonuje wywoÅ‚anie zwrotne. JeÅ›li `geolocationSuccess` wywoÅ‚ania zwrotnego nie jest wywoÅ‚ywany w tej chwili, `geolocationError` wywoÅ‚ania zwrotnego jest przekazywany `PositionError.TIMEOUT` kod błędu. (Należy zauważyć, że w połączeniu z `geolocation.watchPosition` , `geolocationError` wywoÅ‚ania zwrotnego można nazwać w odstÄ™pie co `timeout` milisekund!) *(Liczba)* - - * **maximumAge**: przyjąć buforowane pozycji, w których wiek jest nie wiÄ™ksza niż okreÅ›lony czas w milisekundach. *(Liczba)* - -### Dziwactwa Androida - -Emulatory Androida 2.x nie zwracajÄ… wynik geolocation, chyba że opcja `enableHighAccuracy` jest ustawiona na `wartość true`. - -## navigator.geolocation.clearWatch - -Przestać oglÄ…dać zmiany poÅ‚ożenia urzÄ…dzenia okreÅ›lany przez parametr `watchID`. - - navigator.geolocation.clearWatch(watchID); - - -### Parametry - - * **watchID**: identyfikator `watchPosition` InterwaÅ‚ jasne. (String) - -### PrzykÅ‚ad - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Zawiera współrzÄ™dne `Position` i sygnatury czasowej, stworzony przez geolocation API. - -### WÅ‚aÅ›ciwoÅ›ci - - * **coords**: zestaw współrzÄ™dnych geograficznych. *(WspółrzÄ™dne)* - - * **timestamp**: Sygnatura czasowa utworzenia dla `coords` . *(DOMTimeStamp)* - -## Coordinates - -`Coordinates` obiektu jest dołączone do `Position` obiektu, który jest dostÄ™pny dla funkcji wywoÅ‚ania zwrotnego w proÅ›by o aktualnej pozycji. Zawiera zestaw wÅ‚aÅ›ciwoÅ›ci, które opisujÄ… geograficzne współrzÄ™dne pozycji. - -### WÅ‚aÅ›ciwoÅ›ci - - * **szerokość geograficzna**: Latitude w stopniach dziesiÄ™tnych. *(Liczba)* - - * **dÅ‚ugość geograficzna**: dÅ‚ugość geograficzna w stopniach dziesiÄ™tnych. *(Liczba)* - - * **wysokość**: wysokość pozycji metrów nad elipsoidalny. *(Liczba)* - - * **dokÅ‚adność**: poziom dokÅ‚adnoÅ›ci współrzÄ™dnych szerokoÅ›ci i dÅ‚ugoÅ›ci geograficznej w metrach. *(Liczba)* - - * **altitudeAccuracy**: poziom dokÅ‚adnoÅ›ci WspółrzÄ™dna wysokość w metrach. *(Liczba)* - - * **pozycja**: kierunek podróży, okreÅ›lonego w stopni liczÄ…c ruchu wskazówek zegara wzglÄ™dem północy rzeczywistej. *(Liczba)* - - * **prÄ™dkość**: Aktualna prÄ™dkość ziemi urzÄ…dzenia, okreÅ›lone w metrach na sekundÄ™. *(Liczba)* - -### Amazon ogieÅ„ OS dziwactwa - -**altitudeAccuracy**: nie obsÅ‚ugiwane przez Android urzÄ…dzeÅ„, zwracanie `wartoÅ›ci null`. - -### Dziwactwa Androida - -**altitudeAccuracy**: nie obsÅ‚ugiwane przez Android urzÄ…dzeÅ„, zwracanie `wartoÅ›ci null`. - -## PositionError - -`PositionError` obiekt jest przekazywany do funkcji wywoÅ‚ania zwrotnego `geolocationError`, gdy wystÄ…pi błąd z navigator.geolocation. - -### WÅ‚aÅ›ciwoÅ›ci - - * **Kod**: jeden z kodów błędów wstÄ™pnie zdefiniowanych poniżej. - - * **wiadomość**: komunikat o błędzie, opisujÄ…c szczegóły wystÄ…piÅ‚ błąd. - -### StaÅ‚e - - * `PositionError.PERMISSION_DENIED` - * Zwracane, gdy użytkownicy nie zezwalajÄ… aplikacji do pobierania informacji o pozycji. Jest to zależne od platformy. - * `PositionError.POSITION_UNAVAILABLE` - * Zwracane, gdy urzÄ…dzenie jest w stanie pobrać pozycji. Ogólnie rzecz biorÄ…c oznacza to urzÄ…dzenie nie jest podłączone do sieci lub nie może uzyskać satelita utrwalić. - * `PositionError.TIMEOUT` - * Zwracane, gdy urzÄ…dzenie jest w stanie pobrać pozycji w czasie okreÅ›lonym przez `timeout` w `geolocationOptions` . Gdy używana z `navigator.geolocation.watchPosition` , ten błąd może być wielokrotnie przekazywane do `geolocationError` zwrotne co `timeout` milisekund.
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/pl/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/pl/index.md deleted file mode 100644 index 6d08320e..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/pl/index.md +++ /dev/null @@ -1,255 +0,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. ---> - -# cordova-plugin-geolocation - -Ten plugin zawiera informacje o lokalizacji urzÄ…dzenia, takie jak szerokość i dÅ‚ugość geograficznÄ…. NajczÄ™stsze źródÅ‚a informacji o lokalizacji obejmujÄ… Global Positioning System (GPS) i lokalizacji wywnioskować z sieci sygnaÅ‚y, takie jak adres IP, RFID, WiFi i Bluetooth MAC adresy, a komórki GSM/CDMA identyfikatorów. Nie ma żadnej gwarancji, że API zwraca rzeczywistej lokalizacji urzÄ…dzenia. - -Ten interfejs API jest oparty na [Specyfikacji W3C Geolocation API][1]i tylko wykonuje na urzÄ…dzeniach, które już nie zapewniajÄ… implementacja. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**Ostrzeżenie**: zbierania i wykorzystywania danych geolokacyjnych podnosi kwestie prywatnoÅ›ci ważne. Polityka prywatnoÅ›ci danej aplikacji należy omówić, jak aplikacja używa danych, czy jest on dzielony z innych stron i poziom dokÅ‚adnoÅ›ci danych (na przykÅ‚ad, gruba, porzÄ…dku, kod pocztowy poziom, itp.). Danych geolokacyjnych ogólnie uznaje wrażliwych, bo to może ujawnić pobytu użytkownika i, jeÅ›li przechowywane, historii ich podróży. W zwiÄ…zku z tym oprócz aplikacji prywatnoÅ›ci, zdecydowanie warto powiadomienia just-in-time, zanim aplikacja uzyskuje dostÄ™p do danych (jeÅ›li urzÄ…dzenie system operacyjny nie robi już). Å»e ogÅ‚oszenie powinno zawierać te same informacje, o których wspomniano powyżej, jak również uzyskanie uprawnienia użytkownika (np. poprzez przedstawianie wyborów **OK** i **Nie dziÄ™ki**). Aby uzyskać wiÄ™cej informacji zobacz przewodnik prywatnoÅ›ci. - -Ten plugin definiuje obiekt globalny `navigator.geolocation` (dla platformy gdzie to inaczej brak). - -Mimo, że obiekt jest w globalnym zasiÄ™gu, funkcji oferowanych przez ten plugin nie sÄ… dostÄ™pne dopiero po turnieju `deviceready`. - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## Instalacja - - cordova plugin add cordova-plugin-geolocation - - -## ObsÅ‚ugiwane platformy - -* Amazon Fire OS -* Android -* BlackBerry 10 -* Firefox OS -* iOS -* Tizen -* Windows Phone 7 i 8 -* Windows 8 - -## Metody - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## Obiekty (tylko do odczytu) - -* Stanowisko -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -Zwraca bieżącÄ… pozycjÄ™ urzÄ…dzenia do `geolocationSuccess` wywoÅ‚anie zwrotne z `Position` obiektu jako parametr. JeÅ›li wystÄ™puje błąd, wywoÅ‚ania zwrotnego `geolocationError` jest przekazywany obiekt `PositionError`. - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametry - -* **geolocationSuccess**: wywoÅ‚ania zwrotnego, który jest przekazywany aktualnej pozycji. - -* **geolocationError**: *(opcjonalne)* wywoÅ‚ania zwrotnego, która wykonuje w przypadku wystÄ…pienia błędu. - -* **geolocationOptions**: *(opcjonalne)* opcji geolokalizacji. - -### PrzykÅ‚ad - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Zwraca bieżącÄ… pozycjÄ™ urzÄ…dzenia po wykryciu zmiany pozycji. Gdy urzÄ…dzenie pobiera nowÄ… lokalizacjÄ™, wywoÅ‚ania zwrotnego `geolocationSuccess` wykonuje siÄ™ z `Position` obiektu jako parametr. JeÅ›li wystÄ™puje błąd, wywoÅ‚ania zwrotnego `geolocationError` wykonuje siÄ™ z obiektem `PositionError` jako parametr. - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### Parametry - -* **geolocationSuccess**: wywoÅ‚ania zwrotnego, który jest przekazywany aktualnej pozycji. - -* **geolocationError**: (opcjonalne) wywoÅ‚ania zwrotnego, która wykonuje w przypadku wystÄ…pienia błędu. - -* **geolocationOptions**: (opcjonalne) geolocation opcje. - -### Zwraca - -* **Napis**: zwraca identyfikator zegarek, który odwoÅ‚uje siÄ™ oglÄ…dać pozycji interwaÅ‚. Identyfikator zegarek powinny być używane z `navigator.geolocation.clearWatch` Aby przestać oglÄ…dać do zmiany pozycji. - -### PrzykÅ‚ad - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -Parametry opcjonalne dostosować pobierania geolocation `Position`. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### Opcje - -* **enableHighAccuracy**: stanowi wskazówkÄ™, że aplikacja musi możliwie najlepszych rezultatów. DomyÅ›lnie, urzÄ…dzenie próbuje pobrać `Position` przy użyciu metody oparte na sieci. Ustawienie tej wÅ‚aÅ›ciwoÅ›ci na `true` mówi ramach dokÅ‚adniejszych metod, takich jak pozycjonowanie satelitarne. *(Wartość logiczna)* - -* **Limit czasu**: maksymalna dÅ‚ugość czas (w milisekundach), który może przekazać wywoÅ‚anie `navigator.geolocation.getCurrentPosition` lub `geolocation.watchPosition` do odpowiednich `geolocationSuccess` wykonuje wywoÅ‚anie zwrotne. JeÅ›li `geolocationSuccess` wywoÅ‚ania zwrotnego nie jest wywoÅ‚ywany w tej chwili, `geolocationError` wywoÅ‚ania zwrotnego jest przekazywany `PositionError.TIMEOUT` kod błędu. (Należy zauważyć, że w połączeniu z `geolocation.watchPosition` , `geolocationError` wywoÅ‚ania zwrotnego można nazwać w odstÄ™pie co `timeout` milisekund!) *(Liczba)* - -* **maximumAge**: przyjąć buforowane pozycji, w których wiek jest nie wiÄ™ksza niż okreÅ›lony czas w milisekundach. *(Liczba)* - -### Dziwactwa Androida - -Emulatory Androida 2.x nie zwracajÄ… wynik geolocation, chyba że opcja `enableHighAccuracy` jest ustawiona na `wartość true`. - -## navigator.geolocation.clearWatch - -Przestać oglÄ…dać zmiany poÅ‚ożenia urzÄ…dzenia okreÅ›lany przez parametr `watchID`. - - navigator.geolocation.clearWatch(watchID); - - -### Parametry - -* **watchID**: identyfikator `watchPosition` InterwaÅ‚ jasne. (String) - -### PrzykÅ‚ad - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Stanowisko - -Zawiera współrzÄ™dne `Position` i sygnatury czasowej, stworzony przez geolocation API. - -### WÅ‚aÅ›ciwoÅ›ci - -* **coords**: zestaw współrzÄ™dnych geograficznych. *(WspółrzÄ™dne)* - -* **sygnatura czasowa**: Sygnatura czasowa utworzenia dla `coords` . *(Data)* - -## Coordinates - -`Coordinates` obiektu jest dołączone do `Position` obiektu, który jest dostÄ™pny dla funkcji wywoÅ‚ania zwrotnego w proÅ›by o aktualnej pozycji. Zawiera zestaw wÅ‚aÅ›ciwoÅ›ci, które opisujÄ… geograficzne współrzÄ™dne pozycji. - -### WÅ‚aÅ›ciwoÅ›ci - -* **szerokość geograficzna**: Latitude w stopniach dziesiÄ™tnych. *(Liczba)* - -* **dÅ‚ugość geograficzna**: dÅ‚ugość geograficzna w stopniach dziesiÄ™tnych. *(Liczba)* - -* **wysokość**: wysokość pozycji metrów nad elipsoidalny. *(Liczba)* - -* **dokÅ‚adność**: poziom dokÅ‚adnoÅ›ci współrzÄ™dnych szerokoÅ›ci i dÅ‚ugoÅ›ci geograficznej w metrach. *(Liczba)* - -* **altitudeAccuracy**: poziom dokÅ‚adnoÅ›ci WspółrzÄ™dna wysokość w metrach. *(Liczba)* - -* **pozycja**: kierunek podróży, okreÅ›lonego w stopni liczÄ…c ruchu wskazówek zegara wzglÄ™dem północy rzeczywistej. *(Liczba)* - -* **prÄ™dkość**: Aktualna prÄ™dkość ziemi urzÄ…dzenia, okreÅ›lone w metrach na sekundÄ™. *(Liczba)* - -### Amazon ogieÅ„ OS dziwactwa - -**altitudeAccuracy**: nie obsÅ‚ugiwane przez Android urzÄ…dzeÅ„, zwracanie `wartoÅ›ci null`. - -### Dziwactwa Androida - -**altitudeAccuracy**: nie obsÅ‚ugiwane przez Android urzÄ…dzeÅ„, zwracanie `wartoÅ›ci null`. - -## PositionError - -`PositionError` obiekt jest przekazywany do funkcji wywoÅ‚ania zwrotnego `geolocationError`, gdy wystÄ…pi błąd z navigator.geolocation. - -### WÅ‚aÅ›ciwoÅ›ci - -* **Kod**: jeden z kodów błędów wstÄ™pnie zdefiniowanych poniżej. - -* **wiadomość**: komunikat o błędzie, opisujÄ…c szczegóły wystÄ…piÅ‚ błąd. - -### StaÅ‚e - -* `PositionError.PERMISSION_DENIED` - * Zwracane, gdy użytkownicy nie zezwalajÄ… aplikacji do pobierania informacji o pozycji. Jest to zależne od platformy. -* `PositionError.POSITION_UNAVAILABLE` - * Zwracane, gdy urzÄ…dzenie jest w stanie pobrać pozycji. Ogólnie rzecz biorÄ…c oznacza to urzÄ…dzenie nie jest podłączone do sieci lub nie może uzyskać satelita utrwalić. -* `PositionError.TIMEOUT` - * Zwracane, gdy urzÄ…dzenie jest w stanie pobrać pozycji w czasie okreÅ›lonym przez `timeout` w `geolocationOptions` . Gdy używana z `navigator.geolocation.watchPosition` , ten błąd może być wielokrotnie przekazywane do `geolocationError` zwrotne co `timeout` milisekund. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ru/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/ru/index.md deleted file mode 100644 index 3d9c766e..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/ru/index.md +++ /dev/null @@ -1,206 +0,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. ---> - -# cordova-plugin-geolocation - -Ðтот плагин предоÑтавлÑет информацию о меÑтоположении уÑтройÑтва, например, Широта и Долгота. Общие иÑточники информации о меÑтонахождении включают глобальной ÑиÑтемы Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ (GPS) и меÑтоположение, выведено из Ñети Ñигналов, таких как IP-адреÑ, RFID, WiFi и Bluetooth MAC-адреÑа и идентификаторы базовых Ñтанций Ñотовой GSM/CDMA. Ðет никакой гарантии, что API возвращает фактичеÑкое меÑтоположение уÑтройÑтва. - -Ðтот API оÑнован на [Спецификации W3C Geolocation API][1]и выполнÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ на уÑтройÑтвах, которые уже не обеÑпечивают реализацию. - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**Предупреждение**: Ñбор и иÑпользование данных Ð³ÐµÐ¾Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð´Ð½Ð¸Ð¼Ð°ÐµÑ‚ вопроÑÑ‹ важные конфиденциальноÑти. Политика конфиденциальноÑти вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° обÑудить, как приложение иÑпользует данные геопозиционированиÑ, ли она ÑовмеÑтно Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ Ñторонами и уровень точноÑти данных (например, грубый, тонкий, почтовый Ð¸Ð½Ð´ÐµÐºÑ ÑƒÑ€Ð¾Ð²Ð½Ñ, Ñ‚.д.). Геолокации, как правило, ÑчитаетÑÑ ÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾Ð¹, потому, что она может выÑвить меÑтонахождение Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸, еÑли Ñохранены, иÑÑ‚Ð¾Ñ€Ð¸Ñ Ð¸Ñ… путешеÑтвиÑ. Таким образом помимо политики конфиденциальноÑти приложениÑ, Ñледует решительно раÑÑмотреть ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ just-in-time, прежде чем приложение обращаетÑÑ Ðº геолокации (еÑли операционной ÑиÑтемы уÑтройÑтва не так уже). Ðто уведомление должно обеÑпечивать ту же информацию, отметили выше, а также Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (например, путем предÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° **OK** и **Ðет, ÑпаÑибо**). Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ информации пожалуйÑта, Ñмотрите в руководÑтве конфиденциальноÑти. - -## УÑтановка - - cordova plugin add cordova-plugin-geolocation - - -## Поддерживаемые платформы - -* Amazon Fire OS -* Android -* BlackBerry 10 -* Firefox OS -* iOS -* Tizen -* Windows Phone 7 и 8 -* Windows 8 - -## Методы - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## Объекты (только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ) - -* Position -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -Возвращает текущее положение уÑтройÑтва Ð´Ð»Ñ `geolocationSuccess` обратного вызова Ñ `Position` объект в качеÑтве параметра. ЕÑли еÑть ошибка, `geolocationError` обратного вызова передаетÑÑ `PositionError` объект. - - navigator.geolocation.getCurrentPosition (geolocationSuccess, [geolocationError], [geolocationOptions]); - - -### Параметры - -* **geolocationSuccess**: обратный вызов, который передаетÑÑ Ð² текущей позиции. - -* **geolocationError**: *(необÑзательно)* обратного вызова, который выполнÑетÑÑ Ð¿Ñ€Ð¸ возникновении ошибки. - -* **geolocationOptions**: *(необÑзательно)* параметры геопозиционированиÑ. - -### Пример - - onSuccess обратного вызова / / Ñтот метод принимает позицию объекта, который Ñодержит / / текущие GPS координаты / / var onSuccess = function(position) {alert (' Широта: ' + position.coords.latitude + «\n» + ' Долгота: ' + position.coords.longitude + «\n» + ' Ð’Ñ‹Ñота: ' + position.coords.altitude + «\n» + ' точноÑть: ' + position.coords.accuracy + «\n» + ' выÑоте точноÑть: ' + position.coords.altitudeAccuracy + «\n» + ' заголовок: ' + position.coords.heading + «\n» + ' ÑкороÑть: ' + position.coords.speed + «\n» + ' штампа времени: ' + position.timestamp + «\n»);}; - - onError обратного вызова получает объект PositionError / / Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ onError(error) {alert (' код: ' + error.code + «\n» + ' Ñообщение: ' + error.message + «\n»);} - - navigator.geolocation.getCurrentPosition (onSuccess, onError); - - -## navigator.geolocation.watchPosition - -Возвращает текущее положение уÑтройÑтва при обнаружении Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² позиции. Когда уÑтройÑтво получает новое меÑто, `geolocationSuccess` обратного вызова выполнÑетÑÑ Ñ `Position` объект в качеÑтве параметра. ЕÑли еÑть ошибка, `geolocationError` обратного вызова выполнÑетÑÑ Ñ `PositionError` объект в качеÑтве параметра. - - var watchId = navigator.geolocation.watchPosition (geolocationSuccess, [geolocationError], [geolocationOptions]); - - -### Параметры - -* **geolocationSuccess**: обратный вызов, который передаетÑÑ Ð² текущей позиции. - -* **geolocationError**: (необÑзательно) обратного вызова, который выполнÑетÑÑ Ð¿Ñ€Ð¸ возникновении ошибки. - -* **geolocationOptions**: параметры (необÑзательно) географичеÑкого раÑположениÑ. - -### Возвращает - -* **Строка**: Возвращает идентификатор чаÑÑ‹, ÑÑылаетÑÑ Ð½Ð° позицию интервала чаÑÑ‹. Идентификатор чаÑÑ‹ должны иÑпользоватьÑÑ Ñ `navigator.geolocation.clearWatch` прекратить Ñлежение за изменением в положении. - -### Пример - - onSuccess обратного вызова / / Ñтот метод принимает «Position» объект, который Ñодержит / / текущие GPS координаты / / Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ onSuccess(position) {var Ñлемент = document.getElementById('geolocation'); - element.innerHTML = ' Широта: ' + position.coords.latitude + ' < br / >' + ' Долгота: ' + position.coords.longitude + ' < br / >' + ' < hr / >' + element.innerHTML; - } / / onError обратного вызова получает объект PositionError / / Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ onError(error) {alert (' код: ' + error.code + «\n» + ' Ñообщение: ' + error.message + «\n»);} - - Опции: БроÑьте Ñообщение об ошибке, еÑли обновление не получено каждые 30 Ñекунд. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, {тайм-аут: 30000}); - - -## geolocationOptions - -ÐеобÑзательные параметры Ð´Ð»Ñ Ð½Ð°Ñтройки поиÑка географичеÑкого раÑположениÑ`Position`. - - {maximumAge: 3000, тайм-аут: 5000, enableHighAccuracy: true}; - - -### Параметры - -* **enableHighAccuracy**: предоÑтавлÑет подÑказку, что приложению требуютÑÑ Ð½Ð°Ð¸Ð»ÑƒÑ‡ÑˆÐ¸Ðµ результаты. По умолчанию уÑтройÑтво пытаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ `Position` Ñ Ð¸Ñпользованием методов на оÑнове Ñети. УÑтановка Ñтого ÑвойÑтва значение `true` указывает Ñреде иÑпользовать более точные методы, например Ñпутникового позиционированиÑ. *(ЛогичеÑкое значение)* - -* **Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ**: макÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° времени (в миллиÑекундах), которое может пройти от вызова `navigator.geolocation.getCurrentPosition` или `geolocation.watchPosition` до ÑоответÑтвующих `geolocationSuccess` выполнÑет обратный вызов. ЕÑли `geolocationSuccess` обратного вызова не вызываетÑÑ Ð² течение Ñтого времени, `geolocationError` обратного вызова передаетÑÑ `PositionError.TIMEOUT` код ошибки. (Обратите внимание, что при иÑпользовании в Ñочетании Ñ `geolocation.watchPosition` , `geolocationError` обратный вызов может быть вызван на интервале каждые `timeout` миллиÑекунд!) *(ЧиÑло)* - -* **maximumAge**: принÑть кÑшированное положение, возраÑÑ‚ которых не превышает указанного времени в миллиÑекундах. *(ЧиÑло)* - -### ОÑобенноÑти Android - -ÐмулÑторы Android 2.x не возвращать результат географичеÑкого раÑположениÑ, еÑли `enableHighAccuracy` параметр имеет значение`true`. - -## navigator.geolocation.clearWatch - -ОÑтановить проÑмотр Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼ÐµÑÑ‚Ð¾Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑƒÑтройÑтва ÑÑылаетÑÑ `watchID` параметр. - - navigator.geolocation.clearWatch(watchID); - - -### Параметры - -* **watchID**: идентификатор `watchPosition` интервал, чтобы очиÑтить. (Строка) - -### Пример - - Опции: наблюдать за изменениÑми в положении и иÑпользовать наиболее / / Ñ‚Ð¾Ñ‡Ð½Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð¾Ð±Ñ€ÐµÑ‚ÐµÐ½Ð¸Ðµ доÑтупным методом. - var watchID = navigator.geolocation.watchPosition (onSuccess, onError, {enableHighAccuracy: true}); - - .. .later на... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -Содержит `Position` координат и отметок времени, ÑÐ¾Ð·Ð´Ð°Ð½Ð½Ð°Ñ API геопозиционированиÑ. - -### Параметры - -* **CoOrds**: набор географичеÑких координат. *(Координаты)* - -* **штамп времени**: штамп времени ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð´Ð»Ñ `coords` . *(Дата)* - -## Coordinates - -A `Coordinates` объект приÑоединен к `Position` объект, который доÑтупен Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð¾Ð³Ð¾ вызова функций в запроÑÑ‹ Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ¹ позиции. Он Ñодержит набор ÑвойÑтв, которые опиÑывают географичеÑкие координаты позиции. - -### Параметры - -* **Широта**: Широта в деÑÑтичных градуÑах. *(ЧиÑло)* - -* **Долгота**: Долгота в деÑÑтичных градуÑах. *(ЧиÑло)* - -* **Ð’Ñ‹Ñота**: выÑота позиции в метрах над ÑллипÑоидом. *(ЧиÑло)* - -* **точноÑть**: уровень точноÑти координат широты и долготы в метрах. *(ЧиÑло)* - -* **altitudeAccuracy**: уровень точноÑти координат выÑоты в метрах. *(ЧиÑло)* - -* **заголовок**: направление движениÑ, указанный в градуÑах, ÑÑ‡Ð¸Ñ‚Ð°Ñ Ð¿Ð¾ чаÑовой Ñтрелке отноÑительно иÑтинного Ñевера. *(ЧиÑло)* - -* **ÑкороÑть**: Ð¢ÐµÐºÑƒÑ‰Ð°Ñ ÑкороÑть земли уÑтройÑтва, указанного в метрах в Ñекунду. *(ЧиÑло)* - -### ОÑобенноÑти Amazon Fire OS - -**altitudeAccuracy**: не поддерживаетÑÑ Android уÑтройÑтв, возвращаÑ`null`. - -### ОÑобенноÑти Android - -**altitudeAccuracy**: не поддерживаетÑÑ Android уÑтройÑтв, возвращаÑ`null`. - -## PositionError - -`PositionError`Объект передаетÑÑ Ð² `geolocationError` функции обратного вызова при возникновении ошибки Ñ navigator.geolocation. - -### Параметры - -* **code**: один из Ñтандартных кодов ошибок, перечиÑленных ниже. - -* **Ñообщение**: Ñообщение об ошибке Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ñ‹Ð¼Ð¸ ÑведениÑми об ошибке. - -### КонÑтанты - -* `PositionError.PERMISSION_DENIED` - * ВозвращаетÑÑ, когда пользователи не позволÑÑŽÑ‚ приложению получить ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ положении. Ðто завиÑит от платформы. -* `PositionError.POSITION_UNAVAILABLE` - * ВозвращаетÑÑ, еÑли уÑтройÑтво не удаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ позиции. Ð’ общем Ñто означает, что прибор не подключен к Ñети или не может получить Спутниковое иÑправить. -* `PositionError.TIMEOUT` - * ВозвращаетÑÑ, еÑли уÑтройÑтво не удаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ позиции в течение времени, заданного параметром `timeout` в `geolocationOptions` . При иÑпользовании Ñ `navigator.geolocation.watchPosition` , Ñта ошибка может быть неоднократно передан `geolocationError` обратного вызова каждый `timeout` миллиÑекунд. diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/zh/README.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/zh/README.md deleted file mode 100644 index b2afea51..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/zh/README.md +++ /dev/null @@ -1,268 +0,0 @@ -<!-- -# license: 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. ---> - -# cordova-plugin-geolocation - -[](https://travis-ci.org/apache/cordova-plugin-geolocation) - -é€™å€‹å¤–æŽ›ç¨‹å¼æä¾›äº†æœ‰é—œè©²è¨å‚™çš„ä½ç½®ï¼Œä¾‹å¦‚緯度和經度資訊。 常見的ä½ç½®è³‡è¨Šä¾†æºåŒ…括全çƒå®šä½ç³»çµ± (GPS) 和網路信號,如 IP ä½å€ã€ RFID〠WiFi å’Œè—牙 MAC ä½å€å’Œ GSM/CDMA å„²å˜æ ¼ Id 從推斷出的ä½ç½®ã€‚ 沒有任何ä¿è‰ï¼ŒAPI 返回è¨å‚™çš„實際ä½ç½®ã€‚ - -æ¤ API 基於[W3C 地ç†å®šä½ API è¦ç¯„](http://dev.w3.org/geo/api/spec-source.html),並åªåŸ·è¡Œå·²ç¶“䏿供坦ç¾çš„è¨å‚™ä¸Šã€‚ - -**è¦å‘Š**: 地ç†å®šä½è³‡æ–™çš„æ”¶é›†å’Œä½¿ç”¨æå‡ºäº†é‡è¦çš„éš±ç§å•題。 您的應用程å¼çš„éš±ç§æ¬ŠåŽŸå‰‡æ‡‰è©²è¨Žè«–é€™æ¬¾æ‡‰ç”¨ç¨‹å¼å¦‚何使用地ç†å®šä½è³‡æ–™ï¼Œè³‡æ–™æ˜¯å¦å…±ç”¨å®ƒçš„ä»»ä½•å…¶ä»–ç· ç´„æ–¹å’Œçš„è³‡æ–™ (例如,粗〠細,ZIP 代碼級別,ç‰ç‰ï¼‰ 的精度水準。 地ç†å®šä½è³‡æ–™ä¸€èˆ¬èªç‚ºæ˜¯æ•æ„Ÿï¼Œå› ç‚ºå®ƒèƒ½æç¤ºä½¿ç”¨è€…的下è½ä»¥åŠå¦‚æžœå˜å„²ï¼Œä»–們的旅行的æ·å²ã€‚ å› æ¤ï¼Œé™¤äº†æ‡‰ç”¨ç¨‹å¼çš„éš±ç§æ¬ŠåŽŸå‰‡ï¼Œæ‚¨æ‡‰å¼·çƒˆè€ƒæ…®ä¹‹å‰æ‡‰ç”¨ç¨‹å¼è¨ªå•地ç†å®šä½è³‡æ–™ (如果è¨å‚™ä½œæ¥ç³»çµ±ä¸æœƒé€™æ¨£åšå·²ç¶“) æä¾›åœ¨æ™‚間的通知。 該通知應æä¾›ç›¸åŒçš„資訊上文指出的並ç²å–è©²ä½¿ç”¨è€…çš„è¨±å¯æ¬Š (例如,通éŽç‚º**確定**並**䏿„Ÿè¬**æå‡ºçš„鏿“‡ï¼‰ã€‚ 有關詳細資訊,請åƒé–±éš±ç§æŒ‡å—。 - -這個外掛程å¼å®šç¾©äº†ä¸€å€‹å…¨çƒ `navigator.geolocation` 物件 (為平臺哪裡å¦å‰‡ä¸Ÿå¤±ï¼‰ã€‚ - -儘管物件是在全çƒç¯„åœå…§ï¼Œæä¾›é€™å€‹å¤–掛程å¼çš„功能ä¸å¯ç”¨ç›´åˆ° `deviceready` 事件之後。 - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## å®‰è£ - -é€™å°±è¦æ±‚科爾多瓦 5.0 + (ç•¶å‰ç©©å®š v1.0.0) - - cordova plugin add cordova-plugin-geolocation - - -舊版本的科爾多瓦ä»å¯ä»¥é€šéŽå·²æ£„用 id (陳舊 0.3.12) å®‰è£ - - cordova plugin add org.apache.cordova.geolocation - - -它也是å¯ä»¥ç›´æŽ¥é€šéŽå›žè³¼ url å®‰è£ (ä¸ç©©å®š) - - cordova plugin add https://github.com/apache/cordova-plugin-geolocation.git - - -## 支æ´çš„平臺 - - * 亞馬éœç« OS - * Android 系統 - * 黑莓 10 - * ç«ç‹ç€è¦½å™¨ä½œæ¥ç³»çµ± - * iOS - * Tizen - * Windows Phone 7 å’Œ 8 - * Windows 8 - * Windows - -## 方法 - - * navigator.geolocation.getCurrentPosition - * navigator.geolocation.watchPosition - * navigator.geolocation.clearWatch - -## 物件 (唯讀) - - * Position - * PositionError - * Coordinates - -## navigator.geolocation.getCurrentPosition - -返回è¨å‚™çš„ç•¶å‰ä½ç½®åˆ° `geolocationSuccess` 回檔與 `Position` ç‰©ä»¶ä½œç‚ºåƒæ•¸ã€‚ 如果有錯誤,`geolocationError` 回檔傳éžä¸€å€‹ `PositionError` 物件。 - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### åƒæ•¸ - - * **geolocationSuccess**: 傳éžç•¶å‰ä½ç½®çš„回檔。 - - * **geolocationError**: *(å¯é¸ï¼‰*如果錯誤發生時執行的回檔。 - - * **geolocationOptions**: *(å¯é¸ï¼‰*地ç†å®šä½é¸é …。 - -### 示例 - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -返回è¨å‚™çš„ç•¶å‰çš„ä½ç½®ï¼Œç•¶æª¢æ¸¬åˆ°æ›´æ”¹ä½ç½®ã€‚ ç•¶è¨å‚™æª¢ç´¢ä¸€å€‹æ–°ä½ç½®æ™‚,則 `geolocationSuccess` 回檔執行與 `Position` ç‰©ä»¶ä½œç‚ºåƒæ•¸ã€‚ 如果有錯誤,則 `geolocationError` 回檔執行åŒä¸€å€‹ `PositionError` ç‰©ä»¶ä½œç‚ºåƒæ•¸ã€‚ - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### åƒæ•¸ - - * **geolocationSuccess**: 傳éžç•¶å‰ä½ç½®çš„回檔。 - - * **geolocationError**: (å¯é¸ï¼‰ 如果錯誤發生時執行的回檔。 - - * **geolocationOptions**: (å¯é¸ï¼‰ 地ç†å®šä½é¸é …。 - -### 返回 - - * **String**: 返回引用的觀看ä½ç½®é–“隔的表 id。 應與一起使用的表 id `navigator.geolocation.clearWatch` åœæ¢äº†è§€çœ‹ä¸ä½ç½®çš„æ›´æ”¹ã€‚ - -### 示例 - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -è‹¥è¦è‡ªè¨‚çš„åœ°ç† `Position` 檢索的å¯é¸åƒæ•¸. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### é¸é … - - * **enableHighAccuracy**: æä¾›æ‡‰ç”¨ç¨‹å¼éœ€è¦æœ€ä½³çš„å¯èƒ½çµæžœçš„æç¤ºã€‚ é è¨æƒ…æ³ä¸‹ï¼Œè©²è¨å‚™å°‡å˜—試檢索 `Position` 使用基於網路的方法。 å°‡æ¤å±¬æ€§è¨ç½®ç‚º `true` 告訴è¦ä½¿ç”¨æ›´ç²¾ç¢ºçš„æ–¹æ³•,如衛星定ä½çš„æ¡†æž¶ã€‚ *(布林值)* - - * **timeout**: 時間 (毫秒) 從調用傳éžï¼Œå…許的最大長度 `navigator.geolocation.getCurrentPosition` 或 `geolocation.watchPosition` 直到相應的 `geolocationSuccess` 回檔執行。 如果 `geolocationSuccess` 䏿œƒåœ¨æ¤æ™‚間內調用回檔 `geolocationError` 傳éžå›žæª” `PositionError.TIMEOUT` 錯誤代碼。 (請注æ„,與一起使用時 `geolocation.watchPosition` 〠`geolocationError` 的時間間隔å¯ä»¥èª¿ç”¨å›žæª”æ¯ `timeout` 毫秒!)*(人數)* - - * **maximumAge**: 接å—其年齡大於指定以毫秒為單ä½çš„æ™‚間沒有緩å˜çš„ä½ç½®ã€‚*(人數)* - -### Android 的怪癖 - -Android 2.x 模擬器ä¸é™¤éž `enableHighAccuracy` é¸é …è¨ç½®ç‚º `true`,å¦å‰‡è¿”回地ç†å®šä½çµæžœ. - -## navigator.geolocation.clearWatch - -åœæ¢è§€å¯Ÿåˆ° `watchID` åƒæ•¸æ‰€å¼•用的è¨å‚™çš„ä½ç½®ã€‚ - - navigator.geolocation.clearWatch(watchID); - - -### åƒæ•¸ - - * **watchID**: çš„ id `watchPosition` 清除的時間間隔。(å—串) - -### 示例 - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -åŒ…å« `Position` 座標和時間戳記,由地ç†ä½ç½® API 創建。 - -### 屬性 - - * **coords**: 一組的地ç†åº§æ¨™ã€‚*(座標)* - - * **timestamp**: 創建時間戳記為 `coords` 。*(DOMTimeStamp)* - -## Coordinates - -`Coordinates` çš„ç‰©ä»¶é™„åŠ åˆ°ä¸€å€‹ `Position` 物件,å¯ç”¨æ–¼åœ¨ç•¶å‰è·ä½çš„請求ä¸çš„回呼函數。 它包å«ä¸€çµ„屬性æè¿°ä½ç½®çš„地ç†åº§æ¨™ã€‚ - -### 屬性 - - * **latitude**: 緯度以å進ä½åº¦ç‚ºå–®ä½ã€‚*(人數)* - - * **longitude**: 經度以å進ä½åº¦ç‚ºå–®ä½ã€‚*(人數)* - - * **altitude**: 高度在米以上橢çƒé«”ä¸çš„ä½ç½®ã€‚*(人數)* - - * **accuracy**: ä¸ç±³çš„緯度和經度座標的精度級別。*(人數)* - - * **altitudeAccuracy**: 在米的海拔高度座標的精度級別。*(人數)* - - * **heading**: 旅行,指定以度為單ä½å…ƒæ•¸ç›®ç›¸å°æ–¼çœŸåŒ—é †æ™‚é‡æ–¹å‘。*(人數)* - - * **speed**: ç•¶å‰åœ°é¢é€Ÿåº¦çš„è¨å‚™ï¼ŒæŒ‡å®šåœ¨ç±³æ¯ç§’。*(人數)* - -### 亞馬éœç« OS 怪癖 - -**altitudeAccuracy**: 䏿”¯æ´çš„ Android è¨å‚™ï¼Œè¿”回 `null`. - -### Android 的怪癖 - -**altitudeAccuracy**: 䏿”¯æ´çš„ Android è¨å‚™ï¼Œè¿”回 `null`. - -## PositionError - -`PositionError` 物件將傳éžçµ¦ `geolocationError` 回呼函數ä¸ï¼Œç•¶å‡ºç¾ navigator.geolocation 錯誤時發生。 - -### 屬性 - - * **code**: 下é¢åˆ—出的é 定義的錯誤代碼之一。 - - * **message**: æè¿°æ‰€é‡åˆ°çš„錯誤的詳細資訊的錯誤訊æ¯ã€‚ - -### å¸¸é‡ - - * `PositionError.PERMISSION_DENIED` - * 返回當使用者ä¸å…è¨±æ‡‰ç”¨ç¨‹å¼æª¢ç´¢çš„ä½ç½®è³‡è¨Šã€‚é€™æ˜¯å–æ±ºæ–¼å¹³è‡ºã€‚ - * `PositionError.POSITION_UNAVAILABLE` - * 返回è¨å‚™æ™‚,ä¸èƒ½æª¢ç´¢çš„ä½ç½®ã€‚一般情æ³ä¸‹ï¼Œé€™æ„味著該è¨å‚™æœªé€£æŽ¥åˆ°ç¶²è·¯æˆ–無法ç²å–衛星的修復。 - * `PositionError.TIMEOUT` - * 返回è¨å‚™æ™‚,無法在指定的時間內檢索ä½ç½® `timeout` ä¸åŒ…å« `geolocationOptions` 。 與一起使用時 `navigator.geolocation.watchPosition` ,æ¤éŒ¯èª¤å¯èƒ½å復傳éžçµ¦ `geolocationError` å›žæª”æ¯ `timeout` 毫秒為單ä½ï¼‰ã€‚
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/doc/zh/index.md b/StoneIsland/plugins/cordova-plugin-geolocation/doc/zh/index.md deleted file mode 100644 index c78a9f79..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/doc/zh/index.md +++ /dev/null @@ -1,255 +0,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. ---> - -# cordova-plugin-geolocation - -é€™å€‹å¤–æŽ›ç¨‹å¼æä¾›äº†æœ‰é—œè©²è¨å‚™çš„ä½ç½®ï¼Œä¾‹å¦‚緯度和經度資訊。 常見的ä½ç½®è³‡è¨Šä¾†æºåŒ…括全çƒå®šä½ç³»çµ± (GPS) 和網路信號,如 IP ä½å€ã€ RFID〠WiFi å’Œè—牙 MAC ä½å€å’Œ GSM/CDMA å„²å˜æ ¼ Id 從推斷出的ä½ç½®ã€‚ 沒有任何ä¿è‰ï¼ŒAPI 返回è¨å‚™çš„實際ä½ç½®ã€‚ - -æ¤ API 基於[W3C 地ç†å®šä½ API è¦ç¯„][1],並åªåŸ·è¡Œå·²ç¶“䏿供坦ç¾çš„è¨å‚™ä¸Šã€‚ - - [1]: http://dev.w3.org/geo/api/spec-source.html - -**è¦å‘Š**: 地ç†å®šä½è³‡æ–™çš„æ”¶é›†å’Œä½¿ç”¨æå‡ºäº†é‡è¦çš„éš±ç§å•題。 您的應用程å¼çš„éš±ç§æ¬ŠåŽŸå‰‡æ‡‰è©²è¨Žè«–é€™æ¬¾æ‡‰ç”¨ç¨‹å¼å¦‚何使用地ç†å®šä½è³‡æ–™ï¼Œè³‡æ–™æ˜¯å¦å…±ç”¨å®ƒçš„ä»»ä½•å…¶ä»–ç· ç´„æ–¹å’Œçš„è³‡æ–™ (例如,粗〠細,ZIP 代碼級別,ç‰ç‰ï¼‰ 的精度水準。 地ç†å®šä½è³‡æ–™ä¸€èˆ¬èªç‚ºæ˜¯æ•æ„Ÿï¼Œå› ç‚ºå®ƒèƒ½æç¤ºä½¿ç”¨è€…的下è½ä»¥åŠå¦‚æžœå˜å„²ï¼Œä»–們的旅行的æ·å²ã€‚ å› æ¤ï¼Œé™¤äº†æ‡‰ç”¨ç¨‹å¼çš„éš±ç§æ¬ŠåŽŸå‰‡ï¼Œæ‚¨æ‡‰å¼·çƒˆè€ƒæ…®ä¹‹å‰æ‡‰ç”¨ç¨‹å¼è¨ªå•地ç†å®šä½è³‡æ–™ (如果è¨å‚™ä½œæ¥ç³»çµ±ä¸æœƒé€™æ¨£åšå·²ç¶“) æä¾›åœ¨æ™‚間的通知。 該通知應æä¾›ç›¸åŒçš„資訊上文指出的並ç²å–è©²ä½¿ç”¨è€…çš„è¨±å¯æ¬Š (例如,通éŽç‚º**確定**並**䏿„Ÿè¬**æå‡ºçš„鏿“‡ï¼‰ã€‚ 有關詳細資訊,請åƒé–±éš±ç§æŒ‡å—。 - -這個外掛程å¼å®šç¾©äº†ä¸€å€‹å…¨çƒ `navigator.geolocation` 物件 (為平臺哪裡å¦å‰‡ä¸Ÿå¤±ï¼‰ã€‚ - -儘管物件是在全çƒç¯„åœå…§ï¼Œæä¾›é€™å€‹å¤–掛程å¼çš„功能ä¸å¯ç”¨ç›´åˆ° `deviceready` 事件之後。 - - document.addEventListener("deviceready", onDeviceReady, false); - function onDeviceReady() { - console.log("navigator.geolocation works well"); - } - - -## å®‰è£ - - cordova plugin add cordova-plugin-geolocation - - -## 支æ´çš„平臺 - -* 亞馬éœç« OS -* Android 系統 -* 黑莓 10 -* ç«ç‹ç€è¦½å™¨ä½œæ¥ç³»çµ± -* iOS -* Tizen -* Windows Phone 7 å’Œ 8 -* Windows 8 - -## 方法 - -* navigator.geolocation.getCurrentPosition -* navigator.geolocation.watchPosition -* navigator.geolocation.clearWatch - -## 物件 (唯讀) - -* Position -* PositionError -* Coordinates - -## navigator.geolocation.getCurrentPosition - -返回è¨å‚™çš„ç•¶å‰ä½ç½®åˆ° `geolocationSuccess` 回檔與 `Position` ç‰©ä»¶ä½œç‚ºåƒæ•¸ã€‚ 如果有錯誤,`geolocationError` 回檔傳éžä¸€å€‹ `PositionError` 物件。 - - navigator.geolocation.getCurrentPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### åƒæ•¸ - -* **geolocationSuccess**: 傳éžç•¶å‰ä½ç½®çš„回檔。 - -* **geolocationError**: *(å¯é¸ï¼‰*如果錯誤發生時執行的回檔。 - -* **geolocationOptions**: *(å¯é¸ï¼‰*地ç†å®šä½é¸é …。 - -### 示例 - - // onSuccess Callback - // This method accepts a Position object, which contains the - // current GPS coordinates - // - var onSuccess = function(position) { - alert('Latitude: ' + position.coords.latitude + '\n' + - 'Longitude: ' + position.coords.longitude + '\n' + - 'Altitude: ' + position.coords.altitude + '\n' + - 'Accuracy: ' + position.coords.accuracy + '\n' + - 'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' + - 'Heading: ' + position.coords.heading + '\n' + - 'Speed: ' + position.coords.speed + '\n' + - 'Timestamp: ' + position.timestamp + '\n'); - }; - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - navigator.geolocation.getCurrentPosition(onSuccess, onError); - - -## navigator.geolocation.watchPosition - -返回è¨å‚™çš„ç•¶å‰çš„ä½ç½®ï¼Œç•¶æª¢æ¸¬åˆ°æ›´æ”¹ä½ç½®ã€‚ ç•¶è¨å‚™æª¢ç´¢ä¸€å€‹æ–°ä½ç½®æ™‚,則 `geolocationSuccess` 回檔執行與 `Position` ç‰©ä»¶ä½œç‚ºåƒæ•¸ã€‚ 如果有錯誤,則 `geolocationError` 回檔執行åŒä¸€å€‹ `PositionError` ç‰©ä»¶ä½œç‚ºåƒæ•¸ã€‚ - - var watchId = navigator.geolocation.watchPosition(geolocationSuccess, - [geolocationError], - [geolocationOptions]); - - -### åƒæ•¸ - -* **geolocationSuccess**: 傳éžç•¶å‰ä½ç½®çš„回檔。 - -* **geolocationError**: (å¯é¸ï¼‰ 如果錯誤發生時執行的回檔。 - -* **geolocationOptions**: (å¯é¸ï¼‰ 地ç†å®šä½é¸é …。 - -### 返回 - -* **String**: 返回引用的觀看ä½ç½®é–“隔的表 id。 應與一起使用的表 id `navigator.geolocation.clearWatch` åœæ¢äº†è§€çœ‹ä¸ä½ç½®çš„æ›´æ”¹ã€‚ - -### 示例 - - // onSuccess Callback - // This method accepts a `Position` object, which contains - // the current GPS coordinates - // - function onSuccess(position) { - var element = document.getElementById('geolocation'); - element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' + - 'Longitude: ' + position.coords.longitude + '<br />' + - '<hr />' + element.innerHTML; - } - - // onError Callback receives a PositionError object - // - function onError(error) { - alert('code: ' + error.code + '\n' + - 'message: ' + error.message + '\n'); - } - - // Options: throw an error if no update is received every 30 seconds. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { timeout: 30000 }); - - -## geolocationOptions - -è‹¥è¦è‡ªè¨‚çš„åœ°ç† `Position` 檢索的å¯é¸åƒæ•¸. - - { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }; - - -### é¸é … - -* **enableHighAccuracy**: æä¾›æ‡‰ç”¨ç¨‹å¼éœ€è¦æœ€ä½³çš„å¯èƒ½çµæžœçš„æç¤ºã€‚ é è¨æƒ…æ³ä¸‹ï¼Œè©²è¨å‚™å°‡å˜—試檢索 `Position` 使用基於網路的方法。 å°‡æ¤å±¬æ€§è¨ç½®ç‚º `true` 告訴è¦ä½¿ç”¨æ›´ç²¾ç¢ºçš„æ–¹æ³•,如衛星定ä½çš„æ¡†æž¶ã€‚ *(布林值)* - -* **timeout**: 時間 (毫秒) 從調用傳éžï¼Œå…許的最大長度 `navigator.geolocation.getCurrentPosition` 或 `geolocation.watchPosition` 直到相應的 `geolocationSuccess` 回檔執行。 如果 `geolocationSuccess` 䏿œƒåœ¨æ¤æ™‚間內調用回檔 `geolocationError` 傳éžå›žæª” `PositionError.TIMEOUT` 錯誤代碼。 (請注æ„,與一起使用時 `geolocation.watchPosition` 〠`geolocationError` 的時間間隔å¯ä»¥èª¿ç”¨å›žæª”æ¯ `timeout` 毫秒!)*(人數)* - -* **maximumAge**: 接å—其年齡大於指定以毫秒為單ä½çš„æ™‚間沒有緩å˜çš„ä½ç½®ã€‚*(人數)* - -### Android 的怪癖 - -Android 2.x 模擬器ä¸é™¤éž `enableHighAccuracy` é¸é …è¨ç½®ç‚º `true`,å¦å‰‡è¿”回地ç†å®šä½çµæžœ. - -## navigator.geolocation.clearWatch - -åœæ¢è§€å¯Ÿåˆ° `watchID` åƒæ•¸æ‰€å¼•用的è¨å‚™çš„ä½ç½®ã€‚ - - navigator.geolocation.clearWatch(watchID); - - -### åƒæ•¸ - -* **watchID**: çš„ id `watchPosition` 清除的時間間隔。(å—串) - -### 示例 - - // Options: watch for changes in position, and use the most - // accurate position acquisition method available. - // - var watchID = navigator.geolocation.watchPosition(onSuccess, onError, { enableHighAccuracy: true }); - - // ...later on... - - navigator.geolocation.clearWatch(watchID); - - -## Position - -åŒ…å« `Position` 座標和時間戳記,由地ç†ä½ç½® API 創建。 - -### 屬性 - -* **coords**: 一組的地ç†åº§æ¨™ã€‚*(座標)* - -* **timestamp**: 創建時間戳記為 `coords` 。*(DOMTimeStamp)* - -## Coordinates - -`Coordinates` çš„ç‰©ä»¶é™„åŠ åˆ°ä¸€å€‹ `Position` 物件,å¯ç”¨æ–¼åœ¨ç•¶å‰è·ä½çš„請求ä¸çš„回呼函數。 它包å«ä¸€çµ„屬性æè¿°ä½ç½®çš„地ç†åº§æ¨™ã€‚ - -### 屬性 - -* **latitude**: 緯度以å進ä½åº¦ç‚ºå–®ä½ã€‚*(人數)* - -* **longitude**: 經度以å進ä½åº¦ç‚ºå–®ä½ã€‚*(人數)* - -* **altitude**: 高度在米以上橢çƒé«”ä¸çš„ä½ç½®ã€‚*(人數)* - -* **accuracy**: ä¸ç±³çš„緯度和經度座標的精度級別。*(人數)* - -* **altitudeAccuracy**: 在米的海拔高度座標的精度級別。*(人數)* - -* **heading**: 旅行,指定以度為單ä½å…ƒæ•¸ç›®ç›¸å°æ–¼çœŸåŒ—é †æ™‚é‡æ–¹å‘。*(人數)* - -* **speed**: ç•¶å‰åœ°é¢é€Ÿåº¦çš„è¨å‚™ï¼ŒæŒ‡å®šåœ¨ç±³æ¯ç§’。*(人數)* - -### 亞馬éœç« OS 怪癖 - -**altitudeAccuracy**: 䏿”¯æ´çš„ Android è¨å‚™ï¼Œè¿”回 `null`. - -### Android 的怪癖 - -**altitudeAccuracy**: 䏿”¯æ´çš„ Android è¨å‚™ï¼Œè¿”回 `null`. - -## PositionError - -`PositionError` 物件將傳éžçµ¦ `geolocationError` 回呼函數ä¸ï¼Œç•¶å‡ºç¾ navigator.geolocation 錯誤時發生。 - -### 屬性 - -* **code**: 下é¢åˆ—出的é 定義的錯誤代碼之一。 - -* **message**: æè¿°æ‰€é‡åˆ°çš„錯誤的詳細資訊的錯誤訊æ¯ã€‚ - -### å¸¸é‡ - -* `PositionError.PERMISSION_DENIED` - * 返回當使用者ä¸å…è¨±æ‡‰ç”¨ç¨‹å¼æª¢ç´¢çš„ä½ç½®è³‡è¨Šã€‚é€™æ˜¯å–æ±ºæ–¼å¹³è‡ºã€‚ -* `PositionError.POSITION_UNAVAILABLE` - * 返回è¨å‚™æ™‚,ä¸èƒ½æª¢ç´¢çš„ä½ç½®ã€‚一般情æ³ä¸‹ï¼Œé€™æ„味著該è¨å‚™æœªé€£æŽ¥åˆ°ç¶²è·¯æˆ–無法ç²å–衛星的修復。 -* `PositionError.TIMEOUT` - * 返回è¨å‚™æ™‚,無法在指定的時間內檢索ä½ç½® `timeout` ä¸åŒ…å« `geolocationOptions` 。 與一起使用時 `navigator.geolocation.watchPosition` ,æ¤éŒ¯èª¤å¯èƒ½å復傳éžçµ¦ `geolocationError` å›žæª”æ¯ `timeout` 毫秒為單ä½ï¼‰ã€‚ diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/package.json b/StoneIsland/plugins/cordova-plugin-geolocation/package.json index a043d278..476328b8 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/package.json +++ b/StoneIsland/plugins/cordova-plugin-geolocation/package.json @@ -1,55 +1,82 @@ { - "name": "cordova-plugin-geolocation", - "version": "2.4.0", - "description": "Cordova Geolocation Plugin", + "_from": "cordova-plugin-geolocation@4.0.2", + "_id": "cordova-plugin-geolocation@4.0.2", + "_inBundle": false, + "_integrity": "sha512-QGThnPKzPxESHkruZlpE0+5aFBVOet8al0vIJ7laSUOQHIC1dd/JY6peVIbtLboKi5Dap1wCKRubOqPqH8xcQA==", + "_location": "/cordova-plugin-geolocation", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "cordova-plugin-geolocation@4.0.2", + "name": "cordova-plugin-geolocation", + "escapedName": "cordova-plugin-geolocation", + "rawSpec": "4.0.2", + "saveSpec": null, + "fetchSpec": "4.0.2" + }, + "_requiredBy": [ + "#DEV:/", + "#USER" + ], + "_resolved": "https://registry.npmjs.org/cordova-plugin-geolocation/-/cordova-plugin-geolocation-4.0.2.tgz", + "_shasum": "4668a01ae8a49e27c5515f8b81880983e96d7eb3", + "_spec": "cordova-plugin-geolocation@4.0.2", + "_where": "/Users/user/work/stone-island/StoneIsland", + "author": { + "name": "Apache Software Foundation" + }, + "bugs": { + "url": "https://github.com/apache/cordova-plugin-geolocation/issues" + }, + "bundleDependencies": false, "cordova": { "id": "cordova-plugin-geolocation", "platforms": [ "android", - "amazon-fireos", "ios", - "blackberry10", - "ubuntu", - "wp7", - "wp8", - "windows8", - "windows", - "firefoxos" + "windows" ] }, - "repository": { - "type": "git", - "url": "https://github.com/apache/cordova-plugin-geolocation" + "deprecated": false, + "description": "Cordova Geolocation Plugin", + "devDependencies": { + "eslint": "^4.0.0", + "eslint-config-semistandard": "^11.0.0", + "eslint-config-standard": "^10.2.1", + "eslint-plugin-import": "^2.3.0", + "eslint-plugin-node": "^5.0.0", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^3.0.1" }, + "engines": { + "cordovaDependencies": { + "3.0.0": { + "cordova-android": ">=6.3.0" + }, + "5.0.0": { + "cordova": ">100" + } + } + }, + "homepage": "https://github.com/apache/cordova-plugin-geolocation#readme", "keywords": [ "cordova", "geolocation", "ecosystem:cordova", "cordova-android", - "cordova-amazon-fireos", "cordova-ios", - "cordova-blackberry10", - "cordova-ubuntu", - "cordova-wp7", - "cordova-wp8", - "cordova-windows8", - "cordova-windows", - "cordova-firefoxos" + "cordova-windows" ], - "scripts": { - "test": "npm run jshint", - "jshint": "node node_modules/jshint/bin/jshint www && node node_modules/jshint/bin/jshint src && node node_modules/jshint/bin/jshint tests" - }, - "author": "Apache Software Foundation", "license": "Apache-2.0", - "engines": { - "cordovaDependencies": { - "3.0.0": { - "cordova": ">100" - } - } + "name": "cordova-plugin-geolocation", + "repository": { + "type": "git", + "url": "git+https://github.com/apache/cordova-plugin-geolocation.git" }, - "devDependencies": { - "jshint": "^2.6.0" - } + "scripts": { + "eslint": "node node_modules/eslint/bin/eslint www && node node_modules/eslint/bin/eslint src && node node_modules/eslint/bin/eslint tests", + "test": "npm run eslint" + }, + "version": "4.0.2" } diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/plugin.xml b/StoneIsland/plugins/cordova-plugin-geolocation/plugin.xml index 48abcafc..4663a7ef 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/plugin.xml +++ b/StoneIsland/plugins/cordova-plugin-geolocation/plugin.xml @@ -22,16 +22,18 @@ xmlns:rim="http://www.blackberry.com/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-geolocation" - version="2.4.0"> + version="4.0.2"> <name>Geolocation</name> <description>Cordova Geolocation Plugin</description> <license>Apache 2.0</license> <keywords>cordova,geolocation</keywords> - <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-geolocation.git</repo> - <issue>https://issues.apache.org/jira/browse/CB/component/12320638</issue> + <repo>https://github.com/apache/cordova-plugin-geolocation</repo> + <issue>https://github.com/apache/cordova-plugin-geolocation/issues</issue> - <dependency id="cordova-plugin-compat" version="^1.0.0" /> + <engines> + <engine name="cordova-android" version=">=6.3.0" /> + </engines> <!-- android --> <platform name="android"> @@ -61,16 +63,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" </platform> - <!-- amazon-fireos --> - <platform name="amazon-fireos"> - - <config-file target="AndroidManifest.xml" parent="/*"> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> - <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> - </config-file> - - </platform> - <!-- ios --> <platform name="ios"> @@ -99,117 +91,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" <source-file src="src/ios/CDVLocation.m" /> <framework src="CoreLocation.framework" /> - <config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription"> - <string></string> - </config-file> - - </platform> - - <!-- blackberry10 --> - <platform name="blackberry10"> - - <js-module src="www/blackberry10/GeolocationProxy.js" name="GeolocationProxy"> - <runs /> - </js-module> - - <js-module src="www/Coordinates.js" name="Coordinates"> - <clobbers target="Coordinates" /> - </js-module> - - <js-module src="www/PositionError.js" name="PositionError"> - <clobbers target="PositionError" /> - </js-module> - - <js-module src="www/Position.js" name="Position"> - <clobbers target="Position" /> - </js-module> - - <js-module src="www/geolocation.js" name="geolocation"> - <clobbers target="navigator.geolocation" /> - </js-module> - - <config-file target="www/config.xml" parent="/widget"> - <feature name="Geolocation" value="Geolocation"/> - </config-file> - - <config-file target="www/config.xml" parent="/widget/rim:permissions"> - <rim:permit>read_geolocation</rim:permit> - </config-file> - - </platform> - - <!-- ubuntu --> - <platform name="ubuntu"> - <js-module src="www/Coordinates.js" name="Coordinates"> - <clobbers target="Coordinates" /> - </js-module> - - <js-module src="www/PositionError.js" name="PositionError"> - <clobbers target="PositionError" /> - </js-module> - - <js-module src="www/Position.js" name="Position"> - <clobbers target="Position" /> - </js-module> - - <js-module src="www/geolocation.js" name="geolocation"> - <clobbers target="navigator.geolocation" /> - </js-module> - - <source-file src="src/ubuntu/geolocation.cpp" /> - <header-file src="src/ubuntu/geolocation.h" /> - <config-file target="config.xml" parent="/*"> - <feature name="Geolocation"> - <param policy_group="location" policy_version="1" /> - </feature> - </config-file> - </platform> - - <!-- wp7 --> - <platform name="wp7"> - - <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities"> - <Capability Name="ID_CAP_LOCATION" /> - </config-file> - - <source-file src="src/wp/Geolocation.cs" /> - </platform> - - <!-- wp8 --> - <platform name="wp8"> - - <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities"> - <Capability Name="ID_CAP_LOCATION" /> - </config-file> - - <source-file src="src/wp/Geolocation.cs" /> - </platform> - - <!-- windows8 --> - <platform name="windows8"> - <config-file target="package.appxmanifest" parent="/Package/Capabilities"> - <DeviceCapability Name="location" /> - </config-file> - - <js-module src="src/windows/GeolocationProxy.js" name="GeolocationProxy"> - <runs /> - </js-module> - - <js-module src="www/Coordinates.js" name="Coordinates"> - <clobbers target="Coordinates" /> - </js-module> - - <js-module src="www/PositionError.js" name="PositionError"> - <clobbers target="PositionError" /> - </js-module> - - <js-module src="www/Position.js" name="Position"> - <clobbers target="Position" /> - </js-module> - - <js-module src="www/geolocation.js" name="geolocation"> - <clobbers target="navigator.geolocation" /> - </js-module> </platform> <!-- windows universal apps (Windows 8.1, Windows Phone 8.1, Windows 8.0) --> @@ -238,31 +119,4 @@ xmlns:android="http://schemas.android.com/apk/res/android" <clobbers target="navigator.geolocation" /> </js-module> </platform> - - <!-- firefoxos --> - <platform name="firefoxos"> - <config-file target="config.xml" parent="/*"> - <permission name="geolocation" description="Required for accessing user location." /> - </config-file> - - <js-module src="src/firefoxos/GeolocationProxy.js" name="GeolocationProxy"> - <runs /> - </js-module> - - <js-module src="www/Coordinates.js" name="Coordinates"> - <clobbers target="Coordinates" /> - </js-module> - - <js-module src="www/PositionError.js" name="PositionError"> - <clobbers target="PositionError" /> - </js-module> - - <js-module src="www/Position.js" name="Position"> - <clobbers target="Position" /> - </js-module> - - <js-module src="www/geolocation.js" name="geolocation"> - <clobbers target="navigator.geolocation" /> - </js-module> - </platform> </plugin> diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/firefoxos/GeolocationProxy.js b/StoneIsland/plugins/cordova-plugin-geolocation/src/firefoxos/GeolocationProxy.js deleted file mode 100644 index e4b40529..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/src/firefoxos/GeolocationProxy.js +++ /dev/null @@ -1,67 +0,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. - * -*/ - -// latest geolocation spec can be found here: http://www.w3.org/TR/geolocation-API/ - -var idsMap = {}; - -module.exports = { - getLocation: function(success, error, args) { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - function successCallback(position) { - // Cordova is creating Position object using just coords - success(position.coords); - } - geo.getCurrentPosition(successCallback, error, { - enableHighAccuracy: args[0], - maximumAge: args[1] - }); - }, - - addWatch: function(success, error, args) { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - var id = args[0]; - function successCallback(position) { - success(position.coords); - } - var nativeId = geo.watchPosition(successCallback, error, { - enableHighAccuracy: args[1] - }); - - idsMap[id] = nativeId; - }, - - clearWatch: function(success, error, args) { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - var id = args[0]; - - if(id in idsMap) { - geo.clearWatch(idsMap[id]); - delete idsMap[id]; - } - - if(success) { - success(); - } - } -}; - -require("cordova/exec/proxy").add("Geolocation", module.exports); diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m b/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m index e4b34a11..d07a8e9c 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m @@ -6,9 +6,9 @@ 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 @@ -65,7 +65,7 @@ - (BOOL)isAuthorized { BOOL authorizationStatusClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+ - + if (authorizationStatusClassPropertyAvailable) { NSUInteger authStatus = [CLLocationManager authorizationStatus]; #ifdef __IPHONE_8_0 @@ -73,9 +73,9 @@ return (authStatus == kCLAuthorizationStatusAuthorizedWhenInUse) || (authStatus == kCLAuthorizationStatusAuthorizedAlways) || (authStatus == kCLAuthorizationStatusNotDetermined); } #endif - return (authStatus == kCLAuthorizationStatusAuthorized) || (authStatus == kCLAuthorizationStatusNotDetermined); + return (authStatus == kCLAuthorizationStatusAuthorizedAlways) || (authStatus == kCLAuthorizationStatusNotDetermined); } - + // by default, assume YES (for iOS < 4.2) return YES; } @@ -84,11 +84,9 @@ { BOOL locationServicesEnabledInstancePropertyAvailable = [self.locationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 3.x BOOL locationServicesEnabledClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 4.x - + if (locationServicesEnabledClassPropertyAvailable) { // iOS 4.x return [CLLocationManager locationServicesEnabled]; - } else if (locationServicesEnabledInstancePropertyAvailable) { // iOS 2.x, iOS 3.x - return [(id)self.locationManager locationServicesEnabled]; } else { return NO; } @@ -114,10 +112,10 @@ } // PERMISSIONDENIED is only PositionError that makes sense when authorization denied [self returnLocationError:PERMISSIONDENIED withMessage:message]; - + return; } - + #ifdef __IPHONE_8_0 NSUInteger code = [CLLocationManager authorizationStatus]; if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) { //iOS8+ @@ -132,7 +130,7 @@ return; } #endif - + // Tell the location manager to start notifying us of location updates. We // first stop, and then start the updating to ensure we get at least one // update, even if our location did not change. @@ -159,7 +157,7 @@ if (![self isLocationServicesEnabled]) { return; } - + [self.locationManager stopUpdatingLocation]; __locationStarted = NO; __highAccuracyEnabled = NO; @@ -171,14 +169,16 @@ fromLocation:(CLLocation*)oldLocation { CDVLocationData* cData = self.locationData; - + cData.locationInfo = newLocation; - if (self.locationData.locationCallbacks.count > 0) { - for (NSString* callbackId in self.locationData.locationCallbacks) { - [self returnLocationInfo:callbackId andKeepCallback:NO]; + @synchronized (self.locationData.locationCallbacks) { + if (self.locationData.locationCallbacks.count > 0) { + for (NSString* callbackId in self.locationData.locationCallbacks) { + [self returnLocationInfo:callbackId andKeepCallback:NO]; + } + + [self.locationData.locationCallbacks removeAllObjects]; } - - [self.locationData.locationCallbacks removeAllObjects]; } if (self.locationData.watchCallbacks.count > 0) { for (NSString* timerId in self.locationData.watchCallbacks) { @@ -195,7 +195,7 @@ [self.commandDelegate runInBackground:^{ NSString* callbackId = command.callbackId; BOOL enableHighAccuracy = [[command argumentAtIndex:0] boolValue]; - + if ([self isLocationServicesEnabled] == NO) { NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; [posError setObject:[NSNumber numberWithInt:PERMISSIONDENIED] forKey:@"code"]; @@ -207,14 +207,18 @@ self.locationData = [[CDVLocationData alloc] init]; } CDVLocationData* lData = self.locationData; - if (!lData.locationCallbacks) { - lData.locationCallbacks = [NSMutableArray arrayWithCapacity:1]; + @synchronized (self.locationData.locationCallbacks) { + if (!lData.locationCallbacks) { + lData.locationCallbacks = [NSMutableArray arrayWithCapacity:1]; + } } - + if (!__locationStarted || (__highAccuracyEnabled != enableHighAccuracy)) { // add the callbackId into the array so we can call back when get data - if (callbackId != nil) { - [lData.locationCallbacks addObject:callbackId]; + @synchronized (self.locationData.locationCallbacks) { + if (callbackId != nil) { + [lData.locationCallbacks addObject:callbackId]; + } } // Tell the location manager to start notifying us of heading updates [self startLocation:enableHighAccuracy]; @@ -230,19 +234,19 @@ NSString* callbackId = command.callbackId; NSString* timerId = [command argumentAtIndex:0]; BOOL enableHighAccuracy = [[command argumentAtIndex:1] boolValue]; - + if (!self.locationData) { self.locationData = [[CDVLocationData alloc] init]; } CDVLocationData* lData = self.locationData; - + if (!lData.watchCallbacks) { lData.watchCallbacks = [NSMutableDictionary dictionaryWithCapacity:1]; } - + // add the callbackId into the dictionary so we can call back whenever get data [lData.watchCallbacks setObject:callbackId forKey:timerId]; - + if ([self isLocationServicesEnabled] == NO) { NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; [posError setObject:[NSNumber numberWithInt:PERMISSIONDENIED] forKey:@"code"]; @@ -260,7 +264,7 @@ - (void)clearWatch:(CDVInvokedUrlCommand*)command { NSString* timerId = [command argumentAtIndex:0]; - + if (self.locationData && self.locationData.watchCallbacks && [self.locationData.watchCallbacks objectForKey:timerId]) { [self.locationData.watchCallbacks removeObjectForKey:timerId]; if([self.locationData.watchCallbacks count] == 0) { @@ -278,7 +282,7 @@ { CDVPluginResult* result = nil; CDVLocationData* lData = self.locationData; - + if (lData && !lData.locationInfo) { // return error result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:POSITIONUNAVAILABLE]; @@ -294,7 +298,7 @@ [returnInfo setObject:[NSNumber numberWithDouble:lInfo.altitude] forKey:@"altitude"]; [returnInfo setObject:[NSNumber numberWithDouble:lInfo.coordinate.latitude] forKey:@"latitude"]; [returnInfo setObject:[NSNumber numberWithDouble:lInfo.coordinate.longitude] forKey:@"longitude"]; - + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:returnInfo]; [result setKeepCallbackAsBool:keepCallback]; } @@ -306,17 +310,20 @@ - (void)returnLocationError:(NSUInteger)errorCode withMessage:(NSString*)message { NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; - + [posError setObject:[NSNumber numberWithUnsignedInteger:errorCode] forKey:@"code"]; [posError setObject:message ? message:@"" forKey:@"message"]; CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; - - for (NSString* callbackId in self.locationData.locationCallbacks) { - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + + + @synchronized (self.locationData.locationCallbacks) { + for (NSString* callbackId in self.locationData.locationCallbacks) { + [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + } + + [self.locationData.locationCallbacks removeAllObjects]; } - - [self.locationData.locationCallbacks removeAllObjects]; - + for (NSString* callbackId in self.locationData.watchCallbacks) { [self.commandDelegate sendPluginResult:result callbackId:callbackId]; } @@ -325,7 +332,7 @@ - (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error { NSLog(@"locationManager::didFailWithError %@", [error localizedFailureReason]); - + CDVLocationData* lData = self.locationData; if (lData && __locationStarted) { // TODO: probably have to once over the various error codes and return one of: @@ -338,10 +345,10 @@ } [self returnLocationError:positionError withMessage:[error localizedDescription]]; } - + if (error.code != kCLErrorLocationUnknown) { - [self.locationManager stopUpdatingLocation]; - __locationStarted = NO; + [self.locationManager stopUpdatingLocation]; + __locationStarted = NO; } } diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.cpp b/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.cpp deleted file mode 100644 index 3d40ab4c..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * Copyright 2013-2016 Canonical Ltd. - * - * Licensed 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. - * -*/ - -#include <QUuid> - -#include "geolocation.h" - -Geolocation::Geolocation(Cordova *cordova) - : CPlugin(cordova), - _geoPositionInfoSource(QGeoPositionInfoSource::createDefaultSource(this)) { - if (_geoPositionInfoSource.data() != 0) { - QObject::connect(_geoPositionInfoSource.data(), - SIGNAL(positionUpdated(QGeoPositionInfo)), - this, - SLOT(positionUpdated(QGeoPositionInfo))); - - QObject::connect(_geoPositionInfoSource.data(), - SIGNAL(updateTimeout()), - this, - SLOT(updateTimeout())); - } -} - -void Geolocation::addWatch(int scId, int ecId, const QString &id, bool enableHighAccuracy) { - Q_UNUSED(enableHighAccuracy); - - assert(_id2sc.find(id) == _id2sc.end()); - - if (!_geoPositionInfoSource.data()) { - QVariantMap err; - err.insert("code", POSITION_UNAVAILABLE); - err.insert("message", "unavailable"); - - this->cb(ecId, err); - return; - } - - _id2sc[id] = scId; - _id2ec[id] = ecId; -} - -void Geolocation::clearWatch(int scId, int ecId, const QString &id) { - _id2sc.remove(id); - _id2ec.remove(id); -} - -void Geolocation::getLocation(int scId, int ecId, bool enableHighAccuracy, qint64 maximumAge) { - Q_UNUSED(maximumAge); - Q_UNUSED(enableHighAccuracy); - - if (!_geoPositionInfoSource.data()) { - QVariantMap err; - err.insert("code", POSITION_UNAVAILABLE); - err.insert("message", "unavailable"); - - this->cb(ecId, err); - return; - } - - _geoPositionInfoSource->requestUpdate(); - - QString id = QString("_INTERNAL_") + QUuid::createUuid().toString(); - - _id2sc[id] = scId; - _id2ec[id] = ecId; - _singleUpdate.insert(id); -} - -void Geolocation::positionUpdated(const QGeoPositionInfo &update) { - QGeoCoordinate coordinate = update.coordinate(); - - QVariantMap p; - - p.insert("latitude", coordinate.latitude()); - p.insert("longitude", coordinate.longitude()); - - if (coordinate.type() == QGeoCoordinate::Coordinate3D) - p.insert("altitude", coordinate.altitude()); - - if (update.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) - p.insert("accuracy", update.attribute(QGeoPositionInfo::HorizontalAccuracy)); - - if (update.hasAttribute(QGeoPositionInfo::Direction)) - p.insert("heading", update.attribute(QGeoPositionInfo::Direction)); - - if (update.hasAttribute(QGeoPositionInfo::GroundSpeed)) - p.insert("velocity", update.attribute(QGeoPositionInfo::GroundSpeed)); - - if (update.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) - p.insert("altitudeAccuracy", update.attribute(QGeoPositionInfo::VerticalAccuracy)); - - p.insert("timestamp", update.timestamp().toMSecsSinceEpoch()); - - for (const QString &id: _id2sc.keys()) { - int scId = _id2sc[id]; - this->cb(scId, p); - if (_singleUpdate.contains(id)) { - _singleUpdate.remove(id); - _id2sc.remove(id); - _id2ec.remove(id); - } - } -} - -void Geolocation::updateTimeout() { - QVariantMap err; - err.insert("code", TIMEOUT); - err.insert("message", "timeout"); - - for (int ecId: _id2ec) { - this->cb(ecId, err); - } - - _id2ec.clear(); - _id2sc.clear(); - _singleUpdate.clear(); -} diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.h b/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.h deleted file mode 100644 index 7345bec9..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2013 Canonical Ltd. - * - * Licensed 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. - * -*/ - -#ifndef GEOLOCATION_H_SVO2013 -#define GEOLOCATION_H_SVO2013 - -#include <QGeoPositionInfoSource> -#include <QGeoPositionInfo> -#include <QtCore> -#include <cassert> - -#include <cplugin.h> - -class Geolocation: public CPlugin { - Q_OBJECT -public: - explicit Geolocation(Cordova *cordova); - - virtual const QString fullName() override { - return Geolocation::fullID(); - } - - virtual const QString shortName() override { - return "Geolocation"; - } - - static const QString fullID() { - return "Geolocation"; - } - -public slots: - void getLocation(int scId, int ecId, bool enableHighAccuracy, qint64 maximumAge); - void addWatch(int scId, int ecId, const QString &id, bool enableHighAccuracy); - void clearWatch(int scId, int ecId, const QString &id); - -protected slots: - void positionUpdated(const QGeoPositionInfo &update); - void updateTimeout(); - -private: - QMap<QString, int> _id2sc; - QMap<QString, int> _id2ec; - QSet<QString> _singleUpdate; - QSharedPointer<QGeoPositionInfoSource> _geoPositionInfoSource; - - enum PositionError { - PERMISSION_DENIED = 1, - POSITION_UNAVAILABLE = 2, - TIMEOUT = 3 - }; -}; - -#endif diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js b/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js index 03ed4950..f792b912 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js @@ -16,14 +16,14 @@ /* global Windows, WinJS */ -var PositionError = require('./PositionError'); -var callbacks = {}; -var locs = {}; +var PositionError = require('./PositionError'); +var callbacks = {}; +var locs = {}; // constants var FALLBACK_EPSILON = 0.001; -function ensureAndCreateLocator() { +function ensureAndCreateLocator () { var deferral; var loc = new Windows.Devices.Geolocation.Geolocator(); @@ -46,30 +46,32 @@ function ensureAndCreateLocator() { return deferral; } -function createErrorCode(loc) { +function createErrorCode (loc) { + /* eslint-disable no-fallthrough */ switch (loc.locationStatus) { - case Windows.Devices.Geolocation.PositionStatus.initializing: - // This status indicates that a location device is still initializing - case Windows.Devices.Geolocation.PositionStatus.noData: - // No location data is currently available - case Windows.Devices.Geolocation.PositionStatus.notInitialized: - // This status indicates that the app has not yet requested - // location data by calling GetGeolocationAsync() or - // registering an event handler for the positionChanged event. - case Windows.Devices.Geolocation.PositionStatus.notAvailable: - // Location is not available on this version of Windows - return PositionError.POSITION_UNAVAILABLE; + case Windows.Devices.Geolocation.PositionStatus.initializing: + // This status indicates that a location device is still initializing + case Windows.Devices.Geolocation.PositionStatus.noData: + // No location data is currently available + case Windows.Devices.Geolocation.PositionStatus.notInitialized: + // This status indicates that the app has not yet requested + // location data by calling GetGeolocationAsync() or + // registering an event handler for the positionChanged event. + case Windows.Devices.Geolocation.PositionStatus.notAvailable: + // Location is not available on this version of Windows + return PositionError.POSITION_UNAVAILABLE; - case Windows.Devices.Geolocation.PositionStatus.disabled: - // The app doesn't have permission to access location, - // either because location has been turned off. - return PositionError.PERMISSION_DENIED; + case Windows.Devices.Geolocation.PositionStatus.disabled: + // The app doesn't have permission to access location, + // either because location has been turned off. + return PositionError.PERMISSION_DENIED; - default: - break; + default: + break; } } -function createResult(pos) { +/* eslint-enable no-fallthrough */ +function createResult (pos) { var res = { accuracy: pos.coordinate.accuracy, heading: pos.coordinate.heading, @@ -95,14 +97,14 @@ module.exports = { getLocation: function (success, fail, args, env) { ensureAndCreateLocator().done(function (loc) { if (loc) { - var highAccuracy = args[0], - maxAge = args[1]; + var highAccuracy = args[0]; + var maxAge = args[1]; loc.desiredAccuracy = highAccuracy ? Windows.Devices.Geolocation.PositionAccuracy.high : Windows.Devices.Geolocation.PositionAccuracy.default; - loc.reportInterval = maxAge ? maxAge : 0; + loc.reportInterval = maxAge || 0; loc.getGeopositionAsync().then( function (pos) { @@ -115,11 +117,10 @@ module.exports = { }); } ); - } - else { + } else { fail({ code: PositionError.POSITION_UNAVAILABLE, - message: "You do not have the required location services present on your system." + message: 'You do not have the required location services present on your system.' }); } }, fail); @@ -136,33 +137,33 @@ module.exports = { var onStatusChanged = function (e) { switch (e.status) { - case Windows.Devices.Geolocation.PositionStatus.noData: - case Windows.Devices.Geolocation.PositionStatus.notAvailable: - fail({ - code: PositionError.POSITION_UNAVAILABLE, - message: "Data from location services is currently unavailable or you do not have the required location services present on your system." - }); - break; + case Windows.Devices.Geolocation.PositionStatus.noData: + case Windows.Devices.Geolocation.PositionStatus.notAvailable: + fail({ + code: PositionError.POSITION_UNAVAILABLE, + message: 'Data from location services is currently unavailable or you do not have the required location services present on your system.' + }); + break; - case Windows.Devices.Geolocation.PositionStatus.disabled: - fail({ - code: PositionError.PERMISSION_DENIED, - message: "Your location is currently turned off." - }); - break; + case Windows.Devices.Geolocation.PositionStatus.disabled: + fail({ + code: PositionError.PERMISSION_DENIED, + message: 'Your location is currently turned off.' + }); + break; // case Windows.Devices.Geolocation.PositionStatus.initializing: // case Windows.Devices.Geolocation.PositionStatus.ready: - default: - break; + default: + break; } }; loc.desiredAccuracy = highAccuracy ? - Windows.Devices.Geolocation.PositionAccuracy.high : - Windows.Devices.Geolocation.PositionAccuracy.default; + Windows.Devices.Geolocation.PositionAccuracy.high : + Windows.Devices.Geolocation.PositionAccuracy.default; - if (cordova.platformId == 'windows') { + if (cordova.platformId === 'windows') { // eslint-disable-line no-undef // 'positionchanged' event fails with error below if movementThreshold is not set // JavaScript runtime error: Operation aborted // You must set the MovementThreshold property or the ReportInterval property before adding event handlers. @@ -174,8 +175,8 @@ module.exports = { } } - loc.addEventListener("positionchanged", onPositionChanged); - loc.addEventListener("statuschanged", onStatusChanged); + loc.addEventListener('positionchanged', onPositionChanged); + loc.addEventListener('statuschanged', onStatusChanged); callbacks[clientId] = { pos: onPositionChanged, status: onStatusChanged }; locs[clientId] = loc; @@ -185,11 +186,11 @@ module.exports = { clearWatch: function (success, fail, args, env) { var clientId = args[0]; var callback = callbacks[clientId]; - var loc = locs[clientId]; + var loc = locs[clientId]; if (callback && loc) { - loc.removeEventListener("positionchanged", callback.pos); - loc.removeEventListener("statuschanged", callback.status); + loc.removeEventListener('positionchanged', callback.pos); + loc.removeEventListener('statuschanged', callback.status); delete callbacks[clientId]; delete locs[clientId]; @@ -199,4 +200,4 @@ module.exports = { } }; -require("cordova/exec/proxy").add("Geolocation", module.exports); +require('cordova/exec/proxy').add('Geolocation', module.exports); diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/wp/GeoLocation.cs b/StoneIsland/plugins/cordova-plugin-geolocation/src/wp/GeoLocation.cs deleted file mode 100644 index 42af72de..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/src/wp/GeoLocation.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* - Licensed 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. -*/ - -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using System.Threading; -using System.Device.Location; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// <summary> - /// This is a command stub, the browser provides the correct implementation. We use this to trigger the static analyzer that we require this permission - /// </summary> - public class Geolocation - { - /* Unreachable code, by design -jm */ - private void triggerGeoInclusion() - { - new GeoCoordinateWatcher(); - } - } -} diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/tests/package.json b/StoneIsland/plugins/cordova-plugin-geolocation/tests/package.json new file mode 100644 index 00000000..39d7cc47 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/tests/package.json @@ -0,0 +1,14 @@ +{ + "name": "cordova-plugin-geolocation-tests", + "version": "4.0.2", + "description": "", + "cordova": { + "id": "cordova-plugin-geolocation-tests", + "platforms": [] + }, + "keywords": [ + "ecosystem:cordova" + ], + "author": "", + "license": "Apache-2.0" +} diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/tests/plugin.xml b/StoneIsland/plugins/cordova-plugin-geolocation/tests/plugin.xml index cf0f2f6d..29b17d62 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/tests/plugin.xml +++ b/StoneIsland/plugins/cordova-plugin-geolocation/tests/plugin.xml @@ -22,11 +22,14 @@ xmlns:rim="http://www.blackberry.com/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-geolocation-tests" - version="2.4.0"> + version="4.0.2"> <name>Cordova Geolocation Plugin Tests</name> <license>Apache 2.0</license> <dependency id="cordova-plugin-device" url="https://github.com/apache/cordova-plugin-device" /> <js-module src="tests.js" name="tests"> </js-module> + <edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge"> + <string>need location access to pass tests</string> + </edit-config> </plugin> diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/tests/tests.js b/StoneIsland/plugins/cordova-plugin-geolocation/tests/tests.js index 50c5bfb2..cf3a5ab5 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/tests/tests.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/tests/tests.js @@ -19,7 +19,7 @@ * */ -/* jshint jasmine: true */ +/* eslint-env jasmine */ /* global WinJS, device */ exports.defineAutoTests = function () { @@ -42,7 +42,7 @@ exports.defineAutoTests = function () { done(); }); }; - + var succeed = function (done, context) { // prevents done() to be called several times if (context) { @@ -60,7 +60,7 @@ exports.defineAutoTests = function () { }; // On Windows, some tests prompt user for permission to use geolocation and interrupt autotests run - var isWindowsStore = (cordova.platformId == "windows8") || (cordova.platformId == "windows" && !WinJS.Utilities.isPhone); + var isWindowsStore = (cordova.platformId === 'windows8') || (cordova.platformId === 'windows' && !WinJS.Utilities.isPhone); // eslint-disable-line no-undef var majorDeviceVersion = null; var versionRegex = /(\d)\..+/.exec(device.version); if (versionRegex !== null) { @@ -68,29 +68,28 @@ exports.defineAutoTests = function () { } // Starting from Android 6.0 there are confirmation dialog which prevents us from running auto tests in silent mode (user interaction needed) // Also, Android emulator doesn't provide geo fix without manual interactions or mocks - var skipAndroid = cordova.platformId == "android" && (device.isVirtual || majorDeviceVersion >= 6); + var skipAndroid = cordova.platformId === 'android' && (device.isVirtual || majorDeviceVersion >= 6); // eslint-disable-line no-undef var isIOSSim = false; // if iOS simulator does not have a location set, it will fail. - describe('Geolocation (navigator.geolocation)', function () { - it("geolocation.spec.1 should exist", function () { + it('geolocation.spec.1 should exist', function () { expect(navigator.geolocation).toBeDefined(); }); - it("geolocation.spec.2 should contain a getCurrentPosition function", function () { + it('geolocation.spec.2 should contain a getCurrentPosition function', function () { expect(typeof navigator.geolocation.getCurrentPosition).toBeDefined(); - expect(typeof navigator.geolocation.getCurrentPosition == 'function').toBe(true); + expect(typeof navigator.geolocation.getCurrentPosition === 'function').toBe(true); }); - it("geolocation.spec.3 should contain a watchPosition function", function () { + it('geolocation.spec.3 should contain a watchPosition function', function () { expect(typeof navigator.geolocation.watchPosition).toBeDefined(); - expect(typeof navigator.geolocation.watchPosition == 'function').toBe(true); + expect(typeof navigator.geolocation.watchPosition === 'function').toBe(true); }); - it("geolocation.spec.4 should contain a clearWatch function", function () { + it('geolocation.spec.4 should contain a clearWatch function', function () { expect(typeof navigator.geolocation.clearWatch).toBeDefined(); - expect(typeof navigator.geolocation.clearWatch == 'function').toBe(true); + expect(typeof navigator.geolocation.clearWatch === 'function').toBe(true); }); }); @@ -99,7 +98,7 @@ exports.defineAutoTests = function () { describe('error callback', function () { - it("geolocation.spec.5 should be called if we set timeout to 0 and maximumAge to a very small number", function (done) { + it('geolocation.spec.5 should be called if we set timeout to 0 and maximumAge to a very small number', function (done) { if (isWindowsStore || skipAndroid) { pending(); } @@ -113,14 +112,14 @@ exports.defineAutoTests = function () { }); }); - it("geolocation.spec.9 on failure should return PositionError object with error code constants", function (done) { + it('geolocation.spec.9 on failure should return PositionError object with error code constants', function (done) { if (isWindowsStore || skipAndroid) { pending(); } navigator.geolocation.getCurrentPosition( fail.bind(this, done), - function(gpsError) { + function (gpsError) { // W3C specs: http://dev.w3.org/geo/api/spec-source.html#position_error_interface expect(gpsError.PERMISSION_DENIED).toBe(1); expect(gpsError.POSITION_UNAVAILABLE).toBe(2); @@ -137,7 +136,7 @@ exports.defineAutoTests = function () { describe('success callback', function () { - it("geolocation.spec.6 should be called with a Position object", function (done) { + it('geolocation.spec.6 should be called with a Position object', function (done) { if (isWindowsStore || skipAndroid) { pending(); } @@ -146,14 +145,13 @@ exports.defineAutoTests = function () { expect(p.coords).toBeDefined(); expect(p.timestamp).toBeDefined(); done(); - }, function(err){ - if(err.message && err.message.indexOf('kCLErrorDomain') > -1){ - console.log("Error: Location not set in simulator, tests will fail."); + }, function (err) { + if (err.message && err.message.indexOf('kCLErrorDomain') > -1) { + console.log('Error: Location not set in simulator, tests will fail.'); expect(true).toBe(true); isIOSSim = true; done(); - } - else { + } else { fail(done); } }, @@ -167,10 +165,10 @@ exports.defineAutoTests = function () { describe('watchPosition method', function () { - beforeEach(function(done) { + beforeEach(function (done) { // This timeout is set to lessen the load on platform's geolocation services // which were causing occasional test failures - setTimeout(function() { + setTimeout(function () { done(); }, 100); }); @@ -182,7 +180,7 @@ exports.defineAutoTests = function () { navigator.geolocation.clearWatch(errorWatch); }); - it("geolocation.spec.7 should be called if we set timeout to 0 and maximumAge to a very small number", function (done) { + it('geolocation.spec.7 should be called if we set timeout to 0 and maximumAge to a very small number', function (done) { if (isWindowsStore || skipAndroid) { pending(); } @@ -197,7 +195,7 @@ exports.defineAutoTests = function () { }); }); - it("geolocation.spec.10 on failure should return PositionError object with error code constants", function (done) { + it('geolocation.spec.10 on failure should return PositionError object with error code constants', function (done) { if (isWindowsStore || skipAndroid) { pending(); } @@ -205,7 +203,7 @@ exports.defineAutoTests = function () { var context = this; errorWatch = navigator.geolocation.watchPosition( fail.bind(this, done, context, 'Unexpected win'), - function(gpsError) { + function (gpsError) { if (context.done) return; context.done = true; @@ -231,7 +229,7 @@ exports.defineAutoTests = function () { navigator.geolocation.clearWatch(successWatch); }); - it("geolocation.spec.8 should be called with a Position object", function (done) { + it('geolocation.spec.8 should be called with a Position object', function (done) { if (isWindowsStore || skipAndroid || isIOSSim) { pending(); } @@ -245,7 +243,7 @@ exports.defineAutoTests = function () { expect(p.coords).toBeDefined(); expect(p.timestamp).toBeDefined(); - // callback could be called sync so we invoke done async to make sure we know watcher id to .clear in afterEach + // callback could be called sync so we invoke done async to make sure we know watcher id to .clear in afterEach setTimeout(function () { done(); }); @@ -273,10 +271,10 @@ exports.defineManualTests = function (contentEl, createActionButton) { /** * Set location status */ - function setLocationStatus(status) { + function setLocationStatus (status) { document.getElementById('location_status').innerHTML = status; } - function setLocationDetails(p) { + function setLocationDetails (p) { var date = (new Date(p.timestamp)); document.getElementById('latitude').innerHTML = p.coords.latitude; document.getElementById('longitude').innerHTML = p.coords.longitude; @@ -285,19 +283,19 @@ exports.defineManualTests = function (contentEl, createActionButton) { document.getElementById('heading').innerHTML = p.coords.heading; document.getElementById('speed').innerHTML = p.coords.speed; document.getElementById('altitude_accuracy').innerHTML = p.coords.altitudeAccuracy; - document.getElementById('timestamp').innerHTML = date.toDateString() + " " + date.toTimeString(); + document.getElementById('timestamp').innerHTML = date.toDateString() + ' ' + date.toTimeString(); } /** * Stop watching the location */ - function stopLocation() { + function stopLocation () { var geo = navigator.geolocation; if (!geo) { - alert('navigator.geolocation object is missing.'); + alert('navigator.geolocation object is missing.'); // eslint-disable-line no-undef return; } - setLocationStatus("Stopped"); + setLocationStatus('Stopped'); if (watchLocationId) { geo.clearWatch(watchLocationId); watchLocationId = null; @@ -310,7 +308,7 @@ exports.defineManualTests = function (contentEl, createActionButton) { var watchLocation = function () { var geo = navigator.geolocation; if (!geo) { - alert('navigator.geolocation object is missing.'); + alert('navigator.geolocation object is missing.'); // eslint-disable-line no-undef return; } @@ -321,13 +319,13 @@ exports.defineManualTests = function (contentEl, createActionButton) { // Fail callback var fail = function (e) { - console.log("watchLocation fail callback with error code " + e); + console.log('watchLocation fail callback with error code ' + e); stopLocation(geo); }; // Get location watchLocationId = geo.watchPosition(success, fail, { enableHighAccuracy: true }); - setLocationStatus("Running"); + setLocationStatus('Running'); }; /** @@ -336,7 +334,7 @@ exports.defineManualTests = function (contentEl, createActionButton) { var getLocation = function (opts) { var geo = navigator.geolocation; if (!geo) { - alert('navigator.geolocation object is missing.'); + alert('navigator.geolocation object is missing.'); // eslint-disable-line no-undef return; } @@ -346,16 +344,16 @@ exports.defineManualTests = function (contentEl, createActionButton) { // Success callback var success = function (p) { setLocationDetails(p); - setLocationStatus("Done"); + setLocationStatus('Done'); }; // Fail callback var fail = function (e) { - console.log("getLocation fail callback with error code " + e.code); - setLocationStatus("Error: " + e.code); + console.log('getLocation fail callback with error code ' + e.code); + setLocationStatus('Error: ' + e.code); }; - setLocationStatus("Retrieving location..."); + setLocationStatus('Retrieving location...'); // Get location geo.getCurrentPosition(success, fail, opts || { enableHighAccuracy: true }); //, {timeout: 10000}); @@ -366,54 +364,54 @@ exports.defineManualTests = function (contentEl, createActionButton) { var location_div = '<div id="info">' + '<b>Status:</b> <span id="location_status">Stopped</span>' + - '<table width="100%">', - latitude = '<tr>' + + '<table width="100%">'; + var latitude = '<tr>' + '<td><b>Latitude:</b></td>' + '<td id="latitude"> </td>' + '<td>(decimal degrees) geographic coordinate [<a href="http://dev.w3.org/geo/api/spec-source.html#lat">#ref]</a></td>' + - '</tr>', - longitude = '<tr>' + + '</tr>'; + var longitude = '<tr>' + '<td><b>Longitude:</b></td>' + '<td id="longitude"> </td>' + '<td>(decimal degrees) geographic coordinate [<a href="http://dev.w3.org/geo/api/spec-source.html#lat">#ref]</a></td>' + - '</tr>', - altitude = '<tr>' + + '</tr>'; + var altitude = '<tr>' + '<td><b>Altitude:</b></td>' + '<td id="altitude"> </td>' + '<td>null if not supported;<br>' + '(meters) height above the [<a href="http://dev.w3.org/geo/api/spec-source.html#ref-wgs">WGS84</a>] ellipsoid. [<a href="http://dev.w3.org/geo/api/spec-source.html#altitude">#ref]</a></td>' + - '</tr>', - accuracy = '<tr>' + + '</tr>'; + var accuracy = '<tr>' + '<td><b>Accuracy:</b></td>' + '<td id="accuracy"> </td>' + '<td>(meters; non-negative; 95% confidence level) the accuracy level of the latitude and longitude coordinates. [<a href="http://dev.w3.org/geo/api/spec-source.html#accuracy">#ref]</a></td>' + - '</tr>', - heading = '<tr>' + + '</tr>'; + var heading = '<tr>' + '<td><b>Heading:</b></td>' + '<td id="heading"> </td>' + '<td>null if not supported;<br>' + 'NaN if speed == 0;<br>' + '(degrees; 0° ≤ heading < 360°) direction of travel of the hosting device- counting clockwise relative to the true north. [<a href="http://dev.w3.org/geo/api/spec-source.html#heading">#ref]</a></td>' + - '</tr>', - speed = '<tr>' + + '</tr>'; + var speed = '<tr>' + '<td><b>Speed:</b></td>' + '<td id="speed"> </td>' + '<td>null if not supported;<br>' + '(meters per second; non-negative) magnitude of the horizontal component of the hosting device current velocity. [<a href="http://dev.w3.org/geo/api/spec-source.html#speed">#ref]</a></td>' + - '</tr>', - altitude_accuracy = '<tr>' + + '</tr>'; + var altitude_accuracy = '<tr>' + '<td><b>Altitude Accuracy:</b></td>' + '<td id="altitude_accuracy"> </td>' + '<td>null if not supported;<br>(meters; non-negative; 95% confidence level) the accuracy level of the altitude. [<a href="http://dev.w3.org/geo/api/spec-source.html#altitude-accuracy">#ref]</a></td>' + - '</tr>', - time = '<tr>' + + '</tr>'; + var time = '<tr>' + '<td><b>Time:</b></td>' + '<td id="timestamp"> </td>' + '<td>(DOMTimeStamp) when the position was acquired [<a href="http://dev.w3.org/geo/api/spec-source.html#timestamp">#ref]</a></td>' + '</tr>' + '</table>' + - '</div>', - actions = + '</div>'; + var actions = '<div id="cordova-getLocation"></div>' + 'Expected result: Will update all applicable values in status box for current location. Status will read Retrieving Location (may not see this if location is retrieved immediately) then Done.' + '<p/> <div id="cordova-watchLocation"></div>' + @@ -421,10 +419,10 @@ exports.defineManualTests = function (contentEl, createActionButton) { '<p/> <div id="cordova-stopLocation"></div>' + 'Expected result: Will stop watching the location so values will not be updated. Status will read Stopped.' + '<p/> <div id="cordova-getOld"></div>' + - 'Expected result: Will update location values with a cached position that is up to 30 seconds old. Verify with time value. Status will read Done.', - values_info = - '<h3>Details about each value are listed below in the status box</h3>', - note = + 'Expected result: Will update location values with a cached position that is up to 30 seconds old. Verify with time value. Status will read Done.'; + var values_info = + '<h3>Details about each value are listed below in the status box</h3>'; + var note = '<h3>Allow use of current location, if prompted</h3>'; contentEl.innerHTML = values_info + location_div + latitude + longitude + altitude + accuracy + heading + speed + diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/www/Coordinates.js b/StoneIsland/plugins/cordova-plugin-geolocation/www/Coordinates.js index 84fdd5b8..1d7e8794 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/www/Coordinates.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/www/Coordinates.js @@ -30,7 +30,7 @@ * @param {Object} altacc * @constructor */ -var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) { +var Coordinates = function (lat, lng, alt, acc, head, vel, altacc) { /** * The latitude of the position. */ diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/www/Position.js b/StoneIsland/plugins/cordova-plugin-geolocation/www/Position.js index d6b2c0cc..b4f20e07 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/www/Position.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/www/Position.js @@ -21,7 +21,7 @@ var Coordinates = require('./Coordinates'); -var Position = function(coords, timestamp) { +var Position = function (coords, timestamp) { if (coords) { this.coords = new Coordinates(coords.latitude, coords.longitude, coords.altitude, coords.accuracy, coords.heading, coords.velocity, coords.altitudeAccuracy); } else { diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/www/PositionError.js b/StoneIsland/plugins/cordova-plugin-geolocation/www/PositionError.js index 94562407..476b322a 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/www/PositionError.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/www/PositionError.js @@ -26,7 +26,7 @@ * @param code * @param message */ -var PositionError = function(code, message) { +var PositionError = function (code, message) { this.code = code || null; this.message = message || ''; }; diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/www/android/geolocation.js b/StoneIsland/plugins/cordova-plugin-geolocation/www/android/geolocation.js index 7265bec0..54005545 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/www/android/geolocation.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/www/android/geolocation.js @@ -19,7 +19,7 @@ * */ -var exec = cordova.require('cordova/exec'); +var exec = cordova.require('cordova/exec'); // eslint-disable-line no-undef var utils = require('cordova/utils'); var PositionError = require('./PositionError'); @@ -28,44 +28,44 @@ var PositionError = require('./PositionError'); var pluginToNativeWatchMap = {}; module.exports = { - getCurrentPosition: function(success, error, args) { - var win = function() { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - geo.getCurrentPosition(success, error, args); + getCurrentPosition: function (success, error, args) { + var win = function () { + var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef + geo.getCurrentPosition(success, error, args); }; - var fail = function() { + var fail = function () { if (error) { - error(new PositionError (PositionError.PERMISSION_DENIED, 'Illegal Access')); + error(new PositionError(PositionError.PERMISSION_DENIED, 'Illegal Access')); } }; - exec(win, fail, "Geolocation", "getPermission", []); + exec(win, fail, 'Geolocation', 'getPermission', []); }, - watchPosition: function(success, error, args) { + watchPosition: function (success, error, args) { var pluginWatchId = utils.createUUID(); - var win = function() { - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); + var win = function () { + var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef pluginToNativeWatchMap[pluginWatchId] = geo.watchPosition(success, error, args); }; - var fail = function() { + var fail = function () { if (error) { error(new PositionError(PositionError.PERMISSION_DENIED, 'Illegal Access')); } }; - exec(win, fail, "Geolocation", "getPermission", []); + exec(win, fail, 'Geolocation', 'getPermission', []); return pluginWatchId; }, - clearWatch: function(pluginWatchId) { - var win = function() { + clearWatch: function (pluginWatchId) { + var win = function () { var nativeWatchId = pluginToNativeWatchMap[pluginWatchId]; - var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); + var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); // eslint-disable-line no-undef geo.clearWatch(nativeWatchId); }; - exec(win, null, "Geolocation", "getPermission", []); + exec(win, null, 'Geolocation', 'getPermission', []); } }; diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/www/blackberry10/GeolocationProxy.js b/StoneIsland/plugins/cordova-plugin-geolocation/www/blackberry10/GeolocationProxy.js deleted file mode 100644 index 0bba2263..00000000 --- a/StoneIsland/plugins/cordova-plugin-geolocation/www/blackberry10/GeolocationProxy.js +++ /dev/null @@ -1,69 +0,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. - * -*/ - -var idsMap = {}, - geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); - -module.exports = { - - getLocation: function(success, error, args) { - var successCallback = function (result) { - var pos = result.coords; - pos.timestamp = result.timestamp; - if (success) { - success(pos); - } - }; - geo.getCurrentPosition(successCallback, error, { - enableHighAccuracy: args[0], - maximumAge: args[1] - }); - }, - - addWatch: function(success, error, args) { - var id = args[0], - successCallback = function (result) { - var pos = result.coords; - pos.timestamp = result.timestamp; - if (success) { - success(pos); - } - }, - nativeId = geo.watchPosition(successCallback, error, { - enableHighAccuracy: args[1] - }); - idsMap[id] = nativeId; - }, - - clearWatch: function(success, error, args) { - var id = args[0]; - if(id in idsMap) { - geo.clearWatch(idsMap[id]); - delete idsMap[id]; - } - if(success) { - success(); - } - } - -}; - -require("cordova/exec/proxy").add("Geolocation", module.exports); diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/www/geolocation.js b/StoneIsland/plugins/cordova-plugin-geolocation/www/geolocation.js index f1f64456..c6c57884 100644 --- a/StoneIsland/plugins/cordova-plugin-geolocation/www/geolocation.js +++ b/StoneIsland/plugins/cordova-plugin-geolocation/www/geolocation.js @@ -19,16 +19,16 @@ * */ -var argscheck = require('cordova/argscheck'), - utils = require('cordova/utils'), - exec = require('cordova/exec'), - PositionError = require('./PositionError'), - Position = require('./Position'); +var argscheck = require('cordova/argscheck'); +var utils = require('cordova/utils'); +var exec = require('cordova/exec'); +var PositionError = require('./PositionError'); +var Position = require('./Position'); -var timers = {}; // list of timers in use +var timers = {}; // list of timers in use // Returns default params, overrides if provided with values -function parseParameters(options) { +function parseParameters (options) { var opt = { maximumAge: 0, enableHighAccuracy: false, @@ -55,20 +55,20 @@ function parseParameters(options) { } // Returns a timeout failure, closed over a specified timeout value and error callback. -function createTimeout(errorCallback, timeout) { - var t = setTimeout(function() { +function createTimeout (errorCallback, timeout) { + var t = setTimeout(function () { clearTimeout(t); t = null; errorCallback({ - code:PositionError.TIMEOUT, - message:"Position retrieval timed out." + code: PositionError.TIMEOUT, + message: 'Position retrieval timed out.' }); }, timeout); return t; } var geolocation = { - lastPosition:null, // reference to last known (cached) position returned + lastPosition: null, // reference to last known (cached) position returned /** * Asynchronously acquires the current position. * @@ -76,15 +76,15 @@ var geolocation = { * @param {Function} errorCallback The function to call when there is an error getting the heading position. (OPTIONAL) * @param {PositionOptions} options The options for getting the position data. (OPTIONAL) */ - getCurrentPosition:function(successCallback, errorCallback, options) { + getCurrentPosition: function (successCallback, errorCallback, options) { argscheck.checkArgs('fFO', 'geolocation.getCurrentPosition', arguments); options = parseParameters(options); // Timer var that will fire an error callback if no position is retrieved from native // before the "timeout" param provided expires - var timeoutTimer = {timer:null}; + var timeoutTimer = {timer: null}; - var win = function(p) { + var win = function (p) { clearTimeout(timeoutTimer.timer); if (!(timeoutTimer.timer)) { // Timeout already happened, or native fired error callback for @@ -94,20 +94,20 @@ var geolocation = { } var pos = new Position( { - latitude:p.latitude, - longitude:p.longitude, - altitude:p.altitude, - accuracy:p.accuracy, - heading:p.heading, - velocity:p.velocity, - altitudeAccuracy:p.altitudeAccuracy + latitude: p.latitude, + longitude: p.longitude, + altitude: p.altitude, + accuracy: p.accuracy, + heading: p.heading, + velocity: p.velocity, + altitudeAccuracy: p.altitudeAccuracy }, p.timestamp ); geolocation.lastPosition = pos; successCallback(pos); }; - var fail = function(e) { + var fail = function (e) { clearTimeout(timeoutTimer.timer); timeoutTimer.timer = null; var err = new PositionError(e.code, e.message); @@ -123,8 +123,8 @@ var geolocation = { // If the cached position check failed and the timeout was set to 0, error out with a TIMEOUT error object. } else if (options.timeout === 0) { fail({ - code:PositionError.TIMEOUT, - message:"timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceeds provided PositionOptions' maximumAge parameter." + code: PositionError.TIMEOUT, + message: "timeout value in PositionOptions set to 0 and no cached Position object available, or cached Position object's age exceeds provided PositionOptions' maximumAge parameter." }); // Otherwise we have to call into native to retrieve a position. } else { @@ -139,7 +139,7 @@ var geolocation = { // always truthy before we call into native timeoutTimer.timer = true; } - exec(win, fail, "Geolocation", "getLocation", [options.enableHighAccuracy, options.maximumAge]); + exec(win, fail, 'Geolocation', 'getLocation', [options.enableHighAccuracy, options.maximumAge]); } return timeoutTimer; }, @@ -152,7 +152,7 @@ var geolocation = { * @param {PositionOptions} options The options for getting the location data such as frequency. (OPTIONAL) * @return String The watch id that must be passed to #clearWatch to stop watching. */ - watchPosition:function(successCallback, errorCallback, options) { + watchPosition: function (successCallback, errorCallback, options) { argscheck.checkArgs('fFO', 'geolocation.getCurrentPosition', arguments); options = parseParameters(options); @@ -161,7 +161,7 @@ var geolocation = { // Tell device to get a position ASAP, and also retrieve a reference to the timeout timer generated in getCurrentPosition timers[id] = geolocation.getCurrentPosition(successCallback, errorCallback, options); - var fail = function(e) { + var fail = function (e) { clearTimeout(timers[id].timer); var err = new PositionError(e.code, e.message); if (errorCallback) { @@ -169,20 +169,20 @@ var geolocation = { } }; - var win = function(p) { + var win = function (p) { clearTimeout(timers[id].timer); if (options.timeout !== Infinity) { timers[id].timer = createTimeout(fail, options.timeout); } var pos = new Position( { - latitude:p.latitude, - longitude:p.longitude, - altitude:p.altitude, - accuracy:p.accuracy, - heading:p.heading, - velocity:p.velocity, - altitudeAccuracy:p.altitudeAccuracy + latitude: p.latitude, + longitude: p.longitude, + altitude: p.altitude, + accuracy: p.accuracy, + heading: p.heading, + velocity: p.velocity, + altitudeAccuracy: p.altitudeAccuracy }, p.timestamp ); @@ -190,7 +190,7 @@ var geolocation = { successCallback(pos); }; - exec(win, fail, "Geolocation", "addWatch", [id, options.enableHighAccuracy]); + exec(win, fail, 'Geolocation', 'addWatch', [id, options.enableHighAccuracy]); return id; }, @@ -199,11 +199,11 @@ var geolocation = { * * @param {String} id The ID of the watch returned from #watchPosition */ - clearWatch:function(id) { + clearWatch: function (id) { if (id && timers[id] !== undefined) { clearTimeout(timers[id].timer); timers[id].timer = false; - exec(null, null, "Geolocation", "clearWatch", [id]); + exec(null, null, 'Geolocation', 'clearWatch', [id]); } } }; diff --git a/StoneIsland/plugins/phonegap-plugin-push/MIT-LICENSE b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/LICENSE index a017eb00..623c70a8 100644 --- a/StoneIsland/plugins/phonegap-plugin-push/MIT-LICENSE +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/LICENSE @@ -1,4 +1,7 @@ -Copyright 2012-2016 Adobe Systems +Copyright 2015-present Drifty Co. +http://drifty.com/ + +MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/README.md b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/README.md new file mode 100644 index 00000000..4674035d --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/README.md @@ -0,0 +1,220 @@ +# cordova-plugin-ionic-keyboard + +This plugin has been designed to work seamlessly with `cordova-plugin-ionic-webview`, so make sure you have it installed first: + + - https://github.com/ionic-team/cordova-plugin-ionic-webview + - https://ionicframework.com/docs/wkwebview/ + +## Installation + +``` +cordova plugin add cordova-plugin-ionic-keyboard --save +``` + +## Preferences + +### KeyboardResize (for iOS only) + +> Boolean (true by default) + +#### Possible values +- `true`: Showing/hiding the keyboard will trigger some kind of resizing of the app (see KeyboardResizeMode) +- `false`: Web will not be resized when the keyboard shows up. + +```xml +<preference name="KeyboardResize" value="true" /> +``` + +### KeyboardResizeMode (for iOS only) + +> String ('native' by default) + +#### Possible values + +- `native`: The whole native webview will be resized when the keyboard shows/hides, it will affect the `vh` relative unit. +- `body`: Only the html `<body>` element will be resized. Relative units are not affected, because the viewport does not change. +- `ionic`: Only the html `ion-app` element will be resized. Only for ionic apps. + +```xml +<preference name="KeyboardResizeMode" value="native" /> +``` + +### KeyboardStyle (for iOS only) + +> String ('light' by default) + +#### Possible values + +- `light` +- `dark` + +```xml +<preference name="KeyboardStyle" value="dark" /> +``` + +### HideKeyboardFormAccessoryBar (for iOS only) + +> Boolean (true by default) + +#### Possible values +- `true`: hides the keyboard accessory bar. +- `false`: shows the keyboard accessory bar. + +```xml +<preference name="HideKeyboardFormAccessoryBar" value="false" /> +``` + +### resizeOnFullScreen (for Android only) + +There is an Android bug that prevents the keyboard from resizing the WebView when the app is in full screen (i.e. if StatusBar plugin is used to hide the StatusBar). This setting, if set to true, add a workaround that resizes the WebView even when the app is in full screen. + +> Boolean (false by default) + +#### Possible values +- `false`: doesn't resize the WebView when the app is in full screen. +- `true`: resizes the WebView when the app is in full screen. + + +```xml +<preference name="resizeOnFullScreen" value="true" /> +``` + + +## Methods + +### Keyboard.hideFormAccessoryBar (for iOS only) + +> Hide the keyboard toolbar. + +Set to true to hide the additional toolbar that is on top of the keyboard. This toolbar features the Prev, Next, and Done buttons. + +```js +Keyboard.hideFormAccessoryBar(value, successCallback); +``` + +#### Quick Example + +```js +Keyboard.hideFormAccessoryBar(true); +Keyboard.hideFormAccessoryBar(false); +Keyboard.hideFormAccessoryBar(null, (currentValue) => { console.log(currentValue); }); +``` + +### Keyboard.hide + +> Hide the keyboard + +Call this method to hide the keyboard + +```js +Keyboard.hide(); +``` + +### Keyboard.show (for Android only) + +> Show the keyboard + +Call this method to show the keyboard. + +```js +Keyboard.show(); +``` + +### Keyboard.setResizeMode (for iOS only) + +> Programmatically set the resize mode + +Call the method with parameter to set the resize mode. + +```js +// Possible values are the same as for 'KeyboardResizeMode' preference +Keyboard.setResizeMode('native'); +Keyboard.setResizeMode('body'); +Keyboard.setResizeMode('ionic'); +``` + +### Keyboard.setKeyboardStyle (for iOS only) + +> Programmatically set the keyboard style + +```js +// Possible values are the same as for 'KeyboardStyle' preference +Keyboard.setKeyboardStyle('light'); // <- default +Keyboard.setKeyboardStyle('dark'); +``` + +### Keyboard.disableScroll (for iOS only) + +> Programmatically enable or disable the WebView scroll + +```js +Keyboard.disableScroll(true); // <- default +Keyboard.disableScroll(false); +``` + + +## Properties + +### Keyboard.isVisible + +> Determine if the keyboard is visible. + +Read this property to determine if the keyboard is visible. + +```js +if (Keyboard.isVisible) { + // do something +} +``` + +## Events + +### keyboardDidHide + +> This event is fired when the keyboard is fully closed. + +Attach handler to this event to be able to receive notification when keyboard is closed. + +```js +window.addEventListener('keyboardDidHide', () => { + // Describe your logic which will be run each time keyboard is closed. +}); +``` + +### keyboardDidShow + +> This event is fired when the keyboard is fully open. + +Attach handler to this event to be able to receive notification when keyboard is opened. + +```js +window.addEventListener('keyboardDidShow', (event) => { + // Describe your logic which will be run each time when keyboard is about to be shown. + console.log(event.keyboardHeight); +}); +``` + +### keyboardWillShow + +> This event fires before keyboard will be shown. + +Attach handler to this event to be able to receive notification when keyboard is about to be shown on the screen. + +```js +window.addEventListener('keyboardWillShow', (event) => { + // Describe your logic which will be run each time when keyboard is about to be shown. + console.log(event.keyboardHeight); +}); +``` + +### keyboardWillHide + +> This event fires before keyboard will be closed. + +Attach handler to this event to be able to receive notification when keyboard is about to be closed. + +```js +window.addEventListener('keyboardWillHide', () => { + // Describe your logic which will be run each time when keyboard is about to be closed. +}); +``` diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/package.json b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/package.json new file mode 100644 index 00000000..c987b845 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/package.json @@ -0,0 +1,59 @@ +{ + "_from": "cordova-plugin-ionic-keyboard", + "_id": "cordova-plugin-ionic-keyboard@2.2.0", + "_inBundle": false, + "_integrity": "sha512-yDUG+9ieKVRitq5mGlNxjaZh/MgEhFFIgTIPhqSbUaQ8UuZbawy5mhJAVClqY97q8/rcQtL6dCDa7x2sEtCLcA==", + "_location": "/cordova-plugin-ionic-keyboard", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "cordova-plugin-ionic-keyboard", + "name": "cordova-plugin-ionic-keyboard", + "escapedName": "cordova-plugin-ionic-keyboard", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#DEV:/", + "#USER" + ], + "_resolved": "https://registry.npmjs.org/cordova-plugin-ionic-keyboard/-/cordova-plugin-ionic-keyboard-2.2.0.tgz", + "_shasum": "53ba9ccd5e765165446a094cfe042a2ddd87d81d", + "_spec": "cordova-plugin-ionic-keyboard", + "_where": "/Users/user/work/stone-island/StoneIsland", + "author": { + "name": "Apache Software Foundation" + }, + "bugs": { + "url": "https://github.com/ionic-team/cordova-plugin-ionic-keyboard/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Ionic Keyboard Plugin", + "devDependencies": { + "np": "^5.0.3", + "sync-cordova-xml": "^0.4.0" + }, + "homepage": "https://github.com/ionic-team/cordova-plugin-ionic-keyboard#readme", + "keywords": [ + "cordova", + "keyboard", + "ecosystem:cordova", + "cordova-ios", + "cordova-android" + ], + "license": "Apache 2.0", + "name": "cordova-plugin-ionic-keyboard", + "repository": { + "type": "git", + "url": "git+https://github.com/ionic-team/cordova-plugin-ionic-keyboard.git" + }, + "scripts": { + "deploy": "np --yolo", + "sync_plugin_xml": "sync-cordova-xml package.json plugin.xml --output=plugin.xml", + "version": "npm run sync_plugin_xml && git add plugin.xml" + }, + "version": "2.2.0" +} diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/plugin.xml b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/plugin.xml new file mode 100644 index 00000000..5badf01c --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/plugin.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:rim="http://www.blackberry.com/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-ionic-keyboard" version="2.2.0"> + <name>cordova-plugin-ionic-keyboard</name> + <description>Ionic Keyboard Plugin</description> + <license>Apache 2.0</license> + <keywords>cordova,keyboard,ecosystem:cordova,cordova-ios,cordova-android</keywords> + <repo>https://github.com/ionic-team/cordova-plugin-ionic-keyboard.git</repo> + <issue>https://github.com/ionic-team/cordova-plugin-ionic-keyboard/issues</issue> + <author>Apache Software Foundation</author> + + <engines> + <engine name="cordova" version=">=3.2.0"/> + </engines> + + <!-- ios --> + <platform name="ios"> + + <js-module src="www/ios/keyboard.js" name="keyboard"> + <clobbers target="window.Keyboard"/> + </js-module> + + <config-file target="config.xml" parent="/*"> + <feature name="CDVIonicKeyboard"> + <param name="ios-package" value="CDVIonicKeyboard" onload="true"/> + </feature> + </config-file> + + <header-file src="src/ios/CDVIonicKeyboard.h"/> + <source-file src="src/ios/CDVIonicKeyboard.m"/> + </platform> + + <!-- android --> + <platform name="android"> + <js-module src="www/android/keyboard.js" name="keyboard"> + <clobbers target="window.Keyboard"/> + </js-module> + <config-file target="config.xml" parent="/*"> + <feature name="CDVIonicKeyboard"> + <param name="android-package" value="io.ionic.keyboard.CDVIonicKeyboard" onload="true"/> + </feature> + </config-file> + + <source-file src="src/android/CDVIonicKeyboard.java" target-dir="src/io/ionic/keyboard"/> + </platform> + +</plugin> diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/android/IonicKeyboard.java b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/android/CDVIonicKeyboard.java index 128063b9..b7ec4556 100644 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/android/IonicKeyboard.java +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/android/CDVIonicKeyboard.java @@ -13,6 +13,7 @@ import android.content.Context; import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.View; +import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.inputmethod.InputMethodManager; @@ -20,15 +21,21 @@ import android.view.inputmethod.InputMethodManager; import android.view.Display; import android.graphics.Point; import android.os.Build; +import android.widget.FrameLayout; -public class IonicKeyboard extends CordovaPlugin { +public class CDVIonicKeyboard extends CordovaPlugin { + private OnGlobalLayoutListener list; + private View rootView; + private View mChildOfContent; + private int usableHeightPrevious; + private FrameLayout.LayoutParams frameLayoutParams; public void initialize(CordovaInterface cordova, CordovaWebView webView) { super.initialize(cordova, webView); } public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException { - if ("close".equals(action)) { + if ("hide".equals(action)) { cordova.getThreadPool().execute(new Runnable() { public void run() { //http://stackoverflow.com/a/7696791/1091751 @@ -64,11 +71,16 @@ public class IonicKeyboard extends CordovaPlugin { final float density = dm.density; //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing - final View rootView = cordova.getActivity().getWindow().getDecorView().findViewById(android.R.id.content).getRootView(); - OnGlobalLayoutListener list = new OnGlobalLayoutListener() { + FrameLayout content = (FrameLayout) cordova.getActivity().findViewById(android.R.id.content); + rootView = content.getRootView(); + list = new OnGlobalLayoutListener() { int previousHeightDiff = 0; @Override public void onGlobalLayout() { + boolean resize = preferences.getBoolean("resizeOnFullScreen", false); + if (resize) { + possiblyResizeChildOfContent(); + } Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. rootView.getWindowVisibleDisplayFrame(r); @@ -108,12 +120,33 @@ public class IonicKeyboard extends CordovaPlugin { callbackContext.sendPluginResult(result); } previousHeightDiff = pixelHeightDiff; - } - }; + } - rootView.getViewTreeObserver().addOnGlobalLayoutListener(list); + private void possiblyResizeChildOfContent() { + int usableHeightNow = computeUsableHeight(); + if (usableHeightNow != usableHeightPrevious) { + int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); + int heightDifference = usableHeightSansKeyboard - usableHeightNow; + if (heightDifference > (usableHeightSansKeyboard/4)) { + frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; + } else { + frameLayoutParams.height = usableHeightSansKeyboard; + } + mChildOfContent.requestLayout(); + usableHeightPrevious = usableHeightNow; + } + } + private int computeUsableHeight() { + Rect r = new Rect(); + mChildOfContent.getWindowVisibleDisplayFrame(r); + return (r.bottom - r.top); + } + }; + mChildOfContent = content.getChildAt(0); + rootView.getViewTreeObserver().addOnGlobalLayoutListener(list); + frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); PluginResult dataResult = new PluginResult(PluginResult.Status.OK); dataResult.setKeepCallback(true); callbackContext.sendPluginResult(dataResult); @@ -124,7 +157,9 @@ public class IonicKeyboard extends CordovaPlugin { return false; // Returning false results in a "MethodNotFound" error. } + @Override + public void onDestroy() { + rootView.getViewTreeObserver().removeOnGlobalLayoutListener(list); + } } - - diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/ios/CDVIonicKeyboard.h b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/ios/CDVIonicKeyboard.h new file mode 100644 index 00000000..aae6766a --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/ios/CDVIonicKeyboard.h @@ -0,0 +1,24 @@ +/* + 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. + */ + +#import <Cordova/CDVPlugin.h> + +@interface CDVIonicKeyboard : CDVPlugin + +@end diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/ios/CDVIonicKeyboard.m b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/ios/CDVIonicKeyboard.m new file mode 100644 index 00000000..e4615a84 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/src/ios/CDVIonicKeyboard.m @@ -0,0 +1,411 @@ +/* + 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. + */ + +#import "CDVIonicKeyboard.h" +#import <Cordova/CDVAvailability.h> +#import <Cordova/NSDictionary+CordovaPreferences.h> +#import <objc/runtime.h> + +typedef enum : NSUInteger { + ResizeNone, + ResizeNative, + ResizeBody, + ResizeIonic, +} ResizePolicy; + +#ifndef __CORDOVA_3_2_0 +#warning "The keyboard plugin is only supported in Cordova 3.2 or greater, it may not work properly in an older version. If you do use this plugin in an older version, make sure the HideKeyboardFormAccessoryBar and KeyboardShrinksView preference values are false." +#endif + +@interface CDVIonicKeyboard () <UIScrollViewDelegate> + +@property (readwrite, assign, nonatomic) BOOL disableScroll; +@property (readwrite, assign, nonatomic) BOOL hideFormAccessoryBar; +@property (readwrite, assign, nonatomic) BOOL keyboardIsVisible; +@property (nonatomic, readwrite) ResizePolicy keyboardResizes; +@property (readwrite, assign, nonatomic) NSString* keyboardStyle; +@property (nonatomic, readwrite) BOOL isWK; +@property (nonatomic, readwrite) int paddingBottom; + +@end + +@implementation CDVIonicKeyboard + +NSTimer *hideTimer; + +- (id)settingForKey:(NSString *)key +{ + return [self.commandDelegate.settings objectForKey:[key lowercaseString]]; +} + +#pragma mark Initialize + +NSString* UIClassString; +NSString* WKClassString; +NSString* UITraitsClassString; + +- (void)pluginInitialize +{ + UIClassString = [@[@"UI", @"Web", @"Browser", @"View"] componentsJoinedByString:@""]; + WKClassString = [@[@"WK", @"Content", @"View"] componentsJoinedByString:@""]; + UITraitsClassString = [@[@"UI", @"Text", @"Input", @"Traits"] componentsJoinedByString:@""]; + + NSDictionary *settings = self.commandDelegate.settings; + + self.disableScroll = ![settings cordovaBoolSettingForKey:@"ScrollEnabled" defaultValue:NO]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarDidChangeFrame:) name: UIApplicationDidChangeStatusBarFrameNotification object:nil]; + + self.keyboardResizes = ResizeNative; + BOOL doesResize = [settings cordovaBoolSettingForKey:@"KeyboardResize" defaultValue:YES]; + if (!doesResize) { + self.keyboardResizes = ResizeNone; + NSLog(@"CDVIonicKeyboard: no resize"); + + } else { + NSString *resizeMode = [settings cordovaSettingForKey:@"KeyboardResizeMode"]; + if (resizeMode) { + if ([resizeMode isEqualToString:@"ionic"]) { + self.keyboardResizes = ResizeIonic; + } else if ([resizeMode isEqualToString:@"body"]) { + self.keyboardResizes = ResizeBody; + } + } + NSLog(@"CDVIonicKeyboard: resize mode %lu", (unsigned long)self.keyboardResizes); + } + self.hideFormAccessoryBar = [settings cordovaBoolSettingForKey:@"HideKeyboardFormAccessoryBar" defaultValue:YES]; + + NSString *keyboardStyle = [settings cordovaSettingForKey:@"KeyboardStyle"]; + if (keyboardStyle) { + [self setKeyboardStyle:keyboardStyle]; + } + + if ([settings cordovaBoolSettingForKey:@"KeyboardAppearanceDark" defaultValue:NO]) { + [self setKeyboardStyle:@"dark"]; + } + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + + [nc addObserver:self selector:@selector(onKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + [nc addObserver:self selector:@selector(onKeyboardDidHide:) name:UIKeyboardDidHideNotification object:nil]; + [nc addObserver:self selector:@selector(onKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [nc addObserver:self selector:@selector(onKeyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; + + // Prevent WKWebView to resize window + BOOL isWK = self.isWK = [self.webView isKindOfClass:NSClassFromString(@"WKWebView")]; + if (!isWK) { + NSLog(@"CDVIonicKeyboard: WARNING!!: Keyboard plugin works better with WK"); + } + + if (isWK) { + [nc removeObserver:self.webView name:UIKeyboardWillHideNotification object:nil]; + [nc removeObserver:self.webView name:UIKeyboardWillShowNotification object:nil]; + [nc removeObserver:self.webView name:UIKeyboardWillChangeFrameNotification object:nil]; + [nc removeObserver:self.webView name:UIKeyboardDidChangeFrameNotification object:nil]; + } +} + +-(void)statusBarDidChangeFrame:(NSNotification*)notification +{ + [self _updateFrame]; +} + + +#pragma mark Keyboard events + +- (void)resetScrollView +{ + UIScrollView *scrollView = [self.webView scrollView]; + [scrollView setContentInset:UIEdgeInsetsZero]; +} + +- (void)onKeyboardWillHide:(NSNotification *)sender +{ + if (self.isWK) { + [self setKeyboardHeight:0 delay:0.01]; + [self resetScrollView]; + } + hideTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(fireOnHiding) userInfo:nil repeats:NO]; +} + +- (void)fireOnHiding { + [self.commandDelegate evalJs:@"Keyboard.fireOnHiding();"]; +} + +- (void)onKeyboardWillShow:(NSNotification *)note +{ + if (hideTimer != nil) { + [hideTimer invalidate]; + } + CGRect rect = [[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; + double height = rect.size.height; + + if (self.isWK) { + double duration = [[note.userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + [self setKeyboardHeight:height delay:duration+0.2]; + [self resetScrollView]; + } + + [self setKeyboardStyle:self.keyboardStyle]; + + NSString *js = [NSString stringWithFormat:@"Keyboard.fireOnShowing(%d);", (int)height]; + [self.commandDelegate evalJs:js]; +} + +- (void)onKeyboardDidShow:(NSNotification *)note +{ + CGRect rect = [[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; + double height = rect.size.height; + + if (self.isWK) { + [self resetScrollView]; + } + + NSString *js = [NSString stringWithFormat:@"Keyboard.fireOnShow(%d);", (int)height]; + [self.commandDelegate evalJs:js]; +} + +- (void)onKeyboardDidHide:(NSNotification *)sender +{ + [self.commandDelegate evalJs:@"Keyboard.fireOnHide();"]; + [self resetScrollView]; +} + +- (void)setKeyboardHeight:(int)height delay:(NSTimeInterval)delay +{ + if (self.keyboardResizes != ResizeNone) { + [self setPaddingBottom: height delay:delay]; + } +} + +- (void)setPaddingBottom:(int)paddingBottom delay:(NSTimeInterval)delay +{ + if (self.paddingBottom == paddingBottom) { + return; + } + + self.paddingBottom = paddingBottom; + + __weak CDVIonicKeyboard* weakSelf = self; + SEL action = @selector(_updateFrame); + [NSObject cancelPreviousPerformRequestsWithTarget:weakSelf selector:action object:nil]; + if (delay == 0) { + [self _updateFrame]; + } else { + [weakSelf performSelector:action withObject:nil afterDelay:delay]; + } +} + +- (void)_updateFrame +{ + CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size; + int statusBarHeight = MIN(statusBarSize.width, statusBarSize.height); + + int _paddingBottom = (int)self.paddingBottom; + + if (statusBarHeight == 40) { + _paddingBottom = _paddingBottom + 20; + } + NSLog(@"CDVIonicKeyboard: updating frame"); + // NOTE: to handle split screen correctly, the application's window bounds must be used as opposed to the screen's bounds. + CGRect f = [[[[UIApplication sharedApplication] delegate] window] bounds]; + CGRect wf = self.webView.frame; + switch (self.keyboardResizes) { + case ResizeBody: + { + NSString *js = [NSString stringWithFormat:@"Keyboard.fireOnResize(%d, %d, document.body);", + _paddingBottom, (int)f.size.height]; + [self.commandDelegate evalJs:js]; + break; + } + case ResizeIonic: + { + NSString *js = [NSString stringWithFormat:@"Keyboard.fireOnResize(%d, %d, document.querySelector('ion-app'));", + _paddingBottom, (int)f.size.height]; + [self.commandDelegate evalJs:js]; + break; + } + case ResizeNative: + { + [self.webView setFrame:CGRectMake(wf.origin.x, wf.origin.y, f.size.width - wf.origin.x, f.size.height - wf.origin.y - self.paddingBottom)]; + break; + } + default: + break; + } + [self resetScrollView]; +} + +#pragma mark Keyboard Style + + - (void)setKeyboardStyle:(NSString*)style +{ + IMP newImp = [style isEqualToString:@"dark"] ? imp_implementationWithBlock(^(id _s) { + return UIKeyboardAppearanceDark; + }) : imp_implementationWithBlock(^(id _s) { + return UIKeyboardAppearanceLight; + }); + + if (self.isWK) { + for (NSString* classString in @[WKClassString, UITraitsClassString]) { + Class c = NSClassFromString(classString); + Method m = class_getInstanceMethod(c, @selector(keyboardAppearance)); + + if (m != NULL) { + method_setImplementation(m, newImp); + } else { + class_addMethod(c, @selector(keyboardAppearance), newImp, "l@:"); + } + } + } + else { + for (NSString* classString in @[UIClassString, UITraitsClassString]) { + Class c = NSClassFromString(classString); + Method m = class_getInstanceMethod(c, @selector(keyboardAppearance)); + + if (m != NULL) { + method_setImplementation(m, newImp); + } else { + class_addMethod(c, @selector(keyboardAppearance), newImp, "l@:"); + } + } + } + + _keyboardStyle = style; +} + +#pragma mark HideFormAccessoryBar + +static IMP UIOriginalImp; +static IMP WKOriginalImp; + +- (void)setHideFormAccessoryBar:(BOOL)hideFormAccessoryBar +{ + if (hideFormAccessoryBar == _hideFormAccessoryBar) { + return; + } + + Method UIMethod = class_getInstanceMethod(NSClassFromString(UIClassString), @selector(inputAccessoryView)); + Method WKMethod = class_getInstanceMethod(NSClassFromString(WKClassString), @selector(inputAccessoryView)); + + if (hideFormAccessoryBar) { + UIOriginalImp = method_getImplementation(UIMethod); + WKOriginalImp = method_getImplementation(WKMethod); + + IMP newImp = imp_implementationWithBlock(^(id _s) { + return nil; + }); + + method_setImplementation(UIMethod, newImp); + method_setImplementation(WKMethod, newImp); + } else { + method_setImplementation(UIMethod, UIOriginalImp); + method_setImplementation(WKMethod, WKOriginalImp); + } + + _hideFormAccessoryBar = hideFormAccessoryBar; +} + +#pragma mark scroll + +- (void)setDisableScroll:(BOOL)disableScroll { + if (disableScroll == _disableScroll) { + return; + } + if (disableScroll) { + self.webView.scrollView.scrollEnabled = NO; + self.webView.scrollView.delegate = self; + } + else { + self.webView.scrollView.scrollEnabled = YES; + self.webView.scrollView.delegate = nil; + } + _disableScroll = disableScroll; +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + [scrollView setContentOffset: CGPointZero]; +} + +#pragma mark Plugin interface + +- (void)hideFormAccessoryBar:(CDVInvokedUrlCommand *)command +{ + if (command.arguments.count > 0) { + id value = [command.arguments objectAtIndex:0]; + if (!([value isKindOfClass:[NSNumber class]])) { + value = [NSNumber numberWithBool:NO]; + } + + self.hideFormAccessoryBar = [value boolValue]; + } + + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:self.hideFormAccessoryBar] + callbackId:command.callbackId]; +} + +- (void)hide:(CDVInvokedUrlCommand *)command +{ + [self.webView endEditing:YES]; +} + +- (void)setResizeMode:(CDVInvokedUrlCommand *)command +{ + NSString * mode = [command.arguments objectAtIndex:0]; + if ([mode isEqualToString:@"ionic"]) { + self.keyboardResizes = ResizeIonic; + } else if ([mode isEqualToString:@"body"]) { + self.keyboardResizes = ResizeBody; + } else if ([mode isEqualToString:@"native"]) { + self.keyboardResizes = ResizeNative; + } else { + self.keyboardResizes = ResizeNone; + } +} + +- (void)keyboardStyle:(CDVInvokedUrlCommand*)command +{ + id value = [command.arguments objectAtIndex:0]; + if ([value isKindOfClass:[NSString class]]) { + value = [(NSString*)value lowercaseString]; + } else { + value = @"light"; + } + + self.keyboardStyle = value; +} + +- (void)disableScroll:(CDVInvokedUrlCommand*)command { + if (!command.arguments || ![command.arguments count]){ + return; + } + id value = [command.arguments objectAtIndex:0]; + if (value != [NSNull null]) { + self.disableScroll = [value boolValue]; + } +} + +#pragma mark dealloc + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js new file mode 100755 index 00000000..ac68cfc6 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/www/android/keyboard.js @@ -0,0 +1,84 @@ +var argscheck = require('cordova/argscheck'), + utils = require('cordova/utils'), + exec = require('cordova/exec'), + channel = require('cordova/channel'); + +var Keyboard = function () {}; + +Keyboard.fireOnShow = function (height) { + Keyboard.isVisible = true; + cordova.fireWindowEvent('keyboardDidShow', { + 'keyboardHeight': height + }); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardshow', { + 'keyboardHeight': height + }); +}; + +Keyboard.fireOnHide = function () { + Keyboard.isVisible = false; + cordova.fireWindowEvent('keyboardDidHide'); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardhide'); +}; + +Keyboard.fireOnHiding = function () { + cordova.fireWindowEvent('keyboardWillHide'); +}; + +Keyboard.fireOnShowing = function (height) { + cordova.fireWindowEvent('keyboardWillShow', { + 'keyboardHeight': height + }); +}; + +Keyboard.hideFormAccessoryBar = Keyboard.hideKeyboardAccessoryBar = function (hide) { + console.warn("Keyboard.hideKeyboardAccessoryBar() not supported in Android"); +}; + +Keyboard.hide = function () { + exec(null, null, "CDVIonicKeyboard", "hide", []); +}; + +Keyboard.show = function () { + exec(null, null, "CDVIonicKeyboard", "show", []); +}; + +Keyboard.disableScroll = function (disable) { + console.warn("Keyboard.disableScroll() not supported in Android"); +}; + +Keyboard.setResizeMode = function (mode) { + console.warn("Keyboard.setResizeMode() not supported in Android"); +} + +Keyboard.setKeyboardStyle = function(style) { + console.warn("Keyboard.setKeyboardStyle() not supported in Android"); +}; + +channel.onCordovaReady.subscribe(function () { + exec(success, null, 'CDVIonicKeyboard', 'init', []); + + function success(msg) { + var action = msg.charAt(0); + if (action === 'S') { + var keyboardHeight = parseInt(msg.substr(1)); + Keyboard.fireOnShowing(keyboardHeight); + Keyboard.fireOnShow(keyboardHeight); + + } else if (action === 'H') { + Keyboard.fireOnHiding(); + Keyboard.fireOnHide(); + } + } +}); + + +Keyboard.isVisible = false; + +module.exports = Keyboard; diff --git a/StoneIsland/plugins/cordova-plugin-ionic-keyboard/www/ios/keyboard.js b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/www/ios/keyboard.js new file mode 100644 index 00000000..e9c8cb1e --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-ionic-keyboard/www/ios/keyboard.js @@ -0,0 +1,103 @@ +/* + * + * 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 argscheck = require('cordova/argscheck'), + utils = require('cordova/utils'), + exec = require('cordova/exec'); + +var Keyboard = function () {}; + +Keyboard.fireOnShow = function (height) { + Keyboard.isVisible = true; + cordova.fireWindowEvent('keyboardDidShow', { + 'keyboardHeight': height + }); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardshow', { + 'keyboardHeight': height + }); +}; + +Keyboard.fireOnHide = function () { + Keyboard.isVisible = false; + cordova.fireWindowEvent('keyboardDidHide'); + + // To support the keyboardAttach directive listening events + // inside Ionic's main bundle + cordova.fireWindowEvent('native.keyboardhide'); +}; + +Keyboard.fireOnHiding = function () { + cordova.fireWindowEvent('keyboardWillHide'); +}; + +Keyboard.fireOnShowing = function (height) { + cordova.fireWindowEvent('keyboardWillShow', { + 'keyboardHeight': height + }); +}; + +Keyboard.fireOnResize = function (height, screenHeight, ele) { + if (!ele) { + return; + } + if (height === 0) { + ele.style.height = null; + } else { + ele.style.height = (screenHeight - height) + 'px'; + } +}; + +Keyboard.hideFormAccessoryBar = function (hide, success) { + if (hide !== null && hide !== undefined) { + exec(success, null, "CDVIonicKeyboard", "hideFormAccessoryBar", [hide]); + } else { + exec(success, null, "CDVIonicKeyboard", "hideFormAccessoryBar", []); + } +}; + +Keyboard.hide = function () { + exec(null, null, "CDVIonicKeyboard", "hide", []); +}; + +Keyboard.show = function () { + console.warn('Showing keyboard not supported in iOS due to platform limitations.'); + console.warn('Instead, use input.focus(), and ensure that you have the following setting in your config.xml: \n'); + console.warn(' <preference name="KeyboardDisplayRequiresUserAction" value="false"/>\n'); +}; + +Keyboard.disableScroll = function (disable) { + exec(null, null, "CDVIonicKeyboard", "disableScroll", [disable]); +}; + +Keyboard.setResizeMode = function (mode) { + exec(null, null, "CDVIonicKeyboard", "setResizeMode", [mode]); +} + +Keyboard.setKeyboardStyle = function(style) { + exec(null, null, "CDVIonicKeyboard", "keyboardStyle", [style]); +}; + +Keyboard.isVisible = false; + +module.exports = Keyboard;
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-sim/.editorconfig b/StoneIsland/plugins/cordova-plugin-sim/.editorconfig new file mode 100644 index 00000000..4a7ea303 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-sim/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/StoneIsland/plugins/cordova-plugin-sim/.gitattributes b/StoneIsland/plugins/cordova-plugin-sim/.gitattributes new file mode 100644 index 00000000..bdb0cabc --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-sim/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/StoneIsland/plugins/cordova-plugin-sim/.github/ISSUE_TEMPLATE.md b/StoneIsland/plugins/cordova-plugin-sim/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..f05a8183 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-sim/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,43 @@ +### Expected behaviour +Tell us what should happen. + +### Actual behaviour +Tell us what happens instead. Provide a log message if relevant + +### I'm seeing this behaviour on +_Remove this hint: these checkboxes can be checked like this: [x]_ + +- [ ] iOS device +- [ ] iOS simulator +- [ ] Android device +- [ ] Android emulator + +### I am using + +- [ ] cordova +- [ ] ionic +- [ ] PhoneGap +- [ ] PhoneGap Developer App +- [ ] Intel XDK +- [ ] Intel App Preview +- [ ] Telerik +- [ ] Other: + +#### Hardware models +Example: Samsung Galaxy S6, iPhone 6s + +#### OS versions +Example: Android 4.4.2, iOS 9.2 + +### I've checked these +- [ ] It happens on a fresh Cordova CLI project as well. +- [ ] I'm waiting for `deviceready` to fire. +- [ ] My JavaScript has no errors (`window.onerror` catches nothing). +- [ ] I'm using the latest cordova library, Android SDK, Xcode, etc. + +### So how can we reproduce this? +Provide the used components versions (cordova, ionic, etc). + +Provide the steps to reproduce the issue. + +Provide files, sources if available. diff --git a/StoneIsland/plugins/cordova-plugin-sim/.npmignore b/StoneIsland/plugins/cordova-plugin-sim/.npmignore new file mode 100644 index 00000000..957b79cd --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-sim/.npmignore @@ -0,0 +1,4 @@ +node_modules/ +.DS_Store +npm-debug.log +notes diff --git a/StoneIsland/plugins/fetch.json b/StoneIsland/plugins/fetch.json index 7d39dc7f..8f4521fd 100755 --- a/StoneIsland/plugins/fetch.json +++ b/StoneIsland/plugins/fetch.json @@ -57,14 +57,6 @@ "is_top_level": true, "variables": {} }, - "cordova-plugin-geolocation": { - "source": { - "type": "registry", - "id": "cordova-plugin-geolocation" - }, - "is_top_level": true, - "variables": {} - }, "cordova-plugin-compat": { "source": { "type": "registry", @@ -73,14 +65,6 @@ "is_top_level": false, "variables": {} }, - "ionic-plugin-keyboard": { - "source": { - "type": "registry", - "id": "ionic-plugin-keyboard" - }, - "is_top_level": true, - "variables": {} - }, "cordova-plugin-statusbar": { "source": { "type": "registry", @@ -107,10 +91,42 @@ "is_top_level": true, "variables": {} }, - "phonegap-plugin-push": { + "phonegap-plugin-mobile-accessibility": { "source": { "type": "registry", - "id": "phonegap-plugin-push@1.9.2" + "id": "https://github.com/phonegap/phonegap-mobile-accessibility.git" + }, + "is_top_level": true, + "variables": {} + }, + "cordova-plugin-firebasex": { + "source": { + "type": "registry", + "id": "cordova-plugin-firebasex@^10.2.0-cli" + }, + "is_top_level": true, + "variables": {} + }, + "cordova-plugin-androidx": { + "source": { + "type": "registry", + "id": "cordova-plugin-androidx@^2.0.0" + }, + "is_top_level": false, + "variables": {} + }, + "cordova-plugin-androidx-adapter": { + "source": { + "type": "registry", + "id": "cordova-plugin-androidx-adapter@^1.1.1" + }, + "is_top_level": false, + "variables": {} + }, + "cordova-plugin-ionic-keyboard": { + "source": { + "type": "registry", + "id": "cordova-plugin-ionic-keyboard" }, "is_top_level": true, "variables": {} @@ -123,12 +139,14 @@ "is_top_level": true, "variables": {} }, - "phonegap-plugin-mobile-accessibility": { + "cordova-plugin-geolocation": { "source": { "type": "registry", - "id": "https://github.com/phonegap/phonegap-mobile-accessibility.git" + "id": "cordova-plugin-geolocation@4.0.2" }, "is_top_level": true, - "variables": {} + "variables": { + "GEOLOCATION_USAGE_DESCRIPTION": "Stone Island needs to serve content based on your location." + } } }
\ No newline at end of file diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/LICENSE b/StoneIsland/plugins/ionic-plugin-keyboard/LICENSE deleted file mode 100644 index d6f545b8..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2014 Drifty Co. - - Licensed 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. diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/README.md b/StoneIsland/plugins/ionic-plugin-keyboard/README.md deleted file mode 100644 index 44dbda02..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/README.md +++ /dev/null @@ -1,128 +0,0 @@ -Keyboard -====== - -The `cordova.plugins.Keyboard` object provides functions to make interacting with the keyboard easier, and fires events to indicate that the keyboard will hide/show. - - cordova plugin add ionic-plugin-keyboard - -Methods -------- - -- cordova.plugins.Keyboard.hideKeyboardAccessoryBar -- cordova.plugins.Keyboard.close -- cordova.plugins.Keyboard.disableScroll -- cordova.plugins.Keyboard.show - -Properties --------- - -- cordova.plugins.Keyboard.isVisible - -Events --------- - -These events are fired on the window. - -- native.keyboardshow - * A number `keyboardHeight` is given on the event object, which is the pixel height of the keyboard. -- native.keyboardhide - - -# API reference - -Keyboard.hideKeyboardAccessoryBar -================= - -Hide the keyboard accessory bar with the next, previous and done buttons. - - cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); - cordova.plugins.Keyboard.hideKeyboardAccessoryBar(false); - -Supported Platforms -------------------- - -- iOS - - -Keyboard.close -================= - -Close the keyboard if it is open. - - cordova.plugins.Keyboard.close(); - -Supported Platforms -------------------- - -- iOS, Android, Blackberry 10, Windows - - -Keyboard.disableScroll -================= - -Prevent the native UIScrollView from moving when an input is focused. The telltale sign that this is happening is the top of your app scrolls out of view (if using Ionic, your header bar will disappear). - -This does *not* prevent any DOM elements from being able to scroll. That needs to happen from CSS and JavaScript, not this plugin. - - cordova.plugins.Keyboard.disableScroll(true); - cordova.plugins.Keyboard.disableScroll(false); - -Supported Platforms -------------------- - -- iOS, Windows - -Keyboard.show -================= - -Force keyboard to be shown. This typically helps if autofocus on a text element does not pop up the keyboard automatically - - cordova.plugins.Keyboard.show(); - -Supported Platforms - -- Android, Blackberry 10, Windows - -native.keyboardshow -================= - -This event fires when the keyboard will be shown or when the keyboard frame resizes (when switching between keyboards for example) - - window.addEventListener('native.keyboardshow', keyboardShowHandler); - - function keyboardShowHandler(e){ - alert('Keyboard height is: ' + e.keyboardHeight); - } - -Properties ------------ - -keyboardHeight: the height of the keyboard in pixels - - -Supported Platforms -------------------- - -- iOS, Android, Blackberry 10, Windows - - -native.keyboardhide -================= - -This event fires when the keyboard will hide - - window.addEventListener('native.keyboardhide', keyboardHideHandler); - - function keyboardHideHandler(e){ - alert('Goodnight, sweet prince'); - } - -Properties ------------ - -None - -Supported Platforms -------------------- - -- iOS, Android, Blackberry 10, Windows diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/package.json b/StoneIsland/plugins/ionic-plugin-keyboard/package.json deleted file mode 100644 index 7bfa4542..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "ionic-plugin-keyboard", - "version": "2.2.1", - "cordova": { - "id": "ionic-plugin-keyboard", - "platforms": [ - "android", - "ios", - "blackberry10", - "wp8", - "windows" - ] - }, - "description": "Ionic Keyboard Plugin", - "repository": "https://github.com/driftyco/ionic-plugin-keyboard.git", - "issue": "https://github.com/driftyco/ionic-plugin-keyboard/issues", - "keywords": [ - "ionic", - "cordova", - "keyboard", - "ecosystem:cordova", - "cordova-android", - "cordova-ios", - "cordova-blackberry10", - "cordova-wp8", - "cordova-windows" - ], - "author": "Ionic", - "license": "Apache 2.0" -} diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/plugin.xml b/StoneIsland/plugins/ionic-plugin-keyboard/plugin.xml deleted file mode 100644 index ae85ddfd..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/plugin.xml +++ /dev/null @@ -1,71 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" - id="ionic-plugin-keyboard" - version="2.2.1"> - <name>Keyboard</name> - <description>Ionic Keyboard Plugin</description> - <license>Apache 2.0</license> - <keywords>Ionic,keyboard</keywords> - <repo>https://github.com/driftyco/ionic-plugin-keyboard.git</repo> - <issue>https://github.com/driftyco/ionic-plugin-keyboard/issues</issue> - - - <!-- android --> - <platform name="android"> - <js-module src="www/android/keyboard.js" name="keyboard"> - <runs/> - <clobbers target="cordova.plugins.Keyboard" /> - </js-module> - <config-file target="res/xml/config.xml" parent="/*"> - <feature name="Keyboard"> - <param name="android-package" value="io.ionic.keyboard.IonicKeyboard" /> - <param name="onload" value="true" /> - </feature> - </config-file> - - <source-file src="src/android/IonicKeyboard.java" target-dir="src/io/ionic/keyboard" /> - </platform> - - <!-- ios --> - <platform name="ios"> - <js-module src="www/ios/keyboard.js" name="keyboard"> - <runs/> - <clobbers target="cordova.plugins.Keyboard" /> - </js-module> - <config-file target="config.xml" parent="/*"> - <feature name="Keyboard"> - <param name="ios-package" value="IonicKeyboard" onload="true" /> - </feature> - </config-file> - <header-file src="src/ios/IonicKeyboard.h" /> - <source-file src="src/ios/IonicKeyboard.m" /> - </platform> - - <!-- browser --> - <platform name="browser"> - <js-module src="www/browser/keyboard.js" name="keyboard"> - <runs/> - <clobbers target="cordova.plugins.Keyboard" /> - </js-module> - </platform> - - <!-- blackberry10 --> - <platform name="blackberry10"> - <source-file src="src/blackberry10/index.js" target-dir='Keyboard' /> - <lib-file src="src/blackberry10/native/device/libKeyboard.so" arch="device"/> - <lib-file src="src/blackberry10/native/simulator/libKeyboard.so" arch="simulator"/> - <config-file target="www/config.xml" parent="/widget"> - <feature name="Keyboard" value="io.ionic.keyboard"/> - </config-file> - </platform> - - <!-- windows --> - <platform name="windows"> - <js-module src="src/windows/KeyboardProxy.js" name="KeyboardProxy"> - <runs /> - <clobbers target="cordova.plugins.Keyboard" /> - </js-module> - </platform> - -</plugin> diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/index.js b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/index.js deleted file mode 100644 index a91b94a2..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/index.js +++ /dev/null @@ -1,125 +0,0 @@ -var keyboard, - resultObjs = {}, - threadCallback = null, - _utils = require("../../lib/utils"); - _event = require("../../lib/event"); - _webview = require("../../lib/webview"); - -module.exports = { - - // Code can be declared and used outside the module.exports object, - // but any functions to be called by client.js need to be declared - // here in this object. - - // These methods call into JNEXT.Keyboard which handles the - // communication through the JNEXT plugin to keyboard_js.cpp - startService: function (success, fail, args, env) { - var result = new PluginResult(args, env); - - result.ok(keyboard.getInstance().startService(), false); - }, - show: function (success, fail, args, env) { - var result = new PluginResult(args, env); - - result.ok(keyboard.getInstance().showKeyboard(), false); - }, - close: function (success, fail, args, env) { - var result = new PluginResult(args, env); - - result.ok(keyboard.getInstance().closeKeyboard(), false); - } -}; - -keyboardShow = function(a){ - _webview.executeJavascript("cordova.plugins.Keyboard.isVisible = true"); - _webview.executeJavascript("cordova.fireDocumentEvent('native.keyboardshow',"+a+")"); -}; -keyboardHide = function(){ - _webview.executeJavascript("cordova.plugins.Keyboard.isVisible = false"); - _webview.executeJavascript("cordova.fireDocumentEvent('native.keyboardhide','')"); -}; -onStart = function() { - _webview.executeJavascript("cordova.exec("+null+", "+null+", 'Keyboard', 'startService', '')"); -}; - -setTimeout(onStart,2000); - -/////////////////////////////////////////////////////////////////// -// JavaScript wrapper for JNEXT plugin for connection -/////////////////////////////////////////////////////////////////// - -JNEXT.Keyboard = function () { - var self = this, - hasInstance = false; - - self.getId = function () { - return self.m_id; - }; - - self.init = function () { - if (!JNEXT.require("libKeyboard")) { - return false; - } - - self.m_id = JNEXT.createObject("libKeyboard.Keyboard_JS"); - - if (self.m_id === "") { - return false; - } - - JNEXT.registerEvents(self); - }; - - // ************************ - // Enter your methods here - // ************************ - - // calls into InvokeMethod(string command) in keyboard_js.cpp - self.startService = function () { - return JNEXT.invoke(self.m_id, "startService"); - }; - self.showKeyboard = function () { - return JNEXT.invoke(self.m_id, "showKeyboard"); - }; - self.closeKeyboard = function () { - return JNEXT.invoke(self.m_id, "closeKeyboard"); - }; - - self.onEvent = function (strData) { // Fired by the Event framework (used by asynchronous callbacks) - var arData = strData.split(" "), - strEventDesc = arData[0], - jsonData; - - if (strEventDesc === "native.keyboardshow") { - jsonData = arData.slice(1, arData.length).join(" "); - keyboardShow(jsonData); - } - else if (strEventDesc === "native.keyboardhide") { - keyboardHide(); - } - }; - - // Thread methods - self.keyboardStartThread = function (callbackId) { - return JNEXT.invoke(self.m_id, "keyboardStartThread " + callbackId); - }; - self.keyboardStopThread = function () { - return JNEXT.invoke(self.m_id, "keyboardStopThread"); - }; - - // ************************ - // End of methods to edit - // ************************ - self.m_id = ""; - - self.getInstance = function () { - if (!hasInstance) { - hasInstance = true; - self.init(); - } - return self; - }; - -}; - -keyboard = new JNEXT.Keyboard(); diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/.cproject b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/.cproject deleted file mode 100644 index 7b118eec..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/.cproject +++ /dev/null @@ -1,222 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> - <storageModule moduleId="org.eclipse.cdt.core.settings"> - <cconfiguration id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567" moduleId="org.eclipse.cdt.core.settings" name="device"> - <externalSettings> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/Cordova-Keyboard"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/Cordova-Keyboard/device"/> - <entry flags="RESOLVED" kind="libraryFile" name="Cordova-Keyboard" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <extensions> - <extension id="com.qnx.tools.ide.qde.core.QDELinkerErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" description="" id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567" name="device" parent="com.qnx.qcc.configuration.sharedLib.release"> - <folderInfo id="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567." name="/" resourcePath=""> - <toolChain id="com.qnx.qcc.toolChain.2215983" name="QNX QCC" superClass="com.qnx.qcc.toolChain"> - <option id="com.qnx.qcc.option.cpu.315540759" name="Target CPU:" superClass="com.qnx.qcc.option.cpu" value="com.qnx.qcc.option.gen.cpu.armle-v7" valueType="enumerated"/> - <targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.1359109141" osList="all" superClass="com.qnx.qcc.targetPlatform"/> - <builder buildPath="${workspace_loc:/Keyboard/Device-Release}" id="com.qnx.nto.938326560" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="com.qnx.nto"/> - <tool id="com.qnx.qcc.tool.compiler.242697771" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler"> - <option id="com.qnx.qcc.option.compiler.shared.553244928" name="Shared (-shared)" superClass="com.qnx.qcc.option.compiler.shared" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.compiler.optlevel.2070537906" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.2" valueType="enumerated"/> - <option id="com.qnx.qcc.option.compiler.includePath.1483355415" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath"> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/bb"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4/QtCore"/> - <listOptionValue builtIn="false" value="${workspace_loc:/${ProjName}/public}"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/> - </option> - <option id="com.qnx.qcc.option.compiler.security.9625963" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.compiler.defines.872099896" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/> - </option> - <option id="com.qnx.qcc.option.compiler.qccoptions.1015003128" name="QCC Options" superClass="com.qnx.qcc.option.compiler.qccoptions" valueType="stringList"> - <listOptionValue builtIn="false" value="-frecord-gcc-switches"/> - </option> - <inputType id="com.qnx.qcc.inputType.compiler.1443568066" superClass="com.qnx.qcc.inputType.compiler"/> - </tool> - <tool id="com.qnx.qcc.tool.assembler.1996828008" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler"> - <inputType id="com.qnx.qcc.inputType.assembler.116798417" superClass="com.qnx.qcc.inputType.assembler"/> - </tool> - <tool id="com.qnx.qcc.tool.linker.871546588" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"> - <option id="com.qnx.qcc.option.linker.shared.915102752" name="Shared (-shared)" superClass="com.qnx.qcc.option.linker.shared" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.linker.libraryPaths.1049529253" name="Library Paths (-L)" superClass="com.qnx.qcc.option.linker.libraryPaths" valueType="libPaths"> - <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/lib"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib/qt4/lib"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/usr/lib"/> - </option> - <option id="com.qnx.qcc.option.linker.security.1157664997" name="Enhanced Security (-Wl,-z,relro -Wl,-z,now)" superClass="com.qnx.qcc.option.linker.security" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.linker.libraries.1316432206" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs"> - <listOptionValue builtIn="false" value="slog2"/> - <listOptionValue builtIn="false" value="QtCore"/> - <listOptionValue builtIn="false" value="bb"/> - <listOptionValue builtIn="false" value="bps"/> - </option> - <inputType id="com.qnx.qcc.inputType.linker.1028572887" superClass="com.qnx.qcc.inputType.linker"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool id="com.qnx.qcc.tool.archiver.1781914947" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/> - </toolChain> - </folderInfo> - <sourceEntries> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="public"/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> - </cconfiguration> - <cconfiguration id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091"> - <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091" moduleId="org.eclipse.cdt.core.settings" name="simulator"> - <externalSettings> - <externalSetting> - <entry flags="VALUE_WORKSPACE_PATH" kind="includePath" name="/Cordova-Keyboard"/> - <entry flags="VALUE_WORKSPACE_PATH" kind="libraryPath" name="/Cordova-Keyboard/simulator"/> - <entry flags="RESOLVED" kind="libraryFile" name="Cordova-Keyboard" srcPrefixMapping="" srcRootPath=""/> - </externalSetting> - </externalSettings> - <extensions> - <extension id="com.qnx.tools.ide.qde.core.QDELinkerErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> - <extension id="com.qnx.tools.ide.qde.core.QDEBynaryParser" point="org.eclipse.cdt.core.BinaryParser"/> - </extensions> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactExtension="so" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.sharedLib" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.sharedLib" description="" id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091" name="simulator" parent="com.qnx.qcc.configuration.sharedLib.debug"> - <folderInfo id="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091." name="/" resourcePath=""> - <toolChain id="com.qnx.qcc.toolChain.688026907" name="QNX QCC" superClass="com.qnx.qcc.toolChain"> - <targetPlatform archList="all" binaryParser="com.qnx.tools.ide.qde.core.QDEBynaryParser" id="com.qnx.qcc.targetPlatform.469207190" osList="all" superClass="com.qnx.qcc.targetPlatform"/> - <builder buildPath="${workspace_loc:/Keyboard/Simulator-Debug}" id="com.qnx.nto.2029800497" keepEnvironmentInBuildfile="false" name="CDT Internal Builder" superClass="com.qnx.nto"/> - <tool id="com.qnx.qcc.tool.compiler.1028279123" name="QCC Compiler" superClass="com.qnx.qcc.tool.compiler"> - <option id="com.qnx.qcc.option.compiler.shared.235893159" name="Shared (-shared)" superClass="com.qnx.qcc.option.compiler.shared" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.compiler.optlevel.1164238904" name="Optimization Level" superClass="com.qnx.qcc.option.compiler.optlevel" value="com.qnx.qcc.option.compiler.optlevel.0" valueType="enumerated"/> - <option id="com.qnx.qcc.option.compile.debug.3716470" name="Debug (-g)" superClass="com.qnx.qcc.option.compile.debug" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.compiler.includePath.306305432" name="Include Directories (-I)" superClass="com.qnx.qcc.option.compiler.includePath" valueType="includePath"> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/bb"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4/QtCore"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/qt4"/> - <listOptionValue builtIn="false" value="${workspace_loc:/${ProjName}/public}"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/usr/include/freetype2"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/usr/include"/> - </option> - <option id="com.qnx.qcc.option.compiler.security.1730007887" name="Enhanced Security (-fstack-protector-strong)" superClass="com.qnx.qcc.option.compiler.security" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.compiler.defines.1526896965" name="Defines (-D)" superClass="com.qnx.qcc.option.compiler.defines" valueType="definedSymbols"> - <listOptionValue builtIn="false" value="_FORTIFY_SOURCE=2"/> - </option> - <inputType id="com.qnx.qcc.inputType.compiler.1881183122" superClass="com.qnx.qcc.inputType.compiler"/> - </tool> - <tool id="com.qnx.qcc.tool.assembler.312168125" name="QCC Assembler" superClass="com.qnx.qcc.tool.assembler"> - <option id="com.qnx.qcc.option.assembler.debug.416544277" name="Debug (-g)" superClass="com.qnx.qcc.option.assembler.debug" value="true" valueType="boolean"/> - <inputType id="com.qnx.qcc.inputType.assembler.1722778407" superClass="com.qnx.qcc.inputType.assembler"/> - </tool> - <tool id="com.qnx.qcc.tool.linker.2130364088" name="QCC Linker" superClass="com.qnx.qcc.tool.linker"> - <option id="com.qnx.qcc.option.linker.debug.1332880614" name="Debug (-g)" superClass="com.qnx.qcc.option.linker.debug" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.linker.shared.1633267255" name="Shared (-shared)" superClass="com.qnx.qcc.option.linker.shared" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.linker.libraryPaths.565794953" name="Library Paths (-L)" superClass="com.qnx.qcc.option.linker.libraryPaths" valueType="libPaths"> - <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/lib"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/${CPUVARDIR}/usr/lib/qt4/lib"/> - <listOptionValue builtIn="false" value="${QNX_TARGET}/../target-override/${CPUVARDIR}/usr/lib"/> - </option> - <option id="com.qnx.qcc.option.linker.security.9141791" name="Enhanced Security (-Wl,-z,relro -Wl,-z,now)" superClass="com.qnx.qcc.option.linker.security" value="true" valueType="boolean"/> - <option id="com.qnx.qcc.option.linker.libraries.220836649" name="Libraries (-l)" superClass="com.qnx.qcc.option.linker.libraries" valueType="libs"> - <listOptionValue builtIn="false" value="slog2"/> - <listOptionValue builtIn="false" value="QtCore"/> - <listOptionValue builtIn="false" value="bb"/> - <listOptionValue builtIn="false" value="bps"/> - </option> - <inputType id="com.qnx.qcc.inputType.linker.167117375" superClass="com.qnx.qcc.inputType.linker"> - <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/> - <additionalInput kind="additionalinput" paths="$(LIBS)"/> - </inputType> - </tool> - <tool id="com.qnx.qcc.tool.archiver.489682882" name="QCC Archiver" superClass="com.qnx.qcc.tool.archiver"/> - </toolChain> - </folderInfo> - <sourceEntries> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="public"/> - </sourceEntries> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> - </cconfiguration> - </storageModule> - <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <project id="Keyboard.null.138005006" name="Keyboard"/> - </storageModule> - <storageModule moduleId="refreshScope" versionNumber="2"> - <configuration configurationName="Simulator-Profile"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="simulator"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="Simulator-Coverage"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="Device-Profile"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="Device-Debug"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="Simulator-Debug"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="device"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="Device-Release"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - <configuration configurationName="Device-Coverage"> - <resource resourceType="PROJECT" workspacePath="/Keyboard"/> - </configuration> - </storageModule> - <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/> - <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> - <storageModule moduleId="scannerConfiguration"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.941124085"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.1806890017"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.release.608922875"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.profile.27502649"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.193597202"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.coverage.537092296"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.193597202.362186091"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.release.608922875.1009704567"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - <scannerConfigBuildInfo instanceId="com.qnx.qcc.configuration.sharedLib.debug.1877214659"> - <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.qnx.tools.ide.qde.managedbuilder.core.qccScannerInfo"/> - </scannerConfigBuildInfo> - </storageModule> -</cproject> diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/.project b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/.project deleted file mode 100644 index 8a39f221..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/.project +++ /dev/null @@ -1,76 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>Keyboard</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - <buildCommand> - <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> - <triggers>clean,full,incremental,</triggers> - <arguments> - <dictionary> - <key>?name?</key> - <value></value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.append_environment</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.buildArguments</key> - <value></value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.buildCommand</key> - <value>make</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.buildLocation</key> - <value>${workspace_loc:/Keyboard/Device-Release}</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.contents</key> - <value>org.eclipse.cdt.make.core.activeConfigSettings</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.enableAutoBuild</key> - <value>false</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.enableCleanBuild</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.enableFullBuild</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.stopOnError</key> - <value>true</value> - </dictionary> - <dictionary> - <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key> - <value>true</value> - </dictionary> - </arguments> - </buildCommand> - <buildCommand> - <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> - <triggers>full,incremental,</triggers> - <arguments> - </arguments> - </buildCommand> - <buildCommand> - <name>com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder</name> - <arguments> - </arguments> - </buildCommand> - </buildSpec> - <natures> - <nature>org.eclipse.cdt.core.cnature</nature> - <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> - <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> - <nature>com.qnx.tools.ide.bbt.core.bbtnature</nature> - </natures> -</projectDescription> diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/autolink.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/autolink.h deleted file mode 100644 index 37c9258e..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/autolink.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef JSON_AUTOLINK_H_INCLUDED -# define JSON_AUTOLINK_H_INCLUDED - -# include "config.h" - -# ifdef JSON_IN_CPPTL -# include <cpptl/cpptl_autolink.h> -# endif - -# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL) -# define CPPTL_AUTOLINK_NAME "json" -# undef CPPTL_AUTOLINK_DLL -# ifdef JSON_DLL -# define CPPTL_AUTOLINK_DLL -# endif -# include "autolink.h" -# endif - -#endif // JSON_AUTOLINK_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/config.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/config.h deleted file mode 100644 index 5d334cbc..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef JSON_CONFIG_H_INCLUDED -# define JSON_CONFIG_H_INCLUDED - -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 -/// If defined, indicates that Json specific container should be used -/// (hash table & simple deque container with customizable allocator). -/// THIS FEATURE IS STILL EXPERIMENTAL! -//# define JSON_VALUE_USE_INTERNAL_MAP 1 -/// Force usage of standard new/malloc based allocator instead of memory pool based allocator. -/// The memory pools allocator used optimization (initializing Value and ValueInternalLink -/// as if it was a POD) that may cause some validation tool to report errors. -/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. -//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 - -/// If defined, indicates that Json use exception to report invalid type manipulation -/// instead of C assert macro. -# define JSON_USE_EXCEPTION 1 - -# ifdef JSON_IN_CPPTL -# include <cpptl/config.h> -# ifndef JSON_USE_CPPTL -# define JSON_USE_CPPTL 1 -# endif -# endif - -# ifdef JSON_IN_CPPTL -# define JSON_API CPPTL_API -# elif defined(JSON_DLL_BUILD) -# define JSON_API __declspec(dllexport) -# elif defined(JSON_DLL) -# define JSON_API __declspec(dllimport) -# else -# define JSON_API -# endif - -#endif // JSON_CONFIG_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/features.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/features.h deleted file mode 100644 index 5a9adec1..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/features.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -# define CPPTL_JSON_FEATURES_H_INCLUDED - -# include "forwards.h" - -namespace Json { - - /** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ - class JSON_API Features - { - public: - /** \brief A configuration that allows all features and assumes all strings are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_; - - /// \c true if root must be either an array or an object value. Default: \c false. - bool strictRoot_; - }; - -} // namespace Json - -#endif // CPPTL_JSON_FEATURES_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/forwards.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/forwards.h deleted file mode 100644 index d0ce8300..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/forwards.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef JSON_FORWARDS_H_INCLUDED -# define JSON_FORWARDS_H_INCLUDED - -# include "config.h" - -namespace Json { - - // writer.h - class FastWriter; - class StyledWriter; - - // reader.h - class Reader; - - // features.h - class Features; - - // value.h - typedef int Int; - typedef unsigned int UInt; - class StaticString; - class Path; - class PathArgument; - class Value; - class ValueIteratorBase; - class ValueIterator; - class ValueConstIterator; -#ifdef JSON_VALUE_USE_INTERNAL_MAP - class ValueAllocator; - class ValueMapAllocator; - class ValueInternalLink; - class ValueInternalArray; - class ValueInternalMap; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - -} // namespace Json - - -#endif // JSON_FORWARDS_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/json.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/json.h deleted file mode 100644 index c71ed65a..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/json.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef JSON_JSON_H_INCLUDED -# define JSON_JSON_H_INCLUDED - -# include "autolink.h" -# include "value.h" -# include "reader.h" -# include "writer.h" -# include "features.h" - -#endif // JSON_JSON_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/reader.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/reader.h deleted file mode 100644 index ee1d6a24..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/reader.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef CPPTL_JSON_READER_H_INCLUDED -# define CPPTL_JSON_READER_H_INCLUDED - -# include "features.h" -# include "value.h" -# include <deque> -# include <stack> -# include <string> -# include <iostream> - -namespace Json { - - /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value. - * - */ - class JSON_API Reader - { - public: - typedef char Char; - typedef const Char *Location; - - /** \brief Constructs a Reader allowing all features - * for parsing. - */ - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. - */ - Reader( const Features &features ); - - /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them back during - * serialization, \c false to discard comments. - * This parameter is ignored if Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an error occurred. - */ - bool parse( const std::string &document, - Value &root, - bool collectComments = true ); - - /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them back during - * serialization, \c false to discard comments. - * This parameter is ignored if Features::allowComments_ - * is \c false. - * \return \c true if the document was successfully parsed, \c false if an error occurred. - */ - bool parse( const char *beginDoc, const char *endDoc, - Value &root, - bool collectComments = true ); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse( std::istream &is, - Value &root, - bool collectComments = true ); - - /** \brief Returns a user friendly string that list errors in the parsed document. - * \return Formatted error message with the list of errors with their location in - * the parsed document. An empty string is returned if no error occurred - * during parsing. - */ - std::string getFormatedErrorMessages() const; - - private: - enum TokenType - { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token - { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo - { - public: - Token token_; - std::string message_; - Location extra_; - }; - - typedef std::deque<ErrorInfo> Errors; - - bool expectToken( TokenType type, Token &token, const char *message ); - bool readToken( Token &token ); - void skipSpaces(); - bool match( Location pattern, - int patternLength ); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject( Token &token ); - bool readArray( Token &token ); - bool decodeNumber( Token &token ); - bool decodeString( Token &token ); - bool decodeString( Token &token, std::string &decoded ); - bool decodeDouble( Token &token ); - bool decodeUnicodeCodePoint( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ); - bool decodeUnicodeEscapeSequence( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ); - bool addError( const std::string &message, - Token &token, - Location extra = 0 ); - bool recoverFromError( TokenType skipUntilToken ); - bool addErrorAndRecover( const std::string &message, - Token &token, - TokenType skipUntilToken ); - void skipUntilSpace(); - Value ¤tValue(); - Char getNextChar(); - void getLocationLineAndColumn( Location location, - int &line, - int &column ) const; - std::string getLocationLineAndColumn( Location location ) const; - void addComment( Location begin, - Location end, - CommentPlacement placement ); - void skipCommentTokens( Token &token ); - - typedef std::stack<Value *> Nodes; - Nodes nodes_; - Errors errors_; - std::string document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value *lastValue_; - std::string commentsBefore_; - Features features_; - bool collectComments_; - }; - - /** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() - */ - std::istream& operator>>( std::istream&, Value& ); - -} // namespace Json - -#endif // CPPTL_JSON_READER_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/value.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/value.h deleted file mode 100644 index 58bfd88e..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/value.h +++ /dev/null @@ -1,1069 +0,0 @@ -#ifndef CPPTL_JSON_H_INCLUDED -# define CPPTL_JSON_H_INCLUDED - -# include "forwards.h" -# include <string> -# include <vector> - -# ifndef JSON_USE_CPPTL_SMALLMAP -# include <map> -# else -# include <cpptl/smallmap.h> -# endif -# ifdef JSON_USE_CPPTL -# include <cpptl/forwards.h> -# endif - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - - /** \brief Type of the value held by a Value object. - */ - enum ValueType - { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). - }; - - enum CommentPlacement - { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for root value) - numberOfCommentPlacement - }; - -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; -// typedef CppTL::AnyEnumerator<const Value &> EnumValues; -//# endif - - /** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignement takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - class JSON_API StaticString - { - public: - explicit StaticString( const char *czstring ) - : str_( czstring ) - { - } - - operator const char *() const - { - return str_; - } - - const char *c_str() const - { - return str_; - } - - private: - const char *str_; - }; - - /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. - * Non const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resize and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtanis default value in the case the required element - * does not exist. - * - * It is possible to iterate over the list of a #objectValue values using - * the getMemberNames() method. - */ - class JSON_API Value - { - friend class ValueIteratorBase; -# ifdef JSON_VALUE_USE_INTERNAL_MAP - friend class ValueInternalLink; - friend class ValueInternalMap; -# endif - public: - typedef std::vector<std::string> Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; - typedef UInt ArrayIndex; - - static const Value null; - static const Int minInt; - static const Int maxInt; - static const UInt maxUInt; - - private: -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION -# ifndef JSON_VALUE_USE_INTERNAL_MAP - class CZString - { - public: - enum DuplicationPolicy - { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; - CZString( int index ); - CZString( const char *cstr, DuplicationPolicy allocate ); - CZString( const CZString &other ); - ~CZString(); - CZString &operator =( const CZString &other ); - bool operator<( const CZString &other ) const; - bool operator==( const CZString &other ) const; - int index() const; - const char *c_str() const; - bool isStaticString() const; - private: - void swap( CZString &other ); - const char *cstr_; - int index_; - }; - - public: -# ifndef JSON_USE_CPPTL_SMALLMAP - typedef std::map<CZString, Value> ObjectValues; -# else - typedef CppTL::SmallMap<CZString, Value> ObjectValues; -# endif // ifndef JSON_USE_CPPTL_SMALLMAP -# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. - This is useful since clear() and resize() will not alter types. - - Examples: - \code - Json::Value null_value; // null - Json::Value arr_value(Json::arrayValue); // [] - Json::Value obj_value(Json::objectValue); // {} - \endcode - */ - Value( ValueType type = nullValue ); - Value( Int value ); - Value( UInt value ); - Value( double value ); - Value( const char *value ); - Value( const char *beginValue, const char *endValue ); - /** \brief Constructs a value from a static string. - - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * \endcode - */ - Value( const StaticString &value ); - Value( const std::string &value ); -# ifdef JSON_USE_CPPTL - Value( const CppTL::ConstString &value ); -# endif - Value( bool value ); - Value( const Value &other ); - ~Value(); - - Value &operator=( const Value &other ); - /// Swap values. - /// \note Currently, comments are intentionally not swapped, for - /// both logic and efficiency. - void swap( Value &other ); - - ValueType type() const; - - bool operator <( const Value &other ) const; - bool operator <=( const Value &other ) const; - bool operator >=( const Value &other ) const; - bool operator >( const Value &other ) const; - - bool operator ==( const Value &other ) const; - bool operator !=( const Value &other ) const; - - int compare( const Value &other ); - - const char *asCString() const; - std::string asString() const; -# ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -# endif - Int asInt() const; - UInt asUInt() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isUInt() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - bool isConvertibleTo( ValueType other ) const; - - /// Number of values in array or object - UInt size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return isNull() - bool operator!() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to size elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize( UInt size ); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value &operator[]( UInt index ); - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value &operator[]( UInt index ) const; - /// If the array contains at least index+1 elements, returns the element value, - /// otherwise returns defaultValue. - Value get( UInt index, - const Value &defaultValue ) const; - /// Return true if index < size(). - bool isValidIndex( UInt index ) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value &append( const Value &value ); - - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const char *key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const char *key ) const; - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const std::string &key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const std::string &key ) const; - /** \brief Access an object value by name, create a null member if it does not exist. - - * If the object as no entry for that name, then the member name used to store - * the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value &operator[]( const StaticString &key ); -# ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value &operator[]( const CppTL::ConstString &key ); - /// Access an object value by name, returns null if there is no member with that name. - const Value &operator[]( const CppTL::ConstString &key ) const; -# endif - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const char *key, - const Value &defaultValue ) const; - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const std::string &key, - const Value &defaultValue ) const; -# ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - Value get( const CppTL::ConstString &key, - const Value &defaultValue ) const; -# endif - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \return the removed Value, or null. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - Value removeMember( const char* key ); - /// Same as removeMember(const char*) - Value removeMember( const std::string &key ); - - /// Return true if the object has a member named key. - bool isMember( const char *key ) const; - /// Return true if the object has a member named key. - bool isMember( const std::string &key ) const; -# ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember( const CppTL::ConstString &key ) const; -# endif - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - -//# ifdef JSON_USE_CPPTL -// EnumMemberNames enumMemberNames() const; -// EnumValues enumValues() const; -//# endif - - /// Comments must be //... or /* ... */ - void setComment( const char *comment, - CommentPlacement placement ); - /// Comments must be //... or /* ... */ - void setComment( const std::string &comment, - CommentPlacement placement ); - bool hasComment( CommentPlacement placement ) const; - /// Include delimiters and embedded newlines. - std::string getComment( CommentPlacement placement ) const; - - std::string toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - private: - Value &resolveReference( const char *key, - bool isStatic ); - -# ifdef JSON_VALUE_USE_INTERNAL_MAP - inline bool isItemAvailable() const - { - return itemIsUsed_ == 0; - } - - inline void setItemUsed( bool isUsed = true ) - { - itemIsUsed_ = isUsed ? 1 : 0; - } - - inline bool isMemberNameStatic() const - { - return memberNameIsStatic_ == 0; - } - - inline void setMemberNameIsStatic( bool isStatic ) - { - memberNameIsStatic_ = isStatic ? 1 : 0; - } -# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP - - private: - struct CommentInfo - { - CommentInfo(); - ~CommentInfo(); - - void setComment( const char *text ); - - char *comment_; - }; - - //struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder - { - Int int_; - UInt uint_; - double real_; - bool bool_; - char *string_; -# ifdef JSON_VALUE_USE_INTERNAL_MAP - ValueInternalArray *array_; - ValueInternalMap *map_; -#else - ObjectValues *map_; -# endif - } value_; - ValueType type_ : 8; - int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. -# ifdef JSON_VALUE_USE_INTERNAL_MAP - unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. - int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. -# endif - CommentInfo *comments_; - }; - - - /** \brief Experimental and untested: represents an element of the "path" to access a node. - */ - class PathArgument - { - public: - friend class Path; - - PathArgument(); - PathArgument( UInt index ); - PathArgument( const char *key ); - PathArgument( const std::string &key ); - - private: - enum Kind - { - kindNone = 0, - kindIndex, - kindKey - }; - std::string key_; - UInt index_; - Kind kind_; - }; - - /** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter - */ - class Path - { - public: - Path( const std::string &path, - const PathArgument &a1 = PathArgument(), - const PathArgument &a2 = PathArgument(), - const PathArgument &a3 = PathArgument(), - const PathArgument &a4 = PathArgument(), - const PathArgument &a5 = PathArgument() ); - - const Value &resolve( const Value &root ) const; - Value resolve( const Value &root, - const Value &defaultValue ) const; - /// Creates the "path" to access the specified node and returns a reference on the node. - Value &make( Value &root ) const; - - private: - typedef std::vector<const PathArgument *> InArgs; - typedef std::vector<PathArgument> Args; - - void makePath( const std::string &path, - const InArgs &in ); - void addPathInArg( const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind ); - void invalidPath( const std::string &path, - int location ); - - Args args_; - }; - - /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value. - * - * - makeMemberName() and releaseMemberName() are called to respectively duplicate and - * free an Json::objectValue member name. - * - duplicateStringValue() and releaseStringValue() are called similarly to - * duplicate and free a Json::stringValue value. - */ - class ValueAllocator - { - public: - enum { unknown = (unsigned)-1 }; - - virtual ~ValueAllocator(); - - virtual char *makeMemberName( const char *memberName ) = 0; - virtual void releaseMemberName( char *memberName ) = 0; - virtual char *duplicateStringValue( const char *value, - unsigned int length = unknown ) = 0; - virtual void releaseStringValue( char *value ) = 0; - }; - -#ifdef JSON_VALUE_USE_INTERNAL_MAP - /** \brief Allocator to customize Value internal map. - * Below is an example of a simple implementation (default implementation actually - * use memory pool for speed). - * \code - class DefaultValueMapAllocator : public ValueMapAllocator - { - public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - return new ValueInternalMap(); - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - return new ValueInternalMap( other ); - } - - virtual void destructMap( ValueInternalMap *map ) - { - delete map; - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - return new ValueInternalLink(); - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - delete link; - } - }; - * \endcode - */ - class JSON_API ValueMapAllocator - { - public: - virtual ~ValueMapAllocator(); - virtual ValueInternalMap *newMap() = 0; - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; - virtual void destructMap( ValueInternalMap *map ) = 0; - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; - virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; - virtual ValueInternalLink *allocateMapLink() = 0; - virtual void releaseMapLink( ValueInternalLink *link ) = 0; - }; - - /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). - * \internal previous_ & next_ allows for bidirectional traversal. - */ - class JSON_API ValueInternalLink - { - public: - enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. - enum InternalFlags { - flagAvailable = 0, - flagUsed = 1 - }; - - ValueInternalLink(); - - ~ValueInternalLink(); - - Value items_[itemPerLink]; - char *keys_[itemPerLink]; - ValueInternalLink *previous_; - ValueInternalLink *next_; - }; - - - /** \brief A linked page based hash-table implementation used internally by Value. - * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked - * list in each bucket to handle collision. There is an addional twist in that - * each node of the collision linked list is a page containing a fixed amount of - * value. This provides a better compromise between memory usage and speed. - * - * Each bucket is made up of a chained list of ValueInternalLink. The last - * link of a given bucket can be found in the 'previous_' field of the following bucket. - * The last link of the last bucket is stored in tailLink_ as it has no following bucket. - * Only the last link of a bucket may contains 'available' item. The last link always - * contains at least one element unless is it the bucket one very first link. - */ - class JSON_API ValueInternalMap - { - friend class ValueIteratorBase; - friend class Value; - public: - typedef unsigned int HashKey; - typedef unsigned int BucketIndex; - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState - { - IteratorState() - : map_(0) - , link_(0) - , itemIndex_(0) - , bucketIndex_(0) - { - } - ValueInternalMap *map_; - ValueInternalLink *link_; - BucketIndex itemIndex_; - BucketIndex bucketIndex_; - }; -# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalMap(); - ValueInternalMap( const ValueInternalMap &other ); - ValueInternalMap &operator =( const ValueInternalMap &other ); - ~ValueInternalMap(); - - void swap( ValueInternalMap &other ); - - BucketIndex size() const; - - void clear(); - - bool reserveDelta( BucketIndex growth ); - - bool reserve( BucketIndex newItemCount ); - - const Value *find( const char *key ) const; - - Value *find( const char *key ); - - Value &resolveReference( const char *key, - bool isStatic ); - - void remove( const char *key ); - - void doActualRemove( ValueInternalLink *link, - BucketIndex index, - BucketIndex bucketIndex ); - - ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); - - Value &setNewItem( const char *key, - bool isStatic, - ValueInternalLink *link, - BucketIndex index ); - - Value &unsafeAdd( const char *key, - bool isStatic, - HashKey hashedKey ); - - HashKey hash( const char *key ) const; - - int compare( const ValueInternalMap &other ) const; - - private: - void makeBeginIterator( IteratorState &it ) const; - void makeEndIterator( IteratorState &it ) const; - static bool equals( const IteratorState &x, const IteratorState &other ); - static void increment( IteratorState &iterator ); - static void incrementBucket( IteratorState &iterator ); - static void decrement( IteratorState &iterator ); - static const char *key( const IteratorState &iterator ); - static const char *key( const IteratorState &iterator, bool &isStatic ); - static Value &value( const IteratorState &iterator ); - static int distance( const IteratorState &x, const IteratorState &y ); - - private: - ValueInternalLink *buckets_; - ValueInternalLink *tailLink_; - BucketIndex bucketsSize_; - BucketIndex itemCount_; - }; - - /** \brief A simplified deque implementation used internally by Value. - * \internal - * It is based on a list of fixed "page", each page contains a fixed number of items. - * Instead of using a linked-list, a array of pointer is used for fast item look-up. - * Look-up for an element is as follow: - * - compute page index: pageIndex = itemIndex / itemsPerPage - * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] - * - * Insertion is amortized constant time (only the array containing the index of pointers - * need to be reallocated when items are appended). - */ - class JSON_API ValueInternalArray - { - friend class Value; - friend class ValueIteratorBase; - public: - enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. - typedef Value::ArrayIndex ArrayIndex; - typedef unsigned int PageIndex; - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - struct IteratorState // Must be a POD - { - IteratorState() - : array_(0) - , currentPageIndex_(0) - , currentItemIndex_(0) - { - } - ValueInternalArray *array_; - Value **currentPageIndex_; - unsigned int currentItemIndex_; - }; -# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - - ValueInternalArray(); - ValueInternalArray( const ValueInternalArray &other ); - ValueInternalArray &operator =( const ValueInternalArray &other ); - ~ValueInternalArray(); - void swap( ValueInternalArray &other ); - - void clear(); - void resize( ArrayIndex newSize ); - - Value &resolveReference( ArrayIndex index ); - - Value *find( ArrayIndex index ) const; - - ArrayIndex size() const; - - int compare( const ValueInternalArray &other ) const; - - private: - static bool equals( const IteratorState &x, const IteratorState &other ); - static void increment( IteratorState &iterator ); - static void decrement( IteratorState &iterator ); - static Value &dereference( const IteratorState &iterator ); - static Value &unsafeDereference( const IteratorState &iterator ); - static int distance( const IteratorState &x, const IteratorState &y ); - static ArrayIndex indexOf( const IteratorState &iterator ); - void makeBeginIterator( IteratorState &it ) const; - void makeEndIterator( IteratorState &it ) const; - void makeIterator( IteratorState &it, ArrayIndex index ) const; - - void makeIndexValid( ArrayIndex index ); - - Value **pages_; - ArrayIndex size_; - PageIndex pageCount_; - }; - - /** \brief Experimental: do not use. Allocator to customize Value internal array. - * Below is an example of a simple implementation (actual implementation use - * memory pool). - \code -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator - virtual ~DefaultValueArrayAllocator() - { - } - - virtual ValueInternalArray *newArray() - { - return new ValueInternalArray(); - } - - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) - { - return new ValueInternalArray( other ); - } - - virtual void destruct( ValueInternalArray *array ) - { - delete array; - } - - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) - { - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast<Value **>( newIndexes ); - } - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) - { - if ( indexes ) - free( indexes ); - } - - virtual Value *allocateArrayPage() - { - return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); - } - - virtual void releaseArrayPage( Value *value ) - { - if ( value ) - free( value ); - } -}; - \endcode - */ - class JSON_API ValueArrayAllocator - { - public: - virtual ~ValueArrayAllocator(); - virtual ValueInternalArray *newArray() = 0; - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; - virtual void destructArray( ValueInternalArray *array ) = 0; - /** \brief Reallocate array page index. - * Reallocates an array of pointer on each page. - * \param indexes [input] pointer on the current index. May be \c NULL. - * [output] pointer on the new index of at least - * \a minNewIndexCount pages. - * \param indexCount [input] current number of pages in the index. - * [output] number of page the reallocated index can handle. - * \b MUST be >= \a minNewIndexCount. - * \param minNewIndexCount Minimum number of page the new index must be able to - * handle. - */ - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) = 0; - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) = 0; - virtual Value *allocateArrayPage() = 0; - virtual void releaseArrayPage( Value *value ) = 0; - }; -#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP - - - /** \brief base class for Value iterators. - * - */ - class ValueIteratorBase - { - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; - - ValueIteratorBase(); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); -#else - ValueIteratorBase( const ValueInternalArray::IteratorState &state ); - ValueIteratorBase( const ValueInternalMap::IteratorState &state ); -#endif - - bool operator ==( const SelfType &other ) const - { - return isEqual( other ); - } - - bool operator !=( const SelfType &other ) const - { - return !isEqual( other ); - } - - difference_type operator -( const SelfType &other ) const - { - return computeDistance( other ); - } - - /// Return either the index or the member name of the referenced value as a Value. - Value key() const; - - /// Return the index of the referenced Value. -1 if it is not an arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value. "" if it is not an objectValue. - const char *memberName() const; - - protected: - Value &deref() const; - - void increment(); - - void decrement(); - - difference_type computeDistance( const SelfType &other ) const; - - bool isEqual( const SelfType &other ) const; - - void copy( const SelfType &other ); - - private: -#ifndef JSON_VALUE_USE_INTERNAL_MAP - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_; -#else - union - { - ValueInternalArray::IteratorState array_; - ValueInternalMap::IteratorState map_; - } iterator_; - bool isArray_; -#endif - }; - - /** \brief const iterator for object and array value. - * - */ - class ValueConstIterator : public ValueIteratorBase - { - friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef const Value &reference; - typedef const Value *pointer; - typedef ValueConstIterator SelfType; - - ValueConstIterator(); - private: - /*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); -#else - ValueConstIterator( const ValueInternalArray::IteratorState &state ); - ValueConstIterator( const ValueInternalMap::IteratorState &state ); -#endif - public: - SelfType &operator =( const ValueIteratorBase &other ); - - SelfType operator++( int ) - { - SelfType temp( *this ); - ++*this; - return temp; - } - - SelfType operator--( int ) - { - SelfType temp( *this ); - --*this; - return temp; - } - - SelfType &operator--() - { - decrement(); - return *this; - } - - SelfType &operator++() - { - increment(); - return *this; - } - - reference operator *() const - { - return deref(); - } - }; - - - /** \brief Iterator for object and array value. - */ - class ValueIterator : public ValueIteratorBase - { - friend class Value; - public: - typedef unsigned int size_t; - typedef int difference_type; - typedef Value &reference; - typedef Value *pointer; - typedef ValueIterator SelfType; - - ValueIterator(); - ValueIterator( const ValueConstIterator &other ); - ValueIterator( const ValueIterator &other ); - private: - /*! \internal Use by Value to create an iterator. - */ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); -#else - ValueIterator( const ValueInternalArray::IteratorState &state ); - ValueIterator( const ValueInternalMap::IteratorState &state ); -#endif - public: - - SelfType &operator =( const SelfType &other ); - - SelfType operator++( int ) - { - SelfType temp( *this ); - ++*this; - return temp; - } - - SelfType operator--( int ) - { - SelfType temp( *this ); - --*this; - return temp; - } - - SelfType &operator--() - { - decrement(); - return *this; - } - - SelfType &operator++() - { - increment(); - return *this; - } - - reference operator *() const - { - return deref(); - } - }; - - -} // namespace Json - - -#endif // CPPTL_JSON_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/writer.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/writer.h deleted file mode 100644 index 5f4b83be..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json/writer.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef JSON_WRITER_H_INCLUDED -# define JSON_WRITER_H_INCLUDED - -# include "value.h" -# include <vector> -# include <string> -# include <iostream> - -namespace Json { - - class Value; - - /** \brief Abstract class for writers. - */ - class JSON_API Writer - { - public: - virtual ~Writer(); - - virtual std::string write( const Value &root ) = 0; - }; - - /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. - * \sa Reader, Value - */ - class JSON_API FastWriter : public Writer - { - public: - FastWriter(); - virtual ~FastWriter(){} - - void enableYAMLCompatibility(); - - public: // overridden from Writer - virtual std::string write( const Value &root ); - - private: - void writeValue( const Value &value ); - - std::string document_; - bool yamlCompatiblityEnabled_; - }; - - /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value types, - * and all the values fit on one lines, then print the array on a single line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - */ - class JSON_API StyledWriter: public Writer - { - public: - StyledWriter(); - virtual ~StyledWriter(){} - - public: // overridden from Writer - /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - virtual std::string write( const Value &root ); - - private: - void writeValue( const Value &value ); - void writeArrayValue( const Value &value ); - bool isMultineArray( const Value &value ); - void pushValue( const std::string &value ); - void writeIndent(); - void writeWithIndent( const std::string &value ); - void indent(); - void unindent(); - void writeCommentBeforeValue( const Value &root ); - void writeCommentAfterValueOnSameLine( const Value &root ); - bool hasCommentForValue( const Value &value ); - static std::string normalizeEOL( const std::string &text ); - - typedef std::vector<std::string> ChildValues; - - ChildValues childValues_; - std::string document_; - std::string indentString_; - int rightMargin_; - int indentSize_; - bool addChildValues_; - }; - - /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value types, - * and all the values fit on one lines, then print the array on a single line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputed according to their #CommentPlacement. - * - * \param indentation Each level will be indented by this amount extra. - * \sa Reader, Value, Value::setComment() - */ - class JSON_API StyledStreamWriter - { - public: - StyledStreamWriter( std::string indentation="\t" ); - ~StyledStreamWriter(){} - - public: - /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not return a value. - */ - void write( std::ostream &out, const Value &root ); - - private: - void writeValue( const Value &value ); - void writeArrayValue( const Value &value ); - bool isMultineArray( const Value &value ); - void pushValue( const std::string &value ); - void writeIndent(); - void writeWithIndent( const std::string &value ); - void indent(); - void unindent(); - void writeCommentBeforeValue( const Value &root ); - void writeCommentAfterValueOnSameLine( const Value &root ); - bool hasCommentForValue( const Value &value ); - static std::string normalizeEOL( const std::string &text ); - - typedef std::vector<std::string> ChildValues; - - ChildValues childValues_; - std::ostream* document_; - std::string indentString_; - int rightMargin_; - std::string indentation_; - bool addChildValues_; - }; - - std::string JSON_API valueToString( Int value ); - std::string JSON_API valueToString( UInt value ); - std::string JSON_API valueToString( double value ); - std::string JSON_API valueToString( bool value ); - std::string JSON_API valueToQuotedString( const char *value ); - - /// \brief Output using the StyledStreamWriter. - /// \see Json::operator>>() - std::ostream& operator<<( std::ostream&, const Value &root ); - -} // namespace Json - - - -#endif // JSON_WRITER_H_INCLUDED diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_batchallocator.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_batchallocator.h deleted file mode 100644 index 87ea5ed8..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_batchallocator.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED -# define JSONCPP_BATCHALLOCATOR_H_INCLUDED - -# include <stdlib.h> -# include <assert.h> - -# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -namespace Json { - -/* Fast memory allocator. - * - * This memory allocator allocates memory for a batch of object (specified by - * the page size, the number of object in each page). - * - * It does not allow the destruction of a single object. All the allocated objects - * can be destroyed at once. The memory can be either released or reused for future - * allocation. - * - * The in-place new operator must be used to construct the object using the pointer - * returned by allocate. - */ -template<typename AllocatedType - ,const unsigned int objectPerAllocation> -class BatchAllocator -{ -public: - typedef AllocatedType Type; - - BatchAllocator( unsigned int objectsPerPage = 255 ) - : freeHead_( 0 ) - , objectsPerPage_( objectsPerPage ) - { -// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); - assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. - assert( objectsPerPage >= 16 ); - batches_ = allocateBatch( 0 ); // allocated a dummy page - currentBatch_ = batches_; - } - - ~BatchAllocator() - { - for ( BatchInfo *batch = batches_; batch; ) - { - BatchInfo *nextBatch = batch->next_; - free( batch ); - batch = nextBatch; - } - } - - /// allocate space for an array of objectPerAllocation object. - /// @warning it is the responsability of the caller to call objects constructors. - AllocatedType *allocate() - { - if ( freeHead_ ) // returns node from free list. - { - AllocatedType *object = freeHead_; - freeHead_ = *(AllocatedType **)object; - return object; - } - if ( currentBatch_->used_ == currentBatch_->end_ ) - { - currentBatch_ = currentBatch_->next_; - while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) - currentBatch_ = currentBatch_->next_; - - if ( !currentBatch_ ) // no free batch found, allocate a new one - { - currentBatch_ = allocateBatch( objectsPerPage_ ); - currentBatch_->next_ = batches_; // insert at the head of the list - batches_ = currentBatch_; - } - } - AllocatedType *allocated = currentBatch_->used_; - currentBatch_->used_ += objectPerAllocation; - return allocated; - } - - /// Release the object. - /// @warning it is the responsability of the caller to actually destruct the object. - void release( AllocatedType *object ) - { - assert( object != 0 ); - *(AllocatedType **)object = freeHead_; - freeHead_ = object; - } - -private: - struct BatchInfo - { - BatchInfo *next_; - AllocatedType *used_; - AllocatedType *end_; - AllocatedType buffer_[objectPerAllocation]; - }; - - // disabled copy constructor and assignement operator. - BatchAllocator( const BatchAllocator & ); - void operator =( const BatchAllocator &); - - static BatchInfo *allocateBatch( unsigned int objectsPerPage ) - { - const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation - + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; - BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) ); - batch->next_ = 0; - batch->used_ = batch->buffer_; - batch->end_ = batch->buffer_ + objectsPerPage; - return batch; - } - - BatchInfo *batches_; - BatchInfo *currentBatch_; - /// Head of a single linked list within the allocated space of freeed object - AllocatedType *freeHead_; - unsigned int objectsPerPage_; -}; - - -} // namespace Json - -# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION - -#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED - diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_internalarray.inl b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_internalarray.inl deleted file mode 100644 index 9b985d25..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_internalarray.inl +++ /dev/null @@ -1,448 +0,0 @@ -// included by json_value.cpp -// everything is within Json namespace - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueInternalArray -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueArrayAllocator::~ValueArrayAllocator() -{ -} - -// ////////////////////////////////////////////////////////////////// -// class DefaultValueArrayAllocator -// ////////////////////////////////////////////////////////////////// -#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator - virtual ~DefaultValueArrayAllocator() - { - } - - virtual ValueInternalArray *newArray() - { - return new ValueInternalArray(); - } - - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) - { - return new ValueInternalArray( other ); - } - - virtual void destructArray( ValueInternalArray *array ) - { - delete array; - } - - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) - { - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast<Value **>( newIndexes ); - } - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) - { - if ( indexes ) - free( indexes ); - } - - virtual Value *allocateArrayPage() - { - return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); - } - - virtual void releaseArrayPage( Value *value ) - { - if ( value ) - free( value ); - } -}; - -#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -/// @todo make this thread-safe (lock when accessign batch allocator) -class DefaultValueArrayAllocator : public ValueArrayAllocator -{ -public: // overridden from ValueArrayAllocator - virtual ~DefaultValueArrayAllocator() - { - } - - virtual ValueInternalArray *newArray() - { - ValueInternalArray *array = arraysAllocator_.allocate(); - new (array) ValueInternalArray(); // placement new - return array; - } - - virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) - { - ValueInternalArray *array = arraysAllocator_.allocate(); - new (array) ValueInternalArray( other ); // placement new - return array; - } - - virtual void destructArray( ValueInternalArray *array ) - { - if ( array ) - { - array->~ValueInternalArray(); - arraysAllocator_.release( array ); - } - } - - virtual void reallocateArrayPageIndex( Value **&indexes, - ValueInternalArray::PageIndex &indexCount, - ValueInternalArray::PageIndex minNewIndexCount ) - { - ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; - if ( minNewIndexCount > newIndexCount ) - newIndexCount = minNewIndexCount; - void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); - if ( !newIndexes ) - throw std::bad_alloc(); - indexCount = newIndexCount; - indexes = static_cast<Value **>( newIndexes ); - } - virtual void releaseArrayPageIndex( Value **indexes, - ValueInternalArray::PageIndex indexCount ) - { - if ( indexes ) - free( indexes ); - } - - virtual Value *allocateArrayPage() - { - return static_cast<Value *>( pagesAllocator_.allocate() ); - } - - virtual void releaseArrayPage( Value *value ) - { - if ( value ) - pagesAllocator_.release( value ); - } -private: - BatchAllocator<ValueInternalArray,1> arraysAllocator_; - BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_; -}; -#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR - -static ValueArrayAllocator *&arrayAllocator() -{ - static DefaultValueArrayAllocator defaultAllocator; - static ValueArrayAllocator *arrayAllocator = &defaultAllocator; - return arrayAllocator; -} - -static struct DummyArrayAllocatorInitializer { - DummyArrayAllocatorInitializer() - { - arrayAllocator(); // ensure arrayAllocator() statics are initialized before main(). - } -} dummyArrayAllocatorInitializer; - -// ////////////////////////////////////////////////////////////////// -// class ValueInternalArray -// ////////////////////////////////////////////////////////////////// -bool -ValueInternalArray::equals( const IteratorState &x, - const IteratorState &other ) -{ - return x.array_ == other.array_ - && x.currentItemIndex_ == other.currentItemIndex_ - && x.currentPageIndex_ == other.currentPageIndex_; -} - - -void -ValueInternalArray::increment( IteratorState &it ) -{ - JSON_ASSERT_MESSAGE( it.array_ && - (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_ - != it.array_->size_, - "ValueInternalArray::increment(): moving iterator beyond end" ); - ++(it.currentItemIndex_); - if ( it.currentItemIndex_ == itemsPerPage ) - { - it.currentItemIndex_ = 0; - ++(it.currentPageIndex_); - } -} - - -void -ValueInternalArray::decrement( IteratorState &it ) -{ - JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_ - && it.currentItemIndex_ == 0, - "ValueInternalArray::decrement(): moving iterator beyond end" ); - if ( it.currentItemIndex_ == 0 ) - { - it.currentItemIndex_ = itemsPerPage-1; - --(it.currentPageIndex_); - } - else - { - --(it.currentItemIndex_); - } -} - - -Value & -ValueInternalArray::unsafeDereference( const IteratorState &it ) -{ - return (*(it.currentPageIndex_))[it.currentItemIndex_]; -} - - -Value & -ValueInternalArray::dereference( const IteratorState &it ) -{ - JSON_ASSERT_MESSAGE( it.array_ && - (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_ - < it.array_->size_, - "ValueInternalArray::dereference(): dereferencing invalid iterator" ); - return unsafeDereference( it ); -} - -void -ValueInternalArray::makeBeginIterator( IteratorState &it ) const -{ - it.array_ = const_cast<ValueInternalArray *>( this ); - it.currentItemIndex_ = 0; - it.currentPageIndex_ = pages_; -} - - -void -ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const -{ - it.array_ = const_cast<ValueInternalArray *>( this ); - it.currentItemIndex_ = index % itemsPerPage; - it.currentPageIndex_ = pages_ + index / itemsPerPage; -} - - -void -ValueInternalArray::makeEndIterator( IteratorState &it ) const -{ - makeIterator( it, size_ ); -} - - -ValueInternalArray::ValueInternalArray() - : pages_( 0 ) - , size_( 0 ) - , pageCount_( 0 ) -{ -} - - -ValueInternalArray::ValueInternalArray( const ValueInternalArray &other ) - : pages_( 0 ) - , pageCount_( 0 ) - , size_( other.size_ ) -{ - PageIndex minNewPages = other.size_ / itemsPerPage; - arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages ); - JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, - "ValueInternalArray::reserve(): bad reallocation" ); - IteratorState itOther; - other.makeBeginIterator( itOther ); - Value *value; - for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) ) - { - if ( index % itemsPerPage == 0 ) - { - PageIndex pageIndex = index / itemsPerPage; - value = arrayAllocator()->allocateArrayPage(); - pages_[pageIndex] = value; - } - new (value) Value( dereference( itOther ) ); - } -} - - -ValueInternalArray & -ValueInternalArray::operator =( const ValueInternalArray &other ) -{ - ValueInternalArray temp( other ); - swap( temp ); - return *this; -} - - -ValueInternalArray::~ValueInternalArray() -{ - // destroy all constructed items - IteratorState it; - IteratorState itEnd; - makeBeginIterator( it); - makeEndIterator( itEnd ); - for ( ; !equals(it,itEnd); increment(it) ) - { - Value *value = &dereference(it); - value->~Value(); - } - // release all pages - PageIndex lastPageIndex = size_ / itemsPerPage; - for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex ) - arrayAllocator()->releaseArrayPage( pages_[pageIndex] ); - // release pages index - arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ ); -} - - -void -ValueInternalArray::swap( ValueInternalArray &other ) -{ - Value **tempPages = pages_; - pages_ = other.pages_; - other.pages_ = tempPages; - ArrayIndex tempSize = size_; - size_ = other.size_; - other.size_ = tempSize; - PageIndex tempPageCount = pageCount_; - pageCount_ = other.pageCount_; - other.pageCount_ = tempPageCount; -} - -void -ValueInternalArray::clear() -{ - ValueInternalArray dummy; - swap( dummy ); -} - - -void -ValueInternalArray::resize( ArrayIndex newSize ) -{ - if ( newSize == 0 ) - clear(); - else if ( newSize < size_ ) - { - IteratorState it; - IteratorState itEnd; - makeIterator( it, newSize ); - makeIterator( itEnd, size_ ); - for ( ; !equals(it,itEnd); increment(it) ) - { - Value *value = &dereference(it); - value->~Value(); - } - PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage; - PageIndex lastPageIndex = size_ / itemsPerPage; - for ( ; pageIndex < lastPageIndex; ++pageIndex ) - arrayAllocator()->releaseArrayPage( pages_[pageIndex] ); - size_ = newSize; - } - else if ( newSize > size_ ) - resolveReference( newSize ); -} - - -void -ValueInternalArray::makeIndexValid( ArrayIndex index ) -{ - // Need to enlarge page index ? - if ( index >= pageCount_ * itemsPerPage ) - { - PageIndex minNewPages = (index + 1) / itemsPerPage; - arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages ); - JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" ); - } - - // Need to allocate new pages ? - ArrayIndex nextPageIndex = - (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage - : size_; - if ( nextPageIndex <= index ) - { - PageIndex pageIndex = nextPageIndex / itemsPerPage; - PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1; - for ( ; pageToAllocate-- > 0; ++pageIndex ) - pages_[pageIndex] = arrayAllocator()->allocateArrayPage(); - } - - // Initialize all new entries - IteratorState it; - IteratorState itEnd; - makeIterator( it, size_ ); - size_ = index + 1; - makeIterator( itEnd, size_ ); - for ( ; !equals(it,itEnd); increment(it) ) - { - Value *value = &dereference(it); - new (value) Value(); // Construct a default value using placement new - } -} - -Value & -ValueInternalArray::resolveReference( ArrayIndex index ) -{ - if ( index >= size_ ) - makeIndexValid( index ); - return pages_[index/itemsPerPage][index%itemsPerPage]; -} - -Value * -ValueInternalArray::find( ArrayIndex index ) const -{ - if ( index >= size_ ) - return 0; - return &(pages_[index/itemsPerPage][index%itemsPerPage]); -} - -ValueInternalArray::ArrayIndex -ValueInternalArray::size() const -{ - return size_; -} - -int -ValueInternalArray::distance( const IteratorState &x, const IteratorState &y ) -{ - return indexOf(y) - indexOf(x); -} - - -ValueInternalArray::ArrayIndex -ValueInternalArray::indexOf( const IteratorState &iterator ) -{ - if ( !iterator.array_ ) - return ArrayIndex(-1); - return ArrayIndex( - (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage - + iterator.currentItemIndex_ ); -} - - -int -ValueInternalArray::compare( const ValueInternalArray &other ) const -{ - int sizeDiff( size_ - other.size_ ); - if ( sizeDiff != 0 ) - return sizeDiff; - - for ( ArrayIndex index =0; index < size_; ++index ) - { - int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare( - other.pages_[index/itemsPerPage][index%itemsPerPage] ); - if ( diff != 0 ) - return diff; - } - return 0; -} diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_internalmap.inl b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_internalmap.inl deleted file mode 100644 index 19771488..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_internalmap.inl +++ /dev/null @@ -1,607 +0,0 @@ -// included by json_value.cpp -// everything is within Json namespace - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueInternalMap -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) ); - * This optimization is used by the fast allocator. - */ -ValueInternalLink::ValueInternalLink() - : previous_( 0 ) - , next_( 0 ) -{ -} - -ValueInternalLink::~ValueInternalLink() -{ - for ( int index =0; index < itemPerLink; ++index ) - { - if ( !items_[index].isItemAvailable() ) - { - if ( !items_[index].isMemberNameStatic() ) - free( keys_[index] ); - } - else - break; - } -} - - - -ValueMapAllocator::~ValueMapAllocator() -{ -} - -#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -class DefaultValueMapAllocator : public ValueMapAllocator -{ -public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - return new ValueInternalMap(); - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - return new ValueInternalMap( other ); - } - - virtual void destructMap( ValueInternalMap *map ) - { - delete map; - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - return new ValueInternalLink(); - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - delete link; - } -}; -#else -/// @todo make this thread-safe (lock when accessign batch allocator) -class DefaultValueMapAllocator : public ValueMapAllocator -{ -public: // overridden from ValueMapAllocator - virtual ValueInternalMap *newMap() - { - ValueInternalMap *map = mapsAllocator_.allocate(); - new (map) ValueInternalMap(); // placement new - return map; - } - - virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) - { - ValueInternalMap *map = mapsAllocator_.allocate(); - new (map) ValueInternalMap( other ); // placement new - return map; - } - - virtual void destructMap( ValueInternalMap *map ) - { - if ( map ) - { - map->~ValueInternalMap(); - mapsAllocator_.release( map ); - } - } - - virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) - { - return new ValueInternalLink[size]; - } - - virtual void releaseMapBuckets( ValueInternalLink *links ) - { - delete [] links; - } - - virtual ValueInternalLink *allocateMapLink() - { - ValueInternalLink *link = linksAllocator_.allocate(); - memset( link, 0, sizeof(ValueInternalLink) ); - return link; - } - - virtual void releaseMapLink( ValueInternalLink *link ) - { - link->~ValueInternalLink(); - linksAllocator_.release( link ); - } -private: - BatchAllocator<ValueInternalMap,1> mapsAllocator_; - BatchAllocator<ValueInternalLink,1> linksAllocator_; -}; -#endif - -static ValueMapAllocator *&mapAllocator() -{ - static DefaultValueMapAllocator defaultAllocator; - static ValueMapAllocator *mapAllocator = &defaultAllocator; - return mapAllocator; -} - -static struct DummyMapAllocatorInitializer { - DummyMapAllocatorInitializer() - { - mapAllocator(); // ensure mapAllocator() statics are initialized before main(). - } -} dummyMapAllocatorInitializer; - - - -// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32. - -/* -use linked list hash map. -buckets array is a container. -linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124) -value have extra state: valid, available, deleted -*/ - - -ValueInternalMap::ValueInternalMap() - : buckets_( 0 ) - , tailLink_( 0 ) - , bucketsSize_( 0 ) - , itemCount_( 0 ) -{ -} - - -ValueInternalMap::ValueInternalMap( const ValueInternalMap &other ) - : buckets_( 0 ) - , tailLink_( 0 ) - , bucketsSize_( 0 ) - , itemCount_( 0 ) -{ - reserve( other.itemCount_ ); - IteratorState it; - IteratorState itEnd; - other.makeBeginIterator( it ); - other.makeEndIterator( itEnd ); - for ( ; !equals(it,itEnd); increment(it) ) - { - bool isStatic; - const char *memberName = key( it, isStatic ); - const Value &aValue = value( it ); - resolveReference(memberName, isStatic) = aValue; - } -} - - -ValueInternalMap & -ValueInternalMap::operator =( const ValueInternalMap &other ) -{ - ValueInternalMap dummy( other ); - swap( dummy ); - return *this; -} - - -ValueInternalMap::~ValueInternalMap() -{ - if ( buckets_ ) - { - for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex ) - { - ValueInternalLink *link = buckets_[bucketIndex].next_; - while ( link ) - { - ValueInternalLink *linkToRelease = link; - link = link->next_; - mapAllocator()->releaseMapLink( linkToRelease ); - } - } - mapAllocator()->releaseMapBuckets( buckets_ ); - } -} - - -void -ValueInternalMap::swap( ValueInternalMap &other ) -{ - ValueInternalLink *tempBuckets = buckets_; - buckets_ = other.buckets_; - other.buckets_ = tempBuckets; - ValueInternalLink *tempTailLink = tailLink_; - tailLink_ = other.tailLink_; - other.tailLink_ = tempTailLink; - BucketIndex tempBucketsSize = bucketsSize_; - bucketsSize_ = other.bucketsSize_; - other.bucketsSize_ = tempBucketsSize; - BucketIndex tempItemCount = itemCount_; - itemCount_ = other.itemCount_; - other.itemCount_ = tempItemCount; -} - - -void -ValueInternalMap::clear() -{ - ValueInternalMap dummy; - swap( dummy ); -} - - -ValueInternalMap::BucketIndex -ValueInternalMap::size() const -{ - return itemCount_; -} - -bool -ValueInternalMap::reserveDelta( BucketIndex growth ) -{ - return reserve( itemCount_ + growth ); -} - -bool -ValueInternalMap::reserve( BucketIndex newItemCount ) -{ - if ( !buckets_ && newItemCount > 0 ) - { - buckets_ = mapAllocator()->allocateMapBuckets( 1 ); - bucketsSize_ = 1; - tailLink_ = &buckets_[0]; - } -// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink; - return true; -} - - -const Value * -ValueInternalMap::find( const char *key ) const -{ - if ( !bucketsSize_ ) - return 0; - HashKey hashedKey = hash( key ); - BucketIndex bucketIndex = hashedKey % bucketsSize_; - for ( const ValueInternalLink *current = &buckets_[bucketIndex]; - current != 0; - current = current->next_ ) - { - for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index ) - { - if ( current->items_[index].isItemAvailable() ) - return 0; - if ( strcmp( key, current->keys_[index] ) == 0 ) - return ¤t->items_[index]; - } - } - return 0; -} - - -Value * -ValueInternalMap::find( const char *key ) -{ - const ValueInternalMap *constThis = this; - return const_cast<Value *>( constThis->find( key ) ); -} - - -Value & -ValueInternalMap::resolveReference( const char *key, - bool isStatic ) -{ - HashKey hashedKey = hash( key ); - if ( bucketsSize_ ) - { - BucketIndex bucketIndex = hashedKey % bucketsSize_; - ValueInternalLink **previous = 0; - BucketIndex index; - for ( ValueInternalLink *current = &buckets_[bucketIndex]; - current != 0; - previous = ¤t->next_, current = current->next_ ) - { - for ( index=0; index < ValueInternalLink::itemPerLink; ++index ) - { - if ( current->items_[index].isItemAvailable() ) - return setNewItem( key, isStatic, current, index ); - if ( strcmp( key, current->keys_[index] ) == 0 ) - return current->items_[index]; - } - } - } - - reserveDelta( 1 ); - return unsafeAdd( key, isStatic, hashedKey ); -} - - -void -ValueInternalMap::remove( const char *key ) -{ - HashKey hashedKey = hash( key ); - if ( !bucketsSize_ ) - return; - BucketIndex bucketIndex = hashedKey % bucketsSize_; - for ( ValueInternalLink *link = &buckets_[bucketIndex]; - link != 0; - link = link->next_ ) - { - BucketIndex index; - for ( index =0; index < ValueInternalLink::itemPerLink; ++index ) - { - if ( link->items_[index].isItemAvailable() ) - return; - if ( strcmp( key, link->keys_[index] ) == 0 ) - { - doActualRemove( link, index, bucketIndex ); - return; - } - } - } -} - -void -ValueInternalMap::doActualRemove( ValueInternalLink *link, - BucketIndex index, - BucketIndex bucketIndex ) -{ - // find last item of the bucket and swap it with the 'removed' one. - // set removed items flags to 'available'. - // if last page only contains 'available' items, then desallocate it (it's empty) - ValueInternalLink *&lastLink = getLastLinkInBucket( index ); - BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1 - for ( ; - lastItemIndex < ValueInternalLink::itemPerLink; - ++lastItemIndex ) // may be optimized with dicotomic search - { - if ( lastLink->items_[lastItemIndex].isItemAvailable() ) - break; - } - - BucketIndex lastUsedIndex = lastItemIndex - 1; - Value *valueToDelete = &link->items_[index]; - Value *valueToPreserve = &lastLink->items_[lastUsedIndex]; - if ( valueToDelete != valueToPreserve ) - valueToDelete->swap( *valueToPreserve ); - if ( lastUsedIndex == 0 ) // page is now empty - { // remove it from bucket linked list and delete it. - ValueInternalLink *linkPreviousToLast = lastLink->previous_; - if ( linkPreviousToLast != 0 ) // can not deleted bucket link. - { - mapAllocator()->releaseMapLink( lastLink ); - linkPreviousToLast->next_ = 0; - lastLink = linkPreviousToLast; - } - } - else - { - Value dummy; - valueToPreserve->swap( dummy ); // restore deleted to default Value. - valueToPreserve->setItemUsed( false ); - } - --itemCount_; -} - - -ValueInternalLink *& -ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex ) -{ - if ( bucketIndex == bucketsSize_ - 1 ) - return tailLink_; - ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_; - if ( !previous ) - previous = &buckets_[bucketIndex]; - return previous; -} - - -Value & -ValueInternalMap::setNewItem( const char *key, - bool isStatic, - ValueInternalLink *link, - BucketIndex index ) -{ - char *duplicatedKey = valueAllocator()->makeMemberName( key ); - ++itemCount_; - link->keys_[index] = duplicatedKey; - link->items_[index].setItemUsed(); - link->items_[index].setMemberNameIsStatic( isStatic ); - return link->items_[index]; // items already default constructed. -} - - -Value & -ValueInternalMap::unsafeAdd( const char *key, - bool isStatic, - HashKey hashedKey ) -{ - JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." ); - BucketIndex bucketIndex = hashedKey % bucketsSize_; - ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex ); - ValueInternalLink *link = previousLink; - BucketIndex index; - for ( index =0; index < ValueInternalLink::itemPerLink; ++index ) - { - if ( link->items_[index].isItemAvailable() ) - break; - } - if ( index == ValueInternalLink::itemPerLink ) // need to add a new page - { - ValueInternalLink *newLink = mapAllocator()->allocateMapLink(); - index = 0; - link->next_ = newLink; - previousLink = newLink; - link = newLink; - } - return setNewItem( key, isStatic, link, index ); -} - - -ValueInternalMap::HashKey -ValueInternalMap::hash( const char *key ) const -{ - HashKey hash = 0; - while ( *key ) - hash += *key++ * 37; - return hash; -} - - -int -ValueInternalMap::compare( const ValueInternalMap &other ) const -{ - int sizeDiff( itemCount_ - other.itemCount_ ); - if ( sizeDiff != 0 ) - return sizeDiff; - // Strict order guaranty is required. Compare all keys FIRST, then compare values. - IteratorState it; - IteratorState itEnd; - makeBeginIterator( it ); - makeEndIterator( itEnd ); - for ( ; !equals(it,itEnd); increment(it) ) - { - if ( !other.find( key( it ) ) ) - return 1; - } - - // All keys are equals, let's compare values - makeBeginIterator( it ); - for ( ; !equals(it,itEnd); increment(it) ) - { - const Value *otherValue = other.find( key( it ) ); - int valueDiff = value(it).compare( *otherValue ); - if ( valueDiff != 0 ) - return valueDiff; - } - return 0; -} - - -void -ValueInternalMap::makeBeginIterator( IteratorState &it ) const -{ - it.map_ = const_cast<ValueInternalMap *>( this ); - it.bucketIndex_ = 0; - it.itemIndex_ = 0; - it.link_ = buckets_; -} - - -void -ValueInternalMap::makeEndIterator( IteratorState &it ) const -{ - it.map_ = const_cast<ValueInternalMap *>( this ); - it.bucketIndex_ = bucketsSize_; - it.itemIndex_ = 0; - it.link_ = 0; -} - - -bool -ValueInternalMap::equals( const IteratorState &x, const IteratorState &other ) -{ - return x.map_ == other.map_ - && x.bucketIndex_ == other.bucketIndex_ - && x.link_ == other.link_ - && x.itemIndex_ == other.itemIndex_; -} - - -void -ValueInternalMap::incrementBucket( IteratorState &iterator ) -{ - ++iterator.bucketIndex_; - JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_, - "ValueInternalMap::increment(): attempting to iterate beyond end." ); - if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ ) - iterator.link_ = 0; - else - iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]); - iterator.itemIndex_ = 0; -} - - -void -ValueInternalMap::increment( IteratorState &iterator ) -{ - JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." ); - ++iterator.itemIndex_; - if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink ) - { - JSON_ASSERT_MESSAGE( iterator.link_ != 0, - "ValueInternalMap::increment(): attempting to iterate beyond end." ); - iterator.link_ = iterator.link_->next_; - if ( iterator.link_ == 0 ) - incrementBucket( iterator ); - } - else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() ) - { - incrementBucket( iterator ); - } -} - - -void -ValueInternalMap::decrement( IteratorState &iterator ) -{ - if ( iterator.itemIndex_ == 0 ) - { - JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." ); - if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] ) - { - JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." ); - --(iterator.bucketIndex_); - } - iterator.link_ = iterator.link_->previous_; - iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1; - } -} - - -const char * -ValueInternalMap::key( const IteratorState &iterator ) -{ - JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." ); - return iterator.link_->keys_[iterator.itemIndex_]; -} - -const char * -ValueInternalMap::key( const IteratorState &iterator, bool &isStatic ) -{ - JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." ); - isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic(); - return iterator.link_->keys_[iterator.itemIndex_]; -} - - -Value & -ValueInternalMap::value( const IteratorState &iterator ) -{ - JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." ); - return iterator.link_->items_[iterator.itemIndex_]; -} - - -int -ValueInternalMap::distance( const IteratorState &x, const IteratorState &y ) -{ - int offset = 0; - IteratorState it = x; - while ( !equals( it, y ) ) - increment( it ); - return offset; -} diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_reader.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_reader.cpp deleted file mode 100644 index 5af16c8d..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_reader.cpp +++ /dev/null @@ -1,892 +0,0 @@ -#include <json/reader.h> -#include <json/value.h> -#include <utility> -#include <cstdio> -#include <cassert> -#include <cstring> -#include <iostream> -#include <stdexcept> - -#if _MSC_VER >= 1400 // VC++ 8.0 -#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. -#endif - -namespace Json { - -// QNX is strict about declaring C symbols in the std namespace. -#ifdef __QNXNTO__ -using std::memcpy; -using std::sprintf; -using std::sscanf; -#endif - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() - : allowComments_( true ) - , strictRoot_( false ) -{ -} - - -Features -Features::all() -{ - return Features(); -} - - -Features -Features::strictMode() -{ - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - - -static inline bool -in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) -{ - return c == c1 || c == c2 || c == c3 || c == c4; -} - -static inline bool -in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) -{ - return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; -} - - -static bool -containsNewLine( Reader::Location begin, - Reader::Location end ) -{ - for ( ;begin < end; ++begin ) - if ( *begin == '\n' || *begin == '\r' ) - return true; - return false; -} - -static std::string codePointToUTF8(unsigned int cp) -{ - std::string result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) - { - result.resize(1); - result[0] = static_cast<char>(cp); - } - else if (cp <= 0x7FF) - { - result.resize(2); - result[1] = static_cast<char>(0x80 | (0x3f & cp)); - result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); - } - else if (cp <= 0xFFFF) - { - result.resize(3); - result[2] = static_cast<char>(0x80 | (0x3f & cp)); - result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6))); - result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12))); - } - else if (cp <= 0x10FFFF) - { - result.resize(4); - result[3] = static_cast<char>(0x80 | (0x3f & cp)); - result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() - : features_( Features::all() ) -{ -} - - -Reader::Reader( const Features &features ) - : features_( features ) -{ -} - - -bool -Reader::parse( const std::string &document, - Value &root, - bool collectComments ) -{ - document_ = document; - const char *begin = document_.c_str(); - const char *end = begin + document_.length(); - return parse( begin, end, root, collectComments ); -} - - -bool -Reader::parse( std::istream& sin, - Value &root, - bool collectComments ) -{ - //std::istream_iterator<char> begin(sin); - //std::istream_iterator<char> end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since std::string is reference-counted, this at least does not - // create an extra copy. - std::string doc; - std::getline(sin, doc, (char)EOF); - return parse( doc, root, collectComments ); -} - -bool -Reader::parse( const char *beginDoc, const char *endDoc, - Value &root, - bool collectComments ) -{ - if ( !features_.allowComments_ ) - { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; - commentsBefore_ = ""; - errors_.clear(); - while ( !nodes_.empty() ) - nodes_.pop(); - nodes_.push( &root ); - - bool successful = readValue(); - Token token; - skipCommentTokens( token ); - if ( collectComments_ && !commentsBefore_.empty() ) - root.setComment( commentsBefore_, commentAfter ); - if ( features_.strictRoot_ ) - { - if ( !root.isArray() && !root.isObject() ) - { - // Set error location to start of doc, ideally should be first token found in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( "A valid JSON document must be either an array or an object value.", - token ); - return false; - } - } - return successful; -} - - -bool -Reader::readValue() -{ - Token token; - skipCommentTokens( token ); - bool successful = true; - - if ( collectComments_ && !commentsBefore_.empty() ) - { - currentValue().setComment( commentsBefore_, commentBefore ); - commentsBefore_ = ""; - } - - - switch ( token.type_ ) - { - case tokenObjectBegin: - successful = readObject( token ); - break; - case tokenArrayBegin: - successful = readArray( token ); - break; - case tokenNumber: - successful = decodeNumber( token ); - break; - case tokenString: - successful = decodeString( token ); - break; - case tokenTrue: - currentValue() = true; - break; - case tokenFalse: - currentValue() = false; - break; - case tokenNull: - currentValue() = Value(); - break; - default: - return addError( "Syntax error: value, object or array expected.", token ); - } - - if ( collectComments_ ) - { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - - -void -Reader::skipCommentTokens( Token &token ) -{ - if ( features_.allowComments_ ) - { - do - { - readToken( token ); - } - while ( token.type_ == tokenComment ); - } - else - { - readToken( token ); - } -} - - -bool -Reader::expectToken( TokenType type, Token &token, const char *message ) -{ - readToken( token ); - if ( token.type_ != type ) - return addError( message, token ); - return true; -} - - -bool -Reader::readToken( Token &token ) -{ - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch ( c ) - { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match( "rue", 3 ); - break; - case 'f': - token.type_ = tokenFalse; - ok = match( "alse", 4 ); - break; - case 'n': - token.type_ = tokenNull; - ok = match( "ull", 3 ); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if ( !ok ) - token.type_ = tokenError; - token.end_ = current_; - return true; -} - - -void -Reader::skipSpaces() -{ - while ( current_ != end_ ) - { - Char c = *current_; - if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) - ++current_; - else - break; - } -} - - -bool -Reader::match( Location pattern, - int patternLength ) -{ - if ( end_ - current_ < patternLength ) - return false; - int index = patternLength; - while ( index-- ) - if ( current_[index] != pattern[index] ) - return false; - current_ += patternLength; - return true; -} - - -bool -Reader::readComment() -{ - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if ( c == '*' ) - successful = readCStyleComment(); - else if ( c == '/' ) - successful = readCppStyleComment(); - if ( !successful ) - return false; - - if ( collectComments_ ) - { - CommentPlacement placement = commentBefore; - if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) - { - if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) - placement = commentAfterOnSameLine; - } - - addComment( commentBegin, current_, placement ); - } - return true; -} - - -void -Reader::addComment( Location begin, - Location end, - CommentPlacement placement ) -{ - assert( collectComments_ ); - if ( placement == commentAfterOnSameLine ) - { - assert( lastValue_ != 0 ); - lastValue_->setComment( std::string( begin, end ), placement ); - } - else - { - if ( !commentsBefore_.empty() ) - commentsBefore_ += "\n"; - commentsBefore_ += std::string( begin, end ); - } -} - - -bool -Reader::readCStyleComment() -{ - while ( current_ != end_ ) - { - Char c = getNextChar(); - if ( c == '*' && *current_ == '/' ) - break; - } - return getNextChar() == '/'; -} - - -bool -Reader::readCppStyleComment() -{ - while ( current_ != end_ ) - { - Char c = getNextChar(); - if ( c == '\r' || c == '\n' ) - break; - } - return true; -} - - -void -Reader::readNumber() -{ - while ( current_ != end_ ) - { - if ( !(*current_ >= '0' && *current_ <= '9') && - !in( *current_, '.', 'e', 'E', '+', '-' ) ) - break; - ++current_; - } -} - -bool -Reader::readString() -{ - Char c = 0; - while ( current_ != end_ ) - { - c = getNextChar(); - if ( c == '\\' ) - getNextChar(); - else if ( c == '"' ) - break; - } - return c == '"'; -} - - -bool -Reader::readObject( Token &tokenStart ) -{ - Token tokenName; - std::string name; - currentValue() = Value( objectValue ); - while ( readToken( tokenName ) ) - { - bool initialTokenOk = true; - while ( tokenName.type_ == tokenComment && initialTokenOk ) - initialTokenOk = readToken( tokenName ); - if ( !initialTokenOk ) - break; - if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object - return true; - if ( tokenName.type_ != tokenString ) - break; - - name = ""; - if ( !decodeString( tokenName, name ) ) - return recoverFromError( tokenObjectEnd ); - - Token colon; - if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) - { - return addErrorAndRecover( "Missing ':' after object member name", - colon, - tokenObjectEnd ); - } - Value &value = currentValue()[ name ]; - nodes_.push( &value ); - bool ok = readValue(); - nodes_.pop(); - if ( !ok ) // error already set - return recoverFromError( tokenObjectEnd ); - - Token comma; - if ( !readToken( comma ) - || ( comma.type_ != tokenObjectEnd && - comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment ) ) - { - return addErrorAndRecover( "Missing ',' or '}' in object declaration", - comma, - tokenObjectEnd ); - } - bool finalizeTokenOk = true; - while ( comma.type_ == tokenComment && - finalizeTokenOk ) - finalizeTokenOk = readToken( comma ); - if ( comma.type_ == tokenObjectEnd ) - return true; - } - return addErrorAndRecover( "Missing '}' or object member name", - tokenName, - tokenObjectEnd ); -} - - -bool -Reader::readArray( Token &tokenStart ) -{ - currentValue() = Value( arrayValue ); - skipSpaces(); - if ( *current_ == ']' ) // empty array - { - Token endArray; - readToken( endArray ); - return true; - } - int index = 0; - while ( true ) - { - Value &value = currentValue()[ index++ ]; - nodes_.push( &value ); - bool ok = readValue(); - nodes_.pop(); - if ( !ok ) // error already set - return recoverFromError( tokenArrayEnd ); - - Token token; - // Accept Comment after last item in the array. - ok = readToken( token ); - while ( token.type_ == tokenComment && ok ) - { - ok = readToken( token ); - } - bool badTokenType = ( token.type_ == tokenArraySeparator && - token.type_ == tokenArrayEnd ); - if ( !ok || badTokenType ) - { - return addErrorAndRecover( "Missing ',' or ']' in array declaration", - token, - tokenArrayEnd ); - } - if ( token.type_ == tokenArrayEnd ) - break; - } - return true; -} - - -bool -Reader::decodeNumber( Token &token ) -{ - bool isDouble = false; - for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) - { - isDouble = isDouble - || in( *inspect, '.', 'e', 'E', '+' ) - || ( *inspect == '-' && inspect != token.start_ ); - } - if ( isDouble ) - return decodeDouble( token ); - Location current = token.start_; - bool isNegative = *current == '-'; - if ( isNegative ) - ++current; - Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) - : Value::maxUInt) / 10; - Value::UInt value = 0; - while ( current < token.end_ ) - { - Char c = *current++; - if ( c < '0' || c > '9' ) - return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); - if ( value >= threshold ) - return decodeDouble( token ); - value = value * 10 + Value::UInt(c - '0'); - } - if ( isNegative ) - currentValue() = -Value::Int( value ); - else if ( value <= Value::UInt(Value::maxInt) ) - currentValue() = Value::Int( value ); - else - currentValue() = value; - return true; -} - - -bool -Reader::decodeDouble( Token &token ) -{ - double value = 0; - const int bufferSize = 32; - int count; - int length = int(token.end_ - token.start_); - if ( length <= bufferSize ) - { - Char buffer[bufferSize]; - memcpy( buffer, token.start_, length ); - buffer[length] = 0; - count = sscanf( buffer, "%lf", &value ); - } - else - { - std::string buffer( token.start_, token.end_ ); - count = sscanf( buffer.c_str(), "%lf", &value ); - } - - if ( count != 1 ) - return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); - currentValue() = value; - return true; -} - - -bool -Reader::decodeString( Token &token ) -{ - std::string decoded; - if ( !decodeString( token, decoded ) ) - return false; - currentValue() = decoded; - return true; -} - - -bool -Reader::decodeString( Token &token, std::string &decoded ) -{ - decoded.reserve( token.end_ - token.start_ - 2 ); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while ( current != end ) - { - Char c = *current++; - if ( c == '"' ) - break; - else if ( c == '\\' ) - { - if ( current == end ) - return addError( "Empty escape sequence in string", token, current ); - Char escape = *current++; - switch ( escape ) - { - case '"': decoded += '"'; break; - case '/': decoded += '/'; break; - case '\\': decoded += '\\'; break; - case 'b': decoded += '\b'; break; - case 'f': decoded += '\f'; break; - case 'n': decoded += '\n'; break; - case 'r': decoded += '\r'; break; - case 't': decoded += '\t'; break; - case 'u': - { - unsigned int unicode; - if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) - return false; - decoded += codePointToUTF8(unicode); - } - break; - default: - return addError( "Bad escape sequence in string", token, current ); - } - } - else - { - decoded += c; - } - } - return true; -} - -bool -Reader::decodeUnicodeCodePoint( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ) -{ - - if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) - { - // surrogate pairs - if (end - current < 6) - return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); - unsigned int surrogatePair; - if (*(current++) == '\\' && *(current++)== 'u') - { - if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) - { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } - else - return false; - } - else - return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); - } - return true; -} - -bool -Reader::decodeUnicodeEscapeSequence( Token &token, - Location ¤t, - Location end, - unsigned int &unicode ) -{ - if ( end - current < 4 ) - return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); - unicode = 0; - for ( int index =0; index < 4; ++index ) - { - Char c = *current++; - unicode *= 16; - if ( c >= '0' && c <= '9' ) - unicode += c - '0'; - else if ( c >= 'a' && c <= 'f' ) - unicode += c - 'a' + 10; - else if ( c >= 'A' && c <= 'F' ) - unicode += c - 'A' + 10; - else - return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); - } - return true; -} - - -bool -Reader::addError( const std::string &message, - Token &token, - Location extra ) -{ - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back( info ); - return false; -} - - -bool -Reader::recoverFromError( TokenType skipUntilToken ) -{ - int errorCount = int(errors_.size()); - Token skip; - while ( true ) - { - if ( !readToken(skip) ) - errors_.resize( errorCount ); // discard errors caused by recovery - if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) - break; - } - errors_.resize( errorCount ); - return false; -} - - -bool -Reader::addErrorAndRecover( const std::string &message, - Token &token, - TokenType skipUntilToken ) -{ - addError( message, token ); - return recoverFromError( skipUntilToken ); -} - - -Value & -Reader::currentValue() -{ - return *(nodes_.top()); -} - - -Reader::Char -Reader::getNextChar() -{ - if ( current_ == end_ ) - return 0; - return *current_++; -} - - -void -Reader::getLocationLineAndColumn( Location location, - int &line, - int &column ) const -{ - Location current = begin_; - Location lastLineStart = current; - line = 0; - while ( current < location && current != end_ ) - { - Char c = *current++; - if ( c == '\r' ) - { - if ( *current == '\n' ) - ++current; - lastLineStart = current; - ++line; - } - else if ( c == '\n' ) - { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - - -std::string -Reader::getLocationLineAndColumn( Location location ) const -{ - int line, column; - getLocationLineAndColumn( location, line, column ); - char buffer[18+16+16+1]; - sprintf( buffer, "Line %d, Column %d", line, column ); - return buffer; -} - - -std::string -Reader::getFormatedErrorMessages() const -{ - std::string formattedMessage; - for ( Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError ) - { - const ErrorInfo &error = *itError; - formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if ( error.extra_ ) - formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; - } - return formattedMessage; -} - - -std::istream& operator>>( std::istream &sin, Value &root ) -{ - Json::Reader reader; - bool ok = reader.parse(sin, root, true); - //JSON_ASSERT( ok ); - if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages()); - return sin; -} - - -} // namespace Json diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_value.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_value.cpp deleted file mode 100644 index 6e5dcd3e..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_value.cpp +++ /dev/null @@ -1,1726 +0,0 @@ -#include <iostream> -#include <json/value.h> -#include <json/writer.h> -#include <utility> -#include <stdexcept> -#include <cstring> -#include <cassert> -#ifdef JSON_USE_CPPTL -# include <cpptl/conststring.h> -#endif -#include <cstddef> // size_t -#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR -# include "json_batchallocator.h" -#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR - -#define JSON_ASSERT_UNREACHABLE assert( false ) -#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw -#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message ); - -namespace Json { - -// QNX is strict about declaring C symbols in the std namespace. -#ifdef __QNXNTO__ -using std::memcpy; -using std::strchr; -using std::strcmp; -using std::strlen; -#endif - -const Value Value::null; -const Int Value::minInt = Int( ~(UInt(-1)/2) ); -const Int Value::maxInt = Int( UInt(-1)/2 ); -const UInt Value::maxUInt = UInt(-1); - -// A "safe" implementation of strdup. Allow null pointer to be passed. -// Also avoid warning on msvc80. -// -//inline char *safeStringDup( const char *czstring ) -//{ -// if ( czstring ) -// { -// const size_t length = (unsigned int)( strlen(czstring) + 1 ); -// char *newString = static_cast<char *>( malloc( length ) ); -// memcpy( newString, czstring, length ); -// return newString; -// } -// return 0; -//} -// -//inline char *safeStringDup( const std::string &str ) -//{ -// if ( !str.empty() ) -// { -// const size_t length = str.length(); -// char *newString = static_cast<char *>( malloc( length + 1 ) ); -// memcpy( newString, str.c_str(), length ); -// newString[length] = 0; -// return newString; -// } -// return 0; -//} - -ValueAllocator::~ValueAllocator() -{ -} - -class DefaultValueAllocator : public ValueAllocator -{ -public: - virtual ~DefaultValueAllocator() - { - } - - virtual char *makeMemberName( const char *memberName ) - { - return duplicateStringValue( memberName ); - } - - virtual void releaseMemberName( char *memberName ) - { - releaseStringValue( memberName ); - } - - virtual char *duplicateStringValue( const char *value, - unsigned int length = unknown ) - { - //@todo invesgate this old optimization - //if ( !value || value[0] == 0 ) - // return 0; - - if ( length == unknown ) - length = (unsigned int)strlen(value); - char *newString = static_cast<char *>( malloc( length + 1 ) ); - memcpy( newString, value, length ); - newString[length] = 0; - return newString; - } - - virtual void releaseStringValue( char *value ) - { - if ( value ) - free( value ); - } -}; - -static ValueAllocator *&valueAllocator() -{ - static DefaultValueAllocator defaultAllocator; - static ValueAllocator *valueAllocator = &defaultAllocator; - return valueAllocator; -} - -static struct DummyValueAllocatorInitializer { - DummyValueAllocatorInitializer() - { - valueAllocator(); // ensure valueAllocator() statics are initialized before main(). - } -} dummyValueAllocatorInitializer; - - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#ifdef JSON_VALUE_USE_INTERNAL_MAP -# include "json_internalarray.inl" -# include "json_internalmap.inl" -#endif // JSON_VALUE_USE_INTERNAL_MAP - -# include "json_valueiterator.inl" - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - - -Value::CommentInfo::CommentInfo() - : comment_( 0 ) -{ -} - -Value::CommentInfo::~CommentInfo() -{ - if ( comment_ ) - valueAllocator()->releaseStringValue( comment_ ); -} - - -void -Value::CommentInfo::setComment( const char *text ) -{ - if ( comment_ ) - valueAllocator()->releaseStringValue( comment_ ); - JSON_ASSERT( text ); - JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = valueAllocator()->duplicateStringValue( text ); -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -# ifndef JSON_VALUE_USE_INTERNAL_MAP - -// Notes: index_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString( int index ) - : cstr_( 0 ) - , index_( index ) -{ -} - -Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate ) - : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr) - : cstr ) - , index_( allocate ) -{ -} - -Value::CZString::CZString( const CZString &other ) -: cstr_( other.index_ != noDuplication && other.cstr_ != 0 - ? valueAllocator()->makeMemberName( other.cstr_ ) - : other.cstr_ ) - , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) - : other.index_ ) -{ -} - -Value::CZString::~CZString() -{ - if ( cstr_ && index_ == duplicate ) - valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) ); -} - -void -Value::CZString::swap( CZString &other ) -{ - std::swap( cstr_, other.cstr_ ); - std::swap( index_, other.index_ ); -} - -Value::CZString & -Value::CZString::operator =( const CZString &other ) -{ - CZString temp( other ); - swap( temp ); - return *this; -} - -bool -Value::CZString::operator<( const CZString &other ) const -{ - if ( cstr_ ) - return strcmp( cstr_, other.cstr_ ) < 0; - return index_ < other.index_; -} - -bool -Value::CZString::operator==( const CZString &other ) const -{ - if ( cstr_ ) - return strcmp( cstr_, other.cstr_ ) == 0; - return index_ == other.index_; -} - - -int -Value::CZString::index() const -{ - return index_; -} - - -const char * -Value::CZString::c_str() const -{ - return cstr_; -} - -bool -Value::CZString::isStaticString() const -{ - return index_ == noDuplication; -} - -#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value( ValueType type ) - : type_( type ) - , allocated_( 0 ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - switch ( type ) - { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArray(); - break; - case objectValue: - value_.map_ = mapAllocator()->newMap(); - break; -#endif - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - - -Value::Value( Int value ) - : type_( intValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.int_ = value; -} - - -Value::Value( UInt value ) - : type_( uintValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.uint_ = value; -} - -Value::Value( double value ) - : type_( realValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.real_ = value; -} - -Value::Value( const char *value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = valueAllocator()->duplicateStringValue( value ); -} - - -Value::Value( const char *beginValue, - const char *endValue ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = valueAllocator()->duplicateStringValue( beginValue, - UInt(endValue - beginValue) ); -} - - -Value::Value( const std::string &value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), - (unsigned int)value.length() ); - -} - -Value::Value( const StaticString &value ) - : type_( stringValue ) - , allocated_( false ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = const_cast<char *>( value.c_str() ); -} - - -# ifdef JSON_USE_CPPTL -Value::Value( const CppTL::ConstString &value ) - : type_( stringValue ) - , allocated_( true ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() ); -} -# endif - -Value::Value( bool value ) - : type_( booleanValue ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - value_.bool_ = value; -} - - -Value::Value( const Value &other ) - : type_( other.type_ ) - , comments_( 0 ) -# ifdef JSON_VALUE_USE_INTERNAL_MAP - , itemIsUsed_( 0 ) -#endif -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if ( other.value_.string_ ) - { - value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ ); - allocated_ = true; - } - else - value_.string_ = 0; - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues( *other.value_.map_ ); - break; -#else - case arrayValue: - value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ ); - break; - case objectValue: - value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ ); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - if ( other.comments_ ) - { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for ( int comment =0; comment < numberOfCommentPlacement; ++comment ) - { - const CommentInfo &otherComment = other.comments_[comment]; - if ( otherComment.comment_ ) - comments_[comment].setComment( otherComment.comment_ ); - } - } -} - - -Value::~Value() -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if ( allocated_ ) - valueAllocator()->releaseStringValue( value_.string_ ); - break; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - delete value_.map_; - break; -#else - case arrayValue: - arrayAllocator()->destructArray( value_.array_ ); - break; - case objectValue: - mapAllocator()->destructMap( value_.map_ ); - break; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - - if ( comments_ ) - delete[] comments_; -} - -Value & -Value::operator=( const Value &other ) -{ - Value temp( other ); - swap( temp ); - return *this; -} - -void -Value::swap( Value &other ) -{ - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; - std::swap( value_, other.value_ ); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2; -} - -ValueType -Value::type() const -{ - return type_; -} - - -int -Value::compare( const Value &other ) -{ - /* - int typeDelta = other.type_ - type_; - switch ( type_ ) - { - case nullValue: - - return other.type_ == type_; - case intValue: - if ( other.type_.isNumeric() - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue, - break; - case arrayValue: - delete value_.array_; - break; - case objectValue: - delete value_.map_; - default: - JSON_ASSERT_UNREACHABLE; - } - */ - return 0; // unreachable -} - -bool -Value::operator <( const Value &other ) const -{ - int typeDelta = type_ - other.type_; - if ( typeDelta ) - return typeDelta < 0 ? true : false; - switch ( type_ ) - { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: - return ( value_.string_ == 0 && other.value_.string_ ) - || ( other.value_.string_ - && value_.string_ - && strcmp( value_.string_, other.value_.string_ ) < 0 ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - { - int delta = int( value_.map_->size() - other.value_.map_->size() ); - if ( delta ) - return delta < 0; - return (*value_.map_) < (*other.value_.map_); - } -#else - case arrayValue: - return value_.array_->compare( *(other.value_.array_) ) < 0; - case objectValue: - return value_.map_->compare( *(other.value_.map_) ) < 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable -} - -bool -Value::operator <=( const Value &other ) const -{ - return !(other > *this); -} - -bool -Value::operator >=( const Value &other ) const -{ - return !(*this < other); -} - -bool -Value::operator >( const Value &other ) const -{ - return other < *this; -} - -bool -Value::operator ==( const Value &other ) const -{ - //if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if ( type_ != temp ) - return false; - switch ( type_ ) - { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: - return ( value_.string_ == other.value_.string_ ) - || ( other.value_.string_ - && value_.string_ - && strcmp( value_.string_, other.value_.string_ ) == 0 ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() - && (*value_.map_) == (*other.value_.map_); -#else - case arrayValue: - return value_.array_->compare( *(other.value_.array_) ) == 0; - case objectValue: - return value_.map_->compare( *(other.value_.map_) ) == 0; -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable -} - -bool -Value::operator !=( const Value &other ) const -{ - return !( *this == other ); -} - -const char * -Value::asCString() const -{ - JSON_ASSERT( type_ == stringValue ); - return value_.string_; -} - - -std::string -Value::asString() const -{ - switch ( type_ ) - { - case nullValue: - return ""; - case stringValue: - return value_.string_ ? value_.string_ : ""; - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - case uintValue: - case realValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return ""; // unreachable -} - -# ifdef JSON_USE_CPPTL -CppTL::ConstString -Value::asConstString() const -{ - return CppTL::ConstString( asString().c_str() ); -} -# endif - -Value::Int -Value::asInt() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - return value_.int_; - case uintValue: - JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" ); - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" ); - return Int( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - -Value::UInt -Value::asUInt() const -{ - switch ( type_ ) - { - case nullValue: - return 0; - case intValue: - JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" ); - return value_.int_; - case uintValue: - return value_.uint_; - case realValue: - JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" ); - return UInt( value_.real_ ); - case booleanValue: - return value_.bool_ ? 1 : 0; - case stringValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - -double -Value::asDouble() const -{ - switch ( type_ ) - { - case nullValue: - return 0.0; - case intValue: - return value_.int_; - case uintValue: - return value_.uint_; - case realValue: - return value_.real_; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - case stringValue: - case arrayValue: - case objectValue: - JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" ); - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - -bool -Value::asBool() const -{ - switch ( type_ ) - { - case nullValue: - return false; - case intValue: - case uintValue: - return value_.int_ != 0; - case realValue: - return value_.real_ != 0.0; - case booleanValue: - return value_.bool_; - case stringValue: - return value_.string_ && value_.string_[0] != 0; - case arrayValue: - case objectValue: - return value_.map_->size() != 0; - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable; -} - - -bool -Value::isConvertibleTo( ValueType other ) const -{ - switch ( type_ ) - { - case nullValue: - return true; - case intValue: - return ( other == nullValue && value_.int_ == 0 ) - || other == intValue - || ( other == uintValue && value_.int_ >= 0 ) - || other == realValue - || other == stringValue - || other == booleanValue; - case uintValue: - return ( other == nullValue && value_.uint_ == 0 ) - || ( other == intValue && value_.uint_ <= (unsigned)maxInt ) - || other == uintValue - || other == realValue - || other == stringValue - || other == booleanValue; - case realValue: - return ( other == nullValue && value_.real_ == 0.0 ) - || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt ) - || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt ) - || other == realValue - || other == stringValue - || other == booleanValue; - case booleanValue: - return ( other == nullValue && value_.bool_ == false ) - || other == intValue - || other == uintValue - || other == realValue - || other == stringValue - || other == booleanValue; - case stringValue: - return other == stringValue - || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) ); - case arrayValue: - return other == arrayValue - || ( other == nullValue && value_.map_->size() == 0 ); - case objectValue: - return other == objectValue - || ( other == nullValue && value_.map_->size() == 0 ); - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable; -} - - -/// Number of values in array or object -Value::UInt -Value::size() const -{ - switch ( type_ ) - { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: // size of the array is highest index + 1 - if ( !value_.map_->empty() ) - { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index()+1; - } - return 0; - case objectValue: - return Int( value_.map_->size() ); -#else - case arrayValue: - return Int( value_.array_->size() ); - case objectValue: - return Int( value_.map_->size() ); -#endif - default: - JSON_ASSERT_UNREACHABLE; - } - return 0; // unreachable; -} - - -bool -Value::empty() const -{ - if ( isNull() || isArray() || isObject() ) - return size() == 0u; - else - return false; -} - - -bool -Value::operator!() const -{ - return isNull(); -} - - -void -Value::clear() -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue ); - - switch ( type_ ) - { -#ifndef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - case objectValue: - value_.map_->clear(); - break; -#else - case arrayValue: - value_.array_->clear(); - break; - case objectValue: - value_.map_->clear(); - break; -#endif - default: - break; - } -} - -void -Value::resize( UInt newSize ) -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - *this = Value( arrayValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - UInt oldSize = size(); - if ( newSize == 0 ) - clear(); - else if ( newSize > oldSize ) - (*this)[ newSize - 1 ]; - else - { - for ( UInt index = newSize; index < oldSize; ++index ) - value_.map_->erase( index ); - assert( size() == newSize ); - } -#else - value_.array_->resize( newSize ); -#endif -} - - -Value & -Value::operator[]( UInt index ) -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - *this = Value( arrayValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key( index ); - ObjectValues::iterator it = value_.map_->lower_bound( key ); - if ( it != value_.map_->end() && (*it).first == key ) - return (*it).second; - - ObjectValues::value_type defaultValue( key, null ); - it = value_.map_->insert( it, defaultValue ); - return (*it).second; -#else - return value_.array_->resolveReference( index ); -#endif -} - - -const Value & -Value::operator[]( UInt index ) const -{ - JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString key( index ); - ObjectValues::const_iterator it = value_.map_->find( key ); - if ( it == value_.map_->end() ) - return null; - return (*it).second; -#else - Value *value = value_.array_->find( index ); - return value ? *value : null; -#endif -} - - -Value & -Value::operator[]( const char *key ) -{ - return resolveReference( key, false ); -} - - -Value & -Value::resolveReference( const char *key, - bool isStatic ) -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - *this = Value( objectValue ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, isStatic ? CZString::noDuplication - : CZString::duplicateOnCopy ); - ObjectValues::iterator it = value_.map_->lower_bound( actualKey ); - if ( it != value_.map_->end() && (*it).first == actualKey ) - return (*it).second; - - ObjectValues::value_type defaultValue( actualKey, null ); - it = value_.map_->insert( it, defaultValue ); - Value &value = (*it).second; - return value; -#else - return value_.map_->resolveReference( key, isStatic ); -#endif -} - - -Value -Value::get( UInt index, - const Value &defaultValue ) const -{ - const Value *value = &((*this)[index]); - return value == &null ? defaultValue : *value; -} - - -bool -Value::isValidIndex( UInt index ) const -{ - return index < size(); -} - - - -const Value & -Value::operator[]( const char *key ) const -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, CZString::noDuplication ); - ObjectValues::const_iterator it = value_.map_->find( actualKey ); - if ( it == value_.map_->end() ) - return null; - return (*it).second; -#else - const Value *value = value_.map_->find( key ); - return value ? *value : null; -#endif -} - - -Value & -Value::operator[]( const std::string &key ) -{ - return (*this)[ key.c_str() ]; -} - - -const Value & -Value::operator[]( const std::string &key ) const -{ - return (*this)[ key.c_str() ]; -} - -Value & -Value::operator[]( const StaticString &key ) -{ - return resolveReference( key, true ); -} - - -# ifdef JSON_USE_CPPTL -Value & -Value::operator[]( const CppTL::ConstString &key ) -{ - return (*this)[ key.c_str() ]; -} - - -const Value & -Value::operator[]( const CppTL::ConstString &key ) const -{ - return (*this)[ key.c_str() ]; -} -# endif - - -Value & -Value::append( const Value &value ) -{ - return (*this)[size()] = value; -} - - -Value -Value::get( const char *key, - const Value &defaultValue ) const -{ - const Value *value = &((*this)[key]); - return value == &null ? defaultValue : *value; -} - - -Value -Value::get( const std::string &key, - const Value &defaultValue ) const -{ - return get( key.c_str(), defaultValue ); -} - -Value -Value::removeMember( const char* key ) -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return null; -#ifndef JSON_VALUE_USE_INTERNAL_MAP - CZString actualKey( key, CZString::noDuplication ); - ObjectValues::iterator it = value_.map_->find( actualKey ); - if ( it == value_.map_->end() ) - return null; - Value old(it->second); - value_.map_->erase(it); - return old; -#else - Value *value = value_.map_->find( key ); - if (value){ - Value old(*value); - value_.map_.remove( key ); - return old; - } else { - return null; - } -#endif -} - -Value -Value::removeMember( const std::string &key ) -{ - return removeMember( key.c_str() ); -} - -# ifdef JSON_USE_CPPTL -Value -Value::get( const CppTL::ConstString &key, - const Value &defaultValue ) const -{ - return get( key.c_str(), defaultValue ); -} -# endif - -bool -Value::isMember( const char *key ) const -{ - const Value *value = &((*this)[key]); - return value != &null; -} - - -bool -Value::isMember( const std::string &key ) const -{ - return isMember( key.c_str() ); -} - - -# ifdef JSON_USE_CPPTL -bool -Value::isMember( const CppTL::ConstString &key ) const -{ - return isMember( key.c_str() ); -} -#endif - -Value::Members -Value::getMemberNames() const -{ - JSON_ASSERT( type_ == nullValue || type_ == objectValue ); - if ( type_ == nullValue ) - return Value::Members(); - Members members; - members.reserve( value_.map_->size() ); -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for ( ; it != itEnd; ++it ) - members.push_back( std::string( (*it).first.c_str() ) ); -#else - ValueInternalMap::IteratorState it; - ValueInternalMap::IteratorState itEnd; - value_.map_->makeBeginIterator( it ); - value_.map_->makeEndIterator( itEnd ); - for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) ) - members.push_back( std::string( ValueInternalMap::key( it ) ) ); -#endif - return members; -} -// -//# ifdef JSON_USE_CPPTL -//EnumMemberNames -//Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -//EnumValues -//Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type<const Value &>() ); -// return EnumValues(); -//} -// -//# endif - - -bool -Value::isNull() const -{ - return type_ == nullValue; -} - - -bool -Value::isBool() const -{ - return type_ == booleanValue; -} - - -bool -Value::isInt() const -{ - return type_ == intValue; -} - - -bool -Value::isUInt() const -{ - return type_ == uintValue; -} - - -bool -Value::isIntegral() const -{ - return type_ == intValue - || type_ == uintValue - || type_ == booleanValue; -} - - -bool -Value::isDouble() const -{ - return type_ == realValue; -} - - -bool -Value::isNumeric() const -{ - return isIntegral() || isDouble(); -} - - -bool -Value::isString() const -{ - return type_ == stringValue; -} - - -bool -Value::isArray() const -{ - return type_ == nullValue || type_ == arrayValue; -} - - -bool -Value::isObject() const -{ - return type_ == nullValue || type_ == objectValue; -} - - -void -Value::setComment( const char *comment, - CommentPlacement placement ) -{ - if ( !comments_ ) - comments_ = new CommentInfo[numberOfCommentPlacement]; - comments_[placement].setComment( comment ); -} - - -void -Value::setComment( const std::string &comment, - CommentPlacement placement ) -{ - setComment( comment.c_str(), placement ); -} - - -bool -Value::hasComment( CommentPlacement placement ) const -{ - return comments_ != 0 && comments_[placement].comment_ != 0; -} - -std::string -Value::getComment( CommentPlacement placement ) const -{ - if ( hasComment(placement) ) - return comments_[placement].comment_; - return ""; -} - - -std::string -Value::toStyledString() const -{ - StyledWriter writer; - return writer.write( *this ); -} - - -Value::const_iterator -Value::begin() const -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator( it ); - return const_iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator( it ); - return const_iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return const_iterator( value_.map_->begin() ); - break; -#endif - default: - break; - } - return const_iterator(); -} - -Value::const_iterator -Value::end() const -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator( it ); - return const_iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator( it ); - return const_iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return const_iterator( value_.map_->end() ); - break; -#endif - default: - break; - } - return const_iterator(); -} - - -Value::iterator -Value::begin() -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeBeginIterator( it ); - return iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeBeginIterator( it ); - return iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return iterator( value_.map_->begin() ); - break; -#endif - default: - break; - } - return iterator(); -} - -Value::iterator -Value::end() -{ - switch ( type_ ) - { -#ifdef JSON_VALUE_USE_INTERNAL_MAP - case arrayValue: - if ( value_.array_ ) - { - ValueInternalArray::IteratorState it; - value_.array_->makeEndIterator( it ); - return iterator( it ); - } - break; - case objectValue: - if ( value_.map_ ) - { - ValueInternalMap::IteratorState it; - value_.map_->makeEndIterator( it ); - return iterator( it ); - } - break; -#else - case arrayValue: - case objectValue: - if ( value_.map_ ) - return iterator( value_.map_->end() ); - break; -#endif - default: - break; - } - return iterator(); -} - - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() - : kind_( kindNone ) -{ -} - - -PathArgument::PathArgument( Value::UInt index ) - : index_( index ) - , kind_( kindIndex ) -{ -} - - -PathArgument::PathArgument( const char *key ) - : key_( key ) - , kind_( kindKey ) -{ -} - - -PathArgument::PathArgument( const std::string &key ) - : key_( key.c_str() ) - , kind_( kindKey ) -{ -} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path( const std::string &path, - const PathArgument &a1, - const PathArgument &a2, - const PathArgument &a3, - const PathArgument &a4, - const PathArgument &a5 ) -{ - InArgs in; - in.push_back( &a1 ); - in.push_back( &a2 ); - in.push_back( &a3 ); - in.push_back( &a4 ); - in.push_back( &a5 ); - makePath( path, in ); -} - - -void -Path::makePath( const std::string &path, - const InArgs &in ) -{ - const char *current = path.c_str(); - const char *end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); - while ( current != end ) - { - if ( *current == '[' ) - { - ++current; - if ( *current == '%' ) - addPathInArg( path, in, itInArg, PathArgument::kindIndex ); - else - { - Value::UInt index = 0; - for ( ; current != end && *current >= '0' && *current <= '9'; ++current ) - index = index * 10 + Value::UInt(*current - '0'); - args_.push_back( index ); - } - if ( current == end || *current++ != ']' ) - invalidPath( path, int(current - path.c_str()) ); - } - else if ( *current == '%' ) - { - addPathInArg( path, in, itInArg, PathArgument::kindKey ); - ++current; - } - else if ( *current == '.' ) - { - ++current; - } - else - { - const char *beginName = current; - while ( current != end && !strchr( "[.", *current ) ) - ++current; - args_.push_back( std::string( beginName, current ) ); - } - } -} - - -void -Path::addPathInArg( const std::string &path, - const InArgs &in, - InArgs::const_iterator &itInArg, - PathArgument::Kind kind ) -{ - if ( itInArg == in.end() ) - { - // Error: missing argument %d - } - else if ( (*itInArg)->kind_ != kind ) - { - // Error: bad argument type - } - else - { - args_.push_back( **itInArg ); - } -} - - -void -Path::invalidPath( const std::string &path, - int location ) -{ - // Error: invalid path. -} - - -const Value & -Path::resolve( const Value &root ) const -{ - const Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) - { - // Error: unable to resolve path (array value expected at position... - } - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - { - // Error: unable to resolve path (object value expected at position...) - } - node = &((*node)[arg.key_]); - if ( node == &Value::null ) - { - // Error: unable to resolve path (object has no member named '' at position...) - } - } - } - return *node; -} - - -Value -Path::resolve( const Value &root, - const Value &defaultValue ) const -{ - const Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) - return defaultValue; - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - return defaultValue; - node = &((*node)[arg.key_]); - if ( node == &Value::null ) - return defaultValue; - } - } - return *node; -} - - -Value & -Path::make( Value &root ) const -{ - Value *node = &root; - for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) - { - const PathArgument &arg = *it; - if ( arg.kind_ == PathArgument::kindIndex ) - { - if ( !node->isArray() ) - { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } - else if ( arg.kind_ == PathArgument::kindKey ) - { - if ( !node->isObject() ) - { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - - -} // namespace Json diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_valueiterator.inl b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_valueiterator.inl deleted file mode 100644 index 736e260e..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_valueiterator.inl +++ /dev/null @@ -1,292 +0,0 @@ -// included by json_value.cpp -// everything is within Json namespace - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() -#ifndef JSON_VALUE_USE_INTERNAL_MAP - : current_() - , isNull_( true ) -{ -} -#else - : isArray_( true ) - , isNull_( true ) -{ - iterator_.array_ = ValueInternalArray::IteratorState(); -} -#endif - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t ) - : current_( current ) - , isNull_( false ) -{ -} -#else -ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) - : isArray_( true ) -{ - iterator_.array_ = state; -} - - -ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) - : isArray_( false ) -{ - iterator_.map_ = state; -} -#endif - -Value & -ValueIteratorBase::deref() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - return current_->second; -#else - if ( isArray_ ) - return ValueInternalArray::dereference( iterator_.array_ ); - return ValueInternalMap::value( iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::increment() -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - ++current_; -#else - if ( isArray_ ) - ValueInternalArray::increment( iterator_.array_ ); - ValueInternalMap::increment( iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::decrement() -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - --current_; -#else - if ( isArray_ ) - ValueInternalArray::decrement( iterator_.array_ ); - ValueInternalMap::decrement( iterator_.map_ ); -#endif -} - - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance( const SelfType &other ) const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP -# ifdef JSON_USE_CPPTL_SMALLMAP - return current_ - other.current_; -# else - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if ( isNull_ && other.isNull_ ) - { - return 0; - } - - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it ) - { - ++myDistance; - } - return myDistance; -# endif -#else - if ( isArray_ ) - return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); - return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); -#endif -} - - -bool -ValueIteratorBase::isEqual( const SelfType &other ) const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - if ( isNull_ ) - { - return other.isNull_; - } - return current_ == other.current_; -#else - if ( isArray_ ) - return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); - return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); -#endif -} - - -void -ValueIteratorBase::copy( const SelfType &other ) -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - current_ = other.current_; -#else - if ( isArray_ ) - iterator_.array_ = other.iterator_.array_; - iterator_.map_ = other.iterator_.map_; -#endif -} - - -Value -ValueIteratorBase::key() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if ( czstring.c_str() ) - { - if ( czstring.isStaticString() ) - return Value( StaticString( czstring.c_str() ) ); - return Value( czstring.c_str() ); - } - return Value( czstring.index() ); -#else - if ( isArray_ ) - return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); - bool isStatic; - const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic ); - if ( isStatic ) - return Value( StaticString( memberName ) ); - return Value( memberName ); -#endif -} - - -UInt -ValueIteratorBase::index() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const Value::CZString czstring = (*current_).first; - if ( !czstring.c_str() ) - return czstring.index(); - return Value::UInt( -1 ); -#else - if ( isArray_ ) - return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); - return Value::UInt( -1 ); -#endif -} - - -const char * -ValueIteratorBase::memberName() const -{ -#ifndef JSON_VALUE_USE_INTERNAL_MAP - const char *name = (*current_).first.c_str(); - return name ? name : ""; -#else - if ( !isArray_ ) - return ValueInternalMap::key( iterator_.map_ ); - return ""; -#endif -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() -{ -} - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t ) - : ValueIteratorBase( current ) -{ -} -#else -ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} - -ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} -#endif - -ValueConstIterator & -ValueConstIterator::operator =( const ValueIteratorBase &other ) -{ - copy( other ); - return *this; -} - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() -{ -} - - -#ifndef JSON_VALUE_USE_INTERNAL_MAP -ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t ) - : ValueIteratorBase( current ) -{ -} -#else -ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} - -ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) - : ValueIteratorBase( state ) -{ -} -#endif - -ValueIterator::ValueIterator( const ValueConstIterator &other ) - : ValueIteratorBase( other ) -{ -} - -ValueIterator::ValueIterator( const ValueIterator &other ) - : ValueIteratorBase( other ) -{ -} - -ValueIterator & -ValueIterator::operator =( const SelfType &other ) -{ - copy( other ); - return *this; -} diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_writer.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_writer.cpp deleted file mode 100644 index cdf4188f..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/json_writer.cpp +++ /dev/null @@ -1,829 +0,0 @@ -#include <json/writer.h> -#include <utility> -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include <iostream> -#include <sstream> -#include <iomanip> - -#if _MSC_VER >= 1400 // VC++ 8.0 -#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. -#endif - -namespace Json { - -static bool isControlCharacter(char ch) -{ - return ch > 0 && ch <= 0x1F; -} - -static bool containsControlCharacter( const char* str ) -{ - while ( *str ) - { - if ( isControlCharacter( *(str++) ) ) - return true; - } - return false; -} -static void uintToString( unsigned int value, - char *¤t ) -{ - *--current = 0; - do - { - *--current = (value % 10) + '0'; - value /= 10; - } - while ( value != 0 ); -} - -std::string valueToString( Int value ) -{ - char buffer[32]; - char *current = buffer + sizeof(buffer); - bool isNegative = value < 0; - if ( isNegative ) - value = -value; - uintToString( UInt(value), current ); - if ( isNegative ) - *--current = '-'; - assert( current >= buffer ); - return current; -} - - -std::string valueToString( UInt value ) -{ - char buffer[32]; - char *current = buffer + sizeof(buffer); - uintToString( value, current ); - assert( current >= buffer ); - return current; -} - -std::string valueToString( double value ) -{ - char buffer[32]; -#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. - sprintf_s(buffer, sizeof(buffer), "%#.16g", value); -#else - sprintf(buffer, "%#.16g", value); -#endif - char* ch = buffer + strlen(buffer) - 1; - if (*ch != '0') return buffer; // nothing to truncate, so save time - while(ch > buffer && *ch == '0'){ - --ch; - } - char* last_nonzero = ch; - while(ch >= buffer){ - switch(*ch){ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - --ch; - continue; - case '.': - // Truncate zeroes to save bytes in output, but keep one. - *(last_nonzero+2) = '\0'; - return buffer; - default: - return buffer; - } - } - return buffer; -} - - -std::string valueToString( bool value ) -{ - return value ? "true" : "false"; -} - -std::string valueToQuotedString( const char *value ) -{ - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value )) - return std::string("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to std::string is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL - std::string result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c=value; *c != 0; ++c) - { - switch(*c) - { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - //case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid </ - // sequence. - // Should add a flag to allow this compatibility mode and prevent this - // sequence from occurring. - default: - if ( isControlCharacter( *c ) ) - { - std::ostringstream oss; - oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c); - result += oss.str(); - } - else - { - result += *c; - } - break; - } - } - result += "\""; - return result; -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() -{ -} - - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - : yamlCompatiblityEnabled_( false ) -{ -} - - -void -FastWriter::enableYAMLCompatibility() -{ - yamlCompatiblityEnabled_ = true; -} - - -std::string -FastWriter::write( const Value &root ) -{ - document_ = ""; - writeValue( root ); - document_ += "\n"; - return document_; -} - - -void -FastWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - document_ += "null"; - break; - case intValue: - document_ += valueToString( value.asInt() ); - break; - case uintValue: - document_ += valueToString( value.asUInt() ); - break; - case realValue: - document_ += valueToString( value.asDouble() ); - break; - case stringValue: - document_ += valueToQuotedString( value.asCString() ); - break; - case booleanValue: - document_ += valueToString( value.asBool() ); - break; - case arrayValue: - { - document_ += "["; - int size = value.size(); - for ( int index =0; index < size; ++index ) - { - if ( index > 0 ) - document_ += ","; - writeValue( value[index] ); - } - document_ += "]"; - } - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - document_ += "{"; - for ( Value::Members::iterator it = members.begin(); - it != members.end(); - ++it ) - { - const std::string &name = *it; - if ( it != members.begin() ) - document_ += ","; - document_ += valueToQuotedString( name.c_str() ); - document_ += yamlCompatiblityEnabled_ ? ": " - : ":"; - writeValue( value[name] ); - } - document_ += "}"; - } - break; - } -} - - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() - : rightMargin_( 74 ) - , indentSize_( 3 ) -{ -} - - -std::string -StyledWriter::write( const Value &root ) -{ - document_ = ""; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue( root ); - writeValue( root ); - writeCommentAfterValueOnSameLine( root ); - document_ += "\n"; - return document_; -} - - -void -StyledWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - pushValue( "null" ); - break; - case intValue: - pushValue( valueToString( value.asInt() ) ); - break; - case uintValue: - pushValue( valueToString( value.asUInt() ) ); - break; - case realValue: - pushValue( valueToString( value.asDouble() ) ); - break; - case stringValue: - pushValue( valueToQuotedString( value.asCString() ) ); - break; - case booleanValue: - pushValue( valueToString( value.asBool() ) ); - break; - case arrayValue: - writeArrayValue( value); - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - if ( members.empty() ) - pushValue( "{}" ); - else - { - writeWithIndent( "{" ); - indent(); - Value::Members::iterator it = members.begin(); - while ( true ) - { - const std::string &name = *it; - const Value &childValue = value[name]; - writeCommentBeforeValue( childValue ); - writeWithIndent( valueToQuotedString( name.c_str() ) ); - document_ += " : "; - writeValue( childValue ); - if ( ++it == members.end() ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "}" ); - } - } - break; - } -} - - -void -StyledWriter::writeArrayValue( const Value &value ) -{ - unsigned size = value.size(); - if ( size == 0 ) - pushValue( "[]" ); - else - { - bool isArrayMultiLine = isMultineArray( value ); - if ( isArrayMultiLine ) - { - writeWithIndent( "[" ); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index =0; - while ( true ) - { - const Value &childValue = value[index]; - writeCommentBeforeValue( childValue ); - if ( hasChildValue ) - writeWithIndent( childValues_[index] ); - else - { - writeIndent(); - writeValue( childValue ); - } - if ( ++index == size ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - document_ += ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "]" ); - } - else // output on a single line - { - assert( childValues_.size() == size ); - document_ += "[ "; - for ( unsigned index =0; index < size; ++index ) - { - if ( index > 0 ) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - - -bool -StyledWriter::isMultineArray( const Value &value ) -{ - int size = value.size(); - bool isMultiLine = size*3 >= rightMargin_ ; - childValues_.clear(); - for ( int index =0; index < size && !isMultiLine; ++index ) - { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || - ( (childValue.isArray() || childValue.isObject()) && - childValue.size() > 0 ); - } - if ( !isMultiLine ) // check if line length > max line length - { - childValues_.reserve( size ); - addChildValues_ = true; - int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' - for ( int index =0; index < size && !isMultiLine; ++index ) - { - writeValue( value[index] ); - lineLength += int( childValues_[index].length() ); - isMultiLine = isMultiLine && hasCommentForValue( value[index] ); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - - -void -StyledWriter::pushValue( const std::string &value ) -{ - if ( addChildValues_ ) - childValues_.push_back( value ); - else - document_ += value; -} - - -void -StyledWriter::writeIndent() -{ - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - - -void -StyledWriter::writeWithIndent( const std::string &value ) -{ - writeIndent(); - document_ += value; -} - - -void -StyledWriter::indent() -{ - indentString_ += std::string( indentSize_, ' ' ); -} - - -void -StyledWriter::unindent() -{ - assert( int(indentString_.size()) >= indentSize_ ); - indentString_.resize( indentString_.size() - indentSize_ ); -} - - -void -StyledWriter::writeCommentBeforeValue( const Value &root ) -{ - if ( !root.hasComment( commentBefore ) ) - return; - document_ += normalizeEOL( root.getComment( commentBefore ) ); - document_ += "\n"; -} - - -void -StyledWriter::writeCommentAfterValueOnSameLine( const Value &root ) -{ - if ( root.hasComment( commentAfterOnSameLine ) ) - document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); - - if ( root.hasComment( commentAfter ) ) - { - document_ += "\n"; - document_ += normalizeEOL( root.getComment( commentAfter ) ); - document_ += "\n"; - } -} - - -bool -StyledWriter::hasCommentForValue( const Value &value ) -{ - return value.hasComment( commentBefore ) - || value.hasComment( commentAfterOnSameLine ) - || value.hasComment( commentAfter ); -} - - -std::string -StyledWriter::normalizeEOL( const std::string &text ) -{ - std::string normalized; - normalized.reserve( text.length() ); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while ( current != end ) - { - char c = *current++; - if ( c == '\r' ) // mac or dos EOL - { - if ( *current == '\n' ) // convert dos EOL - ++current; - normalized += '\n'; - } - else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter( std::string indentation ) - : document_(NULL) - , rightMargin_( 74 ) - , indentation_( indentation ) -{ -} - - -void -StyledStreamWriter::write( std::ostream &out, const Value &root ) -{ - document_ = &out; - addChildValues_ = false; - indentString_ = ""; - writeCommentBeforeValue( root ); - writeValue( root ); - writeCommentAfterValueOnSameLine( root ); - *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. -} - - -void -StyledStreamWriter::writeValue( const Value &value ) -{ - switch ( value.type() ) - { - case nullValue: - pushValue( "null" ); - break; - case intValue: - pushValue( valueToString( value.asInt() ) ); - break; - case uintValue: - pushValue( valueToString( value.asUInt() ) ); - break; - case realValue: - pushValue( valueToString( value.asDouble() ) ); - break; - case stringValue: - pushValue( valueToQuotedString( value.asCString() ) ); - break; - case booleanValue: - pushValue( valueToString( value.asBool() ) ); - break; - case arrayValue: - writeArrayValue( value); - break; - case objectValue: - { - Value::Members members( value.getMemberNames() ); - if ( members.empty() ) - pushValue( "{}" ); - else - { - writeWithIndent( "{" ); - indent(); - Value::Members::iterator it = members.begin(); - while ( true ) - { - const std::string &name = *it; - const Value &childValue = value[name]; - writeCommentBeforeValue( childValue ); - writeWithIndent( valueToQuotedString( name.c_str() ) ); - *document_ << " : "; - writeValue( childValue ); - if ( ++it == members.end() ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "}" ); - } - } - break; - } -} - - -void -StyledStreamWriter::writeArrayValue( const Value &value ) -{ - unsigned size = value.size(); - if ( size == 0 ) - pushValue( "[]" ); - else - { - bool isArrayMultiLine = isMultineArray( value ); - if ( isArrayMultiLine ) - { - writeWithIndent( "[" ); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index =0; - while ( true ) - { - const Value &childValue = value[index]; - writeCommentBeforeValue( childValue ); - if ( hasChildValue ) - writeWithIndent( childValues_[index] ); - else - { - writeIndent(); - writeValue( childValue ); - } - if ( ++index == size ) - { - writeCommentAfterValueOnSameLine( childValue ); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine( childValue ); - } - unindent(); - writeWithIndent( "]" ); - } - else // output on a single line - { - assert( childValues_.size() == size ); - *document_ << "[ "; - for ( unsigned index =0; index < size; ++index ) - { - if ( index > 0 ) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - - -bool -StyledStreamWriter::isMultineArray( const Value &value ) -{ - int size = value.size(); - bool isMultiLine = size*3 >= rightMargin_ ; - childValues_.clear(); - for ( int index =0; index < size && !isMultiLine; ++index ) - { - const Value &childValue = value[index]; - isMultiLine = isMultiLine || - ( (childValue.isArray() || childValue.isObject()) && - childValue.size() > 0 ); - } - if ( !isMultiLine ) // check if line length > max line length - { - childValues_.reserve( size ); - addChildValues_ = true; - int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' - for ( int index =0; index < size && !isMultiLine; ++index ) - { - writeValue( value[index] ); - lineLength += int( childValues_[index].length() ); - isMultiLine = isMultiLine && hasCommentForValue( value[index] ); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - - -void -StyledStreamWriter::pushValue( const std::string &value ) -{ - if ( addChildValues_ ) - childValues_.push_back( value ); - else - *document_ << value; -} - - -void -StyledStreamWriter::writeIndent() -{ - /* - Some comments in this method would have been nice. ;-) - - if ( !document_.empty() ) - { - char last = document_[document_.length()-1]; - if ( last == ' ' ) // already indented - return; - if ( last != '\n' ) // Comments may add new-line - *document_ << '\n'; - } - */ - *document_ << '\n' << indentString_; -} - - -void -StyledStreamWriter::writeWithIndent( const std::string &value ) -{ - writeIndent(); - *document_ << value; -} - - -void -StyledStreamWriter::indent() -{ - indentString_ += indentation_; -} - - -void -StyledStreamWriter::unindent() -{ - assert( indentString_.size() >= indentation_.size() ); - indentString_.resize( indentString_.size() - indentation_.size() ); -} - - -void -StyledStreamWriter::writeCommentBeforeValue( const Value &root ) -{ - if ( !root.hasComment( commentBefore ) ) - return; - *document_ << normalizeEOL( root.getComment( commentBefore ) ); - *document_ << "\n"; -} - - -void -StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root ) -{ - if ( root.hasComment( commentAfterOnSameLine ) ) - *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); - - if ( root.hasComment( commentAfter ) ) - { - *document_ << "\n"; - *document_ << normalizeEOL( root.getComment( commentAfter ) ); - *document_ << "\n"; - } -} - - -bool -StyledStreamWriter::hasCommentForValue( const Value &value ) -{ - return value.hasComment( commentBefore ) - || value.hasComment( commentAfterOnSameLine ) - || value.hasComment( commentAfter ); -} - - -std::string -StyledStreamWriter::normalizeEOL( const std::string &text ) -{ - std::string normalized; - normalized.reserve( text.length() ); - const char *begin = text.c_str(); - const char *end = begin + text.length(); - const char *current = begin; - while ( current != end ) - { - char c = *current++; - if ( c == '\r' ) // mac or dos EOL - { - if ( *current == '\n' ) // convert dos EOL - ++current; - normalized += '\n'; - } - else // handle unix EOL & other char - normalized += c; - } - return normalized; -} - - -std::ostream& operator<<( std::ostream &sout, const Value &root ) -{ - Json::StyledStreamWriter writer; - writer.write(sout, root); - return sout; -} - - -} // namespace Json diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/plugin.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/plugin.cpp deleted file mode 100644 index 6906275e..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/plugin.cpp +++ /dev/null @@ -1,320 +0,0 @@ -#include "plugin.h" -#include "tokenizer.h" - -#ifdef _WINDOWS -#include <windows.h> -BOOL APIENTRY DllMain( HANDLE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved ) -{ - return TRUE; -} -#else -#include <errno.h> -#include <string.h> - -extern int errno; -#endif - -SendPluginEv SendPluginEvent; - -string g_GetSysErrMsg( void ) -{ - string strError = "Unknown"; - // Problem loading -#ifdef _WINDOWS - int nErrorCode = GetLastError(); - LPTSTR s; - if ( ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, nErrorCode, 0, ( LPTSTR ) &s, 0, NULL ) ) - { - strError = s; - } - else - { - char szBuf[ 20 ]; - _snprintf_s( szBuf, _countof(szBuf), 19, "%d", nErrorCode ); - strError = szBuf; - } -#else - char szError[80]; - if ( strerror_r( errno, szError, sizeof(szError) ) ) - { - strError = "no description found"; - } - else - { - strError = szError; - } -#endif - return strError; -} - -void g_sleep( unsigned int mseconds ) -{ -#ifdef _WINDOWS - Sleep( mseconds ); -#else - usleep( mseconds * 1000 ); -#endif -} - -string& g_trim( string& str ) -{ - // Whitespace characters - char whspc[] = " \t\r\n\v\f"; - - // Whack off first part - size_t pos = str.find_first_not_of( whspc ); - - if ( pos != string::npos ) - str.replace( 0, pos, "" ); - - // Whack off trailing stuff - pos = str.find_last_not_of( whspc ); - - if ( pos != string::npos ) - str.replace( pos + 1, str.length() - pos, "" ); - - return str; -} - -void g_tokenize( const string& str, const string& delimiters, vector<string>& tokens ) -{ - tokenize( str, tokens, delimiters ); -} - -char* SetEventFunc( SendPluginEv funcPtr ) -{ - static char * szObjList = onGetObjList(); - SendPluginEvent = funcPtr; - return szObjList; -} - - -const int nMAXSIZE = 512; -char* g_pszRetVal = NULL; - -//----------------------------------------------------------- -// Map from an object Id to an object instance -//----------------------------------------------------------- -typedef std::map<string, JSExt*> StringToJExt_T; - -//----------------------------------------------------------- -// Map from a browser context to an id mapping -//----------------------------------------------------------- -typedef std::map<void*, StringToJExt_T*> VoidToMap_T; - -VoidToMap_T g_context2Map; - -class GlobalSharedModule -{ - -public: - GlobalSharedModule( void ) - { - g_pszRetVal = new char[ nMAXSIZE ]; - } - - ~GlobalSharedModule() - { - delete [] g_pszRetVal; - - VoidToMap_T::iterator posMaps; - - for ( posMaps = g_context2Map.begin(); posMaps != g_context2Map.end(); ++posMaps ) - { - StringToJExt_T& id2Obj = *posMaps->second; - StringToJExt_T::iterator posMap; - - for ( posMap = id2Obj.begin(); posMap != id2Obj.end(); ++posMap ) - { - JSExt* pJSExt = posMap->second; - - if ( pJSExt->CanDelete() ) - { - delete pJSExt; - } - } - - id2Obj.erase( id2Obj.begin(), id2Obj.end() ); - } - - g_context2Map.erase( g_context2Map.begin(), g_context2Map.end() ); - } -}; - -GlobalSharedModule g_sharedModule; - -char* g_str2global( const string& strRetVal ) -{ - int nLen = strRetVal.size(); - - if ( nLen >= nMAXSIZE ) - { - delete [] g_pszRetVal; - g_pszRetVal = new char[ nLen + 1 ]; - } - - else - { - // To minimaize the number of memory reallocations, the assumption - // is that in most times this will be the case - delete [] g_pszRetVal; - g_pszRetVal = new char[ nMAXSIZE ]; - } - - strcpy( g_pszRetVal, strRetVal.c_str() ); - return g_pszRetVal; -} - -bool g_unregisterObject( const string& strObjId, void* pContext ) -{ - // Called by the plugin extension implementation - // if the extension handles the deletion of its object - - StringToJExt_T * pID2Obj = NULL; - - VoidToMap_T::iterator iter = g_context2Map.find( pContext ); - - if ( iter != g_context2Map.end() ) - { - pID2Obj = iter->second; - } - else - { - return false; - } - - StringToJExt_T& mapID2Obj = *pID2Obj; - - StringToJExt_T::iterator r = mapID2Obj.find( strObjId ); - - if ( r == mapID2Obj.end() ) - { - return false; - } - - mapID2Obj.erase( strObjId ); - return true; -} - -char* InvokeFunction( const char* szCommand, void* pContext ) -{ - StringToJExt_T * pID2Obj = NULL; - - VoidToMap_T::iterator iter = g_context2Map.find( pContext ); - - if ( iter != g_context2Map.end() ) - { - pID2Obj = iter->second; - } - else - { - pID2Obj = new StringToJExt_T; - g_context2Map[ pContext ] = pID2Obj; - } - - StringToJExt_T& mapID2Obj = *pID2Obj; - - string strFullCommand = szCommand; - vector<string> arParams; - g_tokenize( strFullCommand, " ", arParams ); - string strCommand = arParams[ 0 ]; - string strRetVal = szERROR; - - if ( strCommand == szCREATE ) - { - string strClassName = arParams[ 1 ]; - string strObjId = arParams[ 2 ]; - - StringToJExt_T::iterator r = mapID2Obj.find( strObjId ); - - if ( r != mapID2Obj.end() ) - { - strRetVal += strObjId; - strRetVal += " :Object already exists."; - return g_str2global( strRetVal ); - } - - JSExt* pJSExt = onCreateObject( strClassName, strObjId ); - - if ( pJSExt == NULL ) - { - strRetVal += strObjId; - strRetVal += " :Unknown object type "; - strRetVal += strClassName; - return g_str2global( strRetVal ); - } - - pJSExt->m_pContext = pContext; - mapID2Obj[ strObjId ] = pJSExt; - - strRetVal = szOK; - strRetVal += strObjId; - return g_str2global( strRetVal ); - } - else - if ( strCommand == szINVOKE ) - { - string strObjId = arParams[ 1 ]; - string strMethod = arParams[ 2 ]; - - StringToJExt_T::iterator r = mapID2Obj.find( strObjId ); - - if ( r == mapID2Obj.end() ) - { - strRetVal += strObjId; - strRetVal += " :No object found for id."; - return g_str2global( strRetVal ); - } - - JSExt* pJSExt = r->second; - - size_t nLoc = strFullCommand.find( strObjId ); - - if ( nLoc == string::npos ) - { - strRetVal += strObjId; - strRetVal += " :Internal InvokeMethod error."; - return g_str2global( strRetVal ); - } - - if ( strMethod == szDISPOSE ) - { - StringToJExt_T::iterator r = mapID2Obj.find( strObjId ); - - if ( r == mapID2Obj.end() ) - { - strRetVal = szERROR; - strRetVal += strObjId; - return g_str2global( strRetVal ); - } - - JSExt * pJSExt = mapID2Obj[ strObjId ]; - - if ( pJSExt->CanDelete() ) - { - delete pJSExt; - } - - mapID2Obj.erase( strObjId ); - strRetVal = szOK; - strRetVal += strObjId; - return g_str2global( strRetVal ); - } - - size_t nSuffixLoc = nLoc + strObjId.size(); - string strInvoke = strFullCommand.substr( nSuffixLoc ); - strInvoke = g_trim( strInvoke ); - strRetVal = pJSExt->InvokeMethod( strInvoke ); - return g_str2global( strRetVal ); - } - - strRetVal += " :Unknown command "; - strRetVal += strCommand; - return g_str2global( strRetVal ); -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/plugin.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/plugin.h deleted file mode 100644 index 4ef71169..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/plugin.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _PLUGIN_H -#define _PLUGIN_H - -#include <map> -#include <string> -#include <vector> -#include <unistd.h> -//#include "tokenizer.h" - -using namespace std; - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%% Functions exported by this DLL -//%% Should always be only SetEventFunc and InvokeFunction -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// g++ requires extern "C" otherwise the names of SetEventFunc and InvokeFunction -// are mangled C++ style. MS Visual Studio doesn't seem to care though. -extern "C" -{ - typedef void (*SendPluginEv)( const char* szEvent, void* pContext ); - char* SetEventFunc(SendPluginEv funcPtr); - char* InvokeFunction( const char* szCommand, void* pContext ); -} - -// JNEXT Framework function of the form: -// typedef void (*SendPluginEv)( const char* szEvent ); -// used to notify JavaScript of an asynchronous event -extern SendPluginEv SendPluginEvent; - -///////////////////////////////////////////////////////////////////////// -// Constants and methods common to all JNEXT extensions types -///////////////////////////////////////////////////////////////////////// -#define szERROR "Error " -#define szOK "Ok " - -#define szDISPOSE "Dispose" -#define szINVOKE "InvokeMethod" -#define szCREATE "CreateObj" - -///////////////////////////////////////////////////////////////////////// -// Utility functions -///////////////////////////////////////////////////////////////////////// -string& g_trim( string& str ); -void g_tokenize(const string& str,const string& delimiters, vector<string>& tokens); -char* g_str2static( const string& strRetVal ); -void g_sleep( unsigned int mseconds ); -bool g_unregisterObject( const string& strObjId, void* pContext ); - - -///////////////////////////////////////////////////////////////////////// -// Abstract extension object -///////////////////////////////////////////////////////////////////////// -class JSExt -{ -public: - virtual ~JSExt() {}; - virtual string InvokeMethod( const string& strCommand ) = 0; - virtual bool CanDelete( void ) = 0; - virtual void TryDelete( void ) {} -public: - void* m_pContext; -}; - -///////////////////////////////////////////////////////////////////////// -// Callback functions to be implemented by the plugin implementation -///////////////////////////////////////////////////////////////////////// -extern char* onGetObjList( void ); -extern JSExt* onCreateObject( const string& strClassName, const string& strObjId ); - -#endif diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/tokenizer.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/tokenizer.cpp deleted file mode 100644 index 4a39573b..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/tokenizer.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/************************************************************************ -The zlib/libpng License - -Copyright (c) 2006 Joerg Wiedenmann - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; -you must not claim that you wrote the original software. -If you use this software in a product, an acknowledgment -in the product documentation would be appreciated but is -not required. - -2. Altered source versions must be plainly marked as such, -and must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source distribution. - -***********************************************************************/ - -/******************************************************************** - created: 2006-01-28 - filename: tokenizer.cpp - author: Jörg Wiedenmann - - purpose: A tokenizer function which provides a very - customizable way of breaking up strings. - - history: 2006-01-28, Original version - 2006-03-04, Fixed a small parsing bug, thanks Elias. -*********************************************************************/ - -#include "tokenizer.h" - -using namespace std; - -void tokenize ( const string& str, vector<string>& result, - const string& delimiters, const string& delimiters_preserve, - const string& quote, const string& esc ) -{ - // clear the vector - if ( false == result.empty() ) - { - result.clear(); - } - - string::size_type pos = 0; // the current position (char) in the string - char ch = 0; // buffer for the current character - char delimiter = 0; // the buffer for the delimiter char which - // will be added to the tokens if the delimiter - // is preserved - char current_quote = 0; // the char of the current open quote - bool quoted = false; // indicator if there is an open quote - string token; // string buffer for the token - bool token_complete = false; // indicates if the current token is - // read to be added to the result vector - string::size_type len = str.length(); // length of the input-string - - // for every char in the input-string - while ( len > pos ) - { - // get the character of the string and reset the delimiter buffer - ch = str.at(pos); - delimiter = 0; - - // assume ch isn't a delimiter - bool add_char = true; - - // check ... - - // ... if the delimiter is an escaped character - bool escaped = false; // indicates if the next char is protected - if ( false == esc.empty() ) // check if esc-chars are provided - { - if ( string::npos != esc.find_first_of(ch) ) - { - // get the escaped char - ++pos; - if ( pos < len ) // if there are more chars left - { - // get the next one - ch = str.at(pos); - - // add the escaped character to the token - add_char = true; - } - else // cannot get any more characters - { - // don't add the esc-char - add_char = false; - } - - // ignore the remaining delimiter checks - escaped = true; - } - } - - // ... if the delimiter is a quote - if ( false == quote.empty() && false == escaped ) - { - // if quote chars are provided and the char isn't protected - if ( string::npos != quote.find_first_of(ch) ) - { - // if not quoted, set state to open quote and set - // the quote character - if ( false == quoted ) - { - quoted = true; - current_quote = ch; - - // don't add the quote-char to the token - add_char = false; - } - else // if quote is open already - { - // check if it is the matching character to close it - if ( current_quote == ch ) - { - // close quote and reset the quote character - quoted = false; - current_quote = 0; - - // don't add the quote-char to the token - add_char = false; - } - } // else - } - } - - // ... if the delimiter isn't preserved - if ( false == delimiters.empty() && false == escaped && - false == quoted ) - { - // if a delimiter is provided and the char isn't protected by - // quote or escape char - if ( string::npos != delimiters.find_first_of(ch) ) - { - // if ch is a delimiter and the token string isn't empty - // the token is complete - if ( false == token.empty() ) // BUGFIX: 2006-03-04 - { - token_complete = true; - } - - // don't add the delimiter to the token - add_char = false; - } - } - - // ... if the delimiter is preserved - add it as a token - bool add_delimiter = false; - if ( false == delimiters_preserve.empty() && false == escaped && - false == quoted ) - { - // if a delimiter which will be preserved is provided and the - // char isn't protected by quote or escape char - if ( string::npos != delimiters_preserve.find_first_of(ch) ) - { - // if ch is a delimiter and the token string isn't empty - // the token is complete - if ( false == token.empty() ) // BUGFIX: 2006-03-04 - { - token_complete = true; - } - - // don't add the delimiter to the token - add_char = false; - - // add the delimiter - delimiter = ch; - add_delimiter = true; - } - } - - - // add the character to the token - if ( true == add_char ) - { - // add the current char - token.push_back( ch ); - } - - // add the token if it is complete - if ( true == token_complete && false == token.empty() ) - { - // add the token string - result.push_back( token ); - - // clear the contents - token.clear(); - - // build the next token - token_complete = false; - } - - // add the delimiter - if ( true == add_delimiter ) - { - // the next token is the delimiter - string delim_token; - delim_token.push_back( delimiter ); - result.push_back( delim_token ); - - // REMOVED: 2006-03-04, Bugfix - } - - // repeat for the next character - ++pos; - } // while - - // add the final token - if ( false == token.empty() ) - { - result.push_back( token ); - } -} diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/tokenizer.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/tokenizer.h deleted file mode 100644 index 75f567ce..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/public/tokenizer.h +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************ -The zlib/libpng License - -Copyright (c) 2006 Joerg Wiedenmann - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but is - not required. - -2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source distribution. - -***********************************************************************/ - -/******************************************************************** - created: 2006-01-28 - filename: tokenizer.cpp - author: Jörg Wiedenmann - - purpose: A tokenizer function which provides a very - customizable way of breaking up strings. -*********************************************************************/ - -#include <vector> -#include <string> -using namespace std; - -// Function to break up a string into tokens -// -// Parameters: -//----------- -// str = the input string that will be tokenized -// result = the tokens for str -// delimiters = the delimiter characters -// delimiters preserve = same as above, but the delimiter characters -// will be put into the result as a token -// quote = characters to protect the enclosed characters -// esc = characters to protect a single character -// - -void tokenize ( const string& str, vector<string>& result, - const string& delimiters, const string& delimiters_preserve = "", - const string& quote = "\"", const string& esc = "\\" ); diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/Logger.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/Logger.cpp deleted file mode 100644 index 57b7075e..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/Logger.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2013 BlackBerry Limited - * - * Licensed 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. - */ - -#include "Logger.hpp" -#include "keyboard_js.hpp" -#include <slog2.h> - -namespace webworks { - -Logger::Logger(const char* name, Keyboard_JS *parent): m_pParent(parent) { - buffer_config.buffer_set_name = name; - buffer_config.num_buffers = 2; - buffer_config.verbosity_level = SLOG2_DEBUG1; - - /* Configure the first buffer, using 7 x 4KB pages. This larger buffer will be used for - very chatty logging. Our goal is to have 30-60 seconds of history at any given time, - so we will want to log at a rate of around one log line with a string of 16 bytes - long every 150 milliseconds. - */ - - buffer_config.buffer_config[0].buffer_name = "low_priority"; - buffer_config.buffer_config[0].num_pages = 7; - - /* Configure the second buffer, which we will use for high level info logging that is very - infrequent, but we want a longer history (hours or maybe even over a day or two). This - buffer uses 1 x 4KB. - */ - - buffer_config.buffer_config[1].buffer_name = "high_priority"; - buffer_config.buffer_config[1].num_pages = 1; - - /* Register the buffer set. */ - - if( -1 == slog2_register( &buffer_config, buffer_handle, 0 ) ) { - fprintf( stderr, "Error registering slogger2 buffer!\n" ); - } else { - info("Created slogger2 buffers"); - } - -} - -Logger::~Logger() { - critical("slogger2 buffers reset"); - slog2_reset(); -} - -int Logger::log(slog2_buffer_t buffer, _Uint8t severity, const char* message) { - return slog2c(buffer, 0, severity, message); -} - -int Logger::debug(const char* message) { - return log(lowPriorityBuffer(), SLOG2_DEBUG1, message); -} - -int Logger::info(const char* message) { - return log(lowPriorityBuffer(), SLOG2_INFO, message); -} - -int Logger::notice(const char* message) { - return log(lowPriorityBuffer(), SLOG2_NOTICE, message); -} - -int Logger::warn(const char* message) { - return log(lowPriorityBuffer(), SLOG2_WARNING, message); -} - -int Logger::error(const char* message) { - return log(hiPriorityBuffer(), SLOG2_ERROR, message); -} - -int Logger::critical(const char* message) { - return log(hiPriorityBuffer(), SLOG2_CRITICAL, message); -} - -int Logger::setVerbosity(_Uint8t verbosity) { - return slog2_set_verbosity(buffer_handle[0], verbosity); -} - -_Uint8t Logger::getVerbosity() { - return slog2_get_verbosity(buffer_handle[0]); -} - -slog2_buffer_t Logger::hiPriorityBuffer() { - return buffer_handle[1]; -} - -slog2_buffer_t Logger::lowPriorityBuffer() { - return buffer_handle[0]; -} - -} /* namespace webworks */ diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/Logger.hpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/Logger.hpp deleted file mode 100644 index ca379ca7..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/Logger.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013 BlackBerry Limited - * - * Licensed 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. - */ - -#ifndef LOGGER_HPP_ -#define LOGGER_HPP_ - -#include <string> -#include <slog2.h> - -class Keyboard_JS; - -namespace webworks { - -class Logger { -public: - explicit Logger(const char* name, Keyboard_JS *parent = NULL); - virtual ~Logger(); - int debug(const char* message); - int info(const char* message); - int notice(const char* message); - int warn(const char* message); - int error(const char* message); - int critical(const char* message); - int setVerbosity(_Uint8t verbosity); - _Uint8t getVerbosity(); - slog2_buffer_t hiPriorityBuffer(); - slog2_buffer_t lowPriorityBuffer(); -private: - Keyboard_JS *m_pParent; - slog2_buffer_set_config_t buffer_config; - slog2_buffer_t buffer_handle[2]; - int log(slog2_buffer_t buffer, _Uint8t severity, const char* message); -}; - -} /* namespace webworks */ -#endif /* LOGGER_HPP_ */ diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_js.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_js.cpp deleted file mode 100644 index 64250a14..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_js.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2013 BlackBerry Limited - * - * Licensed 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. - */ - -#include <string> -#include "../public/tokenizer.h" -#include "keyboard_js.hpp" -#include "keyboard_ndk.hpp" -#include <sstream> - -using namespace std; - -/** - * Default constructor. - */ -Keyboard_JS::Keyboard_JS(const std::string& id) : - m_id(id) { - m_pLogger = new webworks::Logger("Keyboard_JS", this); - m_pKeyboardController = new webworks::Keyboard_NDK(this); - - -} - -/** - * Keyboard_JS destructor. - */ -Keyboard_JS::~Keyboard_JS() { - if (m_pKeyboardController) - delete m_pKeyboardController; - if (m_pLogger) - delete m_pLogger; -} - -webworks::Logger* Keyboard_JS::getLog() { - return m_pLogger; -} - -/** - * This method returns the list of objects implemented by this native - * extension. - */ -char* onGetObjList() { - static char name[] = "Keyboard_JS"; - return name; -} - -/** - * This method is used by JNext to instantiate the Keyboard_JS object when - * an object is created on the JavaScript server side. - */ -JSExt* onCreateObject(const string& className, const string& id) { - if (className == "Keyboard_JS") { - return new Keyboard_JS(id); - } - - return NULL; -} - -/** - * Method used by JNext to determine if the object can be deleted. - */ -bool Keyboard_JS::CanDelete() { - return true; -} - -/** - * It will be called from JNext JavaScript side with passed string. - * This method implements the interface for the JavaScript to native binding - * for invoking native code. This method is triggered when JNext.invoke is - * called on the JavaScript side with this native objects id. - */ -string Keyboard_JS::InvokeMethod(const string& command) { - // format must be: "command callbackId params" - size_t commandIndex = command.find_first_of(" "); - std::string strCommand = command.substr(0, commandIndex); - size_t callbackIndex = command.find_first_of(" ", commandIndex + 1); - std::string callbackId = command.substr(commandIndex + 1, callbackIndex - commandIndex - 1); - std::string arg = command.substr(callbackIndex + 1, command.length()); - - // based on the command given, run the appropriate method in keyboard_ndk.cpp - if (strCommand == "showKeyboard") { - m_pKeyboardController->callKeyboardEmail(); - return "Show Keyboard"; - } else if (strCommand == "closeKeyboard") { - m_pKeyboardController->cancelKeyboard(); - return "Cancel Keyboard"; - } - else if(strCommand == "startService"){ - m_pKeyboardController->keyboardStartThread(); - return "Starting Service"; - } - - strCommand.append(";"); - strCommand.append(command); - return strCommand; -} - -// Notifies JavaScript of an event -void Keyboard_JS::NotifyEvent(const std::string& event) { - std::string eventString = m_id + " "; - eventString.append(event); - SendPluginEvent(eventString.c_str(), m_pContext); - -} - diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_js.hpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_js.hpp deleted file mode 100644 index 1ed3bb78..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_js.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* Copyright (c) 2013 BlackBerry Limited -* -* Licensed 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. -*/ - -#ifndef Keyboard_JS_HPP_ -#define Keyboard_JS_HPP_ - -#include <string> -#include "../public/plugin.h" -#include "keyboard_ndk.hpp" -#include "Logger.hpp" - - -class Keyboard_JS: public JSExt { - -public: - explicit Keyboard_JS(const std::string& id); - virtual ~Keyboard_JS(); - virtual bool CanDelete(); - virtual std::string InvokeMethod(const std::string& command); - void NotifyEvent(const std::string& event); - webworks::Logger* getLog(); -private: - std::string m_id; - webworks::Keyboard_NDK *m_pKeyboardController; - webworks::Logger *m_pLogger; - -}; - -#endif /* Keyboard_JS_HPP_ */ diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_ndk.cpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_ndk.cpp deleted file mode 100644 index 26b2e39a..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_ndk.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2013 BlackBerry Limited - * - * Licensed 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. - */ - -#include <string> -#include <sstream> -#include <json/reader.h> -#include <json/writer.h> -#include <pthread.h> -#include "keyboard_ndk.hpp" -#include "keyboard_js.hpp" -#include <QtCore> -namespace webworks { - -Keyboard_NDK::Keyboard_NDK(Keyboard_JS *parent): - m_pParent(parent), - keyboardProperty(50), - keyboardThreadCount(1), - threadHalt(true), - m_thread(0) { - pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - bps_initialize(); - - virtualkeyboard_request_events(0); - - virtualkeyboard_change_options(VIRTUALKEYBOARD_LAYOUT_EMAIL,VIRTUALKEYBOARD_ENTER_DEFAULT); - - m_pParent->getLog()->info("Keyboard Created"); - - -} - - -Keyboard_NDK::~Keyboard_NDK() { - //bps_shutdown(); -} - - -// Loops and runs the callback method -void* KeyboardThread(void* parent) { - Keyboard_NDK *pParent = static_cast<Keyboard_NDK *>(parent); - - sleep(1); - - // 1. Start the library - bps_initialize(); - - // 2. Request events to flow into the event queue - virtualkeyboard_request_events(0); - - sleep(3); - // 3. Use any service at any time - //virtualkeyboard_show(); // Show the virtual keyboard - - // 4. Listen for events - for (;;) { - // get an event - bps_event_t *event; - bps_get_event(&event, -1); // blocking - - // handle the event - pParent->event(event); - } - return NULL; -} - -// Starts the thread and returns a message on status -std::string Keyboard_NDK::keyboardStartThread() { - m_pParent->NotifyEvent("Teste"); - if (!m_thread) { - m_pParent->NotifyEvent("Teste"); - int rc; - rc = pthread_mutex_lock(&mutex); - threadHalt = false; - rc = pthread_cond_signal(&cond); - rc = pthread_mutex_unlock(&mutex); - - pthread_attr_t thread_attr; - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE); - - pthread_create(&m_thread, &thread_attr, KeyboardThread, - static_cast<void *>(this)); - pthread_attr_destroy(&thread_attr); - //threadCallbackId = callbackId; - m_pParent->getLog()->info("Thread Started"); - return "Thread Started"; - } else { - m_pParent->getLog()->warn("Thread Started but already running"); - return "Thread Running"; - } -} - - -void Keyboard_NDK::event(bps_event_t *event) { - Json::FastWriter writer; - Json::Value root; - root["threadCount"] = "10"; - int domain = bps_event_get_domain(event); - if (domain == virtualkeyboard_get_domain()) { - int code = bps_event_get_code(event); - int a; - std::string str; - std::string eventString; - std::ostringstream strs; - switch(code) { - case VIRTUALKEYBOARD_EVENT_VISIBLE: - eventString = "native.keyboardshow"; - eventString.append(" "); - virtualkeyboard_get_height(&a) ; - strs << a; - str = strs.str(); - eventString.append("{\"keyboardHeight\":\""+str+"\"}"); - m_pParent->NotifyEvent(eventString); - - break; - case VIRTUALKEYBOARD_EVENT_HIDDEN: - - m_pParent->NotifyEvent("native.keyboardhide"); - break; - } - } - -} -void Keyboard_NDK::callKeyboardEmail(){ - virtualkeyboard_change_options(VIRTUALKEYBOARD_LAYOUT_EMAIL,VIRTUALKEYBOARD_ENTER_SEND); - virtualkeyboard_show(); -} - -void Keyboard_NDK::callKeyboardNumber(){ - - virtualkeyboard_change_options(VIRTUALKEYBOARD_LAYOUT_NUMBER,VIRTUALKEYBOARD_ENTER_SEND); - virtualkeyboard_show(); -} -void Keyboard_NDK::cancelKeyboard(){ - virtualkeyboard_hide(); -} - - - - -} diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_ndk.hpp b/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_ndk.hpp deleted file mode 100644 index 01062274..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/blackberry10/native/src/keyboard_ndk.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (c) 2013 BlackBerry Limited -* -* Licensed 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. -*/ - -#ifndef Keyboard_NDK_HPP_ -#define Keyboard_NDK_HPP_ - -#include <string> -#include <pthread.h> -#include <bb/AbstractBpsEventHandler> -#include <bps/bps.h> -#include<bps/netstatus.h> -#include<bps/locale.h> -#include<bps/virtualkeyboard.h> -#include<bps/navigator.h> -#include <bps/event.h> -#include <string> -#include <sstream> - -class Keyboard_JS; - -namespace webworks { - -class Keyboard_NDK { -public: - explicit Keyboard_NDK(Keyboard_JS *parent = NULL); - virtual ~Keyboard_NDK(); - virtual void event(bps_event_t *event); - - void callKeyboardEmail(); // Method Calls the Keyboard style Email (default) - - void callKeyboardNumber(); // Method Calls the Keyboard style number - - void cancelKeyboard(); // Method cancel the keyboard - - std::string keyboardStartThread(); - - - - - - - -private: - - Keyboard_JS *m_pParent; - int keyboardProperty; - int keyboardThreadCount; - bool threadHalt; - std::string threadCallbackId; - pthread_t m_thread; - pthread_cond_t cond; - pthread_mutex_t mutex; - -}; - -} // namespace webworks - -#endif /* Keyboard_NDK_HPP_ */ diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/ios/IonicKeyboard.h b/StoneIsland/plugins/ionic-plugin-keyboard/src/ios/IonicKeyboard.h deleted file mode 100644 index 63935dc3..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/ios/IonicKeyboard.h +++ /dev/null @@ -1,16 +0,0 @@ -#import <Cordova/CDVPlugin.h> -#import <objc/runtime.h> - -@interface IonicKeyboard : CDVPlugin <UIScrollViewDelegate> { - @protected - id _keyboardShowObserver, _keyboardHideObserver; - IMP wkOriginalImp, uiOriginalImp, nilImp; - Method wkMethod, uiMethod; -} - -@property (readwrite, assign) BOOL hideKeyboardAccessoryBar; -@property (readwrite, assign) BOOL disableScroll; -//@property (readwrite, assign) BOOL styleDark; - -@end - diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/ios/IonicKeyboard.m b/StoneIsland/plugins/ionic-plugin-keyboard/src/ios/IonicKeyboard.m deleted file mode 100644 index d072ca7f..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/ios/IonicKeyboard.m +++ /dev/null @@ -1,176 +0,0 @@ -#import "IonicKeyboard.h" -// #import "UIWebViewExtension.h" -#import <Cordova/CDVAvailability.h> - -@implementation IonicKeyboard - -@synthesize hideKeyboardAccessoryBar = _hideKeyboardAccessoryBar; -@synthesize disableScroll = _disableScroll; -//@synthesize styleDark = _styleDark; - -- (void)pluginInitialize { - - Class wkClass = NSClassFromString([@[@"UI", @"Web", @"Browser", @"View"] componentsJoinedByString:@""]); - wkMethod = class_getInstanceMethod(wkClass, @selector(inputAccessoryView)); - wkOriginalImp = method_getImplementation(wkMethod); - Class uiClass = NSClassFromString([@[@"WK", @"Content", @"View"] componentsJoinedByString:@""]); - uiMethod = class_getInstanceMethod(uiClass, @selector(inputAccessoryView)); - uiOriginalImp = method_getImplementation(uiMethod); - nilImp = imp_implementationWithBlock(^(id _s) { - return nil; - }); - - //set defaults - self.hideKeyboardAccessoryBar = YES; - self.disableScroll = NO; - //self.styleDark = NO; - - NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; - __weak IonicKeyboard* weakSelf = self; - _keyboardShowObserver = [nc addObserverForName:UIKeyboardWillShowNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification* notification) { - - CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; - keyboardFrame = [self.viewController.view convertRect:keyboardFrame fromView:nil]; - - [weakSelf.commandDelegate evalJs:[NSString stringWithFormat:@"cordova.plugins.Keyboard.isVisible = true; cordova.fireWindowEvent('native.keyboardshow', { 'keyboardHeight': %@ }); ", [@(keyboardFrame.size.height) stringValue]]]; - - //deprecated - [weakSelf.commandDelegate evalJs:[NSString stringWithFormat:@"cordova.fireWindowEvent('native.showkeyboard', { 'keyboardHeight': %@ }); ", [@(keyboardFrame.size.height) stringValue]]]; - }]; - - _keyboardHideObserver = [nc addObserverForName:UIKeyboardWillHideNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification* notification) { - [weakSelf.commandDelegate evalJs:@"cordova.plugins.Keyboard.isVisible = false; cordova.fireWindowEvent('native.keyboardhide'); "]; - - //deprecated - [weakSelf.commandDelegate evalJs:@"cordova.fireWindowEvent('native.hidekeyboard'); "]; - }]; -} - -- (BOOL)disableScroll { - return _disableScroll; -} - -- (void)setDisableScroll:(BOOL)disableScroll { - if (disableScroll == _disableScroll) { - return; - } - if (disableScroll) { - self.webView.scrollView.scrollEnabled = NO; - self.webView.scrollView.delegate = self; - } - else { - self.webView.scrollView.scrollEnabled = YES; - self.webView.scrollView.delegate = nil; - } - - _disableScroll = disableScroll; -} - -//keyboard swizzling inspired by: -//https://github.com/cjpearson/cordova-plugin-keyboard/ - -- (BOOL)hideKeyboardAccessoryBar { - return _hideKeyboardAccessoryBar; -} - -- (void)setHideKeyboardAccessoryBar:(BOOL)hideKeyboardAccessoryBar { - if (hideKeyboardAccessoryBar == _hideKeyboardAccessoryBar) { - return; - } - - if (hideKeyboardAccessoryBar) { - method_setImplementation(wkMethod, nilImp); - method_setImplementation(uiMethod, nilImp); - } else { - method_setImplementation(wkMethod, wkOriginalImp); - method_setImplementation(uiMethod, uiOriginalImp); - } - - _hideKeyboardAccessoryBar = hideKeyboardAccessoryBar; -} - -/* -- (BOOL)styleDark { - return _styleDark; -} - -- (void)setStyleDark:(BOOL)styleDark { - if (styleDark == _styleDark) { - return; - } - if (styleDark) { - self.webView.styleDark = YES; - } - else { - self.webView.styleDark = NO; - } - - _styleDark = styleDark; -} -*/ - - -/* ------------------------------------------------------------- */ - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView { - [scrollView setContentOffset: CGPointZero]; -} - -/* ------------------------------------------------------------- */ - -- (void)dealloc { - NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; - - [nc removeObserver:self name:UIKeyboardWillShowNotification object:nil]; - [nc removeObserver:self name:UIKeyboardWillHideNotification object:nil]; -} - -/* ------------------------------------------------------------- */ - -- (void) disableScroll:(CDVInvokedUrlCommand*)command { - if (!command.arguments || ![command.arguments count]){ - return; - } - id value = [command.arguments objectAtIndex:0]; - if (value != [NSNull null]) { - self.disableScroll = [value boolValue]; - } -} - -- (void) hideKeyboardAccessoryBar:(CDVInvokedUrlCommand*)command { - if (!command.arguments || ![command.arguments count]){ - return; - } - id value = [command.arguments objectAtIndex:0]; - if (value != [NSNull null]) { - self.hideKeyboardAccessoryBar = [value boolValue]; - } -} - -- (void) close:(CDVInvokedUrlCommand*)command { - [self.webView endEditing:YES]; -} - -- (void) show:(CDVInvokedUrlCommand*)command { - NSLog(@"Showing keyboard not supported in iOS due to platform limitations."); -} - -/* -- (void) styleDark:(CDVInvokedUrlCommand*)command { - if (!command.arguments || ![command.arguments count]){ - return; - } - id value = [command.arguments objectAtIndex:0]; - - self.styleDark = [value boolValue]; -} -*/ - -@end - diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/src/windows/KeyboardProxy.js b/StoneIsland/plugins/ionic-plugin-keyboard/src/windows/KeyboardProxy.js deleted file mode 100644 index 2ce74e9f..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/src/windows/KeyboardProxy.js +++ /dev/null @@ -1,37 +0,0 @@ - -/*global Windows, WinJS, cordova, module, require*/ - -var inputPane = Windows.UI.ViewManagement.InputPane.getForCurrentView(); -var keyboardScrollDisabled = false; - -inputPane.addEventListener('hiding', function() { - cordova.fireWindowEvent('native.keyboardhide'); - cordova.plugins.Keyboard.isVisible = false; -}); - -inputPane.addEventListener('showing', function(e) { - if (keyboardScrollDisabled) { - // this disables automatic scrolling of view contents to show focused control - e.ensuredFocusedElementInView = true; - } - cordova.fireWindowEvent('native.keyboardshow', { keyboardHeight: e.occludedRect.height }); - cordova.plugins.Keyboard.isVisible = true; -}); - -module.exports.disableScroll = function (disable) { - keyboardScrollDisabled = disable; -}; - -module.exports.show = function () { - if (typeof inputPane.tryShow === 'function') { - inputPane.tryShow(); - } -}; - -module.exports.close = function () { - if (typeof inputPane.tryShow === 'function') { - inputPane.tryHide(); - } -}; - -require("cordova/exec/proxy").add("Keyboard", module.exports); diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/www/android/keyboard.js b/StoneIsland/plugins/ionic-plugin-keyboard/www/android/keyboard.js deleted file mode 100644 index 125a5a29..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/www/android/keyboard.js +++ /dev/null @@ -1,60 +0,0 @@ - -var argscheck = require('cordova/argscheck'), - utils = require('cordova/utils'), - exec = require('cordova/exec'), - channel = require('cordova/channel'); - - -var Keyboard = function() { -}; - -Keyboard.hideKeyboardAccessoryBar = function(hide) { - exec(null, null, "Keyboard", "hideKeyboardAccessoryBar", [hide]); -}; - -Keyboard.close = function() { - exec(null, null, "Keyboard", "close", []); -}; - -Keyboard.show = function() { - exec(null, null, "Keyboard", "show", []); -}; - -Keyboard.disableScroll = function(disable) { - exec(null, null, "Keyboard", "disableScroll", [disable]); -}; - -/* -Keyboard.styleDark = function(dark) { - exec(null, null, "Keyboard", "styleDark", [dark]); -}; -*/ - -Keyboard.isVisible = false; - -channel.onCordovaReady.subscribe(function() { - exec(success, null, 'Keyboard', 'init', []); - - function success(msg) { - var action = msg.charAt(0); - if ( action === 'S' ) { - var keyboardHeight = msg.substr(1); - cordova.plugins.Keyboard.isVisible = true; - cordova.fireWindowEvent('native.keyboardshow', { 'keyboardHeight': + keyboardHeight }); - - //deprecated - cordova.fireWindowEvent('native.showkeyboard', { 'keyboardHeight': + keyboardHeight }); - } else if ( action === 'H' ) { - cordova.plugins.Keyboard.isVisible = false; - cordova.fireWindowEvent('native.keyboardhide'); - - //deprecated - cordova.fireWindowEvent('native.hidekeyboard'); - } - } -}); - -module.exports = Keyboard; - - - diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/www/browser/keyboard.js b/StoneIsland/plugins/ionic-plugin-keyboard/www/browser/keyboard.js deleted file mode 100644 index 8b73e621..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/www/browser/keyboard.js +++ /dev/null @@ -1,34 +0,0 @@ - -var argscheck = require('cordova/argscheck'), - utils = require('cordova/utils'), - exec = require('cordova/exec'); - - -var Keyboard = function() { -}; - -Keyboard.hideKeyboardAccessoryBar = function(hide) { - return null; -}; - -Keyboard.close = function() { - return null; -}; - -Keyboard.show = function() { - return null; -}; - -Keyboard.disableScroll = function(disable) { - return null; -}; - -/* -Keyboard.styleDark = function(dark) { - exec(null, null, "Keyboard", "styleDark", [dark]); -}; -*/ - -Keyboard.isVisible = false; - -module.exports = Keyboard; diff --git a/StoneIsland/plugins/ionic-plugin-keyboard/www/ios/keyboard.js b/StoneIsland/plugins/ionic-plugin-keyboard/www/ios/keyboard.js deleted file mode 100644 index 888a18a3..00000000 --- a/StoneIsland/plugins/ionic-plugin-keyboard/www/ios/keyboard.js +++ /dev/null @@ -1,40 +0,0 @@ - -var argscheck = require('cordova/argscheck'), - utils = require('cordova/utils'), - exec = require('cordova/exec'); - - -var Keyboard = function() { -}; - -Keyboard.hideKeyboardAccessoryBar = function(hide) { - exec(null, null, "Keyboard", "hideKeyboardAccessoryBar", [hide]); -}; - -Keyboard.close = function() { - exec(null, null, "Keyboard", "close", []); -}; - -Keyboard.show = function() { - console.warn('Showing keyboard not supported in iOS due to platform limitations.') - console.warn('Instead, use input.focus(), and ensure that you have the following setting in your config.xml: \n'); - console.warn(' <preference name="KeyboardDisplayRequiresUserAction" value="false"/>\n'); - // exec(null, null, "Keyboard", "show", []); -}; - -Keyboard.disableScroll = function(disable) { - exec(null, null, "Keyboard", "disableScroll", [disable]); -}; - -/* -Keyboard.styleDark = function(dark) { - exec(null, null, "Keyboard", "styleDark", [dark]); -}; -*/ - -Keyboard.isVisible = false; - -module.exports = Keyboard; - - - diff --git a/StoneIsland/plugins/ios.json b/StoneIsland/plugins/ios.json index b95f9dd3..e653cb5f 100644 --- a/StoneIsland/plugins/ios.json +++ b/StoneIsland/plugins/ios.json @@ -1,64 +1,51 @@ { - "prepare_queue": { - "installed": [], - "uninstalled": [] + "prepare_queue": { + "installed": [], + "uninstalled": [] + }, + "config_munge": { + "files": {} + }, + "installed_plugins": { + "cordova-plugin-app-name": { + "APP_NAME": "Stone Island", + "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "config_munge": { - "files": {} + "cordova-plugin-customurlscheme": { + "URL_SCHEME": "stoneisland", + "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "installed_plugins": { - "cordova-plugin-app-name": { - "APP_NAME": "Stone Island", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-customurlscheme": { - "URL_SCHEME": "stoneisland", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-device": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-dialogs": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-geolocation": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-inappbrowser": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-network-information": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-splashscreen": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-statusbar": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-whitelist": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-x-socialsharing": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "ionic-plugin-keyboard": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "phonegap-plugin-push": { - "SENDER_ID": "85075801930", - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "cordova-plugin-sim": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - }, - "phonegap-plugin-mobile-accessibility": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - } + "cordova-plugin-device": { + "PACKAGE_NAME": "us.okfoc.stoneisland" }, - "dependent_plugins": { - "cordova-plugin-compat": { - "PACKAGE_NAME": "us.okfoc.stoneisland" - } + "cordova-plugin-dialogs": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-firebasex": { + "FIREBASE_ANALYTICS_COLLECTION_ENABLED": "true", + "FIREBASE_PERFORMANCE_COLLECTION_ENABLED": "true", + "FIREBASE_CRASHLYTICS_COLLECTION_ENABLED": "true", + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-ionic-keyboard": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-sim": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-geolocation": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + } + }, + "dependent_plugins": { + "cordova-plugin-compat": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-androidx": { + "PACKAGE_NAME": "us.okfoc.stoneisland" + }, + "cordova-plugin-androidx-adapter": { + "PACKAGE_NAME": "us.okfoc.stoneisland" } -}
\ No newline at end of file + } +} diff --git a/StoneIsland/plugins/phonegap-plugin-push/CHANGELOG.md b/StoneIsland/plugins/phonegap-plugin-push/CHANGELOG.md deleted file mode 100644 index e46cdae8..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/CHANGELOG.md +++ /dev/null @@ -1,597 +0,0 @@ -# Change Log - -## [v1.9.1](https://github.com/phonegap/phonegap-plugin-push/tree/v1.9.1) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.9.0...v1.9.1) - -- 1.9.1 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/6178688d10fc9fd5770795e5caa3f402d3fec574) -- Bumping plugin version to 1.9.1 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4d0d2d0c0f19305189bbc7db11c56abfcb0e629a) -- :bug: Issue #1412: push.subscribe 'not a function' error [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/1c0c0bcac7ae4a0fe8a7c54e2f00fdba90ff5207) -- :memo: Add emoji guide to CONTRIBUTING [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/dce845fde55429c36a885a4711e04a73904ab9c0) -- Issue #1342: Fail to add 1.9.0 to ios platform [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/7481e286607dacf01327c9f6d5a7c21acc5eeba1) -- Issue #1402: force-start:1 brings a killed application to foreground, not background [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/256f28fa08da4aab9691d628a3150022b67da02d) -- Issue #1400: Version 1.9.0 on PGB not working [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/c45228a892c602b8616d165ccf142eac0ff2f7f2) -- Merge pull request #1398 from getlarky/android-badge-documentation [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/6884df95602a15c219846bbcdb01ce1285d660bb) -- Warn about android badge support in documentation [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/2842de212b11a76580865c6ee0d6a1b7b42d030e) -- Enahancement : Add custom permission for PushHandlerActivity (#1362) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e15fdc442030648daabc79a44ae72b2d14b7c1d2) -- Issue #1248: upgrade ShortcutBadger version to latest [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4ab1cf0f0747b1f122f1f43c4af67db37dd0e443) -- Merge pull request #1361 from pataar/master [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/29ec1e241036611c6a3a2c71d2a61860427be5d0) -- Fix minor typos in INSTALLATION.md [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/840b0e06cb2643635cfb882de9a35202799f3953) -- Add mimimum cordova versions to installation docs [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/dcb528384dfd7f65410545b842e16ef89277ff7b) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e268a0dceff248b703ae75ff7923b7b3d673aeee) - -## [v1.9.0](https://github.com/phonegap/phonegap-plugin-push/tree/v1.9.0) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.8.4...v1.9.0) - -- 1.9.0 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e5b7f22299d900a37064a783da43905ad73c58bf) -- Bumping plugin version to 1.9.0 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/dc6a11db4157e1070e48e073a8a78401f185d324) -- Prepare for 1.9.0 release [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/0f889bfb5e612ef3ffbc1466deabfe9eb99b760b) -- Update gitignore [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/d70bad64564444c01e59ff494b8ba09d190d3dbb) -- Bumping plugin version to 1.9.0 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/600993e7739a0a84ef77b60c4a1457f8aea084b6) -- Issue #1154: Register fail iOS 10 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e6013d49ecf0025be10fb6bb87152ee4025b5df4) -- Issue #1337: Build failed, invalid package.json [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/8631666e4654fd6acafa6cf160cc59424e912ceb) -- Set default SENDER_ID [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/82ca365f4d6d91b18fc28c338a647a2622e60f6e) -- Issue #158: Notification Event Not Firing When Closed Through App Launcher [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/ca18653d6ff332db41f48824a2d65bd2699ed8bc) -- Merge branch 'master' of https://github.com/hanicker/phonegap-plugin-push into hanicker-master [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/43402909d3b2d5c6ff518cc69e401dc918b585aa) -- Update plugin to use GCM Cocoapods <framework> reference in plugin.xml (#1183) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/b639d83fe125d5b77720d130ccec53af3a5f3d91) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e4779de2a5996703ba70656630f35d79415d1af8) -- feat(forced restart, notify javascript) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/8c03beff9a5a83927b7020ee04c3ed541de04edd) -- restart application after force close (#158 #333) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/8b7c972dbf617f22218c178d74368b35521eecb9) - -## [v1.8.4](https://github.com/phonegap/phonegap-plugin-push/tree/v1.8.4) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.8.3...v1.8.4) - -- 1.8.4 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4b18505a2c30e17564c0e80060f0524968aa0d40) -- Bumping plugin version to 1.8.4 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/046c727f58a6fa675a5f49c10334095cd4282884) -- Issue #1251: [Android] deviceId persists between uninstalls, but is invalid after an uninstall [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/8a7bbe5cba186d9685f31adc07e25bd908409498) -- Merge pull request #1323 from hung-doan/issue-1319 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/021f0abd9a49fb83d19faca3ffb7d142759bb01a) -- Update GCM to 9.8+ issue #1319 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/450e0e01b9bcd747a49081c4a0d6ce998c37478a) -- Support Twilio Notify (#1306) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/a9bb3bf0a2ca57f68eafc39070fc125746bbbb23) -- Cache multiple Android action button pushes if app is not running (#1272) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/d0547bab04c292024dc6ed41939590fba01115ff) -- Add sub/unsub tests [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/3bf9ff5f04e10622d7d9ff47a9bd57a829ee9eef) -- Add features: push.subscribe, push.unsubscribe (issue #1040) (#1227) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/bb0d3ed087e13e24af57e682776930cea2f577a8) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/cf7ce8e716fe60de121634abc164b509100a9d15) - -## [v1.8.3](https://github.com/phonegap/phonegap-plugin-push/tree/v1.8.3) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.8.2...v1.8.3) - -- 1.8.3 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/a0cfba9f85b7d7dfa3c244c9e78a03872ff938f9) -- Bumping plugin version to 1.8.3 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/cc7d5abe55957cebfdd3b39ba670f8093bdac564) -- Update pluginpub version [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/0d8548d3166b7b4d34b32944b800c96e4aadf70a) -- Issue#1282 Show app name if title is empty (#1285) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/3d7a3a39fb931aafa86be6b1568a682133c36de7) -- Note about background app refresh (#1267) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4f13533deb0c1b927dab9d9cddb13c53fdefd9b0) -- Issue #1213: XDK instructions link for www template is incorrect (#1283) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/d2ede2bab4cd6462f7dffc4e2bc733d585107e89) -- Merge pull request #1277 from dannywillems/patch-1 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/ea5ae88f3fcfa8fc605cf2c974b52d793bd2c4c9) -- Unused variable app. Caused warnings. [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/09dedb43481d207d0b17de4eb26c5a1904d08f65) -- Issue #1254: [Question] Is it possible to get more than 3 action buttons on Android notifications? [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/d8ab6665d878c8dec3ff9914c11a9329c8a415e7) -- Use unique pending intent request code to enable multiple... (#1225) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/475883833556eb001e2e0adb986bd96b78bdcb2f) -- Add `cordovaDependencies` section to package.json (#1232) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/6b343e78e9bfca921cef78eb504755477ecaeff9) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/14afb94126acb51a6f10a2094f7f391f2f17dee5) - -## [v1.8.2](https://github.com/phonegap/phonegap-plugin-push/tree/v1.8.2) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.8.1...v1.8.2) - -- 1.8.2 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/b47d519abff667400c4863fe90a27ae88e3c0671) -- Bumping plugin version to 1.8.2 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/738735ddcd9b60014beb4207c3ccdcd30ba7a803) -- Localization from resources (#1196) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/2de9fc2827a18941ae6040e90ea0da5dc97652d8) -- Issue #1199: iOS 10 is not firing the 'notification' event after clicking on a notification when the app is in hibernate [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e711b09b15a8e85156e9158026509522859c7900) -- Use unique pending intent request code to enable multiple simultaneous notifications with action buttons (#1216) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/1fe640637fd67ec0ce2cf50ee1cab793ed01cfb7) -- (doc) Fixing `ios.catetories` type in api reference. [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/0a93fab9cec5ac2a2b813090958054e8e7b15f9a) -- Issue #1155: [doc] Explain usage of the top level "priority" in GCM notifications [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/ddaf48e089dc3cb46f9bd9f5e4678a2118b14a48) -- Issue #1121: Notification is not shown on ios device [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/432761202c43a1f2a4ba9c643df78b81b87d66fa) -- Issue #1160: data.additionalData.[Object] as 'undefined' in iOS [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/946052a895268155f56a7a3a1006d019599b46f9) -- Few edits (#1179) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/f90b4bbf0e78adaa029737cf70b146ec97d09015) -- Adding workshop tutorial link to the README (#1169) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/59800a930557bd864e527404e1035c2d8ac149c9) -- added Azure server-side example (#1124) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/0bd4d0e612f6f1c62e33d147564b7e495436f15e) -- Update appxmanifests with ToastCapable=true after plugin install (#1158) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/eeefc036a8600bea80135b6b14241509853444ab) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/30d3d5dc733c80bc1687e5eff28d0614a0f38e51) - -## [v1.8.1](https://github.com/phonegap/phonegap-plugin-push/tree/v1.8.1) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.8.0...v1.8.1) - -- 1.8.1 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/95c27d29ef37bfd750972561022db53de256840d) -- Bumping plugin version to 1.8.1 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e4ba55ff310d4d931503de2547738cc169b6f968) -- [Windows] Added a check on activation context existence (#1129) [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/151c8cd97aa71742798e969dd9e6c2208b8c1f15) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4cd4ee00e2eb081d0d29d001e580009fba5c341a) - -## [v1.8.0](https://github.com/phonegap/phonegap-plugin-push/tree/v1.8.0) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/v1.7.4...v1.8.0) - -- 1.8.0 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/d5a8480e6e230c959d8079554a6366f3605cb97e) -- Bumping plugin version to 1.8.0 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/f8c784536e40ce6dddf14edeff7ad2a9ee944156) -- Check that serviceWorker exists before unregistering [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/ef004002d60d8028ed6aad2cef79d4d8ac6aed49) -- Populate additionalData on browser platform [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/63a29cdbbc0cd0374552d51e0e2d2217f5361f79) -- Issue #683: Support Android N inline reply actions [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e835ca31ac02a3455ece8c96938260935e2e7100) -- Issue #1109: Installation.MD has a mistake [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/89834b78a63ad6c927295eb5699204a0ccb49a73) -- Use push server DELETE route to remove browser keys [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4615ea694bd5858bfdb8553c9a9390e1e30c2c36) -- [chore] fix mis-spelling [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/efdef52deec4f7e8b6b4ee87460bd87cc0479c74) -- Browser: always call success on unimplemented methods [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/1b8bf267674508361c68fb03b12f97608e87456b) -- Update push url [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e1d8774f760d7a72a547d68e1b2ac367572e2b6d) -- Merge branch 'browser' [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/a2ad8da9a25a02a1b674e6adf0a37e18cde185ab) -- Add browser platform support [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e8e0fe47001e461cf7fb7274d4c2b3dc687cd90e) -- Issue #1080: clearAllNotifications not working on iOS [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/4bea2a7469ab2bd677e12d440b457e1d5383b1f0) -- [whoops] revert accidental commit of a pluginpub test [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/da301e8a43a0a659947294c9d94f7fd09f5ac4b2) -- [doc] remove deprecation notice on hasPermission [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/d4b79a81c5ad85a4b566e5a23a19b10fa78dcf17) -- Updating CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/8512a6cb7be3c0bb2b5db813c7aaff4c49fc52a2) -- Bumping plugin version to 1.9.0 [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/b015543b8a06526b7b70357407e635c180c473ee) -- Update CHANGELOG [view commit](http://github.com/phonegap/phonegap-plugin-push/commit/e6f87a50d9f9cb3bd7c9ba599b3d3afbc0fd7aaf) - -## [1.7.4](https://github.com/phonegap/phonegap-plugin-push/tree/v1.7.4) (2016-07-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.7.3...v1.7.4) - -**Closed issues:** - -- FYI: Resumed iOS 10 Notifications results in an error (fix problem on iOS) [\#1002](https://github.com/phonegap/phonegap-plugin-push/issues/1002) - - -## [1.7.3](https://github.com/phonegap/phonegap-plugin-push/tree/1.7.3) (2016-07-06) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.7.2...1.7.3) - -**Closed issues:** - -- Implemented clearBadge for Android [\#1030](https://github.com/phonegap/phonegap-plugin-push/issues/1030) -- update badge number even if the app is totally closed [\#1027](https://github.com/phonegap/phonegap-plugin-push/issues/1027) -- Documentation issue of Android pictures push [\#1028](https://github.com/phonegap/phonegap-plugin-push/issues/1028) -- [iOS] unregister for a topic: parameter is not consistent between ios/android [\#1029](https://github.com/phonegap/phonegap-plugin-push/issues/1029) -- [doc] Error installing in IOS, version requirement: >=4.1.0 [\#1047](https://github.com/phonegap/phonegap-plugin-push/issues/1047) - -## [1.7.2](https://github.com/phonegap/phonegap-plugin-push/tree/1.7.2) (2016-06-24) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.7.1...1.7.2) - -**Closed issues:** - -- FYI: Resumed iOS 10 Notifications results in an error [\#1002](https://github.com/phonegap/phonegap-plugin-push/issues/1002) - -## [1.7.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.7.1) (2016-06-17) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.7.0...1.7.1) - -**Closed issues:** - -- Update docs for Android badges [\#982](https://github.com/phonegap/phonegap-plugin-push/issues/982) -- visibility not working [\#987](https://github.com/phonegap/phonegap-plugin-push/issues/982) -- Revert pinning of support-v13 [\#983](https://github.com/phonegap/phonegap-plugin-push/issues/983) - -## [1.7.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.7.0) (2016-06-06) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.6.4...1.7.0) - -**Closed issues:** - -- disable notification's sounds on a per notification basis [\#885](https://github.com/phonegap/phonegap-plugin-push/issues/885) -- Android GCM Action Buttons lack of documentation [\#884](https://github.com/phonegap/phonegap-plugin-push/issues/884) -- Android double on('notification') fired [\#828](https://github.com/phonegap/phonegap-plugin-push/issues/828) -- Device should register, Push Notification should receive on IOS (IntelXDK) [\#926](https://github.com/phonegap/phonegap-plugin-push/issues/926) -- Use cordova-ios 4.1.0 in Milestone 1.7.0 [\#751](https://github.com/phonegap/phonegap-plugin-push/issues/751) -- Badge on android [\#190](https://github.com/phonegap/phonegap-plugin-push/issues/190) -- JS error in Success callbackId: PushNotifiation###.. whenever a notification is sent to the device [\#824](https://github.com/phonegap/phonegap-plugin-push/issues/824) -- coldstart flag always set to true if the app has been opened through an alert, on ios 9.3.1, plugin version 1.6.2 cordova 6.1.0 cordova ios 4.1.1 [\#795](https://github.com/phonegap/phonegap-plugin-push/issues/795) -- Is there any way to clear notifications out from the app? [\#346](https://github.com/phonegap/phonegap-plugin-push/issues/346) -- Show contents of notification when phone is locked [\#750](https://github.com/phonegap/phonegap-plugin-push/issues/750) -- PushPlugin.m init() should send pending notification when js side is ready [\#658](https://github.com/phonegap/phonegap-plugin-push/issues/658) - -## [1.6.4](https://github.com/phonegap/phonegap-plugin-push/tree/1.6.4) (2016-05-24) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.6.3...1.6.4) - -**Closed issues:** - -- hasPermission() for windows [\#874](https://github.com/phonegap/phonegap-plugin-push/issues/874) -- Latest Play store service breaks phonegap-plugin-push [\#909](https://github.com/phonegap/phonegap-plugin-push/issues/909) - -## [1.6.3](https://github.com/phonegap/phonegap-plugin-push/tree/1.6.3) (2016-04-27) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.6.2...1.6.3) - -**Fixed bugs:** - -- \[Android\] Can't install multiple apps using this plugin \(v1.6.x\) [\#768](https://github.com/phonegap/phonegap-plugin-push/issues/768) -- JS error in "Success callbackId: PushNotifiation\#\#\#.." whenever a notification is sent to the device [\#824](https://github.com/phonegap/phonegap-plugin-push/issues/824) - -**Closed issues:** - -- Move example directory to a phonegap template [\#832](https://github.com/phonegap/phonegap-plugin-push/issues/832) -- va [\#830](https://github.com/phonegap/phonegap-plugin-push/issues/830) -- does not create the notification bar [\#821](https://github.com/phonegap/phonegap-plugin-push/issues/821) -- Did not show notification in status bar for Xiomi Redmi Note 3 [\#790](https://github.com/phonegap/phonegap-plugin-push/issues/790) -- PushNotification.hasPermission not working as expected [\#789](https://github.com/phonegap/phonegap-plugin-push/issues/789) - - -## [1.6.2](https://github.com/phonegap/phonegap-plugin-push/tree/1.6.2) (2016-04-06) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.6.1...1.6.2) - -**Fixed bugs:** - -- Unexpected / Broken Android Behavior [\#767](https://github.com/phonegap/phonegap-plugin-push/issues/767) - -**Closed issues:** - -- Android: JSON Exception No Value Found for Sender [\#781](https://github.com/phonegap/phonegap-plugin-push/issues/781) -- Should I call init\(\) every time the app is launched?? [\#777](https://github.com/phonegap/phonegap-plugin-push/issues/777) -- Request: extend action buttons to wearables [\#776](https://github.com/phonegap/phonegap-plugin-push/issues/776) -- After upgrade: 601 duplicate symbols for architecture i386 [\#769](https://github.com/phonegap/phonegap-plugin-push/issues/769) -- push plugin [\#766](https://github.com/phonegap/phonegap-plugin-push/issues/766) -- Documentation mentions old name for dependency [\#763](https://github.com/phonegap/phonegap-plugin-push/issues/763) -- push.on\('notification'\) callback is not called on coldstart on iOS [\#758](https://github.com/phonegap/phonegap-plugin-push/issues/758) -- plugin doesn't work in background or when app not running on kitkat 4.4.2 [\#754](https://github.com/phonegap/phonegap-plugin-push/issues/754) -- App Icon not displayed in tray using build.phonegap and cli-6.0.0 \[ios\] [\#753](https://github.com/phonegap/phonegap-plugin-push/issues/753) -- push.on\('registration'\) event not called on IOS. [\#752](https://github.com/phonegap/phonegap-plugin-push/issues/752) -- catch 22 when trying to use this plug [\#741](https://github.com/phonegap/phonegap-plugin-push/issues/741) -- push.setApplicationIconBadgeNumber not working in background [\#736](https://github.com/phonegap/phonegap-plugin-push/issues/736) -- Strange issue while debugging in Safari Inspector [\#733](https://github.com/phonegap/phonegap-plugin-push/issues/733) - -## [1.6.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.6.1) (2016-03-23) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.6.0...1.6.1) - -**Fixed bugs:** - -- App crashes on notification when in background [\#715](https://github.com/phonegap/phonegap-plugin-push/issues/715) - -**Closed issues:** - -- Memory Leak when call `push.on\('registration'`. so `Push Plugin register called` not called [\#743](https://github.com/phonegap/phonegap-plugin-push/issues/743) -- l [\#739](https://github.com/phonegap/phonegap-plugin-push/issues/739) -- \[testing issue template\] ignore me [\#717](https://github.com/phonegap/phonegap-plugin-push/issues/717) -- Incorrect init option "vibration" in a few ios samples on PAYLOAD.md [\#713](https://github.com/phonegap/phonegap-plugin-push/issues/713) -- android M wear case [\#691](https://github.com/phonegap/phonegap-plugin-push/issues/691) -- Incorrect document detailing \(PHONEGAP\_BUILD.md\) [\#686](https://github.com/phonegap/phonegap-plugin-push/issues/686) -- Windows Phone 8.1, not fired plugin methods [\#526](https://github.com/phonegap/phonegap-plugin-push/issues/526) - -## [1.6.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.6.0) (2016-03-09) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.5.3...1.6.0) - -**Implemented enhancements:** - -- Background processing with coldstart on iOS [\#583](https://github.com/phonegap/phonegap-plugin-push/issues/583) - -**Fixed bugs:** - -- Android: notification does not dismiss after selection button \(1.6.x dev\) [\#610](https://github.com/phonegap/phonegap-plugin-push/issues/610) - -**Closed issues:** - -- XDK doesn't work with v1.5.x. Are you going to have a non-gradle version for v1.5.x [\#675](https://github.com/phonegap/phonegap-plugin-push/issues/675) -- emoji support [\#668](https://github.com/phonegap/phonegap-plugin-push/issues/668) -- iOS sound not found \[edited with new debug info\] [\#667](https://github.com/phonegap/phonegap-plugin-push/issues/667) -- Push notification register APN to GCM Problem [\#665](https://github.com/phonegap/phonegap-plugin-push/issues/665) -- IOS Never fire the registration event [\#659](https://github.com/phonegap/phonegap-plugin-push/issues/659) -- Badge count inaccurate [\#651](https://github.com/phonegap/phonegap-plugin-push/issues/651) -- Android Icon options in phonegap-plugin-push@1.2.3 [\#648](https://github.com/phonegap/phonegap-plugin-push/issues/648) -- Getting same registration id when re-register [\#641](https://github.com/phonegap/phonegap-plugin-push/issues/641) -- Callback not called unless you register to GCM everytime you open the app [\#626](https://github.com/phonegap/phonegap-plugin-push/issues/626) -- How to make GCM show alert automatically ios [\#602](https://github.com/phonegap/phonegap-plugin-push/issues/602) -- Shoddy image for notification icon,status bar icon? [\#587](https://github.com/phonegap/phonegap-plugin-push/issues/587) -- ERROR: Plugin 'PushNotification' not found [\#568](https://github.com/phonegap/phonegap-plugin-push/issues/568) -- ar [\#533](https://github.com/phonegap/phonegap-plugin-push/issues/533) -- No sound and vibration for GCM when built with Cordova but Ok with PhoneBuild [\#520](https://github.com/phonegap/phonegap-plugin-push/issues/520) - -## [1.5.3](https://github.com/phonegap/phonegap-plugin-push/tree/1.5.3) (2016-01-14) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.5.2...1.5.3) - -**Fixed bugs:** - -- Android 4.1 and AppOpsManager [\#495](https://github.com/phonegap/phonegap-plugin-push/issues/495) - -**Closed issues:** - -- iOS Building Error [\#507](https://github.com/phonegap/phonegap-plugin-push/issues/507) -- \[FIX\] notification not fired when app is in background/killed ? Check this out [\#502](https://github.com/phonegap/phonegap-plugin-push/issues/502) -- Which Sender ID to use [\#485](https://github.com/phonegap/phonegap-plugin-push/issues/485) -- coldstart not documented [\#483](https://github.com/phonegap/phonegap-plugin-push/issues/483) -- Android: iconColor doesn't work in hexadecimal \(\#RRGGBB\) format [\#480](https://github.com/phonegap/phonegap-plugin-push/issues/480) -- Cannot find symbol variable INSTANCE\_ID\_SCOPE [\#477](https://github.com/phonegap/phonegap-plugin-push/issues/477) -- notification event not fired on cold start on Android 5 [\#469](https://github.com/phonegap/phonegap-plugin-push/issues/469) -- Push notifications not working with iPhone6 + ios 9.2? [\#462](https://github.com/phonegap/phonegap-plugin-push/issues/462) -- UTF8 support on android: the notification text \(on android only\) is shown with "???" [\#461](https://github.com/phonegap/phonegap-plugin-push/issues/461) -- example application? [\#460](https://github.com/phonegap/phonegap-plugin-push/issues/460) -- build fail in ios - version 1.5.2 [\#458](https://github.com/phonegap/phonegap-plugin-push/issues/458) -- Getting NotRegistered error when sending GCM push notification, but the device never unregistered [\#419](https://github.com/phonegap/phonegap-plugin-push/issues/419) -- Changelog neglected [\#412](https://github.com/phonegap/phonegap-plugin-push/issues/412) - -## [1.5.2](https://github.com/phonegap/phonegap-plugin-push/tree/1.5.1) (2015-12-21) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.5.1...1.5.2) - -**Fixed bugs:** - -- notification\_applicationDidBecomeActive method [\#447](https://github.com/phonegap/phonegap-plugin-push/issues/447) - -## [1.5.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.5.1) (2015-12-18) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.5.0...1.5.1) - -**Closed issues:** - -- Unsubscribing to topics should not clear event handlers [\#443](https://github.com/phonegap/phonegap-plugin-push/issues/443) - -## [1.5.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.5.0) (2015-12-18) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.4.5...1.5.0) - -**Fixed bugs:** - -- Make sure iOS/Android can receive the same GCM payload [\#401](https://github.com/phonegap/phonegap-plugin-push/issues/401) - -**Closed issues:** - -- Using stacking notifications but only able to process one [\#435](https://github.com/phonegap/phonegap-plugin-push/issues/435) -- Cant find stacking docs [\#430](https://github.com/phonegap/phonegap-plugin-push/issues/430) -- Android Marshmallow 6.0 push icon [\#422](https://github.com/phonegap/phonegap-plugin-push/issues/422) -- Distinguish between 'android' or 'ios' on registration event [\#418](https://github.com/phonegap/phonegap-plugin-push/issues/418) -- Phonegap Build Issues for 1.4.X [\#417](https://github.com/phonegap/phonegap-plugin-push/issues/417) -- using in Ionic [\#416](https://github.com/phonegap/phonegap-plugin-push/issues/416) -- notification event not called on ios [\#414](https://github.com/phonegap/phonegap-plugin-push/issues/414) -- \[docs\] detail on deviceready dependency [\#410](https://github.com/phonegap/phonegap-plugin-push/issues/410) -- iOS: Plugin does not start [\#404](https://github.com/phonegap/phonegap-plugin-push/issues/404) -- Process notifications in background [\#398](https://github.com/phonegap/phonegap-plugin-push/issues/398) -- On iOS 9 the badge does not clear [\#395](https://github.com/phonegap/phonegap-plugin-push/issues/395) -- Background notification OK, but event "notification" never called [\#387](https://github.com/phonegap/phonegap-plugin-push/issues/387) -- Android action button callback not triggered [\#298](https://github.com/phonegap/phonegap-plugin-push/issues/298) - -## [1.4.5](https://github.com/phonegap/phonegap-plugin-push/tree/1.4.5) (2015-12-03) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.4.4...1.4.5) - -**Fixed bugs:** - -- register -\> unregister lifecycle [\#368](https://github.com/phonegap/phonegap-plugin-push/issues/368) - -**Closed issues:** - -- jshint support [\#380](https://github.com/phonegap/phonegap-plugin-push/issues/380) -- Platform support [\#379](https://github.com/phonegap/phonegap-plugin-push/issues/379) -- Ionic implemenation [\#364](https://github.com/phonegap/phonegap-plugin-push/issues/364) -- on registration callback getting called repeatedly. [\#353](https://github.com/phonegap/phonegap-plugin-push/issues/353) -- on\("notification"\) dont fire when the app its open [\#351](https://github.com/phonegap/phonegap-plugin-push/issues/351) - -## [1.4.4](https://github.com/phonegap/phonegap-plugin-push/tree/1.4.4) (2015-11-20) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.4.3...1.4.4) - -**Fixed bugs:** - -- InstanceID.getToken\(\) not called in an Intent [\#354](https://github.com/phonegap/phonegap-plugin-push/issues/354) -- Handle both data and notification payloads in the same GCM push [\#343](https://github.com/phonegap/phonegap-plugin-push/issues/343) -- \[INSTALL\_FAILED\_CONFLICTING\_PROVIDER\] [\#320](https://github.com/phonegap/phonegap-plugin-push/issues/320) -- Getting "Error : Empty registration ID received from GCM" [\#315](https://github.com/phonegap/phonegap-plugin-push/issues/315) - -**Closed issues:** - -- xcode build fails with phonegap-plugin-push [\#358](https://github.com/phonegap/phonegap-plugin-push/issues/358) -- App crashes after adding push plugin and wikipedia app installed [\#357](https://github.com/phonegap/phonegap-plugin-push/issues/357) -- Conflict when compiling with com.google.maps [\#355](https://github.com/phonegap/phonegap-plugin-push/issues/355) - -## [1.4.3](https://github.com/phonegap/phonegap-plugin-push/tree/1.4.3) (2015-11-18) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.4.2...1.4.3) - -**Closed issues:** - -- \[Question\] about the action's icon color [\#348](https://github.com/phonegap/phonegap-plugin-push/issues/348) -- Can I access Web API's from 'notification' handler? [\#335](https://github.com/phonegap/phonegap-plugin-push/issues/335) -- Init Error: Missing Instance ID Service [\#334](https://github.com/phonegap/phonegap-plugin-push/issues/334) -- Install issue [\#332](https://github.com/phonegap/phonegap-plugin-push/issues/332) -- Multiple Apps gets error [\#330](https://github.com/phonegap/phonegap-plugin-push/issues/330) -- Can't find variable PushNotification [\#328](https://github.com/phonegap/phonegap-plugin-push/issues/328) -- When app is in background, clicking on Android notification in shade opens app but does not trigger the on\('notification'\) event handler [\#326](https://github.com/phonegap/phonegap-plugin-push/issues/326) -- "Missing Command Error" when running in browser [\#318](https://github.com/phonegap/phonegap-plugin-push/issues/318) -- Small icon not working [\#316](https://github.com/phonegap/phonegap-plugin-push/issues/316) -- Duplicate push notifications happening on iOS when phone is unlocked [\#309](https://github.com/phonegap/phonegap-plugin-push/issues/309) -- Is it possible to add badge on Android portion. [\#308](https://github.com/phonegap/phonegap-plugin-push/issues/308) -- \[just a question\] about the priority [\#306](https://github.com/phonegap/phonegap-plugin-push/issues/306) -- Android - After unregister and reregister no notifications [\#304](https://github.com/phonegap/phonegap-plugin-push/issues/304) -- Amazon-Fireos and Blackberry 10 support [\#300](https://github.com/phonegap/phonegap-plugin-push/issues/300) -- 1.4.x not showing notification on Android [\#299](https://github.com/phonegap/phonegap-plugin-push/issues/299) -- "push.unregister" not really work in iOS [\#296](https://github.com/phonegap/phonegap-plugin-push/issues/296) - -## [1.4.2](https://github.com/phonegap/phonegap-plugin-push/tree/1.4.2) (2015-11-03) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.4.1...1.4.2) - -**Closed issues:** - -- data.registrationId is empty string "" on register event callback [\#295](https://github.com/phonegap/phonegap-plugin-push/issues/295) - -## [1.4.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.4.1) (2015-11-02) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.4.0...1.4.1) - -## [1.4.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.4.0) (2015-10-27) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.3.0...1.4.0) - -**Implemented enhancements:** - -- Use Google's InstanceID API [\#188](https://github.com/phonegap/phonegap-plugin-push/issues/188) - -**Closed issues:** - -- How to handle a re-installed app? [\#203](https://github.com/phonegap/phonegap-plugin-push/issues/203) -- interactive push notifications? [\#266](https://github.com/phonegap/phonegap-plugin-push/issues/266) -- Empty registrationId Android [\#265](https://github.com/phonegap/phonegap-plugin-push/issues/265) -- Run callback when clicking of notification body [\#261](https://github.com/phonegap/phonegap-plugin-push/issues/261) -- Android BUILD FAILED [\#251](https://github.com/phonegap/phonegap-plugin-push/issues/251) -- Re-register [\#250](https://github.com/phonegap/phonegap-plugin-push/issues/250) -- how to work in background ? [\#249](https://github.com/phonegap/phonegap-plugin-push/issues/249) -- installing plugin [\#244](https://github.com/phonegap/phonegap-plugin-push/issues/244) -- No Sound and vibration [\#242](https://github.com/phonegap/phonegap-plugin-push/issues/242) -- Unable to build apk [\#241](https://github.com/phonegap/phonegap-plugin-push/issues/241) -- still having problems with build. [\#239](https://github.com/phonegap/phonegap-plugin-push/issues/239) -- Registering on iOS 9 [\#238](https://github.com/phonegap/phonegap-plugin-push/issues/238) -- Custom sound repeated multiple times on Android [\#237](https://github.com/phonegap/phonegap-plugin-push/issues/237) -- Android: status bar notification is not shown [\#236](https://github.com/phonegap/phonegap-plugin-push/issues/236) -- Multiple Push Notifications - phonegap build [\#234](https://github.com/phonegap/phonegap-plugin-push/issues/234) -- error: cannot find symbol String token = InstanceID.getInstance\(getApplicationContext\(\)\).getToken\(senderID, GCM\); [\#231](https://github.com/phonegap/phonegap-plugin-push/issues/231) -- Problem using "ledColor" and "VibrationPattern" [\#229](https://github.com/phonegap/phonegap-plugin-push/issues/229) -- Notificaction event receive, but not notification showing on android [\#228](https://github.com/phonegap/phonegap-plugin-push/issues/228) -- Events for registration not being fired [\#227](https://github.com/phonegap/phonegap-plugin-push/issues/227) -- 'registration' event not firing on windows phone [\#224](https://github.com/phonegap/phonegap-plugin-push/issues/224) -- Can i subscribe to a topic in using plugin? [\#219](https://github.com/phonegap/phonegap-plugin-push/issues/219) -- GCMIntentService.java:472: error: cannot find symbol iconColor [\#217](https://github.com/phonegap/phonegap-plugin-push/issues/217) -- Push Plugin registering on iOS 9 Devices but not showing Notification [\#216](https://github.com/phonegap/phonegap-plugin-push/issues/216) -- Receiving a notification "outside app" while in it? [\#213](https://github.com/phonegap/phonegap-plugin-push/issues/213) -- iOS push not working for device tokens when spaces removed [\#212](https://github.com/phonegap/phonegap-plugin-push/issues/212) -- Error: Plugin PushPlugin failed to install. [\#210](https://github.com/phonegap/phonegap-plugin-push/issues/210) -- Build error [\#205](https://github.com/phonegap/phonegap-plugin-push/issues/205) -- Android push.on\('registration', cb\) fires correctly on device, but not in emulator. [\#204](https://github.com/phonegap/phonegap-plugin-push/issues/204) -- 1.3.0 version not compatible with "crosswalk" by PGB [\#199](https://github.com/phonegap/phonegap-plugin-push/issues/199) -- How to get data on didReceiveNotification Background Process [\#198](https://github.com/phonegap/phonegap-plugin-push/issues/198) -- PushNotification is not defined in some devices [\#196](https://github.com/phonegap/phonegap-plugin-push/issues/196) -- not getting notifications on the Android device [\#195](https://github.com/phonegap/phonegap-plugin-push/issues/195) -- Installation Errors [\#186](https://github.com/phonegap/phonegap-plugin-push/issues/186) -- IOS: on registration fired twice [\#185](https://github.com/phonegap/phonegap-plugin-push/issues/185) -- Build failed with exit code 8 [\#184](https://github.com/phonegap/phonegap-plugin-push/issues/184) -- iOS: Not able to schedule local notification after adding the plugin [\#183](https://github.com/phonegap/phonegap-plugin-push/issues/183) -- How to show multiple notifications individually in android? [\#181](https://github.com/phonegap/phonegap-plugin-push/issues/181) -- iOS init option type [\#180](https://github.com/phonegap/phonegap-plugin-push/issues/180) -- Building for Android is a quest [\#179](https://github.com/phonegap/phonegap-plugin-push/issues/179) -- How do i tell if the user open the app by tapping the notification? [\#176](https://github.com/phonegap/phonegap-plugin-push/issues/176) -- IOS custom push sound when app is in background [\#175](https://github.com/phonegap/phonegap-plugin-push/issues/175) -- Hi guys please post full working procedure, I'm not able to get registration id also. Please help [\#174](https://github.com/phonegap/phonegap-plugin-push/issues/174) -- Has anyone tested this plugin on windows? [\#173](https://github.com/phonegap/phonegap-plugin-push/issues/173) - -## [1.3.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.3.0) (2015-09-21) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.2.3...1.3.0) - -**Implemented enhancements:** - -- How to use GCM 3.0 with this plugin? [\#127](https://github.com/phonegap/phonegap-plugin-push/issues/127) -- Android: possibility to send a notification with a title and without message [\#122](https://github.com/phonegap/phonegap-plugin-push/issues/122) -- Enhancement - Led, Vibration Pattern, Priority on Android [\#105](https://github.com/phonegap/phonegap-plugin-push/issues/105) - -**Fixed bugs:** - -- It is using in gcm data.additionalData ? [\#126](https://github.com/phonegap/phonegap-plugin-push/issues/126) -- iOS notification from cold boot [\#117](https://github.com/phonegap/phonegap-plugin-push/issues/117) -- Notification LED is not working [\#97](https://github.com/phonegap/phonegap-plugin-push/issues/97) - -**Closed issues:** - -- Know which version is used in build service [\#151](https://github.com/phonegap/phonegap-plugin-push/issues/151) -- Registration is not working in IOS9 [\#150](https://github.com/phonegap/phonegap-plugin-push/issues/150) -- build fail on android [\#149](https://github.com/phonegap/phonegap-plugin-push/issues/149) -- iconColor does not set icon background on Android [\#146](https://github.com/phonegap/phonegap-plugin-push/issues/146) -- Prevent windows toast notification when in foreground [\#145](https://github.com/phonegap/phonegap-plugin-push/issues/145) -- How to implement push notification for ios with this plug-in? [\#143](https://github.com/phonegap/phonegap-plugin-push/issues/143) -- After installing this plugin I can't build on Android [\#141](https://github.com/phonegap/phonegap-plugin-push/issues/141) -- version 1.2.3 [\#134](https://github.com/phonegap/phonegap-plugin-push/issues/134) -- New inbox style on android [\#131](https://github.com/phonegap/phonegap-plugin-push/issues/131) -- impossible to install the phonegap-plugin-push Error [\#130](https://github.com/phonegap/phonegap-plugin-push/issues/130) -- Hello, i am developing a cordova app which requires push notifications to be sent to users android phone, so i tried using this new phonegap push plugin as old one is deprecated, and it keeps giving me an error in console: Uncaught ReferenceError: module is not defined --- Line 154 Push.js and i dont have much experience with cordova, so can anyone assist me ? [\#128](https://github.com/phonegap/phonegap-plugin-push/issues/128) -- INVALID\_REGISTRATION when http post request with to IOS [\#123](https://github.com/phonegap/phonegap-plugin-push/issues/123) -- Andriod :More than 2 notifications in status bar it is not works. [\#121](https://github.com/phonegap/phonegap-plugin-push/issues/121) -- Release notes for 1.2.x [\#119](https://github.com/phonegap/phonegap-plugin-push/issues/119) -- Google cloud messaging GCM - Push Notification not being sent \(Server Side\) [\#110](https://github.com/phonegap/phonegap-plugin-push/issues/110) - -## [1.2.3](https://github.com/phonegap/phonegap-plugin-push/tree/1.2.3) (2015-09-08) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.2.2...1.2.3) - -**Fixed bugs:** - -- Notification not showing..... [\#101](https://github.com/phonegap/phonegap-plugin-push/issues/101) -- Same data payload for messages with action buttons [\#90](https://github.com/phonegap/phonegap-plugin-push/issues/90) - -**Closed issues:** - -- Notification doesn't show the app icon [\#112](https://github.com/phonegap/phonegap-plugin-push/issues/112) -- Notification doesn't show the app icon [\#111](https://github.com/phonegap/phonegap-plugin-push/issues/111) -- Issue with plugin facebook connect [\#107](https://github.com/phonegap/phonegap-plugin-push/issues/107) -- Cordova Support [\#99](https://github.com/phonegap/phonegap-plugin-push/issues/99) -- Uncaught ReferenceError: cordova is not defined, http://localhost:8100/lib/push.js, Line: 7 [\#98](https://github.com/phonegap/phonegap-plugin-push/issues/98) -- Notifications never received on Android [\#96](https://github.com/phonegap/phonegap-plugin-push/issues/96) -- How know the way the app was launched [\#95](https://github.com/phonegap/phonegap-plugin-push/issues/95) -- Android, example doesn't work when it goes into background [\#94](https://github.com/phonegap/phonegap-plugin-push/issues/94) -- Utilizing push plugin [\#91](https://github.com/phonegap/phonegap-plugin-push/issues/91) - -## [1.2.2](https://github.com/phonegap/phonegap-plugin-push/tree/1.2.2) (2015-08-31) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.2.1...1.2.2) - -**Closed issues:** - -- PushPlugin notification icon is too big [\#88](https://github.com/phonegap/phonegap-plugin-push/issues/88) - -## [1.2.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.2.1) (2015-08-31) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.2.0...1.2.1) - -**Implemented enhancements:** - -- Question about GCM Notifications and data in the message payload [\#87](https://github.com/phonegap/phonegap-plugin-push/issues/87) - -**Fixed bugs:** - -- Notification callback for pushes without a message [\#80](https://github.com/phonegap/phonegap-plugin-push/issues/80) - -**Closed issues:** - -- Android: No notification displayed on device. Notification event never called. [\#86](https://github.com/phonegap/phonegap-plugin-push/issues/86) -- it seem no wp8 version for now [\#56](https://github.com/phonegap/phonegap-plugin-push/issues/56) - -## [1.2.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.2.0) (2015-08-25) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.1.1...1.2.0) - -**Implemented enhancements:** - -- Implement Inbox style for Android [\#74](https://github.com/phonegap/phonegap-plugin-push/issues/74) -- multi-line text support [\#63](https://github.com/phonegap/phonegap-plugin-push/issues/63) - -**Fixed bugs:** - -- Pushes being deleted from notification bar when cold start [\#67](https://github.com/phonegap/phonegap-plugin-push/issues/67) - -**Closed issues:** - -- oficial push plugin and windows and wp8 compatibility [\#71](https://github.com/phonegap/phonegap-plugin-push/issues/71) -- On Android, GCMIntentService.onError\(\) doesn't get passed to the JavaScript "error" event [\#65](https://github.com/phonegap/phonegap-plugin-push/issues/65) -- Android: add property to vibrate phone on received notification [\#61](https://github.com/phonegap/phonegap-plugin-push/issues/61) -- push.on =\> "registration" will trigger twice times that only in iOS [\#57](https://github.com/phonegap/phonegap-plugin-push/issues/57) - -## [1.1.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.1.1) (2015-07-27) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.1.0...1.1.1) - -## [1.1.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.1.0) (2015-07-27) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.0.1...1.1.0) - -**Implemented enhancements:** - -- iOS doesn't add foreground key [\#41](https://github.com/phonegap/phonegap-plugin-push/issues/41) -- Android: Notification icon problem [\#20](https://github.com/phonegap/phonegap-plugin-push/issues/20) -- iOS badge number [\#18](https://github.com/phonegap/phonegap-plugin-push/issues/18) -- How i can set icons for push notifications in status bar and push view in android [\#14](https://github.com/phonegap/phonegap-plugin-push/issues/14) -- Support Win8.1 + Phone 8.1 Universal Apps \(WNS\), drop support for WP8.0 \(MPNS\) [\#13](https://github.com/phonegap/phonegap-plugin-push/issues/13) - -**Fixed bugs:** - -- iOS only reads out "aps" payload [\#29](https://github.com/phonegap/phonegap-plugin-push/issues/29) -- Event not fired when in background [\#24](https://github.com/phonegap/phonegap-plugin-push/issues/24) -- Custom notification sound in background mode? [\#17](https://github.com/phonegap/phonegap-plugin-push/issues/17) - -**Closed issues:** - -- iOS only receives first notification in foreground [\#42](https://github.com/phonegap/phonegap-plugin-push/issues/42) -- Cannot register on iOS [\#30](https://github.com/phonegap/phonegap-plugin-push/issues/30) -- Fix Android paths in src folder [\#23](https://github.com/phonegap/phonegap-plugin-push/issues/23) -- PushNotification not defined [\#21](https://github.com/phonegap/phonegap-plugin-push/issues/21) -- Error trying to remove the plugin [\#19](https://github.com/phonegap/phonegap-plugin-push/issues/19) -- Handling multiple notifications on Android devices [\#12](https://github.com/phonegap/phonegap-plugin-push/issues/12) -- PGB \(build.phonegap.com\) problem [\#11](https://github.com/phonegap/phonegap-plugin-push/issues/11) -- reporting location via gcm [\#6](https://github.com/phonegap/phonegap-plugin-push/issues/6) - -**Merged pull requests:** - -- Updating Readme to document toast capable setting [\#47](https://github.com/phonegap/phonegap-plugin-push/pull/47) ([rakatyal](https://github.com/rakatyal)) -- fix issue \#41 [\#44](https://github.com/phonegap/phonegap-plugin-push/pull/44) ([Deminetix](https://github.com/Deminetix)) -- fix issue \#42 [\#43](https://github.com/phonegap/phonegap-plugin-push/pull/43) ([Deminetix](https://github.com/Deminetix)) -- Adding hyperlinks to README [\#40](https://github.com/phonegap/phonegap-plugin-push/pull/40) ([rakatyal](https://github.com/rakatyal)) -- Updating Readme [\#37](https://github.com/phonegap/phonegap-plugin-push/pull/37) ([rakatyal](https://github.com/rakatyal)) -- Adding windows support to plugin [\#36](https://github.com/phonegap/phonegap-plugin-push/pull/36) ([rakatyal](https://github.com/rakatyal)) -- Raghav/update [\#35](https://github.com/phonegap/phonegap-plugin-push/pull/35) ([rakatyal](https://github.com/rakatyal)) -- Adding behavior for different notification types [\#28](https://github.com/phonegap/phonegap-plugin-push/pull/28) ([rakatyal](https://github.com/rakatyal)) -- Initial commit to add support for windows universal platform [\#15](https://github.com/phonegap/phonegap-plugin-push/pull/15) ([rakatyal](https://github.com/rakatyal)) - -## [1.0.1](https://github.com/phonegap/phonegap-plugin-push/tree/1.0.1) (2015-06-08) -[Full Changelog](https://github.com/phonegap/phonegap-plugin-push/compare/1.0.0...1.0.1) - -**Closed issues:** - -- documentation "senderId" correction [\#10](https://github.com/phonegap/phonegap-plugin-push/issues/10) -- add to our ci page [\#9](https://github.com/phonegap/phonegap-plugin-push/issues/9) -- Update installation instructions [\#7](https://github.com/phonegap/phonegap-plugin-push/issues/7) - -## [1.0.0](https://github.com/phonegap/phonegap-plugin-push/tree/1.0.0) (2015-06-05) -**Closed issues:** - -- Update code using enabledRemoteNotificationTypes because it is “not supported in iOS 8†[\#8](https://github.com/phonegap/phonegap-plugin-push/issues/8) -- Register method not working [\#4](https://github.com/phonegap/phonegap-plugin-push/issues/4) -- Publish plugin to npm [\#3](https://github.com/phonegap/phonegap-plugin-push/issues/3) -- Update example to use new API [\#2](https://github.com/phonegap/phonegap-plugin-push/issues/2) -- Lowercase Example/ directory [\#1](https://github.com/phonegap/phonegap-plugin-push/issues/1) - - - -\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* diff --git a/StoneIsland/plugins/phonegap-plugin-push/README.md b/StoneIsland/plugins/phonegap-plugin-push/README.md deleted file mode 100644 index 8f9ff5e9..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/README.md +++ /dev/null @@ -1,26 +0,0 @@ -#phonegap-plugin-push [](https://travis-ci.org/phonegap/phonegap-plugin-push) - -> Register and receive push notifications - -# What is this? - -This plugin offers support to receive and handle native push notifications with a **single unified API**. - -Starting with version `1.9.0`, this plugin will support `CocoaPods` installation of the `Google Cloud Messaging` library. More details are available in the [Installation](docs/INSTALLATION.md#cocoapods) documentation. - -- [Reporting Issues](docs/ISSUES.md) -- [Installation](docs/INSTALLATION.md) -- [API reference](docs/API.md) -- [Typescript support](docs/TYPESCRIPT.md) -- [Examples](docs/EXAMPLES.md) -- [Platform support](docs/PLATFORM_SUPPORT.md) -- [Cloud build support (PG Build, IntelXDK)](docs/PHONEGAP_BUILD.md) -- [Push notification payload details](docs/PAYLOAD.md) -- [Contributing](.github/CONTRIBUTING.md) -- [License (MIT)](MIT-LICENSE) - - -# Do you like tutorial? You get tutorial! - - - [PhoneGap Day US Push Workshop 2016 (using node-gcm)](http://macdonst.github.io/push-workshop/) - - [PhoneGap Day EU Push Workshop 2016 (using PhoneGap Push)](http://macdonst.github.io/push-workshop-eu/) diff --git a/StoneIsland/plugins/phonegap-plugin-push/bower.json b/StoneIsland/plugins/phonegap-plugin-push/bower.json deleted file mode 100644 index 79676644..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/bower.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "phonegap-plugin-push", - "description": "bower package for server side javascript", - "main": "www/push.js", - "authors": [ - "Adobe PhoneGap Team" - ], - "license": "APL", - "keywords": [ - "ecosystem:cordova", - "ecosystem:phonegap", - "cordova-ios", - "cordova-android", - "cordova-windows", - "cordova-browser" - ], - "homepage": "https://github.com/phonegap/phonegap-plugin-push", - "moduleType": [], - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ] -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/API.md b/StoneIsland/plugins/phonegap-plugin-push/docs/API.md deleted file mode 100644 index e0481af8..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/API.md +++ /dev/null @@ -1,425 +0,0 @@ -# API - -- [.init()](#pushnotificationinitoptions) -- [.hasPermission() - Android & iOS only](#pushnotificationhaspermissionsuccesshandler---android--ios-only) -- [push.on()](#pushonevent-callback) - - [push.on('registration')](#pushonregistration-callback) - - [push.on('notification')](#pushonnotification-callback) - - [push.on('error')](#pushonerror-callback) -- [push.off()](#pushoffevent-callback) -- [push.unregister()](#pushunregistersuccesshandler-errorhandler-topics) -- [push.subscribe()](#pushsubscribetopic-successhandler-errorhandler) -- [push.unsubscribe()](#pushunsubscribetopic-successhandler-errorhandler) -- [push.setApplicationIconBadgeNumber() - iOS & Android only](#pushsetapplicationiconbadgenumbersuccesshandler-errorhandler-count---ios--android-only) -- [push.getApplicationIconBadgeNumber() - iOS only](#pushgetapplicationiconbadgenumbersuccesshandler-errorhandler---ios-only) -- [push.finish() - iOS only](#pushfinishsuccesshandler-errorhandler-id---ios-only) -- [push.clearAllNotifications() - iOS & Android only](#pushclearallnotificationssuccesshandler-errorhandler---ios--android-only) - -## PushNotification.init(options) - -Initializes the plugin on the native side. - -**Note:** like all plugins you must wait until you receive the [`deviceready`](https://cordova.apache.org/docs/en/5.4.0/cordova/events/events.deviceready.html) event before calling `PushNotification.init()`. - -**Note:** you will want to call `PushNotification.init()` each time your app starts. The remote push service can periodically reset your registration ID so this ensures you have the correct value. - -### Returns - -- Instance of `PushNotification`. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`options` | `Object` | `{}` | An object describing relevant specific options for all target platforms. - -All available option attributes are described bellow. Currently, there are no Windows specific options. - -#### Android - -Attribute | Type | Default | Description ---------- | ---- | ------- | ----------- -`android.senderID` | `string` | | Maps to the project number in the Google Developer Console. -`android.icon` | `string` | | Optional. The name of a drawable resource to use as the small-icon. The name should not include the extension. -`android.iconColor` | `string` | | Optional. Sets the background color of the small icon on Android 5.0 and greater. [Supported Formats](http://developer.android.com/reference/android/graphics/Color.html#parseColor(java.lang.String)) -`android.sound` | `boolean` | `true` | Optional. If `true` it plays the sound specified in the push data or the default system sound. -`android.vibrate` | `boolean` | `true` | Optional. If `true` the device vibrates on receipt of notification. -`android.clearBadge` | `boolean` | `false` | Optional. If `true` the icon badge will be cleared on init and before push messages are processed. -`android.clearNotifications` | `boolean` | `true` | Optional. If `true` the app clears all pending notifications when it is closed. -`android.forceShow` | `boolean` | `false` | Optional. Controls the behavior of the notification when app is in foreground. If `true` and app is in foreground, it will show a notification in the notification drawer, the same way as when the app is in background (and `on('notification')` callback will be called *only when the user clicks the notification*). When `false` and app is in foreground, the `on('notification')` callback will be called immediately. -`android.topics` | `array` | `[]` | Optional. If the array contains one or more strings each string will be used to subscribe to a GcmPubSub topic. - -#### Browser - -Attribute | Type | Default | Description ---------- | ---- | ------- | ----------- -`browser.pushServiceURL` | `string` | `http://push.api.phonegap.com/v1/push` | Optional. URL for the push server you want to use. - -#### iOS - -All iOS boolean options can also be specified as `string` - -Attribute | Type | Default | Description ---------- | ---- | ------- | ----------- -`ios.alert` | `boolean` | `false` | Optional. If `true` the device shows an alert on receipt of notification. **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings>Notifications>`App Name`. This is normal iOS behaviour. -`ios.badge` | `boolean` | `false` | Optional. If `true` the device sets the badge number on receipt of notification. **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings>Notifications>`App Name`. This is normal iOS behaviour. -`ios.sound` | `boolean` | `false` | Optional. If `true` the device plays a sound on receipt of notification. **Note:** the value you set this option to the first time you call the init method will be how the application always acts. Once this is set programmatically in the init method it can only be changed manually by the user in Settings>Notifications>`App Name`. This is normal iOS behaviour. -`ios.clearBadge` | `boolean` | `false` | Optional. If `true` the badge will be cleared on app startup. -`ios.categories` | `Object` | `{}` | Optional. The data required in order to enabled Action Buttons for iOS. See [Action Buttons on iOS](https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#action-buttons-1) for more details. - -#### iOS GCM support - -The following properties are used if you want use GCM on iOS. - -Attribute | Type | Default | Description ---------- | ---- | ------- | ----------- -`ios.senderID` | `string` | `undefined` (Native) | Maps to the project number in the Google Developer Console. Setting this uses GCM for notifications instead of native -`ios.gcmSandbox` | `boolean` | `false` | Whether to use prod or sandbox GCM setting. Defaults to false. -`ios.topics` | `array` | `[]` | Optional. If the array contains one or more strings each string will be used to subscribe to a GcmPubSub topic. Note: only usable in conjunction with `senderID`. - -##### How GCM on iOS works. - -First it is kind of a misnomer as GCM does not send push messages directly to devices running iOS. - -What happens is on the device side is that it registers with APNS, then that registration ID is sent to GCM which returns a different GCM specific ID. That is the ID you get from the push plugin `registration` event. - -When you send a message to GCM using that ID, what it does is look up the APNS registration ID on it's side and forward the message you sent to GCM on to APSN to deliver to your iOS device. - -Make sure that the certificate you build with matches your `gcmSandbox` value. - -- If you build your app as development and set `gcmSandbox: false` it will fail. -- If you build your app as production and set `gcmSandbox: true` it will fail. -- If you build your app as development and set `gcmSandbox: true` but haven't uploaded the development certs to Google it will fail. -- If you build your app as production and set `gcmSandbox: false` but haven't uploaded the production certs to Google it will fail. - -> Note: The integration between GCM and APNS is a bit finicky. Personally, I feel it is much better to send pushes to Android using GCM and pushes to iOS using APNS which this plugin does support. - -### Example - -```javascript -var push = PushNotification.init({ - android: { - senderID: "12345679" - }, - browser: { - pushServiceURL: 'http://push.api.phonegap.com/v1/push' - }, - ios: { - alert: "true", - badge: true, - sound: 'false' - }, - windows: {} -}); -``` - -## PushNotification.hasPermission(successHandler) - Android & iOS only - -Checks whether the push notification permission has been granted. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`successHandler` | `Function` | | Is called when the api successfully retrieves the details on the permission. - -### Callback parameters - -#### `successHandler` - -Parameter | Type | Description ---------- | ---- | ----------- -`data.isEnabled` | `Boolean` | Whether the permission for push notifications has been granted. - -### Example - -```javascript -PushNotification.hasPermission(function(data) { - if (data.isEnabled) { - console.log('isEnabled'); - } -}); -``` - -## push.on(event, callback) - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`event` | `string` | | Name of the event to listen to. See below for all the event names. -`callback` | `Function` | | Is called when the event is triggered. - -## push.on('registration', callback) - -The event `registration` will be triggered on each successful registration with the 3rd party push service. - -### Callback parameters - -Parameter | Type | Description ---------- | ---- | ----------- -`data.registrationId` | `string` | The registration ID provided by the 3rd party remote push service. - -### Example - -```javascript -push.on('registration', function(data) { - console.log(data.registrationId); -}); -``` - -For APNS users: the `registrationId` you will get will be a production or sandbox id according to how the app was built. ([Source](https://developer.apple.com/library/ios/technotes/tn2265/_index.html)) - -> Note: There is a separate persistent connection to the push service for each environment. The operating system establishes a persistent connection to the sandbox environment for development builds; ad hoc and distribution builds connect to the production environment. - - - -### Common Problems - -#### Got JSON Exception TIMEOUT - -If you run this plugin on older versions of Android and you get an error: - -``` -E/PushPlugin(20077): execute: Got JSON Exception TIMEOUT -``` - -It means you are running an older version of Google Play Services. You will need to open the Google Play Store app and update your version of Google Play Services. - -## push.on('notification', callback) - -The event `notification` will be triggered each time a push notification is received by a 3rd party push service on the device. - -### Callback parameters - -Parameter | Type | Description ---------- | ---- | ----------- -`data.message` | `string` | The text of the push message sent from the 3rd party service. -`data.title` | `string` | The optional title of the push message sent from the 3rd party service. -`data.count` | `string` | The number of messages to be displayed in the badge in iOS/Android or message count in the notification shade in Android. For windows, it represents the value in the badge notification which could be a number or a status glyph. -`data.sound` | `string` | The name of the sound file to be played upon receipt of the notification. -`data.image` | `string` | The path of the image file to be displayed in the notification. -`data.launchArgs` | `string` | The args to be passed to the application on launch from push notification. This works when notification is received in background. (Windows Only) -`data.additionalData` | `Object` | An optional collection of data sent by the 3rd party push service that does not fit in the above properties. -`data.additionalData.foreground` | `boolean` | Whether the notification was received while the app was in the foreground -`data.additionalData.coldstart` | `boolean` | Will be `true` if the application is started by clicking on the push notification, `false` if the app is already started. - -### Example - -```javascript -push.on('notification', function(data) { - console.log(data.message); - console.log(data.title); - console.log(data.count); - console.log(data.sound); - console.log(data.image); - console.log(data.additionalData); -}); -``` - -## push.on('error', callback) - -The event `error` will trigger when an internal error occurs and the cache is aborted. - -### Callback parameters - -Parameter | Type | Description ---------- | ---- | ----------- -`e` | `Error` | Standard JavaScript error object that describes the error. - -### Example - -```javascript -push.on('error', function(e) { - console.log(e.message); -}); -``` - -## push.off(event, callback) - -Removes a previously registered callback for an event. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`event` | `string` | | Name of the event type. The possible event names are the same as for the `push.on` function. -`callback` | `Function` | | The same callback used to register with `push.on`. - -### Example -```javascript -var callback = function(data){ /*...*/}; - -//Adding handler for notification event -push.on('notification', callback); - -//Removing handler for notification event -push.off('notification', callback); -``` - -**WARNING**: As stated in the example, you will have to store your event handler if you are planning to remove it. - -## push.unregister(successHandler, errorHandler, topics) - -The unregister method is used when the application no longer wants to receive push notifications. Beware that this cleans up all event handlers previously registered, so you will need to re-register them if you want them to function again without an application reload. - -If you provide a list of topics as an optional parameter then the application will unsubscribe from these topics but continue to receive other push messages. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`successHandler` | `Function` | | Is called when the api successfully unregisters. -`errorHandler` | `Function` | | Is called when the api encounters an error while unregistering. -`topics` | `Array` | | A list of topics to unsubscribe from. - -### Example - -```javascript -push.unregister(function() { - console.log('success'); -}, function() { - console.log('error'); -}); -``` - -## push.subscribe(topic, successHandler, errorHandler) - -The subscribe method is used when the application wants to subscribe a new topic to receive push notifications. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`topic` | `String` | | Topic to subscribe to. -`successHandler` | `Function` | | Is called when the api successfully subscribes. -`errorHandler` | `Function` | | Is called when the api encounters an error while subscribing. - -### Example - -```javascript -push.subscribe('my-topic', function() { - console.log('success'); -}, function(e) { - console.log('error:'); - console.log(e); -}); -``` -## push.unsubscribe(topic, successHandler, errorHandler) - -The unsubscribe method is used when the application no longer wants to receive push notifications from a specific topic but continue to receive other push messages. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`topic` | `String` | | Topic to unsubscribe from. -`successHandler` | `Function` | | Is called when the api successfully unsubscribe. -`errorHandler` | `Function` | | Is called when the api encounters an error while unsubscribing. - -### Example - -```javascript -push.unsubscribe('my-topic', function() { - console.log('success'); -}, function(e) { - console.log('error:'); - console.log(e); -}); -``` - -## push.setApplicationIconBadgeNumber(successHandler, errorHandler, count) - iOS & Android only - -Set the badge count visible when the app is not running - -> Note: badges are not supported on all Android devices. See [our payload documentation](PAYLOAD.md#badges) for more details. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`successHandler` | `Function` | | Is called when the api successfully sets the icon badge number. -`errorHandler` | `Function` | | Is called when the api encounters an error while trying to set the icon badge number. -`count` | `number` | | Indicates what number should show up in the badge. Passing 0 will clear the badge. Each `notification` event contains a `data.count` value which can be used to set the badge to correct number. - -### Example - -```javascript -push.setApplicationIconBadgeNumber(function() { - console.log('success'); -}, function() { - console.log('error'); -}, 2); -``` - -## push.getApplicationIconBadgeNumber(successHandler, errorHandler) - iOS only - -Get the current badge count visible when the app is not running - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`successHandler` | `Function` | | Is called when the api successfully retrieves the icon badge number. -`errorHandler` | `Function` | | Is called when the api encounters an error while trying to retrieve the icon badge number. - -### Callback parameters - -#### `successHandler` - -Parameter | Type | Description ---------- | ---- | ----------- -`n` | `number` | An integer which is the current badge count. - -### Example - -```javascript -push.getApplicationIconBadgeNumber(function(n) { - console.log('success', n); -}, function() { - console.log('error'); -}); -``` - -## push.finish(successHandler, errorHandler, id) - iOS only - -Tells the OS that you are done processing a background push notification. - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`successHandler` | `Function` | | Is called when the api successfully completes background push processing. -`errorHandler` | `Function` | | Is called when the api encounters an error while processing and completing the background push. -`id` | `String` | | Tells the OS which background process is complete. - -### Example - -```javascript -push.finish(function() { - console.log('success'); -}, function() { - console.log('error'); -}, 'push-1'); -``` - -## push.clearAllNotifications(successHandler, errorHandler) - iOS & Android only - -Tells the OS to clear all notifications from the Notification Center - -### Parameters - -Parameter | Type | Default | Description ---------- | ---- | ------- | ----------- -`successHandler` | `Function` | | Is called when the api successfully clears the notifications. -`errorHandler` | `Function` | | Is called when the api encounters an error when attempting to clears the notifications. - -### Example - -```javascript -push.clearAllNotifications(function() { - console.log('success'); -}, function() { - console.log('error'); -}); -``` diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/EXAMPLES.md b/StoneIsland/plugins/phonegap-plugin-push/docs/EXAMPLES.md deleted file mode 100644 index 8481e7bc..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/EXAMPLES.md +++ /dev/null @@ -1,43 +0,0 @@ -# Creating a Project From a Template - -If you want to get started with a sample project you can create a new project from the example template. - -``` -phonegap create my-app --template phonegap-template-push -``` - -## Quick Example - -```javascript -var push = PushNotification.init({ - android: { - senderID: "12345679" - }, - browser: { - pushServiceURL: 'http://push.api.phonegap.com/v1/push' - }, - ios: { - alert: "true", - badge: "true", - sound: "true" - }, - windows: {} -}); - -push.on('registration', function(data) { - // data.registrationId -}); - -push.on('notification', function(data) { - // data.message, - // data.title, - // data.count, - // data.sound, - // data.image, - // data.additionalData -}); - -push.on('error', function(e) { - // e.message -}); -``` diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/INSTALLATION.md b/StoneIsland/plugins/phonegap-plugin-push/docs/INSTALLATION.md deleted file mode 100644 index 830bbdd7..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/INSTALLATION.md +++ /dev/null @@ -1,313 +0,0 @@ -# Installation - -- [Installation Requirements](#installation-requirements) -- [Android details](#android-details) - - [Compilation](#compilation) - - [Co-existing with Facebook Plugin](#co-existing-with-facebook-plugin) - - [Common errors](#common-errors) - - [minSdkVersion === 14](#minsdkversion--14) - - [Multidex](#multidex) - - [More than one library with package name 'com.google.android.gms'](#more-than-one-library-with-package-name-comgoogleandroidgms) -- [Browser details](#browser-details) - - [Browser quirks](#browser-quirks) - - [Browser Support](#browser-support) -- [iOS details](#ios-details) - - [Xcode](#xcode) - - [Bitcode](#bitcode) - - [CocoaPods](#cocoapods) - - [Common CocoaPod Installation issues](#common-cocoapod-installation-issues) -- [Additional Resources](#additional-resources) - -## Installation Requirements - -Plugin version | Cordova CLI | Cordova Android | Cordova iOS | CocoaPods ----- | ---- | ---- | ---- | ---- -1.9.0 | 6.4.0 | 6.0.0 | 4.3.0 | 1.1.1 -1.8.0 | 3.6.3 | 4.0.0 | 4.1.0 | N/A - -To install from the command line: - -``` -phonegap plugin add phonegap-plugin-push --variable SENDER_ID="XXXXXXX" -``` -or - -``` -cordova plugin add phonegap-plugin-push --variable SENDER_ID="XXXXXXX" -``` - -It is also possible to install via repo url directly ( unstable ) - -``` -phonegap plugin add https://github.com/phonegap/phonegap-plugin-push --variable SENDER_ID="XXXXXXX" -``` - -or - -``` -cordova plugin add https://github.com/phonegap/phonegap-plugin-push --variable SENDER_ID="XXXXXXX" -``` - -Where the `XXXXXXX` in `SENDER_ID="XXXXXXX"` maps to the project number in the [Google Developer Console](https://www.google.ca/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwikqt3nyPjMAhXJ5iYKHR0qDcsQFggbMAA&url=https%3A%2F%2Fconsole.developers.google.com%2F&usg=AFQjCNF0eH059mv86nMIlRmfsf42kde-wA&sig2=BQ2BJpchw1CpGt87sk5p6w&bvm=bv.122852650,d.eWE). To find the project number login to the Google Developer Console, select your project and click the menu item in the screen shot below to display your project number. - - - -If you are not creating an Android application you can put in anything for this value. - -> Note: if you are using Ionic you may need to specify the SENDER_ID variable in your package.json. - -``` - "cordovaPlugins": [ - { - "variables": { - "SENDER_ID": "XXXXXXX" - }, - "locator": "phonegap-plugin-push" - } - ] -``` - -> Note: You need to specify the SENDER_ID variable in your config.xml if you plan on installing/restoring plugins using the prepare method. The prepare method will skip installing the plugin otherwise. - -``` -<plugin name="phonegap-plugin-push" spec="1.6.0"> - <param name="SENDER_ID" value="XXXXXXX" /> -</plugin> -``` - -## Android details - -### Compilation - -As of version 1.3.0 the plugin has been switched to using Gradle/Maven for building. - -You will need to ensure that you have installed the following items through the Android SDK Manager: - -- Android Support Library version 23 or greater -- Local Maven repository for Support Libraries (formerly Android Support Repository) version 20 or greater -- Google Play Services version 27 or greater -- Google Repository version 22 or greater - - - -For more detailed instructions on how to install the Android Support Library visit [Google's documentation](https://developer.android.com/tools/support-library/setup.html). - -*Note:* if you are using an IDE to like Eclipse, Xamarin, etc. then the Android SDK installed by those tools may not be the same version as the one used by the Cordova/PhoneGap CLI while building. Please make sure your command line tooling is up to date with the software versions above. An easy way to make sure you up to date is to run the following command: - -``` -android update sdk --no-ui --filter "extra" -``` - -### Co-existing with Facebook Plugin - -There are a number of Cordova Facebook Plugins available but the one that we recommend is [Jeduan's fork](https://github.com/jeduan/cordova-plugin-facebook4) of the original Wizcorp plugin. It is setup to use Gradle/Maven and the latest Facebook SDK properly. - -To add to your app: - -``` -phonegap plugin add --save cordova-plugin-facebook4 --variable APP_ID="App ID" --variable APP_NAME="App Name" -``` -or - -``` -cordova plugin add --save cordova-plugin-facebook4 --variable APP_ID="App ID" --variable APP_NAME="App Name" -``` - -### Common errors - -#### minSdkVersion === 14 - -If you have an issue compiling the app and you are getting an error similar to this: - -``` -* What went wrong: -Execution failed for task ':processDebugManifest'. -> Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version 15 declared in library .../platforms/android/build/intermediates/exploded-aar/com.facebook.android/facebook-android-sdk/4.6.0/AndroidManifest.xml - Suggestion: use tools:overrideLibrary="com.facebook" to force usage -``` - -Then you can add the following entry into your config.xml file in the android platform tag: - -```xml -<platform name="android"> - <preference name="android-minSdkVersion" value="15"/> - </platform> -``` - -or compile your project using the following command, if the solution above doesn't work for you. Basically add `-- --minSdkVersion=15` to the end of the command line (mind the extra `--`, it's needed): - -```bash -cordova compile android -- --minSdkVersion=15 -cordova build android -- --minSdkVersion=15 -cordova run android -- --minSdkVersion=15 -cordova emulate android -- --minSdkVersion=15 -``` - -#### Multidex - -If you have an issue compiling the app and you're getting an error similar to this (`com.android.dex.DexException: Multiple dex files define`): - -``` -UNEXPECTED TOP-LEVEL EXCEPTION: -com.android.dex.DexException: Multiple dex files define Landroid/support/annotation/AnimRes; - at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:596) - at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:554) - at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:535) - at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:171) - at com.android.dx.merge.DexMerger.merge(DexMerger.java:189) - at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:502) - at com.android.dx.command.dexer.Main.runMonoDex(Main.java:334) - at com.android.dx.command.dexer.Main.run(Main.java:277) - at com.android.dx.command.dexer.Main.main(Main.java:245) - at com.android.dx.command.Main.main(Main.java:106) -``` - -Then at least one other plugin you have installed is using an outdated way to declare dependencies such as `android-support` or `play-services-gcm`. -This causes gradle to fail, and you'll need to identify which plugin is causing it and request an update to the plugin author, so that it uses the proper way to declare dependencies for cordova. -See [this for the reference on the cordova plugin specification](https://cordova.apache.org/docs/en/5.4.0/plugin_ref/spec.html#link-18), it'll be usefull to mention it when creating an issue or requesting that plugin to be updated. - -Common plugins to suffer from this outdated dependency management are plugins related to *facebook*, *google+*, *notifications*, *crosswalk* and *google maps*. - -#### More than one library with package name 'com.google.android.gms' - -When some other packages include `cordova-google-play-services` as a dependency, such as is the case with the cordova-admob and cordova-plugin-analytics plugins, it is impossible to also add the phonegap-plugin-push, for the following error will rise during the build process: - -``` -:processDebugResources FAILED -FAILURE: Build failed with an exception. - -What went wrong: Execution failed for task ':processDebugResources'. > Error: more than one library with package name 'com.google.android.gms' -``` - -Those plugins should be using gradle to include the Google Play Services package but instead they include the play services jar directly or via a plugin dependency. So all of that is bad news. These plugins should be updated to use gradle. Please raise issues on those plugins as the change is not hard to make. - -In fact there is a PR open to do just that appfeel/analytics-google#11 for cordova-plugin-analytics. You should bug the team at appfeel to merge that PR. - -Alternatively, switch to another plugin that provides the same functionality but uses gradle: - -[https://github.com/danwilson/google-analytics-plugin](https://github.com/danwilson/google-analytics-plugin) -[https://github.com/cmackay/google-analytics-plugin](https://github.com/cmackay/google-analytics-plugin) - -## Browser details - -### Browser quirks - -For the time being push support on the browser will only work using the PhoneGap push server. - -When you run `phonegap serve` to test browser push point your browser at `http://localhost:3000`. The browser push implementation uses the W3C Push Spec's implementation which relies on ServiceWorkers and ServiceWorkers can only be accessed via the `https` protocol or via `http://localhost`. Pointing your browser at `localhost` will be the easiest way to test. - -### Browser Support - -Chrome 49+ -Firefox 46+ - -## iOS details - -### Xcode - -Xcode version 8.0 or greater is required for building this plugin. - -### Bitcode - -If you are running into a problem where the linker is complaining about bit code. For instance: - -``` -ld: '<file.o>' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) -``` - -You have two options. The first is to [disable bitcode as per this StackOverflow answer](http://stackoverflow.com/a/32466484/41679) or [upgrade to cordova-ios 4 or greater](https://cordova.apache.org/announcements/2015/12/08/cordova-ios-4.0.0.html). - -``` -cordova platform update ios@4.0.0 -``` - -### CocoaPods - -Required `cordova-cli` version: `6.4.0` - -Required `cordova-ios` version: `4.3.0` - -Version `1.9.0` (and above) of this plugin supports [CocoaPods](https://cocoapods.org) installation of the [Google Cloud Messaging](https://cocoapods.org/pods/GoogleCloudMessaging) library. - -If you are installing this plugin using `npm`, and you are using version `6.1.0` or greater of the `cordova-cli`, it will automatically download the right version of this plugin for both your platform and cli. - -If you are on a `cordova-cli` version less than `6.1.0`, you will either have to upgrade your `cordova-cli` version, or install the plugin explicitly: - -i.e. -``` -cordova plugin add phonegap-plugin-push@1.8.1 -``` - -If you are installing this plugin using a `local file reference` or a `git url`, you will have to specify the version of this plugin explicitly (see above) if you don't fulfill the `cordova-cli` and `cordova-ios` requirements. - -#### Common CocoaPod Installation issues - -If you are attempting to install this plugin and you run into this error: - -``` -Installing "phonegap-plugin-push" for ios -Failed to install 'phonegap-plugin-push':Error: pod: Command failed with exit code 1 - at ChildProcess.whenDone (/Users/smacdona/code/push151/platforms/ios/cordova/node_modules/cordova-common/src/superspawn.js:169:23) - at emitTwo (events.js:87:13) - at ChildProcess.emit (events.js:172:7) - at maybeClose (internal/child_process.js:818:16) - at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5) -Error: pod: Command failed with exit code 1 -``` - -Please run the command `pod repo update` and re-install the plugin. - -## Additional Resources - -The push plugin enables you to play sounds and display different icons during push (Android only). These additional resources need to be added to your projects `platforms` directory in order for them to be included into your final application binary. One way of doing it is to create a hook to do the copying for you on each build. - -First create a `scripts` directory in the root of your project. Next add a file to the scripts directory called `copy_resource_files.js`. The contents of the file will look something like this: - -```javascript -#!/usr/bin/env node - -// each object in the array consists of a key which refers to the source and -// the value which is the destination. -var filestocopy = [{ - "resources/android/images/logo.png": - "platforms/android/res/drawable/logo.png" -}, { - "resources/android/sounds/ring.mp3": - "platforms/android/res/raw/ring.mp3" -}, { - "resources/ios/sounds/ring.caf": - "platforms/ios/YourAppName/ring.caf" -}, ]; - -var fs = require('fs'); -var path = require('path'); - -// no need to configure below -var rootdir = process.argv[2]; - -filestocopy.forEach(function(obj) { - Object.keys(obj).forEach(function(key) { - var val = obj[key]; - var srcfile = path.join(rootdir, key); - var destfile = path.join(rootdir, val); - //console.log("copying "+srcfile+" to "+destfile); - var destdir = path.dirname(destfile); - if (fs.existsSync(srcfile) && fs.existsSync(destdir)) { - fs.createReadStream(srcfile).pipe( - fs.createWriteStream(destfile)); - } - }); -}); -``` - -Obviously, you'll need to modify the `filestocopy` variable to suit your needs. Pay attention to the destination path on iOS where you will need to replace `YourAppName`. - -Next open up your `config.xml` file and add the following line: - -```xml -<hook type="before_build" src="scripts/copy_resource_files.js" /> -``` - -Now, when you build your app the files will get copied into your platforms directory for you. - -If you are using PhoneGap Build check out these instructions on [Additional Resources](PHONEGAP_BUILD.md#additional-resources) diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/ISSUES.md b/StoneIsland/plugins/phonegap-plugin-push/docs/ISSUES.md deleted file mode 100644 index 3b3021af..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/ISSUES.md +++ /dev/null @@ -1,80 +0,0 @@ -# ISSUES - -- [Read the docs](#read-the-docs) -- [Search the issues](#search-the-issues) -- [Opening a new issue](#opening-a-new-issue) - - [Provide details](#provide-details) - - [An example issue](#an-example-issue) -- [Voting on an issue](#voting-on-an-issue) - -The following tips are for users of this plugin who want to get help. - -## Read the docs - -I'll be the first to admit that the docs are not perfect but start here at the [README](https://github.com/phonegap/phonegap-plugin-push/blob/master/README.md) to see if your problem is documented. If it isn't continue on but if you do get an answer then consider sending a documentation pull request. - -## Search the issues - -Your question may have already been answered. Make sure you search at least the repo's [issues](https://github.com/phonegap/phonegap-plugin-push/issues) before you create a new one. - -## Opening a new issue - -If you have searched the issues and haven't found anything that resembles your problem then follow these guidelines in creating a new issue. - -### Provide details - -Give as many details as possible. Issues without many details will be more difficult to debug and will encounter delays. - -Select a concise, informative title for the issue. Here's a good article on writing [subject lines](https://www.nngroup.com/articles/microcontent-how-to-write-headlines-page-titles-and-subject-lines/). - -Include the following at a minimum: -_ what version number of plugin are you using? -- which platform and version you are testing on? iOS 9.0, Android 5.0, etc. -- a detailed description of your problem. Including: - - steps to reproduce - - expected result - - actual result -- how you are sending the push data to the device, including an example payload - -You may also want to include: -- some sample code that illustrates the problem. -- logs taken while the problem was reproduced. -- screenshots! - -If the code or logs are huge, let's say over 20 lines please think about using a web service like [Gist](https://gist.github.com/) or [Pastebin](http://pastebin.com/). - -### An example issue - -**The wrong way** - -*Title:* This plugin does not work for me - -*Details:* Please fix quickly as my business depends on this plugin. - -**The right way** - -*Title:* Registration event never received on Samsung Galaxy S running Android 2.3 - -*Details:* I'm using version 1.5.2 of this plugin on my Samsung Galaxy S5 device which runs Android 4.4. I never receiving the `registration` event in my application when I expect it to return a value I can send to my push service. - -You can see the code I'm using in this gist: [https://gist.github.com/macdonst/191f74ac75b6802c047d](https://gist.github.com/macdonst/191f74ac75b6802c047d) - -And an output of the logs when trying to run the app are in this gist: [https://gist.github.com/macdonst/47549150c299080c455c](https://gist.github.com/macdonst/47549150c299080c455c) - -Please point me in the right direction. - -*Response:* - -Thanks for the detailed logs and example code by looking them over I'm sure of what your problem is. If you look at line [334](https://gist.github.com/macdonst/47549150c299080c455c#file-logcat-txt-L334) of your logcat you will see that it complains that: - -``` -I/chromium(11669): [INFO:CONSOLE(54)] "Uncaught ReferenceError: PushNotification is not defined", source: file:///android_asset/www/js/index.js (54) -``` - -This leads me to line [4](https://gist.github.com/macdonst/191f74ac75b6802c047d#file-app-js-L4) of your code where you are initializing push before you get the `deviceready` event. Like all Cordova API's you have to wait until you receive the `deviceready` event before you initialize Push. - -Check out [https://github.com/phonegap/phonegap-plugin-push/blob/20f489a90cf519f962fd957700f92115f142594b/example/www/js/index.js](https://github.com/phonegap/phonegap-plugin-push/blob/20f489a90cf519f962fd957700f92115f142594b/example/www/js/index.js) for an example of how to wait for `deviceready`. - -## Voting on an issue - -Did you know you can vote on issues in the phonegap-plugin-push repository? If you install the [ZenHub](https://chrome.google.com/webstore/detail/zenhub-for-github/ogcgkffhplmphkaahpmffcafajaocjbd) Chrome Extension you will be able to +1 issues to indicate how popular they are to the community. It's a way better way for the contributors to keep track of important issues. diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/PAYLOAD.md b/StoneIsland/plugins/phonegap-plugin-push/docs/PAYLOAD.md deleted file mode 100644 index b446612e..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/PAYLOAD.md +++ /dev/null @@ -1,1400 +0,0 @@ -- [Overview](#overview) - - [Foreground Events](#push-message-arrives-with-app-in-foreground) - - [Background Events](#push-message-arrives-with-app-in-background) - - [Tap Events](#user-clicks-on-notification-in-notification-center) -- [Android Behaviour](#android-behaviour) - - [Localization](#localization) - - [Images](#images) - - [Sound](#sound) - - [Stacking](#stacking) - - [Inbox Stacking](#inbox-stacking) - - [Action Buttons](#action-buttons) - - [In Line Replies](#in-line-replies) - - [Led in Notifications](#led-in-notifications) - - [Vibration Pattern in Notifications](#vibration-pattern-in-notifications) - - [Priority in Notifications](#priority-in-notifications) - - [Picture Messages](#picture-messages) - - [Background Notifications](#background-notifications) - - [Use of content-available: true](#use-of-content-available-true) - - [Huawei and Xiaomi Phones](#huawei-and-xiaomi-phones) - - [Application force closed](#application-force-closed) - - [Visibility](#visibility-of-notifications) - - [Badges](#badges) - - [Support for Twilio Notify](#support-for-twilio-notify) -- [iOS Behaviour](#ios-behaviour) - - [Sound](#sound-1) - - [Background Notifications](#background-notifications-1) - - [Action Buttons](#action-buttons-1) - - [Action Buttons using GCM on iOS](#action-buttons-using-gcm-on-ios) - - [GCM and Additional Data](#gcm-and-additional-data) -- [Windows Behaviour](#windows-behaviour) - - [Notifications](#notifications) - - [Setting Toast Capable Option for Windows](#setting-toast-capable-option-for-windows) - - [Disabling the default processing of notifications by Windows](#disabling-the-default-processing-of-notifications-by-windows) - - [Background Notifications](#background-notifications-2) - - -# Overview - -The following flowchart attempts to give you a picture of what happens when a push message arrives on your device when you have an app using phonegap-plugin-push. - - - -## Push message arrives with app in foreground - -- The push plugin receives the data from the remote push service and calls all of your `notification` event handlers. -- The message is *not* displayed in the devices notification center as that is not normal behaviour for Android or iOS. - -## Push message arrives with app in background - -- The push plugin receives the data from the remote push service and checks to see if there is a title or message in the data received. If there is then the message will be displayed in the devices notification center. -- Then the push plugin checks to see if the app is running. If the user has killed the application then no further processing of the push data will occur. -- If the app is running in the background the push plugin then checks to see if `content-available` exists in the push data. -- If `content-available` is set to `1` then the plugin calls all of your `notification` event handlers. - -## User clicks on notification in notification center - -- The app starts. -- Then the plugin calls all of your `notification` event handlers. - -> Note: if the push payload contained `content-available: 1` then your `notification` event handler has already been called. It is up to you to handle the double event. - -Some ways to handle this *double* event are: - -- don't include title/message in the push so it doesn't show up in the shader. -- send two pushes, one to be processed in the background the other to show up in the shade. -- include a unique ID in your push so you can check to see if you've already processed this event. - -# Android Behaviour - -## Localization - -Plugin supported localization from resources for: title, message and summaryText. - -You may use simple link to locale constant. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": {"locKey": "push_app_title"}, - "message": "Simple non-localizable text for message!" - } -} -``` - -Or use localization with formatted constants. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": {"locKey": "push_app_title"}, - "message": {"locKey": "push_message_fox", "locData": ["fox", "dog"]} - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', {"locKey": "push_app_title"}); -message.addData('message', 'Simple non-localizable text for message!'); -// Constant with formatted params -// message.addData('message', {"locKey": "push_message_fox", "locData": ["fox", "dog"]}); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -Localization must store in strings.xml - -```xml -<string name="push_app_title">@string/app_name</string> -<string name="push_message_fox">The quick brown %1$s jumps over the lazy %2$s</string> -<string name="push_summary_text">%%n%% new message(s)</string> -``` - -## Images - -By default the icon displayed in your push notification will be your apps icon. So when you initialize the plugin like this: - -```javascript -var push = PushNotification.init({ - "android": { - "senderID": "12345679" - }, - browser: { - pushServiceURL: 'http://push.api.phonegap.com/v1/push' - }, - "ios": { - "alert": "true", - "badge": "true", - "sound": "true" - }, - "windows": {} -}); -``` - -The result will look much like this: - - - -This is because Android now uses Material design and the default icon for push will be completely white. - -In order to get a better user experience you can specify an alternate icon and background color to be shown when receiving a push notification. The code would look like this: - -```javascript -var push = PushNotification.init({ - "android": { - "senderID": "123456789", - "icon": "phonegap", - "iconColor": "blue" - }, - browser: { - pushServiceURL: 'http://push.api.phonegap.com/v1/push' - }, - "ios": { - "alert": "true", - "badge": "true", - "sound": "true" - }, - "windows": {} -}); -``` - -Where *icon* is the name of an image in the Android *drawables* folder. Writing a hook to describe how to copy an image to the Android *drawables* folder is out of scope for this README but there is an [excellent tutorial](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) that you can copy. - -*iconColor* is one of the supported formats #RRGGBB or #AARRGGBB or one of the following names: 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', 'yellow', 'lightgray', 'darkgray', 'grey', 'lightgrey', 'darkgrey', 'aqua', 'fuchsia', 'lime', 'maroon', 'navy', 'olive', 'purple', 'silver', 'teal'. *iconColor* is supported on Android 5.0 and greater. - -Please follow the [Android icon design guidelines](https://www.google.com/design/spec/style/icons.html#) when creating your icon. - - - -Additionally, each push can include a large icon which is used to personalize each push. The location of the image may one of three types. - -The first is the *drawables* folder in your app. This JSON sent from GCM: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Large Icon", - "message": "Loaded from drawables folder", - "image": "twitter" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Large Icon'); -message.addData('message', 'Loaded from drawables folder.'); -message.addData('image', 'twitter'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -Would look for the *twitter* image in the drawables folder and produce the following notification. - - - -The second is the *assets* folder in your app. This JSON sent from GCM: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Large Icon", - "message": "Loaded from assets folder", - "image": "www/image/logo.png" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Large Icon'); -message.addData('message', 'Loaded from assets folder.'); -message.addData('image', 'www/image/logo.png'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -Would look for the *logo.png* file in the assets/www/img folder. Since your apps www folder gets copied into the Android assets folder it is an excellent spot to store the images without needing to write a hook to copy them to the *drawables* folder. It produces the following notification. - - - - -The third is the remote *URL*. This JSON sent from GCM: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Large Icon", - "message": "Loaded from URL", - "image": "https://dl.dropboxusercontent.com/u/887989/antshot.png" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Large Icon'); -message.addData('message', 'Loaded from URL'); -message.addData('image', 'https://dl.dropboxusercontent.com/u/887989/antshot.png'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -Produces the following notification. - - - -## Sound - -For Android there are three special values for sound you can use. The first is `default` which will play the phones default notification sound. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Default", - "message": "Plays default notification sound", - "soundname": "default" - } -} -``` - -Then second is `ringtone` which will play the phones default ringtone sound. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Ringtone", - "message": "Plays default ringtone sound", - "soundname": "ringtone" - } -} -``` -The third is the empty string which will cause for the playing of sound to be skipped. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Silece", - "message": "Skips playing any sound", - "soundname": "" - } -} -``` - -In order for your your notification to play a custom sound you will need to add the files to your Android project's `res/raw` directory. Then send the follow JSON from GCM: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Sound Test", - "message": "Loaded res/raw", - "soundname": "test" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Sound Test'); -message.addData('message', 'Loaded res/raw'); -message.addData('soundname', 'test'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -*Note:* when you specify the custom sound file name omit the file's extension. - -## Stacking - -By default when using this plugin on Android each notification that your app receives will replace the previous notification in the shade. - -If you want to see multiple notifications in the shade you will need to provide a notification ID as part of the push data sent to the app. For instance if you send: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Test Push", - "message": "Push number 1" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Test Push'); -message.addData('message', 'Push number 1'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -Followed by: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Test Push", - "message": "Push number 2" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Test Push'); -message.addData('message', 'Push number 2'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -You will only see "Push number 2" in the shade. However, if you send: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Test Push", - "message": "Push number 1", - "notId": 1 - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Test Push'); -message.addData('message', 'Push number 1'); -message.addData('notId', 1); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -and: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Test Push", - "message": "Push number 2", - "notId": 2 - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Test Push'); -message.addData('message', 'Push number 2'); -message.addData('notId', 2); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -You will see both "Push number 1" and "Push number 2" in the shade. - -## Inbox Stacking - -A better alternative to stacking your notifications is to use the inbox style to have up to 8 lines of notification text in a single notification. If you send the following JSON from GCM you will see: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "My Title", - "message": "My first message", - "style": "inbox", - "summaryText": "There are %n% notifications" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'My Title'); -message.addData('message', 'My first message'); -message.addData('style', 'inbox'); -message.addData('summaryText', 'There are %n% notifications'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -It will produce a normal looking notification: - - - -But, if you follow it up with subsequent notifications like: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "My Title", - "message": "My second message", - "style": "inbox", - "summaryText": "There are %n% notifications" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'My Title'); -message.addData('message', 'My second message'); -message.addData('style', 'inbox'); -message.addData('summaryText', 'There are %n% notifications'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -You will get an inbox view so you can display multiple notifications in a single panel. - - - -If you use `%n%` in the `summaryText` of the JSON coming down from GCM it will be replaced by the number of messages that are currently in the queue. - -## Action Buttons - -Your notification can include a maximum of three action buttons. If you wish to include an icon along with the button name they must be placed in the `res/drawable` directory of your Android project. Then you can send the following JSON from GCM: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "AUX Scrum", - "message": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.", - "actions": [ - { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": true}, - { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false} - ] - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'AUX Scrum'); -message.addData('message', 'Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.'); -message.addData('actions', [ - { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": true}, - { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false}, -]); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -This will produce the following notification in your tray: - - - -If your user clicks on the main body of the notification your app will be opened. However if they click on either of the action buttons the app will open (or start) and the specified JavaScript callback will be executed if there is a function defined, and if there isn't an event will be emitted with the callback name. In this case it is `app.emailGuests` and `app.snooze` respectively. If you set the `foreground` property to `true` the app will be brought to the front, if `foreground` is `false` then the callback is run without the app being brought to the foreground. - -### In Line Replies - -Android N introduces a new capability for push notifications, the in line reply text field. If you wish to get some text data from the user when the action button is called send the following type of payload: - -Your notification can include action buttons. If you wish to include an icon along with the button name they must be placed in the `res/drawable` directory of your Android project. Then you can send the following JSON from GCM: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "AUX Scrum", - "message": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.", - "actions": [ - { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": false, "inline": true }, - { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false} - ] - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'AUX Scrum'); -message.addData('message', 'Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.'); -message.addData('actions', [ - { "icon": "emailGuests", "title": "EMAIL GUESTS", "callback": "app.emailGuests", "foreground": false, "inline": true}, - { "icon": "snooze", "title": "SNOOZE", "callback": "app.snooze", "foreground": false}, -]); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -On Android N and greater when the user clicks on the Email Guests button they will see the following: - - - -Then your app's `on('notification')` event handler will be called without the app being brought to the foreground and the event data would be: - -``` -{ - "title": "AUX Scrum", - "message": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.", - "additionalData": { - "inlineReply": "Sounds good", - "actions": [ - { - "inline": true, - "callback": "app.accept", - "foreground": false, - "title": "Accept" - }, - { - "icon": "snooze", - "callback": "app.reject", - "foreground": false, - "title": "Reject" - } - ], - "actionCallback": "app.accept", - "coldstart": false, - "collapse_key": "do_not_collapse", - "foreground": false - } -} -``` - -and the text data that the user typed would be located in `data.additionalData.inlineReply`. - -**Note:** On Android M and earlier the above in line behavior is not supported. As a fallback when `inline` is set to `true` the `foreground` setting will be changed to the default `true` setting. This allows your app to be launched from a closed state into the foreground where any behavior desired as a result of the user selecting the in line reply action button can be handled through the associated `callback`. - -#### Attributes - -Attribute | Type | Default | Description ---------- | ---- | ------- | ----------- -`icon` | `string` | | Optional. The name of a drawable resource to use as the small-icon. The name should not include the extension. -`title` | `string` | | Required. The label to display for the action button. -`callback` | `string` | | Required. The function to be executed or the event to be emitted when the action button is pressed. The function must be accessible from the global namespace. If you provide `myCallback` then it amounts to calling `window.myCallback`. If you provide `app.myCallback` then there needs to be an object call `app`, with a function called `myCallback` accessible from the global namespace, i.e. `window.app.myCallback`. If there isn't a function with the specified name an event will be emitted with the callback name. -`foreground` | `boolean` | `true` | Optional. Whether or not to bring the app to the foreground when the action button is pressed. -`inline` | `boolean` | `false` | Optional. Whether or not to provide a quick reply text field to the user when the button is clicked. - -## Led in Notifications - -You can use a Led notifcation and choose the color of it. Just add a `ledColor` field in your notification in the ARGB format array: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Green LED", - "message": "This is my message with a Green LED", - "ledColor": [0, 0, 255, 0] - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Green LED'); -message.addData('message', 'This is my message with a Green LED'); -message.addData('ledColor', [0, 0, 255, 0]); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -## Vibration Pattern in Notifications - -You can set a Vibration Pattern for your notifications. Just add a `vibrationPattern` field in your notification: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Vibration Pattern", - "message": "Device should wait for 2 seconds, vibrate for 1 second then be silent for 500 ms then vibrate for 500 ms", - "vibrationPattern": [2000, 1000, 500, 500] - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Vibration Pattern'); -message.addData('message', 'Device should wait for 2 seconds, vibrate for 1 second then be silent for 500 ms then vibrate for 500 ms'); -message.addData('vibrationPattern', [2000, 1000, 500, 500]); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -## Priority in Notifications - -You can set a priority parameter for your notifications. This priority value determines where the push notification will be put in the notification shade. Low-priority notifications may be hidden from the user in certain situations, while the user might be interrupted for a higher-priority notification. Add a `priority` field in your notification. -2: minimum, -1: low, 0: default , 1: high, 2: maximum priority. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "This is a maximum priority Notification", - "message": "This notification should appear in front of all others", - "priority": 2 - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'This is a maximum priority Notification'); -message.addData('message', 'This notification should appear in front of all others'); -message.addData('priority', 2); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -Do not confuse this with the GCM option of setting the [delivery priority of the message](https://developers.google.com/cloud-messaging/concept-options#setting-the-priority-of-a-message). Which is used by GCM to tell the device whether or not it should wake up to deal with the message. - -## Picture Messages - -Perhaps you want to include a large picture in the notification that you are sending to your users. Luckily you can do that too by sending the following JSON from GCM. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Big Picture", - "message": "This is my big picture message", - "style": "picture", - "picture": "http://36.media.tumblr.com/c066cc2238103856c9ac506faa6f3bc2/tumblr_nmstmqtuo81tssmyno1_1280.jpg", - "summaryText": "The internet is built on cat pictures" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Big Picture'); -message.addData('message', 'This is my big picture message'); -message.addData('style', 'picture'); -message.addData('picture', 'http://36.media.tumblr.com/c066cc2238103856c9ac506faa6f3bc2/tumblr_nmstmqtuo81tssmyno1_1280.jpg'); -message.addData('summaryText', 'The internet is built on cat pictures'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -This will produce the following notification in your tray: - - - -> Note: When the notification arrives you will see the title and message like normally. You will only see the picture when the notification is expanded. Once expanded not only will you see the picture but the message portion will disappear and you'll see the summary text portion. - -## Background Notifications - -On Android if you want your `on('notification')` event handler to be called when your app is in the background it is relatively simple. - -First the JSON you send from GCM will need to include `"content-available": "1"`. This will tell the push plugin to call your `on('notification')` event handler no matter what other data is in the push notification. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Test Push", - "message": "Push number 1", - "info": "super secret info", - "content-available": "1" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Test Push'); -message.addData('message', 'Push number 1'); -message.addData('info', 'super secret info'); -message.addData('content-available', '1'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -or if you want the payload to be delivered directly to your app without anything showing up in the notification center omit the tite/message from the payload like so: - - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "info": "super secret info", - "content-available": "1" - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('info', 'super secret info'); -message.addData('content-available', '1'); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -If do not want this type of behaviour just omit `"content-available": 1` from your push data and your `on('notification')` event handler will not be called. - -### Use of content-available: true - -The GCM docs will tell you to send a data payload of: - -```javascript -{ - "registration_ids": ["my device id"], - "content_available": true, - "data": { - "title": "Test Push", - "message": "Push number 1", - "info": "super secret info", - } -} -``` - -Where the `content-available` property is part of the main payload object. Setting the property in this part of the payload will result in the PushPlugin not getting the data correctly. Setting `content-available: true` will cause the Android OS to handle the push payload for you and not pass the data to the PushPlugin. - -Instead move `content-available: true` into the `data` object of the payload and set it to `1` as per the example below: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Test Push", - "message": "Push number 1", - "info": "super secret info", - "content-available": "1" - } -} -``` - -### Huawei and Xiaomi Phones - -These phones have a particular quirk that when the app is force closed that you will no longer be able to receive notifications until the app is restarted. In order for you to receive background notifications: - -- On your Huawei device go to Settings > Protected apps > check "My App" where. -- On your Xiaomi makes sure your phone has the "Auto-start" property enabled for your app. - -### Application force closed - -In order to take advantage of this feature you will need to be using cordova-android 6.0.0 or higher. In order to check if the change has been properly applied look at `platforms/android/**/MainActivity.java`. You should see an `onCreate` method that looks like this: - -```java -@Override -public void onCreate(Bundle savedInstanceState) -{ - super.onCreate(savedInstanceState); - - // enable Cordova apps to be started in the background - Bundle extras = getIntent().getExtras(); - if (extras != null && extras.getBoolean("cdvStartInBackground", false)) { - moveTaskToBack(true); - } - - // Set by <content src="index.html" /> in config.xml - loadUrl(launchUrl); -} -``` - -If you don't see the `if` statement that checks for the appearance of `cdvStartInBackground` you will probably need to do: - -``` -phonegap platform rm android -phonegap platform add android -phonegap build android -``` - -This should add the correct code to the `MainActivity` class. - -If you add `force-start: 1` to the data payload the application will be restarted in background even if it was force closed. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Force Start", - "message": "This notification should restart the app", - "force-start": 1 - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Force Start'); -message.addData('message', 'This notification should restart the app'); -message.addData('force-start', 1); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -## Visibility of Notifications - -You can set a visibility parameter for your notifications. Just add a `visibility` field in your notification. -1: secret, 0: private (default), 1: public. `Secret` shows only the most minimal information, excluding even the notification's icon. `Private` shows basic information about the existence of this notification, including its icon and the name of the app that posted it. The rest of the notification's details are not displayed. `Public` Shows the notification's full content. - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "This is a maximum public Notification", - "message": "This notification should appear in front of all others", - "visibility": 1 - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'This is a public Notification'); -message.addData('message', 'You should be able to read this notification on your lock screen'); -message.addData('visibility', 1); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -## Badges - -On Android not all launchers support badges. In order for us to set badges we use [ShortcutBadger](https://github.com/leolin310148/ShortcutBadger) in order to set the badge. Check out their website to see which launchers are supported. - -In order to set the badge number you will need to include the `badge` property in your push payload as below: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Badge Test", - "message": "Badges, we don't need no stinking badges", - "badge": 7 - } -} -``` - -Here is an example using node-gcm that sends the above JSON: - -```javascript -var gcm = require('node-gcm'); -// Replace these with your own values. -var apiKey = "replace with API key"; -var deviceID = "my device id"; -var service = new gcm.Sender(apiKey); -var message = new gcm.Message(); -message.addData('title', 'Badge Test'); -message.addData('message', 'Badges, we don\'t need no stinking badges'); -message.addData('badge', 7); -service.send(message, { registrationTokens: [ deviceID ] }, function (err, response) { - if(err) console.error(err); - else console.log(response); -}); -``` - -## Support for Twilio Notify - -This plugin seamlessly supports payloads generated by Twilio Notify on Android. Specifically the parameters passed in to the Twilio REST API are available in the message payload passed to your app as follows: - -- `Title` --> `data.title` -- `Body` --> `data.message` -- `Sound` --> `data.sound` - -Here is an example request to Twilio REST API and the corresponding JSON received by your app. - -``` -curl 'https://notify.twilio.com/v1/Services/IS1e928b239609199df31d461071fd3d23/Notifications' -X POST \ ---data-urlencode 'Identity=Bob' \ ---data-urlencode 'Body=Hello Bob! Twilio Notify + Phonegap is awesome!' \ ---data-urlencode 'Title=Hello Bob!' \ ---data-urlencode 'Sound=chime' \ --u [AccountSID]:[AuthToken] -``` - -The JSON received by your app will comply with the standards described in the sections above: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "Hello Bob!", - "message": "Hello Bob! Twilio Notify + Phonegap is awesome!", - "sound": "chime" - } -} -``` - -Note: "sound" and "soundname" are equivalent and are considered to be the same by the plugin. - -# iOS Behaviour - -## Sound - -In order for your notification to play a custom sound you will need to add the files to root of your iOS project. The files must be in the proper format. See the [Local and Remote Notification Programming Guide](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW6) for more info on proper file formats and how to convert existing sound files. - -Then send the follow JSON from APNS: - -```javascript -{ - "aps": { - "alert": "Test sound", - "sound": "sub.caf" - } -} -``` - -If you want the default sound to play upon receipt of push use this payload: - -``` -{ - "aps": { - "alert": "Test sound", - "sound": "default" - } -} -``` - -## Background Notifications - -On iOS if you want your `on('notification')` event handler to be called when your app is in the background you will need to do a few things. - -First the JSON you send from APNS will need to include `"content-available": 1` to the `aps` object. The `"content-available": 1` property in your push message is a signal to iOS to wake up your app and give it up to 30 seconds of background processing. If do not want this type of behaviour just omit `"content-available": 1` from your push data. As well you *should* set a `notId` property in the root of payload object. This is the parameter you pass to the `finish` method in order to tell the operating system that the processing of the push event is done. - -For instance the following JSON: - -```javascript -{ - "aps": { - "alert": "Test background push", - "content-available": 1 - }, - "notId": 1 // unique ID you generate -} -``` - -will produce a notification in the notification shade and call your `on('notification')` event handler. - -**NOTE:** The `on('notification')` event handler will **not** be called if Background App Refresh is disabled on the user's iOS device. (Settings > General > Background App Refresh) - -However if you want your `on('notification')` event handler called but no notification to be shown in the shader you would omit the `alert` property and send the following JSON to APNS: - -```javascript -{ - "aps": { - "data": "Test silent background push", - "moredata": "Do more stuff", - "content-available": 1 - }, - "notId": 2 // unique ID you generate -} -``` - -That covers what you need to do on the server side to accept background pushes on iOS. However, it is critically important that you continue reading as there will be a change in your `on('notification')`. When you receive a background push on iOS you will be given 30 seconds of time in which to complete a task. If you spend longer than 30 seconds on the task the OS may decide that your app is misbehaving and kill it. In order to signal iOS that your `on('notification')` handler is done you will need to call the new `push.finish()` method. - -For example: - -```javascript -var push = PushNotification.init({ - "ios": { - "sound": "true", - "alert": "true", - "badge": "true", - "clearBadge": "true" - } -}); - -push.on('registration', function(data) { - // send data.registrationId to push service -}); - - -push.on('notification', function(data) { - // do something with the push data - // then call finish to let the OS know we are done - push.finish(function() { - console.log("processing of push data is finished"); - }, function() { - console.log("something went wrong with push.finish for ID = " + data.additionalData.notId) - }, data.additionalData.notId); -}); -``` - -It is absolutely critical that you call `push.finish()` when you have successfully processed your background push data. - -## Action Buttons - -Your notification can include action buttons. For iOS 8+ you must setup the possible actions when you initialize the plugin: - -```javascript -var push = PushNotification.init({ - "ios": { - "sound": true, - "alert": true, - "badge": true, - "categories": { - "invite": { - "yes": { - "callback": "app.accept", "title": "Accept", "foreground": true, "destructive": false - }, - "no": { - "callback": "app.reject", "title": "Reject", "foreground": true, "destructive": false - }, - "maybe": { - "callback": "app.maybe", "title": "Maybe", "foreground": true, "destructive": false - } - }, - "delete": { - "yes": { - "callback": "app.doDelete", "title": "Delete", "foreground": true, "destructive": true - }, - "no": { - "callback": "app.cancel", "title": "Cancel", "foreground": true, "destructive": false - } - } - } - } -}); -``` - -You’ll notice that we’ve added a new parameter to the iOS object of our init code called categories. Each category is a named object, invite and delete in this case. These names will need to match the one you send via your payload to APNS if you want the action buttons to be displayed. Each category can have up to three buttons which must be labeled `yes`, `no` and `maybe`. In turn each of these buttons has four properties, `callback` the javascript function you want to call, `title` the label for the button, `foreground` whether or not to bring your app to the foreground and `destructive` which doesn’t actually do anything destructive it just colors the button red as a warning to the user that the action may be destructive. - -Just like with background notifications it is absolutely critical that you call `push.finish()` when you have successfully processed the button callback. For instance: - -```javascript -app.accept = function(data) { - // do something with the notification data - - push.finish(function() { - console.log('accept callback finished'); - }, function() { - console.log('accept callback failed'); - }, data.additionalData.notId); -}; -``` - -You may notice that the `finish` method now takes `success`, `failure` and `id` parameters. The `id` parameter let's the operating system know which background process to stop. You'll set it in the next step. - -Then you will need to set the `category` value in your `aps` payload to match one of the objects in the `categories` object. As well you *should* set a `notId` property in the root of payload object. This is the parameter you pass to the `finish` method in order to tell the operating system that the processing of the push event is done. - -```javascript -{ - "aps": { - "alert": "This is a notification that will be displayed ASAP.", - "category": "invite" - }, - "notId": "1" -} -``` - -This will produce the following notification in your tray: - - - -If your users clicks on the main body of the notification your app will be opened. However if they click on either of the action buttons the app will open (or start) and the specified JavaScript callback will be executed. - -### Action Buttons using GCM on iOS - -If you are using GCM to send push messages on iOS you will need to send a different payload in order for the action buttons to be present in the notification shade. You'll need to use the `click-action` property in order to specify the category. - -```javascript -{ - "registration_ids": ["my device id"], - "notification": { - "title": "AUX Scrum", - "body": "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.", - "click-action": "invite" - } -} -``` - -## GCM and Additional Data - -GCM on iOS is a different animal. The way you send data via GCM on Android is like: - -```javascript -{ - "registration_ids": ["my device id"], - "data": { - "title": "My Title", - "message": "My message", - "key1": "data 1", - "key2": "data 2" - } -} -``` - -will produce a `notification` event with the following data: - -```javascript -{ - "title": "My Title", - "message": "My message", - "additionalData": { - "key1": "data 1", - "key2": "data 2" - } -} -``` - -but in order for the same `notification` event you would need to send your push to GCM iOS in a slight different format: - -```javascript -{ - "registration_ids": ["my device id"], - "notification": { - "title": "My Title", - "body": "My message" - } - "data": { - "key1": "data 1", - "key2": "data 2" - } -} -``` - -The `title` and `body` need to be in the `notification` part of the payload in order for the OS to pick them up correctly. Everything else should be in the `data` part of the payload. - -## GCM Messages Not Arriving - -For some users of the plugin they are unable to get messages sent via GCM to show up on their devices. If you are running into this issue try setting the `priority` of the message to `high` in the payload. - -```javascript -{ - "registration_ids": ["my device id"], - "notification": { - "title": "My Title", - "body": "My message" - }, - "priority": "high" -} -``` - -# Windows Behaviour - -## Notifications - -The plugin supports all types of windows platform notifications namely [Tile, Toast, Badge and Raw](https://msdn.microsoft.com/en-us/library/windows/apps/Hh779725.aspx). The API supports the basic cases of the notification templates with title corresponding to the first text element and message corresponding to the second if title is present else the first one. The image corresponds to the first image element of the notification xml. - -The count is present only for the badge notification in which it represent the value of the notification which could be a number from 0-99 or a status glyph. - -For advanced templates and usage, the notification object is included in [`data.additionalData.pushNotificationReceivedEventArgs`](https://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.pushnotifications.pushnotificationreceivedeventargs). - -## Setting Toast Capable Option for Windows - -This plugin automatically sets the toast capable flag to be true for Cordova 5.1.1+. For lower versions, you must declare that it is Toast Capable in your app's manifest file. - -## Disabling the default processing of notifications by Windows - -The default handling can be disabled by setting the 'cancel' property in the notification object. - -```javascript -data.additionalData.pushNotificationReceivedEventArgs.cancel = true -``` - -## Background Notifications - -On Windows, to trigger the on('notification') event handler when your app is in the background and it is launched through the push notification, you will have to include `activation` data in the payload of the notification. This is done by using the `launch` attribute, which can be any string that can be understood by the app. However it should not cause the XML payload to become invalid. - -If you do not include a launch attribute string, your app will be launched normally, as though the user had launched it from the Start screen, and the notification event handler won't be called. - -Here is an example of a sample toast notification payload containing the launch attribute: - -```xml -<toast launch="{"myContext":"12345"}"> - <visual> - <binding template="ToastImageAndText01"> - <image id="1" src="ms-appx:///images/redWide.png" alt="red graphic"/> - <text id="1">Hello World!</text> - </binding> - </visual> -</toast> -``` - -This launch attribute string is passed on to the app as data.launchArgs through the on('notification') handler. It's important to note that due to the Windows platform design, the other visual payload is not available to the handler on cold start. So notification attributes like message, title etc. which are available through the on('notification') handler when the app is running, won't be available for background notifications. diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/PHONEGAP_BUILD.md b/StoneIsland/plugins/phonegap-plugin-push/docs/PHONEGAP_BUILD.md deleted file mode 100644 index 8a95d6a1..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/PHONEGAP_BUILD.md +++ /dev/null @@ -1,93 +0,0 @@ -# Cloud Build Services - -- [PhoneGap Build Support](#phonegap-build-support) - - [Including the plugin](#including-the-plugin) - - [Adding Resources](#adding-resources) -- [IntelXDK Support](#intelxdk-support) - -## PhoneGap Build Support - -> Currently PhoneGap Build does not support version 1.9.0 of the plugin. Updates are being made to PGB to support the latest release. - -### Including the plugin - -Including this plugin in a project that is built by PhoneGap Build is as easy as adding: - -```xml -<preference name="android-build-tool" value="gradle" /> -<plugin name="phonegap-plugin-push" source="npm"> - <param name="SENDER_ID" value="<Your Sender ID>" /> -</plugin> -``` - -into your app's `config.xml` file. PhoneGap Build will pick up the latest version of phonegap-plugin-push published on npm. If you want to specify a particular version of the plugin you can add the `spec` attribute to the `plugin` tag. - -```xml -<preference name="android-build-tool" value="gradle" /> -<plugin name="phonegap-plugin-push" spec="~1.4.5" source="npm" /> -``` - -Note: version 1.3.0 of this plugin begins to use Gradle to install the Android Support Framework. Support for Gradle has recently been added to PhoneGap Build. Please read [this blog post](http://phonegap.com/blog/2015/09/28/android-using-gradle/) for more information. - -### Adding resources - -Because PhoneGap Build does not support running hooks if you want to include custom image or sounds you will need to use a *beta* feature to include these files. - -#### Android - -To add custom files, create a directory called `locales/android/` in the root of your PGB application zip / repo, and place your resource files there. The contents will be copied into the Android `res/` directory, and any nested sub-directory structures will persist. Here's an example of how these files will be compiled into your APK: - -``` -<www.zip>/locales/android/drawables/logo.png --> <android_apk>/res/drawables/logo.png -<www.zip>/locales/android/raw/beep.mp3 --> <android_apk>/res/raw/beep.mp3 -<www.zip>/locales/android/values-fr/strings.xml --> <android_apk>/res/values-fr/strings.xml -``` - -Existing directories will be merged, but at this time any individual files you include will overwrite their target if it exists. - -## IntelXDK Support - -1. Do pre-requisite setup on [the iOS Provisioning Portal](https://developer.apple.com/account/ios/identifier/bundle). Refer to [this guide](https://www.raywenderlich.com/123862/push-notifications-tutorial) or Apple docs for detailed steps. -a. make a new App ID (you'll need to set this in Intel XDK config later) -b. enable push notifications -c. iOS Distribution cert: create (if needed), download and install (if needed), export as a .p12 (set and remember the password as you'll need this to import into Intel XDK later) -**NOTE**: Intel XDK does not support Development certs, so you MUST use your Distribution cert. -d. Make an AdHoc Provisioning Profile using your App ID from (1a) and your cert from (1c). Make sure your test device is enabled. Download and save with a name you will recognize. (you'll need to add this to your Intel XDK project later) -e. make a push cert, download it, install it, export it to .p12, convert it to .pem (this is for the push server that will send the notification - you'll need this later to test your Intel XDK app) - -2. In Intel XDK, make a new Cordova CLI 5.4.1 project using the HTML5+Cordova Blank Template, then replace the contents of www with [the contents of www from the PhoneGap Push Template](https://github.com/phonegap/phonegap-template-push/tree/master/template_src/www). - -3. Delete www/config.xml (optional? Intel XDK does not use config.xml) - -4. Intel XDK Project Settings -a. set the iOS App ID to match the App ID from (1a) -b. (if needed) import your .p12 from (1c) - Account Settings->Developer Certificates->iOS, then select it as the Developer Certificate for the project -c. Select "adhoc" for Provisioning Profile -d. copy your provisioning profile from (1d) into www/, then click "Ad hoc Provisioning Profile" and select the profile -e. Add the latest version of phonegap-plugin-push as a "Third-Party Plugin" (at time of testing this was 1.6.4) -f. **After the plugin is added, you will need to edit plugins/phonegap-plugin-push/plugin.xml**. Intel XDK 3357 does not support plugins with gradle references, so the gradle reference must be commented out (this will prevent this version of the plugin from working for Android but is needed for the iOS build to succeed): -`<!--framework src="push.gradle" custom="true" type="gradleReference" /-->` -A future version of Intel XDK will support gradle references. - -5. XDK Build Tab -a. Enable iOS build (click the checkmark) -b. Unlock your iOS certificate (click the lock and enter the password from (1c)) -c. click Start Builds -d. once the build completes, download and install the app - -6. connect test device by USB and open XCode Devices window (probably could also use Safari Web Inspector + Cordova Console plugin) - start the app and a log message should be written into the console that looks like "Push Plugin register success: \<XXXXXXXX 19b101a3 71590c03 9ea7f446 50eb8409 19ac24bb c1ec1320 XXXXXXXX\>" - -7. exit the app (close with home button then swipe it off the multitask view) - -8. The angle brackets and everything between (from (5)) is the device token - copy it into a text file - -9. Add the device token to your server and send a push notification -a. I used [phonegap-plugin-push/example/server/pushAPNS.rb](https://github.com/phonegap/phonegap-plugin-push/blob/master/example/server/pushAPNS.rb) for this -b. APNS.host = 'gateway.push.apple.com' -c. APNS.pem = 'PGPush926Prod.pem' #path to your pem file from (1e) -d. device_token = '\<XXXXXXXX 19b101a3 71590c03 9ea7f446 50eb8409 19ac24bb c1ec1320 XXXXXXXX\>' #the device token from (7) -e. edit the alert message and badge number -f. you probably need to install the required gem (`gem install pushmeup`) -g. send the notification (`ruby pushAPNS.rb`) - -10. See notification on device! diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/PLATFORM_SUPPORT.md b/StoneIsland/plugins/phonegap-plugin-push/docs/PLATFORM_SUPPORT.md deleted file mode 100644 index 3a4e2969..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/PLATFORM_SUPPORT.md +++ /dev/null @@ -1,17 +0,0 @@ -## Supported Platforms - -### Version 1.9.x - -- Cordova CLI (6.4.0 or newer) -- Android (`cordova-android` 6.0.0 or higher) -- Browser -- iOS (`cordova-ios` 4.3.0 or higher) -- Windows Universal (not Windows Phone 8) - -### Version 1.8.x - -- Cordova CLI (3.6.3 or newer) -- Android (`cordova-android` 4.0.0 or higher) -- Browser -- iOS (`cordova-ios` 4.1.0 or higher) -- Windows Universal (not Windows Phone 8) diff --git a/StoneIsland/plugins/phonegap-plugin-push/docs/TYPESCRIPT.md b/StoneIsland/plugins/phonegap-plugin-push/docs/TYPESCRIPT.md deleted file mode 100644 index 37117d16..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/docs/TYPESCRIPT.md +++ /dev/null @@ -1,72 +0,0 @@ -# Typescript definition file - -For those of you who use typescript, we're glad to say that we have the complete definition file available at [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped). -Search for `phonegap-plugin-push` there, or simply grab it directly [here](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/phonegap-plugin-push/phonegap-plugin-push.d.ts). - -## Example usage - -All objects will be understood as having a defined type, including init options and eventHandler parameters. -All available attributes and properties will have autocomplete support and type checkings. - -```typescript -let push = PushNotification.init({ - android: { - senderID: "12345679" - }, - ios: { - alert: "true", - badge: true, - sound: 'false' - }, - windows: {} -}); - -push.on('registration', (data) => { - console.log(data.registrationId); -}); - -push.on('notification', (data) => { - console.log(data.message); - console.log(data.title); - console.log(data.count); - console.log(data.sound); - console.log(data.image); - console.log(data.additionalData); -}); - -push.on('error', (e) => { - console.log(e.message); -}); -``` - -If you have custom attributes being sent from the server on the payload, you can define them on a custom interface extending the standard one: - -```typescript -module my.custom { - export interface NotificationEventResponse extends PhonegapPluginPush.NotificationEventResponse { - additionalData: NotificationEventAdditionalData; - } - - export interface NotificationEventAdditionalData extends PhonegapPluginPush.NotificationEventAdditionalData { - bacon?: boolean; - } -} - -push.on('notification', (data: my.custom.NotificationEventResponse) => { - //standard attributes - console.log(data.message); - console.log(data.title); - console.log(data.count); - console.log(data.sound); - console.log(data.image); - console.log(data.additionalData); - - //custom attributes - console.log(data.additionalData.bacon); -}); -``` - -## Outdated definitions - -Is our definition file at DefinitelyTyped outdated? Is there any improvements that could be done? -We welcome any contribution, and they should be done through issues created [there](https://github.com/DefinitelyTyped/DefinitelyTyped/issues/new).
\ No newline at end of file diff --git a/StoneIsland/plugins/phonegap-plugin-push/hooks/windows/setToastCapable.js b/StoneIsland/plugins/phonegap-plugin-push/hooks/windows/setToastCapable.js deleted file mode 100644 index b8cbcbc0..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/hooks/windows/setToastCapable.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = function(context) { - console.log('Updating appxmanifests with ToastCapable=true...'); - var path = require('path'); - var platformProjPath = path.join(context.opts.projectRoot, 'platforms/windows'); - var AppxManifest = require(path.join(platformProjPath, 'cordova/lib/AppxManifest')); - - ['package.phone.appxmanifest', 'package.windows.appxmanifest'].forEach(function(manifestPath) { - var manifest = AppxManifest.get(path.join(platformProjPath, manifestPath)); - manifest.getVisualElements().setToastCapable(true); - manifest.write(); - }); -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/package.json b/StoneIsland/plugins/phonegap-plugin-push/package.json deleted file mode 100644 index 01287217..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/package.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "_from": "phonegap-plugin-push@1.9.2", - "_id": "phonegap-plugin-push@1.9.2", - "_inBundle": false, - "_integrity": "sha1-3PktbNuZLcs3iUCyIbfwjoKcn8E=", - "_location": "/phonegap-plugin-push", - "_phantomChildren": {}, - "_requested": { - "type": "version", - "registry": true, - "raw": "phonegap-plugin-push@1.9.2", - "name": "phonegap-plugin-push", - "escapedName": "phonegap-plugin-push", - "rawSpec": "1.9.2", - "saveSpec": null, - "fetchSpec": "1.9.2" - }, - "_requiredBy": [ - "#USER", - "/" - ], - "_resolved": "https://registry.npmjs.org/phonegap-plugin-push/-/phonegap-plugin-push-1.9.2.tgz", - "_shasum": "dcf92d6cdb992dcb378940b221b7f08e829c9fc1", - "_spec": "phonegap-plugin-push@1.9.2", - "_where": "/Users/user/Sites/stone-island/StoneIsland", - "author": { - "name": "Adobe PhoneGap Team" - }, - "bugs": { - "url": "https://github.com/phonegap/phonegap-plugin-push/issues" - }, - "bundleDependencies": false, - "cordova": { - "id": "phonegap-plugin-push", - "platforms": [ - "ios", - "android", - "windows", - "browser" - ] - }, - "deprecated": false, - "description": "Register and receive push notifications.", - "devDependencies": { - "jasmine-node": "1.14.5", - "pluginpub": "^0.0.5" - }, - "engines": { - "cordovaDependencies": { - "1.8.2": { - "cordova": ">=3.6.3", - "cordova-android": ">=4.0.0", - "cordova-ios": ">=4.1.0" - }, - "1.9.0": { - "cordova": ">=6.4.0", - "cordova-android": ">=6.0.0", - "cordova-ios": ">=4.3.0" - }, - "2.0.0": { - "cordova": ">100" - } - } - }, - "homepage": "http://github.com/phonegap/phonegap-plugin-push#readme", - "keywords": [ - "ecosystem:cordova", - "ecosystem:phonegap", - "cordova-ios", - "cordova-android", - "cordova-windows8", - "cordova-windows", - "cordova-wp8", - "cordova-browser" - ], - "license": "APL", - "name": "phonegap-plugin-push", - "repository": { - "type": "git", - "url": "git://github.com/phonegap/phonegap-plugin-push.git" - }, - "scripts": { - "test": "jasmine-node --color spec" - }, - "version": "1.9.2" -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/plugin.xml b/StoneIsland/plugins/phonegap-plugin-push/plugin.xml deleted file mode 100755 index bf9c659a..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/plugin.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:amazon="http://schemas.android.com/apk/lib/com.amazon.device.ads" xmlns:rim="http://www.blackberry.com/ns/widgets" id="phonegap-plugin-push" version="1.9.2"> - <name>PushPlugin</name> - <description> - This plugin allows your application to receive push notifications on Android, iOS and Windows devices. - Android uses Google Cloud Messaging. - iOS uses Apple APNS Notifications. - Windows uses Microsoft WNS Notifications. - </description> - <license>MIT</license> - <js-module src="www/push.js" name="PushNotification"> - <clobbers target="PushNotification"/> - </js-module> - <engines> - <engine name="cordova" version=">=6.4.0"/> - <engine name="cordova-android" version=">=6.0.0"/> - <engine name="cordova-ios" version=">=4.3.0"/> - </engines> - <preference name="SENDER_ID" default="85075801930"/> - <platform name="android"> - <config-file target="res/xml/config.xml" parent="/*"> - <feature name="PushNotification"> - <param name="android-package" value="com.adobe.phonegap.push.PushPlugin"/> - </feature> - </config-file> - <config-file target="res/values/strings.xml" parent="/resources"> - <string name="google_app_id">$SENDER_ID</string> - </config-file> - <config-file target="AndroidManifest.xml" parent="/manifest"> - <uses-permission android:name="android.permission.INTERNET"/> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> - <uses-permission android:name="android.permission.WAKE_LOCK"/> - <uses-permission android:name="android.permission.VIBRATE"/> - <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> - <uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/> - <uses-permission android:name="${applicationId}.permission.PushHandlerActivity"/> - <permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature"/> - <permission android:name="${applicationId}.permission.PushHandlerActivity" android:protectionLevel="signature"/> - </config-file> - <config-file target="AndroidManifest.xml" parent="/manifest/application"> - <activity android:name="com.adobe.phonegap.push.PushHandlerActivity" android:exported="true" android:permission="${applicationId}.permission.PushHandlerActivity"/> - <receiver android:name="com.adobe.phonegap.push.BackgroundActionButtonHandler"/> - <receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND"> - <intent-filter> - <action android:name="com.google.android.c2dm.intent.RECEIVE"/> - <category android:name="${applicationId}"/> - </intent-filter> - </receiver> - <service android:name="com.adobe.phonegap.push.GCMIntentService" android:exported="false"> - <intent-filter> - <action android:name="com.google.android.c2dm.intent.RECEIVE"/> - </intent-filter> - </service> - <service android:name="com.adobe.phonegap.push.PushInstanceIDListenerService" android:exported="false"> - <intent-filter> - <action android:name="com.google.android.gms.iid.InstanceID"/> - </intent-filter> - </service> - <service android:name="com.adobe.phonegap.push.RegistrationIntentService" android:exported="false"/> - </config-file> - <framework src="push.gradle" custom="true" type="gradleReference"/> - <framework src="com.android.support:support-v13:23+"/> - <framework src="com.google.android.gms:play-services-gcm:9.8+"/> - <framework src="me.leolin:ShortcutBadger:1.1.11@aar"/> - <source-file src="src/android/com/adobe/phonegap/push/GCMIntentService.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/PushConstants.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/PushHandlerActivity.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/PushPlugin.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/RegistrationIntentService.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/PermissionUtils.java" target-dir="src/com/adobe/phonegap/push/"/> - <source-file src="src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java" target-dir="src/com/adobe/phonegap/push/"/> - </platform> - <platform name="browser"> - <js-module src="www/browser/push.js" name="BrowserPush"> - <clobbers target="PushNotification"/> - </js-module> - <asset src="src/browser/ServiceWorker.js" target="ServiceWorker.js"/> - <asset src="src/browser/manifest.json" target="manifest.json"/> - </platform> - <platform name="ios"> - <config-file target="config.xml" parent="/*"> - <feature name="PushNotification"> - <param name="ios-package" value="PushPlugin"/> - </feature> - </config-file> - <config-file target="*-Info.plist" parent="UIBackgroundModes"> - <array> - <string>remote-notification</string> - </array> - </config-file> - <config-file target="*-Info.plist" parent="GCM_SENDER_ID"> - <string>$SENDER_ID</string> - </config-file> - <config-file target="*-Info.plist" parent="IS_GCM_ENABLED"> - <true/> - </config-file> - <config-file target="*-Debug.plist" parent="aps-environment"> - <string>development</string> - </config-file> - <config-file target="*-Release.plist" parent="aps-environment"> - <string>production</string> - </config-file> - <source-file src="src/ios/AppDelegate+notification.m"/> - <source-file src="src/ios/PushPlugin.m"/> - <header-file src="src/ios/AppDelegate+notification.h"/> - <header-file src="src/ios/PushPlugin.h"/> - <framework src="AddressBook.framework"/> - <framework src="libsqlite3.tbd"/> - <framework src="libz.tbd"/> - <framework src="GoogleCloudMessaging" type="podspec" spec="~> 1.2.0"/> - <framework src="GGLInstanceID" type="podspec" spec="~> 1.2.1"/> - </platform> - <platform name="windows"> - <hook type="after_plugin_install" src="hooks/windows/setToastCapable.js"/> - <js-module src="src/windows/PushPluginProxy.js" name="PushPlugin"> - <merges target=""/> - </js-module> - <config-file target="config.xml" parent="/*"> - <preference name="WindowsToastCapable" value="true"/> - </config-file> - </platform> -</plugin>
\ No newline at end of file diff --git a/StoneIsland/plugins/phonegap-plugin-push/push.gradle b/StoneIsland/plugins/phonegap-plugin-push/push.gradle deleted file mode 100644 index 11e735ae..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/push.gradle +++ /dev/null @@ -1,21 +0,0 @@ -import java.util.regex.Pattern - -def doExtractStringFromManifest(name) { - def manifestFile = file(android.sourceSets.main.manifest.srcFile) - def pattern = Pattern.compile(name + "=\"(.*?)\"") - def matcher = pattern.matcher(manifestFile.getText()) - matcher.find() - return matcher.group(1) -} - -android { - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - } - } - - defaultConfig { - applicationId = doExtractStringFromManifest("package") - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/spec/helper/cordova.js b/StoneIsland/plugins/phonegap-plugin-push/spec/helper/cordova.js deleted file mode 100644 index 02bdee5f..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/spec/helper/cordova.js +++ /dev/null @@ -1,83 +0,0 @@ -/* global cordova:true */ - -/*! - * Module dependencies. - */ - -/** - * cordova.js for node. - * - * Think of this as cordova-node, which would be simliar to cordova-android - * or cordova-browser. The purpose of this module is to enable testing - * of a plugin's JavaScript interface. - * - * When this module is first required, it will insert a global cordova - * instance, which can hijack cordova-specific commands within the pluin's - * implementation. - * - * Remember to require this module before the plugin that you want to test. - * - * Example: - * - * var cordova = require('./helper/cordova'), - * myPlugin = require('../www/myPlugin'); - */ - -module.exports = global.cordova = cordova = { - - /** - * cordova.require Mock. - * - * Hijacks all cordova.requires. By default, it returns an empty function. - * You can define your own implementation of each required module before - * or after it has been required. - * - * See `cordova.required` to learn how to add your own module implemtnation. - */ - - require: function(moduleId) { - // define a default function if it doesn't exist - if (!cordova.required[moduleId]) { - cordova.required[moduleId] = function() {}; - } - // create a new module mapping between the module Id and cordova.required. - return new ModuleMap(moduleId); - }, - - /** - * Cordova module implementations. - * - * A key-value hash, where the key is the module such as 'cordova/exec' - * and the value is the function or object returned. - * - * For example: - * - * var exec = require('cordova/exec'); - * - * Will map to: - * - * cordova.required['cordova/exec']; - */ - - required: { - // populated at runtime - } -}; - -/** - * Module Mapper. - * - * Returns a function that when executed will lookup the implementation - * in cordova.required[id]. - * - * @param {String} moduleId is the module name/path, such as 'cordova/exec' - * @return {Function}. - */ - -function ModuleMap(moduleId) { - return function() { - // lookup and execute the module's mock implementation, passing - // in any parameters that were provided. - return cordova.required[moduleId].apply(this, arguments); - }; -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/spec/index.spec.js b/StoneIsland/plugins/phonegap-plugin-push/spec/index.spec.js deleted file mode 100644 index 8e1c2665..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/spec/index.spec.js +++ /dev/null @@ -1,405 +0,0 @@ -/* globals require */ - -/*! - * Module dependencies. - */ - -var cordova = require('./helper/cordova'), - PushNotification = require('../www/push'), - execSpy, - execWin, - options; - -/*! - * Specification. - */ - -describe('phonegap-plugin-push', function () { - beforeEach(function () { - options = {android: {}, ios: {}, windows: {}}; - execWin = jasmine.createSpy(); - execSpy = spyOn(cordova.required, 'cordova/exec').andCallFake(execWin); - }); - - describe('PushNotification', function () { - it('should exist', function () { - expect(PushNotification).toBeDefined(); - expect(typeof PushNotification === 'object').toBe(true); - }); - - it('should contain a init function', function () { - expect(PushNotification.init).toBeDefined(); - expect(typeof PushNotification.init === 'function').toBe(true); - }); - - it('should contain a unregister function', function () { - var push = PushNotification.init({}); - expect(push.unregister).toBeDefined(); - expect(typeof push.unregister === 'function').toBe(true); - }); - - it('should contain a getApplicationIconBadgeNumber function', function () { - var push = PushNotification.init({}); - expect(push.getApplicationIconBadgeNumber).toBeDefined(); - expect(typeof push.getApplicationIconBadgeNumber === 'function').toBe(true); - }); - - it('should contain a setApplicationIconBadgeNumber function', function () { - var push = PushNotification.init({}); - expect(push.setApplicationIconBadgeNumber).toBeDefined(); - expect(typeof push.setApplicationIconBadgeNumber === 'function').toBe(true); - }); - - it('should contain a clearAllNotifications function', function () { - var push = PushNotification.init({}); - expect(push.clearAllNotifications).toBeDefined(); - expect(typeof push.clearAllNotifications === 'function').toBe(true); - }); - - it('should contain a subscribe function', function () { - var push = PushNotification.init({}); - expect(push.subscribe).toBeDefined(); - expect(typeof push.subscribe === 'function').toBe(true); - }); - - it('should contain a unsubscribe function', function () { - var push = PushNotification.init({}); - expect(push.unsubscribe).toBeDefined(); - expect(typeof push.unsubscribe === 'function').toBe(true); - }); - }); - - describe('PushNotification instance', function () { - describe('cordova.exec', function () { - it('should call cordova.exec on next process tick', function (done) { - PushNotification.init(options); - setTimeout(function () { - expect(execSpy).toHaveBeenCalledWith( - jasmine.any(Function), - jasmine.any(Function), - 'PushNotification', - 'init', - jasmine.any(Object) - ); - done(); - }, 100); - }); - }); - - describe('on "registration" event', function () { - it('should be emitted with an argument', function (done) { - execSpy.andCallFake(function (win, fail, service, id, args) { - win({'registrationId': 1}); - }); - var push = PushNotification.init(options); - push.on('registration', function (data) { - expect(data.registrationId).toEqual(1); - done(); - }); - }); - }); - - describe('on "notification" event', function () { - beforeEach(function () { - execSpy.andCallFake(function (win, fail, service, id, args) { - win({ - message: 'Message', - title: 'Title', - count: 1, - sound: 'beep', - image: 'Image', - additionalData: {} - }); - }); - }); - - it('should be emitted on success', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - done(); - }); - }); - - it('should provide the data.message argument', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - expect(data.message).toEqual('Message'); - done(); - }); - }); - - it('should provide the data.title argument', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - expect(data.title).toEqual('Title'); - done(); - }); - }); - - it('should provide the data.count argument', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - expect(data.count).toEqual(1); - done(); - }); - }); - - it('should provide the data.sound argument', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - expect(data.sound).toEqual('beep'); - done(); - }); - }); - - it('should provide the data.image argument', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - expect(data.image).toEqual('Image'); - done(); - }); - }); - - it('should provide the data.additionalData argument', function (done) { - var push = PushNotification.init(options); - push.on('notification', function (data) { - expect(data.additionalData).toEqual({}); - done(); - }); - }); - }); - - describe('on "error" event', function () { - it('should be emitted with an Error', function (done) { - execSpy.andCallFake(function (win, fail, service, id, args) { - fail('something went wrong'); - }); - var push = PushNotification.init(options); - push.on('error', function (e) { - expect(e).toEqual(jasmine.any(Error)); - expect(e.message).toEqual('something went wrong'); - done(); - }); - }); - }); - - describe('off "notification" event', function () { - it('should exist and be registered a callback handle', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - push.on('notification', eventHandler); - - push.off('notification', eventHandler); - - expect(push._handlers.notification.indexOf(eventHandler)).toEqual(-1); - done(); - }); - }); - - describe('off "registration" event', function () { - it('should exist and be registered a callback handle', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - push.on('registration', eventHandler); - - push.off('registration', eventHandler); - - expect(push._handlers.registration.indexOf(eventHandler)).toEqual(-1); - done(); - }); - }); - - describe('off "error" event', function () { - it('should exist and be registered a callback handle', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - push.on('error', eventHandler); - push.off('error', eventHandler); - - expect(push._handlers.error.indexOf(eventHandler)).toEqual(-1); - done(); - }); - }); - - describe('unregister method', function () { - it('should clear "registration" event handlers', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - expect(push._handlers.registration.length).toEqual(0); - - push.on('registration',eventHandler); - - expect(push._handlers.registration.length).toEqual(1); - expect(push._handlers.registration.indexOf(eventHandler)).toBeGreaterThan(-1); - - execSpy.andCallFake(function (win, fail, service, id, args) { - win(); - }); - push.unregister(function() { - expect(push._handlers.registration.length).toEqual(0); - expect(push._handlers.registration.indexOf(eventHandler)).toEqual(-1); - done(); - }); - }); - - it('should clear "notification" event handlers', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - expect(push._handlers.notification.length).toEqual(0); - - push.on('notification', eventHandler); - - expect(push._handlers.notification.length).toEqual(1); - expect(push._handlers.notification.indexOf(eventHandler)).toBeGreaterThan(-1); - - execSpy.andCallFake(function (win, fail, service, id, args) { - win(); - }); - push.unregister(function() { - expect(push._handlers.notification.length).toEqual(0); - expect(push._handlers.notification.indexOf(eventHandler)).toEqual(-1); - done(); - }); - }); - - it('should clear "error" event handlers', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - expect(push._handlers.error.length).toEqual(0); - - push.on('error', eventHandler); - - expect(push._handlers.error.length).toEqual(1); - expect(push._handlers.error.indexOf(eventHandler)).toBeGreaterThan(-1); - - execSpy.andCallFake(function (win, fail, service, id, args) { - win(); - }); - push.unregister(function() { - expect(push._handlers.error.length).toEqual(0); - expect(push._handlers.error.indexOf(eventHandler)).toEqual(-1); - done(); - }); - }); - }); - - describe('unregister topics method', function () { - it('should not clear "registration" event handlers', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - expect(push._handlers.registration.length).toEqual(0); - - push.on('registration',eventHandler); - - expect(push._handlers.registration.length).toEqual(1); - expect(push._handlers.registration.indexOf(eventHandler)).toBeGreaterThan(-1); - - execSpy.andCallFake(function (win, fail, service, id, args) { - win(); - }); - push.unregister(function() { - expect(push._handlers.registration.length).toEqual(1); - expect(push._handlers.registration.indexOf(eventHandler)).toBeGreaterThan(-1); - done(); - }, null, ['foo', 'bar']); - }); - - it('should not clear "notification" event handlers', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - expect(push._handlers.notification.length).toEqual(0); - - push.on('notification', eventHandler); - - expect(push._handlers.notification.length).toEqual(1); - expect(push._handlers.notification.indexOf(eventHandler)).toBeGreaterThan(-1); - - execSpy.andCallFake(function (win, fail, service, id, args) { - win(); - }); - push.unregister(function() { - expect(push._handlers.notification.length).toEqual(1); - expect(push._handlers.notification.indexOf(eventHandler)).toBeGreaterThan(-1); - done(); - }, null, ['foo', 'bar']); - }); - - it('should not clear "error" event handlers', function (done) { - var push = PushNotification.init(options), - eventHandler = function () { - }; - - expect(push._handlers.error.length).toEqual(0); - - push.on('error', eventHandler); - - expect(push._handlers.error.length).toEqual(1); - expect(push._handlers.error.indexOf(eventHandler)).toBeGreaterThan(-1); - - execSpy.andCallFake(function (win, fail, service, id, args) { - win(); - }); - push.unregister(function() { - expect(push._handlers.error.length).toEqual(1); - expect(push._handlers.error.indexOf(eventHandler)).toBeGreaterThan(-1); - done(); - }, null, ['foo', 'bar']); - }); - }); - - describe('subscribe topic method', function () { - describe('cordova.exec', function () { - it('should call cordova.exec on next process tick', function (done) { - var push = PushNotification.init(options); - push.subscribe('foo', function() {}, function() {}); - setTimeout(function () { - expect(execSpy).toHaveBeenCalledWith( - jasmine.any(Function), - jasmine.any(Function), - 'PushNotification', - 'subscribe', - jasmine.any(Object) - ); - done(); - }, 100); - }); - }); - }); - - - describe('unsubscribe topic method', function () { - describe('cordova.exec', function () { - it('should call cordova.exec on next process tick', function (done) { - var push = PushNotification.init(options); - push.unsubscribe('foo', function() {}, function() {}); - setTimeout(function () { - expect(execSpy).toHaveBeenCalledWith( - jasmine.any(Function), - jasmine.any(Function), - 'PushNotification', - 'unsubscribe', - jasmine.any(Object) - ); - done(); - }, 100); - }); - }); - }); - }); -}); diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java deleted file mode 100644 index 3ccea6cb..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.adobe.phonegap.push; - -import android.app.NotificationManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.support.v4.app.RemoteInput; - -public class BackgroundActionButtonHandler extends BroadcastReceiver implements PushConstants { - private static String LOG_TAG = "PushPlugin_BackgroundActionButtonHandler"; - - @Override - public void onReceive(Context context, Intent intent) { - Bundle extras = intent.getExtras(); - Log.d(LOG_TAG, "BackgroundActionButtonHandler = " + extras); - - int notId = intent.getIntExtra(NOT_ID, 0); - Log.d(LOG_TAG, "not id = " + notId); - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(GCMIntentService.getAppName(context), notId); - - if (extras != null) { - Bundle originalExtras = extras.getBundle(PUSH_BUNDLE); - - originalExtras.putBoolean(FOREGROUND, false); - originalExtras.putBoolean(COLDSTART, false); - originalExtras.putString(ACTION_CALLBACK, extras.getString(CALLBACK)); - - Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); - if (remoteInput != null) { - String inputString = remoteInput.getCharSequence(INLINE_REPLY).toString(); - Log.d(LOG_TAG, "response: " + inputString); - originalExtras.putString(INLINE_REPLY, inputString); - } - - PushPlugin.sendExtras(originalExtras); - } - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java deleted file mode 100644 index e1a2b75c..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/GCMIntentService.java +++ /dev/null @@ -1,802 +0,0 @@ -package com.adobe.phonegap.push; - -import android.annotation.SuppressLint; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Color; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; -import android.support.v4.app.NotificationCompat.WearableExtender; -import android.support.v4.app.RemoteInput; -import android.text.Html; -import android.text.Spanned; -import android.util.Log; - -import com.google.android.gms.gcm.GcmListenerService; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Random; - -@SuppressLint("NewApi") -public class GCMIntentService extends GcmListenerService implements PushConstants { - - private static final String LOG_TAG = "PushPlugin_GCMIntentService"; - private static HashMap<Integer, ArrayList<String>> messageMap = new HashMap<Integer, ArrayList<String>>(); - - public void setNotification(int notId, String message){ - ArrayList<String> messageList = messageMap.get(notId); - if(messageList == null) { - messageList = new ArrayList<String>(); - messageMap.put(notId, messageList); - } - - if(message.isEmpty()){ - messageList.clear(); - }else{ - messageList.add(message); - } - } - - @Override - public void onMessageReceived(String from, Bundle extras) { - Log.d(LOG_TAG, "onMessage - from: " + from); - - if (extras != null) { - Context applicationContext = getApplicationContext(); - - SharedPreferences prefs = applicationContext.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - boolean forceShow = prefs.getBoolean(FORCE_SHOW, false); - boolean clearBadge = prefs.getBoolean(CLEAR_BADGE, false); - - extras = normalizeExtras(applicationContext, extras); - - if (clearBadge) { - PushPlugin.setApplicationIconBadgeNumber(getApplicationContext(), 0); - } - - // if we are in the foreground and forceShow is `false` only send data - if (!forceShow && PushPlugin.isInForeground()) { - Log.d(LOG_TAG, "foreground"); - extras.putBoolean(FOREGROUND, true); - extras.putBoolean(COLDSTART, false); - PushPlugin.sendExtras(extras); - } - // if we are in the foreground and forceShow is `true`, force show the notification if the data has at least a message or title - else if (forceShow && PushPlugin.isInForeground()) { - Log.d(LOG_TAG, "foreground force"); - extras.putBoolean(FOREGROUND, true); - extras.putBoolean(COLDSTART, false); - - showNotificationIfPossible(applicationContext, extras); - } - // if we are not in the foreground always send notification if the data has at least a message or title - else { - Log.d(LOG_TAG, "background"); - extras.putBoolean(FOREGROUND, false); - extras.putBoolean(COLDSTART, PushPlugin.isActive()); - - showNotificationIfPossible(applicationContext, extras); - } - } - } - - /* - * Change a values key in the extras bundle - */ - private void replaceKey(Context context, String oldKey, String newKey, Bundle extras, Bundle newExtras) { - Object value = extras.get(oldKey); - if ( value != null ) { - if (value instanceof String) { - value = localizeKey(context, newKey, (String) value); - - newExtras.putString(newKey, (String) value); - } else if (value instanceof Boolean) { - newExtras.putBoolean(newKey, (Boolean) value); - } else if (value instanceof Number) { - newExtras.putDouble(newKey, ((Number) value).doubleValue()); - } else { - newExtras.putString(newKey, String.valueOf(value)); - } - } - } - - /* - * Normalize localization for key - */ - private String localizeKey(Context context, String key, String value) { - if (key.equals(TITLE) || key.equals(MESSAGE) || key.equals(SUMMARY_TEXT)) { - try { - JSONObject localeObject = new JSONObject(value); - - String localeKey = localeObject.getString(LOC_KEY); - - ArrayList<String> localeFormatData = new ArrayList<String>(); - if (!localeObject.isNull(LOC_DATA)) { - String localeData = localeObject.getString(LOC_DATA); - JSONArray localeDataArray = new JSONArray(localeData); - for (int i = 0 ; i < localeDataArray.length(); i++) { - localeFormatData.add(localeDataArray.getString(i)); - } - } - - String packageName = context.getPackageName(); - Resources resources = context.getResources(); - - int resourceId = resources.getIdentifier(localeKey, "string", packageName); - - if (resourceId != 0) { - return resources.getString(resourceId, localeFormatData.toArray()); - } - else { - Log.d(LOG_TAG, "can't find resource for locale key = " + localeKey); - - return value; - } - } - catch(JSONException e) { - Log.d(LOG_TAG, "no locale found for key = " + key + ", error " + e.getMessage()); - - return value; - } - } - - return value; - } - - /* - * Replace alternate keys with our canonical value - */ - private String normalizeKey(String key) { - if (key.equals(BODY) || key.equals(ALERT) || key.equals(GCM_NOTIFICATION_BODY) || key.equals(TWILIO_BODY)) { - return MESSAGE; - } else if (key.equals(TWILIO_TITLE)) { - return TITLE; - }else if (key.equals(MSGCNT) || key.equals(BADGE)) { - return COUNT; - } else if (key.equals(SOUNDNAME) || key.equals(TWILIO_SOUND)) { - return SOUND; - } else if (key.startsWith(GCM_NOTIFICATION)) { - return key.substring(GCM_NOTIFICATION.length()+1, key.length()); - } else if (key.startsWith(GCM_N)) { - return key.substring(GCM_N.length()+1, key.length()); - } else if (key.startsWith(UA_PREFIX)) { - key = key.substring(UA_PREFIX.length()+1, key.length()); - return key.toLowerCase(); - } else { - return key; - } - } - - /* - * Parse bundle into normalized keys. - */ - private Bundle normalizeExtras(Context context, Bundle extras) { - Log.d(LOG_TAG, "normalize extras"); - Iterator<String> it = extras.keySet().iterator(); - Bundle newExtras = new Bundle(); - - while (it.hasNext()) { - String key = it.next(); - - Log.d(LOG_TAG, "key = " + key); - - // If normalizeKeythe key is "data" or "message" and the value is a json object extract - // This is to support parse.com and other services. Issue #147 and pull #218 - if (key.equals(PARSE_COM_DATA) || key.equals(MESSAGE)) { - Object json = extras.get(key); - // Make sure data is json object stringified - if ( json instanceof String && ((String) json).startsWith("{") ) { - Log.d(LOG_TAG, "extracting nested message data from key = " + key); - try { - // If object contains message keys promote each value to the root of the bundle - JSONObject data = new JSONObject((String) json); - if ( data.has(ALERT) || data.has(MESSAGE) || data.has(BODY) || data.has(TITLE) ) { - Iterator<String> jsonIter = data.keys(); - while (jsonIter.hasNext()) { - String jsonKey = jsonIter.next(); - - Log.d(LOG_TAG, "key = data/" + jsonKey); - - String value = data.getString(jsonKey); - jsonKey = normalizeKey(jsonKey); - value = localizeKey(context, jsonKey, value); - - newExtras.putString(jsonKey, value); - } - } - } catch( JSONException e) { - Log.e(LOG_TAG, "normalizeExtras: JSON exception"); - } - } - } else if (key.equals(("notification"))) { - Bundle value = extras.getBundle(key); - Iterator<String> iterator = value.keySet().iterator(); - while (iterator.hasNext()) { - String notifkey = iterator.next(); - - Log.d(LOG_TAG, "notifkey = " + notifkey); - String newKey = normalizeKey(notifkey); - Log.d(LOG_TAG, "replace key " + notifkey + " with " + newKey); - - String valueData = value.getString(notifkey); - valueData = localizeKey(context, newKey, valueData); - - newExtras.putString(newKey, valueData); - } - continue; - } - - String newKey = normalizeKey(key); - Log.d(LOG_TAG, "replace key " + key + " with " + newKey); - replaceKey(context, key, newKey, extras, newExtras); - - } // while - - return newExtras; - } - - private int extractBadgeCount(Bundle extras) { - int count = -1; - String msgcnt = extras.getString(COUNT); - - try { - if (msgcnt != null) { - count = Integer.parseInt(msgcnt); - } - } catch (NumberFormatException e) { - Log.e(LOG_TAG, e.getLocalizedMessage(), e); - } - - return count; - } - - private void showNotificationIfPossible (Context context, Bundle extras) { - - // Send a notification if there is a message or title, otherwise just send data - String message = extras.getString(MESSAGE); - String title = extras.getString(TITLE); - String contentAvailable = extras.getString(CONTENT_AVAILABLE); - String forceStart = extras.getString(FORCE_START); - int badgeCount = extractBadgeCount(extras); - if (badgeCount >= 0) { - Log.d(LOG_TAG, "count =[" + badgeCount + "]"); - PushPlugin.setApplicationIconBadgeNumber(context, badgeCount); - } - - Log.d(LOG_TAG, "message =[" + message + "]"); - Log.d(LOG_TAG, "title =[" + title + "]"); - Log.d(LOG_TAG, "contentAvailable =[" + contentAvailable + "]"); - Log.d(LOG_TAG, "forceStart =[" + forceStart + "]"); - - if ((message != null && message.length() != 0) || - (title != null && title.length() != 0)) { - - Log.d(LOG_TAG, "create notification"); - - if(title == null || title.isEmpty()){ - extras.putString(TITLE, getAppName(this)); - } - - createNotification(context, extras); - } - - if(!PushPlugin.isActive() && "1".equals(forceStart)){ - Log.d(LOG_TAG, "app is not running but we should start it and put in background"); - Intent intent = new Intent(this, PushHandlerActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(PUSH_BUNDLE, extras); - intent.putExtra(START_IN_BACKGROUND, true); - intent.putExtra(FOREGROUND, false); - startActivity(intent); - } else if ("1".equals(contentAvailable)) { - Log.d(LOG_TAG, "app is not running and content available true"); - Log.d(LOG_TAG, "send notification event"); - PushPlugin.sendExtras(extras); - } - } - - public void createNotification(Context context, Bundle extras) { - NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - String appName = getAppName(this); - String packageName = context.getPackageName(); - Resources resources = context.getResources(); - - int notId = parseInt(NOT_ID, extras); - Intent notificationIntent = new Intent(this, PushHandlerActivity.class); - notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); - notificationIntent.putExtra(PUSH_BUNDLE, extras); - notificationIntent.putExtra(NOT_ID, notId); - - int requestCode = new Random().nextInt(); - PendingIntent contentIntent = PendingIntent.getActivity(this, requestCode, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); - - NotificationCompat.Builder mBuilder = - new NotificationCompat.Builder(context) - .setWhen(System.currentTimeMillis()) - .setContentTitle(fromHtml(extras.getString(TITLE))) - .setTicker(fromHtml(extras.getString(TITLE))) - .setContentIntent(contentIntent) - .setAutoCancel(true); - - SharedPreferences prefs = context.getSharedPreferences(PushPlugin.COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - String localIcon = prefs.getString(ICON, null); - String localIconColor = prefs.getString(ICON_COLOR, null); - boolean soundOption = prefs.getBoolean(SOUND, true); - boolean vibrateOption = prefs.getBoolean(VIBRATE, true); - Log.d(LOG_TAG, "stored icon=" + localIcon); - Log.d(LOG_TAG, "stored iconColor=" + localIconColor); - Log.d(LOG_TAG, "stored sound=" + soundOption); - Log.d(LOG_TAG, "stored vibrate=" + vibrateOption); - - /* - * Notification Vibration - */ - - setNotificationVibration(extras, vibrateOption, mBuilder); - - /* - * Notification Icon Color - * - * Sets the small-icon background color of the notification. - * To use, add the `iconColor` key to plugin android options - * - */ - setNotificationIconColor(extras.getString("color"), mBuilder, localIconColor); - - /* - * Notification Icon - * - * Sets the small-icon of the notification. - * - * - checks the plugin options for `icon` key - * - if none, uses the application icon - * - * The icon value must be a string that maps to a drawable resource. - * If no resource is found, falls - * - */ - setNotificationSmallIcon(context, extras, packageName, resources, mBuilder, localIcon); - - /* - * Notification Large-Icon - * - * Sets the large-icon of the notification - * - * - checks the gcm data for the `image` key - * - checks to see if remote image, loads it. - * - checks to see if assets image, Loads It. - * - checks to see if resource image, LOADS IT! - * - if none, we don't set the large icon - * - */ - setNotificationLargeIcon(extras, packageName, resources, mBuilder); - - /* - * Notification Sound - */ - if (soundOption) { - setNotificationSound(context, extras, mBuilder); - } - - /* - * LED Notification - */ - setNotificationLedColor(extras, mBuilder); - - /* - * Priority Notification - */ - setNotificationPriority(extras, mBuilder); - - /* - * Notification message - */ - setNotificationMessage(notId, extras, mBuilder); - - /* - * Notification count - */ - setNotificationCount(context, extras, mBuilder); - - /* - * Notification count - */ - setVisibility(context, extras, mBuilder); - - /* - * Notification add actions - */ - createActions(extras, mBuilder, resources, packageName, notId); - - mNotificationManager.notify(appName, notId, mBuilder.build()); - } - - private void updateIntent(Intent intent, String callback, Bundle extras, boolean foreground, int notId) { - intent.putExtra(CALLBACK, callback); - intent.putExtra(PUSH_BUNDLE, extras); - intent.putExtra(FOREGROUND, foreground); - intent.putExtra(NOT_ID, notId); - } - - private void createActions(Bundle extras, NotificationCompat.Builder mBuilder, Resources resources, String packageName, int notId) { - Log.d(LOG_TAG, "create actions: with in-line"); - String actions = extras.getString(ACTIONS); - if (actions != null) { - try { - JSONArray actionsArray = new JSONArray(actions); - ArrayList<NotificationCompat.Action> wActions = new ArrayList<NotificationCompat.Action>(); - for (int i=0; i < actionsArray.length(); i++) { - int min = 1; - int max = 2000000000; - Random random = new Random(); - int uniquePendingIntentRequestCode = random.nextInt((max - min) + 1) + min; - Log.d(LOG_TAG, "adding action"); - JSONObject action = actionsArray.getJSONObject(i); - Log.d(LOG_TAG, "adding callback = " + action.getString(CALLBACK)); - boolean foreground = action.optBoolean(FOREGROUND, true); - boolean inline = action.optBoolean("inline", false); - Intent intent = null; - PendingIntent pIntent = null; - if (inline) { - Log.d(LOG_TAG, "Version: " + android.os.Build.VERSION.SDK_INT + " = " + android.os.Build.VERSION_CODES.M); - if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { - Log.d(LOG_TAG, "push activity"); - intent = new Intent(this, PushHandlerActivity.class); - } else { - Log.d(LOG_TAG, "push receiver"); - intent = new Intent(this, BackgroundActionButtonHandler.class); - } - - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - - if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) { - Log.d(LOG_TAG, "push activity for notId " + notId); - pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); - } else { - Log.d(LOG_TAG, "push receiver for notId " + notId); - pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_ONE_SHOT); - } - } else if (foreground) { - intent = new Intent(this, PushHandlerActivity.class); - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - pIntent = PendingIntent.getActivity(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } else { - intent = new Intent(this, BackgroundActionButtonHandler.class); - updateIntent(intent, action.getString(CALLBACK), extras, foreground, notId); - pIntent = PendingIntent.getBroadcast(this, uniquePendingIntentRequestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - NotificationCompat.Action.Builder actionBuilder = - new NotificationCompat.Action.Builder(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), - action.getString(TITLE), pIntent); - - RemoteInput remoteInput = null; - if (inline) { - Log.d(LOG_TAG, "create remote input"); - String replyLabel = "Enter your reply here"; - remoteInput = - new RemoteInput.Builder(INLINE_REPLY) - .setLabel(replyLabel) - .build(); - actionBuilder.addRemoteInput(remoteInput); - } - - NotificationCompat.Action wAction = actionBuilder.build(); - wActions.add(actionBuilder.build()); - - if (inline) { - mBuilder.addAction(wAction); - } else { - mBuilder.addAction(resources.getIdentifier(action.optString(ICON, ""), DRAWABLE, packageName), - action.getString(TITLE), pIntent); - } - wAction = null; - pIntent = null; - } - mBuilder.extend(new WearableExtender().addActions(wActions)); - wActions.clear(); - } catch(JSONException e) { - // nope - } - } - } - - private void setNotificationCount(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - int count = extractBadgeCount(extras); - if (count >= 0) { - Log.d(LOG_TAG, "count =[" + count + "]"); - mBuilder.setNumber(count); - } - } - - - private void setVisibility(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - String visibilityStr = extras.getString(VISIBILITY); - if (visibilityStr != null) { - try { - Integer visibility = Integer.parseInt(visibilityStr); - if (visibility >= NotificationCompat.VISIBILITY_SECRET && visibility <= NotificationCompat.VISIBILITY_PUBLIC) { - mBuilder.setVisibility(visibility); - } else { - Log.e(LOG_TAG, "Visibility parameter must be between -1 and 1"); - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - } - } - - private void setNotificationVibration(Bundle extras, Boolean vibrateOption, NotificationCompat.Builder mBuilder) { - String vibrationPattern = extras.getString(VIBRATION_PATTERN); - if (vibrationPattern != null) { - String[] items = vibrationPattern.replaceAll("\\[", "").replaceAll("\\]", "").split(","); - long[] results = new long[items.length]; - for (int i = 0; i < items.length; i++) { - try { - results[i] = Long.parseLong(items[i].trim()); - } catch (NumberFormatException nfe) {} - } - mBuilder.setVibrate(results); - } else { - if (vibrateOption) { - mBuilder.setDefaults(Notification.DEFAULT_VIBRATE); - } - } - } - - private void setNotificationMessage(int notId, Bundle extras, NotificationCompat.Builder mBuilder) { - String message = extras.getString(MESSAGE); - - String style = extras.getString(STYLE, STYLE_TEXT); - if(STYLE_INBOX.equals(style)) { - setNotification(notId, message); - - mBuilder.setContentText(fromHtml(message)); - - ArrayList<String> messageList = messageMap.get(notId); - Integer sizeList = messageList.size(); - if (sizeList > 1) { - String sizeListMessage = sizeList.toString(); - String stacking = sizeList + " more"; - if (extras.getString(SUMMARY_TEXT) != null) { - stacking = extras.getString(SUMMARY_TEXT); - stacking = stacking.replace("%n%", sizeListMessage); - } - NotificationCompat.InboxStyle notificationInbox = new NotificationCompat.InboxStyle() - .setBigContentTitle(fromHtml(extras.getString(TITLE))) - .setSummaryText(fromHtml(stacking)); - - for (int i = messageList.size() - 1; i >= 0; i--) { - notificationInbox.addLine(fromHtml(messageList.get(i))); - } - - mBuilder.setStyle(notificationInbox); - } else { - NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); - if (message != null) { - bigText.bigText(fromHtml(message)); - bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); - mBuilder.setStyle(bigText); - } - } - } else if (STYLE_PICTURE.equals(style)) { - setNotification(notId, ""); - - NotificationCompat.BigPictureStyle bigPicture = new NotificationCompat.BigPictureStyle(); - bigPicture.bigPicture(getBitmapFromURL(extras.getString(PICTURE))); - bigPicture.setBigContentTitle(fromHtml(extras.getString(TITLE))); - bigPicture.setSummaryText(fromHtml(extras.getString(SUMMARY_TEXT))); - - mBuilder.setContentTitle(fromHtml(extras.getString(TITLE))); - mBuilder.setContentText(fromHtml(message)); - - mBuilder.setStyle(bigPicture); - } else { - setNotification(notId, ""); - - NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle(); - - if (message != null) { - mBuilder.setContentText(fromHtml(message)); - - bigText.bigText(fromHtml(message)); - bigText.setBigContentTitle(fromHtml(extras.getString(TITLE))); - - String summaryText = extras.getString(SUMMARY_TEXT); - if (summaryText != null) { - bigText.setSummaryText(fromHtml(summaryText)); - } - - mBuilder.setStyle(bigText); - } - /* - else { - mBuilder.setContentText("<missing message content>"); - } - */ - } - } - - private void setNotificationSound(Context context, Bundle extras, NotificationCompat.Builder mBuilder) { - String soundname = extras.getString(SOUNDNAME); - if (soundname == null) { - soundname = extras.getString(SOUND); - } - if (SOUND_RINGTONE.equals(soundname)) { - mBuilder.setSound(android.provider.Settings.System.DEFAULT_RINGTONE_URI); - } else if (soundname != null && !soundname.contentEquals(SOUND_DEFAULT)) { - Uri sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE - + "://" + context.getPackageName() + "/raw/" + soundname); - Log.d(LOG_TAG, sound.toString()); - mBuilder.setSound(sound); - } else { - mBuilder.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI); - } - } - - private void setNotificationLedColor(Bundle extras, NotificationCompat.Builder mBuilder) { - String ledColor = extras.getString(LED_COLOR); - if (ledColor != null) { - // Converts parse Int Array from ledColor - String[] items = ledColor.replaceAll("\\[", "").replaceAll("\\]", "").split(","); - int[] results = new int[items.length]; - for (int i = 0; i < items.length; i++) { - try { - results[i] = Integer.parseInt(items[i].trim()); - } catch (NumberFormatException nfe) {} - } - if (results.length == 4) { - mBuilder.setLights(Color.argb(results[0], results[1], results[2], results[3]), 500, 500); - } else { - Log.e(LOG_TAG, "ledColor parameter must be an array of length == 4 (ARGB)"); - } - } - } - - private void setNotificationPriority(Bundle extras, NotificationCompat.Builder mBuilder) { - String priorityStr = extras.getString(PRIORITY); - if (priorityStr != null) { - try { - Integer priority = Integer.parseInt(priorityStr); - if (priority >= NotificationCompat.PRIORITY_MIN && priority <= NotificationCompat.PRIORITY_MAX) { - mBuilder.setPriority(priority); - } else { - Log.e(LOG_TAG, "Priority parameter must be between -2 and 2"); - } - } catch (NumberFormatException e) { - e.printStackTrace(); - } - } - } - - private void setNotificationLargeIcon(Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder) { - String gcmLargeIcon = extras.getString(IMAGE); // from gcm - if (gcmLargeIcon != null && !"".equals(gcmLargeIcon)) { - if (gcmLargeIcon.startsWith("http://") || gcmLargeIcon.startsWith("https://")) { - mBuilder.setLargeIcon(getBitmapFromURL(gcmLargeIcon)); - Log.d(LOG_TAG, "using remote large-icon from gcm"); - } else { - AssetManager assetManager = getAssets(); - InputStream istr; - try { - istr = assetManager.open(gcmLargeIcon); - Bitmap bitmap = BitmapFactory.decodeStream(istr); - mBuilder.setLargeIcon(bitmap); - Log.d(LOG_TAG, "using assets large-icon from gcm"); - } catch (IOException e) { - int largeIconId = 0; - largeIconId = resources.getIdentifier(gcmLargeIcon, DRAWABLE, packageName); - if (largeIconId != 0) { - Bitmap largeIconBitmap = BitmapFactory.decodeResource(resources, largeIconId); - mBuilder.setLargeIcon(largeIconBitmap); - Log.d(LOG_TAG, "using resources large-icon from gcm"); - } else { - Log.d(LOG_TAG, "Not setting large icon"); - } - } - } - } - } - - private void setNotificationSmallIcon(Context context, Bundle extras, String packageName, Resources resources, NotificationCompat.Builder mBuilder, String localIcon) { - int iconId = 0; - String icon = extras.getString(ICON); - if (icon != null && !"".equals(icon)) { - iconId = resources.getIdentifier(icon, DRAWABLE, packageName); - Log.d(LOG_TAG, "using icon from plugin options"); - } - else if (localIcon != null && !"".equals(localIcon)) { - iconId = resources.getIdentifier(localIcon, DRAWABLE, packageName); - Log.d(LOG_TAG, "using icon from plugin options"); - } - if (iconId == 0) { - Log.d(LOG_TAG, "no icon resource found - using application icon"); - iconId = context.getApplicationInfo().icon; - } - mBuilder.setSmallIcon(iconId); - } - - private void setNotificationIconColor(String color, NotificationCompat.Builder mBuilder, String localIconColor) { - int iconColor = 0; - if (color != null && !"".equals(color)) { - try { - iconColor = Color.parseColor(color); - } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, "couldn't parse color from android options"); - } - } - else if (localIconColor != null && !"".equals(localIconColor)) { - try { - iconColor = Color.parseColor(localIconColor); - } catch (IllegalArgumentException e) { - Log.e(LOG_TAG, "couldn't parse color from android options"); - } - } - if (iconColor != 0) { - mBuilder.setColor(iconColor); - } - } - - public Bitmap getBitmapFromURL(String strURL) { - try { - URL url = new URL(strURL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setDoInput(true); - connection.connect(); - InputStream input = connection.getInputStream(); - return BitmapFactory.decodeStream(input); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - } - - public static String getAppName(Context context) { - CharSequence appName = context.getPackageManager().getApplicationLabel(context.getApplicationInfo()); - return (String)appName; - } - - private int parseInt(String value, Bundle extras) { - int retval = 0; - - try { - retval = Integer.parseInt(extras.getString(value)); - } - catch(NumberFormatException e) { - Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage()); - } - catch(Exception e) { - Log.e(LOG_TAG, "Number format exception - Error parsing " + value + ": " + e.getMessage()); - } - - return retval; - } - - private Spanned fromHtml(String source) { - if (source != null) - return Html.fromHtml(source); - else - return null; - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java deleted file mode 100644 index 6aa5c9bf..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PermissionUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.adobe.phonegap.push; - -import android.content.Context; -import android.content.pm.ApplicationInfo; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class PermissionUtils { - - private static final String CHECK_OP_NO_THROW = "checkOpNoThrow"; - - public static boolean hasPermission(Context appContext, String appOpsServiceId) throws UnknownError { - - ApplicationInfo appInfo = appContext.getApplicationInfo(); - - String pkg = appContext.getPackageName(); - int uid = appInfo.uid; - Class appOpsClass = null; - Object appOps = appContext.getSystemService("appops"); - - try { - - appOpsClass = Class.forName("android.app.AppOpsManager"); - - Method checkOpNoThrowMethod = appOpsClass.getMethod( - CHECK_OP_NO_THROW, - Integer.TYPE, - Integer.TYPE, - String.class - ); - - Field opValue = appOpsClass.getDeclaredField(appOpsServiceId); - - int value = (int) opValue.getInt(Integer.class); - Object result = checkOpNoThrowMethod.invoke(appOps, value, uid, pkg); - - return Integer.parseInt(result.toString()) == 0; // AppOpsManager.MODE_ALLOWED - - } catch (ClassNotFoundException e) { - throw new UnknownError("class not found"); - } catch (NoSuchMethodException e) { - throw new UnknownError("no such method"); - } catch (NoSuchFieldException e) { - throw new UnknownError("no such field"); - } catch (InvocationTargetException e) { - throw new UnknownError("invocation target"); - } catch (IllegalAccessException e) { - throw new UnknownError("illegal access"); - } - - } - -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java deleted file mode 100644 index 37874e04..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushConstants.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.adobe.phonegap.push; - -public interface PushConstants { - public static final String COM_ADOBE_PHONEGAP_PUSH = "com.adobe.phonegap.push"; - public static final String REGISTRATION_ID = "registrationId"; - public static final String FOREGROUND = "foreground"; - public static final String TITLE = "title"; - public static final String NOT_ID = "notId"; - public static final String PUSH_BUNDLE = "pushBundle"; - public static final String ICON = "icon"; - public static final String ICON_COLOR = "iconColor"; - public static final String SOUND = "sound"; - public static final String SOUND_DEFAULT = "default"; - public static final String SOUND_RINGTONE = "ringtone"; - public static final String VIBRATE = "vibrate"; - public static final String ACTIONS = "actions"; - public static final String CALLBACK = "callback"; - public static final String ACTION_CALLBACK = "actionCallback"; - public static final String DRAWABLE = "drawable"; - public static final String MSGCNT = "msgcnt"; - public static final String VIBRATION_PATTERN = "vibrationPattern"; - public static final String STYLE = "style"; - public static final String SUMMARY_TEXT = "summaryText"; - public static final String PICTURE = "picture"; - public static final String GCM_N = "gcm.n."; - public static final String GCM_NOTIFICATION = "gcm.notification"; - public static final String GCM_NOTIFICATION_BODY = "gcm.notification.body"; - public static final String UA_PREFIX = "com.urbanairship.push"; - public static final String PARSE_COM_DATA = "data"; - public static final String ALERT = "alert"; - public static final String MESSAGE = "message"; - public static final String BODY = "body"; - public static final String SOUNDNAME = "soundname"; - public static final String LED_COLOR = "ledColor"; - public static final String PRIORITY = "priority"; - public static final String IMAGE = "image"; - public static final String STYLE_INBOX = "inbox"; - public static final String STYLE_PICTURE = "picture"; - public static final String STYLE_TEXT = "text"; - public static final String BADGE = "badge"; - public static final String INITIALIZE = "init"; - public static final String SUBSCRIBE = "subscribe"; - public static final String UNSUBSCRIBE = "unsubscribe"; - public static final String UNREGISTER = "unregister"; - public static final String EXIT = "exit"; - public static final String FINISH = "finish"; - public static final String HAS_PERMISSION = "hasPermission"; - public static final String ANDROID = "android"; - public static final String SENDER_ID = "senderID"; - public static final String CLEAR_BADGE = "clearBadge"; - public static final String CLEAR_NOTIFICATIONS = "clearNotifications"; - public static final String COLDSTART = "coldstart"; - public static final String ADDITIONAL_DATA = "additionalData"; - public static final String COUNT = "count"; - public static final String FROM = "from"; - public static final String COLLAPSE_KEY = "collapse_key"; - public static final String FORCE_SHOW = "forceShow"; - public static final String GCM = "GCM"; - public static final String CONTENT_AVAILABLE = "content-available"; - public static final String TOPICS = "topics"; - public static final String SET_APPLICATION_ICON_BADGE_NUMBER = "setApplicationIconBadgeNumber"; - public static final String CLEAR_ALL_NOTIFICATIONS = "clearAllNotifications"; - public static final String VISIBILITY = "visibility"; - public static final String INLINE_REPLY = "inlineReply"; - public static final String LOC_KEY = "locKey"; - public static final String LOC_DATA = "locData"; - public static final String TWILIO_BODY = "twi_body"; - public static final String TWILIO_TITLE = "twi_title"; - public static final String TWILIO_SOUND = "twi_sound"; - public static final String START_IN_BACKGROUND = "cdvStartInBackground"; - public static final String FORCE_START = "force-start"; -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java deleted file mode 100644 index 23682ac8..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushHandlerActivity.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.adobe.phonegap.push; - -import android.app.Activity; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.util.Log; -import android.support.v4.app.RemoteInput; - - -public class PushHandlerActivity extends Activity implements PushConstants { - private static String LOG_TAG = "PushPlugin_PushHandlerActivity"; - - /* - * this activity will be started if the user touches a notification that we own. - * We send it's data off to the push plugin for processing. - * If needed, we boot up the main activity to kickstart the application. - * @see android.app.Activity#onCreate(android.os.Bundle) - */ - @Override - public void onCreate(Bundle savedInstanceState) { - GCMIntentService gcm = new GCMIntentService(); - - Intent intent = getIntent(); - - int notId = intent.getExtras().getInt(NOT_ID, 0); - Log.d(LOG_TAG, "not id = " + notId); - gcm.setNotification(notId, ""); - super.onCreate(savedInstanceState); - Log.v(LOG_TAG, "onCreate"); - String callback = getIntent().getExtras().getString("callback"); - Log.d(LOG_TAG, "callback = " + callback); - boolean foreground = getIntent().getExtras().getBoolean("foreground", true); - boolean startOnBackground = getIntent().getExtras().getBoolean(START_IN_BACKGROUND, false); - - if(!startOnBackground){ - NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(GCMIntentService.getAppName(this), notId); - } - - boolean isPushPluginActive = PushPlugin.isActive(); - boolean inline = processPushBundle(isPushPluginActive, intent); - - if(inline && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N){ - foreground = true; - } - - Log.d(LOG_TAG, "bringToForeground = " + foreground); - - finish(); - - Log.d(LOG_TAG, "isPushPluginActive = " + isPushPluginActive); - if (!isPushPluginActive && foreground && inline) { - Log.d(LOG_TAG, "forceMainActivityReload"); - forceMainActivityReload(false); - } else if(startOnBackground) { - Log.d(LOG_TAG, "startOnBackgroundTrue"); - forceMainActivityReload(true); - } else { - Log.d(LOG_TAG, "don't want main activity"); - } - } - - /** - * Takes the pushBundle extras from the intent, - * and sends it through to the PushPlugin for processing. - */ - private boolean processPushBundle(boolean isPushPluginActive, Intent intent) { - Bundle extras = getIntent().getExtras(); - Bundle remoteInput = null; - - if (extras != null) { - Bundle originalExtras = extras.getBundle(PUSH_BUNDLE); - - originalExtras.putBoolean(FOREGROUND, false); - originalExtras.putBoolean(COLDSTART, !isPushPluginActive); - originalExtras.putString(ACTION_CALLBACK, extras.getString(CALLBACK)); - - remoteInput = RemoteInput.getResultsFromIntent(intent); - if (remoteInput != null) { - String inputString = remoteInput.getCharSequence(INLINE_REPLY).toString(); - Log.d(LOG_TAG, "response: " + inputString); - originalExtras.putString(INLINE_REPLY, inputString); - } - - PushPlugin.sendExtras(originalExtras); - } - return remoteInput == null; - } - - /** - * Forces the main activity to re-launch if it's unloaded. - */ - private void forceMainActivityReload(boolean startOnBackground) { - PackageManager pm = getPackageManager(); - Intent launchIntent = pm.getLaunchIntentForPackage(getApplicationContext().getPackageName()); - - Bundle extras = getIntent().getExtras(); - if (extras != null) { - Bundle originalExtras = extras.getBundle(PUSH_BUNDLE); - if (originalExtras != null) { - launchIntent.putExtras(originalExtras); - } - launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - launchIntent.addFlags(Intent.FLAG_FROM_BACKGROUND); - launchIntent.putExtra(START_IN_BACKGROUND, startOnBackground); - } - - startActivity(launchIntent); - } - - @Override - protected void onResume() { - super.onResume(); - final NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancelAll(); - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java deleted file mode 100644 index eaa39a48..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.adobe.phonegap.push; - -import android.content.Intent; -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; - -import com.google.android.gms.iid.InstanceID; -import com.google.android.gms.iid.InstanceIDListenerService; - -import org.json.JSONException; - -import java.io.IOException; - -public class PushInstanceIDListenerService extends InstanceIDListenerService implements PushConstants { - public static final String LOG_TAG = "PushPlugin_PushInstanceIDListenerService"; - - @Override - public void onTokenRefresh() { - SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - String senderID = sharedPref.getString(SENDER_ID, ""); - if (!"".equals(senderID)) { - Intent intent = new Intent(this, RegistrationIntentService.class); - startService(intent); - } - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java deleted file mode 100644 index f6faaa2b..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java +++ /dev/null @@ -1,458 +0,0 @@ -package com.adobe.phonegap.push; - -import android.app.NotificationManager; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.util.Log; - -import com.google.android.gms.gcm.GcmPubSub; -import com.google.android.gms.iid.InstanceID; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.CordovaWebView; -import org.apache.cordova.PluginResult; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.ArrayList; -import java.util.List; - -import me.leolin.shortcutbadger.ShortcutBadger; - -public class PushPlugin extends CordovaPlugin implements PushConstants { - - public static final String LOG_TAG = "PushPlugin"; - - private static CallbackContext pushContext; - private static CordovaWebView gWebView; - private static List<Bundle> gCachedExtras = Collections.synchronizedList(new ArrayList<Bundle>()); - private static boolean gForeground = false; - - private static String registration_id = ""; - - /** - * Gets the application context from cordova's main activity. - * @return the application context - */ - private Context getApplicationContext() { - return this.cordova.getActivity().getApplicationContext(); - } - - @Override - public boolean execute(final String action, final JSONArray data, final CallbackContext callbackContext) { - Log.v(LOG_TAG, "execute: action=" + action); - gWebView = this.webView; - - if (INITIALIZE.equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - pushContext = callbackContext; - JSONObject jo = null; - - Log.v(LOG_TAG, "execute: data=" + data.toString()); - SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - String senderID = null; - - try { - jo = data.getJSONObject(0).getJSONObject(ANDROID); - - Log.v(LOG_TAG, "execute: jo=" + jo.toString()); - - senderID = jo.getString(SENDER_ID); - - Log.v(LOG_TAG, "execute: senderID=" + senderID); - - String savedSenderID = sharedPref.getString(SENDER_ID, ""); - registration_id = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM); - - if (!"".equals(registration_id)) { - JSONObject json = new JSONObject().put(REGISTRATION_ID, registration_id); - - Log.v(LOG_TAG, "onRegistered: " + json.toString()); - - JSONArray topics = jo.optJSONArray(TOPICS); - subscribeToTopics(topics, registration_id); - - PushPlugin.sendEvent( json ); - } else { - callbackContext.error("Empty registration ID received from GCM"); - return; - } - } catch (JSONException e) { - Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); - callbackContext.error(e.getMessage()); - } catch (IOException e) { - Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); - callbackContext.error(e.getMessage()); - } - - if (jo != null) { - SharedPreferences.Editor editor = sharedPref.edit(); - try { - editor.putString(ICON, jo.getString(ICON)); - } catch (JSONException e) { - Log.d(LOG_TAG, "no icon option"); - } - try { - editor.putString(ICON_COLOR, jo.getString(ICON_COLOR)); - } catch (JSONException e) { - Log.d(LOG_TAG, "no iconColor option"); - } - - boolean clearBadge = jo.optBoolean(CLEAR_BADGE, false); - if (clearBadge) { - setApplicationIconBadgeNumber(getApplicationContext(), 0); - } - - editor.putBoolean(SOUND, jo.optBoolean(SOUND, true)); - editor.putBoolean(VIBRATE, jo.optBoolean(VIBRATE, true)); - editor.putBoolean(CLEAR_BADGE, clearBadge); - editor.putBoolean(CLEAR_NOTIFICATIONS, jo.optBoolean(CLEAR_NOTIFICATIONS, true)); - editor.putBoolean(FORCE_SHOW, jo.optBoolean(FORCE_SHOW, false)); - editor.putString(SENDER_ID, senderID); - editor.commit(); - - } - - if (!gCachedExtras.isEmpty()) { - Log.v(LOG_TAG, "sending cached extras"); - synchronized(gCachedExtras) { - Iterator<Bundle> gCachedExtrasIterator = gCachedExtras.iterator(); - while (gCachedExtrasIterator.hasNext()) { - sendExtras(gCachedExtrasIterator.next()); - } - } - gCachedExtras.clear(); - } - } - }); - } else if (UNREGISTER.equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - try { - SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - JSONArray topics = data.optJSONArray(0); - if (topics != null && !"".equals(registration_id)) { - unsubscribeFromTopics(topics, registration_id); - } else { - InstanceID.getInstance(getApplicationContext()).deleteInstanceID(); - Log.v(LOG_TAG, "UNREGISTER"); - - // Remove shared prefs - SharedPreferences.Editor editor = sharedPref.edit(); - editor.remove(SOUND); - editor.remove(VIBRATE); - editor.remove(CLEAR_BADGE); - editor.remove(CLEAR_NOTIFICATIONS); - editor.remove(FORCE_SHOW); - editor.remove(SENDER_ID); - editor.commit(); - } - - callbackContext.success(); - } catch (IOException e) { - Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); - callbackContext.error(e.getMessage()); - } - } - }); - } else if (FINISH.equals(action)) { - callbackContext.success(); - } else if (HAS_PERMISSION.equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - JSONObject jo = new JSONObject(); - try { - jo.put("isEnabled", PermissionUtils.hasPermission(getApplicationContext(), "OP_POST_NOTIFICATION")); - PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, jo); - pluginResult.setKeepCallback(true); - callbackContext.sendPluginResult(pluginResult); - } catch (UnknownError e) { - callbackContext.error(e.getMessage()); - } catch (JSONException e) { - callbackContext.error(e.getMessage()); - } - } - }); - } else if (SET_APPLICATION_ICON_BADGE_NUMBER.equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - Log.v(LOG_TAG, "setApplicationIconBadgeNumber: data=" + data.toString()); - try { - setApplicationIconBadgeNumber(getApplicationContext(), data.getJSONObject(0).getInt(BADGE)); - } catch (JSONException e) { - callbackContext.error(e.getMessage()); - } - callbackContext.success(); - } - }); - } else if (CLEAR_ALL_NOTIFICATIONS.equals(action)) { - cordova.getThreadPool().execute(new Runnable() { - public void run() { - Log.v(LOG_TAG, "clearAllNotifications"); - clearAllNotifications(); - callbackContext.success(); - } - }); - } else if (SUBSCRIBE.equals(action)){ - // Subscribing for a topic - cordova.getThreadPool().execute(new Runnable() { - public void run() { - try { - String topic = data.getString(0); - subscribeToTopic(topic, registration_id); - callbackContext.success(); - } catch (JSONException e) { - callbackContext.error(e.getMessage()); - } catch (IOException e) { - callbackContext.error(e.getMessage()); - } - } - }); - } else if (UNSUBSCRIBE.equals(action)){ - // un-subscribing for a topic - cordova.getThreadPool().execute(new Runnable(){ - public void run() { - try { - String topic = data.getString(0); - unsubscribeFromTopic(topic, registration_id); - callbackContext.success(); - } catch (JSONException e) { - callbackContext.error(e.getMessage()); - } catch (IOException e) { - callbackContext.error(e.getMessage()); - } - } - }); - } else { - Log.e(LOG_TAG, "Invalid action : " + action); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); - return false; - } - - return true; - } - - public static void sendEvent(JSONObject _json) { - PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, _json); - pluginResult.setKeepCallback(true); - if (pushContext != null) { - pushContext.sendPluginResult(pluginResult); - } - } - - public static void sendError(String message) { - PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, message); - pluginResult.setKeepCallback(true); - if (pushContext != null) { - pushContext.sendPluginResult(pluginResult); - } - } - - /* - * Sends the pushbundle extras to the client application. - * If the client application isn't currently active, it is cached for later processing. - */ - public static void sendExtras(Bundle extras) { - if (extras != null) { - if (gWebView != null) { - sendEvent(convertBundleToJson(extras)); - } else { - Log.v(LOG_TAG, "sendExtras: caching extras to send at a later time."); - gCachedExtras.add(extras); - } - } - } - - public static void setApplicationIconBadgeNumber(Context context, int badgeCount) { - if (badgeCount > 0) { - ShortcutBadger.applyCount(context, badgeCount); - } else { - ShortcutBadger.removeCount(context); - } - } - - @Override - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - gForeground = true; - } - - @Override - public void onPause(boolean multitasking) { - super.onPause(multitasking); - gForeground = false; - - SharedPreferences prefs = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - if (prefs.getBoolean(CLEAR_NOTIFICATIONS, true)) { - clearAllNotifications(); - } - } - - @Override - public void onResume(boolean multitasking) { - super.onResume(multitasking); - gForeground = true; - } - - @Override - public void onDestroy() { - super.onDestroy(); - gForeground = false; - gWebView = null; - } - - private void clearAllNotifications() { - final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancelAll(); - } - - /** - * Transform `topic name` to `topic path` - * Normally, the `topic` inputed from end-user is `topic name` only. - * We should convert them to GCM `topic path` - * Example: - * when topic name = 'my-topic' - * then topic path = '/topics/my-topic' - * - * @param String topic The topic name - * @return The topic path - */ - private String getTopicPath(String topic) - { - return "/topics/" + topic; - } - - private void subscribeToTopics(JSONArray topics, String registrationToken) throws IOException { - if (topics != null) { - String topic = null; - for (int i=0; i<topics.length(); i++) { - topic = topics.optString(i, null); - subscribeToTopic(topic, registrationToken); - } - } - } - - private void subscribeToTopic(String topic, String registrationToken) throws IOException - { - try { - if (topic != null) { - Log.d(LOG_TAG, "Subscribing to topic: " + topic); - GcmPubSub.getInstance(getApplicationContext()).subscribe(registrationToken, getTopicPath(topic), null); - } - } catch (IOException e) { - Log.e(LOG_TAG, "Failed to subscribe to topic: " + topic, e); - throw e; - } - } - - private void unsubscribeFromTopics(JSONArray topics, String registrationToken) { - if (topics != null) { - String topic = null; - for (int i=0; i<topics.length(); i++) { - try { - topic = topics.optString(i, null); - if (topic != null) { - Log.d(LOG_TAG, "Unsubscribing to topic: " + topic); - GcmPubSub.getInstance(getApplicationContext()).unsubscribe(registrationToken, getTopicPath(topic)); - } - } catch (IOException e) { - Log.e(LOG_TAG, "Failed to unsubscribe to topic: " + topic, e); - } - } - } - } - - private void unsubscribeFromTopic(String topic, String registrationToken) throws IOException - { - try { - if (topic != null) { - Log.d(LOG_TAG, "Unsubscribing to topic: " + topic); - GcmPubSub.getInstance(getApplicationContext()).unsubscribe(registrationToken, getTopicPath(topic)); - } - } catch (IOException e) { - Log.e(LOG_TAG, "Failed to unsubscribe to topic: " + topic, e); - throw e; - } - } - - /* - * serializes a bundle to JSON. - */ - private static JSONObject convertBundleToJson(Bundle extras) { - Log.d(LOG_TAG, "convert extras to json"); - try { - JSONObject json = new JSONObject(); - JSONObject additionalData = new JSONObject(); - - // Add any keys that need to be in top level json to this set - HashSet<String> jsonKeySet = new HashSet(); - Collections.addAll(jsonKeySet, TITLE,MESSAGE,COUNT,SOUND,IMAGE); - - Iterator<String> it = extras.keySet().iterator(); - while (it.hasNext()) { - String key = it.next(); - Object value = extras.get(key); - - Log.d(LOG_TAG, "key = " + key); - - if (jsonKeySet.contains(key)) { - json.put(key, value); - } - else if (key.equals(COLDSTART)) { - additionalData.put(key, extras.getBoolean(COLDSTART)); - } - else if (key.equals(FOREGROUND)) { - additionalData.put(key, extras.getBoolean(FOREGROUND)); - } - else if ( value instanceof String ) { - String strValue = (String)value; - try { - // Try to figure out if the value is another JSON object - if (strValue.startsWith("{")) { - additionalData.put(key, new JSONObject(strValue)); - } - // Try to figure out if the value is another JSON array - else if (strValue.startsWith("[")) { - additionalData.put(key, new JSONArray(strValue)); - } - else { - additionalData.put(key, value); - } - } catch (Exception e) { - additionalData.put(key, value); - } - } - } // while - - json.put(ADDITIONAL_DATA, additionalData); - Log.v(LOG_TAG, "extrasToJSON: " + json.toString()); - - return json; - } - catch( JSONException e) { - Log.e(LOG_TAG, "extrasToJSON: JSON exception"); - } - return null; - } - - public static boolean isInForeground() { - return gForeground; - } - - public static boolean isActive() { - return gWebView != null; - } - - protected static void setRegistrationID(String token) { - registration_id = token; - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/RegistrationIntentService.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/RegistrationIntentService.java deleted file mode 100644 index b181e88e..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/RegistrationIntentService.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.adobe.phonegap.push; - -import android.content.Context; - -import android.app.IntentService; -import android.content.Intent; -import android.content.SharedPreferences; -import android.util.Log; - -import com.google.android.gms.gcm.GoogleCloudMessaging; -import com.google.android.gms.iid.InstanceID; - -import java.io.IOException; - -public class RegistrationIntentService extends IntentService implements PushConstants { - public static final String LOG_TAG = "PushPlugin_RegistrationIntentService"; - - public RegistrationIntentService() { - super(LOG_TAG); - } - - @Override - protected void onHandleIntent(Intent intent) { - SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); - - try { - InstanceID instanceID = InstanceID.getInstance(this); - String senderID = sharedPreferences.getString(SENDER_ID, ""); - String token = instanceID.getToken(senderID, - GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); - PushPlugin.setRegistrationID(token); - Log.i(LOG_TAG, "new GCM Registration Token: " + token); - - } catch (Exception e) { - Log.d(LOG_TAG, "Failed to complete token refresh", e); - } - } -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/browser/ServiceWorker.js b/StoneIsland/plugins/phonegap-plugin-push/src/browser/ServiceWorker.js deleted file mode 100644 index 0fc06d09..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/browser/ServiceWorker.js +++ /dev/null @@ -1,51 +0,0 @@ -var messageChannel; - -self.addEventListener('install', function(event) { - self.skipWaiting(); -}); - -self.addEventListener('push', function(event) { - // parse incoming message - var obj = {}; - var pushData = { - image: 'https://avatars1.githubusercontent.com/u/60365?v=3&s=200', - additionalData: {} - }; - if (event.data) { - obj = event.data.json(); - } - - console.log(obj); - - // convert to push plugin API - for (var key in obj) { - if (key === 'title') { - pushData.title = obj[key]; - } else if (key === 'message' || key === 'body') { - pushData.message = obj[key]; - } else if (key === 'count' || key === 'msgcnt' || key === 'badge') { - pushData.count = obj[key]; - } else if (key === 'sound' || key === 'soundname') { - pushData.sound = obj[key]; - } else if (key === 'image') { - pushData.image = obj[key]; - } else { - pushData.additionalData[key] = obj[key]; - } - } - - event.waitUntil( - self.registration.showNotification(pushData.title, { - body: pushData.message, - icon: pushData.image, - tag: 'simple-push-demo-notification-tag' - }) - ); - - messageChannel.ports[0].postMessage(pushData); - -}); - -self.addEventListener('message', function(event) { - messageChannel = event; -}); diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/browser/manifest.json b/StoneIsland/plugins/phonegap-plugin-push/src/browser/manifest.json deleted file mode 100644 index ce8390ab..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/browser/manifest.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "Push Demo", - "gcm_sender_id": "85075801930" -} diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/ios/AppDelegate+notification.h b/StoneIsland/plugins/phonegap-plugin-push/src/ios/AppDelegate+notification.h deleted file mode 100644 index 9970762b..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/ios/AppDelegate+notification.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// AppDelegate+notification.h -// pushtest -// -// Created by Robert Easterday on 10/26/12. -// -// - -#import "AppDelegate.h" - -@interface AppDelegate (notification) -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; -- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:( void (^)(UIBackgroundFetchResult))completionHandler; -- (void)pushPluginOnApplicationDidBecomeActive:(UIApplication *)application; -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler; -- (id) getCommandInstance:(NSString*)className; - -@property (nonatomic, retain) NSDictionary *launchNotification; -@property (nonatomic, retain) NSNumber *coldstart; - -@end diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/ios/AppDelegate+notification.m b/StoneIsland/plugins/phonegap-plugin-push/src/ios/AppDelegate+notification.m deleted file mode 100644 index fc18dd79..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/ios/AppDelegate+notification.m +++ /dev/null @@ -1,278 +0,0 @@ -// -// AppDelegate+notification.m -// pushtest -// -// Created by Robert Easterday on 10/26/12. -// -// - -#import "AppDelegate+notification.h" -#import "PushPlugin.h" -#import <objc/runtime.h> - -static char launchNotificationKey; -static char coldstartKey; - -@implementation AppDelegate (notification) - -- (id) getCommandInstance:(NSString*)className -{ - return [self.viewController getCommandInstance:className]; -} - -// its dangerous to override a method from within a category. -// Instead we will use method swizzling. we set this up in the load call. -+ (void)load -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Class class = [self class]; - - SEL originalSelector = @selector(init); - SEL swizzledSelector = @selector(pushPluginSwizzledInit); - - Method original = class_getInstanceMethod(class, originalSelector); - Method swizzled = class_getInstanceMethod(class, swizzledSelector); - - BOOL didAddMethod = - class_addMethod(class, - originalSelector, - method_getImplementation(swizzled), - method_getTypeEncoding(swizzled)); - - if (didAddMethod) { - class_replaceMethod(class, - swizzledSelector, - method_getImplementation(original), - method_getTypeEncoding(original)); - } else { - method_exchangeImplementations(original, swizzled); - } - }); -} - -- (AppDelegate *)pushPluginSwizzledInit -{ - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(createNotificationChecker:) - name:UIApplicationDidFinishLaunchingNotification - object:nil]; - [[NSNotificationCenter defaultCenter]addObserver:self - selector:@selector(pushPluginOnApplicationDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - - // This actually calls the original init method over in AppDelegate. Equivilent to calling super - // on an overrided method, this is not recursive, although it appears that way. neat huh? - return [self pushPluginSwizzledInit]; -} - -// This code will be called immediately after application:didFinishLaunchingWithOptions:. We need -// to process notifications in cold-start situations -- (void)createNotificationChecker:(NSNotification *)notification -{ - NSLog(@"createNotificationChecker"); - if (notification) - { - NSDictionary *launchOptions = [notification userInfo]; - if (launchOptions) { - NSLog(@"coldstart"); - self.launchNotification = [launchOptions objectForKey: @"UIApplicationLaunchOptionsRemoteNotificationKey"]; - self.coldstart = [NSNumber numberWithBool:YES]; - } else { - NSLog(@"not coldstart"); - self.coldstart = [NSNumber numberWithBool:NO]; - } - } -} - -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - [pushHandler didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; -} - -- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - [pushHandler didFailToRegisterForRemoteNotificationsWithError:error]; -} - -- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { - NSLog(@"clicked on the shade"); - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - pushHandler.notificationMessage = userInfo; - pushHandler.isInline = NO; - [pushHandler notificationReceived]; -} - -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { - NSLog(@"didReceiveNotification with fetchCompletionHandler"); - - // app is in the foreground so call notification callback - if (application.applicationState == UIApplicationStateActive) { - NSLog(@"app active"); - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - pushHandler.notificationMessage = userInfo; - pushHandler.isInline = YES; - [pushHandler notificationReceived]; - - completionHandler(UIBackgroundFetchResultNewData); - } - // app is in background or in stand by - else { - NSLog(@"app in-active"); - - // do some convoluted logic to find out if this should be a silent push. - long silent = 0; - id aps = [userInfo objectForKey:@"aps"]; - id contentAvailable = [aps objectForKey:@"content-available"]; - if ([contentAvailable isKindOfClass:[NSString class]] && [contentAvailable isEqualToString:@"1"]) { - silent = 1; - } else if ([contentAvailable isKindOfClass:[NSNumber class]]) { - silent = [contentAvailable integerValue]; - } - - if (silent == 1) { - NSLog(@"this should be a silent push"); - void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){ - dispatch_async(dispatch_get_main_queue(), ^{ - completionHandler(result); - }); - }; - - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - - if (pushHandler.handlerObj == nil) { - pushHandler.handlerObj = [NSMutableDictionary dictionaryWithCapacity:2]; - } - - id notId = [userInfo objectForKey:@"notId"]; - if (notId != nil) { - NSLog(@"Push Plugin notId %@", notId); - [pushHandler.handlerObj setObject:safeHandler forKey:notId]; - } else { - NSLog(@"Push Plugin notId handler"); - [pushHandler.handlerObj setObject:safeHandler forKey:@"handler"]; - } - - pushHandler.notificationMessage = userInfo; - pushHandler.isInline = NO; - [pushHandler notificationReceived]; - } else { - NSLog(@"just put it in the shade"); - //save it for later - self.launchNotification = userInfo; - - completionHandler(UIBackgroundFetchResultNewData); - } - } -} - -- (BOOL)userHasRemoteNotificationsEnabled { - UIApplication *application = [UIApplication sharedApplication]; - if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) { - return application.currentUserNotificationSettings.types != UIUserNotificationTypeNone; - } else { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - return application.enabledRemoteNotificationTypes != UIRemoteNotificationTypeNone; -#pragma GCC diagnostic pop - } -} - -- (void)pushPluginOnApplicationDidBecomeActive:(NSNotification *)notification { - - NSLog(@"active"); - - UIApplication *application = notification.object; - - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - if (pushHandler.clearBadge) { - NSLog(@"PushPlugin clearing badge"); - //zero badge - application.applicationIconBadgeNumber = 0; - } else { - NSLog(@"PushPlugin skip clear badge"); - } - - if (self.launchNotification) { - pushHandler.isInline = NO; - pushHandler.coldstart = [self.coldstart boolValue]; - pushHandler.notificationMessage = self.launchNotification; - self.launchNotification = nil; - self.coldstart = [NSNumber numberWithBool:NO]; - [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO]; - } -} - - -- (void)application:(UIApplication *) application handleActionWithIdentifier: (NSString *) identifier -forRemoteNotification: (NSDictionary *) notification completionHandler: (void (^)()) completionHandler { - - NSLog(@"Push Plugin handleActionWithIdentifier %@", identifier); - NSMutableDictionary *userInfo = [notification mutableCopy]; - [userInfo setObject:identifier forKey:@"actionCallback"]; - NSLog(@"Push Plugin userInfo %@", userInfo); - - if (application.applicationState == UIApplicationStateActive) { - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - pushHandler.notificationMessage = userInfo; - pushHandler.isInline = NO; - [pushHandler notificationReceived]; - } else { - void (^safeHandler)() = ^(void){ - dispatch_async(dispatch_get_main_queue(), ^{ - completionHandler(); - }); - }; - - PushPlugin *pushHandler = [self getCommandInstance:@"PushNotification"]; - - if (pushHandler.handlerObj == nil) { - pushHandler.handlerObj = [NSMutableDictionary dictionaryWithCapacity:2]; - } - - id notId = [userInfo objectForKey:@"notId"]; - if (notId != nil) { - NSLog(@"Push Plugin notId %@", notId); - [pushHandler.handlerObj setObject:safeHandler forKey:notId]; - } else { - NSLog(@"Push Plugin notId handler"); - [pushHandler.handlerObj setObject:safeHandler forKey:@"handler"]; - } - - pushHandler.notificationMessage = userInfo; - pushHandler.isInline = NO; - - [pushHandler performSelectorOnMainThread:@selector(notificationReceived) withObject:pushHandler waitUntilDone:NO]; - } -} - -// The accessors use an Associative Reference since you can't define a iVar in a category -// http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html -- (NSMutableArray *)launchNotification -{ - return objc_getAssociatedObject(self, &launchNotificationKey); -} - -- (void)setLaunchNotification:(NSDictionary *)aDictionary -{ - objc_setAssociatedObject(self, &launchNotificationKey, aDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (NSNumber *)coldstart -{ - return objc_getAssociatedObject(self, &coldstartKey); -} - -- (void)setColdstart:(NSNumber *)aNumber -{ - objc_setAssociatedObject(self, &coldstartKey, aNumber, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -- (void)dealloc -{ - self.launchNotification = nil; // clear the association and release the object - self.coldstart = nil; -} - -@end diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/ios/PushPlugin.h b/StoneIsland/plugins/phonegap-plugin-push/src/ios/PushPlugin.h deleted file mode 100644 index 276a0080..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/ios/PushPlugin.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright 2009-2011 Urban Airship Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binaryform must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided withthe distribution. - - THIS SOFTWARE IS PROVIDED BY THE URBAN AIRSHIP INC``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - EVENT SHALL URBAN AIRSHIP INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import <Foundation/Foundation.h> -#import <Cordova/CDV.h> -#import <Cordova/CDVPlugin.h> - -@protocol GGLInstanceIDDelegate; -@protocol GCMReceiverDelegate; -@interface PushPlugin : CDVPlugin<GGLInstanceIDDelegate, GCMReceiverDelegate> -{ - NSDictionary *notificationMessage; - BOOL isInline; - NSString *notificationCallbackId; - NSString *callback; - BOOL clearBadge; - - NSMutableDictionary *handlerObj; - void (^completionHandler)(UIBackgroundFetchResult); - - BOOL ready; -} - -@property (nonatomic, copy) NSString *callbackId; -@property (nonatomic, copy) NSString *notificationCallbackId; -@property (nonatomic, copy) NSString *callback; - -@property (nonatomic, strong) NSDictionary *notificationMessage; -@property BOOL isInline; -@property BOOL coldstart; -@property BOOL clearBadge; -@property (nonatomic, strong) NSMutableDictionary *handlerObj; - -- (void)init:(CDVInvokedUrlCommand*)command; -- (void)unregister:(CDVInvokedUrlCommand*)command; -- (void)subscribe:(CDVInvokedUrlCommand*)command; -- (void)unsubscribe:(CDVInvokedUrlCommand*)command; - -- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; -- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; - -- (void)setNotificationMessage:(NSDictionary *)notification; -- (void)notificationReceived; - -- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error; -- (void)didSendDataMessageWithID:(NSString *)messageID; -- (void)didDeleteMessagesOnServer; - -// GCM Features -@property(nonatomic, assign) BOOL usesGCM; -@property(nonatomic, strong) NSNumber* gcmSandbox; -@property(nonatomic, strong) NSString *gcmSenderId; -@property(nonatomic, strong) NSDictionary *gcmRegistrationOptions; -@property(nonatomic, strong) void (^gcmRegistrationHandler) (NSString *registrationToken, NSError *error); -@property(nonatomic, strong) NSString *gcmRegistrationToken; -@property(nonatomic, strong) NSArray *gcmTopics; - -@end diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/ios/PushPlugin.m b/StoneIsland/plugins/phonegap-plugin-push/src/ios/PushPlugin.m deleted file mode 100644 index a176b9af..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/ios/PushPlugin.m +++ /dev/null @@ -1,677 +0,0 @@ -/* - Copyright 2009-2011 Urban Airship Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binaryform must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided withthe distribution. - - THIS SOFTWARE IS PROVIDED BY THE URBAN AIRSHIP INC``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - EVENT SHALL URBAN AIRSHIP INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// See GGLInstanceID.h -#define GMP_NO_MODULES true - -#import "PushPlugin.h" -#import "GoogleCloudMessaging.h" -#import "GGLInstanceIDHeaders.h" - -@implementation PushPlugin : CDVPlugin - -@synthesize notificationMessage; -@synthesize isInline; -@synthesize coldstart; - -@synthesize callbackId; -@synthesize notificationCallbackId; -@synthesize callback; -@synthesize clearBadge; -@synthesize handlerObj; - -@synthesize usesGCM; -@synthesize gcmSandbox; -@synthesize gcmSenderId; -@synthesize gcmRegistrationOptions; -@synthesize gcmRegistrationHandler; -@synthesize gcmRegistrationToken; -@synthesize gcmTopics; - --(void)initGCMRegistrationHandler; -{ - __weak __block PushPlugin *weakSelf = self; - gcmRegistrationHandler = ^(NSString *registrationToken, NSError *error){ - if (registrationToken != nil) { - NSLog(@"GCM Registration Token: %@", registrationToken); - [weakSelf setGcmRegistrationToken: registrationToken]; - - id topics = [weakSelf gcmTopics]; - if (topics != nil) { - for (NSString *topic in topics) { - NSLog(@"subscribe from topic: %@", topic); - id pubSub = [GCMPubSub sharedInstance]; - [pubSub subscribeWithToken: [weakSelf gcmRegistrationToken] - topic:[NSString stringWithFormat:@"/topics/%@", topic] - options:nil - handler:^void(NSError *error) { - if (error) { - if (error.code == 3001) { - NSLog(@"Already subscribed to %@", topic); - } else { - NSLog(@"Failed to subscribe to topic %@: %@", topic, error); - } - } - else { - NSLog(@"Successfully subscribe to topic %@", topic); - } - }]; - } - } - - [weakSelf registerWithToken:registrationToken]; - } else { - NSLog(@"Registration to GCM failed with error: %@", error.localizedDescription); - [weakSelf failWithMessage:self.callbackId withMsg:@"" withError:error]; - } - }; -} - -// GCM refresh token -// Unclear how this is testable under normal circumstances -- (void)onTokenRefresh { -#if !TARGET_IPHONE_SIMULATOR - // A rotation of the registration tokens is happening, so the app needs to request a new token. - NSLog(@"The GCM registration token needs to be changed."); - [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:[self gcmSenderId] - scope:kGGLInstanceIDScopeGCM - options:[self gcmRegistrationOptions] - handler:[self gcmRegistrationHandler]]; -#endif -} - -- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error { - NSLog(@"willSendDataMessageWithID"); - if (error) { - // Failed to send the message. - } else { - // Will send message, you can save the messageID to track the message - } -} - -- (void)didSendDataMessageWithID:(NSString *)messageID { - NSLog(@"willSendDataMessageWithID"); - // Did successfully send message identified by messageID -} - -- (void)didDeleteMessagesOnServer { - NSLog(@"didDeleteMessagesOnServer"); - // Some messages sent to this device were deleted on the GCM server before reception, likely - // because the TTL expired. The client should notify the app server of this, so that the app - // server can resend those messages. -} - -- (void)unregister:(CDVInvokedUrlCommand*)command; -{ - NSArray* topics = [command argumentAtIndex:0]; - - if (topics != nil) { - id pubSub = [GCMPubSub sharedInstance]; - for (NSString *topic in topics) { - NSLog(@"unsubscribe from topic: %@", topic); - [pubSub unsubscribeWithToken: [self gcmRegistrationToken] - topic:[NSString stringWithFormat:@"/topics/%@", topic] - options:nil - handler:^void(NSError *error) { - if (error) { - NSLog(@"Failed to unsubscribe from topic %@: %@", topic, error); - } - else { - NSLog(@"Successfully unsubscribe from topic %@", topic); - } - }]; - } - } else { - [[UIApplication sharedApplication] unregisterForRemoteNotifications]; - [self successWithMessage:command.callbackId withMsg:@"unregistered"]; - } -} - -- (void)subscribe:(CDVInvokedUrlCommand*)command; -{ - NSString* topic = [command argumentAtIndex:0]; - - if (topic != nil) { - NSLog(@"subscribe from topic: %@", topic); - id pubSub = [GCMPubSub sharedInstance]; - [pubSub subscribeWithToken: [self gcmRegistrationToken] - topic:[NSString stringWithFormat:@"/topics/%@", topic] - options:nil - handler:^void(NSError *error) { - if (error) { - if (error.code == 3001) { - NSLog(@"Already subscribed to %@", topic); - [self successWithMessage:command.callbackId withMsg:[NSString stringWithFormat:@"Already subscribed to %@", topic]]; - } else { - NSLog(@"Failed to subscribe to topic %@: %@", topic, error); - [self failWithMessage:command.callbackId withMsg:[NSString stringWithFormat:@"Failed to subscribe to topic %@", topic] withError:error]; - } - } - else { - NSLog(@"Successfully subscribe to topic %@", topic); - [self successWithMessage:command.callbackId withMsg:[NSString stringWithFormat:@"Successfully subscribe to topic %@", topic]]; - } - }]; - } else { - NSLog(@"There is no topic to subscribe"); - [self successWithMessage:command.callbackId withMsg:@"There is no topic to subscribe"]; - } -} - -- (void)unsubscribe:(CDVInvokedUrlCommand*)command; -{ - NSString* topic = [command argumentAtIndex:0]; - - if (topic != nil) { - NSLog(@"unsubscribe from topic: %@", topic); - id pubSub = [GCMPubSub sharedInstance]; - [pubSub unsubscribeWithToken: [self gcmRegistrationToken] - topic:[NSString stringWithFormat:@"/topics/%@", topic] - options:nil - handler:^void(NSError *error) { - if (error) { - NSLog(@"Failed to unsubscribe to topic %@: %@", topic, error); - [self failWithMessage:command.callbackId withMsg:[NSString stringWithFormat:@"Failed to unsubscribe to topic %@", topic] withError:error]; - } else { - NSLog(@"Successfully unsubscribe to topic %@", topic); - [self successWithMessage:command.callbackId withMsg:[NSString stringWithFormat:@"Successfully unsubscribe to topic %@", topic]]; - } - }]; - } else { - NSLog(@"There is no topic to unsubscribe"); - [self successWithMessage:command.callbackId withMsg:@"There is no topic to unsubscribe"]; - } -} - -- (void)init:(CDVInvokedUrlCommand*)command; -{ - [self.commandDelegate runInBackground:^ { - - NSLog(@"Push Plugin register called"); - self.callbackId = command.callbackId; - - NSMutableDictionary* options = [command.arguments objectAtIndex:0]; - NSMutableDictionary* iosOptions = [options objectForKey:@"ios"]; - - NSArray* topics = [iosOptions objectForKey:@"topics"]; - [self setGcmTopics:topics]; - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - UIUserNotificationType UserNotificationTypes = UIUserNotificationTypeNone; -#endif - UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeNone; - - id badgeArg = [iosOptions objectForKey:@"badge"]; - id soundArg = [iosOptions objectForKey:@"sound"]; - id alertArg = [iosOptions objectForKey:@"alert"]; - id clearBadgeArg = [iosOptions objectForKey:@"clearBadge"]; - - if (([badgeArg isKindOfClass:[NSString class]] && [badgeArg isEqualToString:@"true"]) || [badgeArg boolValue]) - { - notificationTypes |= UIRemoteNotificationTypeBadge; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - UserNotificationTypes |= UIUserNotificationTypeBadge; -#endif - } - - if (([soundArg isKindOfClass:[NSString class]] && [soundArg isEqualToString:@"true"]) || [soundArg boolValue]) - { - notificationTypes |= UIRemoteNotificationTypeSound; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - UserNotificationTypes |= UIUserNotificationTypeSound; -#endif - } - - if (([alertArg isKindOfClass:[NSString class]] && [alertArg isEqualToString:@"true"]) || [alertArg boolValue]) - { - notificationTypes |= UIRemoteNotificationTypeAlert; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - UserNotificationTypes |= UIUserNotificationTypeAlert; -#endif - } - - notificationTypes |= UIRemoteNotificationTypeNewsstandContentAvailability; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - UserNotificationTypes |= UIUserNotificationActivationModeBackground; -#endif - - if (clearBadgeArg == nil || ([clearBadgeArg isKindOfClass:[NSString class]] && [clearBadgeArg isEqualToString:@"false"]) || ![clearBadgeArg boolValue]) { - NSLog(@"PushPlugin.register: setting badge to false"); - clearBadge = NO; - } else { - NSLog(@"PushPlugin.register: setting badge to true"); - clearBadge = YES; - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; - } - NSLog(@"PushPlugin.register: clear badge is set to %d", clearBadge); - - if (notificationTypes == UIRemoteNotificationTypeNone) - NSLog(@"PushPlugin.register: Push notification type is set to none"); - - isInline = NO; - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - NSLog(@"PushPlugin.register: better button setup"); - // setup action buttons - NSMutableSet *categories = [[NSMutableSet alloc] init]; - id categoryOptions = [iosOptions objectForKey:@"categories"]; - if (categoryOptions != nil && [categoryOptions isKindOfClass:[NSDictionary class]]) { - for (id key in categoryOptions) { - NSLog(@"categories: key %@", key); - id category = [categoryOptions objectForKey:key]; - - id yesButton = [category objectForKey:@"yes"]; - UIMutableUserNotificationAction *yesAction; - if (yesButton != nil && [yesButton isKindOfClass:[NSDictionary class]]) { - yesAction = [self createAction: yesButton]; - } - id noButton = [category objectForKey:@"no"]; - UIMutableUserNotificationAction *noAction; - if (noButton != nil && [noButton isKindOfClass:[NSDictionary class]]) { - noAction = [self createAction: noButton]; - } - id maybeButton = [category objectForKey:@"maybe"]; - UIMutableUserNotificationAction *maybeAction; - if (maybeButton != nil && [maybeButton isKindOfClass:[NSDictionary class]]) { - maybeAction = [self createAction: maybeButton]; - } - - // First create the category - UIMutableUserNotificationCategory *notificationCategory = [[UIMutableUserNotificationCategory alloc] init]; - - // Identifier to include in your push payload and local notification - notificationCategory.identifier = key; - - NSMutableArray *categoryArray = [[NSMutableArray alloc] init]; - NSMutableArray *minimalCategoryArray = [[NSMutableArray alloc] init]; - if (yesButton != nil) { - [categoryArray addObject:yesAction]; - [minimalCategoryArray addObject:yesAction]; - } - if (noButton != nil) { - [categoryArray addObject:noAction]; - [minimalCategoryArray addObject:noAction]; - } - if (maybeButton != nil) { - [categoryArray addObject:maybeAction]; - } - - // Add the actions to the category and set the action context - [notificationCategory setActions:categoryArray forContext:UIUserNotificationActionContextDefault]; - - // Set the actions to present in a minimal context - [notificationCategory setActions:minimalCategoryArray forContext:UIUserNotificationActionContextMinimal]; - - NSLog(@"Adding category %@", key); - [categories addObject:notificationCategory]; - } - - } -#else - NSLog(@"PushPlugin.register: action buttons only supported on iOS8 and above"); -#endif - - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 - if ([[UIApplication sharedApplication]respondsToSelector:@selector(registerUserNotificationSettings:)]) { - UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UserNotificationTypes categories:categories]; - [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; - [[UIApplication sharedApplication] registerForRemoteNotifications]; - } else { - [[UIApplication sharedApplication] registerForRemoteNotificationTypes: - (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; - } -#else - [[UIApplication sharedApplication] registerForRemoteNotificationTypes: - (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]; -#endif - - // GCM options - [self setGcmSenderId: [iosOptions objectForKey:@"senderID"]]; - NSLog(@"GCM Sender ID %@", gcmSenderId); - if([[self gcmSenderId] length] > 0) { - NSLog(@"Using GCM Notification"); - [self setUsesGCM: YES]; - [self initGCMRegistrationHandler]; - } else { - NSLog(@"Using APNS Notification"); - [self setUsesGCM:NO]; - } - id gcmSandBoxArg = [iosOptions objectForKey:@"gcmSandbox"]; - - [self setGcmSandbox:@NO]; - if ([self usesGCM] && - (([gcmSandBoxArg isKindOfClass:[NSString class]] && [gcmSandBoxArg isEqualToString:@"true"]) || - [gcmSandBoxArg boolValue])) - { - NSLog(@"Using GCM Sandbox"); - [self setGcmSandbox:@YES]; - } - - if (notificationMessage) { // if there is a pending startup notification - dispatch_async(dispatch_get_main_queue(), ^{ - // delay to allow JS event handlers to be setup - [self performSelector:@selector(notificationReceived) withObject:nil afterDelay: 0.5]; - }); - } - }]; -} - -- (UIMutableUserNotificationAction *)createAction:(NSDictionary *)dictionary { - - UIMutableUserNotificationAction *myAction = [[UIMutableUserNotificationAction alloc] init]; - - myAction = [[UIMutableUserNotificationAction alloc] init]; - myAction.identifier = [dictionary objectForKey:@"callback"]; - myAction.title = [dictionary objectForKey:@"title"]; - id mode =[dictionary objectForKey:@"foreground"]; - if (mode == nil || ([mode isKindOfClass:[NSString class]] && [mode isEqualToString:@"false"]) || ![mode boolValue]) { - myAction.activationMode = UIUserNotificationActivationModeBackground; - } else { - myAction.activationMode = UIUserNotificationActivationModeForeground; - } - id destructive = [dictionary objectForKey:@"destructive"]; - if (destructive == nil || ([destructive isKindOfClass:[NSString class]] && [destructive isEqualToString:@"false"]) || ![destructive boolValue]) { - myAction.destructive = NO; - } else { - myAction.destructive = YES; - } - myAction.authenticationRequired = NO; - - return myAction; -} - -- (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - if (self.callbackId == nil) { - NSLog(@"Unexpected call to didRegisterForRemoteNotificationsWithDeviceToken, ignoring: %@", deviceToken); - return; - } - NSLog(@"Push Plugin register success: %@", deviceToken); - - NSMutableDictionary *results = [NSMutableDictionary dictionary]; - NSString *token = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""] - stringByReplacingOccurrencesOfString:@">" withString:@""] - stringByReplacingOccurrencesOfString: @" " withString: @""]; - [results setValue:token forKey:@"deviceToken"]; - -#if !TARGET_IPHONE_SIMULATOR - // Get Bundle Info for Remote Registration (handy if you have more than one app) - [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] forKey:@"appName"]; - [results setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] forKey:@"appVersion"]; - - // Check what Notifications the user has turned on. We registered for all three, but they may have manually disabled some or all of them. -#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) - - NSUInteger rntypes; - if (!SYSTEM_VERSION_LESS_THAN(@"8.0")) { - rntypes = [[[UIApplication sharedApplication] currentUserNotificationSettings] types]; - } else { - rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes]; - } - - // Set the defaults to disabled unless we find otherwise... - NSString *pushBadge = @"disabled"; - NSString *pushAlert = @"disabled"; - NSString *pushSound = @"disabled"; - - // Check what Registered Types are turned on. This is a bit tricky since if two are enabled, and one is off, it will return a number 2... not telling you which - // one is actually disabled. So we are literally checking to see if rnTypes matches what is turned on, instead of by number. The "tricky" part is that the - // single notification types will only match if they are the ONLY one enabled. Likewise, when we are checking for a pair of notifications, it will only be - // true if those two notifications are on. This is why the code is written this way - if(rntypes & UIRemoteNotificationTypeBadge){ - pushBadge = @"enabled"; - } - if(rntypes & UIRemoteNotificationTypeAlert) { - pushAlert = @"enabled"; - } - if(rntypes & UIRemoteNotificationTypeSound) { - pushSound = @"enabled"; - } - - [results setValue:pushBadge forKey:@"pushBadge"]; - [results setValue:pushAlert forKey:@"pushAlert"]; - [results setValue:pushSound forKey:@"pushSound"]; - - // Get the users Device Model, Display Name, Token & Version Number - UIDevice *dev = [UIDevice currentDevice]; - [results setValue:dev.name forKey:@"deviceName"]; - [results setValue:dev.model forKey:@"deviceModel"]; - [results setValue:dev.systemVersion forKey:@"deviceSystemVersion"]; - - if([self usesGCM]) { - GGLInstanceIDConfig *instanceIDConfig = [GGLInstanceIDConfig defaultConfig]; - instanceIDConfig.delegate = self; - [[GGLInstanceID sharedInstance] startWithConfig:instanceIDConfig]; - - [self setGcmRegistrationOptions: @{kGGLInstanceIDRegisterAPNSOption:deviceToken, - kGGLInstanceIDAPNSServerTypeSandboxOption:[self gcmSandbox]}]; - - [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:[self gcmSenderId] - scope:kGGLInstanceIDScopeGCM - options:[self gcmRegistrationOptions] - handler:[self gcmRegistrationHandler]]; - - GCMConfig *gcmConfig = [GCMConfig defaultConfig]; - gcmConfig.receiverDelegate = self; - [[GCMService sharedInstance] startWithConfig:gcmConfig]; - - } else { - [self registerWithToken: token]; - } -#endif -} - -- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error -{ - if (self.callbackId == nil) { - NSLog(@"Unexpected call to didFailToRegisterForRemoteNotificationsWithError, ignoring: %@", error); - return; - } - NSLog(@"Push Plugin register failed"); - [self failWithMessage:self.callbackId withMsg:@"" withError:error]; -} - -- (void)notificationReceived { - NSLog(@"Notification received"); - - if (notificationMessage && self.callbackId != nil) - { - NSMutableDictionary* message = [NSMutableDictionary dictionaryWithCapacity:4]; - NSMutableDictionary* additionalData = [NSMutableDictionary dictionaryWithCapacity:4]; - - - for (id key in notificationMessage) { - if ([key isEqualToString:@"aps"]) { - id aps = [notificationMessage objectForKey:@"aps"]; - - for(id key in aps) { - NSLog(@"Push Plugin key: %@", key); - id value = [aps objectForKey:key]; - - if ([key isEqualToString:@"alert"]) { - if ([value isKindOfClass:[NSDictionary class]]) { - for (id messageKey in value) { - id messageValue = [value objectForKey:messageKey]; - if ([messageKey isEqualToString:@"body"]) { - [message setObject:messageValue forKey:@"message"]; - } else if ([messageKey isEqualToString:@"title"]) { - [message setObject:messageValue forKey:@"title"]; - } else { - [additionalData setObject:messageValue forKey:messageKey]; - } - } - } - else { - [message setObject:value forKey:@"message"]; - } - } else if ([key isEqualToString:@"title"]) { - [message setObject:value forKey:@"title"]; - } else if ([key isEqualToString:@"badge"]) { - [message setObject:value forKey:@"count"]; - } else if ([key isEqualToString:@"sound"]) { - [message setObject:value forKey:@"sound"]; - } else if ([key isEqualToString:@"image"]) { - [message setObject:value forKey:@"image"]; - } else { - [additionalData setObject:value forKey:key]; - } - } - } else { - [additionalData setObject:[notificationMessage objectForKey:key] forKey:key]; - } - } - - if (isInline) { - [additionalData setObject:[NSNumber numberWithBool:YES] forKey:@"foreground"]; - } else { - [additionalData setObject:[NSNumber numberWithBool:NO] forKey:@"foreground"]; - } - - if (coldstart) { - [additionalData setObject:[NSNumber numberWithBool:YES] forKey:@"coldstart"]; - } else { - [additionalData setObject:[NSNumber numberWithBool:NO] forKey:@"coldstart"]; - } - - [message setObject:additionalData forKey:@"additionalData"]; - - // send notification message - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message]; - [pluginResult setKeepCallbackAsBool:YES]; - [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; - - self.coldstart = NO; - self.notificationMessage = nil; - } -} - -- (void)setApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command -{ - NSMutableDictionary* options = [command.arguments objectAtIndex:0]; - int badge = [[options objectForKey:@"badge"] intValue] ?: 0; - - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge]; - - NSString* message = [NSString stringWithFormat:@"app badge count set to %d", badge]; - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; - [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; -} - -- (void)getApplicationIconBadgeNumber:(CDVInvokedUrlCommand *)command -{ - NSInteger badge = [UIApplication sharedApplication].applicationIconBadgeNumber; - - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)badge]; - [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; -} - -- (void)clearAllNotifications:(CDVInvokedUrlCommand *)command -{ - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; - - NSString* message = [NSString stringWithFormat:@"cleared all notifications"]; - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; - [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; -} - -- (void)hasPermission:(CDVInvokedUrlCommand *)command -{ - BOOL enabled = NO; - id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate; - if ([appDelegate respondsToSelector:@selector(userHasRemoteNotificationsEnabled)]) { - enabled = [appDelegate performSelector:@selector(userHasRemoteNotificationsEnabled)]; - } - - NSMutableDictionary* message = [NSMutableDictionary dictionaryWithCapacity:1]; - [message setObject:[NSNumber numberWithBool:enabled] forKey:@"isEnabled"]; - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message]; - [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; -} - --(void)successWithMessage:(NSString *)callbackId withMsg:(NSString *)message -{ - if (callbackId != nil) - { - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:message]; - [self.commandDelegate sendPluginResult:commandResult callbackId:callbackId]; - } -} - --(void)registerWithToken:(NSString*)token; { - // Send result to trigger 'registration' event but keep callback - NSMutableDictionary* message = [NSMutableDictionary dictionaryWithCapacity:1]; - [message setObject:token forKey:@"registrationId"]; - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:message]; - [pluginResult setKeepCallbackAsBool:YES]; - [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; -} - - --(void)failWithMessage:(NSString *)callbackId withMsg:(NSString *)message withError:(NSError *)error -{ - NSString *errorMessage = (error) ? [NSString stringWithFormat:@"%@ - %@", message, [error localizedDescription]] : message; - CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:errorMessage]; - - [self.commandDelegate sendPluginResult:commandResult callbackId:callbackId]; -} - --(void) finish:(CDVInvokedUrlCommand*)command -{ - NSLog(@"Push Plugin finish called"); - - [self.commandDelegate runInBackground:^ { - NSString* notId = [command.arguments objectAtIndex:0]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [NSTimer scheduledTimerWithTimeInterval:0.1 - target:self - selector:@selector(stopBackgroundTask:) - userInfo:notId - repeats:NO]; - }); - - CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; - }]; -} - --(void)stopBackgroundTask:(NSTimer*)timer -{ - UIApplication *app = [UIApplication sharedApplication]; - - NSLog(@"Push Plugin stopBackgroundTask called"); - - if (handlerObj) { - NSLog(@"Push Plugin handlerObj"); - completionHandler = [handlerObj[[timer userInfo]] copy]; - if (completionHandler) { - NSLog(@"Push Plugin: stopBackgroundTask (remaining t: %f)", app.backgroundTimeRemaining); - completionHandler(UIBackgroundFetchResultNewData); - completionHandler = nil; - } - } -} - -@end diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/windows/PushPluginProxy.js b/StoneIsland/plugins/phonegap-plugin-push/src/windows/PushPluginProxy.js deleted file mode 100644 index ac04f39d..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/src/windows/PushPluginProxy.js +++ /dev/null @@ -1,93 +0,0 @@ -var myApp = {}; -var pushNotifications = Windows.Networking.PushNotifications; - -var createNotificationJSON = function (e) { - var result = { message: '' }; //Added to identify callback as notification type in the API in case where notification has no message - var notificationPayload; - - switch (e.notificationType) { - case pushNotifications.PushNotificationType.toast: - case pushNotifications.PushNotificationType.tile: - if (e.notificationType === pushNotifications.PushNotificationType.toast) { - notificationPayload = e.toastNotification.content; - } - else { - notificationPayload = e.tileNotification.content; - } - var texts = notificationPayload.getElementsByTagName("text"); - if (texts.length > 1) { - result.title = texts[0].innerText; - result.message = texts[1].innerText; - } - else if(texts.length === 1) { - result.message = texts[0].innerText; - } - var images = notificationPayload.getElementsByTagName("image"); - if (images.length > 0) { - result.image = images[0].getAttribute("src"); - } - var soundFile = notificationPayload.getElementsByTagName("audio"); - if (soundFile.length > 0) { - result.sound = soundFile[0].getAttribute("src"); - } - break; - - case pushNotifications.PushNotificationType.badge: - notificationPayload = e.badgeNotification.content; - result.count = notificationPayload.getElementsByTagName("badge")[0].getAttribute("value"); - break; - - case pushNotifications.PushNotificationType.raw: - result.message = e.rawNotification.content; - break; - } - - result.additionalData = { coldstart: false }; // this gets called only when the app is running - result.additionalData.pushNotificationReceivedEventArgs = e; - return result; -} - -module.exports = { - init: function (onSuccess, onFail, args) { - - var onNotificationReceived = function (e) { - var result = createNotificationJSON(e); - onSuccess(result, { keepCallback: true }); - } - - try { - pushNotifications.PushNotificationChannelManager.createPushNotificationChannelForApplicationAsync().done( - function (channel) { - var result = {}; - result.registrationId = channel.uri; - myApp.channel = channel; - channel.addEventListener("pushnotificationreceived", onNotificationReceived); - myApp.notificationEvent = onNotificationReceived; - onSuccess(result, { keepCallback: true }); - - var context = cordova.require('cordova/platform').activationContext; - var launchArgs = context ? context.args : null; - if (launchArgs) { //If present, app launched through push notification - var result = { message: '' }; //Added to identify callback as notification type in the API - result.launchArgs = launchArgs; - result.additionalData = { coldstart: true }; - onSuccess(result, { keepCallback: true }); - } - }, function (error) { - onFail(error); - }); - } catch (ex) { - onFail(ex); - } - }, - unregister: function (onSuccess, onFail, args) { - try { - myApp.channel.removeEventListener("pushnotificationreceived", myApp.notificationEvent); - myApp.channel.close(); - onSuccess(); - } catch(ex) { - onFail(ex); - } - } -}; -require("cordova/exec/proxy").add("PushNotification", module.exports); diff --git a/StoneIsland/plugins/phonegap-plugin-push/www/browser/push.js b/StoneIsland/plugins/phonegap-plugin-push/www/browser/push.js deleted file mode 100644 index 9b74d8a4..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/www/browser/push.js +++ /dev/null @@ -1,357 +0,0 @@ -/* global cordova:false */ -/* globals window, document, navigator */ - -/*! - * Module dependencies. - */ - -var exec = cordova.require('cordova/exec'); - -/** - * PushNotification constructor. - * - * @param {Object} options to initiate Push Notifications. - * @return {PushNotification} instance that can be monitored and cancelled. - */ -var serviceWorker, subscription; -var PushNotification = function(options) { - this._handlers = { - 'registration': [], - 'notification': [], - 'error': [] - }; - - // require options parameter - if (typeof options === 'undefined') { - throw new Error('The options argument is required.'); - } - - // store the options to this object instance - this.options = options; - - // triggered on registration and notification - var that = this; - - // Add manifest.json to main HTML file - var linkElement = document.createElement('link'); - linkElement.rel = 'manifest'; - linkElement.href = 'manifest.json'; - document.getElementsByTagName('head')[0].appendChild(linkElement); - - if ('serviceWorker' in navigator && 'MessageChannel' in window) { - var result; - var channel = new MessageChannel(); - channel.port1.onmessage = function(event) { - that.emit('notification', event.data); - }; - - navigator.serviceWorker.register('ServiceWorker.js').then(function() { - return navigator.serviceWorker.ready; - }) - .then(function(reg) { - serviceWorker = reg; - reg.pushManager.subscribe({userVisibleOnly: true}).then(function(sub) { - subscription = sub; - result = { 'registrationId': sub.endpoint.substring(sub.endpoint.lastIndexOf('/') + 1) }; - that.emit('registration', result); - - // send encryption keys to push server - var xmlHttp = new XMLHttpRequest(); - var xmlURL = (options.browser.pushServiceURL || 'http://push.api.phonegap.com/v1/push') + '/keys'; - xmlHttp.open('POST', xmlURL, true); - - var formData = new FormData(); - formData.append('subscription', JSON.stringify(sub)); - - xmlHttp.send(formData); - - navigator.serviceWorker.controller.postMessage(result, [channel.port2]); - }).catch(function(error) { - if (navigator.serviceWorker.controller === null) { - // When you first register a SW, need a page reload to handle network operations - window.location.reload(); - return; - } - - throw new Error('Error subscribing for Push notifications.'); - }); - }).catch(function(error) { - console.log(error); - throw new Error('Error registering Service Worker'); - }); - } else { - throw new Error('Service Workers are not supported on your browser.'); - } -}; - -/** - * Unregister from push notifications - */ - -PushNotification.prototype.unregister = function(successCallback, errorCallback, options) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.unregister failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.unregister failure: success callback parameter must be a function'); - return; - } - - var that = this; - if (!options) { - that._handlers = { - 'registration': [], - 'notification': [], - 'error': [] - }; - } - - if (serviceWorker) { - serviceWorker.unregister().then(function(isSuccess) { - if (isSuccess) { - var deviceID = subscription.endpoint.substring(subscription.endpoint.lastIndexOf('/') + 1); - var xmlHttp = new XMLHttpRequest(); - var xmlURL = (that.options.browser.pushServiceURL || 'http://push.api.phonegap.com/v1/push') - + '/keys/' + deviceID; - xmlHttp.open('DELETE', xmlURL, true); - xmlHttp.send(); - - successCallback(); - } else { - errorCallback(); - } - }); - } -}; - -/** - * subscribe to a topic - * @param {String} topic topic to subscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ -PushNotification.prototype.subscribe = function(topic, successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.subscribe failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.subscribe failure: success callback parameter must be a function'); - return; - } - - successCallback(); -}; - -/** - * unsubscribe to a topic - * @param {String} topic topic to unsubscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ -PushNotification.prototype.unsubscribe = function(topic, successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.unsubscribe failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.unsubscribe failure: success callback parameter must be a function'); - return; - } - - successCallback(); -}; - -/** - * Call this to set the application icon badge - */ - -PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: success callback parameter must be a function'); - return; - } - - successCallback(); -}; - -/** - * Get the application icon badge - */ - -PushNotification.prototype.getApplicationIconBadgeNumber = function(successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: success callback parameter must be a function'); - return; - } - - successCallback(); -}; - -/** - * Get the application icon badge - */ - -PushNotification.prototype.clearAllNotifications = function(successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: success callback parameter must be a function'); - return; - } - - successCallback(); -}; - -/** - * Listen for an event. - * - * The following events are supported: - * - * - registration - * - notification - * - error - * - * @param {String} eventName to subscribe to. - * @param {Function} callback triggered on the event. - */ - -PushNotification.prototype.on = function(eventName, callback) { - if (this._handlers.hasOwnProperty(eventName)) { - this._handlers[eventName].push(callback); - } -}; - -/** - * Remove event listener. - * - * @param {String} eventName to match subscription. - * @param {Function} handle function associated with event. - */ - -PushNotification.prototype.off = function (eventName, handle) { - if (this._handlers.hasOwnProperty(eventName)) { - var handleIndex = this._handlers[eventName].indexOf(handle); - if (handleIndex >= 0) { - this._handlers[eventName].splice(handleIndex, 1); - } - } -}; - -/** - * Emit an event. - * - * This is intended for internal use only. - * - * @param {String} eventName is the event to trigger. - * @param {*} all arguments are passed to the event listeners. - * - * @return {Boolean} is true when the event is triggered otherwise false. - */ - -PushNotification.prototype.emit = function() { - var args = Array.prototype.slice.call(arguments); - var eventName = args.shift(); - - if (!this._handlers.hasOwnProperty(eventName)) { - return false; - } - - for (var i = 0, length = this._handlers[eventName].length; i < length; i++) { - var callback = this._handlers[eventName][i]; - if (typeof callback === 'function') { - callback.apply(undefined,args); - } else { - console.log('event handler: ' + eventName + ' must be a function'); - } - } - - return true; -}; - -PushNotification.prototype.finish = function(successCallback, errorCallback, id) { - if (!successCallback) { successCallback = function() {}; } - if (!errorCallback) { errorCallback = function() {}; } - if (!id) { id = 'handler'; } - - if (typeof successCallback !== 'function') { - console.log('finish failure: success callback parameter must be a function'); - return; - } - - if (typeof errorCallback !== 'function') { - console.log('finish failure: failure parameter not a function'); - return; - } - - successCallback(); -}; - -/*! - * Push Notification Plugin. - */ - -module.exports = { - /** - * Register for Push Notifications. - * - * This method will instantiate a new copy of the PushNotification object - * and start the registration process. - * - * @param {Object} options - * @return {PushNotification} instance - */ - - init: function(options) { - return new PushNotification(options); - }, - - hasPermission: function(successCallback, errorCallback) { - successCallback(true); - }, - - unregister: function(successCallback, errorCallback, options) { - PushNotification.unregister(successCallback, errorCallback, options); - }, - - /** - * PushNotification Object. - * - * Expose the PushNotification object for direct use - * and testing. Typically, you should use the - * .init helper method. - */ - - PushNotification: PushNotification -}; diff --git a/StoneIsland/plugins/phonegap-plugin-push/www/push.js b/StoneIsland/plugins/phonegap-plugin-push/www/push.js deleted file mode 100644 index 58c686d3..00000000 --- a/StoneIsland/plugins/phonegap-plugin-push/www/push.js +++ /dev/null @@ -1,326 +0,0 @@ -/* global cordova:false */ -/* globals window */ - -/*! - * Module dependencies. - */ - -var exec = cordova.require('cordova/exec'); - -/** - * PushNotification constructor. - * - * @param {Object} options to initiate Push Notifications. - * @return {PushNotification} instance that can be monitored and cancelled. - */ - -var PushNotification = function(options) { - this._handlers = { - 'registration': [], - 'notification': [], - 'error': [] - }; - - // require options parameter - if (typeof options === 'undefined') { - throw new Error('The options argument is required.'); - } - - // store the options to this object instance - this.options = options; - - // triggered on registration and notification - var that = this; - var success = function(result) { - if (result && typeof result.registrationId !== 'undefined') { - that.emit('registration', result); - } else if (result && result.additionalData && typeof result.additionalData.actionCallback !== 'undefined') { - var executeFuctionOrEmitEventByName = function(callbackName, context, arg) { - var namespaces = callbackName.split('.'); - var func = namespaces.pop(); - for (var i = 0; i < namespaces.length; i++) { - context = context[namespaces[i]]; - } - - if (typeof context[func] === 'function') { - context[func].call(context, arg); - } else { - that.emit(callbackName, arg); - } - }; - - executeFuctionOrEmitEventByName(result.additionalData.actionCallback, window, result); - } else if (result) { - that.emit('notification', result); - } - }; - - // triggered on error - var fail = function(msg) { - var e = (typeof msg === 'string') ? new Error(msg) : msg; - that.emit('error', e); - }; - - // wait at least one process tick to allow event subscriptions - setTimeout(function() { - exec(success, fail, 'PushNotification', 'init', [options]); - }, 10); -}; - -/** - * Unregister from push notifications - */ - -PushNotification.prototype.unregister = function(successCallback, errorCallback, options) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.unregister failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.unregister failure: success callback parameter must be a function'); - return; - } - - var that = this; - var cleanHandlersAndPassThrough = function() { - if (!options) { - that._handlers = { - 'registration': [], - 'notification': [], - 'error': [] - }; - } - successCallback(); - }; - - exec(cleanHandlersAndPassThrough, errorCallback, 'PushNotification', 'unregister', [options]); -}; - -/** - * subscribe to a topic - * @param {String} topic topic to subscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ -PushNotification.prototype.subscribe = function(topic, successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.subscribe failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.subscribe failure: success callback parameter must be a function'); - return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'subscribe', [topic]); -}; - -/** - * unsubscribe to a topic - * @param {String} topic topic to unsubscribe - * @param {Function} successCallback success callback - * @param {Function} errorCallback error callback - * @return {void} - */ -PushNotification.prototype.unsubscribe = function(topic, successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.unsubscribe failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.unsubscribe failure: success callback parameter must be a function'); - return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'unsubscribe', [topic]); -}; - -/** - * Call this to set the application icon badge - */ - -PushNotification.prototype.setApplicationIconBadgeNumber = function(successCallback, errorCallback, badge) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.setApplicationIconBadgeNumber failure: success callback parameter must be a function'); - return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'setApplicationIconBadgeNumber', [{badge: badge}]); -}; - -/** - * Get the application icon badge - */ - -PushNotification.prototype.getApplicationIconBadgeNumber = function(successCallback, errorCallback) { - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.getApplicationIconBadgeNumber failure: success callback parameter must be a function'); - return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'getApplicationIconBadgeNumber', []); -}; - -/** - * Get the application icon badge - */ - -PushNotification.prototype.clearAllNotifications = function(successCallback, errorCallback) { - if (!successCallback) { successCallback = function() {}; } - if (!errorCallback) { errorCallback = function() {}; } - - if (typeof errorCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: failure parameter not a function'); - return; - } - - if (typeof successCallback !== 'function') { - console.log('PushNotification.clearAllNotifications failure: success callback parameter must be a function'); - return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'clearAllNotifications', []); -}; - -/** - * Listen for an event. - * - * Any event is supported, but the following are built-in: - * - * - registration - * - notification - * - error - * - * @param {String} eventName to subscribe to. - * @param {Function} callback triggered on the event. - */ - -PushNotification.prototype.on = function(eventName, callback) { - if (!this._handlers.hasOwnProperty(eventName)) { - this._handlers[eventName] = []; - } - this._handlers[eventName].push(callback); -}; - -/** - * Remove event listener. - * - * @param {String} eventName to match subscription. - * @param {Function} handle function associated with event. - */ - -PushNotification.prototype.off = function (eventName, handle) { - if (this._handlers.hasOwnProperty(eventName)) { - var handleIndex = this._handlers[eventName].indexOf(handle); - if (handleIndex >= 0) { - this._handlers[eventName].splice(handleIndex, 1); - } - } -}; - -/** - * Emit an event. - * - * This is intended for internal use only. - * - * @param {String} eventName is the event to trigger. - * @param {*} all arguments are passed to the event listeners. - * - * @return {Boolean} is true when the event is triggered otherwise false. - */ - -PushNotification.prototype.emit = function() { - var args = Array.prototype.slice.call(arguments); - var eventName = args.shift(); - - if (!this._handlers.hasOwnProperty(eventName)) { - return false; - } - - for (var i = 0, length = this._handlers[eventName].length; i < length; i++) { - var callback = this._handlers[eventName][i]; - if (typeof callback === 'function') { - callback.apply(undefined,args); - } else { - console.log('event handler: ' + eventName + ' must be a function'); - } - } - - return true; -}; - -PushNotification.prototype.finish = function(successCallback, errorCallback, id) { - if (!successCallback) { successCallback = function() {}; } - if (!errorCallback) { errorCallback = function() {}; } - if (!id) { id = 'handler'; } - - if (typeof successCallback !== 'function') { - console.log('finish failure: success callback parameter must be a function'); - return; - } - - if (typeof errorCallback !== 'function') { - console.log('finish failure: failure parameter not a function'); - return; - } - - exec(successCallback, errorCallback, 'PushNotification', 'finish', [id]); -}; - -/*! - * Push Notification Plugin. - */ - -module.exports = { - /** - * Register for Push Notifications. - * - * This method will instantiate a new copy of the PushNotification object - * and start the registration process. - * - * @param {Object} options - * @return {PushNotification} instance - */ - - init: function(options) { - return new PushNotification(options); - }, - - hasPermission: function(successCallback, errorCallback) { - exec(successCallback, errorCallback, 'PushNotification', 'hasPermission', []); - }, - - /** - * PushNotification Object. - * - * Expose the PushNotification object for direct use - * and testing. Typically, you should use the - * .init helper method. - */ - - PushNotification: PushNotification -}; |
