├── .eslintignore ├── dist ├── AdMobRewarded.d.ts ├── AdMobInterstitial.d.ts ├── utils.d.ts ├── AdTestIds.d.ts ├── utils.js ├── index.d.ts ├── index.js ├── AdSize.d.ts ├── AdSize.js ├── AdmobBanner.d.ts ├── AdTestIds.js ├── AdmobBanner.js ├── AdMobInterstitial.js └── AdMobRewarded.js ├── .gitattributes ├── android ├── src │ └── main │ │ ├── res │ │ └── values │ │ │ └── strings.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── izo │ │ └── rnadmob │ │ ├── RNAdMobPackage.java │ │ ├── RNAdMobInterstitialAdModule.java │ │ ├── RNAdMobRewardedVideoAdModule.java │ │ ├── RNAdMobBannerViewManager.java │ │ └── RNPublisherBannerViewManager.java └── build.gradle ├── ios ├── RNAdMobUtils.h ├── RCTConvert+GADAdSize.h ├── RNGADBannerViewManager.h ├── RNGAMBannerViewManager.h ├── RNAdMobInterstitial.h ├── RNAdMobRewarded.h ├── RNAdMobUtils.m ├── RNGADBannerView.h ├── RNGAMBannerView.h ├── RCTConvert+GADAdSize.m ├── RNGADBannerViewManager.m ├── RNGAMBannerViewManager.m ├── RNGADBannerView.m ├── RNAdMobRewarded.m ├── RNAdMobInterstitial.m ├── RNGAMBannerView.m └── RNAdMobManager.xcodeproj │ └── project.pbxproj ├── src ├── utils.ts ├── index.ts ├── AdSize.ts ├── AdTestIds.ts ├── AdMobInterstitial.ts ├── AdmobBanner.tsx └── AdMobRewarded.ts ├── utils.js ├── RNAdSize.js ├── .editorconfig ├── .eslintrc ├── RNAdTestIds.js ├── index.js ├── .gitignore ├── package.json ├── tsconfig.json ├── LICENSE ├── react-native-admob-next.podspec ├── RNAdMobInterstitial.js ├── RNAdMobRewarded.js ├── RNAdMobBanner.js ├── RNPublisherBanner.js └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.js 2 | !/*.js 3 | -------------------------------------------------------------------------------- /dist/AdMobRewarded.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: any; 2 | export default _default; 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf -------------------------------------------------------------------------------- /dist/AdMobInterstitial.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: any; 2 | export default _default; 3 | -------------------------------------------------------------------------------- /dist/utils.d.ts: -------------------------------------------------------------------------------- 1 | export declare const createErrorFromErrorData: (errorData: any) => any; 2 | -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ReactNativeAdMob 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /ios/RNAdMobUtils.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NSArray *__nullable RNAdMobProcessTestDevices(NSArray *__nullable testDevices, id _Nonnull simulatorId); 4 | -------------------------------------------------------------------------------- /dist/AdTestIds.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: { 2 | BANNER?: string | undefined; 3 | INTERSTITIAL?: string | undefined; 4 | REWARDED?: string | undefined; 5 | }; 6 | export default _default; 7 | -------------------------------------------------------------------------------- /ios/RCTConvert+GADAdSize.h: -------------------------------------------------------------------------------- 1 | #import 2 | @import GoogleMobileAds; 3 | 4 | @interface RCTConvert (GADAdSize) 5 | 6 | + (GADAdSize)GADAdSize:(id)json withWidth:(CGFloat)width; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /ios/RNGADBannerViewManager.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #else 4 | #import "RCTViewManager.h" 5 | #endif 6 | 7 | @interface RNGADBannerViewManager : RCTViewManager 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /ios/RNGAMBannerViewManager.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #else 4 | #import "RCTViewManager.h" 5 | #endif 6 | 7 | @interface RNGAMBannerViewManager : RCTViewManager 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /dist/utils.js: -------------------------------------------------------------------------------- 1 | export const createErrorFromErrorData = (errorData) => { 2 | const { message, ...extraErrorInfo } = errorData || {}; 3 | const error = new Error(message); 4 | error.framesToPop = 1; 5 | return Object.assign(error, extraErrorInfo); 6 | }; 7 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export const createErrorFromErrorData = (errorData: any) => { 2 | const { message, ...extraErrorInfo } = errorData || {}; 3 | const error: any = new Error(message); 4 | error.framesToPop = 1; 5 | return Object.assign(error, extraErrorInfo); 6 | }; 7 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | export const createErrorFromErrorData = (errorData) => { 2 | const { 3 | message, 4 | ...extraErrorInfo 5 | } = errorData || {}; 6 | const error = new Error(message); 7 | error.framesToPop = 1; 8 | return Object.assign(error, extraErrorInfo); 9 | } 10 | -------------------------------------------------------------------------------- /RNAdSize.js: -------------------------------------------------------------------------------- 1 | export default { 2 | BANNER: 'banner', 3 | FULL_BANNER: 'fullBanner', 4 | LARGE_BANNER: 'largeBanner', 5 | FLUID: 'fluid', 6 | SKYSCRAPER: 'skyscraper', 7 | LEADERBOARD: 'leaderboard', 8 | MEDIUM_RECTANGLE: 'mediumRectangle', 9 | ADAPTIVE_BANNER: 'adaptiveBanner', 10 | } 11 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import AdMobBanner from "./AdmobBanner"; 2 | import AdMobInterstitial from "./AdMobInterstitial"; 3 | import AdMobRewarded from "./AdMobRewarded"; 4 | import AdSize from "./AdSize"; 5 | import AdTestIds from "./AdTestIds"; 6 | export { AdMobBanner, AdMobInterstitial, AdMobRewarded, AdTestIds, AdSize }; 7 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | import AdMobBanner from "./AdmobBanner"; 2 | import AdMobInterstitial from "./AdMobInterstitial"; 3 | import AdMobRewarded from "./AdMobRewarded"; 4 | import AdSize from "./AdSize"; 5 | import AdTestIds from "./AdTestIds"; 6 | export { AdMobBanner, AdMobInterstitial, AdMobRewarded, AdTestIds, AdSize }; 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import AdMobBanner from "./AdmobBanner"; 2 | import AdMobInterstitial from "./AdMobInterstitial"; 3 | import AdMobRewarded from "./AdMobRewarded"; 4 | import AdSize from "./AdSize"; 5 | import AdTestIds from "./AdTestIds"; 6 | export { AdMobBanner, AdMobInterstitial, AdMobRewarded, AdTestIds, AdSize }; 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.js] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /dist/AdSize.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: { 2 | BANNER: string; 3 | FULL_BANNER: string; 4 | LARGE_BANNER: string; 5 | FLUID: string; 6 | SKYSCRAPER: string; 7 | LEADERBOARD: string; 8 | MEDIUM_RECTANGLE: string; 9 | ADAPTIVE_BANNER: string; 10 | }; 11 | export default _default; 12 | -------------------------------------------------------------------------------- /dist/AdSize.js: -------------------------------------------------------------------------------- 1 | export default { 2 | BANNER: "banner", 3 | FULL_BANNER: "fullBanner", 4 | LARGE_BANNER: "largeBanner", 5 | FLUID: "fluid", 6 | SKYSCRAPER: "skyscraper", 7 | LEADERBOARD: "leaderboard", 8 | MEDIUM_RECTANGLE: "mediumRectangle", 9 | ADAPTIVE_BANNER: "adaptiveBanner", 10 | }; 11 | -------------------------------------------------------------------------------- /src/AdSize.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | BANNER: "banner", 3 | FULL_BANNER: "fullBanner", 4 | LARGE_BANNER: "largeBanner", 5 | FLUID: "fluid", 6 | SKYSCRAPER: "skyscraper", 7 | LEADERBOARD: "leaderboard", 8 | MEDIUM_RECTANGLE: "mediumRectangle", 9 | ADAPTIVE_BANNER: "adaptiveBanner", 10 | }; 11 | -------------------------------------------------------------------------------- /ios/RNAdMobInterstitial.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #import 4 | #else 5 | #import "RCTBridgeModule.h" 6 | #import "RCTEventEmitter.h" 7 | #endif 8 | 9 | @import GoogleMobileAds; 10 | 11 | @interface RNAdMobInterstitial : RCTEventEmitter 12 | @end 13 | -------------------------------------------------------------------------------- /ios/RNAdMobRewarded.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #import 4 | #else 5 | #import "RCTBridgeModule.h" 6 | #import "RCTEventEmitter.h" 7 | #endif 8 | 9 | @import GoogleMobileAds; 10 | 11 | @interface RNAdMobRewarded : RCTEventEmitter 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": ["eslint:recommended", "plugin:react/recommended"], 7 | "parser": "babel-eslint", 8 | "parserOptions": { 9 | "ecmaVersion": 6 10 | }, 11 | "plugins": [ 12 | "react", 13 | "react-native" 14 | ], 15 | "rules": { 16 | "comma-dangle": ["error", "always-multiline"], 17 | "react/jsx-handler-names": "error" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dist/AdmobBanner.d.ts: -------------------------------------------------------------------------------- 1 | import { FC } from "react"; 2 | declare type AdmobBannerTypes = { 3 | style?: any | {}; 4 | onSizeChange?: any; 5 | onAdFailedToLoad?: any; 6 | adSize?: string; 7 | adUnitID?: string; 8 | testDevices?: any; 9 | onAdLoaded?: any; 10 | onAdRecordImpression?: any; 11 | onAdOpened?: any; 12 | onAdClosed?: any; 13 | simulatorId?: string | "SIMULATOR"; 14 | }; 15 | declare const AdmobBanner: FC; 16 | export default AdmobBanner; 17 | -------------------------------------------------------------------------------- /RNAdTestIds.js: -------------------------------------------------------------------------------- 1 | import { Platform } from 'react-native'; 2 | 3 | export default { 4 | ...Platform.select({ 5 | android: { 6 | BANNER: 'ca-app-pub-3940256099942544/6300978111', 7 | INTERSTITIAL: 'ca-app-pub-3940256099942544/1033173712', 8 | REWARDED: 'ca-app-pub-3940256099942544/5224354917', 9 | }, 10 | ios: { 11 | BANNER: 'ca-app-pub-3940256099942544/2934735716', 12 | INTERSTITIAL: 'ca-app-pub-3940256099942544/4411468910', 13 | REWARDED: 'ca-app-pub-3940256099942544/1712485313', 14 | }, 15 | }), 16 | }; 17 | -------------------------------------------------------------------------------- /ios/RNAdMobUtils.m: -------------------------------------------------------------------------------- 1 | #import "RNAdMobUtils.h" 2 | 3 | NSArray *__nullable RNAdMobProcessTestDevices(NSArray *__nullable testDevices, id _Nonnull simulatorId) 4 | { 5 | if (testDevices == NULL) { 6 | return testDevices; 7 | } 8 | NSInteger index = [testDevices indexOfObject:@"SIMULATOR"]; 9 | if (index == NSNotFound) { 10 | return testDevices; 11 | } 12 | NSMutableArray *values = [testDevices mutableCopy]; 13 | [values removeObjectAtIndex:index]; 14 | [values addObject:simulatorId]; 15 | return values; 16 | } 17 | -------------------------------------------------------------------------------- /src/AdTestIds.ts: -------------------------------------------------------------------------------- 1 | import { Platform } from 'react-native'; 2 | 3 | export default { 4 | ...Platform.select({ 5 | android: { 6 | BANNER: 'ca-app-pub-3940256099942544/6300978111', 7 | INTERSTITIAL: 'ca-app-pub-3940256099942544/1033173712', 8 | REWARDED: 'ca-app-pub-3940256099942544/5224354917', 9 | }, 10 | ios: { 11 | BANNER: 'ca-app-pub-3940256099942544/2934735716', 12 | INTERSTITIAL: 'ca-app-pub-3940256099942544/4411468910', 13 | REWARDED: 'ca-app-pub-3940256099942544/1712485313', 14 | }, 15 | }), 16 | }; 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable global-require */ 2 | module.exports = { 3 | get AdMobBanner() { 4 | return require('./RNAdMobBanner').default; 5 | }, 6 | get AdMobInterstitial() { 7 | return require('./RNAdMobInterstitial').default; 8 | }, 9 | get PublisherBanner() { 10 | return require('./RNPublisherBanner').default; 11 | }, 12 | get AdMobRewarded() { 13 | return require('./RNAdMobRewarded').default; 14 | }, 15 | get AdSize() { 16 | return require('./RNAdSize').default; 17 | }, 18 | get AdTestIds() { 19 | return require('./RNAdTestIds').default; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /dist/AdTestIds.js: -------------------------------------------------------------------------------- 1 | import { Platform } from 'react-native'; 2 | export default { 3 | ...Platform.select({ 4 | android: { 5 | BANNER: 'ca-app-pub-3940256099942544/6300978111', 6 | INTERSTITIAL: 'ca-app-pub-3940256099942544/1033173712', 7 | REWARDED: 'ca-app-pub-3940256099942544/5224354917', 8 | }, 9 | ios: { 10 | BANNER: 'ca-app-pub-3940256099942544/2934735716', 11 | INTERSTITIAL: 'ca-app-pub-3940256099942544/4411468910', 12 | REWARDED: 'ca-app-pub-3940256099942544/1712485313', 13 | }, 14 | }), 15 | }; 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # XDE 6 | .expo/ 7 | 8 | # VSCode 9 | .vscode/ 10 | jsconfig.json 11 | 12 | # Xcode 13 | # 14 | build/ 15 | *.pbxuser 16 | !default.pbxuser 17 | *.mode1v3 18 | !default.mode1v3 19 | *.mode2v3 20 | !default.mode2v3 21 | *.perspectivev3 22 | !default.perspectivev3 23 | xcuserdata 24 | *.xccheckout 25 | *.moved-aside 26 | DerivedData 27 | *.hmap 28 | *.ipa 29 | *.xcuserstate 30 | project.xcworkspace 31 | 32 | # Android/IJ 33 | # 34 | .idea 35 | .gradle 36 | local.properties 37 | android.iml 38 | 39 | # Cocoapods 40 | # 41 | example/ios/Pods 42 | 43 | # node.js 44 | # 45 | node_modules/ 46 | npm-debug.log 47 | yarn-debug.log 48 | yarn-error.log 49 | 50 | # BUCK 51 | buck-out/ 52 | \.buckd/ 53 | android/app/libs 54 | android/keystores/debug.keystore 55 | 56 | # Expo 57 | .expo/* 58 | 59 | # generated by bob 60 | lib/ 61 | -------------------------------------------------------------------------------- /ios/RNGADBannerView.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #else 4 | #import "RCTView.h" 5 | #endif 6 | 7 | @import GoogleMobileAds; 8 | 9 | @class RCTEventDispatcher; 10 | 11 | @interface RNGADBannerView : RCTView 12 | 13 | @property (nonatomic, copy) NSArray *testDevices; 14 | @property (nonatomic, copy) NSString *adSize; 15 | 16 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoaded; 17 | @property (nonatomic, copy) RCTBubblingEventBlock onAdFailedToLoad; 18 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordImpression; 19 | @property (nonatomic, copy) RCTBubblingEventBlock onAdOpened; 20 | @property (nonatomic, copy) RCTBubblingEventBlock onAdClosed; 21 | @property (nonatomic, copy) RCTBubblingEventBlock onSizeChange; 22 | 23 | - (void)loadBanner; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-admob-next", 3 | "version": "1.2.0", 4 | "description": "A react-native component for Google AdMob banners and interstitials", 5 | "author": "Izet Molla ", 6 | "main": "dist/index.js", 7 | "types": "dist/index.d.js", 8 | "license": "BSD-2-Clause", 9 | "repository": { 10 | "type": "git", 11 | "url": "git@github.com:izetmolla/react-native-admob-next.git" 12 | }, 13 | "scripts": { 14 | "build": "rm -rf dist && tsc" 15 | }, 16 | "dependencies": { 17 | "prop-types": "^15.5.10" 18 | }, 19 | "peerDependencies": { 20 | "react-native": ">=0.44.0" 21 | }, 22 | "devDependencies": { 23 | "@types/react": "^17.0.15", 24 | "@types/react-native": "^0.64.12", 25 | "babel-eslint": "^7.2.3", 26 | "eslint": "^4.3.0", 27 | "eslint-plugin-react": "^7.1.0", 28 | "typescript": "^4.3.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ios/RNGAMBannerView.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #else 4 | #import "RCTView.h" 5 | #endif 6 | 7 | @import GoogleMobileAds; 8 | 9 | @class RCTEventDispatcher; 10 | 11 | @interface RNGAMBannerView : RCTView 12 | 13 | @property (nonatomic, copy) NSArray *validAdSizes; 14 | @property (nonatomic, copy) NSArray *testDevices; 15 | @property (nonatomic, copy) NSString *adSize; 16 | 17 | @property (nonatomic, copy) RCTBubblingEventBlock onAdLoaded; 18 | @property (nonatomic, copy) RCTBubblingEventBlock onAdFailedToLoad; 19 | @property (nonatomic, copy) RCTBubblingEventBlock onAdRecordImpression; 20 | @property (nonatomic, copy) RCTBubblingEventBlock onAdOpened; 21 | @property (nonatomic, copy) RCTBubblingEventBlock onAdClosed; 22 | @property (nonatomic, copy) RCTBubblingEventBlock onSizeChange; 23 | @property (nonatomic, copy) RCTBubblingEventBlock onAppEvent; 24 | 25 | - (void)loadBanner; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ios/RCTConvert+GADAdSize.m: -------------------------------------------------------------------------------- 1 | #import "RCTConvert+GADAdSize.h" 2 | 3 | @implementation RCTConvert (GADAdSize) 4 | 5 | + (GADAdSize)GADAdSize:(id)json withWidth:(CGFloat)width 6 | { 7 | NSString *adSize = [self NSString:json]; 8 | if ([adSize isEqualToString:@"banner"]) { 9 | return kGADAdSizeBanner; 10 | } else if ([adSize isEqualToString:@"fullBanner"]) { 11 | return kGADAdSizeFullBanner; 12 | } else if ([adSize isEqualToString:@"largeBanner"]) { 13 | return kGADAdSizeLargeBanner; 14 | } else if ([adSize isEqualToString:@"fluid"]) { 15 | return kGADAdSizeFluid; 16 | } else if ([adSize isEqualToString:@"skyscraper"]) { 17 | return kGADAdSizeSkyscraper; 18 | } else if ([adSize isEqualToString:@"leaderboard"]) { 19 | return kGADAdSizeLeaderboard; 20 | } else if ([adSize isEqualToString:@"mediumRectangle"]) { 21 | return kGADAdSizeMediumRectangle; 22 | } else if ([adSize isEqualToString:@"adaptiveBanner"]) { 23 | return GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(width); 24 | } 25 | else { 26 | return kGADAdSizeInvalid; 27 | } 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "react-themeui": ["./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 | "removeComments": true /* Do not emit comments to output. */, 26 | "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, 27 | "outDir": "./dist" /* Redirect output structure to the directory. */, 28 | "declaration": true /* Generates corresponding '.d.ts' file. */, 29 | "target": "esnext" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android/src/main/java/com/izo/rnadmob/RNAdMobPackage.java: -------------------------------------------------------------------------------- 1 | package com.izo.rnadmob; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | public class RNAdMobPackage implements ReactPackage { 15 | 16 | @Override 17 | public List createNativeModules(ReactApplicationContext reactContext) { 18 | return Arrays.asList( 19 | new RNAdMobInterstitialAdModule(reactContext), 20 | new RNAdMobRewardedVideoAdModule(reactContext) 21 | ); 22 | } 23 | 24 | // Deprecated from RN 0.47.0 25 | public List> createJSModules() { 26 | return Collections.emptyList(); 27 | } 28 | 29 | @Override 30 | public List createViewManagers(ReactApplicationContext reactContext) { 31 | return Arrays.asList( 32 | new RNAdMobBannerViewManager(), 33 | new RNPublisherBannerViewManager() 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Simon Bugert 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /react-native-admob-next.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | version = package['version'] 5 | 6 | Pod::Spec.new do |s| 7 | s.name = 'react-native-admob-next' 8 | s.version = version 9 | s.summary = 'A react-native component for Google AdMob banners' 10 | s.homepage = 'https://github.com/izetmolla/react-native-admob-next' 11 | s.license = package['license'] 12 | s.author = 'Izet Molla ' 13 | s.platform = :ios, '9.0' 14 | s.source = { :git => 'https://github.com/izetmolla/react-native-admob-next.git', :tag => "v#{version}" } 15 | s.source_files = 'ios/*.{h,m}' 16 | 17 | # We can't add the Google-Mobile-Ads-SDK as a dependency, as it would prevent 18 | # this library to be used with `use_frameworks!`. 19 | # So instead we add the default location of the framework to the framework 20 | # search paths, and we rely on consumers of this library to add 21 | # Google-Mobile-Ads-SDK as a direct dependency. 22 | # s.weak_frameworks = 'GoogleMobileAds' 23 | s.dependency 'Google-Mobile-Ads-SDK', "8.6.0" 24 | # s.dependency 'GoogleMobileAds' 25 | 26 | 27 | s.pod_target_xcconfig = { 28 | 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/Google-Mobile-Ads-SDK/Frameworks/**"', 29 | } 30 | 31 | s.dependency 'React' 32 | end 33 | -------------------------------------------------------------------------------- /dist/AdmobBanner.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef, useState } from "react"; 2 | import { requireNativeComponent, UIManager, findNodeHandle, } from "react-native"; 3 | import { createErrorFromErrorData } from "./utils"; 4 | const AdmobBanner = ({ style, onSizeChange, onAdFailedToLoad, ...res }) => { 5 | const _bannerView = useRef(null); 6 | const [custonStyle, setCustomStyle] = useState({}); 7 | useEffect(() => { 8 | loadBanner(); 9 | }); 10 | const loadBanner = () => { 11 | UIManager.dispatchViewManagerCommand(findNodeHandle(_bannerView.current), UIManager.getViewManagerConfig("RNGADBannerView").Commands 12 | .loadBanner, undefined); 13 | }; 14 | const handleSizeChange = (event) => { 15 | const { height, width } = event.nativeEvent; 16 | setCustomStyle({ width, height }); 17 | if (onSizeChange) { 18 | onSizeChange({ width, height }); 19 | } 20 | }; 21 | const handleAdFailedToLoad = (event) => { 22 | if (onAdFailedToLoad) { 23 | onAdFailedToLoad(createErrorFromErrorData(event.nativeEvent.error)); 24 | } 25 | }; 26 | return (React.createElement(RNGADBannerView, { ...res, style: [style, custonStyle], onSizeChange: handleSizeChange, onAdFailedToLoad: handleAdFailedToLoad, ref: _bannerView })); 27 | }; 28 | AdmobBanner.simulatorId = "SIMULATOR"; 29 | const RNGADBannerView = requireNativeComponent("RNGADBannerView"); 30 | export default AdmobBanner; 31 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | if (project == rootProject) { 3 | repositories { 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | // classpath 'com.android.tools.build:gradle:3.5.3' 9 | } 10 | } 11 | } 12 | 13 | apply plugin: 'com.android.library' 14 | 15 | def safeExtGet(prop, fallback) { 16 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 17 | } 18 | 19 | android { 20 | compileSdkVersion safeExtGet('compileSdkVersion', 30) 21 | defaultConfig { 22 | minSdkVersion safeExtGet('minSdkVersion', 16) 23 | targetSdkVersion safeExtGet('targetSdkVersion', 30) 24 | versionCode 1 25 | versionName "1.0" 26 | 27 | } 28 | 29 | buildTypes { 30 | release { 31 | minifyEnabled false 32 | } 33 | } 34 | lintOptions { 35 | disable 'GradleCompatible' 36 | } 37 | compileOptions { 38 | sourceCompatibility JavaVersion.VERSION_1_8 39 | targetCompatibility JavaVersion.VERSION_1_8 40 | } 41 | } 42 | 43 | repositories { 44 | mavenLocal() 45 | maven { 46 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 47 | url("$rootDir/../node_modules/react-native/android") 48 | } 49 | google() 50 | } 51 | 52 | dependencies { 53 | //noinspection GradleDynamicVersion 54 | implementation "com.facebook.react:react-native:+" // From node_modules 55 | implementation 'com.intellij:annotations:+@jar' 56 | implementation 'com.google.android.gms:play-services-ads:20.2.0' 57 | } 58 | -------------------------------------------------------------------------------- /ios/RNGADBannerViewManager.m: -------------------------------------------------------------------------------- 1 | #import "RNGADBannerViewManager.h" 2 | #import "RNGADBannerView.h" 3 | #import "RCTConvert+GADAdSize.h" 4 | 5 | #if __has_include() 6 | #import 7 | #import 8 | #import 9 | #else 10 | #import "RCTBridge.h" 11 | #import "RCTUIManager.h" 12 | #import "RCTEventDispatcher.h" 13 | #endif 14 | 15 | @implementation RNGADBannerViewManager 16 | 17 | RCT_EXPORT_MODULE(); 18 | 19 | - (UIView *)view 20 | { 21 | return [RNGADBannerView new]; 22 | } 23 | 24 | RCT_EXPORT_METHOD(loadBanner:(nonnull NSNumber *)reactTag) 25 | { 26 | [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { 27 | RNGADBannerView *view = viewRegistry[reactTag]; 28 | if (![view isKindOfClass:[RNGADBannerView class]]) { 29 | RCTLogError(@"Invalid view returned from registry, expecting RNGADBannerView, got: %@", view); 30 | } else { 31 | [view loadBanner]; 32 | } 33 | }]; 34 | } 35 | 36 | RCT_REMAP_VIEW_PROPERTY(adUnitID, _bannerView.adUnitID, NSString) 37 | 38 | RCT_EXPORT_VIEW_PROPERTY(adSize, NSString) 39 | RCT_EXPORT_VIEW_PROPERTY(testDevices, NSArray) 40 | 41 | RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTBubblingEventBlock) 42 | RCT_EXPORT_VIEW_PROPERTY(onAdFailedToLoad, RCTBubblingEventBlock) 43 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordImpression,RCTBubblingEventBlock) 44 | RCT_EXPORT_VIEW_PROPERTY(onAdOpened, RCTBubblingEventBlock) 45 | RCT_EXPORT_VIEW_PROPERTY(onAdClosed, RCTBubblingEventBlock) 46 | RCT_EXPORT_VIEW_PROPERTY(onSizeChange, RCTBubblingEventBlock) 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /ios/RNGAMBannerViewManager.m: -------------------------------------------------------------------------------- 1 | #import "RNGAMBannerViewManager.h" 2 | #import "RNGAMBannerView.h" 3 | 4 | #if __has_include() 5 | #import 6 | #import 7 | #import 8 | #else 9 | #import "RCTBridge.h" 10 | #import "RCTUIManager.h" 11 | #import "RCTEventDispatcher.h" 12 | #endif 13 | 14 | @implementation RNGAMBannerViewManager 15 | 16 | RCT_EXPORT_MODULE(); 17 | 18 | - (UIView *)view 19 | { 20 | return [RNGAMBannerView new]; 21 | } 22 | 23 | RCT_EXPORT_METHOD(loadBanner:(nonnull NSNumber *)reactTag) 24 | { 25 | [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary *viewRegistry) { 26 | RNGAMBannerView *view = viewRegistry[reactTag]; 27 | if (![view isKindOfClass:[RNGAMBannerView class]]) { 28 | RCTLogError(@"Invalid view returned from registry, expecting RNGADBannerView, got: %@", view); 29 | } else { 30 | [view loadBanner]; 31 | } 32 | }]; 33 | } 34 | 35 | RCT_REMAP_VIEW_PROPERTY(adUnitID, _bannerView.adUnitID, NSString) 36 | 37 | RCT_EXPORT_VIEW_PROPERTY(adSize, NSString) 38 | RCT_EXPORT_VIEW_PROPERTY(validAdSizes, NSArray) 39 | RCT_EXPORT_VIEW_PROPERTY(testDevices, NSArray) 40 | 41 | RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTBubblingEventBlock) 42 | RCT_EXPORT_VIEW_PROPERTY(onAdFailedToLoad, RCTBubblingEventBlock) 43 | RCT_EXPORT_VIEW_PROPERTY(onAdRecordImpression,RCTBubblingEventBlock) 44 | RCT_EXPORT_VIEW_PROPERTY(onAdOpened, RCTBubblingEventBlock) 45 | RCT_EXPORT_VIEW_PROPERTY(onAdClosed, RCTBubblingEventBlock) 46 | RCT_EXPORT_VIEW_PROPERTY(onSizeChange, RCTBubblingEventBlock) 47 | RCT_EXPORT_VIEW_PROPERTY(onAppEvent, RCTBubblingEventBlock) 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /RNAdMobInterstitial.js: -------------------------------------------------------------------------------- 1 | import { 2 | NativeModules, 3 | NativeEventEmitter, 4 | } from 'react-native'; 5 | 6 | import { createErrorFromErrorData } from './utils'; 7 | 8 | const RNAdMobInterstitial = NativeModules.RNAdMobInterstitial; 9 | 10 | const eventEmitter = new NativeEventEmitter(RNAdMobInterstitial); 11 | 12 | const eventMap = { 13 | adLoaded: 'interstitialAdLoaded', 14 | adFailedToLoad: 'interstitialAdFailedToLoad', 15 | adOpened: 'interstitialAdOpened', 16 | adFailedToOpen: 'interstitialAdFailedToOpen', 17 | adClosed: 'interstitialAdClosed', 18 | adImpression: 'interstitialAdImpression', 19 | }; 20 | 21 | const _subscriptions = new Map(); 22 | 23 | const addEventListener = (event, handler) => { 24 | const mappedEvent = eventMap[event]; 25 | if (mappedEvent) { 26 | let listener; 27 | if (event === 'adFailedToLoad') { 28 | listener = eventEmitter.addListener(mappedEvent, error => handler(createErrorFromErrorData(error))); 29 | } else { 30 | listener = eventEmitter.addListener(mappedEvent, handler); 31 | } 32 | _subscriptions.set(handler, listener); 33 | return { 34 | remove: () => removeEventListener(event, handler), 35 | }; 36 | } else { 37 | // eslint-disable-next-line no-console 38 | console.warn(`Trying to subscribe to unknown event: "${event}"`); 39 | return { 40 | remove: () => {}, 41 | }; 42 | } 43 | }; 44 | 45 | const removeEventListener = (type, handler) => { 46 | const listener = _subscriptions.get(handler); 47 | if (!listener) { 48 | return; 49 | } 50 | listener.remove(); 51 | _subscriptions.delete(handler); 52 | }; 53 | 54 | const removeAllListeners = () => { 55 | _subscriptions.forEach((listener, key, map) => { 56 | listener.remove(); 57 | map.delete(key); 58 | }); 59 | }; 60 | 61 | export default { 62 | ...RNAdMobInterstitial, 63 | addEventListener, 64 | removeEventListener, 65 | removeAllListeners, 66 | simulatorId: 'SIMULATOR', 67 | }; 68 | -------------------------------------------------------------------------------- /dist/AdMobInterstitial.js: -------------------------------------------------------------------------------- 1 | import { NativeModules, NativeEventEmitter } from "react-native"; 2 | import { createErrorFromErrorData } from "./utils"; 3 | const RNAdMobInterstitial = NativeModules.RNAdMobInterstitial; 4 | const eventEmitter = new NativeEventEmitter(RNAdMobInterstitial); 5 | const eventMap = { 6 | adLoaded: "interstitialAdLoaded", 7 | adFailedToLoad: "interstitialAdFailedToLoad", 8 | adOpened: "interstitialAdOpened", 9 | adFailedToOpen: "interstitialAdFailedToOpen", 10 | adClosed: "interstitialAdClosed", 11 | adImpression: "interstitialAdImpression", 12 | }; 13 | const _subscriptions = new Map(); 14 | const addEventListener = (event, handler) => { 15 | const mappedEvent = eventMap[event]; 16 | if (mappedEvent) { 17 | let listener; 18 | if (event === "adFailedToLoad") { 19 | listener = eventEmitter.addListener(mappedEvent, (error) => handler(createErrorFromErrorData(error))); 20 | } 21 | else { 22 | listener = eventEmitter.addListener(mappedEvent, handler); 23 | } 24 | _subscriptions.set(handler, listener); 25 | return { 26 | remove: () => removeEventListener(event, handler), 27 | }; 28 | } 29 | else { 30 | console.warn(`Trying to subscribe to unknown event: "${event}"`); 31 | return { 32 | remove: () => { }, 33 | }; 34 | } 35 | }; 36 | const removeEventListener = (type, handler) => { 37 | const listener = _subscriptions.get(handler); 38 | if (!listener) { 39 | return; 40 | } 41 | listener.remove(); 42 | _subscriptions.delete(handler); 43 | }; 44 | const removeAllListeners = () => { 45 | _subscriptions.forEach((listener, key, map) => { 46 | listener.remove(); 47 | map.delete(key); 48 | }); 49 | }; 50 | export default { 51 | ...RNAdMobInterstitial, 52 | addEventListener, 53 | removeEventListener, 54 | removeAllListeners, 55 | simulatorId: "SIMULATOR", 56 | }; 57 | -------------------------------------------------------------------------------- /RNAdMobRewarded.js: -------------------------------------------------------------------------------- 1 | import { 2 | NativeModules, 3 | NativeEventEmitter, 4 | } from 'react-native'; 5 | 6 | import { createErrorFromErrorData } from './utils'; 7 | 8 | const RNAdMobRewarded = NativeModules.RNAdMobRewarded; 9 | 10 | const eventEmitter = new NativeEventEmitter(RNAdMobRewarded); 11 | 12 | const eventMap = { 13 | adLoaded: 'rewardedVideoAdLoaded', 14 | adFailedToLoad: 'rewardedVideoAdFailedToLoad', 15 | adOpened: 'rewardedVideoAdOpened', 16 | adFailedToOpen:'rewardedVideoAdFailedToOpen', 17 | adClosed: 'rewardedVideoAdClosed', 18 | rewarded: 'rewardedVideoAdRewarded', 19 | adImpression: 'rewardedVideoAdImpression', 20 | }; 21 | 22 | const _subscriptions = new Map(); 23 | 24 | const addEventListener = (event, handler) => { 25 | const mappedEvent = eventMap[event]; 26 | if (mappedEvent) { 27 | let listener; 28 | if (event === 'adFailedToLoad') { 29 | listener = eventEmitter.addListener(mappedEvent, error => handler(createErrorFromErrorData(error))); 30 | } else { 31 | listener = eventEmitter.addListener(mappedEvent, handler); 32 | } 33 | _subscriptions.set(handler, listener); 34 | return { 35 | remove: () => removeEventListener(event, handler), 36 | }; 37 | } else { 38 | // eslint-disable-next-line no-console 39 | console.warn(`Trying to subscribe to unknown event: "${event}"`); 40 | return { 41 | remove: () => {}, 42 | }; 43 | } 44 | }; 45 | 46 | const removeEventListener = (type, handler) => { 47 | const listener = _subscriptions.get(handler); 48 | if (!listener) { 49 | return; 50 | } 51 | listener.remove(); 52 | _subscriptions.delete(handler); 53 | }; 54 | 55 | const removeAllListeners = () => { 56 | _subscriptions.forEach((listener, key, map) => { 57 | listener.remove(); 58 | map.delete(key); 59 | }); 60 | }; 61 | 62 | export default { 63 | ...RNAdMobRewarded, 64 | addEventListener, 65 | removeEventListener, 66 | removeAllListeners, 67 | simulatorId: 'SIMULATOR', 68 | }; 69 | -------------------------------------------------------------------------------- /dist/AdMobRewarded.js: -------------------------------------------------------------------------------- 1 | import { NativeModules, NativeEventEmitter } from "react-native"; 2 | import { createErrorFromErrorData } from "./utils"; 3 | const RNAdMobRewarded = NativeModules.RNAdMobRewarded; 4 | const eventEmitter = new NativeEventEmitter(RNAdMobRewarded); 5 | const eventMap = { 6 | adLoaded: "rewardedVideoAdLoaded", 7 | adFailedToLoad: "rewardedVideoAdFailedToLoad", 8 | adOpened: "rewardedVideoAdOpened", 9 | adFailedToOpen: "rewardedVideoAdFailedToOpen", 10 | adClosed: "rewardedVideoAdClosed", 11 | rewarded: "rewardedVideoAdRewarded", 12 | adImpression: "rewardedVideoAdImpression", 13 | }; 14 | const _subscriptions = new Map(); 15 | const addEventListener = (event, handler) => { 16 | const mappedEvent = eventMap[event]; 17 | if (mappedEvent) { 18 | let listener; 19 | if (event === "adFailedToLoad") { 20 | listener = eventEmitter.addListener(mappedEvent, (error) => handler(createErrorFromErrorData(error))); 21 | } 22 | else { 23 | listener = eventEmitter.addListener(mappedEvent, handler); 24 | } 25 | _subscriptions.set(handler, listener); 26 | return { 27 | remove: () => removeEventListener(event, handler), 28 | }; 29 | } 30 | else { 31 | console.warn(`Trying to subscribe to unknown event: "${event}"`); 32 | return { 33 | remove: () => { }, 34 | }; 35 | } 36 | }; 37 | const removeEventListener = (type, handler) => { 38 | const listener = _subscriptions.get(handler); 39 | if (!listener) { 40 | return; 41 | } 42 | listener.remove(); 43 | _subscriptions.delete(handler); 44 | }; 45 | const removeAllListeners = () => { 46 | _subscriptions.forEach((listener, key, map) => { 47 | listener.remove(); 48 | map.delete(key); 49 | }); 50 | }; 51 | export default { 52 | ...RNAdMobRewarded, 53 | addEventListener, 54 | removeEventListener, 55 | removeAllListeners, 56 | simulatorId: "SIMULATOR", 57 | }; 58 | -------------------------------------------------------------------------------- /src/AdMobInterstitial.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules, NativeEventEmitter } from "react-native"; 2 | 3 | import { createErrorFromErrorData } from "./utils"; 4 | 5 | const RNAdMobInterstitial = NativeModules.RNAdMobInterstitial; 6 | 7 | const eventEmitter = new NativeEventEmitter(RNAdMobInterstitial); 8 | 9 | const eventMap = { 10 | adLoaded: "interstitialAdLoaded", 11 | adFailedToLoad: "interstitialAdFailedToLoad", 12 | adOpened: "interstitialAdOpened", 13 | adFailedToOpen: "interstitialAdFailedToOpen", 14 | adClosed: "interstitialAdClosed", 15 | adImpression: "interstitialAdImpression", 16 | }; 17 | 18 | const _subscriptions = new Map(); 19 | 20 | const addEventListener = (event: any, handler: any) => { 21 | const mappedEvent = eventMap[event]; 22 | if (mappedEvent) { 23 | let listener; 24 | if (event === "adFailedToLoad") { 25 | listener = eventEmitter.addListener(mappedEvent, (error) => 26 | handler(createErrorFromErrorData(error)) 27 | ); 28 | } else { 29 | listener = eventEmitter.addListener(mappedEvent, handler); 30 | } 31 | _subscriptions.set(handler, listener); 32 | return { 33 | remove: () => removeEventListener(event, handler), 34 | }; 35 | } else { 36 | // eslint-disable-next-line no-console 37 | console.warn(`Trying to subscribe to unknown event: "${event}"`); 38 | return { 39 | remove: () => {}, 40 | }; 41 | } 42 | }; 43 | 44 | const removeEventListener = (type: any, handler: any) => { 45 | const listener = _subscriptions.get(handler); 46 | if (!listener) { 47 | return; 48 | } 49 | listener.remove(); 50 | _subscriptions.delete(handler); 51 | }; 52 | 53 | const removeAllListeners = () => { 54 | _subscriptions.forEach((listener, key, map) => { 55 | listener.remove(); 56 | map.delete(key); 57 | }); 58 | }; 59 | 60 | export default { 61 | ...RNAdMobInterstitial, 62 | addEventListener, 63 | removeEventListener, 64 | removeAllListeners, 65 | simulatorId: "SIMULATOR", 66 | }; 67 | -------------------------------------------------------------------------------- /src/AdmobBanner.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useEffect, useRef, useState } from "react"; 2 | import { 3 | requireNativeComponent, 4 | UIManager, 5 | findNodeHandle, 6 | } from "react-native"; 7 | 8 | import { createErrorFromErrorData } from "./utils"; 9 | 10 | type AdmobBannerTypes = { 11 | style?: any | {}; 12 | onSizeChange?: any; 13 | onAdFailedToLoad?: any; 14 | adSize?: string; 15 | adUnitID?: string; 16 | testDevices?: any; 17 | onAdLoaded?: any; 18 | onAdRecordImpression?: any; 19 | onAdOpened?: any; 20 | onAdClosed?: any; 21 | simulatorId?: string | "SIMULATOR"; 22 | }; 23 | const AdmobBanner: FC = ({ 24 | style, 25 | onSizeChange, 26 | onAdFailedToLoad, 27 | ...res 28 | }) => { 29 | const _bannerView: any = useRef(null); 30 | const [custonStyle, setCustomStyle]: any = useState({}); 31 | useEffect(() => { 32 | loadBanner(); 33 | }); 34 | 35 | const loadBanner = () => { 36 | UIManager.dispatchViewManagerCommand( 37 | findNodeHandle(_bannerView.current), 38 | UIManager.getViewManagerConfig("RNGADBannerView").Commands 39 | .loadBanner, 40 | undefined 41 | ); 42 | }; 43 | const handleSizeChange = (event: any) => { 44 | const { height, width } = event.nativeEvent; 45 | setCustomStyle({ width, height }); 46 | if (onSizeChange) { 47 | onSizeChange({ width, height }); 48 | } 49 | }; 50 | const handleAdFailedToLoad = (event: any) => { 51 | if (onAdFailedToLoad) { 52 | onAdFailedToLoad(createErrorFromErrorData(event.nativeEvent.error)); 53 | } 54 | }; 55 | return ( 56 | 63 | ); 64 | }; 65 | 66 | AdmobBanner.simulatorId = "SIMULATOR"; 67 | 68 | const RNGADBannerView = requireNativeComponent("RNGADBannerView"); 69 | 70 | export default AdmobBanner; 71 | -------------------------------------------------------------------------------- /src/AdMobRewarded.ts: -------------------------------------------------------------------------------- 1 | import { NativeModules, NativeEventEmitter } from "react-native"; 2 | 3 | import { createErrorFromErrorData } from "./utils"; 4 | 5 | const RNAdMobRewarded = NativeModules.RNAdMobRewarded; 6 | 7 | const eventEmitter = new NativeEventEmitter(RNAdMobRewarded); 8 | 9 | const eventMap = { 10 | adLoaded: "rewardedVideoAdLoaded", 11 | adFailedToLoad: "rewardedVideoAdFailedToLoad", 12 | adOpened: "rewardedVideoAdOpened", 13 | adFailedToOpen: "rewardedVideoAdFailedToOpen", 14 | adClosed: "rewardedVideoAdClosed", 15 | rewarded: "rewardedVideoAdRewarded", 16 | adImpression: "rewardedVideoAdImpression", 17 | }; 18 | 19 | const _subscriptions = new Map(); 20 | 21 | const addEventListener = (event: any, handler: any) => { 22 | const mappedEvent = eventMap[event]; 23 | if (mappedEvent) { 24 | let listener; 25 | if (event === "adFailedToLoad") { 26 | listener = eventEmitter.addListener(mappedEvent, (error) => 27 | handler(createErrorFromErrorData(error)) 28 | ); 29 | } else { 30 | listener = eventEmitter.addListener(mappedEvent, handler); 31 | } 32 | _subscriptions.set(handler, listener); 33 | return { 34 | remove: () => removeEventListener(event, handler), 35 | }; 36 | } else { 37 | // eslint-disable-next-line no-console 38 | console.warn(`Trying to subscribe to unknown event: "${event}"`); 39 | return { 40 | remove: () => {}, 41 | }; 42 | } 43 | }; 44 | 45 | const removeEventListener = (type: any, handler: any) => { 46 | const listener = _subscriptions.get(handler); 47 | if (!listener) { 48 | return; 49 | } 50 | listener.remove(); 51 | _subscriptions.delete(handler); 52 | }; 53 | 54 | const removeAllListeners = () => { 55 | _subscriptions.forEach((listener, key, map) => { 56 | listener.remove(); 57 | map.delete(key); 58 | }); 59 | }; 60 | 61 | export default { 62 | ...RNAdMobRewarded, 63 | addEventListener, 64 | removeEventListener, 65 | removeAllListeners, 66 | simulatorId: "SIMULATOR", 67 | }; 68 | -------------------------------------------------------------------------------- /RNAdMobBanner.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | requireNativeComponent, 4 | UIManager, 5 | findNodeHandle, 6 | ViewPropTypes, 7 | } from 'react-native'; 8 | import { string, func, arrayOf } from 'prop-types'; 9 | 10 | import { createErrorFromErrorData } from './utils'; 11 | 12 | class AdMobBanner extends Component { 13 | 14 | constructor() { 15 | super(); 16 | this.handleSizeChange = this.handleSizeChange.bind(this); 17 | this.handleAdFailedToLoad = this.handleAdFailedToLoad.bind(this); 18 | this.state = { 19 | style: {}, 20 | }; 21 | } 22 | 23 | componentDidMount() { 24 | this.loadBanner(); 25 | } 26 | 27 | loadBanner() { 28 | UIManager.dispatchViewManagerCommand( 29 | findNodeHandle(this._bannerView), 30 | UIManager.getViewManagerConfig('RNGADBannerView').Commands.loadBanner, 31 | null, 32 | ); 33 | } 34 | 35 | handleSizeChange(event) { 36 | const { height, width } = event.nativeEvent; 37 | this.setState({ style: { width, height } }); 38 | if (this.props.onSizeChange) { 39 | this.props.onSizeChange({ width, height }); 40 | } 41 | } 42 | 43 | handleAdFailedToLoad(event) { 44 | if (this.props.onAdFailedToLoad) { 45 | this.props.onAdFailedToLoad(createErrorFromErrorData(event.nativeEvent.error)); 46 | } 47 | } 48 | 49 | render() { 50 | return ( 51 | (this._bannerView = el)} 57 | /> 58 | ); 59 | } 60 | } 61 | 62 | AdMobBanner.simulatorId = 'SIMULATOR'; 63 | 64 | AdMobBanner.propTypes = { 65 | ...ViewPropTypes, 66 | 67 | /** 68 | * AdMob iOS library banner size constants 69 | * (https://developers.google.com/admob/ios/banner) 70 | * banner (320x50, Standard Banner for Phones and Tablets) 71 | * largeBanner (320x100, Large Banner for Phones and Tablets) 72 | * mediumRectangle (300x250, IAB Medium Rectangle for Phones and Tablets) 73 | * fullBanner (468x60, IAB Full-Size Banner for Tablets) 74 | * leaderboard (728x90, IAB Leaderboard for Tablets) 75 | * adaptiveBannerPortrait (Screen width x Adaptive height, Adaptive Banner for Phones and Tablets) 76 | * adaptiveBannerLandscape (Screen width x Adaptive height, Adaptive Banner for Phones and Tablets) 77 | * 78 | * banner is default 79 | */ 80 | adSize: string, 81 | 82 | /** 83 | * AdMob ad unit ID 84 | */ 85 | adUnitID: string, 86 | 87 | /** 88 | * Array of test devices. Use AdMobBanner.simulatorId for the simulator 89 | */ 90 | testDevices: arrayOf(string), 91 | 92 | /** 93 | * AdMob iOS library events 94 | */ 95 | onSizeChange: func, 96 | 97 | onAdLoaded: func, 98 | onAdFailedToLoad: func, 99 | onAdRecordImpression: func, 100 | onAdOpened: func, 101 | onAdClosed: func, 102 | }; 103 | 104 | const RNGADBannerView = requireNativeComponent('RNGADBannerView', AdMobBanner); 105 | 106 | export default AdMobBanner; 107 | -------------------------------------------------------------------------------- /RNPublisherBanner.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { 3 | requireNativeComponent, 4 | UIManager, 5 | findNodeHandle, 6 | ViewPropTypes, 7 | } from 'react-native'; 8 | import { string, func, arrayOf } from 'prop-types'; 9 | 10 | import { createErrorFromErrorData } from './utils'; 11 | 12 | class PublisherBanner extends Component { 13 | 14 | constructor() { 15 | super(); 16 | this.handleSizeChange = this.handleSizeChange.bind(this); 17 | this.handleAppEvent = this.handleAppEvent.bind(this); 18 | this.handleAdFailedToLoad = this.handleAdFailedToLoad.bind(this); 19 | this.state = { 20 | style: {}, 21 | }; 22 | } 23 | 24 | componentDidMount() { 25 | this.loadBanner(); 26 | } 27 | 28 | loadBanner() { 29 | UIManager.dispatchViewManagerCommand( 30 | findNodeHandle(this._bannerView), 31 | UIManager.getViewManagerConfig('RNGAMBannerView').Commands.loadBanner, 32 | null, 33 | ); 34 | } 35 | 36 | handleSizeChange(event) { 37 | const { height, width } = event.nativeEvent; 38 | this.setState({ style: { width, height } }); 39 | if (this.props.onSizeChange) { 40 | this.props.onSizeChange({ width, height }); 41 | } 42 | } 43 | 44 | handleAppEvent(event) { 45 | if (this.props.onAppEvent) { 46 | const { name, info } = event.nativeEvent; 47 | this.props.onAppEvent({ name, info }); 48 | } 49 | } 50 | 51 | handleAdFailedToLoad(event) { 52 | if (this.props.onAdFailedToLoad) { 53 | this.props.onAdFailedToLoad(createErrorFromErrorData(event.nativeEvent.error)); 54 | } 55 | } 56 | 57 | render() { 58 | return ( 59 | (this._bannerView = el)} 66 | /> 67 | ); 68 | } 69 | } 70 | 71 | PublisherBanner.simulatorId = 'SIMULATOR'; 72 | 73 | PublisherBanner.propTypes = { 74 | ...ViewPropTypes, 75 | 76 | /** 77 | * DFP iOS library banner size constants 78 | * (https://developers.google.com/admob/ios/banner) 79 | * banner (320x50, Standard Banner for Phones and Tablets) 80 | * largeBanner (320x100, Large Banner for Phones and Tablets) 81 | * mediumRectangle (300x250, IAB Medium Rectangle for Phones and Tablets) 82 | * fullBanner (468x60, IAB Full-Size Banner for Tablets) 83 | * leaderboard (728x90, IAB Leaderboard for Tablets) 84 | * adaptiveBannerPortrait (Screen width x Adaptive height, Adaptive Banner for Phones and Tablets) 85 | * adaptiveBannerLandscape (Screen width x Adaptive height, Adaptive Banner for Phones and Tablets) 86 | * 87 | * banner is default 88 | */ 89 | adSize: string, 90 | 91 | /** 92 | * Optional array specifying all valid sizes that are appropriate for this slot. 93 | */ 94 | validAdSizes: arrayOf(string), 95 | 96 | /** 97 | * DFP ad unit ID 98 | */ 99 | adUnitID: string, 100 | 101 | /** 102 | * Array of test devices. Use PublisherBanner.simulatorId for the simulator 103 | */ 104 | testDevices: arrayOf(string), 105 | 106 | onSizeChange: func, 107 | 108 | /** 109 | * DFP library events 110 | */ 111 | onAdLoaded: func, 112 | onAdFailedToLoad: func, 113 | onAdOpened: func, 114 | onAdClosed: func, 115 | onAppEvent: func, 116 | }; 117 | 118 | const RNGAMBannerView = requireNativeComponent('RNGAMBannerView', PublisherBanner); 119 | 120 | export default PublisherBanner; 121 | -------------------------------------------------------------------------------- /ios/RNGADBannerView.m: -------------------------------------------------------------------------------- 1 | #import "RNGADBannerView.h" 2 | #import "RNAdMobUtils.h" 3 | 4 | #if __has_include() 5 | #import 6 | #import 7 | #import 8 | #else 9 | #import "RCTBridgeModule.h" 10 | #import "UIView+React.h" 11 | #import "RCTLog.h" 12 | #endif 13 | 14 | #include "RCTConvert+GADAdSize.h" 15 | 16 | @implementation RNGADBannerView 17 | { 18 | GADBannerView *_bannerView; 19 | } 20 | 21 | - (void)dealloc 22 | { 23 | _bannerView.delegate = nil; 24 | _bannerView.adSizeDelegate = nil; 25 | } 26 | 27 | - (instancetype)initWithFrame:(CGRect)frame 28 | { 29 | if ((self = [super initWithFrame:frame])) { 30 | super.backgroundColor = [UIColor clearColor]; 31 | 32 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 33 | 34 | _bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner]; 35 | _bannerView.delegate = self; 36 | _bannerView.adSizeDelegate = self; 37 | _bannerView.rootViewController = rootViewController; 38 | [self addSubview:_bannerView]; 39 | } 40 | return self; 41 | } 42 | 43 | #pragma clang diagnostic push 44 | #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" 45 | - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex 46 | { 47 | RCTLogError(@"RNGADBannerView cannot have subviews"); 48 | } 49 | #pragma clang diagnostic pop 50 | 51 | - (void)loadBanner 52 | { 53 | if(self.onSizeChange) { 54 | CGSize size = CGSizeFromGADAdSize(_bannerView.adSize); 55 | if(!CGSizeEqualToSize(size, self.bounds.size)) { 56 | self.onSizeChange(@{ 57 | @"width": @(size.width), 58 | @"height": @(size.height) 59 | }); 60 | } 61 | } 62 | 63 | GADRequest *request = [GADRequest request]; 64 | [_bannerView loadRequest:request]; 65 | } 66 | 67 | - (void)setTestDevices:(NSArray *)testDevices 68 | { 69 | _testDevices = RNAdMobProcessTestDevices(testDevices, kGADSimulatorID); 70 | 71 | [GADMobileAds sharedInstance].requestConfiguration.testDeviceIdentifiers = _testDevices; 72 | } 73 | 74 | - (void)setAdSize:(NSString *)adSize 75 | { 76 | _adSize = adSize; 77 | 78 | UIView *view = _bannerView.rootViewController.view; 79 | CGRect frame = view.frame; 80 | 81 | if (@available(iOS 11.0, *)) { 82 | frame = UIEdgeInsetsInsetRect(view.frame, view.safeAreaInsets); 83 | } 84 | 85 | [_bannerView setAdSize:[RCTConvert GADAdSize:_adSize withWidth:frame.size.width]]; 86 | } 87 | 88 | -(void)layoutSubviews 89 | { 90 | [super layoutSubviews]; 91 | _bannerView.frame = self.bounds; 92 | } 93 | 94 | # pragma mark GADBannerViewDelegate 95 | 96 | /// Tells the delegate that an ad request successfully received an ad. The delegate may want to add 97 | /// the banner view to the view hierarchy if it hasn't been added yet. 98 | - (void)bannerViewDidReceiveAd:(nonnull GADBannerView *)bannerView 99 | { 100 | if (self.onAdLoaded) { 101 | self.onAdLoaded(@{}); 102 | } 103 | } 104 | 105 | /// Tells the delegate that an ad request failed. The failure is normally due to network 106 | /// connectivity or ad availablility (i.e., no fill). 107 | - (void)bannerView:(nonnull GADBannerView *)bannerView 108 | didFailToReceiveAdWithError:(nonnull NSError *)error 109 | { 110 | if (self.onAdFailedToLoad) { 111 | self.onAdFailedToLoad(@{ @"error": @{ @"message": [error localizedDescription] } }); 112 | } 113 | } 114 | 115 | /// Tells the delegate that an impression has been recorded for an ad. 116 | - (void)bannerViewDidRecordImpression:(nonnull GADBannerView *)bannerView 117 | { 118 | if (self.onAdRecordImpression) { 119 | self.onAdRecordImpression(@{}); 120 | } 121 | } 122 | 123 | /// Tells the delegate that a full screen view will be presented in response to the user clicking on 124 | /// an ad. The delegate may want to pause animations and time sensitive interactions. 125 | - (void)bannerViewWillPresentScreen:(nonnull GADBannerView *)bannerView 126 | { 127 | if (self.onAdOpened) { 128 | self.onAdOpened(@{}); 129 | } 130 | } 131 | 132 | /// Tells the delegate that the full screen view will be dismissed. 133 | - (void)bannerViewWillDismissScreen:(nonnull GADBannerView *)bannerView 134 | { 135 | if (self.onAdClosed) { 136 | self.onAdClosed(@{}); 137 | } 138 | } 139 | 140 | # pragma mark GADAdSizeDelegate 141 | 142 | /// Called before the ad view changes to the new size. 143 | - (void)adView:(nonnull GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size 144 | { 145 | CGSize adSize = CGSizeFromGADAdSize(size); 146 | self.onSizeChange(@{ 147 | @"width": @(adSize.width), 148 | @"height": @(adSize.height) 149 | }); 150 | } 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /ios/RNAdMobRewarded.m: -------------------------------------------------------------------------------- 1 | #import "RNAdMobRewarded.h" 2 | #import "RNAdMobUtils.h" 3 | 4 | #if __has_include() 5 | #import 6 | #else 7 | #import "RCTUtils.h" 8 | #endif 9 | 10 | static NSString *const kEventAdLoaded = @"rewardedVideoAdLoaded"; 11 | static NSString *const kEventAdFailedToLoad = @"rewardedVideoAdFailedToLoad"; 12 | static NSString *const kEventAdOpened = @"rewardedVideoAdOpened"; 13 | static NSString *const kEventAdFailedToOpen = @"rewardedVideoAdFailedToOpen"; 14 | static NSString *const kEventAdClosed = @"rewardedVideoAdClosed"; 15 | static NSString *const kEventRewarded = @"rewardedVideoAdRewarded"; 16 | static NSString *const kEventAdImpression = @"rewardedVideoAdImpression"; 17 | 18 | @implementation RNAdMobRewarded 19 | { 20 | NSString *_adUnitID; 21 | NSArray *_testDevices; 22 | GADRewardedAd *_rewardedAd; 23 | BOOL hasListeners; 24 | } 25 | 26 | - (dispatch_queue_t)methodQueue 27 | { 28 | return dispatch_get_main_queue(); 29 | } 30 | 31 | + (BOOL)requiresMainQueueSetup 32 | { 33 | return NO; 34 | } 35 | 36 | RCT_EXPORT_MODULE(); 37 | 38 | - (NSArray *)supportedEvents 39 | { 40 | return @[ 41 | kEventRewarded, 42 | kEventAdLoaded, 43 | kEventAdFailedToLoad, 44 | kEventAdOpened, 45 | kEventAdFailedToOpen, 46 | kEventAdClosed, 47 | kEventAdImpression ]; 48 | } 49 | 50 | #pragma mark exported methods 51 | 52 | RCT_EXPORT_METHOD(setAdUnitID:(NSString *)adUnitID) 53 | { 54 | _adUnitID = adUnitID; 55 | } 56 | 57 | RCT_EXPORT_METHOD(setTestDevices:(NSArray *)testDevices) 58 | { 59 | _testDevices = RNAdMobProcessTestDevices(testDevices, kGADSimulatorID); 60 | } 61 | 62 | RCT_EXPORT_METHOD(requestAd:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 63 | { 64 | GADRequest *request = [GADRequest request]; 65 | [GADRewardedAd loadWithAdUnitID:_adUnitID 66 | request:request 67 | completionHandler:^(GADRewardedAd * _Nullable rewardedAd, NSError * _Nullable error) { 68 | if (error) { 69 | if (self->hasListeners) { 70 | NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError(@"E_AD_FAILED_TO_LOAD", error.localizedDescription, error); 71 | [self sendEventWithName:kEventAdFailedToLoad body:jsError]; 72 | } 73 | 74 | reject(@"E_AD_FAILED_TO_LOAD", error.localizedDescription, error); 75 | 76 | return; 77 | } 78 | 79 | self->_rewardedAd = rewardedAd; 80 | self->_rewardedAd.fullScreenContentDelegate = self; 81 | 82 | if (self->hasListeners) { 83 | [self sendEventWithName:kEventAdLoaded body:nil]; 84 | } 85 | 86 | resolve(nil); 87 | }]; 88 | } 89 | 90 | RCT_EXPORT_METHOD(showAd:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 91 | { 92 | if (!_rewardedAd) { 93 | reject(@"E_AD_NOT_READY", @"Ad is not ready.", nil); 94 | return; 95 | } 96 | 97 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 98 | BOOL isReady = [_rewardedAd canPresentFromRootViewController:rootViewController error:nil]; 99 | 100 | if (isReady) { 101 | [_rewardedAd presentFromRootViewController:rootViewController 102 | userDidEarnRewardHandler:^{ 103 | GADAdReward *reward = self->_rewardedAd.adReward; 104 | 105 | if (self->hasListeners) { 106 | [self sendEventWithName:kEventRewarded body:@{@"type": reward.type, @"amount": reward.amount}]; 107 | } 108 | }]; 109 | 110 | resolve(nil); 111 | } else { 112 | reject(@"E_AD_NOT_READY", @"Ad is not ready.", nil); 113 | } 114 | } 115 | 116 | RCT_EXPORT_METHOD(isReady:(RCTResponseSenderBlock)callback) 117 | { 118 | if (!_rewardedAd) { 119 | callback(@[[NSNumber numberWithBool:NO]]); 120 | return; 121 | } 122 | 123 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 124 | BOOL isReady = [_rewardedAd canPresentFromRootViewController:rootViewController error:nil]; 125 | 126 | callback(@[[NSNumber numberWithBool:isReady]]); 127 | } 128 | 129 | - (void)startObserving 130 | { 131 | hasListeners = YES; 132 | } 133 | 134 | - (void)stopObserving 135 | { 136 | hasListeners = NO; 137 | } 138 | 139 | #pragma mark GADFullScreenContentDelegate 140 | 141 | /// Tells the delegate that an impression has been recorded for the ad. 142 | - (void)adDidRecordImpression:(nonnull id)ad 143 | { 144 | if (hasListeners) { 145 | [self sendEventWithName:kEventAdImpression body:nil]; 146 | } 147 | } 148 | 149 | /// Tells the delegate that the ad failed to present full screen content. 150 | - (void)ad:(nonnull id)ad 151 | didFailToPresentFullScreenContentWithError:(nonnull NSError *)error 152 | { 153 | if (hasListeners) { 154 | [self sendEventWithName:kEventAdFailedToOpen body:nil]; 155 | } 156 | } 157 | 158 | /// Tells the delegate that the ad presented full screen content. 159 | - (void)adDidPresentFullScreenContent:(nonnull id)ad 160 | { 161 | if (hasListeners) { 162 | [self sendEventWithName:kEventAdOpened body:nil]; 163 | } 164 | } 165 | 166 | /// Tells the delegate that the ad dismissed full screen content. 167 | - (void)adDidDismissFullScreenContent:(nonnull id)ad 168 | { 169 | if (hasListeners) { 170 | [self sendEventWithName:kEventAdClosed body:nil]; 171 | } 172 | } 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /ios/RNAdMobInterstitial.m: -------------------------------------------------------------------------------- 1 | #import "RNAdMobInterstitial.h" 2 | #import "RNAdMobUtils.h" 3 | 4 | #if __has_include() 5 | #import 6 | #else 7 | #import "RCTUtils.h" 8 | #endif 9 | 10 | static NSString *const kEventAdLoaded = @"interstitialAdLoaded"; 11 | static NSString *const kEventAdFailedToLoad = @"interstitialAdFailedToLoad"; 12 | static NSString *const kEventAdOpened = @"interstitialAdOpened"; 13 | static NSString *const kEventAdFailedToOpen = @"interstitialAdFailedToOpen"; 14 | static NSString *const kEventAdClosed = @"interstitialAdClosed"; 15 | static NSString *const kEventAdImpression = @"interstitialAdImpression"; 16 | 17 | @implementation RNAdMobInterstitial 18 | { 19 | GADInterstitialAd *_interstitial; 20 | NSString *_adUnitID; 21 | NSArray *_testDevices; 22 | BOOL hasListeners; 23 | } 24 | 25 | - (dispatch_queue_t)methodQueue 26 | { 27 | return dispatch_get_main_queue(); 28 | } 29 | 30 | + (BOOL)requiresMainQueueSetup 31 | { 32 | return NO; 33 | } 34 | 35 | RCT_EXPORT_MODULE(); 36 | 37 | - (NSArray *)supportedEvents 38 | { 39 | return @[ 40 | kEventAdLoaded, 41 | kEventAdFailedToLoad, 42 | kEventAdOpened, 43 | kEventAdFailedToOpen, 44 | kEventAdClosed, 45 | kEventAdImpression ]; 46 | } 47 | 48 | #pragma mark exported methods 49 | 50 | RCT_EXPORT_METHOD(setAdUnitID:(NSString *)adUnitID) 51 | { 52 | _adUnitID = adUnitID; 53 | } 54 | 55 | RCT_EXPORT_METHOD(setTestDevices:(NSArray *)testDevices) 56 | { 57 | _testDevices = RNAdMobProcessTestDevices(testDevices, kGADSimulatorID); 58 | } 59 | 60 | RCT_EXPORT_METHOD(requestAd:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 61 | { 62 | if (_interstitial) { 63 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 64 | BOOL hasBeenUsed = [_interstitial canPresentFromRootViewController:rootViewController error:nil]; 65 | 66 | if (hasBeenUsed) { 67 | reject(@"E_AD_ALREADY_LOADED", @"Ad is already loaded.", nil); 68 | return; 69 | } 70 | } 71 | 72 | GADRequest *request = [GADRequest request]; 73 | [GADInterstitialAd loadWithAdUnitID:_adUnitID 74 | request:request 75 | completionHandler:^(GADInterstitialAd * _Nullable interstitialAd, NSError * _Nullable error) { 76 | if (error) { 77 | if (self->hasListeners) { 78 | NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError(@"E_AD_REQUEST_FAILED", error.localizedDescription, error); 79 | [self sendEventWithName:kEventAdFailedToLoad body:jsError]; 80 | } 81 | 82 | reject(@"E_AD_REQUEST_FAILED", error.localizedDescription, error); 83 | 84 | return; 85 | } 86 | 87 | self->_interstitial = interstitialAd; 88 | self->_interstitial.fullScreenContentDelegate = self; 89 | 90 | if (self->hasListeners) { 91 | [self sendEventWithName:kEventAdLoaded body:nil]; 92 | } 93 | 94 | resolve(nil); 95 | }]; 96 | } 97 | 98 | RCT_EXPORT_METHOD(showAd:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 99 | { 100 | if (!_interstitial) { 101 | reject(@"E_AD_NOT_READY", @"Ad is not ready.", nil); 102 | return; 103 | } 104 | 105 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 106 | BOOL isReady = [_interstitial canPresentFromRootViewController:rootViewController error:nil]; 107 | 108 | if (isReady) { 109 | [_interstitial presentFromRootViewController:rootViewController]; 110 | 111 | resolve(nil); 112 | } else { 113 | reject(@"E_AD_NOT_READY", @"Ad is not ready.", nil); 114 | } 115 | } 116 | 117 | RCT_EXPORT_METHOD(isReady:(RCTResponseSenderBlock)callback) 118 | { 119 | if (!_interstitial) { 120 | callback(@[[NSNumber numberWithBool:NO]]); 121 | return; 122 | } 123 | 124 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 125 | BOOL isReady = [_interstitial canPresentFromRootViewController:rootViewController error:nil]; 126 | 127 | callback(@[[NSNumber numberWithBool:isReady]]); 128 | } 129 | 130 | - (void)startObserving 131 | { 132 | hasListeners = YES; 133 | } 134 | 135 | - (void)stopObserving 136 | { 137 | hasListeners = NO; 138 | } 139 | 140 | #pragma mark GADFullScreenContentDelegate 141 | 142 | /// Tells the delegate that an impression has been recorded for the ad. 143 | - (void)adDidRecordImpression:(nonnull id)ad 144 | { 145 | if (hasListeners) { 146 | [self sendEventWithName:kEventAdImpression body:nil]; 147 | } 148 | } 149 | 150 | /// Tells the delegate that the ad failed to present full screen content. 151 | - (void)ad:(nonnull id)ad 152 | didFailToPresentFullScreenContentWithError:(nonnull NSError *)error 153 | { 154 | if (hasListeners) { 155 | [self sendEventWithName:kEventAdFailedToOpen body:nil]; 156 | } 157 | } 158 | 159 | /// Tells the delegate that the ad presented full screen content. 160 | - (void)adDidPresentFullScreenContent:(nonnull id)ad 161 | { 162 | if (hasListeners) { 163 | [self sendEventWithName:kEventAdOpened body:nil]; 164 | } 165 | } 166 | 167 | /// Tells the delegate that the ad dismissed full screen content. 168 | - (void)adDidDismissFullScreenContent:(nonnull id)ad 169 | { 170 | if (hasListeners) { 171 | [self sendEventWithName:kEventAdClosed body:nil]; 172 | } 173 | } 174 | 175 | @end 176 | -------------------------------------------------------------------------------- /ios/RNGAMBannerView.m: -------------------------------------------------------------------------------- 1 | #import "RNGAMBannerView.h" 2 | #import "RNAdMobUtils.h" 3 | 4 | #if __has_include() 5 | #import 6 | #import 7 | #import 8 | #else 9 | #import "RCTBridgeModule.h" 10 | #import "UIView+React.h" 11 | #import "RCTLog.h" 12 | #endif 13 | 14 | #include "RCTConvert+GADAdSize.h" 15 | 16 | @implementation RNGAMBannerView 17 | { 18 | GAMBannerView *_bannerView; 19 | } 20 | 21 | - (void)dealloc 22 | { 23 | _bannerView.delegate = nil; 24 | _bannerView.adSizeDelegate = nil; 25 | _bannerView.appEventDelegate = nil; 26 | } 27 | 28 | - (instancetype)initWithFrame:(CGRect)frame 29 | { 30 | if ((self = [super initWithFrame:frame])) { 31 | super.backgroundColor = [UIColor clearColor]; 32 | 33 | UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController; 34 | 35 | _bannerView = [[GAMBannerView alloc] initWithAdSize:kGADAdSizeBanner]; 36 | _bannerView.delegate = self; 37 | _bannerView.adSizeDelegate = self; 38 | _bannerView.appEventDelegate = self; 39 | _bannerView.rootViewController = rootViewController; 40 | [self addSubview:_bannerView]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | #pragma clang diagnostic push 47 | #pragma clang diagnostic ignored "-Wobjc-missing-super-calls" 48 | - (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex 49 | { 50 | RCTLogError(@"RNGADBannerView cannot have subviews"); 51 | } 52 | #pragma clang diagnostic pop 53 | 54 | - (void)loadBanner { 55 | GADRequest *request = [GADRequest request]; 56 | [_bannerView loadRequest:request]; 57 | } 58 | 59 | - (void)setAdSize:(NSString *)adSize 60 | { 61 | _adSize = adSize; 62 | 63 | UIView *view = _bannerView.rootViewController.view; 64 | CGRect frame = view.frame; 65 | 66 | if (@available(iOS 11.0, *)) { 67 | frame = UIEdgeInsetsInsetRect(view.frame, view.safeAreaInsets); 68 | } 69 | 70 | [_bannerView setAdSize:[RCTConvert GADAdSize:adSize withWidth:frame.size.width]]; 71 | } 72 | 73 | - (void)setValidAdSizes:(NSArray *)adSizes 74 | { 75 | UIView *view = _bannerView.rootViewController.view; 76 | CGRect frame = view.frame; 77 | 78 | if (@available(iOS 11.0, *)) { 79 | frame = UIEdgeInsetsInsetRect(view.frame, view.safeAreaInsets); 80 | } 81 | 82 | __block NSMutableArray *validAdSizes = [[NSMutableArray alloc] initWithCapacity:adSizes.count]; 83 | [adSizes enumerateObjectsUsingBlock:^(id jsonValue, NSUInteger idx, __unused BOOL *stop) { 84 | GADAdSize adSize = [RCTConvert GADAdSize:jsonValue withWidth:frame.size.width]; 85 | if (GADAdSizeEqualToSize(adSize, kGADAdSizeInvalid)) { 86 | RCTLogWarn(@"Invalid adSize %@", jsonValue); 87 | } else { 88 | [validAdSizes addObject:NSValueFromGADAdSize(adSize)]; 89 | } 90 | }]; 91 | _bannerView.validAdSizes = validAdSizes; 92 | } 93 | 94 | - (void)setTestDevices:(NSArray *)testDevices 95 | { 96 | _testDevices = RNAdMobProcessTestDevices(testDevices, kGADSimulatorID); 97 | 98 | [GADMobileAds sharedInstance].requestConfiguration.testDeviceIdentifiers = _testDevices; 99 | } 100 | 101 | -(void)layoutSubviews 102 | { 103 | [super layoutSubviews]; 104 | _bannerView.frame = self.bounds; 105 | } 106 | 107 | # pragma mark GADBannerViewDelegate 108 | 109 | /// Tells the delegate that an ad request successfully received an ad. The delegate may want to add 110 | /// the banner view to the view hierarchy if it hasn't been added yet. 111 | - (void)bannerViewDidReceiveAd:(nonnull GADBannerView *)bannerView 112 | { 113 | if (self.onSizeChange) { 114 | self.onSizeChange(@{ 115 | @"width": @(bannerView.frame.size.width), 116 | @"height": @(bannerView.frame.size.height) 117 | }); 118 | } 119 | 120 | if (self.onAdLoaded) { 121 | self.onAdLoaded(@{}); 122 | } 123 | } 124 | 125 | /// Tells the delegate that an ad request failed. The failure is normally due to network 126 | /// connectivity or ad availablility (i.e., no fill). 127 | - (void)bannerView:(nonnull GADBannerView *)bannerView 128 | didFailToReceiveAdWithError:(nonnull NSError *)error 129 | { 130 | if (self.onAdFailedToLoad) { 131 | self.onAdFailedToLoad(@{ @"error": @{ @"message": [error localizedDescription] } }); 132 | } 133 | } 134 | 135 | /// Tells the delegate that an impression has been recorded for an ad. 136 | - (void)bannerViewDidRecordImpression:(nonnull GADBannerView *)bannerView 137 | { 138 | if (self.onAdRecordImpression) { 139 | self.onAdRecordImpression(@{}); 140 | } 141 | } 142 | 143 | /// Tells the delegate that a full screen view will be presented in response to the user clicking on 144 | /// an ad. The delegate may want to pause animations and time sensitive interactions. 145 | - (void)bannerViewWillPresentScreen:(nonnull GADBannerView *)bannerView 146 | { 147 | if (self.onAdOpened) { 148 | self.onAdOpened(@{}); 149 | } 150 | } 151 | 152 | /// Tells the delegate that the full screen view will be dismissed. 153 | - (void)bannerViewWillDismissScreen:(nonnull GADBannerView *)bannerView 154 | { 155 | if (self.onAdClosed) { 156 | self.onAdClosed(@{}); 157 | } 158 | } 159 | 160 | # pragma mark GADAdSizeDelegate 161 | 162 | /// Called before the ad view changes to the new size. 163 | - (void)adView:(nonnull GADBannerView *)bannerView willChangeAdSizeTo:(GADAdSize)size 164 | { 165 | CGSize adSize = CGSizeFromGADAdSize(size); 166 | self.onSizeChange(@{ 167 | @"width": @(adSize.width), 168 | @"height": @(adSize.height) 169 | }); 170 | } 171 | 172 | # pragma mark GADAppEventDelegate 173 | 174 | /// Called when the banner receives an app event. 175 | - (void)adView:(nonnull GADBannerView *)banner didReceiveAppEvent:(nonnull NSString *)name withInfo:(nullable NSString *)info 176 | { 177 | if (self.onAppEvent) { 178 | self.onAppEvent(@{ @"name": name, @"info": info }); 179 | } 180 | } 181 | 182 | @end 183 | -------------------------------------------------------------------------------- /android/src/main/java/com/izo/rnadmob/RNAdMobInterstitialAdModule.java: -------------------------------------------------------------------------------- 1 | package com.izo.rnadmob; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | 10 | import com.facebook.react.bridge.Arguments; 11 | import com.facebook.react.bridge.Callback; 12 | import com.facebook.react.bridge.Promise; 13 | import com.facebook.react.bridge.ReactApplicationContext; 14 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 15 | import com.facebook.react.bridge.ReactMethod; 16 | import com.facebook.react.bridge.ReadableArray; 17 | import com.facebook.react.bridge.ReadableNativeArray; 18 | import com.facebook.react.bridge.WritableMap; 19 | import com.facebook.react.modules.core.DeviceEventManagerModule; 20 | import com.google.android.gms.ads.AdError; 21 | import com.google.android.gms.ads.AdRequest; 22 | import com.google.android.gms.ads.FullScreenContentCallback; 23 | import com.google.android.gms.ads.LoadAdError; 24 | import com.google.android.gms.ads.MobileAds; 25 | import com.google.android.gms.ads.RequestConfiguration; 26 | import com.google.android.gms.ads.interstitial.InterstitialAd; 27 | import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback; 28 | 29 | import org.jetbrains.annotations.NotNull; 30 | 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | 34 | public class RNAdMobInterstitialAdModule extends ReactContextBaseJavaModule { 35 | 36 | public static final String REACT_CLASS = "RNAdMobInterstitial"; 37 | 38 | public static final String EVENT_AD_LOADED = "interstitialAdLoaded"; 39 | public static final String EVENT_AD_FAILED_TO_LOAD = "interstitialAdFailedToLoad"; 40 | public static final String EVENT_AD_OPENED = "interstitialAdOpened"; 41 | public static final String EVENT_AD_FAILED_TO_OPEN = "rewardedVideoAdFailedToOpen"; 42 | public static final String EVENT_AD_CLOSED = "interstitialAdClosed"; 43 | public static final String EVENT_AD_IMPRESSION = "interstitialAdImpression"; 44 | 45 | InterstitialAd mInterstitialAd; 46 | String adUnitID; 47 | String[] testDevices; 48 | 49 | @Override 50 | public String getName() { 51 | return REACT_CLASS; 52 | } 53 | 54 | public RNAdMobInterstitialAdModule(ReactApplicationContext reactContext) { 55 | super(reactContext); 56 | } 57 | 58 | private void sendEvent(String eventName, @Nullable WritableMap params) { 59 | getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params); 60 | } 61 | 62 | @ReactMethod 63 | public void setAdUnitID(String adUnitID) { 64 | this.adUnitID = adUnitID; 65 | } 66 | 67 | @ReactMethod 68 | public void setTestDevices(ReadableArray testDevices) { 69 | ReadableNativeArray nativeArray = (ReadableNativeArray)testDevices; 70 | ArrayList list = nativeArray.toArrayList(); 71 | this.testDevices = list.toArray(new String[list.size()]); 72 | 73 | if (testDevices != null) { 74 | List testDeviceIds = new ArrayList<>(); 75 | 76 | for (int i = 0; i < this.testDevices.length; i++) { 77 | String testDevice = this.testDevices[i]; 78 | if (testDevice == "SIMULATOR") { 79 | testDeviceIds.add(AdRequest.DEVICE_ID_EMULATOR); 80 | } else { 81 | testDeviceIds.add(testDevice); 82 | } 83 | } 84 | 85 | RequestConfiguration configuration = new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build(); 86 | MobileAds.setRequestConfiguration(configuration); 87 | } 88 | } 89 | 90 | @ReactMethod 91 | public void requestAd(final Promise promise) { 92 | new Handler(Looper.getMainLooper()).post(new Runnable() { 93 | @Override 94 | public void run () { 95 | FullScreenContentCallback fullScreenContentCallback = new FullScreenContentCallback() { 96 | @Override 97 | public void onAdFailedToShowFullScreenContent(@NonNull @NotNull AdError adError) { 98 | super.onAdFailedToShowFullScreenContent(adError); 99 | 100 | sendEvent(EVENT_AD_FAILED_TO_OPEN, null); 101 | } 102 | 103 | @Override 104 | public void onAdShowedFullScreenContent() { 105 | super.onAdShowedFullScreenContent(); 106 | 107 | sendEvent(EVENT_AD_OPENED, null); 108 | } 109 | 110 | @Override 111 | public void onAdDismissedFullScreenContent() { 112 | super.onAdDismissedFullScreenContent(); 113 | 114 | sendEvent(EVENT_AD_CLOSED, null); 115 | } 116 | 117 | @Override 118 | public void onAdImpression() { 119 | super.onAdImpression(); 120 | 121 | sendEvent(EVENT_AD_IMPRESSION, null); 122 | } 123 | }; 124 | 125 | InterstitialAdLoadCallback interstitialAdLoadCallback = new InterstitialAdLoadCallback() { 126 | @Override 127 | public void onAdLoaded(@NonNull @NotNull InterstitialAd interstitialAd) { 128 | super.onAdLoaded(interstitialAd); 129 | 130 | mInterstitialAd = interstitialAd; 131 | mInterstitialAd.setFullScreenContentCallback(fullScreenContentCallback); 132 | 133 | sendEvent(EVENT_AD_LOADED, null); 134 | 135 | promise.resolve(null); 136 | } 137 | 138 | @Override 139 | public void onAdFailedToLoad(@NonNull @NotNull LoadAdError loadAdError) { 140 | super.onAdFailedToLoad(loadAdError); 141 | 142 | int errorCode = loadAdError.getCode(); 143 | 144 | String errorString = "ERROR_UNKNOWN"; 145 | String errorMessage = "Unknown error"; 146 | 147 | switch (errorCode) { 148 | case AdRequest.ERROR_CODE_INTERNAL_ERROR: 149 | errorString = "ERROR_CODE_INTERNAL_ERROR"; 150 | errorMessage = "Internal error, an invalid response was received from the ad server."; 151 | break; 152 | case AdRequest.ERROR_CODE_INVALID_REQUEST: 153 | errorString = "ERROR_CODE_INVALID_REQUEST"; 154 | errorMessage = "Invalid ad request, possibly an incorrect ad unit ID was given."; 155 | break; 156 | case AdRequest.ERROR_CODE_NETWORK_ERROR: 157 | errorString = "ERROR_CODE_NETWORK_ERROR"; 158 | errorMessage = "The ad request was unsuccessful due to network connectivity."; 159 | break; 160 | case AdRequest.ERROR_CODE_NO_FILL: 161 | errorString = "ERROR_CODE_NO_FILL"; 162 | errorMessage = "The ad request was successful, but no ad was returned due to lack of ad inventory."; 163 | break; 164 | } 165 | WritableMap event = Arguments.createMap(); 166 | event.putString("message", errorMessage); 167 | sendEvent(EVENT_AD_FAILED_TO_LOAD, event); 168 | 169 | promise.reject(errorString, errorMessage); 170 | } 171 | }; 172 | 173 | AdRequest.Builder adRequestBuilder = new AdRequest.Builder(); 174 | AdRequest adRequest = adRequestBuilder.build(); 175 | 176 | InterstitialAd.load(getCurrentActivity(), adUnitID, adRequest, interstitialAdLoadCallback); 177 | } 178 | }); 179 | } 180 | 181 | @ReactMethod 182 | public void showAd(final Promise promise) { 183 | new Handler(Looper.getMainLooper()).post(new Runnable() { 184 | @Override 185 | public void run () { 186 | if (mInterstitialAd != null) { 187 | mInterstitialAd.show(getCurrentActivity()); 188 | 189 | promise.resolve(null); 190 | } else { 191 | promise.reject("E_AD_NOT_READY", "Ad is not ready."); 192 | } 193 | } 194 | }); 195 | } 196 | 197 | @ReactMethod 198 | public void isReady(final Callback callback) { 199 | new Handler(Looper.getMainLooper()).post(new Runnable() { 200 | @Override 201 | public void run() { 202 | if (mInterstitialAd != null) { 203 | callback.invoke(true); 204 | } else { 205 | callback.invoke(false); 206 | } 207 | } 208 | }); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /android/src/main/java/com/izo/rnadmob/RNAdMobRewardedVideoAdModule.java: -------------------------------------------------------------------------------- 1 | package com.izo.rnadmob; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | import com.facebook.react.bridge.Arguments; 10 | import com.facebook.react.bridge.Callback; 11 | import com.facebook.react.bridge.Promise; 12 | import com.facebook.react.bridge.ReactApplicationContext; 13 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 14 | import com.facebook.react.bridge.ReactMethod; 15 | import com.facebook.react.bridge.ReadableArray; 16 | import com.facebook.react.bridge.ReadableNativeArray; 17 | import com.facebook.react.bridge.WritableMap; 18 | import com.facebook.react.modules.core.DeviceEventManagerModule; 19 | import com.google.android.gms.ads.AdError; 20 | import com.google.android.gms.ads.LoadAdError; 21 | import com.google.android.gms.ads.MobileAds; 22 | import com.google.android.gms.ads.OnUserEarnedRewardListener; 23 | import com.google.android.gms.ads.RequestConfiguration; 24 | import com.google.android.gms.ads.rewarded.RewardedAd; 25 | import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback; 26 | import com.google.android.gms.ads.FullScreenContentCallback; 27 | import com.google.android.gms.ads.rewarded.RewardItem; 28 | import com.google.android.gms.ads.AdRequest; 29 | 30 | import org.jetbrains.annotations.NotNull; 31 | 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | public class RNAdMobRewardedVideoAdModule extends ReactContextBaseJavaModule { 36 | 37 | public static final String REACT_CLASS = "RNAdMobRewarded"; 38 | 39 | public static final String EVENT_AD_LOADED = "rewardedVideoAdLoaded"; 40 | public static final String EVENT_AD_FAILED_TO_LOAD = "rewardedVideoAdFailedToLoad"; 41 | public static final String EVENT_AD_OPENED = "rewardedVideoAdOpened"; 42 | public static final String EVENT_AD_FAILED_TO_OPEN = "rewardedVideoAdFailedToOpen"; 43 | public static final String EVENT_AD_CLOSED = "rewardedVideoAdClosed"; 44 | public static final String EVENT_REWARDED = "rewardedVideoAdRewarded"; 45 | public static final String EVENT_AD_IMPRESSION = "rewardedVideoAdImpression"; 46 | 47 | RewardedAd mRewardedAd; 48 | String adUnitID; 49 | String[] testDevices; 50 | 51 | @Override 52 | public String getName() { 53 | return REACT_CLASS; 54 | } 55 | 56 | public RNAdMobRewardedVideoAdModule(ReactApplicationContext reactContext) { 57 | super(reactContext); 58 | } 59 | 60 | private void sendEvent(String eventName, @Nullable WritableMap params) { 61 | getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params); 62 | } 63 | 64 | @ReactMethod 65 | public void setAdUnitID(String adUnitID) { 66 | this.adUnitID = adUnitID; 67 | } 68 | 69 | @ReactMethod 70 | public void setTestDevices(ReadableArray testDevices) { 71 | ReadableNativeArray nativeArray = (ReadableNativeArray)testDevices; 72 | ArrayList list = nativeArray.toArrayList(); 73 | this.testDevices = list.toArray(new String[list.size()]); 74 | 75 | if (testDevices != null) { 76 | List testDeviceIds = new ArrayList<>(); 77 | 78 | for (int i = 0; i < this.testDevices.length; i++) { 79 | String testDevice = this.testDevices[i]; 80 | if (testDevice == "SIMULATOR") { 81 | testDeviceIds.add(AdRequest.DEVICE_ID_EMULATOR); 82 | } else { 83 | testDeviceIds.add(testDevice); 84 | } 85 | } 86 | 87 | RequestConfiguration configuration = new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build(); 88 | MobileAds.setRequestConfiguration(configuration); 89 | } 90 | } 91 | 92 | @ReactMethod 93 | public void requestAd(final Promise promise) { 94 | new Handler(Looper.getMainLooper()).post(new Runnable() { 95 | @Override 96 | public void run() { 97 | FullScreenContentCallback fullScreenContentCallback = new FullScreenContentCallback() { 98 | @Override 99 | public void onAdFailedToShowFullScreenContent(@NonNull @NotNull AdError adError) { 100 | super.onAdFailedToShowFullScreenContent(adError); 101 | 102 | sendEvent(EVENT_AD_FAILED_TO_OPEN, null); 103 | } 104 | 105 | @Override 106 | public void onAdShowedFullScreenContent() { 107 | super.onAdShowedFullScreenContent(); 108 | 109 | sendEvent(EVENT_AD_OPENED, null); 110 | } 111 | 112 | @Override 113 | public void onAdDismissedFullScreenContent() { 114 | super.onAdDismissedFullScreenContent(); 115 | 116 | sendEvent(EVENT_AD_CLOSED, null); 117 | } 118 | 119 | @Override 120 | public void onAdImpression() { 121 | super.onAdImpression(); 122 | 123 | sendEvent(EVENT_AD_IMPRESSION, null); 124 | } 125 | }; 126 | 127 | RewardedAdLoadCallback rewardedAdLoadCallback = new RewardedAdLoadCallback() { 128 | @Override 129 | public void onAdLoaded(@NonNull @NotNull RewardedAd rewardedAd) { 130 | super.onAdLoaded(rewardedAd); 131 | 132 | mRewardedAd = rewardedAd; 133 | mRewardedAd.setFullScreenContentCallback(fullScreenContentCallback); 134 | 135 | sendEvent(EVENT_AD_LOADED, null); 136 | 137 | promise.resolve(null); 138 | } 139 | 140 | @Override 141 | public void onAdFailedToLoad(@NonNull @NotNull LoadAdError loadAdError) { 142 | super.onAdFailedToLoad(loadAdError); 143 | 144 | int errorCode = loadAdError.getCode(); 145 | 146 | String errorString = "ERROR_UNKNOWN"; 147 | String errorMessage = "Unknown error"; 148 | 149 | switch (errorCode) { 150 | case AdRequest.ERROR_CODE_INTERNAL_ERROR: 151 | errorString = "ERROR_CODE_INTERNAL_ERROR"; 152 | errorMessage = "Internal error, an invalid response was received from the ad server."; 153 | break; 154 | case AdRequest.ERROR_CODE_INVALID_REQUEST: 155 | errorString = "ERROR_CODE_INVALID_REQUEST"; 156 | errorMessage = "Invalid ad request, possibly an incorrect ad unit ID was given."; 157 | break; 158 | case AdRequest.ERROR_CODE_NETWORK_ERROR: 159 | errorString = "ERROR_CODE_NETWORK_ERROR"; 160 | errorMessage = "The ad request was unsuccessful due to network connectivity."; 161 | break; 162 | case AdRequest.ERROR_CODE_NO_FILL: 163 | errorString = "ERROR_CODE_NO_FILL"; 164 | errorMessage = "The ad request was successful, but no ad was returned due to lack of ad inventory."; 165 | break; 166 | } 167 | 168 | WritableMap event = Arguments.createMap(); 169 | event.putString("message", errorMessage); 170 | sendEvent(EVENT_AD_FAILED_TO_LOAD, event); 171 | 172 | promise.reject(errorString, errorMessage); 173 | } 174 | }; 175 | 176 | AdRequest.Builder adRequestBuilder = new AdRequest.Builder(); 177 | AdRequest adRequest = adRequestBuilder.build(); 178 | 179 | RewardedAd.load(getCurrentActivity(), adUnitID, adRequest, rewardedAdLoadCallback); 180 | } 181 | }); 182 | } 183 | 184 | @ReactMethod 185 | public void showAd(final Promise promise) { 186 | new Handler(Looper.getMainLooper()).post(new Runnable() { 187 | @Override 188 | public void run() { 189 | if (mRewardedAd != null) { 190 | mRewardedAd.show(getCurrentActivity(), new OnUserEarnedRewardListener() { 191 | @Override 192 | public void onUserEarnedReward(@NonNull @NotNull RewardItem rewardItem) { 193 | WritableMap reward = Arguments.createMap(); 194 | 195 | reward.putInt("amount", rewardItem.getAmount()); 196 | reward.putString("type", rewardItem.getType()); 197 | 198 | sendEvent(EVENT_REWARDED, reward); 199 | } 200 | }); 201 | 202 | promise.resolve(null); 203 | } else { 204 | promise.reject("E_AD_NOT_READY", "Ad is not ready."); 205 | } 206 | } 207 | }); 208 | } 209 | 210 | @ReactMethod 211 | public void isReady(final Callback callback) { 212 | new Handler(Looper.getMainLooper()).post(new Runnable() { 213 | @Override 214 | public void run() { 215 | if (mRewardedAd != null) { 216 | callback.invoke(true); 217 | } else { 218 | callback.invoke(false); 219 | } 220 | } 221 | }); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-admob-next [![npm](https://img.shields.io/npm/v/react-native-admob-next.svg)](https://www.npmjs.com/package/react-native-admob-next) 2 | 3 | 4 | A react-native module for Google AdMob Banners, Interstitials, Rewarded Videos and also DFP Banners. 5 | 6 | The banner types are implemented as components while the interstitial and rewarded video have an imperative API. 7 | 8 | ## Installation 9 | 10 | You can use npm or Yarn to install the latest beta version: 11 | 12 | **npm:** 13 | 14 | npm i --save react-native-admob-next 15 | 16 | **Yarn:** 17 | 18 | yarn add react-native-admob-next 19 | 20 | **ios:** 21 | pod install --repo-update 22 | 23 | In order to use this library, you have to link it to your project first. There's excellent documentation on how to do this in the [React Native Docs](https://facebook.github.io/react-native/docs/linking-libraries-ios.html#content). 24 | 25 | Alternatively for iOS you can install the library with CocoaPods by adding a line to your `Podfile`; 26 | 27 | pod 'react-native-admob-next', path: '../node_modules/react-native-admob-next' 28 | 29 | ### iOS 30 | 31 | For iOS you will have to add the [Google Mobile Ads SDK](https://developers.google.com/admob/ios/quick-start#import_the_mobile_ads_sdk) to your Xcode project. 32 | 33 | 34 | 35 | ### Android 36 | 37 | On Android the AdMob library code is part of Play Services, which is automatically added when this library is linked. 38 | 39 | But you still have to manually update your `AndroidManifest.xml`, as described in the [Google Mobile Ads SDK documentation](https://developers.google.com/admob/android/quick-start#update_your_androidmanifestxml). 40 | 41 | 42 | ## Usage 43 | 44 | ```jsx 45 | import { 46 | AdMobBanner, 47 | AdMobInterstitial, 48 | PublisherBanner, 49 | AdMobRewarded, 50 | } from 'react-native-admob-next' 51 | 52 | // Display a banner 53 | console.error(error)} 58 | /> 59 | 60 | // Display a DFP Publisher banner 61 | console.error(error)} 66 | onAppEvent={event => console.log(event.name, event.info)} 67 | /> 68 | 69 | // Display an interstitial 70 | AdMobInterstitial.setAdUnitID('your-admob-unit-id'); 71 | AdMobInterstitial.setTestDevices([AdMobInterstitial.simulatorId]); 72 | AdMobInterstitial.requestAd().then(() => AdMobInterstitial.showAd()); 73 | 74 | // Display a rewarded ad 75 | AdMobRewarded.setAdUnitID('your-admob-unit-id'); 76 | AdMobRewarded.requestAd().then(() => AdMobRewarded.showAd()); 77 | ``` 78 | 79 | For a full example reference to the [example project](Example). 80 | 81 | ## Reference 82 | 83 | ### AdMobBanner 84 | 85 | #### Properties 86 | 87 | ##### `adSize` 88 | 89 | _Corresponding to [iOS framework banner size constants](https://developers.google.com/admob/ios/banner)_ 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 135 | 136 | 137 | 138 | 139 | 140 |
ValueDescriptionAvailabilitySize (WxH)
bannerStandard BannerPhones and Tablets320x50
largeBannerLarge BannerPhones and Tablets320x100
mediumRectangleIAB Medium RectanglePhones and Tablets300x250
fullBannerIAB Full-Size BannerTablets468x60
leaderboardIAB LeaderboardTablets728x90
133 | adaptiveBanner 134 | Adaptive BannerPhones and TabletsScreen width x Adaptive height
141 | 142 | ##### `onAdLoaded` 143 | 144 | Accepts a function. Called when an ad is received. 145 | 146 | ##### `onAdFailedToLoad` 147 | 148 | Accepts a function. Called when an ad request failed. 149 | 150 | ##### `onAdOpened` 151 | 152 | Accepts a function. Called when an ad opens an overlay that covers the screen. 153 | 154 | ##### `onAdClosed` 155 | 156 | Accepts a function. Called when the user is about to return to the application after clicking on an ad. 157 | 158 | ##### `onAdRecordImpression` 159 | 160 | Accepts a function. Called when an ad impression has been recorded. 161 | 162 | ##### `onSizeChange` 163 | 164 | Accepts a function. Called when the size of the banner changes. The function is called with an object containing the width and the height. 165 | 166 | _Above names correspond to the [Ad lifecycle event callbacks](https://developers.google.com/admob/android/banner#ad_events)_ 167 | 168 | ### PublisherBanner 169 | 170 | #### Properties 171 | 172 | Same as `AdMobBanner`, with the addition of 2 extra properties: 173 | 174 | ##### `onAppEvent` 175 | 176 | Accepts a function. Called when DFP sends an event back to the app. 177 | 178 | These events may occur at any time during the ad's lifecycle, even before `onAdLoaded` is called. The function is called with an object, containing the name of the event and an info property, containing additional information. 179 | 180 | More info here: https://developers.google.com/mobile-ads-sdk/docs/dfp/ios/banner#app_events 181 | 182 | ##### `validAdSizes` 183 | 184 | An array of ad sizes which may be eligible to be served. 185 | 186 | ### AdMobInterstitial 187 | 188 | In comparison to the `AdMobBanner` and `PublisherBanner` which have a declaritive API, the `AdMobInterstitial` has an imperative API. 189 | 190 | #### Methods 191 | 192 | ##### `setAdUnitID(adUnitID)` 193 | 194 | Sets the AdUnit ID for all future ad requests. 195 | 196 | ##### `setTestDevices(devices)` 197 | 198 | Sets the devices which are served test ads. 199 | 200 | _For simulators/emulators you can use `AdMobInterstitial.simulatorId` for the test device ID._ 201 | 202 | ##### `requestAd()` 203 | 204 | Requests an interstitial and returns a promise, which resolves on load and rejects on error. 205 | 206 | ##### `showAd()` 207 | 208 | Shows an interstitial and returns a promise, which resolves when an ad is going to be shown, rejects when the ad is not ready to be shown. 209 | 210 | ##### `isReady(callback)` 211 | 212 | Calls callback with a boolean value whether the interstitial is ready to be shown. 213 | 214 | #### Events 215 | 216 | Unfortunately, events are not consistent across iOS and Android. To have one unified API, new event names are introduced for pairs that are roughly equivalent. 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 |
This libraryiOSAndroid
adLoadedinterstitialDidReceiveAdonAdLoaded
adFailedToLoadinterstitial:didFailToReceiveAdWithErroronAdFailedToLoad
adOpenedinterstitialWillPresentScreenonAdOpened
adFailedToOpeninterstitialAdFailedToOpen
adFailedToOpeninterstitialDidFailToPresentScreenNot supported
adClosedinterstitialWillDismissScreenonAdClosed
adImpressioninterstitialAdImpression
264 | 265 | ### AdMobRewarded 266 | 267 | In comparison to the `AdMobBanner` and `PublisherBanner` which have a declaritive API, the `AdMobRewarded` has an imperative API, just like the `AdMobInterstitial`. 268 | 269 | #### Methods 270 | 271 | ##### `setAdUnitID(adUnitID)` 272 | 273 | Sets the AdUnit ID for all future ad requests. 274 | 275 | ##### `setTestDevices(devices)` 276 | 277 | Sets the devices which are served test ads. 278 | 279 | _For simulators/emulators you can use `AdMobRewarded.simulatorId` for the test device ID._ 280 | 281 | ##### `requestAd()` 282 | 283 | Requests a rewarded ad and returns a promise, which resolves on load and rejects on error. 284 | 285 | ##### `showAd()` 286 | 287 | Shows a rewarded ad and returns a promise, which resolves when an ad is going to be shown, rejects when the ad is not ready to be shown. 288 | 289 | ##### `isReady(callback)` 290 | 291 | Calls callback with a boolean value whether the rewarded ad is ready to be shown. 292 | 293 | #### Events 294 | 295 | Unfortunately, events are not consistent across iOS and Android. To have one unified API, new event names are introduced for pairs that are roughly equivalent. 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 |
This libraryiOSAndroid
adLoadedrewardBasedVideoAdDidReceiveAdonRewardedVideoAdLoaded
adFailedToLoadrewardBasedVideoAd:didFailToLoadWithErroronRewardedVideoAdFailedToLoad
rewardedrewardBasedVideoAd:didRewardUserWithRewardonRewarded
adOpenedrewardBasedVideoAdDidOpenonRewardedVideoAdOpened
adFailedToOpenrewardedVideoAdFailedToOpen
adClosedrewardBasedVideoAdDidCloseonRewardedVideoAdClosed
adImpressionrewardedVideoAdImpression
343 | 344 | --- 345 | 346 | ## TODO 347 | 348 | - [ ] Support [Ad Targeting](https://developers.google.com/admob/ios/targeting) 349 | -------------------------------------------------------------------------------- /android/src/main/java/com/izo/rnadmob/RNAdMobBannerViewManager.java: -------------------------------------------------------------------------------- 1 | package com.izo.rnadmob; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.view.Display; 6 | import android.view.View; 7 | import android.view.WindowManager; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | import com.facebook.react.bridge.Arguments; 13 | import com.facebook.react.bridge.ReactContext; 14 | import com.facebook.react.bridge.WritableMap; 15 | import com.facebook.react.bridge.ReadableArray; 16 | import com.facebook.react.bridge.ReadableNativeArray; 17 | import com.facebook.react.common.MapBuilder; 18 | import com.facebook.react.uimanager.ViewGroupManager; 19 | import com.facebook.react.uimanager.annotations.ReactProp; 20 | import com.facebook.react.uimanager.ThemedReactContext; 21 | import com.facebook.react.uimanager.events.RCTEventEmitter; 22 | import com.facebook.react.views.view.ReactViewGroup; 23 | import com.google.android.gms.ads.AdListener; 24 | import com.google.android.gms.ads.AdRequest; 25 | import com.google.android.gms.ads.AdSize; 26 | import com.google.android.gms.ads.AdView; 27 | import com.google.android.gms.ads.LoadAdError; 28 | import com.google.android.gms.ads.MobileAds; 29 | import com.google.android.gms.ads.RequestConfiguration; 30 | 31 | import org.jetbrains.annotations.NotNull; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | import java.util.Map; 36 | 37 | class ReactAdView extends ReactViewGroup { 38 | 39 | protected AdView adView; 40 | 41 | String adUnitID; 42 | String[] testDevices; 43 | AdSize adSize; 44 | 45 | public ReactAdView(final Context context) { 46 | super(context); 47 | this.createAdView(); 48 | } 49 | 50 | private void createAdView() { 51 | if (this.adView != null) this.adView.destroy(); 52 | 53 | final Context context = getContext(); 54 | this.adView = new AdView(context); 55 | this.adView.setAdListener(new AdListener() { 56 | @Override 57 | public void onAdClosed() { 58 | super.onAdClosed(); 59 | 60 | sendEvent(RNAdMobBannerViewManager.EVENT_AD_CLOSED, null); 61 | } 62 | 63 | @Override 64 | public void onAdFailedToLoad(@NonNull @NotNull LoadAdError loadAdError) { 65 | super.onAdFailedToLoad(loadAdError); 66 | 67 | int errorCode = loadAdError.getCode(); 68 | 69 | String errorMessage = "Unknown error"; 70 | switch (errorCode) { 71 | case AdRequest.ERROR_CODE_INTERNAL_ERROR: 72 | errorMessage = "Internal error, an invalid response was received from the ad server."; 73 | break; 74 | case AdRequest.ERROR_CODE_INVALID_REQUEST: 75 | errorMessage = "Invalid ad request, possibly an incorrect ad unit ID was given."; 76 | break; 77 | case AdRequest.ERROR_CODE_NETWORK_ERROR: 78 | errorMessage = "The ad request was unsuccessful due to network connectivity."; 79 | break; 80 | case AdRequest.ERROR_CODE_NO_FILL: 81 | errorMessage = "The ad request was successful, but no ad was returned due to lack of ad inventory."; 82 | break; 83 | } 84 | WritableMap event = Arguments.createMap(); 85 | WritableMap error = Arguments.createMap(); 86 | error.putString("message", errorMessage); 87 | event.putMap("error", error); 88 | sendEvent(RNAdMobBannerViewManager.EVENT_AD_FAILED_TO_LOAD, event); 89 | } 90 | 91 | @Override 92 | public void onAdOpened() { 93 | super.onAdOpened(); 94 | 95 | sendEvent(RNAdMobBannerViewManager.EVENT_AD_OPENED, null); 96 | } 97 | 98 | @Override 99 | public void onAdLoaded() { 100 | super.onAdLoaded(); 101 | 102 | int width = adView.getAdSize().getWidthInPixels(context); 103 | int height = adView.getAdSize().getHeightInPixels(context); 104 | int left = adView.getLeft(); 105 | int top = adView.getTop(); 106 | adView.measure(width, height); 107 | adView.layout(left, top, left + width, top + height); 108 | sendOnSizeChangeEvent(); 109 | sendEvent(RNAdMobBannerViewManager.EVENT_AD_LOADED, null); 110 | } 111 | 112 | @Override 113 | public void onAdClicked() { 114 | super.onAdClicked(); 115 | } 116 | 117 | @Override 118 | public void onAdImpression() { 119 | super.onAdImpression(); 120 | 121 | sendEvent(RNAdMobBannerViewManager.EVENT_AD_RECORD_IMPRESSION, null); 122 | } 123 | }); 124 | this.addView(this.adView); 125 | } 126 | 127 | private void sendOnSizeChangeEvent() { 128 | int width; 129 | int height; 130 | WritableMap event = Arguments.createMap(); 131 | AdSize adSize = this.adView.getAdSize(); 132 | 133 | width = adSize.getWidth(); 134 | height = adSize.getHeight(); 135 | 136 | event.putDouble("width", width); 137 | event.putDouble("height", height); 138 | sendEvent(RNAdMobBannerViewManager.EVENT_SIZE_CHANGE, event); 139 | } 140 | 141 | private void sendEvent(String name, @Nullable WritableMap event) { 142 | ReactContext reactContext = (ReactContext) getContext(); 143 | reactContext.getJSModule(RCTEventEmitter.class).receiveEvent( 144 | getId(), 145 | name, 146 | event); 147 | } 148 | 149 | public void loadBanner() { 150 | AdRequest.Builder adRequestBuilder = new AdRequest.Builder(); 151 | AdRequest adRequest = adRequestBuilder.build(); 152 | this.adView.loadAd(adRequest); 153 | } 154 | 155 | public void setAdUnitID(String adUnitID) { 156 | if (this.adUnitID != null) { 157 | // We can only set adUnitID once, so when it was previously set we have 158 | // to recreate the view 159 | this.createAdView(); 160 | } 161 | this.adUnitID = adUnitID; 162 | this.adView.setAdUnitId(adUnitID); 163 | } 164 | 165 | public void setTestDevices(String[] testDevices) { 166 | this.testDevices = testDevices; 167 | 168 | if (testDevices != null) { 169 | List testDeviceIds = new ArrayList<>(); 170 | 171 | for (int i = 0; i < testDevices.length; i++) { 172 | String testDevice = testDevices[i]; 173 | if (testDevice == "SIMULATOR") { 174 | testDeviceIds.add(AdRequest.DEVICE_ID_EMULATOR); 175 | } else { 176 | testDeviceIds.add(testDevice); 177 | } 178 | } 179 | 180 | RequestConfiguration configuration = new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build(); 181 | MobileAds.setRequestConfiguration(configuration); 182 | } 183 | } 184 | 185 | public void setAdSize(AdSize adSize) { 186 | this.adSize = adSize; 187 | this.adView.setAdSize(adSize); 188 | } 189 | } 190 | 191 | public class RNAdMobBannerViewManager extends ViewGroupManager { 192 | 193 | public static final String REACT_CLASS = "RNGADBannerView"; 194 | 195 | public static final String PROP_AD_SIZE = "adSize"; 196 | public static final String PROP_AD_UNIT_ID = "adUnitID"; 197 | public static final String PROP_TEST_DEVICES = "testDevices"; 198 | 199 | public static final String EVENT_AD_LOADED = "onAdLoaded"; 200 | public static final String EVENT_AD_FAILED_TO_LOAD = "onAdFailedToLoad"; 201 | public static final String EVENT_AD_RECORD_IMPRESSION = "onAdRecordImpression"; 202 | public static final String EVENT_AD_OPENED = "onAdOpened"; 203 | public static final String EVENT_AD_CLOSED = "onAdClosed"; 204 | public static final String EVENT_SIZE_CHANGE = "onSizeChange"; 205 | 206 | public static final int COMMAND_LOAD_BANNER = 1; 207 | 208 | @Override 209 | public String getName() { 210 | return REACT_CLASS; 211 | } 212 | 213 | @Override 214 | protected ReactAdView createViewInstance(ThemedReactContext themedReactContext) { 215 | ReactAdView adView = new ReactAdView(themedReactContext); 216 | return adView; 217 | } 218 | 219 | @Override 220 | public void addView(ReactAdView parent, View child, int index) { 221 | throw new RuntimeException("RNAdMobBannerView cannot have subviews"); 222 | } 223 | 224 | @Override 225 | @Nullable 226 | public Map getExportedCustomDirectEventTypeConstants() { 227 | MapBuilder.Builder builder = MapBuilder.builder(); 228 | String[] events = { 229 | EVENT_AD_LOADED, 230 | EVENT_AD_FAILED_TO_LOAD, 231 | EVENT_AD_RECORD_IMPRESSION, 232 | EVENT_AD_OPENED, 233 | EVENT_AD_CLOSED, 234 | EVENT_SIZE_CHANGE 235 | }; 236 | for (int i = 0; i < events.length; i++) { 237 | builder.put(events[i], MapBuilder.of("registrationName", events[i])); 238 | } 239 | return builder.build(); 240 | } 241 | 242 | @ReactProp(name = PROP_AD_SIZE) 243 | public void setPropAdSize(final ReactAdView view, final String sizeString) { 244 | Context context = view.getContext(); 245 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 246 | Display display = windowManager.getDefaultDisplay(); 247 | DisplayMetrics outMetrics = new DisplayMetrics(); 248 | display.getMetrics(outMetrics); 249 | 250 | float widthPixels = outMetrics.widthPixels; 251 | float density = outMetrics.density; 252 | 253 | int adWidth = (int) (widthPixels / density); 254 | 255 | AdSize adSize = getAdSizeFromString(context, sizeString, adWidth); 256 | view.setAdSize(adSize); 257 | } 258 | 259 | @ReactProp(name = PROP_AD_UNIT_ID) 260 | public void setPropAdUnitID(final ReactAdView view, final String adUnitID) { 261 | view.setAdUnitID(adUnitID); 262 | } 263 | 264 | @ReactProp(name = PROP_TEST_DEVICES) 265 | public void setPropTestDevices(final ReactAdView view, final ReadableArray testDevices) { 266 | ReadableNativeArray nativeArray = (ReadableNativeArray)testDevices; 267 | ArrayList list = nativeArray.toArrayList(); 268 | view.setTestDevices(list.toArray(new String[list.size()])); 269 | } 270 | 271 | private AdSize getAdSizeFromString(Context context, String adSize, int width) { 272 | switch (adSize) { 273 | case "largeBanner": 274 | return AdSize.LARGE_BANNER; 275 | case "mediumRectangle": 276 | return AdSize.MEDIUM_RECTANGLE; 277 | case "fullBanner": 278 | return AdSize.FULL_BANNER; 279 | case "leaderBoard": 280 | return AdSize.LEADERBOARD; 281 | case "adaptiveBanner": 282 | return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, width); 283 | default: 284 | return AdSize.BANNER; 285 | } 286 | } 287 | 288 | @Nullable 289 | @Override 290 | public Map getCommandsMap() { 291 | return MapBuilder.of("loadBanner", COMMAND_LOAD_BANNER); 292 | } 293 | 294 | @Override 295 | public void receiveCommand(ReactAdView root, int commandId, @javax.annotation.Nullable ReadableArray args) { 296 | switch (commandId) { 297 | case COMMAND_LOAD_BANNER: 298 | root.loadBanner(); 299 | break; 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /ios/RNAdMobManager.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0CB8C04B1D913E00002BC3EF /* RNGAMBannerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CB8C04A1D913E00002BC3EF /* RNGAMBannerView.m */; }; 11 | 0CB8C04E1D9143A6002BC3EF /* RNGAMBannerViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CB8C04D1D9143A6002BC3EF /* RNGAMBannerViewManager.m */; }; 12 | 5E2419841FE11E0F00C6B738 /* RNAdMobUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E2419831FE11E0F00C6B738 /* RNAdMobUtils.m */; }; 13 | 5E86A6471F126FCE008013EB /* RCTConvert+GADAdSize.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E86A6461F126FCE008013EB /* RCTConvert+GADAdSize.m */; }; 14 | A90F2F8C1D50AEF200F2A2E3 /* RNAdMobRewarded.m in Sources */ = {isa = PBXBuildFile; fileRef = A90F2F8B1D50AEF200F2A2E3 /* RNAdMobRewarded.m */; }; 15 | A962C2531CB27DBD00E508A1 /* RNAdMobInterstitial.m in Sources */ = {isa = PBXBuildFile; fileRef = A962C2521CB27DBD00E508A1 /* RNAdMobInterstitial.m */; }; 16 | A96DA7841C146DA600FC639B /* RNGADBannerView.m in Sources */ = {isa = PBXBuildFile; fileRef = A96DA7811C146DA600FC639B /* RNGADBannerView.m */; }; 17 | A96DA7851C146DA600FC639B /* RNGADBannerViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A96DA7831C146DA600FC639B /* RNGADBannerViewManager.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXCopyFilesBuildPhase section */ 21 | A96DA7721C146D7200FC639B /* CopyFiles */ = { 22 | isa = PBXCopyFilesBuildPhase; 23 | buildActionMask = 2147483647; 24 | dstPath = "include/$(PRODUCT_NAME)"; 25 | dstSubfolderSpec = 16; 26 | files = ( 27 | ); 28 | runOnlyForDeploymentPostprocessing = 0; 29 | }; 30 | /* End PBXCopyFilesBuildPhase section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 0CB8C0491D913E00002BC3EF /* RNGAMBannerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGAMBannerView.h; sourceTree = SOURCE_ROOT; }; 34 | 0CB8C04A1D913E00002BC3EF /* RNGAMBannerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGAMBannerView.m; sourceTree = SOURCE_ROOT; }; 35 | 0CB8C04C1D9143A6002BC3EF /* RNGAMBannerViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGAMBannerViewManager.h; sourceTree = SOURCE_ROOT; }; 36 | 0CB8C04D1D9143A6002BC3EF /* RNGAMBannerViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGAMBannerViewManager.m; sourceTree = SOURCE_ROOT; }; 37 | 5E2419831FE11E0F00C6B738 /* RNAdMobUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNAdMobUtils.m; sourceTree = SOURCE_ROOT; }; 38 | 5E2419851FE11F1200C6B738 /* RNAdMobUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNAdMobUtils.h; sourceTree = SOURCE_ROOT; }; 39 | 5E86A6451F126FCE008013EB /* RCTConvert+GADAdSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTConvert+GADAdSize.h"; sourceTree = SOURCE_ROOT; }; 40 | 5E86A6461F126FCE008013EB /* RCTConvert+GADAdSize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+GADAdSize.m"; sourceTree = SOURCE_ROOT; }; 41 | A90F2F8A1D50AEF200F2A2E3 /* RNAdMobRewarded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNAdMobRewarded.h; sourceTree = SOURCE_ROOT; }; 42 | A90F2F8B1D50AEF200F2A2E3 /* RNAdMobRewarded.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNAdMobRewarded.m; sourceTree = SOURCE_ROOT; }; 43 | A962C2511CB27DBD00E508A1 /* RNAdMobInterstitial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNAdMobInterstitial.h; sourceTree = SOURCE_ROOT; }; 44 | A962C2521CB27DBD00E508A1 /* RNAdMobInterstitial.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = RNAdMobInterstitial.m; sourceTree = SOURCE_ROOT; }; 45 | A96DA7741C146D7200FC639B /* libRNAdMobManager.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNAdMobManager.a; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | A96DA7801C146DA600FC639B /* RNGADBannerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGADBannerView.h; sourceTree = SOURCE_ROOT; }; 47 | A96DA7811C146DA600FC639B /* RNGADBannerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGADBannerView.m; sourceTree = SOURCE_ROOT; }; 48 | A96DA7821C146DA600FC639B /* RNGADBannerViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGADBannerViewManager.h; sourceTree = SOURCE_ROOT; }; 49 | A96DA7831C146DA600FC639B /* RNGADBannerViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGADBannerViewManager.m; sourceTree = SOURCE_ROOT; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | A96DA7711C146D7200FC639B /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | A96DA76B1C146D7200FC639B = { 64 | isa = PBXGroup; 65 | children = ( 66 | A96DA7761C146D7200FC639B /* RNAdMobManager */, 67 | A96DA7751C146D7200FC639B /* Products */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | A96DA7751C146D7200FC639B /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | A96DA7741C146D7200FC639B /* libRNAdMobManager.a */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | A96DA7761C146D7200FC639B /* RNAdMobManager */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 0CB8C04C1D9143A6002BC3EF /* RNGAMBannerViewManager.h */, 83 | 0CB8C04D1D9143A6002BC3EF /* RNGAMBannerViewManager.m */, 84 | A96DA7801C146DA600FC639B /* RNGADBannerView.h */, 85 | A96DA7811C146DA600FC639B /* RNGADBannerView.m */, 86 | A96DA7821C146DA600FC639B /* RNGADBannerViewManager.h */, 87 | A96DA7831C146DA600FC639B /* RNGADBannerViewManager.m */, 88 | A962C2511CB27DBD00E508A1 /* RNAdMobInterstitial.h */, 89 | A962C2521CB27DBD00E508A1 /* RNAdMobInterstitial.m */, 90 | 0CB8C0491D913E00002BC3EF /* RNGAMBannerView.h */, 91 | 0CB8C04A1D913E00002BC3EF /* RNGAMBannerView.m */, 92 | 5E2419831FE11E0F00C6B738 /* RNAdMobUtils.m */, 93 | 5E2419851FE11F1200C6B738 /* RNAdMobUtils.h */, 94 | A90F2F8A1D50AEF200F2A2E3 /* RNAdMobRewarded.h */, 95 | A90F2F8B1D50AEF200F2A2E3 /* RNAdMobRewarded.m */, 96 | 5E86A6451F126FCE008013EB /* RCTConvert+GADAdSize.h */, 97 | 5E86A6461F126FCE008013EB /* RCTConvert+GADAdSize.m */, 98 | ); 99 | path = RNAdMobManager; 100 | sourceTree = ""; 101 | }; 102 | /* End PBXGroup section */ 103 | 104 | /* Begin PBXNativeTarget section */ 105 | A96DA7731C146D7200FC639B /* RNAdMobManager */ = { 106 | isa = PBXNativeTarget; 107 | buildConfigurationList = A96DA77D1C146D7200FC639B /* Build configuration list for PBXNativeTarget "RNAdMobManager" */; 108 | buildPhases = ( 109 | A96DA7701C146D7200FC639B /* Sources */, 110 | A96DA7711C146D7200FC639B /* Frameworks */, 111 | A96DA7721C146D7200FC639B /* CopyFiles */, 112 | ); 113 | buildRules = ( 114 | ); 115 | dependencies = ( 116 | ); 117 | name = RNAdMobManager; 118 | productName = RNAdMobManager; 119 | productReference = A96DA7741C146D7200FC639B /* libRNAdMobManager.a */; 120 | productType = "com.apple.product-type.library.static"; 121 | }; 122 | /* End PBXNativeTarget section */ 123 | 124 | /* Begin PBXProject section */ 125 | A96DA76C1C146D7200FC639B /* Project object */ = { 126 | isa = PBXProject; 127 | attributes = { 128 | LastUpgradeCheck = 0710; 129 | ORGANIZATIONNAME = accosine; 130 | TargetAttributes = { 131 | A96DA7731C146D7200FC639B = { 132 | CreatedOnToolsVersion = 7.1; 133 | DevelopmentTeam = BMF2ZL32LL; 134 | }; 135 | }; 136 | }; 137 | buildConfigurationList = A96DA76F1C146D7200FC639B /* Build configuration list for PBXProject "RNAdMobManager" */; 138 | compatibilityVersion = "Xcode 3.2"; 139 | developmentRegion = English; 140 | hasScannedForEncodings = 0; 141 | knownRegions = ( 142 | English, 143 | en, 144 | ); 145 | mainGroup = A96DA76B1C146D7200FC639B; 146 | productRefGroup = A96DA7751C146D7200FC639B /* Products */; 147 | projectDirPath = ""; 148 | projectRoot = ""; 149 | targets = ( 150 | A96DA7731C146D7200FC639B /* RNAdMobManager */, 151 | ); 152 | }; 153 | /* End PBXProject section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | A96DA7701C146D7200FC639B /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | A962C2531CB27DBD00E508A1 /* RNAdMobInterstitial.m in Sources */, 161 | 0CB8C04B1D913E00002BC3EF /* RNGAMBannerView.m in Sources */, 162 | A90F2F8C1D50AEF200F2A2E3 /* RNAdMobRewarded.m in Sources */, 163 | A96DA7841C146DA600FC639B /* RNGADBannerView.m in Sources */, 164 | A96DA7851C146DA600FC639B /* RNGADBannerViewManager.m in Sources */, 165 | 5E2419841FE11E0F00C6B738 /* RNAdMobUtils.m in Sources */, 166 | 5E86A6471F126FCE008013EB /* RCTConvert+GADAdSize.m in Sources */, 167 | 0CB8C04E1D9143A6002BC3EF /* RNGAMBannerViewManager.m in Sources */, 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | }; 171 | /* End PBXSourcesBuildPhase section */ 172 | 173 | /* Begin XCBuildConfiguration section */ 174 | A96DA77B1C146D7200FC639B /* Debug */ = { 175 | isa = XCBuildConfiguration; 176 | buildSettings = { 177 | ALWAYS_SEARCH_USER_PATHS = NO; 178 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 179 | CLANG_CXX_LIBRARY = "libc++"; 180 | CLANG_ENABLE_MODULES = YES; 181 | CLANG_ENABLE_OBJC_ARC = YES; 182 | CLANG_WARN_BOOL_CONVERSION = YES; 183 | CLANG_WARN_CONSTANT_CONVERSION = YES; 184 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 185 | CLANG_WARN_EMPTY_BODY = YES; 186 | CLANG_WARN_ENUM_CONVERSION = YES; 187 | CLANG_WARN_INT_CONVERSION = YES; 188 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 189 | CLANG_WARN_UNREACHABLE_CODE = YES; 190 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 191 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 192 | COPY_PHASE_STRIP = NO; 193 | DEBUG_INFORMATION_FORMAT = dwarf; 194 | ENABLE_STRICT_OBJC_MSGSEND = YES; 195 | ENABLE_TESTABILITY = YES; 196 | GCC_C_LANGUAGE_STANDARD = gnu99; 197 | GCC_DYNAMIC_NO_PIC = NO; 198 | GCC_NO_COMMON_BLOCKS = YES; 199 | GCC_OPTIMIZATION_LEVEL = 0; 200 | GCC_PREPROCESSOR_DEFINITIONS = ( 201 | "DEBUG=1", 202 | "$(inherited)", 203 | ); 204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 205 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 206 | GCC_WARN_UNDECLARED_SELECTOR = YES; 207 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 208 | GCC_WARN_UNUSED_FUNCTION = YES; 209 | GCC_WARN_UNUSED_VARIABLE = YES; 210 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 211 | MTL_ENABLE_DEBUG_INFO = YES; 212 | ONLY_ACTIVE_ARCH = YES; 213 | SDKROOT = iphoneos; 214 | }; 215 | name = Debug; 216 | }; 217 | A96DA77C1C146D7200FC639B /* Release */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | ALWAYS_SEARCH_USER_PATHS = NO; 221 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 222 | CLANG_CXX_LIBRARY = "libc++"; 223 | CLANG_ENABLE_MODULES = YES; 224 | CLANG_ENABLE_OBJC_ARC = YES; 225 | CLANG_WARN_BOOL_CONVERSION = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INT_CONVERSION = YES; 231 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 232 | CLANG_WARN_UNREACHABLE_CODE = YES; 233 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 234 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 235 | COPY_PHASE_STRIP = NO; 236 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 237 | ENABLE_NS_ASSERTIONS = NO; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | GCC_C_LANGUAGE_STANDARD = gnu99; 240 | GCC_NO_COMMON_BLOCKS = YES; 241 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 242 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 243 | GCC_WARN_UNDECLARED_SELECTOR = YES; 244 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 245 | GCC_WARN_UNUSED_FUNCTION = YES; 246 | GCC_WARN_UNUSED_VARIABLE = YES; 247 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 248 | MTL_ENABLE_DEBUG_INFO = NO; 249 | SDKROOT = iphoneos; 250 | VALIDATE_PRODUCT = YES; 251 | }; 252 | name = Release; 253 | }; 254 | A96DA77E1C146D7200FC639B /* Debug */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../../../ios/Pods/**"; 258 | HEADER_SEARCH_PATHS = ( 259 | "$(inherited)", 260 | "$(SRCROOT)/../../../node_modules/react-native/React/**", 261 | ); 262 | OTHER_LDFLAGS = "-ObjC"; 263 | PRODUCT_NAME = "$(TARGET_NAME)"; 264 | SKIP_INSTALL = YES; 265 | }; 266 | name = Debug; 267 | }; 268 | A96DA77F1C146D7200FC639B /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../../../ios/Pods/**"; 272 | HEADER_SEARCH_PATHS = ( 273 | "$(inherited)", 274 | "$(SRCROOT)/../../../node_modules/react-native/React/**", 275 | ); 276 | OTHER_LDFLAGS = "-ObjC"; 277 | PRODUCT_NAME = "$(TARGET_NAME)"; 278 | SKIP_INSTALL = YES; 279 | }; 280 | name = Release; 281 | }; 282 | /* End XCBuildConfiguration section */ 283 | 284 | /* Begin XCConfigurationList section */ 285 | A96DA76F1C146D7200FC639B /* Build configuration list for PBXProject "RNAdMobManager" */ = { 286 | isa = XCConfigurationList; 287 | buildConfigurations = ( 288 | A96DA77B1C146D7200FC639B /* Debug */, 289 | A96DA77C1C146D7200FC639B /* Release */, 290 | ); 291 | defaultConfigurationIsVisible = 0; 292 | defaultConfigurationName = Release; 293 | }; 294 | A96DA77D1C146D7200FC639B /* Build configuration list for PBXNativeTarget "RNAdMobManager" */ = { 295 | isa = XCConfigurationList; 296 | buildConfigurations = ( 297 | A96DA77E1C146D7200FC639B /* Debug */, 298 | A96DA77F1C146D7200FC639B /* Release */, 299 | ); 300 | defaultConfigurationIsVisible = 0; 301 | defaultConfigurationName = Release; 302 | }; 303 | /* End XCConfigurationList section */ 304 | }; 305 | rootObject = A96DA76C1C146D7200FC639B /* Project object */; 306 | } 307 | -------------------------------------------------------------------------------- /android/src/main/java/com/izo/rnadmob/RNPublisherBannerViewManager.java: -------------------------------------------------------------------------------- 1 | package com.izo.rnadmob; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.view.Display; 6 | import android.view.View; 7 | import android.view.WindowManager; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | import com.facebook.react.bridge.Arguments; 13 | import com.facebook.react.bridge.ReactContext; 14 | import com.facebook.react.bridge.WritableMap; 15 | import com.facebook.react.bridge.ReadableArray; 16 | import com.facebook.react.bridge.ReadableNativeArray; 17 | import com.facebook.react.common.MapBuilder; 18 | import com.facebook.react.uimanager.ViewGroupManager; 19 | import com.facebook.react.uimanager.annotations.ReactProp; 20 | import com.facebook.react.uimanager.ThemedReactContext; 21 | import com.facebook.react.uimanager.events.RCTEventEmitter; 22 | import com.facebook.react.views.view.ReactViewGroup; 23 | import com.google.android.gms.ads.AdListener; 24 | import com.google.android.gms.ads.LoadAdError; 25 | import com.google.android.gms.ads.MobileAds; 26 | import com.google.android.gms.ads.RequestConfiguration; 27 | import com.google.android.gms.ads.admanager.AdManagerAdView; 28 | import com.google.android.gms.ads.admanager.AppEventListener; 29 | import com.google.android.gms.ads.admanager.AdManagerAdRequest; 30 | import com.google.android.gms.ads.AdSize; 31 | 32 | import org.jetbrains.annotations.NotNull; 33 | 34 | import java.util.ArrayList; 35 | import java.util.List; 36 | import java.util.Map; 37 | 38 | class ReactPublisherAdView extends ReactViewGroup implements AppEventListener { 39 | 40 | protected AdManagerAdView adView; 41 | 42 | String[] testDevices; 43 | AdSize[] validAdSizes; 44 | String adUnitID; 45 | AdSize adSize; 46 | 47 | public ReactPublisherAdView(final Context context) { 48 | super(context); 49 | this.createAdView(); 50 | } 51 | 52 | private void createAdView() { 53 | if (this.adView != null) this.adView.destroy(); 54 | 55 | final Context context = getContext(); 56 | this.adView = new AdManagerAdView(context); 57 | this.adView.setAppEventListener(this); 58 | this.adView.setAdListener(new AdListener() { 59 | @Override 60 | public void onAdClosed() { 61 | super.onAdClosed(); 62 | 63 | sendEvent(RNPublisherBannerViewManager.EVENT_AD_CLOSED, null); 64 | } 65 | 66 | @Override 67 | public void onAdFailedToLoad(@NonNull @NotNull LoadAdError loadAdError) { 68 | super.onAdFailedToLoad(loadAdError); 69 | 70 | int errorCode = loadAdError.getCode(); 71 | 72 | String errorMessage = "Unknown error"; 73 | switch (errorCode) { 74 | case AdManagerAdRequest.ERROR_CODE_INTERNAL_ERROR: 75 | errorMessage = "Internal error, an invalid response was received from the ad server."; 76 | break; 77 | case AdManagerAdRequest.ERROR_CODE_INVALID_REQUEST: 78 | errorMessage = "Invalid ad request, possibly an incorrect ad unit ID was given."; 79 | break; 80 | case AdManagerAdRequest.ERROR_CODE_NETWORK_ERROR: 81 | errorMessage = "The ad request was unsuccessful due to network connectivity."; 82 | break; 83 | case AdManagerAdRequest.ERROR_CODE_NO_FILL: 84 | errorMessage = "The ad request was successful, but no ad was returned due to lack of ad inventory."; 85 | break; 86 | } 87 | WritableMap event = Arguments.createMap(); 88 | WritableMap error = Arguments.createMap(); 89 | error.putString("message", errorMessage); 90 | event.putMap("error", error); 91 | sendEvent(RNPublisherBannerViewManager.EVENT_AD_FAILED_TO_LOAD, event); 92 | } 93 | 94 | @Override 95 | public void onAdOpened() { 96 | super.onAdOpened(); 97 | 98 | sendEvent(RNPublisherBannerViewManager.EVENT_AD_OPENED, null); 99 | } 100 | 101 | @Override 102 | public void onAdLoaded() { 103 | super.onAdLoaded(); 104 | 105 | int width = adView.getAdSize().getWidthInPixels(context); 106 | int height = adView.getAdSize().getHeightInPixels(context); 107 | int left = adView.getLeft(); 108 | int top = adView.getTop(); 109 | adView.measure(width, height); 110 | adView.layout(left, top, left + width, top + height); 111 | sendOnSizeChangeEvent(); 112 | sendEvent(RNPublisherBannerViewManager.EVENT_AD_LOADED, null); 113 | } 114 | 115 | @Override 116 | public void onAdClicked() { 117 | super.onAdClicked(); 118 | } 119 | 120 | @Override 121 | public void onAdImpression() { 122 | super.onAdImpression(); 123 | 124 | sendEvent(RNAdMobBannerViewManager.EVENT_AD_RECORD_IMPRESSION, null); 125 | } 126 | }); 127 | this.addView(this.adView); 128 | } 129 | 130 | private void sendOnSizeChangeEvent() { 131 | int width; 132 | int height; 133 | WritableMap event = Arguments.createMap(); 134 | AdSize adSize = this.adView.getAdSize(); 135 | 136 | width = adSize.getWidth(); 137 | height = adSize.getHeight(); 138 | 139 | event.putDouble("width", width); 140 | event.putDouble("height", height); 141 | sendEvent(RNAdMobBannerViewManager.EVENT_SIZE_CHANGE, event); 142 | } 143 | 144 | private void sendEvent(String name, @Nullable WritableMap event) { 145 | ReactContext reactContext = (ReactContext) getContext(); 146 | reactContext.getJSModule(RCTEventEmitter.class).receiveEvent( 147 | getId(), 148 | name, 149 | event); 150 | } 151 | 152 | public void loadBanner() { 153 | ArrayList adSizes = new ArrayList(); 154 | if (this.adSize != null) { 155 | adSizes.add(this.adSize); 156 | } 157 | if (this.validAdSizes != null) { 158 | for (int i = 0; i < this.validAdSizes.length; i++) { 159 | adSizes.add(this.validAdSizes[i]); 160 | } 161 | } 162 | 163 | if (adSizes.size() == 0) { 164 | adSizes.add(AdSize.BANNER); 165 | } 166 | 167 | AdSize[] adSizesArray = adSizes.toArray(new AdSize[adSizes.size()]); 168 | this.adView.setAdSizes(adSizesArray); 169 | 170 | AdManagerAdRequest.Builder adRequestBuilder = new AdManagerAdRequest.Builder(); 171 | AdManagerAdRequest adRequest = adRequestBuilder.build(); 172 | this.adView.loadAd(adRequest); 173 | } 174 | 175 | public void setAdUnitID(String adUnitID) { 176 | if (this.adUnitID != null) { 177 | // We can only set adUnitID once, so when it was previously set we have 178 | // to recreate the view 179 | this.createAdView(); 180 | } 181 | this.adUnitID = adUnitID; 182 | this.adView.setAdUnitId(adUnitID); 183 | } 184 | 185 | public void setTestDevices(String[] testDevices) { 186 | this.testDevices = testDevices; 187 | 188 | if (testDevices != null) { 189 | List testDeviceIds = new ArrayList<>(); 190 | 191 | for (int i = 0; i < testDevices.length; i++) { 192 | String testDevice = testDevices[i]; 193 | if (testDevice == "SIMULATOR") { 194 | testDeviceIds.add(AdManagerAdRequest.DEVICE_ID_EMULATOR); 195 | } else { 196 | testDeviceIds.add(testDevice); 197 | } 198 | } 199 | 200 | RequestConfiguration configuration = new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build(); 201 | MobileAds.setRequestConfiguration(configuration); 202 | } 203 | } 204 | 205 | public void setAdSize(AdSize adSize) { 206 | this.adSize = adSize; 207 | } 208 | 209 | public void setValidAdSizes(AdSize[] adSizes) { 210 | this.validAdSizes = adSizes; 211 | } 212 | 213 | @Override 214 | public void onAppEvent(String name, String info) { 215 | WritableMap event = Arguments.createMap(); 216 | event.putString("name", name); 217 | event.putString("info", info); 218 | sendEvent(RNPublisherBannerViewManager.EVENT_APP_EVENT, event); 219 | } 220 | } 221 | 222 | public class RNPublisherBannerViewManager extends ViewGroupManager { 223 | 224 | public static final String REACT_CLASS = "RNGADBannerView"; 225 | 226 | public static final String PROP_AD_SIZE = "adSize"; 227 | public static final String PROP_VALID_AD_SIZES = "validAdSizes"; 228 | public static final String PROP_AD_UNIT_ID = "adUnitID"; 229 | public static final String PROP_TEST_DEVICES = "testDevices"; 230 | 231 | public static final String EVENT_AD_LOADED = "onAdLoaded"; 232 | public static final String EVENT_AD_FAILED_TO_LOAD = "onAdFailedToLoad"; 233 | public static final String EVENT_AD_RECORD_IMPRESSION = "onAdRecordImpression"; 234 | public static final String EVENT_AD_OPENED = "onAdOpened"; 235 | public static final String EVENT_AD_CLOSED = "onAdClosed"; 236 | public static final String EVENT_SIZE_CHANGE = "onSizeChange"; 237 | public static final String EVENT_APP_EVENT = "onAppEvent"; 238 | 239 | public static final int COMMAND_LOAD_BANNER = 1; 240 | 241 | @Override 242 | public String getName() { 243 | return REACT_CLASS; 244 | } 245 | 246 | @Override 247 | protected ReactPublisherAdView createViewInstance(ThemedReactContext themedReactContext) { 248 | ReactPublisherAdView adView = new ReactPublisherAdView(themedReactContext); 249 | return adView; 250 | } 251 | 252 | @Override 253 | public void addView(ReactPublisherAdView parent, View child, int index) { 254 | throw new RuntimeException("RNPublisherBannerView cannot have subviews"); 255 | } 256 | 257 | @Override 258 | @Nullable 259 | public Map getExportedCustomDirectEventTypeConstants() { 260 | MapBuilder.Builder builder = MapBuilder.builder(); 261 | String[] events = { 262 | EVENT_AD_LOADED, 263 | EVENT_AD_FAILED_TO_LOAD, 264 | EVENT_AD_RECORD_IMPRESSION, 265 | EVENT_AD_OPENED, 266 | EVENT_AD_CLOSED, 267 | EVENT_SIZE_CHANGE, 268 | EVENT_APP_EVENT 269 | }; 270 | for (int i = 0; i < events.length; i++) { 271 | builder.put(events[i], MapBuilder.of("registrationName", events[i])); 272 | } 273 | return builder.build(); 274 | } 275 | 276 | @ReactProp(name = PROP_AD_SIZE) 277 | public void setPropAdSize(final ReactPublisherAdView view, final String sizeString) { 278 | Context context = view.getContext(); 279 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 280 | Display display = windowManager.getDefaultDisplay(); 281 | DisplayMetrics outMetrics = new DisplayMetrics(); 282 | display.getMetrics(outMetrics); 283 | 284 | float widthPixels = outMetrics.widthPixels; 285 | float density = outMetrics.density; 286 | 287 | int adWidth = (int) (widthPixels / density); 288 | 289 | AdSize adSize = getAdSizeFromString(context, sizeString, adWidth); 290 | view.setAdSize(adSize); 291 | } 292 | 293 | @ReactProp(name = PROP_VALID_AD_SIZES) 294 | public void setPropValidAdSizes(final ReactPublisherAdView view, final ReadableArray adSizeStrings) { 295 | Context context = view.getContext(); 296 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 297 | Display display = windowManager.getDefaultDisplay(); 298 | DisplayMetrics outMetrics = new DisplayMetrics(); 299 | display.getMetrics(outMetrics); 300 | 301 | float widthPixels = outMetrics.widthPixels; 302 | float density = outMetrics.density; 303 | 304 | int adWidth = (int) (widthPixels / density); 305 | 306 | ReadableNativeArray nativeArray = (ReadableNativeArray)adSizeStrings; 307 | ArrayList list = nativeArray.toArrayList(); 308 | String[] adSizeStringsArray = list.toArray(new String[list.size()]); 309 | AdSize[] adSizes = new AdSize[list.size()]; 310 | 311 | for (int i = 0; i < adSizeStringsArray.length; i++) { 312 | String adSizeString = adSizeStringsArray[i]; 313 | adSizes[i] = getAdSizeFromString(context, adSizeString, adWidth); 314 | } 315 | view.setValidAdSizes(adSizes); 316 | } 317 | 318 | @ReactProp(name = PROP_AD_UNIT_ID) 319 | public void setPropAdUnitID(final ReactPublisherAdView view, final String adUnitID) { 320 | view.setAdUnitID(adUnitID); 321 | } 322 | 323 | @ReactProp(name = PROP_TEST_DEVICES) 324 | public void setPropTestDevices(final ReactPublisherAdView view, final ReadableArray testDevices) { 325 | ReadableNativeArray nativeArray = (ReadableNativeArray)testDevices; 326 | ArrayList list = nativeArray.toArrayList(); 327 | view.setTestDevices(list.toArray(new String[list.size()])); 328 | } 329 | 330 | private AdSize getAdSizeFromString(Context context, String adSize, int width) { 331 | switch (adSize) { 332 | case "largeBanner": 333 | return AdSize.LARGE_BANNER; 334 | case "mediumRectangle": 335 | return AdSize.MEDIUM_RECTANGLE; 336 | case "fullBanner": 337 | return AdSize.FULL_BANNER; 338 | case "leaderBoard": 339 | return AdSize.LEADERBOARD; 340 | case "adaptiveBanner": 341 | return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, width); 342 | default: 343 | return AdSize.BANNER; 344 | } 345 | } 346 | 347 | @Nullable 348 | @Override 349 | public Map getCommandsMap() { 350 | return MapBuilder.of("loadBanner", COMMAND_LOAD_BANNER); 351 | } 352 | 353 | @Override 354 | public void receiveCommand(ReactPublisherAdView root, int commandId, @javax.annotation.Nullable ReadableArray args) { 355 | switch (commandId) { 356 | case COMMAND_LOAD_BANNER: 357 | root.loadBanner(); 358 | break; 359 | } 360 | } 361 | } 362 | --------------------------------------------------------------------------------