of(
51 | "onAdLoaded",
52 | MapBuilder.of("registrationName", "onAdLoaded"),
53 | "onAdFailed",
54 | MapBuilder.of("registrationName", "onAdFailed")
55 | );
56 | }
57 |
58 | @Override
59 | public void addView(NativeAdView parent, View child, int index) {
60 | parent.addView(child, index);
61 | }
62 |
63 | @Override
64 | public int getChildCount(NativeAdView parent) {
65 | return parent.getChildCount();
66 | }
67 |
68 | @Override
69 | public View getChildAt(NativeAdView parent, int index) {
70 | return parent.getChildAt(index);
71 | }
72 |
73 | @Override
74 | public void removeViewAt(NativeAdView parent, int index) {
75 | parent.removeViewAt(index);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ReactNativeFbAds
3 |
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | // google()
4 | jcenter()
5 | maven { url 'https://maven.google.com' }
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.0.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | jcenter()
15 | maven { url 'https://maven.google.com' }
16 | }
17 | }
18 |
19 | task clean(type: Delete) {
20 | delete rootProject.buildDir
21 | }
22 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 | android.useAndroidX=true
19 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Oct 02 14:21:13 IDT 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app.plugin.js:
--------------------------------------------------------------------------------
1 | module.exports = require("./plugin/build/withReactNativeFbads");
--------------------------------------------------------------------------------
/example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: '@react-native-community',
4 | };
5 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 | yarn-error.log
37 |
38 | # BUCK
39 | buck-out/
40 | \.buckd/
41 | *.keystore
42 | !debug.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | */fastlane/report.xml
52 | */fastlane/Preview.html
53 | */fastlane/screenshots
54 |
55 | # Bundle artifact
56 | *.jsbundle
57 |
58 | # CocoaPods
59 | /ios/Pods/
60 |
--------------------------------------------------------------------------------
/example/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: false,
3 | jsxBracketSameLine: true,
4 | singleQuote: true,
5 | trailingComma: 'all',
6 | };
7 |
--------------------------------------------------------------------------------
/example/App.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {Container} from 'native-base';
3 | import {Scene, Router} from 'react-native-router-flux';
4 |
5 | import Main from './src';
6 | import NativeAd from './src/NativeAds';
7 | import BannerAd from './src/BannerAds';
8 | import InterstitialAd from './src/InterstitialAds';
9 |
10 | export default class App extends Component {
11 | render() {
12 | return (
13 |
14 |
15 |
16 |
23 |
30 |
37 |
44 |
45 |
46 |
47 | );
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/example/__tests__/App-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import 'react-native';
6 | import React from 'react';
7 | import App from '../App';
8 |
9 | // Note: test renderer must be required after react-native.
10 | import renderer from 'react-test-renderer';
11 |
12 | it('renders correctly', () => {
13 | renderer.create();
14 | });
15 |
--------------------------------------------------------------------------------
/example/android/app/BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.example",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.example",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation. If none specified and
19 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is
20 | * // default. Can be overridden with ENTRY_FILE environment variable.
21 | * entryFile: "index.android.js",
22 | *
23 | * // https://reactnative.dev/docs/performance#enable-the-ram-format
24 | * bundleCommand: "ram-bundle",
25 | *
26 | * // whether to bundle JS and assets in debug mode
27 | * bundleInDebug: false,
28 | *
29 | * // whether to bundle JS and assets in release mode
30 | * bundleInRelease: true,
31 | *
32 | * // whether to bundle JS and assets in another build variant (if configured).
33 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
34 | * // The configuration property can be in the following formats
35 | * // 'bundleIn${productFlavor}${buildType}'
36 | * // 'bundleIn${buildType}'
37 | * // bundleInFreeDebug: true,
38 | * // bundleInPaidRelease: true,
39 | * // bundleInBeta: true,
40 | *
41 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
42 | * // for example: to disable dev mode in the staging build type (if configured)
43 | * devDisabledInStaging: true,
44 | * // The configuration property can be in the following formats
45 | * // 'devDisabledIn${productFlavor}${buildType}'
46 | * // 'devDisabledIn${buildType}'
47 | *
48 | * // the root of your project, i.e. where "package.json" lives
49 | * root: "../../",
50 | *
51 | * // where to put the JS bundle asset in debug mode
52 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
53 | *
54 | * // where to put the JS bundle asset in release mode
55 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
56 | *
57 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
58 | * // require('./image.png')), in debug mode
59 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
60 | *
61 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
62 | * // require('./image.png')), in release mode
63 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
64 | *
65 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
66 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
67 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
68 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
69 | * // for example, you might want to remove it from here.
70 | * inputExcludes: ["android/**", "ios/**"],
71 | *
72 | * // override which node gets called and with what additional arguments
73 | * nodeExecutableAndArgs: ["node"],
74 | *
75 | * // supply additional arguments to the packager
76 | * extraPackagerArgs: []
77 | * ]
78 | */
79 |
80 | project.ext.react = [
81 | enableHermes: false, // clean and rebuild if changing
82 | ]
83 |
84 | apply from: "../../node_modules/react-native/react.gradle"
85 |
86 | /**
87 | * Set this to true to create two separate APKs instead of one:
88 | * - An APK that only works on ARM devices
89 | * - An APK that only works on x86 devices
90 | * The advantage is the size of the APK is reduced by about 4MB.
91 | * Upload all the APKs to the Play Store and people will download
92 | * the correct one based on the CPU architecture of their device.
93 | */
94 | def enableSeparateBuildPerCPUArchitecture = false
95 |
96 | /**
97 | * Run Proguard to shrink the Java bytecode in release builds.
98 | */
99 | def enableProguardInReleaseBuilds = false
100 |
101 | /**
102 | * The preferred build flavor of JavaScriptCore.
103 | *
104 | * For example, to use the international variant, you can use:
105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
106 | *
107 | * The international variant includes ICU i18n library and necessary data
108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
109 | * give correct results when using with locales other than en-US. Note that
110 | * this variant is about 6MiB larger per architecture than default.
111 | */
112 | def jscFlavor = 'org.webkit:android-jsc:+'
113 |
114 | /**
115 | * Whether to enable the Hermes VM.
116 | *
117 | * This should be set on project.ext.react and mirrored here. If it is not set
118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
119 | * and the benefits of using Hermes will therefore be sharply reduced.
120 | */
121 | def enableHermes = project.ext.react.get("enableHermes", false);
122 |
123 | android {
124 | compileSdkVersion rootProject.ext.compileSdkVersion
125 |
126 | compileOptions {
127 | sourceCompatibility JavaVersion.VERSION_1_8
128 | targetCompatibility JavaVersion.VERSION_1_8
129 | }
130 |
131 | defaultConfig {
132 | applicationId "com.example"
133 | minSdkVersion rootProject.ext.minSdkVersion
134 | targetSdkVersion rootProject.ext.targetSdkVersion
135 | versionCode 1
136 | versionName "1.0"
137 | multiDexEnabled true
138 | }
139 | splits {
140 | abi {
141 | reset()
142 | enable enableSeparateBuildPerCPUArchitecture
143 | universalApk false // If true, also generate a universal APK
144 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
145 | }
146 | }
147 | buildTypes {
148 | release {
149 | // Caution! In production, you need to generate your own keystore file.
150 | // see https://reactnative.dev/docs/signed-apk-android.
151 | signingConfig signingConfigs.debug
152 | minifyEnabled enableProguardInReleaseBuilds
153 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
154 | }
155 | }
156 |
157 | // applicationVariants are e.g. debug, release
158 | applicationVariants.all { variant ->
159 | variant.outputs.each { output ->
160 | // For each separate APK per architecture, set a unique version code as described here:
161 | // https://developer.android.com/studio/build/configure-apk-splits.html
162 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
163 | def abi = output.getFilter(OutputFile.ABI)
164 | if (abi != null) { // null for the universal-debug, universal-release variants
165 | output.versionCodeOverride =
166 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
167 | }
168 |
169 | }
170 | }
171 | }
172 |
173 | dependencies {
174 | implementation fileTree(dir: "libs", include: ["*.jar"])
175 | //noinspection GradleDynamicVersion
176 | implementation "com.facebook.react:react-native:+" // From node_modules
177 |
178 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
179 |
180 | implementation 'com.facebook.android:facebook-android-sdk:[5,6)'
181 |
182 | implementation 'com.android.support:multidex:1.0.3'
183 |
184 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
185 | exclude group:'com.facebook.fbjni'
186 | }
187 |
188 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
189 | exclude group:'com.facebook.flipper'
190 | exclude group:'com.squareup.okhttp3', module:'okhttp'
191 | }
192 |
193 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
194 | exclude group:'com.facebook.flipper'
195 | }
196 |
197 | if (enableHermes) {
198 | def hermesPath = "../../node_modules/hermes-engine/android/";
199 | debugImplementation files(hermesPath + "hermes-debug.aar")
200 | releaseImplementation files(hermesPath + "hermes-release.aar")
201 | } else {
202 | implementation jscFlavor
203 | }
204 | }
205 |
206 | // Run this once to be able to run the application with BUCK
207 | // puts all compile dependencies into folder libs for BUCK to use
208 | task copyDownloadableDepsToLibs(type: Copy) {
209 | from configurations.compile
210 | into 'libs'
211 | }
212 |
213 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
214 |
--------------------------------------------------------------------------------
/example/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/example/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.example;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceManager;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.modules.network.NetworkingModule;
25 | import okhttp3.OkHttpClient;
26 |
27 | public class ReactNativeFlipper {
28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
29 | if (FlipperUtils.shouldEnableFlipper(context)) {
30 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
31 |
32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
33 | client.addPlugin(new ReactFlipperPlugin());
34 | client.addPlugin(new DatabasesFlipperPlugin(context));
35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
36 | client.addPlugin(CrashReporterPlugin.getInstance());
37 |
38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39 | NetworkingModule.setCustomClientBuilder(
40 | new NetworkingModule.CustomClientBuilder() {
41 | @Override
42 | public void apply(OkHttpClient.Builder builder) {
43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44 | }
45 | });
46 | client.addPlugin(networkFlipperPlugin);
47 | client.start();
48 |
49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
50 | // Hence we run if after all native modules have been initialized
51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
52 | if (reactContext == null) {
53 | reactInstanceManager.addReactInstanceEventListener(
54 | new ReactInstanceManager.ReactInstanceEventListener() {
55 | @Override
56 | public void onReactContextInitialized(ReactContext reactContext) {
57 | reactInstanceManager.removeReactInstanceEventListener(this);
58 | reactContext.runOnNativeModulesQueueThread(
59 | new Runnable() {
60 | @Override
61 | public void run() {
62 | client.addPlugin(new FrescoFlipperPlugin());
63 | }
64 | });
65 | }
66 | });
67 | } else {
68 | client.addPlugin(new FrescoFlipperPlugin());
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/AntDesign.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/AntDesign.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Entypo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Entypo.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/EvilIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/EvilIcons.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Feather.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Feather.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/FontAwesome.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/FontAwesome.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Fontisto.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Fontisto.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Foundation.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Foundation.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Ionicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Ionicons.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/MaterialIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/MaterialIcons.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Octicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Octicons.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Roboto.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Roboto.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Roboto_medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Roboto_medium.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/SimpleLineIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/SimpleLineIcons.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/Zocial.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/Zocial.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/assets/fonts/rubicon-icon-font.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/assets/fonts/rubicon-icon-font.ttf
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript. This is used to schedule
9 | * rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "example";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.reactnative.androidsdk.FBSDKPackage;
8 | import suraj.tiwari.reactnativefbads.FBAdsPackage;
9 | import com.facebook.react.ReactInstanceManager;
10 | import com.facebook.react.ReactNativeHost;
11 | import com.facebook.react.ReactPackage;
12 | import com.facebook.soloader.SoLoader;
13 | import java.lang.reflect.InvocationTargetException;
14 | import java.util.List;
15 |
16 | public class MainApplication extends Application implements ReactApplication {
17 |
18 | private final ReactNativeHost mReactNativeHost =
19 | new ReactNativeHost(this) {
20 | @Override
21 | public boolean getUseDeveloperSupport() {
22 | return BuildConfig.DEBUG;
23 | }
24 |
25 | @Override
26 | protected List getPackages() {
27 | @SuppressWarnings("UnnecessaryLocalVariable")
28 | List packages = new PackageList(this).getPackages();
29 | // Packages that cannot be autolinked yet can be added manually here, for example:
30 | // packages.add(new MyReactNativePackage());
31 | return packages;
32 | }
33 |
34 | @Override
35 | protected String getJSMainModuleName() {
36 | return "index";
37 | }
38 | };
39 |
40 | @Override
41 | public ReactNativeHost getReactNativeHost() {
42 | return mReactNativeHost;
43 | }
44 |
45 | @Override
46 | public void onCreate() {
47 | super.onCreate();
48 | SoLoader.init(this, /* native exopackage */ false);
49 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
50 | }
51 |
52 | /**
53 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
54 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
55 | *
56 | * @param context
57 | * @param reactInstanceManager
58 | */
59 | private static void initializeFlipper(
60 | Context context, ReactInstanceManager reactInstanceManager) {
61 | if (BuildConfig.DEBUG) {
62 | try {
63 | /*
64 | We use reflection here to pick up the class that initializes Flipper,
65 | since Flipper library is not available in release mode
66 | */
67 | Class> aClass = Class.forName("com.example.ReactNativeFlipper");
68 | aClass
69 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
70 | .invoke(null, context, reactInstanceManager);
71 | } catch (ClassNotFoundException e) {
72 | e.printStackTrace();
73 | } catch (NoSuchMethodException e) {
74 | e.printStackTrace();
75 | } catch (IllegalAccessException e) {
76 | e.printStackTrace();
77 | } catch (InvocationTargetException e) {
78 | e.printStackTrace();
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | example
3 | Facebook App ID
4 |
5 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "29.0.2"
6 | minSdkVersion = 16
7 | compileSdkVersion = 29
8 | targetSdkVersion = 29
9 | }
10 | repositories {
11 | google()
12 | jcenter()
13 | mavenCentral()
14 | }
15 | dependencies {
16 | classpath("com.android.tools.build:gradle:3.5.3")
17 | // NOTE: Do not place your application dependencies here; they belong
18 | // in the individual module build.gradle files
19 | }
20 | }
21 |
22 | allprojects {
23 | repositories {
24 | mavenLocal()
25 | maven {
26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
27 | url("$rootDir/../node_modules/react-native/android")
28 | }
29 | maven {
30 | // Android JSC is installed from npm
31 | url("$rootDir/../node_modules/jsc-android/dist")
32 | }
33 |
34 | google()
35 | jcenter()
36 | maven { url 'https://www.jitpack.io' }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.54.0
29 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin or MSYS, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=`expr $i + 1`
158 | done
159 | case $i in
160 | 0) set -- ;;
161 | 1) set -- "$args0" ;;
162 | 2) set -- "$args0" "$args1" ;;
163 | 3) set -- "$args0" "$args1" "$args2" ;;
164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=`save "$@"`
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | exec "$JAVACMD" "$@"
184 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 | @rem Execute Gradle
88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
89 |
90 | :end
91 | @rem End local scope for the variables with windows NT shell
92 | if "%ERRORLEVEL%"=="0" goto mainEnd
93 |
94 | :fail
95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
96 | rem the _cmd.exe /c_ return code!
97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
98 | exit /b 1
99 |
100 | :mainEnd
101 | if "%OS%"=="Windows_NT" endlocal
102 |
103 | :omega
104 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'example'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "displayName": "example"
4 | }
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import {AppRegistry} from 'react-native';
6 | import App from './App';
7 | import {name as appName} from './app.json';
8 |
9 | AppRegistry.registerComponent(appName, () => App);
10 |
--------------------------------------------------------------------------------
/example/ios/File.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | require_relative '../node_modules/react-native/scripts/react_native_pods'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | platform :ios, '10.0'
5 |
6 | target 'example' do
7 |
8 | config = use_native_modules!
9 |
10 | use_react_native!(:path => config["reactNativePath"])
11 |
12 | target 'exampleTests' do
13 | inherit! :complete
14 | # Pods for testing
15 | end
16 |
17 | # Enables Flipper.
18 | #
19 | # Note that if you have use_frameworks! enabled, Flipper will not work and
20 | # you should disable these next few lines.
21 | use_flipper!
22 | post_install do |installer|
23 | flipper_post_install(installer)
24 | end
25 | end
26 |
27 | target 'example-tvOS' do
28 | # Pods for example-tvOS
29 |
30 | target 'example-tvOSTests' do
31 | inherit! :search_paths
32 | # Pods for testing
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/example/ios/example-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 |
--------------------------------------------------------------------------------
/example/ios/example-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSExceptionDomains
28 |
29 | localhost
30 |
31 | NSExceptionAllowsInsecureHTTPLoads
32 |
33 |
34 |
35 |
36 | NSLocationWhenInUseUsageDescription
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/example/ios/example-tvOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/example.xcodeproj/xcshareddata/xcschemes/example-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/example/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : UIResponder
5 |
6 | @property (nonatomic, strong) UIWindow *window;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/example/ios/example/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #ifdef FB_SONARKIT_ENABLED
8 | #import
9 | #import
10 | #import
11 | #import
12 | #import
13 | #import
14 |
15 | static void InitializeFlipper(UIApplication *application) {
16 | FlipperClient *client = [FlipperClient sharedClient];
17 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
18 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
19 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
20 | [client addPlugin:[FlipperKitReactPlugin new]];
21 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
22 | [client start];
23 | }
24 | #endif
25 |
26 | @implementation AppDelegate
27 |
28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
29 | {
30 | #ifdef FB_SONARKIT_ENABLED
31 | InitializeFlipper(application);
32 | #endif
33 |
34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
35 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
36 | moduleName:@"example"
37 | initialProperties:nil];
38 |
39 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
40 |
41 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
42 | UIViewController *rootViewController = [UIViewController new];
43 | rootViewController.view = rootView;
44 | self.window.rootViewController = rootViewController;
45 | [self.window makeKeyAndVisible];
46 | return YES;
47 | }
48 |
49 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
50 | {
51 | #if DEBUG
52 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
53 | #else
54 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
55 | #endif
56 | }
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | NSLocationWhenInUseUsageDescription
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIViewControllerBasedStatusBarAppearance
55 |
56 | NSUserTrackingUsageDescription
57 | Testing purposes
58 | UIAppFonts
59 |
60 | AntDesign.ttf
61 | Entypo.ttf
62 | EvilIcons.ttf
63 | Feather.ttf
64 | FontAwesome.ttf
65 | FontAwesome5_Brands.ttf
66 | FontAwesome5_Regular.ttf
67 | FontAwesome5_Solid.ttf
68 | Fontisto.ttf
69 | Foundation.ttf
70 | Ionicons.ttf
71 | MaterialCommunityIcons.ttf
72 | MaterialIcons.ttf
73 | Octicons.ttf
74 | Roboto_medium.ttf
75 | Roboto.ttf
76 | rubicon-icon-font.ttf
77 | SimpleLineIcons.ttf
78 | Zocial.ttf
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/example/ios/example/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/example/ios/example/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char * argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/ios/exampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/exampleTests/exampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface exampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation exampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
38 | if (level >= RCTLogLevelError) {
39 | redboxError = message;
40 | }
41 | });
42 | #endif
43 |
44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 |
48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
50 | return YES;
51 | }
52 | return NO;
53 | }];
54 | }
55 |
56 | #ifdef DEBUG
57 | RCTSetLogFunction(RCTDefaultLogFunction);
58 | #endif
59 |
60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
62 | }
63 |
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | module.exports = {
9 | transformer: {
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: false,
14 | },
15 | }),
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest",
10 | "lint": "eslint ."
11 | },
12 | "dependencies": {
13 | "native-base": "^2.8.0",
14 | "react": "16.13.1",
15 | "react-native": "0.63.4",
16 | "react-native-fbads": "file:..",
17 | "react-native-fbsdk": "^3.0.0",
18 | "react-native-gesture-handler": "^1.9.0",
19 | "react-native-reanimated": "^1.13.2",
20 | "react-native-router-flux": "^4.0.1",
21 | "react-native-screens": "^2.15.2"
22 | },
23 | "devDependencies": {
24 | "@babel/core": "^7.12.10",
25 | "@babel/runtime": "^7.12.5",
26 | "@react-native-community/eslint-config": "^2.0.0",
27 | "babel-jest": "^26.6.3",
28 | "eslint": "^7.18.0",
29 | "jest": "^26.6.3",
30 | "metro-react-native-babel-preset": "^0.64.0",
31 | "react-test-renderer": "16.13.1"
32 | },
33 | "jest": {
34 | "preset": "react-native"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/example/src/BannerAds/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {StyleSheet, View} from 'react-native';
3 | import {Container} from 'native-base';
4 | import {BannerView} from 'react-native-fbads';
5 | import {bannerAdPlacementId} from '../Variables';
6 |
7 | export default class BannerAd extends Component {
8 | render() {
9 | return (
10 |
11 |
12 | console.log('click')}
16 | onError={(err) => console.log('error', err)}
17 | />
18 |
19 |
20 | console.log('click')}
24 | onError={(err) => console.log('error', err)}
25 | />
26 |
27 |
28 | );
29 | }
30 | }
31 |
32 | let styles = StyleSheet.create({
33 | container: {
34 | justifyContent: 'center',
35 | },
36 | bannerContainer: {
37 | marginVertical: 10,
38 | },
39 | });
40 |
--------------------------------------------------------------------------------
/example/src/InterstitialAds/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {StyleSheet, Dimensions, TouchableHighlight} from 'react-native';
3 | import {Container, Text} from 'native-base';
4 | import {InterstitialAdManager} from 'react-native-fbads';
5 | import {InterstitialAdPlacementId} from '../Variables';
6 |
7 | const {width} = Dimensions.get('window');
8 |
9 | export default class InterstitialAd extends Component {
10 | render() {
11 | return (
12 |
13 | this._showAd()}>
17 | Show Interstitial Ad
18 |
19 |
20 | );
21 | }
22 |
23 | _showAd() {
24 | InterstitialAdManager.showAd(InterstitialAdPlacementId)
25 | .then(() => {})
26 | .catch(() => {});
27 | }
28 | }
29 |
30 | let styles = StyleSheet.create({
31 | container: {
32 | width,
33 | position: 'absolute',
34 | justifyContent: 'center',
35 | alignItems: 'center',
36 | },
37 | button: {
38 | elevation: 3,
39 | borderRadius: 10,
40 | paddingVertical: 10,
41 | width: width - 80,
42 | alignItems: 'center',
43 | marginVertical: 5,
44 | backgroundColor: '#fff',
45 | justifyContent: 'center',
46 | },
47 | buttonText: {
48 | color: '#a70f0a',
49 | },
50 | });
51 |
--------------------------------------------------------------------------------
/example/src/NativeAds/NativeAdView.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {Text, View, Dimensions} from 'react-native';
3 | import {
4 | withNativeAd,
5 | AdIconView,
6 | TriggerableView,
7 | MediaView,
8 | } from 'react-native-fbads';
9 |
10 | const {width} = Dimensions.get('window');
11 |
12 | class NativeAdView extends Component {
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
19 |
21 |
22 | {this.props.nativeAd.headline}
23 |
24 | {this.props.nativeAd.sponsoredTranslation}
25 |
26 | {this.props.nativeAd.linkDescription}
27 |
28 |
29 |
30 |
31 |
42 | {this.props.nativeAd.callToActionText}
43 |
44 |
45 |
46 | );
47 | }
48 | }
49 |
50 | export default withNativeAd(NativeAdView);
51 |
--------------------------------------------------------------------------------
/example/src/NativeAds/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {NativeAdsManager, AdSettings} from 'react-native-fbads';
3 | import {Container} from 'native-base';
4 | import {nativeAdPlacementId} from '../Variables';
5 |
6 | import NativeAdView from './NativeAdView';
7 |
8 | export default class NativeAd extends Component {
9 | adsManager = new NativeAdsManager(nativeAdPlacementId);
10 |
11 | render() {
12 | return (
13 |
19 |
23 |
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/example/src/Variables/index.js:
--------------------------------------------------------------------------------
1 | const nativeAdPlacementId = '2122084034714087_2122088321380325';
2 | const bannerAdPlacementId = '';
3 | const InterstitialAdPlacementId = '';
4 |
5 | export {nativeAdPlacementId, bannerAdPlacementId, InterstitialAdPlacementId};
6 |
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {StyleSheet, Dimensions, TouchableHighlight} from 'react-native';
3 | import {Container, Text} from 'native-base';
4 | import {Actions} from 'react-native-router-flux';
5 | import {AdSettings} from 'react-native-fbads';
6 |
7 | const {width} = Dimensions.get('window');
8 |
9 | export default class Main extends Component {
10 | async componentDidMount() {
11 | AdSettings.setLogLevel('debug');
12 | AdSettings.addTestDevice(AdSettings.currentDeviceHash);
13 | const requestedStatus = await AdSettings.requestTrackingPermission();
14 |
15 | if (requestedStatus === 'authorized' || requestedStatus === 'unavailable') {
16 | AdSettings.setAdvertiserIDCollectionEnabled(true);
17 | // Both calls are not related to each other
18 | // FB won't deliver any ads if this is set to false or not called at all.
19 | AdSettings.setAdvertiserTrackingEnabled(true);
20 | }
21 | }
22 |
23 | componentWillUnmount() {
24 | AdSettings.clearTestDevices();
25 | }
26 | render() {
27 | return (
28 |
29 | Actions.nativeAd()}>
33 | Native Ad
34 |
35 | Actions.bannerAd()}
38 | style={styles.button}>
39 | Banner Ad
40 |
41 | Actions.interstitialAd()}
44 | style={styles.button}>
45 | Interstitial Ad
46 |
47 |
48 | );
49 | }
50 | }
51 |
52 | let styles = StyleSheet.create({
53 | container: {
54 | width,
55 | position: 'absolute',
56 | justifyContent: 'center',
57 | alignItems: 'center',
58 | },
59 | button: {
60 | elevation: 3,
61 | borderRadius: 10,
62 | paddingVertical: 10,
63 | width: width - 80,
64 | alignItems: 'center',
65 | marginVertical: 5,
66 | backgroundColor: '#fff',
67 | justifyContent: 'center',
68 | },
69 | buttonText: {
70 | color: '#a70f0a',
71 | },
72 | });
73 |
--------------------------------------------------------------------------------
/images/nativeAd.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/images/nativeAd.png
--------------------------------------------------------------------------------
/images/threed_mockup_fbNativeads.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/callstack/react-native-fbads/78935205b95cbd572dd1db3f849fc8fee4d5b5cf/images/threed_mockup_fbNativeads.png
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/AdChoiceManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // AdChoiceManager.h
3 | // ReactNativeAdsFacebook
4 | //
5 | // Created by Suraj Tiwari on 14/08/18.
6 | // Copyright © 2018 Suraj Tiwari . All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 |
13 | @interface AdChoiceManager : RCTViewManager
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/AdChoiceManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // AdChoiceManager.m
3 | // ReactNativeAdsFacebook
4 | //
5 | // Created by Suraj Tiwari on 14/08/18.
6 | // Copyright © 2018 Suraj Tiwari . All rights reserved.
7 | //
8 | #import "AdChoiceManager.h"
9 | #import "EXNativeAdManager.h"
10 | #import "AdChoiceView.h"
11 | #import
12 |
13 | @implementation RCTConvert (AdChoiceView)
14 |
15 | RCT_ENUM_CONVERTER(UIRectCorner, (@{
16 | @"topRight": @(UIRectCornerTopRight),
17 | @"topLeft": @(UIRectCornerTopLeft),
18 | @"bottomLeft": @(UIRectCornerBottomLeft),
19 | @"bottomRight": @(UIRectCornerBottomRight)
20 | }), UIRectCornerTopRight, intValue )
21 | @end
22 |
23 | @implementation AdChoiceManager
24 |
25 | RCT_EXPORT_MODULE(AdChoicesView)
26 |
27 | @synthesize bridge = _bridge;
28 |
29 | - (instancetype)init
30 | {
31 | self = [super init];
32 | return self;
33 | }
34 |
35 | - (UIView *)view
36 | {
37 | return [[AdChoiceView new] initWithBridge:_bridge];
38 | }
39 |
40 | + (BOOL) requiresMainQueueSetup {
41 | return YES;
42 | }
43 |
44 | RCT_EXPORT_VIEW_PROPERTY(placementId,NSString);
45 | RCT_EXPORT_VIEW_PROPERTY(location,UIRectCorner);
46 | RCT_EXPORT_VIEW_PROPERTY(expandable,BOOL);
47 |
48 | @end
49 |
50 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/AdChoiceView.h:
--------------------------------------------------------------------------------
1 | //
2 | // AdChoiceView.h
3 | // ReactNativeAdsFacebook
4 | //
5 | // Created by Suraj Tiwari on 14/08/18.
6 | // Copyright © 2018 Suraj Tiwari . All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 | #import
12 | #import
13 |
14 | @interface AdChoiceView : RCTView
15 |
16 | @property (nonatomic, strong) NSString *placementId;
17 | @property (nonatomic) UIRectCorner location;
18 | @property (nonatomic) BOOL *expandable;
19 |
20 | - (instancetype)initWithBridge:(RCTBridge *)bridge;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/AdChoiceView.m:
--------------------------------------------------------------------------------
1 | //
2 | // AdChoiceView.m
3 | // ReactNativeAdsFacebook
4 | //
5 | // Created by Suraj Tiwari on 14/08/18.
6 | // Copyright © 2018 Suraj Tiwari . All rights reserved.
7 | //
8 |
9 | #import "AdChoiceView.h"
10 | #import
11 | #import "EXNativeAdManager.h"
12 |
13 | @interface AdChoiceView ()
14 | @property (nonatomic, strong) RCTBridge *bridge;
15 | @end
16 |
17 | @implementation AdChoiceView
18 |
19 | - (instancetype)initWithBridge:(RCTBridge *)bridge
20 | {
21 | if (self = [super init]) {
22 | _bridge = bridge;
23 | }
24 | return self;
25 | }
26 |
27 | - (void)setPlacementId:(NSString *)placementId
28 | {
29 | _placementId = placementId;
30 | [self createViewIfCan:_placementId:_location: _expandable];
31 | }
32 |
33 | - (void)setLocation:(UIRectCorner)location
34 | {
35 | _location = location;
36 | [self createViewIfCan:_placementId:_location: _expandable];
37 | }
38 |
39 | - (void)setExpandable:(BOOL *)expandable
40 | {
41 | _expandable = expandable;
42 | [self createViewIfCan:_placementId :_location :_expandable];
43 | }
44 |
45 | - (void)createViewIfCan:(NSString *)placementId :(UIRectCorner) location :(BOOL) expandable
46 | {
47 | if (!location || !placementId) {
48 | return;
49 | }
50 | EXNativeAdManager *nativeAdManager = [_bridge moduleForClass:[EXNativeAdManager class]];
51 | FBNativeAdsManager *_adsManager = [nativeAdManager getFBAdsManager:placementId];
52 | FBNativeAd *nativeAd = [_adsManager nextNativeAd];
53 | FBAdChoicesView *adChoicesView = [[FBAdChoicesView alloc] initWithNativeAd:nativeAd expandable:expandable];
54 | [adChoicesView updateFrameFromSuperview:location];
55 | [self addSubview:adChoicesView];
56 | }
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXAdIconViewManager.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 |
5 | @interface EXAdIconViewManager : RCTViewManager
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXAdIconViewManager.m:
--------------------------------------------------------------------------------
1 | #import "EXAdIconViewManager.h"
2 |
3 | @implementation EXAdIconViewManager
4 |
5 | RCT_EXPORT_MODULE(AdIconViewManager)
6 |
7 | - (UIView *)view
8 | {
9 | return [[FBMediaView alloc] init];
10 | }
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXAdSettingsManager.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface EXAdSettingsManager : NSObject
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXAdSettingsManager.m:
--------------------------------------------------------------------------------
1 | #import "EXAdSettingsManager.h"
2 | #import "EXUnversioned.h"
3 |
4 | //#import
5 | #import
6 | #import
7 | #import
8 | #import
9 |
10 | #import
11 |
12 | @implementation RCTConvert (EXNativeAdView)
13 |
14 | RCT_ENUM_CONVERTER(FBAdLogLevel, (@{
15 | @"none": @(FBAdLogLevelNone),
16 | @"debug": @(FBAdLogLevelDebug),
17 | @"verbose": @(FBAdLogLevelVerbose),
18 | @"warning": @(FBAdLogLevelWarning),
19 | @"notification": @(FBAdLogLevelNotification),
20 | @"error": @(FBAdLogLevelError),
21 | }), FBAdLogLevelLog, integerValue)
22 |
23 | @end
24 |
25 | @interface EXAdSettingsManager ()
26 |
27 | @property (nonatomic) BOOL isChildDirected;
28 | @property (nonatomic, strong) NSString *mediationService;
29 | @property (nonatomic, strong) NSString *urlPrefix;
30 | @property (nonatomic) FBAdLogLevel logLevel;
31 | @property (nonatomic, strong) NSMutableArray *testDevices;
32 |
33 | @end
34 |
35 | @implementation EXAdSettingsManager
36 |
37 | @synthesize bridge = _bridge;
38 |
39 | RCT_EXPORT_MODULE(CTKAdSettingsManager)
40 |
41 | - (instancetype)init {
42 | if (self = [super init]) {
43 | _testDevices = [NSMutableArray new];
44 | _urlPrefix = @"";
45 | _mediationService = @"";
46 | }
47 | return self;
48 | }
49 |
50 | + (BOOL)requiresMainQueueSetup
51 | {
52 | return NO;
53 | }
54 |
55 | - (void)setBridge:(RCTBridge *)bridge
56 | {
57 | _bridge = bridge;
58 |
59 | [[NSNotificationCenter defaultCenter] addObserver:self
60 | selector:@selector(bridgeDidForeground:)
61 | name:EX_UNVERSIONED(@"EXKernelBridgeDidForegroundNotification")
62 | object:self.bridge];
63 |
64 | [[NSNotificationCenter defaultCenter] addObserver:self
65 | selector:@selector(bridgeDidBackground:)
66 | name:EX_UNVERSIONED(@"EXKernelBridgeDidBackgroundNotification")
67 | object:self.bridge];
68 | }
69 |
70 | RCT_EXPORT_METHOD(addTestDevice:(NSString *)deviceHash)
71 | {
72 | [FBAdSettings addTestDevice:deviceHash];
73 | [_testDevices addObject:deviceHash];
74 | }
75 |
76 | RCT_EXPORT_METHOD(clearTestDevices)
77 | {
78 | [FBAdSettings clearTestDevices];
79 | [_testDevices removeAllObjects];
80 | }
81 |
82 | RCT_EXPORT_METHOD(setLogLevel:(FBAdLogLevel)logLevel)
83 | {
84 | [FBAdSettings setLogLevel:logLevel];
85 | _logLevel = logLevel;
86 | }
87 |
88 | RCT_EXPORT_METHOD(setIsChildDirected:(BOOL)isDirected)
89 | {
90 | [FBAdSettings setMixedAudience:isDirected];
91 | _isChildDirected = isDirected;
92 | }
93 |
94 | RCT_EXPORT_METHOD(setMediationService:(NSString *)mediationService)
95 | {
96 | [FBAdSettings setMediationService:mediationService];
97 | _mediationService = mediationService;
98 | }
99 |
100 | RCT_EXPORT_METHOD(setUrlPrefix:(NSString *)urlPrefix)
101 | {
102 | [FBAdSettings setUrlPrefix:urlPrefix];
103 | _urlPrefix = urlPrefix;
104 | }
105 |
106 |
107 | RCT_EXPORT_METHOD(getTrackingStatus:(RCTPromiseResolveBlock)resolve rejector:(RCTPromiseRejectBlock)reject)
108 | {
109 | if (@available(iOS 14, *)) {
110 | resolve([EXAdSettingsManager convertTrackingStatusToString:[ATTrackingManager trackingAuthorizationStatus]]);
111 | } else {
112 | resolve(@"unavailable");
113 | }
114 | }
115 |
116 | RCT_EXPORT_METHOD(requestTrackingPermission:(RCTPromiseResolveBlock)resolve rejector:(RCTPromiseRejectBlock)reject)
117 | {
118 | if (@available(iOS 14, *)) {
119 | [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
120 | resolve([EXAdSettingsManager convertTrackingStatusToString:status]);
121 | }];
122 | } else {
123 | resolve(@"unavailable");
124 | }
125 | }
126 |
127 | RCT_EXPORT_METHOD(setAdvertiserIDCollectionEnabled:(BOOL)enabled)
128 | {
129 | [FBSDKSettings setAdvertiserIDCollectionEnabled:enabled];
130 | }
131 |
132 |
133 | RCT_EXPORT_METHOD(setAdvertiserTrackingEnabled:(BOOL)enabled)
134 | {
135 | [FBAdSettings setAdvertiserTrackingEnabled:enabled];
136 | }
137 |
138 |
139 | - (void)bridgeDidForeground:(NSNotification *)notification
140 | {
141 | [FBAdSettings setMixedAudience:_isChildDirected];
142 | [FBAdSettings setMediationService:_mediationService];
143 | [FBAdSettings setUrlPrefix:_urlPrefix];
144 | [FBAdSettings setLogLevel:_logLevel];
145 | [FBAdSettings addTestDevices:_testDevices];
146 | }
147 |
148 | - (void)bridgeDidBackground:(NSNotification *)notification
149 | {
150 | [FBAdSettings setMixedAudience:NO];
151 | [FBAdSettings setMediationService:@""];
152 | [FBAdSettings setUrlPrefix:@""];
153 | [FBAdSettings setLogLevel:FBAdLogLevelLog];
154 | [FBAdSettings clearTestDevices];
155 | }
156 |
157 | - (void)dealloc
158 | {
159 | [[NSNotificationCenter defaultCenter] removeObserver:self];
160 | }
161 |
162 | - (NSDictionary *)constantsToExport
163 | {
164 | return @{ @"currentDeviceHash": [FBAdSettings testDeviceHash] };
165 | }
166 |
167 | + (NSString *) convertTrackingStatusToString:(ATTrackingManagerAuthorizationStatus) status API_AVAILABLE(ios(14)) {
168 | switch (status) {
169 | case ATTrackingManagerAuthorizationStatusDenied:
170 | return @"denied";
171 | case ATTrackingManagerAuthorizationStatusAuthorized:
172 | return @"authorized";
173 | case ATTrackingManagerAuthorizationStatusRestricted:
174 | return @"restricted";
175 | case ATTrackingManagerAuthorizationStatusNotDetermined:
176 | return @"not-determined";
177 | }
178 | }
179 |
180 | @end
181 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXBannerView.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface EXBannerView : RCTView
5 |
6 | @property (nonatomic, copy) RCTBubblingEventBlock onAdPress;
7 | @property (nonatomic, copy) RCTBubblingEventBlock onAdError;
8 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoad;
9 |
10 | @property (nonatomic, strong) NSNumber *size;
11 | @property (nonatomic, strong) NSString *placementId;
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXBannerView.m:
--------------------------------------------------------------------------------
1 | #import "EXBannerView.h"
2 |
3 | #import
4 | #import
5 |
6 | @interface EXBannerView ()
7 |
8 | @property (nonatomic, strong) FBAdView *adView;
9 |
10 | @end
11 |
12 | @implementation EXBannerView
13 |
14 | - (void)setSize:(NSNumber *)size
15 | {
16 | _size = size;
17 | [self createViewIfCan];
18 | }
19 |
20 | - (void)setPlacementId:(NSString *)placementId
21 | {
22 | _placementId = placementId;
23 | [self createViewIfCan];
24 | }
25 |
26 | // Initialise BannerAdView as soon as all the props are set
27 | - (void)createViewIfCan
28 | {
29 | if (!_placementId || !_size) {
30 | return;
31 | }
32 |
33 | if (_adView) {
34 | [_adView removeFromSuperview];
35 | }
36 |
37 | FBAdSize fbAdSize = [self fbAdSizeForHeight:_size];
38 |
39 | FBAdView *adView = [[FBAdView alloc] initWithPlacementID:_placementId
40 | adSize:fbAdSize
41 | rootViewController:RCTPresentedViewController()];
42 |
43 | adView.frame = CGRectMake(0, 0, adView.bounds.size.width, adView.bounds.size.height);
44 | // adView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
45 | adView.delegate = self;
46 |
47 | [adView loadAd];
48 |
49 | [self addSubview:adView];
50 |
51 | _adView = adView;
52 | }
53 |
54 | - (FBAdSize)fbAdSizeForHeight:(NSNumber *)height
55 | {
56 | switch ([height intValue]) {
57 | case 90:
58 | return kFBAdSizeHeight90Banner;
59 | case 50:
60 | default:
61 | return kFBAdSizeHeight50Banner;
62 | }
63 | }
64 |
65 | # pragma mark - FBAdViewDelegate
66 |
67 | - (void)adViewDidClick:(FBAdView *)adView
68 | {
69 | if (_onAdPress) {
70 | _onAdPress(nil);
71 | }
72 | }
73 |
74 | - (void)adView:(FBAdView *)adView didFailWithError:(NSError *)error
75 | {
76 | if (_onAdError) {
77 | _onAdError(RCTJSErrorFromNSError(error));
78 | } else {
79 | RCTMakeAndLogError(error.localizedDescription, nil, error.userInfo);
80 | }
81 | }
82 |
83 | - (void)adViewDidLoad:(FBAdView *)adView
84 | {
85 | NSLog(@"Ad was loaded and ready to be displayed");
86 |
87 | if (_onAdLoad) {
88 | _onAdLoad(nil);
89 | }
90 | }
91 |
92 |
93 | - (void)adViewDidFinishHandlingClick:(FBAdView *)adView {}
94 | - (void)adViewWillLogImpression:(FBAdView *)adView {}
95 |
96 | @end
97 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXBannerViewManager.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface EXBannerViewManager : RCTViewManager
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXBannerViewManager.m:
--------------------------------------------------------------------------------
1 | #import "EXBannerViewManager.h"
2 | #import "EXBannerView.h"
3 |
4 | @implementation EXBannerViewManager
5 |
6 | RCT_EXPORT_MODULE(CTKBannerViewManager)
7 |
8 | @synthesize bridge = _bridge;
9 |
10 | - (UIView *)view
11 | {
12 | // if (![EXFacebook facebookAppIdFromNSBundle]) {
13 | // RCTLogWarn(@"No Facebook app id is specified. Facebook ads may have undefined behavior.");
14 | // }
15 | return [EXBannerView new];
16 | }
17 |
18 | RCT_EXPORT_VIEW_PROPERTY(size, NSNumber)
19 | RCT_EXPORT_VIEW_PROPERTY(placementId, NSString)
20 | RCT_EXPORT_VIEW_PROPERTY(onAdLoad, RCTBubblingEventBlock)
21 | RCT_EXPORT_VIEW_PROPERTY(onAdPress, RCTBubblingEventBlock)
22 | RCT_EXPORT_VIEW_PROPERTY(onAdError, RCTBubblingEventBlock)
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXInterstitialAdManager.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface EXInterstitialAdManager : NSObject
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXInterstitialAdManager.m:
--------------------------------------------------------------------------------
1 | #import "EXInterstitialAdManager.h"
2 | #import "EXUnversioned.h"
3 |
4 | #import
5 | #import
6 | #import
7 |
8 | @interface EXInterstitialAdManager ()
9 |
10 | @property (nonatomic, strong) RCTPromiseResolveBlock resolve;
11 | @property (nonatomic, strong) RCTPromiseRejectBlock reject;
12 | @property (nonatomic, strong) FBInterstitialAd *interstitialAd;
13 | @property (nonatomic, strong) UIViewController *adViewController;
14 | @property (nonatomic) bool didClick;
15 | @property (nonatomic) bool didLoad;
16 | @property (nonatomic) bool showWhenLoaded;
17 | @property (nonatomic) bool isBackground;
18 |
19 | @end
20 |
21 | @implementation EXInterstitialAdManager
22 |
23 | @synthesize bridge = _bridge;
24 |
25 | RCT_EXPORT_MODULE(CTKInterstitialAdManager)
26 |
27 | - (void)setBridge:(RCTBridge *)bridge
28 | {
29 | _bridge = bridge;
30 |
31 | [[NSNotificationCenter defaultCenter] addObserver:self
32 | selector:@selector(bridgeDidForeground:)
33 | name:EX_UNVERSIONED(@"EXKernelBridgeDidForegroundNotification")
34 | object:self.bridge];
35 |
36 | [[NSNotificationCenter defaultCenter] addObserver:self
37 | selector:@selector(bridgeDidBackground:)
38 | name:EX_UNVERSIONED(@"EXKernelBridgeDidBackgroundNotification")
39 | object:self.bridge];
40 | }
41 |
42 | RCT_EXPORT_METHOD(
43 | showAd:(NSString *)placementId
44 | resolver:(RCTPromiseResolveBlock)resolve
45 | rejecter:(RCTPromiseRejectBlock)reject
46 | )
47 | {
48 | RCTAssert(_resolve == nil && _reject == nil, @"Only one `showAd` can be called at once");
49 | RCTAssert(_isBackground == false, @"`showAd` can be called only when experience is running in foreground");
50 | // if (![EXFacebook facebookAppIdFromNSBundle]) {
51 | // RCTLogWarn(@"No Facebook app id is specified. Facebook ads may have undefined behavior.");
52 | // }
53 |
54 | _resolve = resolve;
55 | _reject = reject;
56 |
57 | _interstitialAd = [[FBInterstitialAd alloc] initWithPlacementID:placementId];
58 | _interstitialAd.delegate = self;
59 | _showWhenLoaded = true;
60 | // [EXUtil performSynchronouslyOnMainThread:^{
61 | [self->_interstitialAd loadAd];
62 | // }];
63 | }
64 |
65 |
66 | RCT_EXPORT_METHOD(
67 | preloadAd:(NSString *)placementId
68 | resolver:(RCTPromiseResolveBlock)resolve
69 | rejecter:(RCTPromiseRejectBlock)reject
70 | )
71 | {
72 | RCTAssert(_resolve == nil && _reject == nil, @"Only one `preloadAd` can be called at once");
73 | RCTAssert(_isBackground == false, @"`preloadAd` can be called only when experience is running in foreground");
74 |
75 | _resolve = resolve;
76 | _reject = reject;
77 |
78 | _interstitialAd = [[FBInterstitialAd alloc] initWithPlacementID:placementId];
79 | _interstitialAd.delegate = self;
80 | _showWhenLoaded = false;
81 | [self->_interstitialAd loadAd];
82 | }
83 |
84 | RCT_EXPORT_METHOD(
85 | showPreloadedAd:(NSString *)placementId
86 | resolver:(RCTPromiseResolveBlock)resolve
87 | rejecter:(RCTPromiseRejectBlock)reject
88 | ) {
89 | // If already loaded, show it
90 | if(_didLoad) {
91 | dispatch_async(dispatch_get_main_queue(), ^{
92 | [_interstitialAd showAdFromRootViewController:RCTPresentedViewController()];
93 | });
94 | } else {
95 | // If not make sure its shown asap
96 | _showWhenLoaded = true;
97 | }
98 | resolve(nil);
99 | }
100 |
101 | #pragma mark - FBInterstitialAdDelegate
102 |
103 | - (void)interstitialAdDidLoad:(__unused FBInterstitialAd *)interstitialAd
104 | {
105 | _didLoad = true;
106 | if (_showWhenLoaded) {
107 | [_interstitialAd showAdFromRootViewController:RCTPresentedViewController()];
108 | }
109 |
110 | }
111 |
112 | - (void)interstitialAd:(FBInterstitialAd *)interstitialAd didFailWithError:(NSError *)error
113 | {
114 | _reject(@"E_FAILED_TO_LOAD", [error localizedDescription], error);
115 |
116 | [self cleanUpAd];
117 | }
118 |
119 | - (void)interstitialAdDidClick:(FBInterstitialAd *)interstitialAd
120 | {
121 | _didClick = true;
122 | }
123 |
124 | - (void)interstitialAdDidClose:(FBInterstitialAd *)interstitialAd
125 | {
126 | _resolve(@(_didClick));
127 |
128 | [self cleanUpAd];
129 | }
130 |
131 | - (void)bridgeDidForeground:(NSNotification *)notification
132 | {
133 | _isBackground = false;
134 |
135 | if (_adViewController) {
136 | [RCTPresentedViewController() presentViewController:_adViewController animated:NO completion:nil];
137 | _adViewController = nil;
138 | }
139 | }
140 |
141 | - (void)bridgeDidBackground:(NSNotification *)notification
142 | {
143 | _isBackground = true;
144 |
145 | if (_interstitialAd) {
146 | _adViewController = RCTPresentedViewController();
147 | [_adViewController dismissViewControllerAnimated:NO completion:nil];
148 | }
149 | }
150 |
151 | - (void)cleanUpAd
152 | {
153 | _reject = nil;
154 | _resolve = nil;
155 | _interstitialAd = nil;
156 | _adViewController = nil;
157 | _didClick = false;
158 | _didLoad = false;
159 | _showWhenLoaded = false;
160 | }
161 |
162 | @end
163 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeAdEmitter.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface EXNativeAdEmitter : RCTEventEmitter
4 |
5 | - (void)sendManagersState:(NSDictionary *)adManagersState;
6 | - (void)sendError:(NSString *)error;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeAdEmitter.m:
--------------------------------------------------------------------------------
1 | #import "EXNativeAdEmitter.h"
2 |
3 | @implementation EXNativeAdEmitter
4 |
5 | RCT_EXPORT_MODULE(CTKNativeAdEmitter)
6 |
7 | - (NSArray *)supportedEvents
8 | {
9 | return @[@"CTKNativeAdsManagersChanged", @"onAdError"];
10 | }
11 |
12 | - (void)sendManagersState:(NSDictionary *)adManagersState {
13 | [self sendEventWithName:@"CTKNativeAdsManagersChanged" body:adManagersState];
14 | }
15 |
16 | - (void)sendError:(NSString *)error {
17 | [self sendEventWithName:@"onAdError" body:error];
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeAdManager.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface EXNativeAdManager : RCTViewManager
5 |
6 | - (FBNativeAdsManager *) getFBAdsManager:(NSString *)placementId;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeAdManager.m:
--------------------------------------------------------------------------------
1 | #import "EXNativeAdManager.h"
2 | #import "EXNativeAdView.h"
3 | #import "EXNativeAdEmitter.h"
4 |
5 | #import
6 | #import
7 | #import
8 | #import
9 | #import
10 | #import
11 |
12 | @implementation RCTConvert (EXNativeAdView)
13 |
14 | RCT_ENUM_CONVERTER(FBNativeAdsCachePolicy, (@{
15 | @"none": @(FBNativeAdsCachePolicyNone),
16 | @"all": @(FBNativeAdsCachePolicyAll),
17 | }), FBNativeAdsCachePolicyNone, integerValue)
18 |
19 | @end
20 |
21 | @interface EXNativeAdManager ()
22 |
23 | @property (nonatomic, strong) NSMutableDictionary *adsManagers;
24 | @property (nonatomic, strong) NSString *myAdChoiceViewPlacementId;
25 |
26 | @end
27 |
28 | @implementation EXNativeAdManager
29 |
30 | RCT_EXPORT_MODULE(CTKNativeAdManager)
31 |
32 | @synthesize bridge = _bridge;
33 |
34 | - (instancetype)init
35 | {
36 | self = [super init];
37 | if (self) {
38 | _adsManagers = [NSMutableDictionary new];
39 | }
40 | return self;
41 | }
42 |
43 | + (BOOL)requiresMainQueueSetup
44 | {
45 | return NO;
46 | }
47 |
48 | RCT_EXPORT_METHOD(registerViewsForInteraction:(nonnull NSNumber *)nativeAdViewTag
49 | mediaViewTag:(nonnull NSNumber *)mediaViewTag
50 | adIconViewTag:(nonnull NSNumber *)adIconViewTag
51 | clickableViewsTags:(nonnull NSArray *)tags
52 | resolve:(RCTPromiseResolveBlock)resolve
53 | reject:(RCTPromiseRejectBlock)reject)
54 | {
55 | [_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
56 | FBMediaView *mediaView = nil;
57 | FBMediaView *adIconView = nil;
58 | EXNativeAdView *nativeAdView = nil;
59 |
60 | if ([viewRegistry objectForKey:mediaViewTag] == nil) {
61 | reject(@"E_NO_VIEW_FOR_TAG", @"Could not find mediaView", nil);
62 | return;
63 | }
64 |
65 | if ([viewRegistry objectForKey:nativeAdViewTag] == nil) {
66 | reject(@"E_NO_NATIVEAD_VIEW", @"Could not find nativeAdView", nil);
67 | return;
68 | }
69 |
70 | if ([[viewRegistry objectForKey:mediaViewTag] isKindOfClass:[FBMediaView class]]) {
71 | mediaView = (FBMediaView *)[viewRegistry objectForKey:mediaViewTag];
72 | } else {
73 | reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed media view tag is not an instance of FBMediaView", nil);
74 | return;
75 | }
76 |
77 | if ([[viewRegistry objectForKey:nativeAdViewTag] isKindOfClass:[EXNativeAdView class]]) {
78 | nativeAdView = (EXNativeAdView *)[viewRegistry objectForKey:nativeAdViewTag];
79 | } else {
80 | reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed native ad view tag is not an instance of EXNativeAdView", nil);
81 | return;
82 | }
83 |
84 | if ([viewRegistry objectForKey:adIconViewTag]) {
85 | if ([[viewRegistry objectForKey:adIconViewTag] isKindOfClass:[FBMediaView class]]) {
86 | adIconView = (FBMediaView *)[viewRegistry objectForKey:adIconViewTag];
87 | } else {
88 | reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed ad icon view tag is not an instance of FBMediaView", nil);
89 | return;
90 | }
91 | }
92 |
93 | NSMutableArray *clickableViews = [NSMutableArray new];
94 | for (id tag in tags) {
95 | if ([viewRegistry objectForKey:tag]) {
96 | [clickableViews addObject:[viewRegistry objectForKey:tag]];
97 | } else {
98 | reject(@"E_INVALID_VIEW_TAG", [NSString stringWithFormat:@"Could not find view for tag: %@", [tag stringValue]], nil);
99 | return;
100 | }
101 | }
102 |
103 | [nativeAdView registerViewsForInteraction:mediaView adIcon:adIconView clickableViews:clickableViews];
104 | resolve(@[]);
105 | }];
106 | }
107 |
108 | RCT_EXPORT_METHOD(init:(NSString *)placementId withAdsToRequest:(nonnull NSNumber *)adsToRequest)
109 | {
110 | FBNativeAdsManager *adsManager = [[FBNativeAdsManager alloc] initWithPlacementID:placementId
111 | forNumAdsRequested:[adsToRequest intValue]];
112 | _myAdChoiceViewPlacementId = placementId;
113 | [adsManager setDelegate:self];
114 |
115 | dispatch_async(dispatch_get_main_queue(), ^{
116 | [adsManager loadAds];
117 | [self->_adsManagers setValue:adsManager forKey:placementId];
118 | });
119 | }
120 |
121 | RCT_EXPORT_METHOD(setMediaCachePolicy:(NSString*)placementId cachePolicy:(FBNativeAdsCachePolicy)cachePolicy)
122 | {
123 | [_adsManagers[placementId] setMediaCachePolicy:cachePolicy];
124 | }
125 |
126 | RCT_EXPORT_METHOD(disableAutoRefresh:(NSString*)placementId)
127 | {
128 | [_adsManagers[placementId] disableAutoRefresh];
129 | }
130 |
131 | - (FBNativeAdsManager *) getFBAdsManager:(NSString *)placementId
132 | {
133 | return _adsManagers[placementId];
134 | }
135 |
136 | - (void)nativeAdsLoaded
137 | {
138 | NSMutableDictionary *adsManagersState = [NSMutableDictionary new];
139 |
140 | [_adsManagers enumerateKeysAndObjectsUsingBlock:^(NSString* key, FBNativeAdsManager* adManager, __unused BOOL* stop) {
141 | [adsManagersState setValue:@([adManager isValid]) forKey:key];
142 | }];
143 |
144 | EXNativeAdEmitter *nativeAdEmitter = [_bridge moduleForClass:[EXNativeAdEmitter class]];
145 | [nativeAdEmitter sendManagersState:adsManagersState];
146 | }
147 |
148 | - (void)nativeAdsFailedToLoadWithError:(NSError *)errors
149 | {
150 | EXNativeAdEmitter *nativeAdEmitter = [_bridge moduleForClass:[EXNativeAdEmitter class]];
151 | [nativeAdEmitter sendError:[NSString stringWithFormat:@"%i: %@", [errors code], [errors localizedDescription]]];
152 | }
153 |
154 | - (UIView *)view
155 | {
156 | return [[EXNativeAdView alloc] initWithBridge:_bridge];
157 | }
158 |
159 | RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTBubblingEventBlock)
160 | RCT_CUSTOM_VIEW_PROPERTY(adsManager, NSString, EXNativeAdView)
161 | {
162 | view.nativeAd = [_adsManagers[json] nextNativeAd];
163 | }
164 |
165 | @end
166 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeAdView.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 | #import
5 |
6 | @interface EXNativeAdView : RCTView
7 |
8 | // `onAdLoaded` event called when ad has been loaded
9 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoaded;
10 |
11 | // NativeAd this view has been loaded with
12 | @property (nonatomic, strong) FBNativeAd *nativeAd;
13 |
14 | - (instancetype)initWithBridge:(RCTBridge *)bridge;
15 | - (void)registerViewsForInteraction:(FBMediaView *)mediaView adIcon:(FBMediaView *)adIconView clickableViews:(NSArray *)clickable;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeAdView.m:
--------------------------------------------------------------------------------
1 | #import "EXNativeAdView.h"
2 | #import
3 | #import
4 |
5 | @interface EXNativeAdView ()
6 |
7 | @property (nonatomic, strong) RCTBridge *bridge;
8 |
9 | @end
10 |
11 | @implementation EXNativeAdView
12 |
13 | - (instancetype)initWithBridge:(RCTBridge *)bridge
14 | {
15 | if (self = [super init]) {
16 | _bridge = bridge;
17 | }
18 | return self;
19 | }
20 |
21 | - (void)setOnAdLoaded:(RCTBubblingEventBlock)onAdLoaded
22 | {
23 | _onAdLoaded = onAdLoaded;
24 |
25 | if (_nativeAd != nil) {
26 | [self callOnAdLoadedWithAd:_nativeAd];
27 | }
28 | }
29 |
30 | - (void)setNativeAd:(FBNativeAd *)nativeAd
31 | {
32 | _nativeAd = nativeAd;
33 | [self callOnAdLoadedWithAd:_nativeAd];
34 | }
35 |
36 | - (void)callOnAdLoadedWithAd:(FBNativeAd *)nativeAd
37 | {
38 | if (_onAdLoaded != nil) {
39 | _onAdLoaded(@{
40 | @"advertiserName": nativeAd.advertiserName,
41 | @"sponsoredTranslation": nativeAd.sponsoredTranslation,
42 | @"bodyText": nativeAd.bodyText,
43 | @"socialContext": nativeAd.socialContext,
44 | @"callToActionText": nativeAd.callToAction,
45 | @"translation": nativeAd.adTranslation,
46 | @"linkDescription": nativeAd.linkDescription,
47 | @"promotedTranslation": nativeAd.promotedTranslation,
48 | @"headline": nativeAd.headline,
49 | });
50 | }
51 | }
52 |
53 | - (void)registerViewsForInteraction:(FBMediaView *)mediaView adIcon:(FBMediaView *)adIconView clickableViews:(NSArray *)clickable
54 | {
55 | [_nativeAd registerViewForInteraction:self
56 | mediaView:mediaView
57 | iconView:adIconView
58 | viewController:RCTKeyWindow().rootViewController
59 | clickableViews:clickable];
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeMediaViewManager.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 |
5 | @interface EXNativeMediaViewManager : RCTViewManager
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXNativeMediaViewManager.m:
--------------------------------------------------------------------------------
1 | #import "EXNativeMediaViewManager.h"
2 |
3 | @implementation EXNativeMediaViewManager
4 |
5 | RCT_EXPORT_MODULE(MediaViewManager)
6 |
7 | - (UIView *)view
8 | {
9 | return [[FBMediaView alloc] init];
10 | }
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdsFacebook/EXUnversioned.h:
--------------------------------------------------------------------------------
1 | @import Foundation;
2 |
3 | #define EX_UNVERSIONED(symbol) symbol
4 |
5 | @protocol EXUnversioned
6 |
7 | @end
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-fbads",
3 | "version": "7.1.0",
4 | "description": "Native Facebook Ads for React Native",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/callstack/react-native-fbads"
8 | },
9 | "homepage": "https://github.com/callstack/react-native-fbads",
10 | "main": "dist/lib/index.js",
11 | "typings": "dist/types/index.d.ts",
12 | "directories": {
13 | "example": "example"
14 | },
15 | "scripts": {
16 | "build:plugin": "tsc --build plugin",
17 | "clean:plugin": "expo-module clean plugin",
18 | "lint:plugin": "eslint plugin/src/*",
19 | "prepare": "npm run build:plugin",
20 | "tsc": "tsc --project .",
21 | "lint": "tslint --project ."
22 | },
23 | "author": "Suraj Tiwari ",
24 | "license": "MIT",
25 | "peerDependencies": {
26 | "react-native": "*"
27 | },
28 | "dependencies": {
29 | "@expo/config-plugins": "^4.0.4",
30 | "fbemitter": "^2.1.1"
31 | },
32 | "devDependencies": {
33 | "@types/fbemitter": "^2.0.32",
34 | "@types/react-native": "^0.57.4",
35 | "expo-module-scripts": "^2.0.0",
36 | "tslint": "^5.11.0",
37 | "tslint-config-airbnb": "^5.11.0",
38 | "tslint-config-prettier": "^1.15.0",
39 | "typescript": "^4.5.5"
40 | },
41 | "keywords": [
42 | "react-native",
43 | "facebook",
44 | "Audience Network",
45 | "Native ads"
46 | ],
47 | "files": [
48 | "android",
49 | "ios",
50 | "src",
51 | "LICENSE",
52 | "package.json",
53 | "dist",
54 | "react-native.config.js",
55 | "ReactNativeAdsFacebook.podspec",
56 | "app.plugin.js",
57 | "plugin/build/"
58 | ]
59 | }
60 |
--------------------------------------------------------------------------------
/plugin/src/withReactNativeFbads.ts:
--------------------------------------------------------------------------------
1 | import {
2 | AndroidConfig,
3 | ConfigPlugin,
4 | createRunOncePlugin,
5 | withAndroidManifest,
6 | } from '@expo/config-plugins';
7 | const { getMainApplicationOrThrow, prefixAndroidKeys } = AndroidConfig.Manifest;
8 |
9 | const INTERSTITIAL_AD_ACTIVITY = 'com.facebook.ads.InterstitialAdActivity';
10 |
11 | export const withFacebookManifest: ConfigPlugin = (config) => {
12 | return withAndroidManifest(config, (config) => {
13 | config.modResults = setFacebookConfig(config.modResults);
14 | return config;
15 | });
16 | };
17 |
18 | export function setFacebookConfig(
19 | androidManifest: AndroidConfig.Manifest.AndroidManifest
20 | ) {
21 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
22 | let mainApplication = getMainApplicationOrThrow(androidManifest);
23 | mainApplication = ensureFacebookActivity({ mainApplication });
24 |
25 | return androidManifest;
26 | }
27 |
28 | function ensureFacebookActivity({
29 | mainApplication,
30 | }: {
31 | mainApplication: AndroidConfig.Manifest.ManifestApplication;
32 | }) {
33 | if (Array.isArray(mainApplication.activity)) {
34 | // Remove all Facebook InterstitialAdActivity first
35 | mainApplication.activity = mainApplication.activity.filter((activity) => {
36 | return activity.$?.['android:name'] !== INTERSTITIAL_AD_ACTIVITY;
37 | });
38 | } else {
39 | mainApplication.activity = [];
40 | }
41 |
42 | mainApplication.activity.push(getFacebookAdActivity());
43 | return mainApplication;
44 | }
45 |
46 | function buildXMLItem({
47 | head,
48 | children,
49 | }: {
50 | head: Record;
51 | children?: Record;
52 | }) {
53 | return { ...(children ?? {}), $: head };
54 | }
55 |
56 | function getFacebookAdActivity() {
57 | /**
58 |
62 | */
63 | return buildXMLItem({
64 | head: prefixAndroidKeys({
65 | name: INTERSTITIAL_AD_ACTIVITY,
66 | configChanges: 'keyboardHidden|orientation',
67 | }),
68 | }) as AndroidConfig.Manifest.ManifestActivity;
69 | }
70 |
71 | /**
72 | * Apply react-native-fbads configuration for Expo SDK 44 projects.
73 | */
74 | const withReactNativeFbads: ConfigPlugin = (config) => {
75 | return withFacebookManifest(config);
76 | };
77 |
78 | const pkg = require('react-native-fbads/package.json');
79 |
80 | export default createRunOncePlugin(withReactNativeFbads, pkg.name, pkg.version);
81 |
--------------------------------------------------------------------------------
/plugin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "expo-module-scripts/tsconfig.plugin",
3 | "compilerOptions": {
4 | "outDir": "./build"
5 | },
6 | "include": ["./src"],
7 | "exclude": ["**/__mocks__/*", "**/__tests__/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/react-native.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | dependency: {
3 | platforms: {
4 | android: {
5 | sourceDir: 'android/app',
6 | },
7 | },
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/src/AdSettings.ts:
--------------------------------------------------------------------------------
1 | import { NativeModules, Platform } from 'react-native';
2 |
3 | const { CTKAdSettingsManager } = NativeModules;
4 |
5 | type SDKLogLevel =
6 | | 'none'
7 | | 'debug'
8 | | 'verbose'
9 | | 'warning'
10 | | 'error'
11 | | 'notification';
12 |
13 | export type TrackingStatus =
14 | | 'unavailable'
15 | | 'denied'
16 | | 'authorized'
17 | | 'restricted'
18 | | 'not-determined';
19 |
20 | export default {
21 | /**
22 | * Contains hash of the device id
23 | */
24 | get currentDeviceHash(): string {
25 | return CTKAdSettingsManager.currentDeviceHash;
26 | },
27 |
28 | /**
29 | * Registers given device with `deviceHash` to receive test Facebook ads.
30 | */
31 | addTestDevice(deviceHash: string) {
32 | CTKAdSettingsManager.addTestDevice(deviceHash);
33 | },
34 | /**
35 | * Clears previously set test devices
36 | */
37 | clearTestDevices() {
38 | CTKAdSettingsManager.clearTestDevices();
39 | },
40 | /**
41 | * Sets current SDK log level
42 | */
43 | setLogLevel(logLevel: SDKLogLevel) {
44 | CTKAdSettingsManager.setLogLevel(logLevel);
45 | },
46 | /**
47 | * Specifies whether ads are treated as child-directed
48 | */
49 | setIsChildDirected(isDirected: boolean) {
50 | CTKAdSettingsManager.setIsChildDirected(isDirected);
51 | },
52 | /**
53 | * Sets mediation service name
54 | */
55 | setMediationService(mediationService: string) {
56 | CTKAdSettingsManager.setMediationService(mediationService);
57 | },
58 | /**
59 | * Sets URL prefix
60 | */
61 | setUrlPrefix(urlPrefix: string) {
62 | CTKAdSettingsManager.setUrlPrefix(urlPrefix);
63 | },
64 |
65 | /**
66 | * Requests permission to track the user.
67 | *
68 | * Requires a [`NSUserTrackingUsageDescription`](https://developer.apple.com/documentation/bundleresources/information_property_list/nsusertrackingusagedescription) in your `Info.plist`
69 | *
70 | * @platform iOS 14
71 | */
72 | async requestTrackingPermission(): Promise {
73 | if (Platform.OS !== 'ios') return 'unavailable';
74 | return await CTKAdSettingsManager.requestTrackingPermission();
75 | },
76 | /**
77 | * Gets the current tracking status.
78 | *
79 | * @platform iOS 14
80 | */
81 | async getTrackingStatus(): Promise {
82 | if (Platform.OS !== 'ios') return 'unavailable';
83 | return await CTKAdSettingsManager.getTrackingStatus();
84 | },
85 |
86 | /**
87 | * Enable or disable the automatic Advertiser ID Collection. On iOS 14 it is recommended to only enable automatic Advertiser ID Collection when the user has granted permission to track. (@see `requestTrackingPermission()`)
88 | */
89 | setAdvertiserIDCollectionEnabled(enabled: boolean): void {
90 | CTKAdSettingsManager.setAdvertiserIDCollectionEnabled(enabled);
91 | },
92 |
93 | /**
94 | * Enable or disable ads tracking. Only works for iOS 14+. In order to ask user for tracking permission (@see `requestTrackingPermission()`).
95 | */
96 | setAdvertiserTrackingEnabled(enabled: boolean): void {
97 | if (Platform.OS !== 'ios') {
98 | return;
99 | }
100 | CTKAdSettingsManager.setAdvertiserTrackingEnabled(enabled);
101 | },
102 | };
103 |
--------------------------------------------------------------------------------
/src/BannerViewManager.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { requireNativeComponent, StyleProp, ViewStyle } from 'react-native';
3 |
4 | type AdType = 'large' | 'standard';
5 |
6 | interface NativeBannerViewProps {
7 | size: number;
8 | onAdPress: Function;
9 | onAdError: Function;
10 | onAdLoad: Function;
11 | style: StyleProp;
12 | placementId: string;
13 | }
14 |
15 | interface BannerViewProps {
16 | type: AdType;
17 | placementId: string;
18 | onPress: Function;
19 | onError: Function;
20 | onLoad: Function;
21 | style: StyleProp;
22 | }
23 |
24 | // tslint:disable-next-line:variable-name
25 | const CTKBannerView = requireNativeComponent(
26 | 'CTKBannerView'
27 | );
28 |
29 | const sizeForType: Record = {
30 | large: 90,
31 | standard: 50,
32 | };
33 |
34 | const getSizeForType = (type: AdType) => sizeForType[type];
35 |
36 | // tslint:disable-next-line:variable-name
37 | const BannerView = (props: BannerViewProps) => {
38 | const { type, onPress, onError, onLoad, style, ...restProps } = props;
39 | const size = getSizeForType(type);
40 |
41 | return (
42 |
50 | );
51 | };
52 |
53 | export default BannerView;
54 |
--------------------------------------------------------------------------------
/src/InterstitialAdManager.ts:
--------------------------------------------------------------------------------
1 | import { NativeModules } from 'react-native';
2 |
3 | const { CTKInterstitialAdManager } = NativeModules;
4 |
5 | export default {
6 | /**
7 | * Load interstitial ad for a given placementId and shows it
8 | */
9 | showAd(placementId: string): Promise {
10 | return CTKInterstitialAdManager.showAd(placementId);
11 | },
12 |
13 | /**
14 | * Preloads an interstitial ad for a given placementId
15 | */
16 | preloadAd(placementId: string): Promise {
17 | return CTKInterstitialAdManager.preloadAd(placementId);
18 | },
19 |
20 | /**
21 | * Shows an already preloaded Ad
22 | */
23 | showPreloadedAd(placementId: string): Promise {
24 | return CTKInterstitialAdManager.showPreloadedAd(placementId);
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { default as withNativeAd } from './native-ads/withNativeAd';
2 | export { default as AdSettings } from './AdSettings';
3 | export { default as NativeAdsManager } from './native-ads/NativeAdsManager';
4 | export { default as InterstitialAdManager } from './InterstitialAdManager';
5 | export { default as BannerView } from './BannerViewManager';
6 | export { default as MediaView } from './native-ads/MediaViewManager';
7 | export { default as AdIconView } from './native-ads/AdIconViewManager';
8 | export { default as TriggerableView } from './native-ads/TriggerableView';
9 | export { default as AdChoicesView } from './native-ads/AdChoicesManager';
10 | export * from './native-ads/nativeAd';
11 |
--------------------------------------------------------------------------------
/src/native-ads/AdChoicesManager.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | StyleProp,
4 | ViewStyle,
5 | requireNativeComponent,
6 | StyleSheet,
7 | Platform
8 | } from 'react-native';
9 |
10 | import {
11 | AdChoicesViewContext,
12 | AdChoicesViewContextValueType
13 | } from './contexts';
14 |
15 | interface AdChoicesProps {
16 | location?: AdChoiceLocation;
17 | expandable?: boolean;
18 | style?: StyleProp;
19 | }
20 |
21 | // tslint:disable-next-line:variable-name
22 | const NativeAdChoicesView = requireNativeComponent<
23 | AdChoicesProps & { placementId: string }
24 | >('AdChoicesView');
25 |
26 | type AdChoiceLocation = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
27 |
28 | export default class AdChoicesView extends React.Component {
29 | static defaultProps: AdChoicesProps = {
30 | location: 'topLeft',
31 | expandable: false
32 | };
33 |
34 | render() {
35 | return (
36 |
37 | {(placementId: AdChoicesViewContextValueType) => (
38 |
44 | )}
45 |
46 | );
47 | }
48 | }
49 |
50 | const styles = StyleSheet.create({
51 | adChoice: {
52 | backgroundColor: 'transparent',
53 | ...Platform.select({
54 | ios: {
55 | width: 0,
56 | height: 0
57 | },
58 | android: {
59 | width: 22,
60 | height: 22
61 | }
62 | })
63 | }
64 | });
65 |
--------------------------------------------------------------------------------
/src/native-ads/AdIconViewManager.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { requireNativeComponent, ViewProps } from 'react-native';
3 |
4 | import {
5 | AdIconViewContext,
6 | AdIconViewContextValueType,
7 | ComponentOrClass
8 | } from './contexts';
9 | import { NativeAd } from './nativeAd';
10 |
11 | export type AdIconViewProps = ViewProps;
12 |
13 | // tslint:disable-next-line:variable-name
14 | export const NativeAdIconView = requireNativeComponent(
15 | 'AdIconView'
16 | );
17 |
18 | class AdIconViewChild extends React.Component<
19 | AdIconViewProps & AdIconViewContextValueType
20 | > {
21 | private iconView: ComponentOrClass | null = null;
22 |
23 | private handleAdIconViewRef = (ref: ComponentOrClass | null) => {
24 | if (this.iconView) {
25 | this.props.unregister();
26 | this.iconView = null;
27 | }
28 |
29 | if (ref) {
30 | this.props.register(ref);
31 | this.iconView = ref;
32 | }
33 | };
34 |
35 | render() {
36 | return ;
37 | }
38 | }
39 |
40 | export default class AdIconView extends React.Component {
41 | render() {
42 | return (
43 |
44 | {(contextValue: AdIconViewContextValueType) => (
45 |
46 | )}
47 |
48 | );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/native-ads/MediaViewManager.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { requireNativeComponent, ViewProps } from 'react-native';
3 | import {
4 | ComponentOrClass,
5 | MediaViewContext,
6 | MediaViewContextValueType
7 | } from './contexts';
8 |
9 | export type MediaViewProps = ViewProps;
10 |
11 | // tslint:disable-next-line:variable-name
12 | export const NativeMediaView = requireNativeComponent(
13 | 'MediaView'
14 | );
15 |
16 | class MediaViewChild extends React.Component<
17 | MediaViewProps & MediaViewContextValueType
18 | > {
19 | private mediaView: ComponentOrClass | null = null;
20 |
21 | private handleMediaViewMount = (ref: ComponentOrClass | null) => {
22 | if (this.mediaView) {
23 | this.props.unregister();
24 | this.mediaView = null;
25 | }
26 |
27 | if (ref) {
28 | this.props.register(ref);
29 | this.mediaView = ref;
30 | }
31 | };
32 |
33 | render() {
34 | return ;
35 | }
36 | }
37 |
38 | export default class MediaView extends React.Component {
39 | render() {
40 | return (
41 |
42 | {(contextValue: MediaViewContextValueType) => (
43 |
44 | )}
45 |
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/native-ads/NativeAdsManager.ts:
--------------------------------------------------------------------------------
1 | import { NativeModules, NativeEventEmitter } from 'react-native';
2 | import { EventEmitter, EventSubscription } from 'fbemitter';
3 |
4 | const { CTKNativeAdManager, CTKNativeAdEmitter } = NativeModules;
5 |
6 | const nativeAdEmitter = new NativeEventEmitter(CTKNativeAdEmitter);
7 |
8 | const EVENT_DID_BECOME_VALID = 'AdsManagerDidBecomeValid';
9 | const EVENT_DID_BECOME_INVALID = 'AdsManagerDidBecomeInvalid';
10 |
11 | type AdManagerCachePolicy = 'none' | 'icon' | 'image' | 'all';
12 |
13 | export default class NativeAdsManager {
14 | private placementId: string;
15 |
16 | // Indicates whether AdsManager is ready to serve ads
17 | private isValid: boolean = false;
18 | private eventEmitter: EventEmitter = new EventEmitter();
19 |
20 | static async registerViewsForInteractionAsync(
21 | nativeAdViewTag: number,
22 | mediaViewTag: number,
23 | adIconViewTag: number,
24 | clickable: number[]
25 | ) {
26 | if (adIconViewTag > 0 && mediaViewTag > 0) {
27 | clickable.push(mediaViewTag, adIconViewTag);
28 | } else if (mediaViewTag > 0) {
29 | clickable.push(mediaViewTag);
30 | } else if (adIconViewTag > 0) {
31 | clickable.push(adIconViewTag);
32 | }
33 | const result = await CTKNativeAdManager.registerViewsForInteraction(
34 | nativeAdViewTag,
35 | mediaViewTag,
36 | adIconViewTag,
37 | clickable
38 | );
39 | return result;
40 | }
41 |
42 | /**
43 | * Creates an instance of AdsManager with a given placementId and adsToRequest.
44 | * Default number of ads to request is `10`.
45 | *
46 | * AdsManager will become loading ads immediately
47 | */
48 | constructor(placementId: string, adsToRequest: number = 10) {
49 | this.placementId = placementId;
50 |
51 | this.listenForStateChanges();
52 | this.listenForErrors();
53 |
54 | CTKNativeAdManager.init(placementId, adsToRequest);
55 | }
56 |
57 | /**
58 | * Listens for AdManager state changes and updates internal state. When it changes,
59 | * callers will be notified of a change
60 | */
61 | private listenForStateChanges() {
62 | nativeAdEmitter.addListener(
63 | 'CTKNativeAdsManagersChanged',
64 | (managers: Record) => {
65 | const isValidNow = managers[this.placementId];
66 |
67 | if (this.isValid !== isValidNow && isValidNow) {
68 | this.isValid = true;
69 | this.eventEmitter.emit(EVENT_DID_BECOME_VALID);
70 | }
71 | }
72 | );
73 | }
74 |
75 | /**
76 | * Listens for AdManager errors. When error occures,
77 | * callers will be notified of it
78 | */
79 | private listenForErrors() {
80 | nativeAdEmitter.addListener('onAdError', (error: string) => {
81 | this.isValid = false;
82 | this.eventEmitter.emit(EVENT_DID_BECOME_INVALID, error);
83 | });
84 | }
85 |
86 | /**
87 | * Used to listening for state changes
88 | *
89 | * If manager already became valid, it will call the function w/o registering
90 | * handler for events
91 | */
92 | onAdsLoaded(func: Function): EventSubscription {
93 | if (this.isValid) {
94 | setTimeout(func);
95 | return {
96 | context: null,
97 | listener: () => {},
98 | remove: () => {}
99 | };
100 | }
101 |
102 | return this.eventEmitter.once(EVENT_DID_BECOME_VALID, func);
103 | }
104 |
105 | /**
106 | * Used to listening for errors from this native ad manager
107 | */
108 | onAdsError(func: Function): EventSubscription {
109 | return this.eventEmitter.once(EVENT_DID_BECOME_INVALID, func);
110 | }
111 |
112 | /**
113 | * Disables auto refreshing for this native ad manager
114 | */
115 | disableAutoRefresh() {
116 | CTKNativeAdManager.disableAutoRefresh(this.placementId);
117 | }
118 |
119 | /**
120 | * Set the native ads manager caching policy. This controls which media from
121 | * the native ads are cached before the onAdsLoaded is called.
122 | * The default is to not block on caching.
123 | */
124 | setMediaCachePolicy(cachePolicy: AdManagerCachePolicy) {
125 | CTKNativeAdManager.setMediaCachePolicy(this.placementId, cachePolicy);
126 | }
127 |
128 | toJSON() {
129 | return this.placementId;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/native-ads/TriggerableView.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Text, TextProps, View } from 'react-native';
3 | import { TriggerableContext, TriggerableContextValueType } from './contexts';
4 |
5 | class TriggerableViewChild extends React.Component<
6 | TextProps & TriggerableContextValueType
7 | > {
8 | private wrapperRef: View | null = null;
9 |
10 | private handleWrapperRef = (ref: View) => {
11 | if (this.wrapperRef) {
12 | this.props.unregister(this.wrapperRef);
13 | this.wrapperRef = null;
14 | }
15 |
16 | if (ref) {
17 | this.props.register(ref);
18 | this.wrapperRef = ref;
19 | }
20 | };
21 |
22 | render() {
23 | return ;
24 | }
25 | }
26 |
27 | export default class TriggerableView extends React.Component {
28 | render() {
29 | return (
30 |
31 | {(contextValue: TriggerableContextValueType) => (
32 |
33 | )}
34 |
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/native-ads/contexts.ts:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react';
2 |
3 | export type ComponentOrClass = React.ComponentClass | React.Component;
4 |
5 | type Receiver = (c: ComponentOrClass) => void;
6 | export interface MultipleRegisterablesContextValueType {
7 | unregister: Receiver;
8 | register: Receiver;
9 | }
10 |
11 | export interface RegisterableContextValueType {
12 | register: Receiver;
13 | unregister: () => void;
14 | }
15 |
16 | export type TriggerableContextValueType = MultipleRegisterablesContextValueType;
17 | export type AdIconViewContextValueType = RegisterableContextValueType;
18 | export type MediaViewContextValueType = RegisterableContextValueType;
19 | export type AdChoicesViewContextValueType = string;
20 |
21 | const defaultValue = {
22 | register: () => {
23 | throw new Error('Stub!');
24 | },
25 | unregister: () => {
26 | throw new Error('Stub!');
27 | }
28 | };
29 |
30 | // tslint:disable-next-line:variable-name
31 | export const TriggerableContext = React.createContext<
32 | TriggerableContextValueType
33 | >(defaultValue);
34 | // tslint:disable-next-line:variable-name
35 | export const MediaViewContext = React.createContext(
36 | defaultValue
37 | );
38 |
39 | // tslint:disable-next-line:variable-name
40 | export const AdIconViewContext = React.createContext<
41 | AdIconViewContextValueType
42 | >(defaultValue);
43 |
44 | // tslint:disable-next-line:variable-name
45 | export const AdChoicesViewContext = React.createContext<
46 | AdChoicesViewContextValueType
47 | >('');
48 |
--------------------------------------------------------------------------------
/src/native-ads/nativeAd.ts:
--------------------------------------------------------------------------------
1 | export interface NativeAd {
2 | advertiserName: string;
3 | bodyText: string;
4 | callToActionText: string;
5 | headline: string;
6 | linkDescription: string;
7 | promotedTranslation: string;
8 | sponsoredTranslation: string;
9 | socialContext: string;
10 | translation: string;
11 | }
12 |
13 | export interface HasNativeAd {
14 | nativeAd: NativeAd;
15 | }
16 |
--------------------------------------------------------------------------------
/src/native-ads/withNativeAd.tsx:
--------------------------------------------------------------------------------
1 | import { EventSubscription } from 'fbemitter';
2 | import React, { ReactNode } from 'react';
3 | import { findNodeHandle, requireNativeComponent } from 'react-native';
4 | import MediaView from './MediaViewManager';
5 | import AdIconView from './AdIconViewManager';
6 | import {
7 | AdChoicesViewContext,
8 | AdIconViewContext,
9 | AdIconViewContextValueType,
10 | ComponentOrClass,
11 | MediaViewContext,
12 | MediaViewContextValueType,
13 | TriggerableContext,
14 | TriggerableContextValueType
15 | } from './contexts';
16 | import { HasNativeAd, NativeAd } from './nativeAd';
17 | import AdsManager from './NativeAdsManager';
18 | import { areSetsEqual } from '../util/areSetsEqual';
19 |
20 | interface NativeAdViewProps {
21 | adsManager: string;
22 | onAdLoaded: (args: { nativeEvent: NativeAd }) => void;
23 | }
24 |
25 | // tslint:disable-next-line:variable-name
26 | const NativeAdView = requireNativeComponent('CTKNativeAd');
27 |
28 | interface AdWrapperState {
29 | ad?: NativeAd;
30 | canRequestAds: boolean;
31 | mediaViewNodeHandle: number;
32 | adIconViewNodeHandle: number;
33 | clickableChildren: Set;
34 | }
35 |
36 | interface AdWrapperProps {
37 | adsManager: AdsManager;
38 | onAdLoaded?: (ad: NativeAd) => void;
39 | }
40 |
41 | export default (
42 | // tslint:disable-next-line:variable-name
43 | Component: React.ComponentType
44 | ) =>
45 | class NativeAdWrapper extends React.Component<
46 | AdWrapperProps & T,
47 | AdWrapperState
48 | > {
49 | private subscription?: EventSubscription;
50 | private subscriptionError?: EventSubscription;
51 | private nativeAdViewRef?: React.Component;
52 | private registerFunctionsForTriggerables: TriggerableContextValueType;
53 | private registerFunctionsForMediaView: MediaViewContextValueType;
54 | private registerFunctionsForAdIconView: AdIconViewContextValueType;
55 | private clickableChildrenNodeHandles: Map;
56 |
57 | constructor(props: AdWrapperProps & T) {
58 | super(props);
59 |
60 | this.registerFunctionsForTriggerables = {
61 | register: this.registerClickableChild,
62 | unregister: this.unregisterClickableChild
63 | };
64 |
65 | this.registerFunctionsForMediaView = {
66 | unregister: this.unregisterMediaView,
67 | register: this.registerMediaView
68 | };
69 |
70 | this.registerFunctionsForAdIconView = {
71 | unregister: this.unregisterAdIconView,
72 | register: this.registerAdIconView
73 | };
74 |
75 | this.clickableChildrenNodeHandles = new Map();
76 |
77 | this.state = {
78 | // iOS requires a non-null value
79 | mediaViewNodeHandle: -1,
80 | adIconViewNodeHandle: -1,
81 | clickableChildren: new Set(),
82 | canRequestAds: false
83 | };
84 | }
85 |
86 | /**
87 | * On init, register for updates on `adsManager` to know when it becomes available
88 | */
89 | public componentDidMount() {
90 | this.subscription = this.props.adsManager.onAdsLoaded(() =>
91 | this.setState({ canRequestAds: true })
92 | );
93 | this.subscriptionError = this.props.adsManager.onAdsError(() =>
94 | this.setState({ canRequestAds: false })
95 | );
96 | }
97 |
98 | public componentDidUpdate(_: AdWrapperProps, prevState: AdWrapperState) {
99 | if (
100 | this.state.mediaViewNodeHandle === -1 ||
101 | this.state.adIconViewNodeHandle === -1
102 | ) {
103 | // Facebook's SDK requires both MediaView and AdIconView references in order to register
104 | // interactable views. If one of them is missing, we can't proceed with the registration.
105 | return;
106 | }
107 |
108 | const mediaViewNodeHandleChanged =
109 | this.state.mediaViewNodeHandle !== prevState.mediaViewNodeHandle;
110 | const adIconViewNodeHandleChanged =
111 | this.state.adIconViewNodeHandle !== prevState.adIconViewNodeHandle;
112 | const clickableChildrenChanged = areSetsEqual(
113 | prevState.clickableChildren,
114 | this.state.clickableChildren
115 | );
116 |
117 | if (
118 | mediaViewNodeHandleChanged ||
119 | adIconViewNodeHandleChanged ||
120 | clickableChildrenChanged
121 | ) {
122 | const viewHandle = findNodeHandle(this.nativeAdViewRef!);
123 | if (!viewHandle) {
124 | // Skip registration if the view is no longer valid.
125 | return;
126 | }
127 |
128 | AdsManager.registerViewsForInteractionAsync(
129 | viewHandle,
130 | this.state.mediaViewNodeHandle,
131 | this.state.adIconViewNodeHandle,
132 | [...this.state.clickableChildren]
133 | );
134 | }
135 | }
136 |
137 | /**
138 | * Clear subscription when component goes off screen
139 | */
140 | public componentWillUnmount() {
141 | if (this.subscription) {
142 | this.subscription.remove();
143 | }
144 | if (this.subscriptionError) {
145 | this.subscriptionError.remove();
146 | }
147 | }
148 |
149 | private registerMediaView = (mediaView: ComponentOrClass) =>
150 | this.setState({ mediaViewNodeHandle: findNodeHandle(mediaView) || -1 });
151 | private unregisterMediaView = () =>
152 | this.setState({ mediaViewNodeHandle: -1 });
153 |
154 | private registerAdIconView = (adIconView: ComponentOrClass) =>
155 | this.setState({ adIconViewNodeHandle: findNodeHandle(adIconView) || -1 });
156 | private unregisterAdIconView = () =>
157 | this.setState({ adIconViewNodeHandle: -1 });
158 |
159 | private registerClickableChild = (child: ComponentOrClass) => {
160 | const handle = findNodeHandle(child);
161 |
162 | if (!handle) {
163 | return;
164 | }
165 |
166 | this.clickableChildrenNodeHandles.set(child, handle);
167 |
168 | this.setState({
169 | clickableChildren: this.state.clickableChildren.add(handle)
170 | });
171 | };
172 |
173 | private unregisterClickableChild = (child: ComponentOrClass) => {
174 | this.setState(({ clickableChildren }) => {
175 | const newClickableChildren = new Set(clickableChildren);
176 | newClickableChildren.delete(
177 | this.clickableChildrenNodeHandles.get(child)!
178 | );
179 | this.clickableChildrenNodeHandles.delete(child);
180 | return { clickableChildren: newClickableChildren };
181 | });
182 | };
183 |
184 | private handleAdUpdated = () =>
185 | this.state.ad &&
186 | this.props.onAdLoaded &&
187 | this.props.onAdLoaded(this.state.ad);
188 |
189 | private handleAdLoaded = ({ nativeEvent }: { nativeEvent: NativeAd }) => {
190 | this.setState({ ad: nativeEvent }, this.handleAdUpdated);
191 | };
192 |
193 | private handleNativeAdViewMount = (ref: React.Component) => {
194 | this.nativeAdViewRef = ref;
195 | };
196 |
197 | private renderAdComponent(componentProps: T): ReactNode {
198 | if (!this.state.ad) {
199 | return null;
200 | }
201 | return (
202 |
203 |
204 |
207 |
210 | {/* Facebook's registerViewForInteraction requires both AdIconView and MediaView
211 | references to be set. We include both as a default */}
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 | );
221 | }
222 |
223 | render() {
224 | // Cast to any until https://github.com/Microsoft/TypeScript/issues/10727 is resolved
225 | const { adsManager, onAdLoaded, ...rest } = this.props as any;
226 |
227 | if (!this.state.canRequestAds) {
228 | return null;
229 | }
230 |
231 | return (
232 |
237 | {this.renderAdComponent(rest)}
238 |
239 | );
240 | }
241 | };
242 |
--------------------------------------------------------------------------------
/src/util/areSetsEqual.ts:
--------------------------------------------------------------------------------
1 | export const areSetsEqual = (a: Set, b: Set) => {
2 | if (a.size !== b.size) return false;
3 | for (const aItem of a) {
4 | if (!b.has(aItem)) return false;
5 | }
6 | return true;
7 | };
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "node",
4 | "target": "es6",
5 | "module": "es2015",
6 | "strict": true,
7 | "jsx": "react-native",
8 | "sourceMap": false,
9 | "declaration": true,
10 | "allowSyntheticDefaultImports": true,
11 | "declarationDir": "dist/types",
12 | "outDir": "dist/lib",
13 | "typeRoots": ["node_modules/@types"]
14 | },
15 | "include": ["src"]
16 | }
17 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": ["tslint-config-airbnb", "tslint-config-prettier"],
4 | "jsRules": {},
5 | "rules": {
6 | "import-name": false
7 | },
8 | "rulesDirectory": []
9 | }
10 |
--------------------------------------------------------------------------------