Commit 0e18049a authored by Libin Lu's avatar Libin Lu Committed by GitHub

Merge pull request #152 from tioback/master

sample project
parents 77cfdf39 03065662
{
"presets": ["react-native"]
}
\ No newline at end of file
[android]
target = Google Inc.:Google APIs:23
[maven_repositories]
central = https://repo1.maven.org/maven2
[ignore]
# We fork some components by platform.
.*/*[.]android.js
# Ignore templates with `@flow` in header
.*/local-cli/generator.*
# Ignore malformed json
.*/node_modules/y18n/test/.*\.json
# Ignore the website subdir
<PROJECT_ROOT>/website/.*
# Ignore BUCK generated dirs
<PROJECT_ROOT>/\.buckd/
# Ignore unexpected extra @providesModule
.*/node_modules/commoner/test/source/widget/share.js
# Ignore duplicate module providers
# For RN Apps installed via npm, "Libraries" folder is inside node_modules/react-native but in the source repo it is in the root
.*/Libraries/react-native/React.js
.*/Libraries/react-native/ReactNative.js
.*/node_modules/jest-runtime/build/__tests__/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/flow
flow/
[options]
module.system=haste
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
experimental.strict_type_args=true
munge_underscores=true
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-2]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-2]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
unsafe.enable_getters_and_setters=true
[version]
^0.32.0
# OSX
#
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IJ
#
*.iml
.idea
.gradle
local.properties
# node.js
#
node_modules/
npm-debug.log
# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore
# FCM
ios/SimpleFcmClient/GoogleService-Info.plist
android/app/google-services.json
app/FirebaseConstants.js
{}
\ No newline at end of file
import 'react-native';
import React from 'react';
import Index from '../index.android.js';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
});
import 'react-native';
import React from 'react';
import Index from '../index.ios.js';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
});
import re
# To learn about Buck see [Docs](https://buckbuild.com/).
# To run your application with Buck:
# - install Buck
# - `npm start` - to start the packager
# - `cd android`
# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
# - `buck install -r android/app` - compile, install and run application
#
lib_deps = []
for jarfile in glob(['libs/*.jar']):
name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
lib_deps.append(':' + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)
for aarfile in glob(['libs/*.aar']):
name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
lib_deps.append(':' + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)
android_library(
name = 'all-libs',
exported_deps = lib_deps
)
android_library(
name = 'app-code',
srcs = glob([
'src/main/java/**/*.java',
]),
deps = [
':all-libs',
':build_config',
':res',
],
)
android_build_config(
name = 'build_config',
package = 'fcm.simplefcmclient',
)
android_resource(
name = 'res',
res = 'src/main/res',
package = 'fcm.simplefcmclient',
)
android_binary(
name = 'app',
package_type = 'debug',
manifest = 'src/main/AndroidManifest.xml',
keystore = '//android/keystores:debug',
deps = [
':app-code',
],
)
apply plugin: "com.android.application"
apply plugin: "com.google.gms.google-services"
import com.android.build.OutputFile
/**
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* entryFile: "index.android.js",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"]
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "fcm.simplefcmclient"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86"
}
}
buildTypes {
release {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
compile project(':react-native-fcm')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Disabling obfuscation is useful if you collect stack traces from production crashes
# (unless you are using a system that supports de-obfuscate the stack traces).
-dontobfuscate
# React Native
# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.proguard.annotations.DoNotStrip class *
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
@com.facebook.proguard.annotations.DoNotStrip *;
@com.facebook.common.internal.DoNotStrip *;
}
-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
void set*(***);
*** get*();
}
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
-keepclassmembers,includedescriptorclasses class * { native <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; }
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }
-dontwarn com.facebook.react.**
# okhttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
# okio
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fcm.simplefcmclient"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<receiver android:name="com.evollu.react.fcm.FIRLocalMessagingPublisher"/>
<receiver android:enabled="true" android:exported="true" android:name="com.evollu.react.fcm.FIRSystemBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="com.evollu.react.fcm.MessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="fcm.ACTION.HELLO" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
package fcm.simplefcmclient;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
/**
* Returns the name of the main component registered from JavaScript.
* This is used to schedule rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "SimpleFcmClient";
}
}
package fcm.simplefcmclient;
import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.evollu.react.fcm.FIRMessagingPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import java.util.Arrays;
import java.util.List;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new FIRMessagingPackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
<resources>
<string name="app_name">SimpleFcmClient</string>
</resources>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
</style>
</resources>
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useDeprecatedNdk=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
keystore(
name = 'debug',
store = 'debug.keystore',
properties = 'debug.keystore.properties',
visibility = [
'PUBLIC',
],
)
key.store=debug.keystore
key.alias=androiddebugkey
key.store.password=android
key.alias.password=android
rootProject.name = 'SimpleFcmClient'
include ':app'
include ':react-native-fcm'
project(':react-native-fcm').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fcm/android')
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import PushController from "./PushController";
import firebaseClient from "./FirebaseClient";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
token: ""
}
}
render() {
let { token } = this.state;
return (
<View style={styles.container}>
<PushController
onChangeToken={token => this.setState({token: token || ""})}
/>
<Text style={styles.welcome}>
Welcome to Simple Fcm Client!
</Text>
<Text style={styles.instructions}>
Token: {this.state.token}
</Text>
<TouchableOpacity onPress={() => firebaseClient.sendNotification(token)} style={styles.button}>
<Text style={styles.buttonText}>Send Notification</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => firebaseClient.sendData(token)} style={styles.button}>
<Text style={styles.buttonText}>Send Data</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => firebaseClient.sendNotificationWithData(token)} style={styles.button}>
<Text style={styles.buttonText}>Send Notification With Data</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
button: {
backgroundColor: "teal",
paddingHorizontal: 20,
paddingVertical: 10,
marginVertical: 15,
borderRadius: 10
},
buttonText: {
color: "white",
backgroundColor: "transparent"
},
});
import FirebaseConstants from "./FirebaseConstants";
const API_URL = "https://fcm.googleapis.com/fcm/send";
class FirebaseClient {
constructor() {
this.sendData = this.sendData.bind(this);
this.sendNotification = this.sendNotification.bind(this);
this.sendNotificationWithData = this.sendNotificationWithData.bind(this);
}
sendNotification(token) {
let body = {
"to": token,
"notification":{
"title": "Simple FCM Client",
"body": "This is a notification with only NOTIFICATION.",
"sound": "default",
"click_action": "fcm.ACTION.HELLO"
},
"priority": 10
}
this._send(JSON.stringify(body), "notification");
}
sendData(token) {
let body = {
"to": token,
"data":{
"title": "Simple FCM Client",
"body": "This is a notification with only DATA.",
"sound": "default",
"click_action": "fcm.ACTION.HELLO",
"remote": true
},
"priority": "normal"
}
this._send(JSON.stringify(body), "data");
}
sendNotificationWithData(token) {
let body = {
"to": token,
"notification":{
"title": "Simple FCM Client",
"body": "This is a notification with NOTIFICATION and DATA (NOTIF).",
"sound": "default",
"click_action": "fcm.ACTION.HELLO"
},
"data":{
"title": "Simple FCM Client",
"body": "This is a notification with NOTIFICATION and DATA (DATA)",
"click_action": "fcm.ACTION.HELLO",
"remote": true
},
"priority": "high"
}
this._send(JSON.stringify(body), "notification-data");
}
_send(body, type) {
let headers = new Headers({
"Content-Type": "application/json",
"Content-Length": parseInt(body.length),
"Authorization": "key=" + FirebaseConstants.KEY
});
fetch(API_URL, { method: "POST", headers, body })
.then(response => console.log("Send " + type + " response", response))
.catch(error => console.log("Error sending " + type, error));
}
}
let firebaseClient = new FirebaseClient();
export default firebaseClient;
import React, { Component } from "react";
import FCM from "react-native-fcm";
import firebaseClient from "./FirebaseClient";
export default class PushController extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
FCM.requestPermissions();
FCM.getFCMToken().then(token => {
console.log("TOKEN (getFCMToken)", token);
this.props.onChangeToken(token);
});
FCM.getInitialNotification().then(notif => {
console.log("INITIAL NOTIFICATION", notif)
});
this.notificationUnsubscribe = FCM.on("notification", notif => {
console.log("Notification", notif);
if (notif && notif.local) {
return;
}
this.sendRemote(notif);
});
this.refreshUnsubscribe = FCM.on("refreshToken", token => {
console.log("TOKEN (refreshUnsubscribe)", token);
this.props.onChangeToken(token);
});
}
sendRemote(notif) {
FCM.presentLocalNotification({
title: notif.title,
body: notif.body,
priority: "high",
click_action: notif.click_action,
show_in_foreground: true,
local: true
});
}
componentWillUnmount() {
this.refreshUnsubscribe();
this.notificationUnsubscribe();
}
render() {
return null;
}
}
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import App from "./app/App";
export default class SimpleFcmClient extends Component {
render() {
return (<App />);
}
}
AppRegistry.registerComponent('SimpleFcmClient', () => SimpleFcmClient);
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import App from "./app/App";
export default class SimpleFcmClient extends Component {
render() {
return (<App />);
}
}
AppRegistry.registerComponent('SimpleFcmClient', () => SimpleFcmClient);
#import <FirebaseAnalytics/FirebaseAnalytics.h>
#import <FirebaseCore/FirebaseCore.h>
#if !defined(__has_include)
#error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \
import the headers individually."
#else
#if __has_include(<FirebaseAppIndexing/FirebaseAppIndexing.h>)
#import <FirebaseAppIndexing/FirebaseAppIndexing.h>
#endif
#if __has_include(<FirebaseAuth/FirebaseAuth.h>)
#import <FirebaseAuth/FirebaseAuth.h>
#endif
#if __has_include(<FirebaseCrash/FirebaseCrash.h>)
#import <FirebaseCrash/FirebaseCrash.h>
#endif
#if __has_include(<FirebaseDatabase/FirebaseDatabase.h>)
#import <FirebaseDatabase/FirebaseDatabase.h>
#endif
#if __has_include(<FirebaseDynamicLinks/FirebaseDynamicLinks.h>)
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
#endif
#if __has_include(<FirebaseInstanceID/FirebaseInstanceID.h>)
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#endif
#if __has_include(<FirebaseInvites/FirebaseInvites.h>)
#import <FirebaseInvites/FirebaseInvites.h>
#endif
#if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
#import <FirebaseMessaging/FirebaseMessaging.h>
#endif
#if __has_include(<FirebaseRemoteConfig/FirebaseRemoteConfig.h>)
#import <FirebaseRemoteConfig/FirebaseRemoteConfig.h>
#endif
#if __has_include(<FirebaseStorage/FirebaseStorage.h>)
#import <FirebaseStorage/FirebaseStorage.h>
#endif
#if __has_include(<GoogleMobileAds/GoogleMobileAds.h>)
#import <GoogleMobileAds/GoogleMobileAds.h>
#endif
#endif // defined(__has_include)
#import <Foundation/Foundation.h>
#import "FIRAnalytics.h"
/**
* Provides App Delegate handlers to be used in your App Delegate.
*
* To save time integrating Firebase Analytics in an application, Firebase Analytics does not
* require delegation implementation from the AppDelegate. Instead this is automatically done by
* Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App
* Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting
* it to NO, and adding the methods in this category to corresponding delegation handlers.
*
* To handle Universal Links, you must return YES in
* [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
*/
@interface FIRAnalytics (AppDelegate)
/**
* Handles events related to a URL session that are waiting to be processed.
*
* For optimal use of Firebase Analytics, call this method from the
* [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler]
* method of the app delegate in your app.
*
* @param identifier The identifier of the URL session requiring attention.
* @param completionHandler The completion handler to call when you finish processing the events.
* Calling this completion handler lets the system know that your app's user interface is
* updated and a new snapshot can be taken.
*/
+ (void)handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)(void))completionHandler;
/**
* Handles the event when the app is launched by a URL.
*
* Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and
* above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on iOS 8.x
* and below) in your app.
*
* @param url The URL resource to open. This resource can be a network resource or a file.
*/
+ (void)handleOpenURL:(NSURL *)url;
/**
* Handles the event when the app receives data associated with user activity that includes a
* Universal Link (on iOS 9.0 and above).
*
* Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app
* delegate (on iOS 9.0 and above).
*
* @param userActivity The activity object containing the data associated with the task the user
* was performing.
*/
+ (void)handleUserActivity:(id)userActivity;
@end
#import <Foundation/Foundation.h>
#import "FIREventNames.h"
#import "FIRParameterNames.h"
#import "FIRUserPropertyNames.h"
/// The top level Firebase Analytics singleton that provides methods for logging events and setting
/// user properties. See <a href="http://goo.gl/gz8SLz">the developer guides</a> for general
/// information on using Firebase Analytics in your apps.
@interface FIRAnalytics : NSObject
/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have
/// the same parameters. Up to 500 event names are supported. Using predefined events and/or
/// parameters is recommended for optimal reporting.
///
/// The following event names are reserved and cannot be used:
/// <ul>
/// <li>app_clear_data</li>
/// <li>app_remove</li>
/// <li>app_update</li>
/// <li>error</li>
/// <li>first_open</li>
/// <li>in_app_purchase</li>
/// <li>notification_dismiss</li>
/// <li>notification_foreground</li>
/// <li>notification_open</li>
/// <li>notification_receive</li>
/// <li>os_update</li>
/// <li>session_start</li>
/// <li>user_engagement</li>
/// </ul>
///
/// @param name The name of the event. Should contain 1 to 32 alphanumeric characters or
/// underscores. The name must start with an alphabetic character. Some event names are
/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_" prefix
/// is reserved and should not be used. Note that event names are case-sensitive and that
/// logging two events whose names differ only in case will result in two distinct events.
/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has
/// no parameters. Parameter names can be up to 24 characters long and must start with an
/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString
/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are
/// supported. NSString parameter values can be up to 36 characters long. The "firebase_" prefix
/// is reserved and should not be used for parameter names.
+ (void)logEventWithName:(nonnull NSString *)name
parameters:(nullable NSDictionary<NSString *, NSObject *> *)parameters;
/// Sets a user property to a given value. Up to 25 user property names are supported. Once set,
/// user property values persist throughout the app lifecycle and across sessions.
///
/// The following user property names are reserved and cannot be used:
/// <ul>
/// <li>first_open_time</li>
/// <li>last_deep_link_referrer</li>
/// <li>user_id</li>
/// </ul>
///
/// @param value The value of the user property. Values can be up to 36 characters long. Setting the
/// value to nil removes the user property.
/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters
/// or underscores and must start with an alphabetic character. The "firebase_" prefix is
/// reserved and should not be used for user property names.
+ (void)setUserPropertyString:(nullable NSString *)value forName:(nonnull NSString *)name;
/// Sets the user ID property. This feature must be used in accordance with
/// <a href="https://www.google.com/policies/privacy">Google's Privacy Policy</a>
///
/// @param userID The user ID to ascribe to the user of this app on this device, which must be
/// non-empty and no more than 36 characters long. Setting userID to nil removes the user ID.
+ (void)setUserID:(nullable NSString *)userID;
@end
/// @file FIRParameterNames.h
///
/// Predefined event parameter names.
///
/// Params supply information that contextualize Events. You can associate up to 25 unique Params
/// with each Event type. Some Params are suggested below for certain common Events, but you are
/// not limited to these. You may supply extra Params for suggested Events or custom Params for
/// Custom events. Param names can be up to 24 characters long, may only contain alphanumeric
/// characters and underscores ("_"), and must start with an alphabetic character. Param values can
/// be up to 36 characters long. The "firebase_" prefix is reserved and should not be used.
/// Game achievement ID (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterAchievementID : @"10_matches_won",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterAchievementID = @"achievement_id";
/// Character used in game (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCharacter : @"beat_boss",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCharacter = @"character";
/// Type of content selected (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterContentType : @"news article",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterContentType = @"content_type";
/// Coupon code for a purchasable item (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCoupon : @"zz123",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCoupon = @"coupon";
/// Purchase currency in 3-letter <a href="http://en.wikipedia.org/wiki/ISO_4217#Active_codes">
/// ISO_4217</a> format (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCurrency : @"USD",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCurrency = @"currency";
/// Flight or Travel destination (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterDestination : @"Mountain View, CA",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterDestination = @"destination";
/// The arrival date, check-out date or rental end date for the item. This should be in
/// YYYY-MM-DD format (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterEndDate : @"2015-09-14",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterEndDate = @"end_date";
/// Flight number for travel events (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterFlightNumber : @"ZZ800",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterFlightNumber = @"flight_number";
/// Group/clan/guild ID (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterGroupID : @"g1",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterGroupID = @"group_id";
/// Item category (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemCategory : @"t-shirts",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemCategory = @"item_category";
/// Item ID (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemID : @"p7654",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemID = @"item_id";
/// The Google <a href="https://developers.google.com/places/place-id">Place ID</a> (NSString) that
/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemLocationID = @"item_location_id";
/// Item name (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemName : @"abc",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemName = @"item_name";
/// Level in game (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterLevel : @(42),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterLevel = @"level";
/// Location (NSString). The Google <a href="https://developers.google.com/places/place-id">Place ID
/// </a> that corresponds to the associated event. Alternatively, you can supply your own custom
/// Location ID.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterLocation = @"location";
/// Number of nights staying at hotel (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterNumberOfNights : @(3),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterNumberOfNights = @"number_of_nights";
/// Number of passengers traveling (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterNumberOfPassengers : @(11),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterNumberOfPassengers = @"number_of_passengers";
/// Number of rooms for travel events (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterNumberOfRooms : @(2),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterNumberOfRooms = @"number_of_rooms";
/// Flight or Travel origin (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterOrigin : @"Mountain View, CA",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterOrigin = @"origin";
/// Purchase price (double as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterPrice : @(1.0),
/// kFIRParameterCurrency : @"USD", // e.g. $1.00 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterPrice = @"price";
/// Purchase quantity (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterQuantity : @(1),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterQuantity = @"quantity";
/// Score in game (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterScore : @(4200),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterScore = @"score";
/// The search string/keywords used (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterSearchTerm : @"periodic table",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterSearchTerm = @"search_term";
/// Shipping cost (double as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterShipping : @(9.50),
/// kFIRParameterCurrency : @"USD", // e.g. $9.50 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterShipping = @"shipping";
/// Sign up method (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterSignUpMethod : @"google",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterSignUpMethod = @"sign_up_method";
/// The departure date, check-in date or rental start date for the item. This should be in
/// YYYY-MM-DD format (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterStartDate : @"2015-09-14",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterStartDate = @"start_date";
/// Tax amount (double as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTax : @(1.0),
/// kFIRParameterCurrency : @"USD", // e.g. $1.00 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTax = @"tax";
/// A single ID for a ecommerce group transaction (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTransactionID : @"ab7236dd9823",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTransactionID = @"transaction_id";
/// Travel class (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTravelClass : @"business",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTravelClass = @"travel_class";
/// A context-specific numeric value which is accumulated automatically for each event type. This is
/// a general purpose parameter that is useful for accumulating a key metric that pertains to an
/// event. Examples include revenue, distance, time and points. Value should be specified as signed
/// 64-bit integer or double as NSNumber. Notes: Currency-related values should be supplied using
/// double as NSNumber and must be accompanied by a {@link kFIRParameterCurrency} parameter. The
/// valid range of accumulated values is [-9,223,372,036,854.77, 9,223,372,036,854.77].
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterValue : @(3.99),
/// kFIRParameterCurrency : @"USD", // e.g. $3.99 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterValue = @"value";
/// Name of virtual currency type (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterVirtualCurrencyName = @"virtual_currency_name";
/// @file FIRUserPropertyNames.h
///
/// Predefined user property names.
///
/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can
/// later analyze different behaviors of various segments of your userbase. You may supply up to 25
/// unique UserProperties per app, and you can use the name and value of your choosing for each one.
/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and
/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to
/// 36 characters long. The "firebase_" prefix is reserved and should not be used.
/// The method used to sign in. For example, "google", "facebook" or "twitter".
static NSString *const kFIRUserPropertySignUpMethod = @"sign_up_method";
// Generated umbrella header for FirebaseAnalytics.
#import "FIRAnalytics+AppDelegate.h"
#import "FIRAnalytics.h"
#import "FIRAnalyticsConfiguration.h"
#import "FIRApp.h"
#import "FIRConfiguration.h"
#import "FIREventNames.h"
#import "FIROptions.h"
#import "FIRParameterNames.h"
#import "FIRUserPropertyNames.h"
framework module FirebaseAnalytics {
export *
umbrella header "FirebaseAnalytics.h"
header "FIRAnalytics+AppDelegate.h"
header "FIRAnalytics.h"
header "FIRAnalyticsConfiguration.h"
header "FIRApp.h"
header "FIRConfiguration.h"
header "FIREventNames.h"
header "FIROptions.h"
header "FIRParameterNames.h"
header "FIRUserPropertyNames.h"
link framework "AddressBook"
link framework "StoreKit"
link "c++"
link "sqlite3"
link "z"
}
#import <Foundation/Foundation.h>
/**
* This class provides configuration fields for Firebase Analytics.
*/
@interface FIRAnalyticsConfiguration : NSObject
/**
* Returns the shared instance of FIRAnalyticsConfiguration.
*/
+ (FIRAnalyticsConfiguration *)sharedInstance;
/**
* Sets the minimum engagement time in seconds required to start a new session. The default value
* is 10 seconds.
*/
- (void)setMinimumSessionInterval:(NSTimeInterval)minimumSessionInterval;
/**
* Sets the interval of inactivity in seconds that terminates the current session. The default
* value is 1800 seconds (30 minutes).
*/
- (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval;
/**
* Sets whether analytics collection is enabled for this app on this device. This setting is
* persisted across app sessions. By default it is enabled.
*/
- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled;
/**
* Deprecated. Sets whether measurement and reporting are enabled for this app on this device. By
* default they are enabled.
*/
- (void)setIsEnabled:(BOOL)isEnabled
DEPRECATED_MSG_ATTRIBUTE("Use setAnalyticsCollectionEnabled: instead.");
@end
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class FIROptions;
NS_ASSUME_NONNULL_BEGIN
typedef void (^FIRAppVoidBoolCallback)(BOOL success);
/**
* The entry point of Firebase SDKs.
*
* Initialize and configure FIRApp using [FIRApp configure];
* Or other customized ways as shown below.
*
* The logging system has two modes: default mode and debug mode. In default mode, only logs with
* log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent
* to device. The log levels that Firebase uses are consistent with the ASL log levels.
*
* Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this
* argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled,
* further executions of the application will also be in debug mode. In order to return to default
* mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled.
*/
@interface FIRApp : NSObject
/**
* Configures a default Firebase app. Raises an exception if any configuration step fails. The
* default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched
* and before using Firebase services. This method is thread safe.
*/
+ (void)configure;
/**
* Configures the default Firebase app with the provided options. The default app is named
* "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread
* safe.
*
* @param options The Firebase application options used to configure the service.
*/
+ (void)configureWithOptions:(FIROptions *)options;
/**
* Configures a Firebase app with the given name and options. Raises an exception if any
* configuration step fails. This method is thread safe.
*
* @param name The application's name given by the developer. The name should should only contain
Letters, Numbers and Underscore.
* @param options The Firebase application options used to configure the services.
*/
+ (void)configureWithName:(NSString *)name options:(FIROptions *)options;
/**
* Returns the default app, or nil if the default app does not exist.
*/
+ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(defaultApp());
/**
* Returns a previously created FIRApp instance with the given name, or nil if no such app exists.
* This method is thread safe.
*/
+ (nullable FIRApp *)appNamed:(NSString *)name;
/**
* Returns the set of all extant FIRApp instances, or nil if there is no FIRApp instance. This
* method is thread safe.
*/
+ (nullable NSDictionary *)allApps;
/**
* Cleans up the current FIRApp, freeing associated data and returning its name to the pool for
* future use. This method is thread safe in class level.
*/
- (void)deleteApp:(FIRAppVoidBoolCallback)completion;
/**
* FIRFirebaseApp instances should not be initialized directly. Call |FIRApp configure|, or
* |FIRApp configureWithOptions:|, or |FIRApp configureWithNames:options| directly.
*/
- (nullable instancetype)init NS_UNAVAILABLE;
/**
* Gets the name of this app.
*/
@property(nonatomic, copy, readonly) NSString *name;
/**
* Gets the options for this app.
*/
@property(nonatomic, readonly) FIROptions *options;
@end
NS_ASSUME_NONNULL_END
#import <Foundation/Foundation.h>
#import "FIRAnalyticsConfiguration.h"
/**
* The log levels used by FIRConfiguration.
*/
typedef NS_ENUM(NSInteger, FIRLogLevel) {
kFIRLogLevelError __deprecated = 0,
kFIRLogLevelWarning __deprecated,
kFIRLogLevelInfo __deprecated,
kFIRLogLevelDebug __deprecated,
kFIRLogLevelAssert __deprecated,
kFIRLogLevelMax __deprecated = kFIRLogLevelAssert
} DEPRECATED_MSG_ATTRIBUTE(
"Use -FIRDebugEnabled and -FIRDebugDisabled. See FIRApp.h for more details.");
/**
* This interface provides global level properties that the developer can tweak, and the singleton
* of the Firebase Analytics configuration class.
*/
@interface FIRConfiguration : NSObject
+ (FIRConfiguration *)sharedInstance;
// The configuration class for Firebase Analytics.
@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration;
// Global log level. Defaults to kFIRLogLevelError.
@property(nonatomic, readwrite, assign) FIRLogLevel logLevel DEPRECATED_MSG_ATTRIBUTE(
"Use -FIRDebugEnabled and -FIRDebugDisabled. See FIRApp.h for more details.");
@end
#import <Foundation/Foundation.h>
/**
* This class provides constant fields of Google APIs.
*/
@interface FIROptions : NSObject<NSCopying>
/**
* Returns the default options.
*/
+ (FIROptions *)defaultOptions;
/**
* An iOS API key used for authenticating requests from your app, e.g.
* @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers.
*/
@property(nonatomic, readonly, copy) NSString *APIKey;
/**
* The OAuth2 client ID for iOS application used to authenticate Google users, for example
* @"12345.apps.googleusercontent.com", used for signing in with Google.
*/
@property(nonatomic, readonly, copy) NSString *clientID;
/**
* The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics.
*/
@property(nonatomic, readonly, copy) NSString *trackingID;
/**
* The Project Number from the Google Developer's console, for example @"012345678901", used to
* configure Google Cloud Messaging.
*/
@property(nonatomic, readonly, copy) NSString *GCMSenderID;
/**
* The Android client ID used in Google AppInvite when an iOS app has its Android version, for
* example @"12345.apps.googleusercontent.com".
*/
@property(nonatomic, readonly, copy) NSString *androidClientID;
/**
* The Google App ID that is used to uniquely identify an instance of an app.
*/
@property(nonatomic, readonly, copy) NSString *googleAppID;
/**
* The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com".
*/
@property(nonatomic, readonly, copy) NSString *databaseURL;
/**
* The URL scheme used to set up Durable Deep Link service.
*/
@property(nonatomic, readwrite, copy) NSString *deepLinkURLScheme;
/**
* The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com".
*/
@property(nonatomic, readonly, copy) NSString *storageBucket;
/**
* Initializes a customized instance of FIROptions with keys. googleAppID, bundleID and GCMSenderID
* are required. Other keys may required for configuring specific services.
*/
- (instancetype)initWithGoogleAppID:(NSString *)googleAppID
bundleID:(NSString *)bundleID
GCMSenderID:(NSString *)GCMSenderID
APIKey:(NSString *)APIKey
clientID:(NSString *)clientID
trackingID:(NSString *)trackingID
androidClientID:(NSString *)androidClientID
databaseURL:(NSString *)databaseURL
storageBucket:(NSString *)storageBucket
deepLinkURLScheme:(NSString *)deepLinkURLScheme;
/**
* Initializes a customized instance of FIROptions from the file at the given plist file path.
* For example,
* NSString *filePath =
* [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
* FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath];
* Returns nil if the plist file does not exist or is invalid.
*/
- (instancetype)initWithContentsOfFile:(NSString *)plistPath;
@end
// Generated umbrella header for FirebaseCore.
#import "FIRAnalyticsConfiguration.h"
#import "FIRApp.h"
#import "FIRConfiguration.h"
#import "FIROptions.h"
framework module FirebaseCore {
export *
umbrella header "FirebaseCore.h"
header "FIRAnalyticsConfiguration.h"
header "FIRApp.h"
header "FIRConfiguration.h"
header "FIROptions.h"
link framework "SystemConfiguration"
link "c++"
}
#import <Foundation/Foundation.h>
/**
* @memberof FIRInstanceID
*
* The scope to be used when fetching/deleting a token for Firebase Messaging.
*/
FOUNDATION_EXPORT NSString * __nonnull const kFIRInstanceIDScopeFirebaseMessaging;
/**
* Called when the system determines that tokens need to be refreshed.
* This method is also called if Instance ID has been reset in which
* case, tokens and FCM topic subscriptions also need to be refreshed.
*
* Instance ID service will throttle the refresh event across all devices
* to control the rate of token updates on application servers.
*/
FOUNDATION_EXPORT NSString * __nonnull const kFIRInstanceIDTokenRefreshNotification;
/**
* @related FIRInstanceID
*
* The completion handler invoked when the InstanceID token returns. If
* the call fails we return the appropriate `error code` as described below.
*
* @param token The valid token as returned by InstanceID backend.
*
* @param error The error describing why generating a new token
* failed. See the error codes below for a more detailed
* description.
*/
typedef void(^FIRInstanceIDTokenHandler)( NSString * __nullable token, NSError * __nullable error);
/**
* @related FIRInstanceID
*
* The completion handler invoked when the InstanceID `deleteToken` returns. If
* the call fails we return the appropriate `error code` as described below
*
* @param error The error describing why deleting the token failed.
* See the error codes below for a more detailed description.
*/
typedef void(^FIRInstanceIDDeleteTokenHandler)(NSError * __nullable error);
/**
* @related FIRInstanceID
*
* The completion handler invoked when the app identity is created. If the
* identity wasn't created for some reason we return the appropriate error code.
*
* @param identity A valid identity for the app instance, nil if there was an error
* while creating an identity.
* @param error The error if fetching the identity fails else nil.
*/
typedef void(^FIRInstanceIDHandler)(NSString * __nullable identity, NSError * __nullable error);
/**
* @related FIRInstanceID
*
* The completion handler invoked when the app identity and all the tokens associated
* with it are deleted. Returns a valid error object in case of failure else nil.
*
* @param error The error if deleting the identity and all the tokens associated with
* it fails else nil.
*/
typedef void(^FIRInstanceIDDeleteHandler)(NSError * __nullable error);
/**
* @enum FIRInstanceIDError
*/
typedef NS_ENUM(NSUInteger, FIRInstanceIDError) {
// Http related errors.
/// Unknown error.
FIRInstanceIDErrorUnknown = 0,
/// Auth Error -- GCM couldn't validate request from this client.
FIRInstanceIDErrorAuthentication = 1,
/// NoAccess -- InstanceID service cannot be accessed.
FIRInstanceIDErrorNoAccess = 2,
/// Timeout -- Request to InstanceID backend timed out.
FIRInstanceIDErrorTimeout = 3,
/// Network -- No network available to reach the servers.
FIRInstanceIDErrorNetwork = 4,
/// OperationInProgress -- Another similar operation in progress,
/// bailing this one.
FIRInstanceIDErrorOperationInProgress = 5,
/// InvalidRequest -- Some parameters of the request were invalid.
FIRInstanceIDErrorInvalidRequest = 7,
};
/**
* The APNS token type for the app. If the token type is set to `UNKNOWN`
* InstanceID will implicitly try to figure out what the actual token type
* is from the provisioning profile.
*/
typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) {
/// Unknown token type.
FIRInstanceIDAPNSTokenTypeUnknown,
/// Sandbox token type.
FIRInstanceIDAPNSTokenTypeSandbox,
/// Production token type.
FIRInstanceIDAPNSTokenTypeProd,
};
/**
* Instance ID provides a unique identifier for each app instance and a mechanism
* to authenticate and authorize actions (for example, sending a GCM message).
*
* Instance ID is long lived but, may be reset if the device is not used for
* a long time or the Instance ID service detects a problem.
* If Instance ID is reset, the app will be notified with a `com.firebase.iid.token-refresh`
* notification.
*
* If the Instance ID has become invalid, the app can request a new one and
* send it to the app server.
* To prove ownership of Instance ID and to allow servers to access data or
* services associated with the app, call
* `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`.
*/
@interface FIRInstanceID : NSObject
/**
* FIRInstanceID.
*
* @return A shared instance of FIRInstanceID.
*/
+ (nonnull instancetype)instanceID NS_SWIFT_NAME(instanceID());
/**
* Unavailable. Use +instanceID instead.
*/
- (nonnull instancetype)init __attribute__((unavailable("Use +instanceID instead.")));
/**
* Set APNS token for the application. This APNS token will be used to register
* with Firebase Messaging using `token` or
* `tokenWithAuthorizedEntity:scope:options:handler`. If the token type is set to
* `FIRInstanceIDAPNSTokenTypeUnknown` InstanceID will read the provisioning profile
* to find out the token type.
*
* @param token The APNS token for the application.
* @param type The APNS token type for the above token.
*/
- (void)setAPNSToken:(nonnull NSData *)token
type:(FIRInstanceIDAPNSTokenType)type;
#pragma mark - Tokens
/**
* Returns a Firebase Messaging scoped token for the firebase app.
*
* @return Null Returns null if the device has not yet been registerd with
* Firebase Message else returns a valid token.
*/
- (nullable NSString *)token;
/**
* Returns a token that authorizes an Entity (example: cloud service) to perform
* an action on behalf of the application identified by Instance ID.
*
* This is similar to an OAuth2 token except, it applies to the
* application instance instead of a user.
*
* This is an asynchronous call. If the token fetching fails for some reason
* we invoke the completion callback with nil `token` and the appropriate
* error.
*
* Note, you can only have one `token` or `deleteToken` call for a given
* authorizedEntity and scope at any point of time. Making another such call with the
* same authorizedEntity and scope before the last one finishes will result in an
* error with code `OperationInProgress`.
*
* @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler:
*
* @param authorizedEntity Entity authorized by the token.
* @param scope Action authorized for authorizedEntity.
* @param options The extra options to be sent with your token request. The
* value for the `apns_token` should be the NSData object
* passed to UIApplication's
* `didRegisterForRemoteNotificationsWithDeviceToken` method.
* All other keys and values in the options dict need to be
* instances of NSString or else they will be discarded. Bundle
* keys starting with 'GCM.' and 'GOOGLE.' are reserved.
* @param handler The callback handler which is invoked when the token is
* successfully fetched. In case of success a valid `token` and
* `nil` error are returned. In case of any error the `token`
* is nil and a valid `error` is returned. The valid error
* codes have been documented above.
*/
- (void)tokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity
scope:(nonnull NSString *)scope
options:(nullable NSDictionary *)options
handler:(nonnull FIRInstanceIDTokenHandler)handler;
/**
* Revokes access to a scope (action) for an entity previously
* authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`.
*
* This is an asynchronous call. Call this on the main thread since InstanceID lib
* is not thread safe. In case token deletion fails for some reason we invoke the
* `handler` callback passed in with the appropriate error code.
*
* Note, you can only have one `token` or `deleteToken` call for a given
* authorizedEntity and scope at a point of time. Making another such call with the
* same authorizedEntity and scope before the last one finishes will result in an error
* with code `OperationInProgress`.
*
* @param authorizedEntity Entity that must no longer have access.
* @param scope Action that entity is no longer authorized to perform.
* @param handler The handler that is invoked once the unsubscribe call ends.
* In case of error an appropriate error object is returned
* else error is nil.
*/
- (void)deleteTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity
scope:(nonnull NSString *)scope
handler:(nonnull FIRInstanceIDDeleteTokenHandler)handler;
#pragma mark - Identity
/**
* Asynchronously fetch a stable identifier that uniquely identifies the app
* instance. If the identifier has been revoked or has expired, this method will
* return a new identifier.
*
*
* @param handler The handler to invoke once the identifier has been fetched.
* In case of error an appropriate error object is returned else
* a valid identifier is returned and a valid identifier for the
* application instance.
*/
- (void)getIDWithHandler:(nonnull FIRInstanceIDHandler)handler;
/**
* Resets Instance ID and revokes all tokens.
*/
- (void)deleteIDWithHandler:(nonnull FIRInstanceIDDeleteHandler)handler;
@end
framework module FirebaseInstanceID {
export *
umbrella header "FirebaseInstanceID.h"
header "FIRInstanceID.h"
}
#import <Foundation/Foundation.h>
/**
* The completion handler invoked once the data connection with FIRMessaging is
* established. The data connection is used to send a continous stream of
* data and all the FIRMessaging data notifications arrive through this connection.
* Once the connection is established we invoke the callback with `nil` error.
* Correspondingly if we get an error while trying to establish a connection
* we invoke the handler with an appropriate error object and do an
* exponential backoff to try and connect again unless successful.
*
* @param error The error object if any describing why the data connection
* to FIRMessaging failed.
*/
typedef void(^FIRMessagingConnectCompletion)(NSError * __nullable error);
/**
* Notification sent when the upstream message has been delivered
* successfully to the server. The notification object will be the messageID
* of the successfully delivered message.
*/
FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingSendSuccessNotification;
/**
* Notification sent when the upstream message was failed to be sent to the
* server. The notification object will be the messageID of the failed
* message. The userInfo dictionary will contain the relevant error
* information for the failure.
*/
FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingSendErrorNotification;
/**
* Notification sent when the Firebase messaging server deletes pending
* messages due to exceeded storage limits. This may occur, for example, when
* the device cannot be reached for an extended period of time.
*
* It is recommended to retrieve any missing messages directly from the
* server.
*/
FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingMessagesDeletedNotification;
/**
* @enum FIRMessagingError
*/
typedef NS_ENUM(NSUInteger, FIRMessagingError) {
// Unknown error.
FIRMessagingErrorUnknown = 0,
// Auth Error -- FIRMessaging couldn't validate request from this client.
FIRMessagingErrorAuthentication = 1,
// NoAccess -- InstanceID service cannot be accessed.
FIRMessagingErrorNoAccess = 2,
// Timeout -- Request to InstanceID backend timed out.
FIRMessagingErrorTimeout = 3,
// Network -- No network available to reach the servers.
FIRMessagingErrorNetwork = 4,
// OperationInProgress -- Another similar operation in progress,
// bailing this one.
FIRMessagingErrorOperationInProgress = 5,
// InvalidRequest -- Some parameters of the request were invalid.
FIRMessagingErrorInvalidRequest = 7,
};
/// Status for the downstream message received by the app.
typedef NS_ENUM(NSInteger, FIRMessagingMessageStatus) {
FIRMessagingMessageStatusUnknown,
/// New downstream message received by the app.
FIRMessagingMessageStatusNew,
};
/// Information about a downstream message received by the app.
@interface FIRMessagingMessageInfo : NSObject
@property(nonatomic, readonly, assign) FIRMessagingMessageStatus status;
@end
/**
* A remote data message received by the app via FCM (not just the APNs interface).
*
* This is only for devices running iOS 10 or above. To support devices running iOS 9 or below, use
* the local and remote notifications handlers defined in UIApplicationDelegate protocol.
*/
@interface FIRMessagingRemoteMessage : NSObject
/// The downstream message received by the application.
@property(nonatomic, readonly, strong, nonnull) NSDictionary *appData;
@end
/**
* A protocol to receive data message via FCM for devices running iOS 10 or above.
*
* To support devices running iOS 9 or below, use the local and remote notifications handlers
* defined in UIApplicationDelegate protocol.
*/
@protocol FIRMessagingDelegate <NSObject>
/// The callback to handle data message received via FCM for devices running iOS 10 or above.
- (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage;
@end
/**
* Firebase Messaging enables apps to communicate with their app servers
* using simple messages.
*
* To send or receive messages, the app must get a
* registration token from GGLInstanceID, which authorizes an
* app server to send messages to an app instance. Pass your sender ID and
* `kGGLInstanceIDScopeFIRMessaging` as parameters to the method.
*
* A sender ID is a project number created when you configure your API project.
* It is labeled "Project Number" in the Google Developers Console.
*
* In order to receive FIRMessaging messages, declare application:didReceiveRemoteNotification:
*
* Client apps can send upstream messages back to the app server using the XMPP-based
* <a href="http://developers.google.com/cloud-messaging/ccs.html">Cloud Connection Server</a>,
*
*/
@interface FIRMessaging : NSObject
/**
* Delegate to handle remote data messages received via FCM for devices running iOS 10 or above.
*/
@property(nonatomic, weak, nullable) id<FIRMessagingDelegate> remoteMessageDelegate;
/**
* FIRMessaging
*
* @return An instance of FIRMessaging.
*/
+ (nonnull instancetype)messaging NS_SWIFT_NAME(messaging());
/**
* Unavailable. Use +messaging instead.
*/
- (nonnull instancetype)init __attribute__((unavailable("Use +messaging instead.")));
#pragma mark - Connect
/**
* Create a FIRMessaging data connection which will be used to send the data notifications
* send by your server. It will also be used to send ACKS and other messages based
* on the FIRMessaging ACKS and other messages based on the FIRMessaging protocol.
*
* Use the `disconnect` method to disconnect the connection.
*
* @see FIRMessagingService disconnect
*
* @param handler The handler to be invoked once the connection is established.
* If the connection fails we invoke the handler with an
* appropriate error code letting you know why it failed. At
* the same time, FIRMessaging performs exponential backoff to retry
* establishing a connection and invoke the handler when successful.
*/
- (void)connectWithCompletion:(nonnull FIRMessagingConnectCompletion)handler;
/**
* Disconnect the current FIRMessaging data connection. This stops any attempts to
* connect to FIRMessaging. Calling this on an already disconnected client is a no-op.
*
* Call this before `teardown` when your app is going to the background.
* Since the FIRMessaging connection won't be allowed to live when in background it is
* prudent to close the connection.
*/
- (void)disconnect;
#pragma mark - Topics
/**
* Asynchronously subscribes to a topic.
*
* @param topic The name of the topic, for example @"sports".
*/
- (void)subscribeToTopic:(nonnull NSString *)topic;
/**
* Asynchronously unsubscribe to a topic.
*
* @param topic The name of the topic, for example @"sports".
*/
- (void)unsubscribeFromTopic:(nonnull NSString *)topic;
#pragma mark - Upstream
/**
* Sends an upstream ("device to cloud") message.
*
* The message will be queued if we don't have an active connection.
* You can only use the upstream feature if your GCM implementation
* uses the XMPP-based Cloud Connection Server.
*
* @param message Key/Value pairs to be sent. Values must be String, any
* other type will be ignored.
* @param to A string identifying the receiver of the message. For GCM
* project IDs the value is `SENDER_ID@gcm.googleapis.com`.
* @param messageID The ID of the message. This is generated by the application. It
* must be unique for each message generated by this application.
* It allows error callbacks and debugging, to uniquely identify
* each message.
* @param ttl The time to live for the message. In case we aren't able to
* send the message before the TTL expires we will send you a
* callback. If 0, we'll attempt to send immediately and return
* an error if we're not connected. Otherwise, the message will
* be queued. As for server-side messages, we don't return an error
* if the message has been dropped because of TTL; this can happen
* on the server side, and it would require extra communication.
*/
- (void)sendMessage:(nonnull NSDictionary *)message
to:(nonnull NSString *)receiver
withMessageID:(nonnull NSString *)messageID
timeToLive:(int64_t)ttl;
#pragma mark - Analytics
/**
* Call this when the app received a downstream message. Used to track message
* delivery and analytics for messages. You don't need to call this if you
* don't set the `FIRMessagingAutoSetupEnabled` flag in your Info.plist. In the
* latter case the library will call this implicitly to track relevant
* messages.
*
* @param message The downstream message received by the application.
*
* @return Information about the downstream message.
*/
- (nonnull FIRMessagingMessageInfo *)appDidReceiveMessage:(nonnull NSDictionary *)message;
@end
framework module FirebaseMessaging {
export *
umbrella header "FirebaseMessaging.h"
header "FIRMessaging.h"
link framework "AddressBook"
link framework "SystemConfiguration"
link "sqlite3"
}
<?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>
<key>AD_UNIT_ID_FOR_BANNER_TEST</key>
<string>ca-app-pub-3940256099942544/2934735716</string>
<key>AD_UNIT_ID_FOR_INTERSTITIAL_TEST</key>
<string>ca-app-pub-3940256099942544/4411468910</string>
<key>CLIENT_ID</key>
<string>921337447974-nkp854vmsbldse8r7um80tj8h93h21f5.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.921337447974-nkp854vmsbldse8r7um80tj8h93h21f5</string>
<key>API_KEY</key>
<string>AIzaSyDe8YJFybMewQFa6PVT7M01hb8K7Ct6AnU</string>
<key>GCM_SENDER_ID</key>
<string>921337447974</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>fcm.simplefcmclient</string>
<key>PROJECT_ID</key>
<string>simplefcmclient-d7db1</string>
<key>STORAGE_BUCKET</key>
<string>simplefcmclient-d7db1.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<true/>
<key>IS_ANALYTICS_ENABLED</key>
<false/>
<key>IS_APPINVITE_ENABLED</key>
<false/>
<key>IS_GCM_ENABLED</key>
<true/>
<key>IS_SIGNIN_ENABLED</key>
<true/>
<key>GOOGLE_APP_ID</key>
<string>1:921337447974:ios:b71c73a2fedb7a5a</string>
<key>DATABASE_URL</key>
<string>https://simplefcmclient-d7db1.firebaseio.com</string>
</dict>
</plist>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "SimpleFcmClient.app"
BlueprintName = "SimpleFcmClient"
ReferencedContainer = "container:SimpleFcmClient.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "SimpleFcmClientTests.xctest"
BlueprintName = "SimpleFcmClientTests"
ReferencedContainer = "container:SimpleFcmClient.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "SimpleFcmClientTests.xctest"
BlueprintName = "SimpleFcmClientTests"
ReferencedContainer = "container:SimpleFcmClient.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "SimpleFcmClient.app"
BlueprintName = "SimpleFcmClient"
ReferencedContainer = "container:SimpleFcmClient.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "SimpleFcmClient.app"
BlueprintName = "SimpleFcmClient"
ReferencedContainer = "container:SimpleFcmClient.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "SimpleFcmClient.app"
BlueprintName = "SimpleFcmClient"
ReferencedContainer = "container:SimpleFcmClient.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
@import UserNotifications;
@interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "AppDelegate.h"
#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"
#import "RNFIRMessaging.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"SimpleFcmClient"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[FIRApp configure];
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
#endif
return YES;
}
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
[[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:notification.request.content.userInfo];
if([[notification.request.content.userInfo valueForKey:@"show_in_foreground"] isEqual:@YES]) {
completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound);
} else {
completionHandler(UNNotificationPresentationOptionNone);
}
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary* userInfo = [[NSMutableDictionary alloc] initWithDictionary: response.notification.request.content.userInfo];
[userInfo setValue:@YES forKey:@"opened_from_tray"];
[[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:userInfo];
}
#else
//You can skip this method if you don't want to use local notification
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
[[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self + userInfo:notification.userInfo];
}
#endif
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
[[NSNotificationCenter defaultCenter] postNotificationName:FCMNotificationReceived object:self userInfo:userInfo];
completionHandler(UIBackgroundFetchResultNoData);
}
@end
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SimpleFcmClient" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?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>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Simple Fcm Client</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
<?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>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
<?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>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "RCTLog.h"
#import "RCTRootView.h"
#define TIMEOUT_SECONDS 600
#define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
@interface SimpleFcmClientTests : XCTestCase
@end
@implementation SimpleFcmClientTests
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
{
if (test(view)) {
return YES;
}
for (UIView *subview in [view subviews]) {
if ([self findSubviewInView:subview matching:test]) {
return YES;
}
}
return NO;
}
- (void)testRendersWelcomeScreen
{
UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
BOOL foundElement = NO;
__block NSString *redboxError = nil;
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
if (level >= RCTLogLevelError) {
redboxError = message;
}
});
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
return YES;
}
return NO;
}];
}
RCTSetLogFunction(RCTDefaultLogFunction);
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
}
@end
module Firebase {
header "Firebase.h"
export *
}
{
"name": "SimpleFcmClient",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "15.3.2",
"react-native": "0.35.0",
"react-native-fcm": "^2.3.1"
},
"jest": {
"preset": "jest-react-native"
},
"devDependencies": {
"babel-jest": "16.0.0",
"babel-preset-react-native": "1.9.0",
"jest": "16.0.1",
"jest-react-native": "16.0.0",
"react-test-renderer": "15.3.2"
}
}
......@@ -311,8 +311,8 @@ class App extends Component {
FCM.getScheduledLocalNotifications().then(notif=>console.log(notif));
FCM.cancelLocalNotification("UNIQ_ID_STRING");
FCM.cancelAllLocalNotifications();
FCM.setBadgeNumber();
FCM.getBadgeNumber().then(number=>console.log(number));
FCM.setBadgeNumber(); // iOS only and there's no way to set it in Android, yet.
FCM.getBadgeNumber().then(number=>console.log(number)); // iOS only and there's no way to get it in Android, yet.
FCM.send('984XXXXXXXXX', {
my_custom_data_1: 'my_custom_field_value_1',
my_custom_data_2: 'my_custom_field_value_2'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment