deconstructedList = new ArrayList<>(readableArray.size());
118 |
119 | for (int i = 0; i < readableArray.size(); i++) {
120 | ReadableType type = readableArray.getType(i);
121 |
122 | switch (type) {
123 | case Null:
124 | deconstructedList.add(i, null);
125 | break;
126 | case Boolean:
127 | deconstructedList.add(i, Boolean.toString(readableArray.getBoolean(i)));
128 | break;
129 | case Number:
130 | deconstructedList.add(i, Double.toString(readableArray.getDouble(i)));
131 | break;
132 | case String:
133 | deconstructedList.add(i, readableArray.getString(i));
134 | break;
135 | case Map:
136 | // skip second level maps
137 | // deconstructedList.add(i, fromObject(readableArray.getMap(i)));
138 | break;
139 | case Array:
140 | // skip second level arrays
141 | // deconstructedList.add(i, fromArray(readableArray.getArray(i)));
142 | break;
143 | }
144 | }
145 |
146 | return deconstructedList;
147 | }
148 |
149 | /**
150 | * Generate and associate a Correlator to this Ad View. The Correlator can be set to another ad
151 | * view to instruct the Ad Server to avoid giving them the same ad.
152 | *
153 | * @return A type erased Correlator associated with this Ad View
154 | */
155 | public static Object getCorelator(String adUnitID) {
156 | if (!correlators.containsKey(adUnitID)) {
157 | correlators.put(adUnitID, genRandomCorrelator());
158 | }
159 |
160 | return correlators.get(adUnitID);
161 | }
162 |
163 | private static String genRandomCorrelator() {
164 | StringBuilder stringBuilder = new StringBuilder();
165 | Random random = new Random();
166 | for (int i = 0; i < 16; i++) {
167 | if (i == 0) {
168 | // Append range [1, 9] to the leading digit, as we are looking
169 | // for getting a random number that's 16-digit long, so the
170 | // leading digit can't be 0;
171 | stringBuilder.append(1 + random.nextInt(8));
172 | } else {
173 | // Append range [0, 9] for the reast of the digits
174 | stringBuilder.append(random.nextInt(10));
175 | }
176 | }
177 |
178 | return stringBuilder.toString();
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/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
19 | * entryFile: "index.android.js",
20 | *
21 | * // https://reactnative.dev/docs/performance#enable-the-ram-format
22 | * bundleCommand: "ram-bundle",
23 | *
24 | * // whether to bundle JS and assets in debug mode
25 | * bundleInDebug: false,
26 | *
27 | * // whether to bundle JS and assets in release mode
28 | * bundleInRelease: true,
29 | *
30 | * // whether to bundle JS and assets in another build variant (if configured).
31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
32 | * // The configuration property can be in the following formats
33 | * // 'bundleIn${productFlavor}${buildType}'
34 | * // 'bundleIn${buildType}'
35 | * // bundleInFreeDebug: true,
36 | * // bundleInPaidRelease: true,
37 | * // bundleInBeta: true,
38 | *
39 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
40 | * // for AdManagerExample: to disable dev mode in the staging build type (if configured)
41 | * devDisabledInStaging: true,
42 | * // The configuration property can be in the following formats
43 | * // 'devDisabledIn${productFlavor}${buildType}'
44 | * // 'devDisabledIn${buildType}'
45 | *
46 | * // the root of your project, i.e. where "package.json" lives
47 | * root: "../../",
48 | *
49 | * // where to put the JS bundle asset in debug mode
50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
51 | *
52 | * // where to put the JS bundle asset in release mode
53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
54 | *
55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
56 | * // require('./image.png')), in debug mode
57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
58 | *
59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
60 | * // require('./image.png')), in release mode
61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
62 | *
63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
67 | * // for AdManagerExample, you might want to remove it from here.
68 | * inputExcludes: ["android/**", "ios/**"],
69 | *
70 | * // override which node gets called and with what additional arguments
71 | * nodeExecutableAndArgs: ["node"],
72 | *
73 | * // supply additional arguments to the packager
74 | * extraPackagerArgs: []
75 | * ]
76 | */
77 |
78 | project.ext.react = [
79 | enableHermes: false, // clean and rebuild if changing
80 | entryFile: "index.tsx",
81 | ]
82 |
83 | apply from: "../../node_modules/react-native/react.gradle"
84 |
85 | /**
86 | * Set this to true to create two separate APKs instead of one:
87 | * - An APK that only works on ARM devices
88 | * - An APK that only works on x86 devices
89 | * The advantage is the size of the APK is reduced by about 4MB.
90 | * Upload all the APKs to the Play Store and people will download
91 | * the correct one based on the CPU architecture of their device.
92 | */
93 | def enableSeparateBuildPerCPUArchitecture = false
94 |
95 | /**
96 | * Run Proguard to shrink the Java bytecode in release builds.
97 | */
98 | def enableProguardInReleaseBuilds = false
99 |
100 | /**
101 | * The preferred build flavor of JavaScriptCore.
102 | *
103 | * For AdManagerExample, to use the international variant, you can use:
104 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
105 | *
106 | * The international variant includes ICU i18n library and necessary data
107 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
108 | * give correct results when using with locales other than en-US. Note that
109 | * this variant is about 6MiB larger per architecture than default.
110 | */
111 | def jscFlavor = 'org.webkit:android-jsc:+'
112 |
113 | /**
114 | * Whether to enable the Hermes VM.
115 | *
116 | * This should be set on project.ext.react and mirrored here. If it is not set
117 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
118 | * and the benefits of using Hermes will therefore be sharply reduced.
119 | */
120 | def enableHermes = project.ext.react.get("enableHermes", false);
121 |
122 | android {
123 | compileSdkVersion rootProject.ext.compileSdkVersion
124 |
125 | compileOptions {
126 | sourceCompatibility JavaVersion.VERSION_1_8
127 | targetCompatibility JavaVersion.VERSION_1_8
128 | }
129 |
130 | defaultConfig {
131 | applicationId "com.example.reactnativeadmanager"
132 | minSdkVersion rootProject.ext.minSdkVersion
133 | targetSdkVersion rootProject.ext.targetSdkVersion
134 | versionCode 1
135 | versionName "1.0"
136 | multiDexEnabled true
137 | }
138 | splits {
139 | abi {
140 | reset()
141 | enable enableSeparateBuildPerCPUArchitecture
142 | universalApk false // If true, also generate a universal APK
143 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
144 | }
145 | }
146 | signingConfigs {
147 | debug {
148 | storeFile file('debug.keystore')
149 | storePassword 'android'
150 | keyAlias 'androiddebugkey'
151 | keyPassword 'android'
152 | }
153 | }
154 | buildTypes {
155 | debug {
156 | signingConfig signingConfigs.debug
157 | }
158 | release {
159 | // Caution! In production, you need to generate your own keystore file.
160 | // see https://reactnative.dev/docs/signed-apk-android.
161 | signingConfig signingConfigs.debug
162 | minifyEnabled enableProguardInReleaseBuilds
163 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
164 | }
165 | }
166 | // applicationVariants are e.g. debug, release
167 | applicationVariants.all { variant ->
168 | variant.outputs.each { output ->
169 | // For each separate APK per architecture, set a unique version code as described here:
170 | // https://developer.android.com/studio/build/configure-apk-splits.html
171 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
172 | def abi = output.getFilter(OutputFile.ABI)
173 | if (abi != null) { // null for the universal-debug, universal-release variants
174 | output.versionCodeOverride =
175 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
176 | }
177 |
178 | }
179 | }
180 | }
181 |
182 | dependencies {
183 | implementation fileTree(dir: "libs", include: ["*.jar"])
184 | //noinspection GradleDynamicVersion
185 | implementation "com.facebook.react:react-native:+" // From node_modules
186 |
187 |
188 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
189 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
190 | exclude group:'com.facebook.fbjni'
191 | }
192 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
193 | exclude group:'com.facebook.flipper'
194 | exclude group:'com.squareup.okhttp3', module:'okhttp'
195 | }
196 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
197 | exclude group:'com.facebook.flipper'
198 | }
199 |
200 | if (enableHermes) {
201 | def hermesPath = "../../node_modules/hermes-engine/android/";
202 | debugImplementation files(hermesPath + "hermes-debug.aar")
203 | releaseImplementation files(hermesPath + "hermes-release.aar")
204 | } else {
205 | implementation jscFlavor
206 | }
207 |
208 | implementation project(':reactnativeadmanager')
209 | }
210 |
211 | // Run this once to be able to run the application with BUCK
212 | // puts all compile dependencies into folder libs for BUCK to use
213 | task copyDownloadableDepsToLibs(type: Copy) {
214 | from configurations.compile
215 | into 'libs'
216 | }
217 |
218 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
219 |
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/java/com/example/reactnativeadmanager/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.reactnativeadmanager;
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 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
32 | client.addPlugin(new ReactFlipperPlugin());
33 | client.addPlugin(new DatabasesFlipperPlugin(context));
34 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
35 | client.addPlugin(CrashReporterPlugin.getInstance());
36 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
37 | NetworkingModule.setCustomClientBuilder(
38 | new NetworkingModule.CustomClientBuilder() {
39 | @Override
40 | public void apply(OkHttpClient.Builder builder) {
41 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
42 | }
43 | });
44 | client.addPlugin(networkFlipperPlugin);
45 | client.start();
46 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
47 | // Hence we run if after all native modules have been initialized
48 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
49 | if (reactContext == null) {
50 | reactInstanceManager.addReactInstanceEventListener(
51 | new ReactInstanceManager.ReactInstanceEventListener() {
52 | @Override
53 | public void onReactContextInitialized(ReactContext reactContext) {
54 | reactInstanceManager.removeReactInstanceEventListener(this);
55 | reactContext.runOnNativeModulesQueueThread(
56 | new Runnable() {
57 | @Override
58 | public void run() {
59 | client.addPlugin(new FrescoFlipperPlugin());
60 | }
61 | });
62 | }
63 | });
64 | } else {
65 | client.addPlugin(new FrescoFlipperPlugin());
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/reactnativeadmanager/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.reactnativeadmanager;
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 "AdManagerExample";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/reactnativeadmanager/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.reactnativeadmanager;
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.react.ReactNativeHost;
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.ReactInstanceManager;
10 | import com.facebook.soloader.SoLoader;
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.util.List;
13 | import com.matejdr.admanager.RNAdManagerPackage;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost =
18 | new ReactNativeHost(this) {
19 | @Override
20 | public boolean getUseDeveloperSupport() {
21 | return BuildConfig.DEBUG;
22 | }
23 |
24 | @Override
25 | protected List getPackages() {
26 | @SuppressWarnings("UnnecessaryLocalVariable")
27 | List packages = new PackageList(this).getPackages();
28 | // Packages that cannot be autolinked yet can be added manually here, for AdManagerExample:
29 | // packages.add(new MyReactNativePackage());
30 | packages.add(new RNAdManagerPackage());
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()); // Remove this line if you don't want Flipper enabled
50 | }
51 |
52 | /**
53 | * Loads Flipper in React Native templates.
54 | *
55 | * @param context
56 | */
57 | private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
58 | if (BuildConfig.DEBUG) {
59 | try {
60 | /*
61 | We use reflection here to pick up the class that initializes Flipper,
62 | since Flipper library is not available in release mode
63 | */
64 | Class> aClass = Class.forName("com.example.reactnativeadmanager.ReactNativeFlipper");
65 | aClass
66 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
67 | .invoke(null, context, reactInstanceManager);
68 | } catch (ClassNotFoundException e) {
69 | e.printStackTrace();
70 | } catch (NoSuchMethodException e) {
71 | e.printStackTrace();
72 | } catch (IllegalAccessException e) {
73 | e.printStackTrace();
74 | } catch (InvocationTargetException e) {
75 | e.printStackTrace();
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AdManager Example
3 |
4 |
--------------------------------------------------------------------------------
/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 | minSdkVersion = 21
6 | compileSdkVersion = 29
7 | targetSdkVersion = 29
8 | }
9 | repositories {
10 | google()
11 | mavenCentral()
12 | jcenter()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle:3.5.4")
16 |
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 | mavenCentral()
36 | jcenter()
37 | maven { url 'https://www.jitpack.io' }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/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 | android.useAndroidX=true
21 | android.enableJetifier=true
22 | FLIPPER_VERSION=0.54.0
23 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NZME/react-native-ad-manager/6354c0b06c002a94fa0672e7d209f6bd107ea63a/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 http://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 = 'AdManagerExample'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 |
5 | include ':reactnativeadmanager'
6 | project(':reactnativeadmanager').projectDir = new File(rootProject.projectDir, '../../android')
7 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "AdManagerExample",
3 | "displayName": "AdManager Example"
4 | }
5 |
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const pak = require('../package.json');
3 |
4 | module.exports = {
5 | presets: ['module:metro-react-native-babel-preset'],
6 | plugins: [
7 | [
8 | 'module-resolver',
9 | {
10 | extensions: ['.tsx', '.ts', '.js', '.json'],
11 | alias: {
12 | [pak.name]: path.join(__dirname, '..', pak.source),
13 | },
14 | },
15 | ],
16 | ],
17 | };
18 |
--------------------------------------------------------------------------------
/example/index.tsx:
--------------------------------------------------------------------------------
1 | import { AppRegistry } from 'react-native';
2 | import App from './src/App';
3 | import { name as appName } from './app.json';
4 |
5 | AppRegistry.registerComponent(appName, () => App);
6 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample-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 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample.xcodeproj/xcshareddata/xcschemes/AdManagerExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
81 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | #import
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (nonatomic, strong) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | #import "AppDelegate.h"
9 |
10 | #import
11 | #import
12 | #import
13 |
14 | #ifdef FB_SONARKIT_ENABLED
15 | #import
16 | #import
17 | #import
18 | #import
19 | #import
20 | #import
21 | static void InitializeFlipper(UIApplication *application) {
22 | FlipperClient *client = [FlipperClient sharedClient];
23 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
24 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
25 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
26 | [client addPlugin:[FlipperKitReactPlugin new]];
27 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
28 | [client start];
29 | }
30 | #endif
31 |
32 | @implementation AppDelegate
33 |
34 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
35 | {
36 | #ifdef FB_SONARKIT_ENABLED
37 | InitializeFlipper(application);
38 | #endif
39 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
40 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
41 | moduleName:@"AdManagerExample"
42 | initialProperties:nil];
43 |
44 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
45 |
46 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
47 | UIViewController *rootViewController = [UIViewController new];
48 | rootViewController.view = rootView;
49 | self.window.rootViewController = rootViewController;
50 | [self.window makeKeyAndVisible];
51 | return YES;
52 | }
53 |
54 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
55 | {
56 | #if DEBUG
57 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
58 | #else
59 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
60 | #endif
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/example/ios/AdManagerExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | AdManager 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 | GADApplicationIdentifier
57 | ca-app-pub-3940256099942544~1458002511
58 | SKAdNetworkItems
59 |
60 |
61 | SKAdNetworkIdentifier
62 | cstr6suwn9.skadnetwork
63 |
64 |
65 | SKAdNetworkIdentifier
66 | 4fzdc2evr5.skadnetwork
67 |
68 |
69 | SKAdNetworkIdentifier
70 | 2fnua5tdw4.skadnetwork
71 |
72 |
73 | SKAdNetworkIdentifier
74 | ydx93a7ass.skadnetwork
75 |
76 |
77 | SKAdNetworkIdentifier
78 | 5a6flpkh64.skadnetwork
79 |
80 |
81 | SKAdNetworkIdentifier
82 | p78axxw29g.skadnetwork
83 |
84 |
85 | SKAdNetworkIdentifier
86 | v72qych5uu.skadnetwork
87 |
88 |
89 | SKAdNetworkIdentifier
90 | c6k4g5qg8m.skadnetwork
91 |
92 |
93 | SKAdNetworkIdentifier
94 | s39g8k73mm.skadnetwork
95 |
96 |
97 | SKAdNetworkIdentifier
98 | 3qy4746246.skadnetwork
99 |
100 |
101 | SKAdNetworkIdentifier
102 | 3sh42y64q3.skadnetwork
103 |
104 |
105 | SKAdNetworkIdentifier
106 | f38h382jlk.skadnetwork
107 |
108 |
109 | SKAdNetworkIdentifier
110 | hs6bdukanm.skadnetwork
111 |
112 |
113 | SKAdNetworkIdentifier
114 | prcb7njmu6.skadnetwork
115 |
116 |
117 | SKAdNetworkIdentifier
118 | v4nxqhlyqp.skadnetwork
119 |
120 |
121 | SKAdNetworkIdentifier
122 | wzmmz9fp6w.skadnetwork
123 |
124 |
125 | SKAdNetworkIdentifier
126 | yclnxrl5pm.skadnetwork
127 |
128 |
129 | SKAdNetworkIdentifier
130 | t38b2kh725.skadnetwork
131 |
132 |
133 | SKAdNetworkIdentifier
134 | 7ug5zh24hu.skadnetwork
135 |
136 |
137 | SKAdNetworkIdentifier
138 | 9rd848q2bz.skadnetwork
139 |
140 |
141 | SKAdNetworkIdentifier
142 | n6fk4nfna4.skadnetwork
143 |
144 |
145 | SKAdNetworkIdentifier
146 | kbd757ywx3.skadnetwork
147 |
148 |
149 | SKAdNetworkIdentifier
150 | 9t245vhmpl.skadnetwork
151 |
152 |
153 | SKAdNetworkIdentifier
154 | 4468km3ulz.skadnetwork
155 |
156 |
157 | SKAdNetworkIdentifier
158 | 2u9pt9hc89.skadnetwork
159 |
160 |
161 | SKAdNetworkIdentifier
162 | 8s468mfl3y.skadnetwork
163 |
164 |
165 | SKAdNetworkIdentifier
166 | av6w8kgt66.skadnetwork
167 |
168 |
169 | SKAdNetworkIdentifier
170 | klf5c3l5u5.skadnetwork
171 |
172 |
173 | SKAdNetworkIdentifier
174 | ppxm28t8ap.skadnetwork
175 |
176 |
177 | SKAdNetworkIdentifier
178 | 424m5254lk.skadnetwork
179 |
180 |
181 | SKAdNetworkIdentifier
182 | uw77j35x4d.skadnetwork
183 |
184 |
185 | SKAdNetworkIdentifier
186 | 578prtvx9j.skadnetwork
187 |
188 |
189 | SKAdNetworkIdentifier
190 | 4dzt52r2t5.skadnetwork
191 |
192 |
193 | SKAdNetworkIdentifier
194 | e5fvkxwrpn.skadnetwork
195 |
196 |
197 | SKAdNetworkIdentifier
198 | 8c4e2ghe7u.skadnetwork
199 |
200 |
201 | SKAdNetworkIdentifier
202 | zq492l623r.skadnetwork
203 |
204 |
205 | SKAdNetworkIdentifier
206 | 3qcr597p9d.skadnetwork
207 |
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/example/ios/AdManagerExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
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/AdManagerExample/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | #import
9 |
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/example/ios/File.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // AdManagerExample
4 | //
5 |
6 | import Foundation
7 |
--------------------------------------------------------------------------------
/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, '11.0'
5 |
6 | target 'AdManagerExample' do
7 | config = use_native_modules!
8 |
9 | use_react_native!(:path => config["reactNativePath"])
10 |
11 | pod 'react-native-ad-manager', :path => '../..'
12 |
13 | # Enables Flipper.
14 | #
15 | # Note that if you have use_frameworks! enabled, Flipper will not work and
16 | # you should disable these next few lines.
17 | # use_flipper!({ 'Flipper' => '0.80.0' })
18 | post_install do |installer|
19 | flipper_post_install(installer)
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const blacklist = require('metro-config/src/defaults/blacklist');
3 | const escape = require('escape-string-regexp');
4 | const pak = require('../package.json');
5 |
6 | const root = path.resolve(__dirname, '..');
7 |
8 | const modules = Object.keys({
9 | ...pak.peerDependencies,
10 | });
11 |
12 | module.exports = {
13 | projectRoot: __dirname,
14 | watchFolders: [root],
15 |
16 | // We need to make sure that only one version is loaded for peerDependencies
17 | // So we blacklist them at the root, and alias them to the versions in example's node_modules
18 | resolver: {
19 | blacklistRE: blacklist(
20 | modules.map(
21 | (m) =>
22 | new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
23 | )
24 | ),
25 |
26 | extraNodeModules: modules.reduce((acc, name) => {
27 | acc[name] = path.join(__dirname, 'node_modules', name);
28 | return acc;
29 | }, {}),
30 | },
31 |
32 | transformer: {
33 | getTransformOptions: async () => ({
34 | transform: {
35 | experimentalImportSupport: false,
36 | inlineRequires: true,
37 | },
38 | }),
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-ad-manager-example",
3 | "description": "Example app for react-native-ad-manager",
4 | "version": "0.0.1",
5 | "private": true,
6 | "scripts": {
7 | "android": "react-native run-android",
8 | "ios": "react-native run-ios",
9 | "start": "react-native start"
10 | },
11 | "dependencies": {
12 | "react": "16.13.1",
13 | "react-native": "0.64.1"
14 | },
15 | "devDependencies": {
16 | "@babel/core": "^7.12.10",
17 | "@babel/runtime": "^7.12.5",
18 | "babel-plugin-module-resolver": "^4.0.0",
19 | "metro-react-native-babel-preset": "^0.64.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/example/src/BannerExample.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { StyleSheet, Text, View, ViewProps } from 'react-native';
3 |
4 | interface IBannerExampleProps extends ViewProps {
5 | title: string;
6 | children: React.ReactNode;
7 | }
8 | export const BannerExample = ({
9 | style,
10 | title,
11 | children,
12 | ...props
13 | }: IBannerExampleProps) => (
14 |
15 | {title}
16 | {children}
17 |
18 | );
19 |
20 | const styles = StyleSheet.create({
21 | example: {
22 | paddingVertical: 10,
23 | },
24 | title: {
25 | margin: 10,
26 | fontSize: 20,
27 | },
28 | });
29 |
--------------------------------------------------------------------------------
/example/src/NativeAdView.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Text, View, Image, StyleSheet } from 'react-native';
3 | import {
4 | withNativeAd,
5 | TriggerableView,
6 | IAdManagerEventLoadedBanner,
7 | IAdManagerEventLoadedTemplate,
8 | IAdManagerEventLoadedNative,
9 | IAdManagerTemplateImage,
10 | } from 'react-native-ad-manager';
11 |
12 | interface INativeAdViewProps {
13 | nativeAd:
14 | | IAdManagerEventLoadedBanner
15 | | IAdManagerEventLoadedTemplate
16 | | IAdManagerEventLoadedNative;
17 | }
18 |
19 | interface INativeAdViewState {}
20 |
21 | interface INativeAdElement {
22 | headline?: string;
23 | bodyText?: string;
24 | advertiserName?: string;
25 | starRating?: string;
26 | storeName?: string;
27 | price?: string;
28 | callToActionText?: string;
29 | icon?: IAdManagerTemplateImage;
30 | images?: IAdManagerTemplateImage[];
31 | }
32 |
33 | export class NativeAdView extends React.Component<
34 | INativeAdViewProps,
35 | INativeAdViewState
36 | > {
37 | render() {
38 | const { nativeAd } = this.props;
39 | if (!['native', 'template'].includes(nativeAd?.type)) {
40 | return null;
41 | }
42 |
43 | let data: INativeAdElement = {};
44 | if (nativeAd?.type === 'native') {
45 | data.headline = nativeAd?.headline;
46 | data.bodyText = nativeAd?.bodyText;
47 | data.advertiserName = nativeAd?.advertiserName;
48 | data.starRating = nativeAd?.starRating;
49 | data.storeName = nativeAd?.storeName;
50 | data.price = nativeAd?.price;
51 | data.icon = nativeAd?.icon;
52 | data.callToActionText = nativeAd?.callToActionText;
53 | data.images = nativeAd?.images;
54 | } else if (nativeAd?.type === 'template') {
55 | data.headline = (nativeAd?.title || nativeAd?.Headline) as string;
56 | data.bodyText = (nativeAd?.text || nativeAd?.Caption) as string;
57 | data.advertiserName = nativeAd?.label as string;
58 | data.starRating = nativeAd?.imptrk as string;
59 | data.storeName = nativeAd?.headline as string;
60 | data.price = undefined;
61 | data.icon = (nativeAd?.image ||
62 | nativeAd?.MainImage) as IAdManagerTemplateImage;
63 | data.callToActionText = undefined;
64 | data.images = [];
65 | }
66 |
67 | return (
68 |
69 |
70 |
71 |
72 | {data?.headline && (
73 | {data.headline}
74 | )}
75 | {data?.bodyText && (
76 | {data.bodyText}
77 | )}
78 |
79 | {data?.advertiserName}
80 | {data?.starRating}
81 | {data?.storeName}
82 | {data?.price}
83 |
84 |
85 | {data?.icon?.uri && (
86 |
87 | )}
88 |
89 | {data?.callToActionText && (
90 |
91 |
92 |
93 | {data.callToActionText}
94 |
95 |
96 |
97 | )}
98 |
99 | );
100 | }
101 | }
102 |
103 | const styles = StyleSheet.create({
104 | container: {
105 | flexDirection: 'column',
106 | borderWidth: 1,
107 | position: 'relative',
108 | },
109 | triggerableView: {
110 | backgroundColor: 'rgba(52, 52, 52, 0.5)',
111 | position: 'absolute',
112 | zIndex: 99,
113 | top: 0,
114 | left: 0,
115 | width: '100%',
116 | height: '100%',
117 | },
118 |
119 | native: { flexDirection: 'row', padding: 10 },
120 | nativeContainer: { flexDirection: 'column', flex: 1 },
121 | nativeHeadline: { fontSize: 18 },
122 | nativeBodyText: { fontSize: 10 },
123 | nativeContent: { flexDirection: 'row' },
124 | nativeIcon: { width: 80, height: 80 },
125 | callToActionHolder: { alignItems: 'center' },
126 | callToActionText: {
127 | fontSize: 15,
128 | color: '#a70f0a',
129 | paddingVertical: 10,
130 | paddingHorizontal: 30,
131 | elevation: 3,
132 | borderTopWidth: 0,
133 | margin: 10,
134 | borderRadius: 6,
135 | },
136 | });
137 |
138 | export default withNativeAd(NativeAdView);
139 |
--------------------------------------------------------------------------------
/ios/RCTConvert+GADAdSize.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface RCTConvert (GADAdSize)
5 |
6 | + (GADAdSize)GADAdSize:(id)json;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/ios/RCTConvert+GADAdSize.m:
--------------------------------------------------------------------------------
1 | #import "RCTConvert+GADAdSize.h"
2 |
3 | @implementation RCTConvert (GADAdSize)
4 |
5 | + (GADAdSize)GADAdSize:(id)json
6 | {
7 | NSString *adSize = [self NSString:json];
8 | if ([adSize containsString:@"x"]) {
9 | NSArray *splitAdSizes = [adSize componentsSeparatedByString:@"x"];
10 | if ([splitAdSizes count] == 2) {
11 | return GADAdSizeFromCGSize(CGSizeMake([splitAdSizes[0] intValue], [splitAdSizes[1] intValue]));
12 | }
13 | }
14 |
15 | if ([adSize isEqualToString:@"banner"]) {
16 | return GADAdSizeBanner;
17 | } else if ([adSize isEqualToString:@"fullBanner"]) {
18 | return GADAdSizeFullBanner;
19 | } else if ([adSize isEqualToString:@"largeBanner"]) {
20 | return GADAdSizeLargeBanner;
21 | } else if ([adSize isEqualToString:@"fluid"]) {
22 | return GADAdSizeFluid;
23 | } else if ([adSize isEqualToString:@"skyscraper"]) {
24 | return GADAdSizeSkyscraper;
25 | } else if ([adSize isEqualToString:@"leaderboard"]) {
26 | return GADAdSizeLeaderboard;
27 | } else if ([adSize isEqualToString:@"mediumRectangle"]) {
28 | return GADAdSizeMediumRectangle;
29 | } else {
30 | return GADAdSizeInvalid;
31 | }
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/ios/RNAdManageNativeManager.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface RNAdManageNativeManager : RCTViewManager
5 |
6 | @property (strong, nonatomic) NSString *adUnitID;
7 | @property (strong, nonatomic) NSArray *testDevices;
8 |
9 | - (RNAdManageNativeManager *) getAdsManager:(NSString *)adUnitID;
10 | - (GADAdLoader *) getAdLoader:(NSString *)adUnitID validAdTypes:(NSArray *)validAdTypes loaderIndex:(NSString *)loaderIndex;
11 |
12 | @end
13 |
--------------------------------------------------------------------------------
/ios/RNAdManageNativeManager.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManageNativeManager.h"
2 | #import "RNAdManageNativeView.h"
3 |
4 | #import
5 | #import
6 | #import
7 | #import
8 | #import
9 | #import
10 |
11 | #import "RNAdManagerUtils.h"
12 |
13 | @interface RNAdManageNativeManager ()
14 |
15 | //@property (nonatomic, strong) NSMutableDictionary *adsManagers;
16 | //@property (nonatomic, strong) NSMutableDictionary *adLoaders;
17 | @property (nonatomic, strong) NSString *myAdChoiceViewAdUnitID;
18 |
19 | @end
20 |
21 | @implementation RNAdManageNativeManager
22 |
23 | RCT_EXPORT_MODULE(CTKAdManageNativeManager)
24 |
25 | @synthesize bridge = _bridge;
26 |
27 | - (instancetype)init
28 | {
29 | self = [super init];
30 | if (self) {
31 | if (adsManagers == nil) {
32 | adsManagers = [NSMutableDictionary new];
33 | }
34 | if (adLoaders == nil) {
35 | adLoaders = [NSMutableDictionary new];
36 | }
37 | }
38 | return self;
39 | }
40 |
41 | static NSMutableDictionary *adsManagers;
42 | static NSMutableDictionary *adLoaders;
43 |
44 | + (BOOL)requiresMainQueueSetup
45 | {
46 | return NO;
47 | }
48 |
49 | RCT_EXPORT_METHOD(registerViewsForInteraction:(nonnull NSNumber *)nativeAdViewTag
50 | clickableViewsTags:(nonnull NSArray *)tags
51 | resolve:(RCTPromiseResolveBlock)resolve
52 | reject:(RCTPromiseRejectBlock)reject)
53 | {
54 | [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) {
55 | RNAdManageNativeView *nativeAdView = nil;
56 |
57 | if ([viewRegistry objectForKey:nativeAdViewTag] == nil) {
58 | reject(@"E_NO_NATIVEAD_VIEW", @"Could not find nativeAdView", nil);
59 | return;
60 | }
61 |
62 | if ([[viewRegistry objectForKey:nativeAdViewTag] isKindOfClass:[RNAdManageNativeView class]]) {
63 | nativeAdView = (RNAdManageNativeView *)[viewRegistry objectForKey:nativeAdViewTag];
64 | } else {
65 | reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed native ad view tag is not an instance of RNAdManageNativeView", nil);
66 | return;
67 | }
68 |
69 | NSMutableArray *clickableViews = [NSMutableArray new];
70 | for (id tag in tags) {
71 | if ([viewRegistry objectForKey:tag]) {
72 | [clickableViews addObject:[viewRegistry objectForKey:tag]];
73 | } else {
74 | reject(@"E_INVALID_VIEW_TAG", [NSString stringWithFormat:@"Could not find view for tag: %@", [tag stringValue]], nil);
75 | return;
76 | }
77 | }
78 |
79 | [nativeAdView registerViewsForInteraction:clickableViews];
80 | resolve(@[]);
81 | }];
82 | }
83 |
84 | RCT_EXPORT_METHOD(init:(NSString *)adUnitID testDevices:(NSArray *)testDevices)
85 | {
86 | if (adsManagers == nil) {
87 | adsManagers = [NSMutableDictionary new];
88 | }
89 |
90 | RNAdManageNativeManager *adsManager = [RNAdManageNativeManager alloc];
91 |
92 | adsManager.adUnitID = adUnitID;
93 | adsManager.testDevices = RNAdManagerProcessTestDevices(testDevices, GADSimulatorID);
94 |
95 | _myAdChoiceViewAdUnitID = adUnitID;
96 |
97 | [adsManagers setValue:adsManager forKey:adUnitID];
98 | }
99 |
100 | - (RNAdManageNativeManager *) getAdsManager:(NSString *)adUnitID
101 | {
102 | return adsManagers[adUnitID];
103 | }
104 |
105 | - (GADAdLoader *) getAdLoader:(NSString *)adUnitID validAdTypes:(NSArray *)validAdTypes loaderIndex:(NSString *)loaderIndex
106 | {
107 | if (adLoaders == nil) {
108 | adLoaders = [NSMutableDictionary new];
109 | }
110 |
111 | NSString *adLoaderKey = adUnitID;
112 | if ([validAdTypes containsObject:@"native"]) {
113 | adLoaderKey = [NSString stringWithFormat:@"%@%@", adLoaderKey, @"native"];
114 | }
115 | if ([validAdTypes containsObject:@"banner"]) {
116 | adLoaderKey = [NSString stringWithFormat:@"%@%@", adLoaderKey, @"banner"];
117 | }
118 | if ([validAdTypes containsObject:@"template"]) {
119 | NSString *index = loaderIndex ? loaderIndex : @"";
120 | adLoaderKey = [NSString stringWithFormat:@"%@%@%@", adLoaderKey, @"template", index];
121 | }
122 |
123 | GADAdLoader *adLoader = [adLoaders objectForKey:adLoaderKey];
124 | if (adLoader == nil) {
125 | // Loads an ad for any of app install, content, or custom native ads.
126 | NSMutableArray *adTypes = [[NSMutableArray alloc] init];
127 | if ([validAdTypes containsObject:@"native"]) {
128 | [adTypes addObject:GADAdLoaderAdTypeNative];
129 | }
130 | if ([validAdTypes containsObject:@"banner"]) {
131 | [adTypes addObject:GADAdLoaderAdTypeGAMBanner];
132 | }
133 | if ([validAdTypes containsObject:@"template"]) {
134 | [adTypes addObject:GADAdLoaderAdTypeCustomNative];
135 | }
136 |
137 | GADVideoOptions *videoOptions = [[GADVideoOptions alloc] init];
138 | videoOptions.startMuted = YES;
139 |
140 | adLoader = [[GADAdLoader alloc] initWithAdUnitID:adUnitID
141 | rootViewController:[UIApplication sharedApplication].delegate.window.rootViewController
142 | adTypes:adTypes
143 | options:@[ videoOptions ]];
144 |
145 | [adLoaders setValue:adLoader forKey:adLoaderKey];
146 | }
147 |
148 | return adLoader;
149 | }
150 |
151 | - (UIView *)view
152 | {
153 | return [[RNAdManageNativeView alloc] initWithBridge:_bridge];
154 | }
155 |
156 | RCT_EXPORT_METHOD(reloadAd:(nonnull NSNumber *)reactTag)
157 | {
158 | [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) {
159 | RNAdManageNativeView *view = viewRegistry[reactTag];
160 | if (![view isKindOfClass:[RNAdManageNativeView class]]) {
161 | RCTLogError(@"Invalid view returned from registry, expecting RNAdManageNativeView, got: %@", view);
162 | } else {
163 | [view reloadAd];
164 | }
165 | }];
166 | }
167 |
168 | RCT_CUSTOM_VIEW_PROPERTY(adsManager, NSString, RNAdManageNativeView)
169 | {
170 | // RNAdManageNativeManager *nativeAdManager = [_bridge moduleForClass:[RNAdManageNativeManager class]];
171 | RNAdManageNativeManager *_adsManager = [[_bridge moduleForClass:[RNAdManageNativeManager class]] getAdsManager:json];
172 | [view loadAd:_adsManager];
173 | }
174 |
175 | RCT_EXPORT_VIEW_PROPERTY(loaderIndex, NSString)
176 | RCT_EXPORT_VIEW_PROPERTY(customTemplateIds, NSArray)
177 | RCT_EXPORT_VIEW_PROPERTY(customClickTemplateIds, NSArray)
178 | RCT_EXPORT_VIEW_PROPERTY(validAdTypes, NSArray)
179 | RCT_EXPORT_VIEW_PROPERTY(adSize, NSString)
180 | RCT_EXPORT_VIEW_PROPERTY(validAdSizes, NSArray)
181 | RCT_EXPORT_VIEW_PROPERTY(targeting, NSDictionary)
182 | RCT_EXPORT_VIEW_PROPERTY(correlator, NSString)
183 |
184 | RCT_EXPORT_VIEW_PROPERTY(onSizeChange, RCTBubblingEventBlock)
185 | RCT_EXPORT_VIEW_PROPERTY(onAppEvent, RCTBubblingEventBlock)
186 | RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTBubblingEventBlock)
187 | RCT_EXPORT_VIEW_PROPERTY(onAdFailedToLoad, RCTBubblingEventBlock)
188 | RCT_EXPORT_VIEW_PROPERTY(onAdOpened, RCTBubblingEventBlock)
189 | RCT_EXPORT_VIEW_PROPERTY(onAdClosed, RCTBubblingEventBlock)
190 | RCT_EXPORT_VIEW_PROPERTY(onAdCustomClick, RCTBubblingEventBlock)
191 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordImpression, RCTBubblingEventBlock)
192 |
193 | @end
194 |
--------------------------------------------------------------------------------
/ios/RNAdManageNativeView.h:
--------------------------------------------------------------------------------
1 | #import "RNAdManageNativeManager.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #import
8 |
9 | @class RCTEventDispatcher;
10 |
11 | @interface RNAdManageNativeView : RCTView
12 |
13 | /// You must keep a strong reference to the GADAdLoader during the ad loading process.
14 | @property(nonatomic, strong) IBOutlet GADAdLoader *adLoader;
15 |
16 | /// The native ad that is being loaded.
17 | @property(nonatomic, strong) IBOutlet GADNativeAd *nativeAd;
18 |
19 | /// The native ad view
20 | @property(nonatomic, strong) IBOutlet GADNativeAdView *nativeAdView;
21 |
22 | /// The DFP banner view.
23 | @property(nonatomic, strong) IBOutlet GAMBannerView *bannerView;
24 |
25 | /// The native custom template ad
26 | @property(nonatomic, strong) IBOutlet GADCustomNativeAd *nativeCustomTemplateAd;
27 |
28 | @property (nonatomic, copy) NSString *loaderIndex;
29 | @property (nonatomic, copy) NSArray *customTemplateIds;
30 | @property (nonatomic, copy) NSArray *customClickTemplateIds;
31 | @property (nonatomic, copy) NSArray *validAdTypes;
32 | @property (nonatomic, copy) NSString *adSize;
33 | @property (nonatomic, copy) NSArray *validAdSizes;
34 | @property (nonatomic, copy) NSDictionary *targeting;
35 | @property (nonatomic, copy) NSString *correlator;
36 |
37 | @property (nonatomic, copy) RCTBubblingEventBlock onSizeChange;
38 | @property (nonatomic, copy) RCTBubblingEventBlock onAppEvent;
39 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoaded;
40 | @property (nonatomic, copy) RCTBubblingEventBlock onAdFailedToLoad;
41 | @property (nonatomic, copy) RCTBubblingEventBlock onAdOpened;
42 | @property (nonatomic, copy) RCTBubblingEventBlock onAdClosed;
43 | @property (nonatomic, copy) RCTBubblingEventBlock onAdCustomClick;
44 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordImpression;
45 |
46 | - (instancetype)initWithBridge:(RCTBridge *)bridge;
47 | - (void)registerViewsForInteraction:(NSArray *)clickableViews;
48 | - (void)reloadAd;
49 | - (void)loadAd:(RNAdManageNativeManager *)adManager;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/ios/RNAdManagerAdaptiveBannerView.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface RNAdManagerAdaptiveBannerView : RCTView
5 |
6 | @property (nonatomic, copy) NSArray *testDevices;
7 | @property (nonatomic, copy) NSDictionary *targeting;
8 | @property (nonatomic, copy) NSString *adPosition;
9 | @property (nonatomic, copy) NSNumber *maxHeight;
10 | @property (nonatomic, strong) NSString *adUnitID;
11 | @property (nonatomic, copy) NSString *correlator;
12 |
13 | @property (nonatomic, copy) RCTBubblingEventBlock onSizeChange;
14 | @property (nonatomic, copy) RCTBubblingEventBlock onAppEvent;
15 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoaded;
16 | @property (nonatomic, copy) RCTBubblingEventBlock onAdFailedToLoad;
17 | @property (nonatomic, copy) RCTBubblingEventBlock onAdOpened;
18 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordImpression;
19 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordClick;
20 |
21 | @property (nonatomic, copy) RCTBubblingEventBlock onAdClosed;
22 |
23 | - (void)loadBanner;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/ios/RNAdManagerAdaptiveBannerView.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManagerAdaptiveBannerView.h"
2 |
3 | #import
4 | #import
5 |
6 | #import
7 |
8 | #import "RNAdManagerUtils.h"
9 |
10 | @interface RNAdManagerAdaptiveBannerView ()
11 |
12 | @property (nonatomic, strong) GAMBannerView *bannerView;
13 |
14 | @end
15 |
16 | @implementation RNAdManagerAdaptiveBannerView
17 | {
18 | BOOL _isFrameLayout;
19 | BOOL _loadOnFrameLayout;
20 | }
21 |
22 | - (void)dealloc
23 | {
24 |
25 | _bannerView.delegate = nil;
26 | _bannerView.adSizeDelegate = nil;
27 | _bannerView.appEventDelegate = nil;
28 | _bannerView.rootViewController = nil;
29 | }
30 |
31 | - (void)setAdUnitID:(NSString *)adUnitID
32 | {
33 | _adUnitID = adUnitID;
34 | }
35 |
36 | - (void)setAdPosition:(NSString *)adPosition
37 | {
38 | _adPosition = adPosition;
39 | }
40 |
41 | - (void)setMaxHeight:(NSNumber *)maxHeight
42 | {
43 | _maxHeight = maxHeight;
44 | }
45 |
46 | - (void)setTargeting:(NSDictionary *)targeting
47 | {
48 | _targeting = targeting;
49 | }
50 |
51 | - (void)setCorrelator:(NSString *)correlator
52 | {
53 | _correlator = correlator;
54 | }
55 |
56 | // Initialise BannerAdView as soon as all the props are set
57 | - (void)createViewIfCan
58 | {
59 | if (!_adUnitID) {
60 | return;
61 | }
62 |
63 | if (_bannerView) {
64 | [_bannerView removeFromSuperview];
65 | }
66 | CGRect frame = self.frame;
67 | // Here safe area is taken into account, hence the view frame is used after the
68 | // view has been laid out.
69 | if (@available(iOS 11.0, *)) {
70 | frame = UIEdgeInsetsInsetRect(self.frame, self.safeAreaInsets);
71 | }
72 | CGFloat viewWidth = frame.size.width;
73 | // Here the current interface orientation is used. If the ad is being preloaded
74 | // for a future orientation change or different orientation, the function for the
75 | // relevant orientation should be used.
76 | GADAdSize adSize;
77 | if ([_adPosition isEqualToString:@"currentOrientationAnchored"]) {
78 | adSize = GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(viewWidth);
79 | } else if ([_adPosition isEqualToString:@"currentOrientationInline"]) {
80 | adSize = GADPortraitInlineAdaptiveBannerAdSizeWithWidth(viewWidth);
81 | } else if ([_adPosition isEqualToString:@"portraitInline"]) {
82 | adSize = GADPortraitInlineAdaptiveBannerAdSizeWithWidth(viewWidth);
83 | } else if ([_adPosition isEqualToString:@"landscapeInline"]) {
84 | adSize = GADLandscapeInlineAdaptiveBannerAdSizeWithWidth(viewWidth);
85 | } else { // _adPosition == "inline"
86 | CGFloat adMaxHeight;
87 | if (_maxHeight == nil) {
88 | CGFloat viewHeight = frame.size.height;
89 | if (viewHeight == 0) {
90 | viewHeight = 350;
91 | }
92 | adMaxHeight = viewHeight;
93 | } else {
94 | adMaxHeight = [_maxHeight doubleValue];
95 | }
96 | adSize = GADInlineAdaptiveBannerAdSizeWithWidthAndMaxHeight(viewWidth, adMaxHeight);
97 | }
98 | GAMBannerView *bannerView = [[GAMBannerView alloc] initWithAdSize:adSize];
99 |
100 | bannerView.delegate = self;
101 | bannerView.adSizeDelegate = self;
102 | bannerView.appEventDelegate = self;
103 | bannerView.rootViewController = RCTPresentedViewController();
104 | bannerView.translatesAutoresizingMaskIntoConstraints = YES;
105 |
106 | GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = _testDevices;
107 | GAMRequest *request = [GAMRequest request];
108 |
109 | GADExtras *extras = [[GADExtras alloc] init];
110 | if (_correlator == nil) {
111 | _correlator = getCorrelator(_adUnitID);
112 | }
113 | extras.additionalParameters = [[NSDictionary alloc] initWithObjectsAndKeys:
114 | _correlator, @"correlator",
115 | nil];
116 | [request registerAdNetworkExtras:extras];
117 |
118 | if (_targeting != nil) {
119 | NSDictionary *customTargeting = [_targeting objectForKey:@"customTargeting"];
120 | if (customTargeting != nil) {
121 | request.customTargeting = customTargeting;
122 | }
123 | NSArray *categoryExclusions = [_targeting objectForKey:@"categoryExclusions"];
124 | if (categoryExclusions != nil) {
125 | request.categoryExclusions = categoryExclusions;
126 | }
127 | NSArray *keywords = [_targeting objectForKey:@"keywords"];
128 | if (keywords != nil) {
129 | request.keywords = keywords;
130 | }
131 | NSString *content_url = [_targeting objectForKey:@"content_url"];
132 | if (content_url != nil) {
133 | request.contentURL = content_url;
134 | }
135 | NSString *publisherProvidedID = [_targeting objectForKey:@"publisherProvidedID"];
136 | if (publisherProvidedID != nil) {
137 | request.publisherProvidedID = publisherProvidedID;
138 | }
139 | }
140 |
141 | bannerView.adUnitID = _adUnitID;
142 | bannerView.adSize = adSize;
143 |
144 | [bannerView loadRequest:request];
145 |
146 | [self addSubview:bannerView];
147 |
148 | _bannerView = bannerView;
149 | }
150 |
151 | - (void)loadBanner {
152 | if (_isFrameLayout) {
153 | [self createViewIfCan];
154 | } else {
155 | _loadOnFrameLayout = YES;
156 | }
157 | }
158 |
159 | -(void)layoutSubviews
160 | {
161 | [super layoutSubviews];
162 | if (!_isFrameLayout) {
163 | _isFrameLayout = YES;
164 | if (_loadOnFrameLayout) {
165 | _loadOnFrameLayout = NO;
166 | [self createViewIfCan];
167 | }
168 | }
169 | }
170 |
171 | # pragma mark GADBannerViewDelegate
172 |
173 | /// Tells the delegate an ad request loaded an ad.
174 | - (void)bannerViewDidReceiveAd:(nonnull GADBannerView *)bannerView
175 | {
176 | if (self.onSizeChange) {
177 | self.onSizeChange(@{
178 | @"type": @"banner",
179 | @"width": @(bannerView.frame.size.width),
180 | @"height": @(bannerView.frame.size.height) });
181 | }
182 | if (self.onAdLoaded) {
183 | self.onAdLoaded(@{
184 | @"type": @"banner",
185 | @"gadSize": @{@"adSize": NSStringFromGADAdSize(bannerView.adSize),
186 | @"width": @(bannerView.frame.size.width),
187 | @"height": @(bannerView.frame.size.height)},
188 | @"isFluid": @"false",
189 | @"measurements": @{@"adWidth": @(bannerView.adSize.size.width),
190 | @"adHeight": @(bannerView.adSize.size.height),
191 | @"width": @(bannerView.frame.size.width),
192 | @"height": @(bannerView.frame.size.height),
193 | @"left": @(bannerView.frame.origin.x),
194 | @"top": @(bannerView.frame.origin.y)},
195 | });
196 | }
197 | }
198 |
199 | /// Tells the delegate an ad request failed.
200 | - (void)bannerView:(nonnull GADBannerView *)bannerView
201 | didFailToReceiveAdWithError:(nonnull NSError *)error
202 | {
203 | if (self.onAdFailedToLoad) {
204 | self.onAdFailedToLoad(@{ @"error": @{ @"message": [error localizedDescription] } });
205 | }
206 | _bannerView.delegate = nil;
207 | _bannerView.adSizeDelegate = nil;
208 | _bannerView.appEventDelegate = nil;
209 | _bannerView.rootViewController = nil;
210 | _bannerView = nil;
211 | }
212 |
213 | - (void)bannerViewDidRecordImpression:(nonnull GADBannerView *)bannerView
214 | {
215 | if (self.onAdRecordImpression) {
216 | self.onAdRecordImpression(@{});
217 | }
218 | }
219 |
220 | - (void)bannerViewDidRecordClick:(nonnull GADBannerView *)bannerView
221 | {
222 | if (self.onAdRecordClick) {
223 | self.onAdRecordClick(@{});
224 | }
225 | }
226 |
227 | /// Tells the delegate that a full screen view will be presented in response
228 | /// to the user clicking on an ad.
229 | - (void)bannerViewWillPresentScreen:(nonnull GADBannerView *)bannerView
230 | {
231 | if (self.onAdOpened) {
232 | self.onAdOpened(@{});
233 | }
234 | }
235 |
236 | /// Tells the delegate that the full screen view will be dismissed.
237 | - (void)bannerViewWillDismissScreen:(nonnull GADBannerView *)bannerView
238 | {
239 | if (self.onAdClosed) {
240 | self.onAdClosed(@{});
241 | }
242 | }
243 |
244 | # pragma mark GADAdSizeDelegate
245 |
246 | - (void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size
247 | {
248 | CGSize adSize = CGSizeFromGADAdSize(size);
249 | self.onSizeChange(@{
250 | @"type": @"banner",
251 | @"width": @(adSize.width),
252 | @"height": @(adSize.height) });
253 | }
254 |
255 | # pragma mark GADAppEventDelegate
256 |
257 | - (void)adView:(GADBannerView *)banner didReceiveAppEvent:(NSString *)name withInfo:(NSString *)info
258 | {
259 | if (self.onAppEvent) {
260 | self.onAppEvent(@{ @"name": name, @"info": info });
261 | }
262 | }
263 |
264 | @end
265 |
--------------------------------------------------------------------------------
/ios/RNAdManagerAdaptiveBannerViewManager.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface RNAdManagerAdaptiveBannerViewManager : RCTViewManager
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/ios/RNAdManagerAdaptiveBannerViewManager.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManagerAdaptiveBannerViewManager.h"
2 | #import "RNAdManagerAdaptiveBannerView.h"
3 |
4 | #import
5 | #import
6 | #import
7 |
8 | @implementation RNAdManagerAdaptiveBannerViewManager
9 |
10 | RCT_EXPORT_MODULE(CTKAdaptiveBannerViewManager)
11 |
12 | @synthesize bridge = _bridge;
13 |
14 | - (UIView *)view
15 | {
16 | return [RNAdManagerAdaptiveBannerView new];
17 | }
18 |
19 | RCT_EXPORT_VIEW_PROPERTY(size, NSNumber)
20 | RCT_EXPORT_VIEW_PROPERTY(placementId, NSString)
21 | RCT_EXPORT_VIEW_PROPERTY(onAdLoad, RCTBubblingEventBlock)
22 | RCT_EXPORT_VIEW_PROPERTY(onAdPress, RCTBubblingEventBlock)
23 | RCT_EXPORT_VIEW_PROPERTY(onAdError, RCTBubblingEventBlock)
24 |
25 | RCT_EXPORT_METHOD(loadBanner:(nonnull NSNumber *)reactTag)
26 | {
27 | [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) {
28 | RNAdManagerAdaptiveBannerView *view = viewRegistry[reactTag];
29 | if (![view isKindOfClass:[RNAdManagerAdaptiveBannerView class]]) {
30 | RCTLogError(@"Invalid view returned from registry, expecting RNAdManagerAdaptiveBannerView, got: %@", view);
31 | } else {
32 | [view loadBanner];
33 | }
34 | }];
35 | }
36 |
37 | RCT_EXPORT_VIEW_PROPERTY(adPosition, NSString)
38 | RCT_EXPORT_VIEW_PROPERTY(maxHeight, NSNumber)
39 | RCT_EXPORT_VIEW_PROPERTY(adUnitID, NSString)
40 | RCT_EXPORT_VIEW_PROPERTY(correlator, NSString)
41 | RCT_EXPORT_VIEW_PROPERTY(testDevices, NSArray)
42 | RCT_EXPORT_VIEW_PROPERTY(targeting, NSDictionary)
43 |
44 | RCT_EXPORT_VIEW_PROPERTY(onSizeChange, RCTBubblingEventBlock)
45 | RCT_EXPORT_VIEW_PROPERTY(onAppEvent, RCTBubblingEventBlock)
46 | RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTBubblingEventBlock)
47 | RCT_EXPORT_VIEW_PROPERTY(onAdFailedToLoad, RCTBubblingEventBlock)
48 | RCT_EXPORT_VIEW_PROPERTY(onAdOpened, RCTBubblingEventBlock)
49 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordImpression, RCTBubblingEventBlock)
50 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordClick, RCTBubblingEventBlock)
51 |
52 | RCT_EXPORT_VIEW_PROPERTY(onAdClosed, RCTBubblingEventBlock)
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/ios/RNAdManagerBannerView.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface RNAdManagerBannerView : RCTView
5 |
6 | @property (nonatomic, copy) NSArray *validAdSizes;
7 | @property (nonatomic, copy) NSArray *testDevices;
8 | @property (nonatomic, copy) NSDictionary *targeting;
9 | @property (nonatomic, copy) NSString *adSize;
10 | @property (nonatomic, strong) NSString *adUnitID;
11 | @property (nonatomic, copy) NSString *correlator;
12 |
13 | @property (nonatomic, copy) RCTBubblingEventBlock onSizeChange;
14 | @property (nonatomic, copy) RCTBubblingEventBlock onAppEvent;
15 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoaded;
16 | @property (nonatomic, copy) RCTBubblingEventBlock onAdFailedToLoad;
17 | @property (nonatomic, copy) RCTBubblingEventBlock onAdOpened;
18 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordImpression;
19 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordClick;
20 |
21 | @property (nonatomic, copy) RCTBubblingEventBlock onAdClosed;
22 |
23 | - (void)loadBanner;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/ios/RNAdManagerBannerView.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManagerBannerView.h"
2 |
3 | #import
4 | #import
5 |
6 | #import
7 |
8 | #include "RCTConvert+GADAdSize.h"
9 | #import "RNAdManagerUtils.h"
10 |
11 | @interface RNAdManagerBannerView ()
12 |
13 | @property (nonatomic, strong) GAMBannerView *bannerView;
14 |
15 | @end
16 |
17 | @implementation RNAdManagerBannerView
18 |
19 | - (void)dealloc
20 | {
21 |
22 | _bannerView.delegate = nil;
23 | _bannerView.adSizeDelegate = nil;
24 | _bannerView.appEventDelegate = nil;
25 | _bannerView.rootViewController = nil;
26 | }
27 |
28 | - (void)setAdUnitID:(NSString *)adUnitID
29 | {
30 | _adUnitID = adUnitID;
31 | // [self createViewIfCan];
32 | }
33 |
34 | - (void)setAdSize:(NSString *)adSize
35 | {
36 | _adSize = adSize;
37 | // [self createViewIfCan];
38 | }
39 |
40 | - (void)setValidAdSizes:(NSArray *)adSizes
41 | {
42 | __block NSMutableArray *validAdSizes = [[NSMutableArray alloc] initWithCapacity:adSizes.count];
43 | [adSizes enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, __unused BOOL *stop) {
44 | GADAdSize adSize = [RCTConvert GADAdSize:jsonValue];
45 | if (GADAdSizeEqualToSize(adSize, GADAdSizeInvalid)) {
46 | RCTLogWarn(@"Invalid adSize %@", jsonValue);
47 | } else if (![validAdSizes containsObject:NSValueFromGADAdSize(adSize)]) {
48 | [validAdSizes addObject:NSValueFromGADAdSize(adSize)];
49 | }
50 | }];
51 |
52 | _validAdSizes = validAdSizes;
53 | // [self createViewIfCan];
54 | }
55 |
56 | - (void)setTargeting:(NSDictionary *)targeting
57 | {
58 | _targeting = targeting;
59 | // [self createViewIfCan];
60 | }
61 |
62 | - (void)setCorrelator:(NSString *)correlator
63 | {
64 | _correlator = correlator;
65 | }
66 |
67 | // Initialise BannerAdView as soon as all the props are set
68 | - (void)createViewIfCan
69 | {
70 | if (!_adUnitID || !_adSize/* || !_validAdSizes || !_targeting*/) {
71 | return;
72 | }
73 |
74 | if (_bannerView) {
75 | [_bannerView removeFromSuperview];
76 | }
77 |
78 | GADAdSize adSize = [RCTConvert GADAdSize:_adSize];
79 | GAMBannerView *bannerView;
80 | if (!GADAdSizeEqualToSize(adSize, GADAdSizeInvalid)) {
81 | // self.bannerView.adSize = adSize;
82 | bannerView = [[GAMBannerView alloc] initWithAdSize:adSize];
83 | } else {
84 | bannerView = [[GAMBannerView alloc] initWithAdSize:GADAdSizeBanner];
85 | }
86 |
87 | bannerView.delegate = self;
88 | bannerView.adSizeDelegate = self;
89 | bannerView.appEventDelegate = self;
90 | bannerView.rootViewController = RCTPresentedViewController();
91 | bannerView.translatesAutoresizingMaskIntoConstraints = YES;
92 |
93 | GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = _testDevices;
94 | GAMRequest *request = [GAMRequest request];
95 |
96 | GADExtras *extras = [[GADExtras alloc] init];
97 | if (_correlator == nil) {
98 | _correlator = getCorrelator(_adUnitID);
99 | }
100 | extras.additionalParameters = [[NSDictionary alloc] initWithObjectsAndKeys:
101 | _correlator, @"correlator",
102 | nil];
103 | [request registerAdNetworkExtras:extras];
104 |
105 | if (_targeting != nil) {
106 | NSDictionary *customTargeting = [_targeting objectForKey:@"customTargeting"];
107 | if (customTargeting != nil) {
108 | request.customTargeting = customTargeting;
109 | }
110 | NSArray *categoryExclusions = [_targeting objectForKey:@"categoryExclusions"];
111 | if (categoryExclusions != nil) {
112 | request.categoryExclusions = categoryExclusions;
113 | }
114 | NSArray *keywords = [_targeting objectForKey:@"keywords"];
115 | if (keywords != nil) {
116 | request.keywords = keywords;
117 | }
118 | NSString *content_url = [_targeting objectForKey:@"content_url"];
119 | if (content_url != nil) {
120 | request.contentURL = content_url;
121 | }
122 | NSString *publisherProvidedID = [_targeting objectForKey:@"publisherProvidedID"];
123 | if (publisherProvidedID != nil) {
124 | request.publisherProvidedID = publisherProvidedID;
125 | }
126 | // NSDictionary *location = [_targeting objectForKey:@"location"];
127 | // if (location != nil) {
128 | // CGFloat latitude = [[location objectForKey:@"latitude"] doubleValue];
129 | // CGFloat longitude = [[location objectForKey:@"longitude"] doubleValue];
130 | // CGFloat accuracy = [[location objectForKey:@"accuracy"] doubleValue];
131 | // [request setLocationWithLatitude:latitude longitude:longitude accuracy:accuracy];
132 | // }
133 | }
134 |
135 | bannerView.adUnitID = _adUnitID;
136 |
137 | bannerView.validAdSizes = _validAdSizes;
138 |
139 | [bannerView loadRequest:request];
140 |
141 | [self addSubview:bannerView];
142 |
143 | _bannerView = bannerView;
144 | }
145 |
146 | - (void)loadBanner {
147 | [self createViewIfCan];
148 | }
149 |
150 | # pragma mark GADBannerViewDelegate
151 |
152 | /// Tells the delegate an ad request loaded an ad.
153 | - (void)bannerViewDidReceiveAd:(nonnull GADBannerView *)bannerView
154 | {
155 | if (self.onSizeChange) {
156 | self.onSizeChange(@{
157 | @"type": @"banner",
158 | @"width": @(bannerView.frame.size.width),
159 | @"height": @(bannerView.frame.size.height) });
160 | }
161 | if (self.onAdLoaded) {
162 | // self.onAdLoaded(@{
163 | // @"type": @"banner",
164 | // @"gadSize": @{@"width": @(bannerView.frame.size.width),
165 | // @"height": @(bannerView.frame.size.height)},
166 | // });
167 | self.onAdLoaded(@{
168 | @"type": @"banner",
169 | @"gadSize": @{@"adSize": NSStringFromGADAdSize(bannerView.adSize),
170 | @"width": @(bannerView.frame.size.width),
171 | @"height": @(bannerView.frame.size.height)},
172 | @"isFluid": GADAdSizeIsFluid(bannerView.adSize) ? @"true" : @"false",
173 | @"measurements": @{@"adWidth": @(bannerView.adSize.size.width),
174 | @"adHeight": @(bannerView.adSize.size.height),
175 | @"width": @(bannerView.frame.size.width),
176 | @"height": @(bannerView.frame.size.height),
177 | @"left": @(bannerView.frame.origin.x),
178 | @"top": @(bannerView.frame.origin.y)},
179 | });
180 | }
181 | }
182 |
183 | /// Tells the delegate an ad request failed.
184 | - (void)bannerView:(nonnull GADBannerView *)bannerView
185 | didFailToReceiveAdWithError:(nonnull NSError *)error
186 | {
187 | if (self.onAdFailedToLoad) {
188 | self.onAdFailedToLoad(@{ @"error": @{ @"message": [error localizedDescription] } });
189 | }
190 | _bannerView.delegate = nil;
191 | _bannerView.adSizeDelegate = nil;
192 | _bannerView.appEventDelegate = nil;
193 | _bannerView.rootViewController = nil;
194 | _bannerView = nil;
195 | }
196 |
197 | - (void)bannerViewDidRecordImpression:(nonnull GADBannerView *)bannerView
198 | {
199 | if (self.onAdRecordImpression) {
200 | self.onAdRecordImpression(@{});
201 | }
202 | }
203 |
204 | - (void)bannerViewDidRecordClick:(nonnull GADBannerView *)bannerView
205 | {
206 | if (self.onAdRecordClick) {
207 | self.onAdRecordClick(@{});
208 | }
209 | }
210 |
211 | /// Tells the delegate that a full screen view will be presented in response
212 | /// to the user clicking on an ad.
213 | - (void)bannerViewWillPresentScreen:(nonnull GADBannerView *)bannerView
214 | {
215 | if (self.onAdOpened) {
216 | self.onAdOpened(@{});
217 | }
218 | }
219 |
220 | /// Tells the delegate that the full screen view will be dismissed.
221 | - (void)bannerViewWillDismissScreen:(nonnull GADBannerView *)bannerView
222 | {
223 | if (self.onAdClosed) {
224 | self.onAdClosed(@{});
225 | }
226 | }
227 |
228 | # pragma mark GADAdSizeDelegate
229 |
230 | - (void)adView:(GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size
231 | {
232 | CGSize adSize = CGSizeFromGADAdSize(size);
233 | self.onSizeChange(@{
234 | @"type": @"banner",
235 | @"width": @(adSize.width),
236 | @"height": @(adSize.height) });
237 | }
238 |
239 | # pragma mark GADAppEventDelegate
240 |
241 | - (void)adView:(GADBannerView *)banner didReceiveAppEvent:(NSString *)name withInfo:(NSString *)info
242 | {
243 | if (self.onAppEvent) {
244 | self.onAppEvent(@{ @"name": name, @"info": info });
245 | }
246 | }
247 |
248 | @end
249 |
--------------------------------------------------------------------------------
/ios/RNAdManagerBannerViewManager.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface RNAdManagerBannerViewManager : RCTViewManager
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/ios/RNAdManagerBannerViewManager.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManagerBannerViewManager.h"
2 | #import "RNAdManagerBannerView.h"
3 |
4 | #import
5 | #import
6 | #import
7 |
8 | @implementation RNAdManagerBannerViewManager
9 |
10 | RCT_EXPORT_MODULE(CTKBannerViewManager)
11 |
12 | @synthesize bridge = _bridge;
13 |
14 | - (UIView *)view
15 | {
16 | // if (![EXFacebook facebookAppIdFromNSBundle]) {
17 | // RCTLogWarn(@"No Facebook app id is specified. Facebook ads may have undefined behavior.");
18 | // }
19 | return [RNAdManagerBannerView new];
20 | }
21 |
22 | RCT_EXPORT_VIEW_PROPERTY(size, NSNumber)
23 | RCT_EXPORT_VIEW_PROPERTY(placementId, NSString)
24 | RCT_EXPORT_VIEW_PROPERTY(onAdLoad, RCTBubblingEventBlock)
25 | RCT_EXPORT_VIEW_PROPERTY(onAdPress, RCTBubblingEventBlock)
26 | RCT_EXPORT_VIEW_PROPERTY(onAdError, RCTBubblingEventBlock)
27 |
28 | RCT_EXPORT_METHOD(loadBanner:(nonnull NSNumber *)reactTag)
29 | {
30 | [_bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) {
31 | RNAdManagerBannerView *view = viewRegistry[reactTag];
32 | if (![view isKindOfClass:[RNAdManagerBannerView class]]) {
33 | RCTLogError(@"Invalid view returned from registry, expecting RNAdManagerBannerView, got: %@", view);
34 | } else {
35 | [view loadBanner];
36 | }
37 | }];
38 | }
39 |
40 | //RCT_REMAP_VIEW_PROPERTY(adSize, _bannerView.adSize, GADAdSize)
41 | //RCT_REMAP_VIEW_PROPERTY(adUnitID, _bannerView.adUnitID, NSString)
42 | RCT_EXPORT_VIEW_PROPERTY(adSize, NSString)
43 | RCT_EXPORT_VIEW_PROPERTY(adUnitID, NSString)
44 | RCT_EXPORT_VIEW_PROPERTY(correlator, NSString)
45 | RCT_EXPORT_VIEW_PROPERTY(validAdSizes, NSArray)
46 | RCT_EXPORT_VIEW_PROPERTY(testDevices, NSArray)
47 | RCT_EXPORT_VIEW_PROPERTY(targeting, NSDictionary)
48 |
49 | RCT_EXPORT_VIEW_PROPERTY(onSizeChange, RCTBubblingEventBlock)
50 | RCT_EXPORT_VIEW_PROPERTY(onAppEvent, RCTBubblingEventBlock)
51 | RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTBubblingEventBlock)
52 | RCT_EXPORT_VIEW_PROPERTY(onAdFailedToLoad, RCTBubblingEventBlock)
53 | RCT_EXPORT_VIEW_PROPERTY(onAdOpened, RCTBubblingEventBlock)
54 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordImpression, RCTBubblingEventBlock)
55 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordClick, RCTBubblingEventBlock)
56 |
57 | RCT_EXPORT_VIEW_PROPERTY(onAdClosed, RCTBubblingEventBlock)
58 |
59 | @end
60 |
--------------------------------------------------------------------------------
/ios/RNAdManagerInterstitial.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 |
6 | @interface RNAdManagerInterstitial : RCTEventEmitter
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/ios/RNAdManagerInterstitial.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManagerInterstitial.h"
2 | #import "RNAdManagerUtils.h"
3 |
4 | #import
5 |
6 | static NSString *const kEventAdLoaded = @"interstitialAdLoaded";
7 | static NSString *const kEventAdFailedToLoad = @"interstitialAdFailedToLoad";
8 | static NSString *const kEventAdOpened = @"interstitialAdOpened";
9 | static NSString *const kEventAdFailedToOpen = @"interstitialAdFailedToOpen";
10 | static NSString *const kEventAdClosed = @"interstitialAdClosed";
11 |
12 | @implementation RNAdManagerInterstitial
13 | {
14 | GADInterstitialAd *_interstitial;
15 | NSString *_adUnitID;
16 | NSArray *_testDevices;
17 | NSDictionary *_targeting;
18 |
19 | RCTPromiseResolveBlock _requestAdResolve;
20 | RCTPromiseRejectBlock _requestAdReject;
21 | BOOL hasListeners;
22 | }
23 |
24 | - (dispatch_queue_t)methodQueue
25 | {
26 | return dispatch_get_main_queue();
27 | }
28 |
29 | + (BOOL)requiresMainQueueSetup
30 | {
31 | return NO;
32 | }
33 |
34 | RCT_EXPORT_MODULE(CTKInterstitial)
35 |
36 | - (NSArray *)supportedEvents
37 | {
38 | return @[
39 | kEventAdLoaded,
40 | kEventAdFailedToLoad,
41 | kEventAdOpened,
42 | kEventAdFailedToOpen,
43 | kEventAdClosed ];
44 | }
45 |
46 | #pragma mark exported methods
47 |
48 | RCT_EXPORT_METHOD(setAdUnitID:(NSString *)adUnitID)
49 | {
50 | _adUnitID = adUnitID;
51 | }
52 |
53 | RCT_EXPORT_METHOD(setTestDevices:(NSArray *)testDevices)
54 | {
55 | _testDevices = RNAdManagerProcessTestDevices(testDevices, GADSimulatorID);
56 | }
57 |
58 | RCT_EXPORT_METHOD(setTargeting:(NSDictionary *)targeting)
59 | {
60 | _targeting = targeting;
61 | }
62 |
63 | RCT_EXPORT_METHOD(requestAd:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
64 | {
65 | _requestAdResolve = nil;
66 | _requestAdReject = nil;
67 |
68 | BOOL isReady = [_interstitial canPresentFromRootViewController:[UIApplication sharedApplication].delegate.window.rootViewController error:nil];
69 | if (!isReady) {
70 | _requestAdResolve = resolve;
71 | _requestAdReject = reject;
72 |
73 | GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = _testDevices;
74 | GAMRequest *request = [GAMRequest request];
75 |
76 | if (_targeting != nil) {
77 | NSDictionary *customTargeting = [_targeting objectForKey:@"customTargeting"];
78 | if (customTargeting != nil) {
79 | request.customTargeting = customTargeting;
80 | }
81 | NSArray *categoryExclusions = [_targeting objectForKey:@"categoryExclusions"];
82 | if (categoryExclusions != nil) {
83 | request.categoryExclusions = categoryExclusions;
84 | }
85 | NSArray *keywords = [_targeting objectForKey:@"keywords"];
86 | if (keywords != nil) {
87 | request.keywords = keywords;
88 | }
89 | NSString *content_url = [_targeting objectForKey:@"content_url"];
90 | if (content_url != nil) {
91 | request.contentURL = content_url;
92 | }
93 | NSString *publisherProvidedID = [_targeting objectForKey:@"publisherProvidedID"];
94 | if (publisherProvidedID != nil) {
95 | request.publisherProvidedID = publisherProvidedID;
96 | }
97 | // NSDictionary *location = [_targeting objectForKey:@"location"];
98 | // if (location != nil) {
99 | // CGFloat latitude = [[location objectForKey:@"latitude"] doubleValue];
100 | // CGFloat longitude = [[location objectForKey:@"longitude"] doubleValue];
101 | // CGFloat accuracy = [[location objectForKey:@"accuracy"] doubleValue];
102 | // [request setLocationWithLatitude:latitude longitude:longitude accuracy:accuracy];
103 | // }
104 | }
105 |
106 | [GADInterstitialAd loadWithAdUnitID:_adUnitID request:request completionHandler:^(GADInterstitialAd * _Nullable interstitialAd, NSError * _Nullable error) {
107 | if (error) {
108 | if (hasListeners) {
109 | NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError(@"E_AD_REQUEST_FAILED", error.localizedDescription, error);
110 | [self sendEventWithName:kEventAdFailedToLoad body:jsError];
111 | }
112 | _requestAdReject(@"E_AD_REQUEST_FAILED", error.localizedDescription, error);
113 | _interstitial = nil;
114 | return;
115 | }
116 |
117 | if (hasListeners) {
118 | [self sendEventWithName:kEventAdLoaded body:@{ @"type": @"interstitial" }];
119 | }
120 | _requestAdResolve(nil);
121 |
122 | _interstitial = interstitialAd;
123 | _interstitial.fullScreenContentDelegate = self;
124 |
125 | }];
126 | } else {
127 | reject(@"E_AD_ALREADY_LOADED", @"Ad is already loaded.", nil);
128 | }
129 | }
130 |
131 | RCT_EXPORT_METHOD(showAd:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
132 | {
133 | // may not need to check if it is ready..
134 | // BOOL isReady = [_interstitial canPresentFromRootViewController:[UIApplication sharedApplication].delegate.window.rootViewController error:nil];
135 | if (_interstitial) {
136 | [_interstitial presentFromRootViewController:[UIApplication sharedApplication].delegate.window.rootViewController];
137 | resolve(nil);
138 | }
139 | else {
140 | reject(@"E_AD_NOT_READY", @"Ad is not ready.", nil);
141 | }
142 | }
143 |
144 | RCT_EXPORT_METHOD(isReady:(RCTResponseSenderBlock)callback)
145 | {
146 | BOOL isReady = [_interstitial canPresentFromRootViewController:[UIApplication sharedApplication].delegate.window.rootViewController error:nil];
147 | callback(@[[NSNumber numberWithBool:isReady]]);
148 | }
149 |
150 | - (void)startObserving
151 | {
152 | hasListeners = YES;
153 | }
154 |
155 | - (void)stopObserving
156 | {
157 | hasListeners = NO;
158 | }
159 |
160 | #pragma mark GADFullScreenContentDelegate
161 |
162 | - (void)adWillPresentFullScreenContent:(id)ad {
163 | NSLog(@"Ad did present full screen content.");
164 | if (hasListeners){
165 | [self sendEventWithName:kEventAdOpened body:nil];
166 | }
167 | }
168 |
169 |
170 | - (void)ad:(id)ad didFailToPresentFullScreenContentWithError:(NSError *)error {
171 | NSLog(@"Ad failed to present full screen content with error %@.", [error localizedDescription]);
172 | if (hasListeners) {
173 | NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError(@"E_AD_PRESENT_FAILED", error.localizedDescription, error);
174 | [self sendEventWithName:kEventAdFailedToOpen body:jsError];
175 | }
176 | }
177 |
178 | - (void)adDidDismissFullScreenContent:(id)ad {
179 | NSLog(@"Ad did dismiss full screen content.");
180 | if (hasListeners) {
181 | [self sendEventWithName:kEventAdClosed body:nil];
182 | }
183 | _interstitial = nil;
184 | }
185 |
186 | @end
187 |
--------------------------------------------------------------------------------
/ios/RNAdManagerUtils.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | NSArray *__nullable RNAdManagerProcessTestDevices(NSArray *__nullable testDevices, id _Nonnull simulatorId);
4 | NSString *__nullable getRandomPINString(NSInteger length);
5 | NSString *__nullable getCorrelator(NSString *__nullable adUnitID);
6 |
--------------------------------------------------------------------------------
/ios/RNAdManagerUtils.m:
--------------------------------------------------------------------------------
1 | #import "RNAdManagerUtils.h"
2 |
3 | static NSMutableDictionary *correlators;
4 |
5 | NSArray *__nullable RNAdManagerProcessTestDevices(NSArray *__nullable testDevices, id _Nonnull simulatorId)
6 | {
7 | if (testDevices == NULL) {
8 | return testDevices;
9 | }
10 | NSInteger index = [testDevices indexOfObject:@"SIMULATOR"];
11 | if (index == NSNotFound) {
12 | return testDevices;
13 | }
14 | NSMutableArray *values = [testDevices mutableCopy];
15 | [values removeObjectAtIndex:index];
16 | [values addObject:simulatorId];
17 | return values;
18 | }
19 |
20 | NSString *__nullable getRandomPINString(NSInteger length)
21 | {
22 | NSMutableString *returnString = [NSMutableString stringWithCapacity:length];
23 |
24 | NSString *numbers = @"0123456789";
25 |
26 | // First number cannot be 0
27 | [returnString appendFormat:@"%C", [numbers characterAtIndex:(arc4random() % ([numbers length]-1))+1]];
28 |
29 | for (int i = 1; i < length; i++)
30 | {
31 | [returnString appendFormat:@"%C", [numbers characterAtIndex:arc4random() % [numbers length]]];
32 | }
33 |
34 | return returnString;
35 | }
36 |
37 | NSString *__nullable getCorrelator(NSString *adUnitID)
38 | {
39 | if (correlators == nil) {
40 | correlators = [NSMutableDictionary new];
41 | }
42 |
43 | NSString *correlator = [correlators objectForKey:adUnitID];
44 |
45 | if (correlator == nil) {
46 | correlator = getRandomPINString(16);
47 | [correlators setValue:correlator forKey:adUnitID];
48 | }
49 |
50 | return correlator;
51 | }
52 |
--------------------------------------------------------------------------------
/ios/ReactNativeAdManager.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-ad-manager",
3 | "title": "React Native Ad Manager",
4 | "version": "2.1.2",
5 | "description": "A react-native component for Google Ad Manager banners, interstitials and native ads.",
6 | "main": "lib/commonjs/index",
7 | "module": "lib/module/index",
8 | "types": "lib/typescript/index.d.ts",
9 | "react-native": "src/index",
10 | "source": "src/index",
11 | "files": [
12 | "src",
13 | "lib",
14 | "android",
15 | "ios",
16 | "cpp",
17 | "react-native-ad-manager.podspec",
18 | "!lib/typescript/example",
19 | "!android/build",
20 | "!ios/build",
21 | "!**/__tests__",
22 | "!**/__fixtures__",
23 | "!**/__mocks__"
24 | ],
25 | "scripts": {
26 | "test": "jest",
27 | "typescript": "tsc --noEmit",
28 | "lint": "eslint \"**/*.{js,ts,tsx}\"",
29 | "prepare": "bob build",
30 | "release": "release-it",
31 | "example": "yarn --cwd example",
32 | "pods": "cd example && pod-install --quiet",
33 | "bootstrap": "yarn example && yarn && yarn pods"
34 | },
35 | "keywords": [
36 | "react-native",
37 | "ios",
38 | "android"
39 | ],
40 | "repository": "https://github.com/NZME/react-native-ad-manager",
41 | "author": "Matej Drobnic (https://github.com/matejdr)",
42 | "license": "MIT",
43 | "licenseFilename": "LICENSE",
44 | "readmeFilename": "README.md",
45 | "bugs": {
46 | "url": "https://github.com/NZME/react-native-ad-manager/issues"
47 | },
48 | "homepage": "https://github.com/NZME/react-native-ad-manager#readme",
49 | "publishConfig": {
50 | "registry": "https://registry.npmjs.org/"
51 | },
52 | "devDependencies": {
53 | "@commitlint/config-conventional": "^11.0.0",
54 | "@react-native-community/eslint-config": "^2.0.0",
55 | "@release-it/conventional-changelog": "^2.0.0",
56 | "@types/jest": "^26.0.0",
57 | "@types/react": "^16.9.19",
58 | "@types/react-native": "0.62.13",
59 | "commitlint": "^11.0.0",
60 | "eslint": "^7.2.0",
61 | "eslint-config-prettier": "^7.0.0",
62 | "eslint-plugin-prettier": "^3.1.3",
63 | "husky": "^6.0.0",
64 | "jest": "^26.0.1",
65 | "pod-install": "^0.1.0",
66 | "prettier": "^2.0.5",
67 | "react": "17.0.2",
68 | "react-native": "0.72.17",
69 | "react-native-builder-bob": "^0.18.0",
70 | "release-it": "^14.2.2",
71 | "typescript": "^4.1.3"
72 | },
73 | "peerDependencies": {
74 | "react": "*",
75 | "react-native": "*"
76 | },
77 | "jest": {
78 | "preset": "react-native",
79 | "modulePathIgnorePatterns": [
80 | "/example/node_modules",
81 | "/lib/"
82 | ]
83 | },
84 | "commitlint": {
85 | "extends": [
86 | "@commitlint/config-conventional"
87 | ]
88 | },
89 | "release-it": {
90 | "git": {
91 | "commitMessage": "chore: release ${version}",
92 | "tagName": "v${version}"
93 | },
94 | "npm": {
95 | "publish": true
96 | },
97 | "github": {
98 | "release": true
99 | },
100 | "plugins": {
101 | "@release-it/conventional-changelog": {
102 | "preset": "angular"
103 | }
104 | }
105 | },
106 | "eslintConfig": {
107 | "root": true,
108 | "extends": [
109 | "@react-native-community",
110 | "prettier"
111 | ],
112 | "rules": {
113 | "prettier/prettier": [
114 | "error",
115 | {
116 | "quoteProps": "consistent",
117 | "singleQuote": true,
118 | "tabWidth": 2,
119 | "trailingComma": "es5",
120 | "useTabs": false
121 | }
122 | ]
123 | }
124 | },
125 | "eslintIgnore": [
126 | "node_modules/",
127 | "lib/"
128 | ],
129 | "prettier": {
130 | "quoteProps": "consistent",
131 | "singleQuote": true,
132 | "tabWidth": 2,
133 | "trailingComma": "es5",
134 | "useTabs": false
135 | },
136 | "react-native-builder-bob": {
137 | "source": "src",
138 | "output": "lib",
139 | "targets": [
140 | "commonjs",
141 | "module",
142 | [
143 | "typescript",
144 | {
145 | "project": "tsconfig.build.json"
146 | }
147 | ]
148 | ]
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/react-native-ad-manager.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "react-native-ad-manager"
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.description = <<-DESC
10 | react-native-ad-manager
11 | DESC
12 | s.homepage = package["homepage"]
13 | s.license = package["license"]
14 | s.authors = package["author"]
15 |
16 | s.platforms = { :ios => "15.0" }
17 | s.source = { :git => "https://github.com/NZME/react-native-ad-manager.git", :tag => "v#{s.version}" }
18 |
19 | s.source_files = "ios/**/*.{h,m,mm}"
20 | s.requires_arc = true
21 |
22 | s.dependency "React-Core"
23 | s.dependency 'Google-Mobile-Ads-SDK', '~> 11.4.0'
24 | s.dependency "GoogleMobileAdsMediationFacebook"
25 | end
26 |
--------------------------------------------------------------------------------
/scripts/bootstrap.js:
--------------------------------------------------------------------------------
1 | const os = require('os');
2 | const path = require('path');
3 | const child_process = require('child_process');
4 |
5 | const root = path.resolve(__dirname, '..');
6 | const args = process.argv.slice(2);
7 | const options = {
8 | cwd: process.cwd(),
9 | env: process.env,
10 | stdio: 'inherit',
11 | encoding: 'utf-8',
12 | };
13 |
14 | if (os.type() === 'Windows_NT') {
15 | options.shell = true
16 | }
17 |
18 | let result;
19 |
20 | if (process.cwd() !== root || args.length) {
21 | // We're not in the root of the project, or additional arguments were passed
22 | // In this case, forward the command to `yarn`
23 | result = child_process.spawnSync('yarn', args, options);
24 | } else {
25 | // If `yarn` is run without arguments, perform bootstrap
26 | result = child_process.spawnSync('yarn', ['bootstrap'], options);
27 | }
28 |
29 | process.exitCode = result.status;
30 |
--------------------------------------------------------------------------------
/src/AdManagerEvent.ts:
--------------------------------------------------------------------------------
1 | import type { IAdManagerTemplateImage } from './AdManagerTypes';
2 |
3 | export interface IAdManagerEventBase {
4 | target?: number;
5 | }
6 |
7 | export interface IAdManagerEventErrorPayload {
8 | message: string;
9 | framesToPop?: number;
10 | }
11 |
12 | export interface IAdManagerEventError extends IAdManagerEventBase {
13 | error: IAdManagerEventErrorPayload;
14 | }
15 |
16 | export interface IAdManagerEventAppEvent extends IAdManagerEventBase {
17 | name: string;
18 | info: string;
19 | }
20 |
21 | export interface IAdManagerEventLoadedInterstitial extends IAdManagerEventBase {
22 | type: 'interstitial';
23 | }
24 |
25 | export interface IAdManagerEventLoadedBanner extends IAdManagerEventBase {
26 | type: 'banner';
27 | gadSize: {
28 | adSize: string;
29 | width: number;
30 | height: number;
31 | };
32 | isFluid?: string;
33 | measurements?: {
34 | adWidth: number;
35 | adHeight: number;
36 | width: number;
37 | height: number;
38 | left: number;
39 | top: number;
40 | };
41 | }
42 |
43 | export interface IAdManagerEventLoadedTemplate {
44 | type: 'template';
45 | templateID: string;
46 | [key: string]: IAdManagerTemplateImage | string;
47 | }
48 |
49 | export interface IAdManagerEventLoadedNative {
50 | type: 'native';
51 | headline?: string;
52 | bodyText?: string;
53 | callToActionText?: string;
54 | advertiserName?: string;
55 | starRating?: string;
56 | storeName?: string;
57 | price?: string;
58 | icon?: IAdManagerTemplateImage;
59 | images?: IAdManagerTemplateImage[];
60 | socialContext?: string;
61 | }
62 |
63 | export interface IAdManagerEventSize extends IAdManagerEventBase {
64 | type: 'banner';
65 | width: number;
66 | height: number;
67 | }
68 |
69 | export interface IAdManagerEventCustomClick {
70 | assetName: string;
71 | [key: string]: string;
72 | }
73 |
--------------------------------------------------------------------------------
/src/AdManagerTypes.ts:
--------------------------------------------------------------------------------
1 | export type TReactNodeHandleRef = number;
2 |
3 | export interface IAdManagerTargetingLocation {
4 | latitude?: number;
5 | longitude?: number;
6 | accuracy?: number;
7 | }
8 |
9 | export interface IAdManagerTargeting {
10 | /**
11 | * Arbitrary object of custom targeting information.
12 | */
13 | customTargeting?: Record;
14 |
15 | /**
16 | * Array of exclusion labels.
17 | */
18 | categoryExclusions?: string[];
19 |
20 | /**
21 | * Array of keyword strings.
22 | */
23 | keywords?: string[];
24 |
25 | /**
26 | * Applications that monetize content matching a webpage's content may pass
27 | * a content URL for keyword targeting.
28 | */
29 | contentURL?: string;
30 |
31 | /**
32 | * You can set a publisher provided identifier (PPID) for use in frequency
33 | * capping, audience segmentation and targeting, sequential ad rotation, and
34 | * other audience-based ad delivery controls across devices.
35 | */
36 | publisherProvidedID?: string;
37 |
38 | /**
39 | * The user’s current location may be used to deliver more relevant ads.
40 | */
41 | /**
42 | * @deprecated Location has deleted from Ad Request since location data is not used
43 | * by Google to target ads. Use third-party APIs to provide the
44 | * information to third-party ad networks if required.
45 | */
46 | location?: IAdManagerTargetingLocation;
47 |
48 | /**
49 | * Correlator string to pass to ad loader.
50 | */
51 | correlator?: string;
52 | }
53 |
54 | export interface IAdManagerTemplateImage {
55 | uri: string;
56 | width: number;
57 | height: number;
58 | scale: number;
59 | }
60 |
--------------------------------------------------------------------------------
/src/CTKAdManagerAdaptiveBanner.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | requireNativeComponent,
4 | UIManager,
5 | ViewProps,
6 | findNodeHandle,
7 | NativeSyntheticEvent,
8 | } from 'react-native';
9 | import { createErrorFromErrorData } from './utils';
10 | import type {
11 | IAdManagerEventBase,
12 | IAdManagerEventError,
13 | IAdManagerEventAppEvent,
14 | IAdManagerEventLoadedBanner,
15 | IAdManagerEventSize,
16 | } from './AdManagerEvent';
17 | import type { IAdManagerTargeting } from './AdManagerTypes';
18 | import { LINKING_ERROR } from './Constants';
19 |
20 | interface IAdManagerAdaptiveBannerPropsBase extends ViewProps {
21 | /**
22 | * Adaptive banner position.
23 | */
24 | adPosition?:
25 | | 'currentOrientationAnchored'
26 | | 'currentOrientationInline'
27 | | 'portraitInline'
28 | | 'landscapeInline'
29 | | 'inline';
30 |
31 | /**
32 | * Max height of the adaptive banner. Only works with "inline" adPosition.
33 | */
34 | maxHeight?: number;
35 |
36 | /**
37 | * DFP ad unit ID
38 | */
39 | adUnitID?: string;
40 |
41 | /**
42 | * Array of test devices. Use Banner.simulatorId for the simulator
43 | */
44 | testDevices?: string[];
45 |
46 | targeting?: IAdManagerTargeting;
47 | }
48 |
49 | interface IAdManagerAdaptiveBannerProps
50 | extends IAdManagerAdaptiveBannerPropsBase {
51 | /**
52 | * DFP library events
53 | */
54 | onSizeChange?: (event: IAdManagerEventSize) => void;
55 | onAdLoaded?: (event: IAdManagerEventLoadedBanner) => void;
56 | onAdFailedToLoad?: (error: Error) => void;
57 | onAppEvent?: (event: IAdManagerEventAppEvent) => void;
58 | onAdOpened?: (event: IAdManagerEventBase) => void;
59 | onAdClosed?: (event: IAdManagerEventBase) => void;
60 | }
61 |
62 | interface IAdManagerAdaptiveBannerState {
63 | style: {
64 | width?: number;
65 | height?: number;
66 | };
67 | }
68 |
69 | interface IAdManagerAdaptiveBannerNativeProps
70 | extends IAdManagerAdaptiveBannerPropsBase {
71 | /**
72 | * DFP library events
73 | */
74 | onSizeChange?: (event: NativeSyntheticEvent) => void;
75 | onAdLoaded?: (
76 | event: NativeSyntheticEvent
77 | ) => void;
78 | onAdFailedToLoad?: (
79 | event: NativeSyntheticEvent
80 | ) => void;
81 | onAppEvent?: (event: NativeSyntheticEvent) => void;
82 | onAdOpened?: (event: NativeSyntheticEvent) => void;
83 | onAdClosed?: (event: NativeSyntheticEvent) => void;
84 | }
85 |
86 | const ComponentName = 'CTKAdaptiveBannerView';
87 |
88 | const AdManagerAdaptiveBannerView =
89 | UIManager.getViewManagerConfig(ComponentName) != null
90 | ? requireNativeComponent(ComponentName)
91 | : () => {
92 | throw new Error(LINKING_ERROR);
93 | };
94 |
95 | export class AdaptiveBanner extends React.Component<
96 | IAdManagerAdaptiveBannerProps,
97 | IAdManagerAdaptiveBannerState
98 | > {
99 | constructor(props: IAdManagerAdaptiveBannerProps) {
100 | super(props);
101 | this.handleSizeChange = this.handleSizeChange.bind(this);
102 | this.state = {
103 | style: {},
104 | };
105 | }
106 |
107 | shouldComponentUpdate(
108 | nextProps: IAdManagerAdaptiveBannerProps,
109 | nextState: IAdManagerAdaptiveBannerState
110 | ) {
111 | if (
112 | Object.entries(this.state.style).toString() ===
113 | Object.entries(nextState.style).toString() &&
114 | Object.entries(this.props).toString() ===
115 | Object.entries(nextProps).toString()
116 | ) {
117 | return false;
118 | }
119 | return true;
120 | }
121 |
122 | componentDidMount() {
123 | this.loadBanner();
124 | }
125 |
126 | loadBanner() {
127 | UIManager.dispatchViewManagerCommand(
128 | findNodeHandle(this),
129 | UIManager.getViewManagerConfig(ComponentName).Commands.loadBanner,
130 | []
131 | );
132 | }
133 |
134 | handleSizeChange({ nativeEvent }: NativeSyntheticEvent) {
135 | const { height, width } = nativeEvent;
136 | this.setState({ style: { width, height } });
137 | this.props.onSizeChange && this.props.onSizeChange(nativeEvent);
138 | }
139 |
140 | render() {
141 | return (
142 |
147 | this.props.onAdLoaded && this.props.onAdLoaded(event.nativeEvent)
148 | }
149 | onAdFailedToLoad={(event) =>
150 | this.props.onAdFailedToLoad &&
151 | this.props.onAdFailedToLoad(
152 | createErrorFromErrorData(event.nativeEvent.error)
153 | )
154 | }
155 | onAppEvent={(event) =>
156 | this.props.onAppEvent && this.props.onAppEvent(event.nativeEvent)
157 | }
158 | onAdOpened={(event) =>
159 | this.props.onAdOpened && this.props.onAdOpened(event.nativeEvent)
160 | }
161 | onAdClosed={(event) =>
162 | this.props.onAdClosed && this.props.onAdClosed(event.nativeEvent)
163 | }
164 | />
165 | );
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/CTKAdManagerBanner.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | requireNativeComponent,
4 | UIManager,
5 | ViewProps,
6 | findNodeHandle,
7 | NativeSyntheticEvent,
8 | DeviceEventEmitter,
9 | EventSubscription
10 | } from 'react-native';
11 | import { createErrorFromErrorData } from './utils';
12 | import type {
13 | IAdManagerEventBase,
14 | IAdManagerEventError,
15 | IAdManagerEventAppEvent,
16 | IAdManagerEventLoadedBanner,
17 | IAdManagerEventSize,
18 | } from './AdManagerEvent';
19 | import type { IAdManagerTargeting } from './AdManagerTypes';
20 | import { LINKING_ERROR } from './Constants';
21 |
22 | interface IAdManagerBannerPropsBase extends ViewProps {
23 | /**
24 | * DFP iOS library banner size constants
25 | * (https://developers.google.com/admob/ios/banner)
26 | * banner (320x50, Standard Banner for Phones and Tablets)
27 | * fullBanner (468x60, IAB Full-Size Banner for Tablets)
28 | * largeBanner (320x100, Large Banner for Phones and Tablets)
29 | * mediumRectangle (300x250, IAB Medium Rectangle for Phones and Tablets)
30 | * leaderboard (728x90, IAB Leaderboard for Tablets)
31 | * skyscraper (120x600, Skyscraper size for the iPad. Mediation only. AdMob/Google does not offer this size)
32 | * fluid (An ad size that spans the full width of its container, with a height dynamically determined by the ad)
33 | * {\d}x{\d} (Dynamic size determined byt the user, 300x250, 300x100 etc.)
34 | *
35 | * banner is default
36 | */
37 | adSize?: string;
38 |
39 | /**
40 | * Optional array specifying all valid sizes that are appropriate for this slot.
41 | */
42 | validAdSizes?: string[];
43 |
44 | /**
45 | * DFP ad unit ID
46 | */
47 | adUnitID?: string;
48 |
49 | /**
50 | * Array of test devices. Use Banner.simulatorId for the simulator
51 | */
52 | testDevices?: string[];
53 |
54 | targeting?: IAdManagerTargeting;
55 | }
56 |
57 | interface IAdManagerBannerProps extends IAdManagerBannerPropsBase {
58 | // onError is a callback function sent from parent RN component of your RN app, aka: the error handler.
59 | // so if your RN App wants to handle the error, please pass in the "onError" function.
60 | onError?: (eventData: Error) => void;
61 | /**
62 | * DFP library events
63 | */
64 | onSizeChange?: (event: IAdManagerEventSize) => void;
65 | onAdLoaded?: (event: IAdManagerEventLoadedBanner) => void;
66 | onAdFailedToLoad?: (error: Error) => void;
67 | onAppEvent?: (event: IAdManagerEventAppEvent) => void;
68 | onAdOpened?: (event: IAdManagerEventBase) => void;
69 | onAdClosed?: (event: IAdManagerEventBase) => void;
70 | onAdRecordImpression?: (event: IAdManagerEventBase) => void;
71 | }
72 |
73 | interface IAdManagerBannerState {
74 | style: {
75 | width?: number;
76 | height?: number;
77 | };
78 | error: Error | null;
79 | }
80 |
81 | interface IAdManagerBannerNativeProps extends IAdManagerBannerPropsBase {
82 | /**
83 | * DFP library events
84 | */
85 | onSizeChange?: (event: NativeSyntheticEvent) => void;
86 | onAdLoaded?: (
87 | event: NativeSyntheticEvent
88 | ) => void;
89 | onAdFailedToLoad?: (
90 | event: NativeSyntheticEvent
91 | ) => void;
92 | onAppEvent?: (event: NativeSyntheticEvent) => void;
93 | onAdOpened?: (event: NativeSyntheticEvent) => void;
94 | onAdClosed?: (event: NativeSyntheticEvent) => void;
95 | onAdRecordImpression?: (event: NativeSyntheticEvent) => void;
96 | }
97 |
98 | const ComponentName = 'CTKBannerView';
99 |
100 | const AdManagerBannerView =
101 | UIManager.getViewManagerConfig(ComponentName) != null
102 | ? requireNativeComponent(ComponentName)
103 | : () => {
104 | throw new Error(LINKING_ERROR);
105 | };
106 |
107 | export class Banner extends React.Component<
108 | IAdManagerBannerProps,
109 | IAdManagerBannerState
110 | > {
111 | hasOnErrorFromParent: boolean;
112 | customListener: EventSubscription | undefined;
113 |
114 | constructor(props: IAdManagerBannerProps) {
115 | super(props);
116 | this.hasOnErrorFromParent = Object.prototype.hasOwnProperty.call(props, 'onError');
117 | this.handleSizeChange = this.handleSizeChange.bind(this);
118 | this.state = {
119 | style: {},
120 | error: null,
121 | };
122 | }
123 |
124 | shouldComponentUpdate(
125 | nextProps: IAdManagerBannerProps,
126 | nextState: IAdManagerBannerState
127 | ) {
128 | if (
129 | Object.entries(this.state.style).toString() ===
130 | Object.entries(nextState.style).toString() &&
131 | Object.entries(this.props).toString() ===
132 | Object.entries(nextProps).toString()
133 | ) {
134 | return false;
135 | }
136 | return true;
137 | }
138 |
139 | componentDidMount() {
140 | this.customListener= DeviceEventEmitter.addListener('onError',eventData=>{
141 | this.setState({ error: eventData });
142 | if (this.hasOnErrorFromParent && this.props.onError) {
143 | this.props.onError(eventData);
144 | }
145 | });
146 | this.loadBanner();
147 | }
148 |
149 | componentWillUnmount() {
150 | if (this.customListener) {
151 | this.customListener.remove();
152 | }
153 | }
154 |
155 | loadBanner() {
156 | UIManager.dispatchViewManagerCommand(
157 | findNodeHandle(this),
158 | UIManager.getViewManagerConfig(ComponentName).Commands.loadBanner,
159 | []
160 | );
161 | }
162 |
163 | handleSizeChange({ nativeEvent }: NativeSyntheticEvent) {
164 | const { height, width } = nativeEvent;
165 | this.setState({ style: { width, height } });
166 | this.props.onSizeChange && this.props.onSizeChange(nativeEvent);
167 | }
168 |
169 | render() {
170 | return (
171 |
176 | this.props.onAdLoaded && this.props.onAdLoaded(event.nativeEvent)
177 | }
178 | onAdFailedToLoad={(event) =>
179 | this.props.onAdFailedToLoad &&
180 | this.props.onAdFailedToLoad(
181 | createErrorFromErrorData(event.nativeEvent.error)
182 | )
183 | }
184 | onAppEvent={(event) =>
185 | this.props.onAppEvent && this.props.onAppEvent(event.nativeEvent)
186 | }
187 | onAdOpened={(event) =>
188 | this.props.onAdOpened && this.props.onAdOpened(event.nativeEvent)
189 | }
190 | onAdClosed={(event) =>
191 | this.props.onAdClosed && this.props.onAdClosed(event.nativeEvent)
192 | }
193 | onAdRecordImpression={(event) =>
194 | this.props.onAdRecordImpression && this.props.onAdRecordImpression(event.nativeEvent)
195 | }
196 | />
197 | );
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/CTKAdManagerInterstitial.ts:
--------------------------------------------------------------------------------
1 | import { NativeEventEmitter, NativeModules } from 'react-native';
2 | import { createErrorFromErrorData } from './utils';
3 | import type {
4 | IAdManagerEventBase,
5 | IAdManagerEventErrorPayload,
6 | IAdManagerEventLoadedInterstitial,
7 | } from './AdManagerEvent';
8 | import { LINKING_ERROR } from './Constants';
9 | import type { IAdManagerTargeting } from './AdManagerTypes';
10 |
11 | const CTKInterstitial = NativeModules.CTKInterstitial
12 | ? NativeModules.CTKInterstitial
13 | : new Proxy(
14 | {},
15 | {
16 | get() {
17 | throw new Error(LINKING_ERROR);
18 | },
19 | }
20 | );
21 |
22 | const eventEmitter = new NativeEventEmitter(CTKInterstitial);
23 |
24 | const eventMap = {
25 | adLoaded: 'interstitialAdLoaded',
26 | adFailedToLoad: 'interstitialAdFailedToLoad',
27 | adOpened: 'interstitialAdOpened',
28 | adClosed: 'interstitialAdClosed',
29 | };
30 |
31 | type TAdManagerInterstitialEvent =
32 | | 'adLoaded'
33 | | 'adFailedToLoad'
34 | | 'adOpened'
35 | | 'adClosed';
36 |
37 | type TAdManagerInterstitialHandler = (
38 | event: Error | IAdManagerEventBase | IAdManagerEventLoadedInterstitial
39 | ) => void;
40 |
41 | const _subscriptions = new Map();
42 |
43 | const addEventListener = (
44 | event: TAdManagerInterstitialEvent,
45 | handler: TAdManagerInterstitialHandler
46 | ) => {
47 | const mappedEvent = eventMap[event];
48 | if (mappedEvent) {
49 | let listener;
50 | if (event === 'adFailedToLoad') {
51 | listener = eventEmitter.addListener(
52 | mappedEvent,
53 | (error: IAdManagerEventErrorPayload) =>
54 | handler(createErrorFromErrorData(error))
55 | );
56 | } else {
57 | listener = eventEmitter.addListener(mappedEvent, handler);
58 | }
59 | _subscriptions.set(handler, listener);
60 | return {
61 | remove: () => removeEventListener(event, handler),
62 | };
63 | } else {
64 | console.warn(`Trying to subscribe to unknown event: "${event}"`);
65 | return {
66 | remove: () => {},
67 | };
68 | }
69 | };
70 |
71 | const removeEventListener = (
72 | _event: TAdManagerInterstitialEvent,
73 | handler: TAdManagerInterstitialHandler
74 | ) => {
75 | const listener = _subscriptions.get(handler);
76 | if (!listener) {
77 | return;
78 | }
79 | listener.remove();
80 | _subscriptions.delete(handler);
81 | };
82 |
83 | const removeAllListeners = () => {
84 | _subscriptions.forEach((listener, key, map) => {
85 | listener.remove();
86 | map.delete(key);
87 | });
88 | };
89 |
90 | const simulatorId = 'SIMULATOR';
91 |
92 | const setAdUnitID = (adUnitID: string) => {
93 | CTKInterstitial.setAdUnitID(adUnitID);
94 | };
95 |
96 | const setTestDevices = (testDevices: string[]) => {
97 | CTKInterstitial.setTestDevices(testDevices);
98 | };
99 |
100 | const setTargeting = (targeting: IAdManagerTargeting) => {
101 | CTKInterstitial.setTargeting(targeting);
102 | };
103 |
104 | const requestAd = (): Promise => {
105 | return CTKInterstitial.requestAd();
106 | }
107 |
108 | const showAd = (): Promise => {
109 | return CTKInterstitial.showAd();
110 | }
111 |
112 | const isReady = (callback: (isReady: boolean) => void): Promise => {
113 | return CTKInterstitial.isReady(callback);
114 | }
115 |
116 | export default {
117 | addEventListener,
118 | removeEventListener,
119 | removeAllListeners,
120 | simulatorId,
121 | setAdUnitID,
122 | setTestDevices,
123 | setTargeting,
124 | requestAd,
125 | showAd,
126 | isReady
127 | }
128 |
--------------------------------------------------------------------------------
/src/Constants.ts:
--------------------------------------------------------------------------------
1 | import { Platform } from 'react-native';
2 |
3 | export const LINKING_ERROR =
4 | `The package 'react-native-ad-manager' doesn't seem to be linked. Make sure: \n\n` +
5 | Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6 | '- You rebuilt the app after installing the package\n' +
7 | '- You are not using Expo managed workflow\n';
8 |
--------------------------------------------------------------------------------
/src/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | it.todo('write a test');
2 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Interstitial } from './CTKAdManagerInterstitial';
2 |
3 | export { Banner } from './CTKAdManagerBanner';
4 | export { AdaptiveBanner } from './CTKAdManagerAdaptiveBanner';
5 | export { NativeAdsManager } from './native-ads/NativeAdsManager';
6 | export { TriggerableView } from './native-ads/TriggerableViewManager';
7 | export { default as withNativeAd } from './native-ads/withNativeAd';
8 |
9 | export * from './AdManagerEvent';
10 | export * from './AdManagerTypes';
11 |
--------------------------------------------------------------------------------
/src/native-ads/NativeAdsManager.ts:
--------------------------------------------------------------------------------
1 | import { NativeModules } from 'react-native';
2 | import type { TReactNodeHandleRef } from '../AdManagerTypes';
3 |
4 | const { CTKAdManageNativeManager } = NativeModules;
5 |
6 | export class NativeAdsManager {
7 | isValid: boolean;
8 | adUnitID: string;
9 |
10 | constructor(adUnitID: string, testDevices: string[]) {
11 | // Indicates whether AdsManager is ready to serve ads
12 | this.isValid = true;
13 | this.adUnitID = adUnitID;
14 | CTKAdManageNativeManager.init(adUnitID, testDevices);
15 | }
16 |
17 | static async registerViewsForInteractionAsync(
18 | nativeAdViewTag: TReactNodeHandleRef,
19 | clickable: TReactNodeHandleRef[]
20 | ) {
21 | return await CTKAdManageNativeManager.registerViewsForInteraction(
22 | nativeAdViewTag,
23 | clickable
24 | );
25 | }
26 |
27 | /**
28 | * Set the native ad manager.
29 | */
30 | toJSON() {
31 | return this.adUnitID;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/native-ads/TriggerableViewManager.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Text, ViewProps } from 'react-native';
3 | import type { TReactNodeHandleRef } from '../AdManagerTypes';
4 |
5 | interface ITriggerableContext {
6 | register: (child: TReactNodeHandleRef) => void;
7 | unregister: (child: TReactNodeHandleRef) => void;
8 | }
9 |
10 | export const TriggerableContext = React.createContext({
11 | register: (child: TReactNodeHandleRef) => {
12 | throw new Error('Stub! ' + child);
13 | },
14 | unregister: (child: TReactNodeHandleRef) => {
15 | throw new Error('Stub! ' + child);
16 | },
17 | });
18 |
19 | class TriggerableViewChild extends React.Component {
20 | static contextType = TriggerableContext;
21 | wrapperRef = null;
22 |
23 | // TODO: convert to ref type
24 | handleWrapperRef = (ref: any) => {
25 | if (this.wrapperRef) {
26 | this.context.unregister(this.wrapperRef);
27 | this.wrapperRef = null;
28 | }
29 | if (ref) {
30 | this.context.register(ref);
31 | this.wrapperRef = ref;
32 | }
33 | };
34 |
35 | render() {
36 | return ;
37 | }
38 | }
39 |
40 | interface ITriggerableViewProps extends ViewProps {}
41 |
42 | export class TriggerableView extends React.Component {
43 | render() {
44 | return (
45 |
46 | {(contextValue) => (
47 |
48 | )}
49 |
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/native-ads/withNativeAd.tsx:
--------------------------------------------------------------------------------
1 | import React, { JSXElementConstructor } from 'react';
2 | import {
3 | findNodeHandle,
4 | NativeSyntheticEvent,
5 | requireNativeComponent,
6 | UIManager,
7 | ViewProps,
8 | } from 'react-native';
9 | import { TriggerableContext } from './TriggerableViewManager';
10 | import { NativeAdsManager } from './NativeAdsManager';
11 | import type {
12 | IAdManagerTargeting,
13 | TReactNodeHandleRef,
14 | } from '../AdManagerTypes';
15 | import type {
16 | IAdManagerEventBase,
17 | IAdManagerEventCustomClick,
18 | IAdManagerEventAppEvent,
19 | IAdManagerEventLoadedBanner,
20 | IAdManagerEventLoadedNative,
21 | IAdManagerEventLoadedTemplate,
22 | IAdManagerEventSize,
23 | IAdManagerEventError,
24 | } from '../AdManagerEvent';
25 | import { createErrorFromErrorData, stripProperties } from '../utils';
26 | import { LINKING_ERROR } from '../Constants';
27 |
28 | /*
29 | @property (nonatomic, copy) NSDictionary *targeting;
30 |
31 | */
32 | interface INativeAdPropsBase extends ViewProps {
33 | adSize?: string;
34 | correlator?: string;
35 | customTemplateIds?: string[];
36 | validAdSizes?: string[];
37 | validAdTypes?: ('banner' | 'native' | 'template')[];
38 | customClickTemplateIds?: string[];
39 | targeting?: IAdManagerTargeting;
40 | }
41 |
42 | interface INativeAdNativeProps extends INativeAdPropsBase {
43 | children: React.ReactNode;
44 | adsManager: string;
45 | loaderIndex?: string;
46 | onSizeChange?: (event: NativeSyntheticEvent) => void;
47 | onAdLoaded?: (
48 | event: NativeSyntheticEvent<
49 | | IAdManagerEventLoadedBanner
50 | | IAdManagerEventLoadedTemplate
51 | | IAdManagerEventLoadedNative
52 | >
53 | ) => void;
54 | onAdFailedToLoad?: (
55 | event: NativeSyntheticEvent
56 | ) => void;
57 | onAppEvent?: (event: NativeSyntheticEvent) => void;
58 | onAdOpened?: (event: NativeSyntheticEvent) => void;
59 | onAdClosed?: (event: NativeSyntheticEvent) => void;
60 | onAdCustomClick?: (
61 | event: NativeSyntheticEvent
62 | ) => void;
63 | onAdRecordImpression?: (event: NativeSyntheticEvent) => void;
64 | }
65 |
66 | interface INativeAdProps extends INativeAdPropsBase {
67 | adsManager: NativeAdsManager;
68 | adLoaderIndex?: string;
69 | onSizeChange?: (event: IAdManagerEventSize) => void;
70 | onAdLoaded?: (
71 | event:
72 | | IAdManagerEventLoadedBanner
73 | | IAdManagerEventLoadedTemplate
74 | | IAdManagerEventLoadedNative
75 | ) => void;
76 | onAdFailedToLoad?: (error: Error) => void;
77 | onAppEvent?: (event: IAdManagerEventAppEvent) => void;
78 | onAdOpened?: (event: IAdManagerEventBase) => void;
79 | onAdClosed?: (event: IAdManagerEventBase) => void;
80 | onAdCustomClick?: (event: IAdManagerEventCustomClick) => void;
81 | onAdRecordImpression?: (event: IAdManagerEventBase) => void;
82 | }
83 |
84 | interface INativeAdState {
85 | clickableChildren: Set;
86 | style: {
87 | width?: number;
88 | height?: number;
89 | };
90 | nativeAd?:
91 | | IAdManagerEventLoadedBanner
92 | | IAdManagerEventLoadedTemplate
93 | | IAdManagerEventLoadedNative;
94 | }
95 |
96 | const areSetsEqual = (
97 | a: Set,
98 | b: Set
99 | ) => {
100 | if (a.size !== b.size) return false;
101 | for (const aItem of a) {
102 | if (!b.has(aItem)) return false;
103 | }
104 | return true;
105 | };
106 |
107 | const ComponentName = 'CTKAdManageNative';
108 |
109 | const NativeAdView =
110 | UIManager.getViewManagerConfig(ComponentName) != null
111 | ? requireNativeComponent(ComponentName)
112 | : () => {
113 | // eslint-disable-next-line no-undef
114 | throw new Error(LINKING_ERROR);
115 | };
116 |
117 | export default (Component: JSXElementConstructor) =>
118 | class NativeAdWrapper extends React.Component<
119 | INativeAdProps,
120 | INativeAdState
121 | > {
122 | clickableChildrenNodeHandles = new Map();
123 |
124 | constructor(props: INativeAdProps) {
125 | super(props);
126 | this.state = {
127 | // iOS requires a non-null value
128 | clickableChildren: new Set(),
129 | style: {},
130 | };
131 | }
132 |
133 | componentDidMount() {
134 | this.reloadAd();
135 | }
136 |
137 | registerClickableChild = (child: TReactNodeHandleRef) => {
138 | const handle = findNodeHandle(child);
139 | if (!handle) {
140 | return;
141 | }
142 | this.clickableChildrenNodeHandles.set(child, handle);
143 | this.setState({
144 | clickableChildren: this.state.clickableChildren.add(handle),
145 | });
146 | };
147 |
148 | unregisterClickableChild = (child: TReactNodeHandleRef) => {
149 | this.setState(({ clickableChildren }) => {
150 | const newClickableChildren = new Set(clickableChildren);
151 | newClickableChildren.delete(
152 | this.clickableChildrenNodeHandles.get(child)
153 | );
154 | this.clickableChildrenNodeHandles.delete(child);
155 | return { clickableChildren: newClickableChildren };
156 | });
157 | };
158 |
159 | handleSizeChange = ({
160 | nativeEvent,
161 | }: NativeSyntheticEvent) => {
162 | const { height, width } = nativeEvent;
163 | this.setState({ style: { width, height } });
164 | this.props.onSizeChange && this.props.onSizeChange(nativeEvent);
165 | };
166 |
167 | handleAdLoaded = ({
168 | nativeEvent,
169 | }: NativeSyntheticEvent<
170 | | IAdManagerEventLoadedBanner
171 | | IAdManagerEventLoadedTemplate
172 | | IAdManagerEventLoadedNative
173 | >) => {
174 | this.setState({ nativeAd: nativeEvent });
175 | this.props.onAdLoaded && this.props.onAdLoaded(nativeEvent);
176 | };
177 |
178 | shouldComponentUpdate(
179 | nextProps: INativeAdProps,
180 | nextState: INativeAdState
181 | ) {
182 | if (
183 | Object.entries(this.state).toString() ===
184 | Object.entries(nextState).toString() &&
185 | Object.entries(this.props).toString() ===
186 | Object.entries(nextProps).toString()
187 | ) {
188 | return false;
189 | }
190 | return true;
191 | }
192 |
193 | componentDidUpdate(_: INativeAdProps, prevState: INativeAdState) {
194 | const clickableChildrenChanged = areSetsEqual(
195 | prevState.clickableChildren,
196 | this.state.clickableChildren
197 | );
198 | if (clickableChildrenChanged) {
199 | const viewHandle = findNodeHandle(this);
200 | if (!viewHandle) {
201 | // Skip registration if the view is no longer valid.
202 | return;
203 | }
204 |
205 | NativeAdsManager.registerViewsForInteractionAsync(viewHandle, [
206 | ...this.state.clickableChildren,
207 | ])
208 | .then(() => {
209 | // do nothing for now
210 | })
211 | .catch(() => {
212 | // do nothing for now
213 | });
214 | }
215 | }
216 |
217 | reloadAd() {
218 | UIManager.dispatchViewManagerCommand(
219 | findNodeHandle(this),
220 | UIManager.getViewManagerConfig(ComponentName).Commands.reloadAd,
221 | []
222 | );
223 | }
224 |
225 | renderAdComponent(componentProps: INativeAdProps) {
226 | if (!this.state.nativeAd) {
227 | return null;
228 | }
229 |
230 | return (
231 |
237 |
238 |
239 | );
240 | }
241 |
242 | render() {
243 | // Cast to any until https://github.com/Microsoft/TypeScript/issues/10727 is resolved
244 | const _a = this.props,
245 | { adsManager } = _a,
246 | rest = stripProperties(_a, ['adsManager', 'onAdLoaded']);
247 |
248 | return (
249 |
260 | this.props.onAdFailedToLoad &&
261 | this.props.onAdFailedToLoad(
262 | createErrorFromErrorData(event.nativeEvent.error)
263 | )
264 | }
265 | onAppEvent={(event) =>
266 | this.props.onAppEvent && this.props.onAppEvent(event.nativeEvent)
267 | }
268 | onAdOpened={(event) =>
269 | this.props.onAdOpened && this.props.onAdOpened(event.nativeEvent)
270 | }
271 | onAdClosed={(event) =>
272 | this.props.onAdClosed && this.props.onAdClosed(event.nativeEvent)
273 | }
274 | onAdCustomClick={(event) =>
275 | this.props.onAdCustomClick &&
276 | this.props.onAdCustomClick(event.nativeEvent)
277 | }
278 | onAdRecordImpression={(event) =>
279 | this.props.onAdRecordImpression && this.props.onAdRecordImpression(event.nativeEvent)
280 | }
281 | targeting={this.props.targeting}
282 | customClickTemplateIds={this.props.customClickTemplateIds}
283 | adsManager={adsManager.toJSON()}
284 | >
285 | {this.renderAdComponent(rest)}
286 |
287 | );
288 | }
289 | };
290 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import type { IAdManagerEventErrorPayload } from './AdManagerEvent';
2 |
3 | export const createErrorFromErrorData = (
4 | errorData: IAdManagerEventErrorPayload
5 | ) => {
6 | const { message, ...extraErrorInfo } = errorData || {};
7 | const error = new Error(message);
8 | extraErrorInfo.framesToPop = 1;
9 | return Object.assign(error, extraErrorInfo);
10 | };
11 |
12 | export const stripProperties = (s: any, e: string[]): any => {
13 | const t: any = {};
14 | for (let p in s)
15 | if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16 | t[p] = s[p];
17 | if (s != null && typeof Object.getOwnPropertySymbols === 'function')
18 | for (let i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++)
19 | if (e.indexOf(String(p[i])) < 0) t[p[i]] = s[p[i]];
20 | return t;
21 | };
22 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "extends": "./tsconfig",
4 | "exclude": ["example"]
5 | }
6 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./",
4 | "paths": {
5 | "react-native-ad-manager": ["./src/index"]
6 | },
7 | "allowUnreachableCode": false,
8 | "allowUnusedLabels": false,
9 | "esModuleInterop": true,
10 | "importsNotUsedAsValues": "error",
11 | "forceConsistentCasingInFileNames": true,
12 | "jsx": "react",
13 | "lib": ["esnext"],
14 | "module": "esnext",
15 | "moduleResolution": "node",
16 | "noFallthroughCasesInSwitch": true,
17 | "noImplicitReturns": true,
18 | "noImplicitUseStrict": false,
19 | "noStrictGenericChecks": false,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "resolveJsonModule": true,
23 | "skipLibCheck": true,
24 | "strict": true,
25 | "target": "esnext"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------