This commit is contained in:
ehesp
2019-08-09 19:01:12 +01:00
parent 593422762e
commit 0b4bbf00a0
12 changed files with 438 additions and 111 deletions

View File

@@ -98,6 +98,28 @@ public class ReactNativeFirebaseAdMobCommon {
));
}
static public void sendAdEvent(String event, int requestId, String type, String adUnitId, @Nullable WritableMap error, @Nullable WritableMap data) {
ReactNativeFirebaseEventEmitter emitter = ReactNativeFirebaseEventEmitter.getSharedInstance();
WritableMap eventBody = Arguments.createMap();
eventBody.putString("type", type);
if (error != null) {
eventBody.putMap("error", error);
}
if (data != null) {
eventBody.putMap("data", data);
}
emitter.sendEvent(new ReactNativeFirebaseAdMobEvent(
event,
requestId,
adUnitId,
eventBody
));
}
static public String[] getCodeAndMessageFromAdErrorCode(int errorCode) {
String code = "unknown";
String message = "An unknown error occurred";

View File

@@ -24,6 +24,7 @@ import io.invertase.firebase.interfaces.NativeEvent;
public class ReactNativeFirebaseAdMobEvent implements NativeEvent {
public static final String EVENT_INTERSTITIAL = "admob_interstitial_event";
public static final String EVENT_REWARDED = "admob_rewarded_event";
public static final String AD_LOADED = "loaded";
public static final String AD_ERROR= "error";
@@ -32,6 +33,9 @@ public class ReactNativeFirebaseAdMobEvent implements NativeEvent {
public static final String AD_LEFT_APPLICATION = "left_application";
public static final String AD_CLOSED = "closed";
public static final String AD_REWARDED_LOADED = "rewarded_loaded";
public static final String AD_REWARDED_EARNED_REWARD = "rewarded_earned_reward";
private static final String KEY_BODY = "body";
private static final String KEY_REQUEST_ID = "requestId";
private static final String KEY_AD_UNIT_ID = "adUnitId";

View File

@@ -90,7 +90,7 @@ public class ReactNativeFirebaseAdMobModule extends ReactNativeFirebaseModule {
@ReactMethod
public void openDebugMenu(String adUnitId, Promise promise) {
MobileAds.openDebugMenu(getCurrentActivity(), adUnitId);
MobileAds.openDebugMenu(getReactApplicationContext(), adUnitId);
promise.resolve(null);
}
}

View File

@@ -0,0 +1,123 @@
package io.invertase.firebase.admob;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.google.android.gms.ads.rewarded.RewardItem;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdCallback;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
import io.invertase.firebase.common.ReactNativeFirebaseModule;
import io.invertase.firebase.database.ReactNativeFirebaseAdMobEvent;
import static io.invertase.firebase.admob.ReactNativeFirebaseAdMobCommon.buildAdRequest;
import static io.invertase.firebase.admob.ReactNativeFirebaseAdMobCommon.getCodeAndMessageFromAdErrorCode;
import static io.invertase.firebase.admob.ReactNativeFirebaseAdMobCommon.sendAdEvent;
import static io.invertase.firebase.database.ReactNativeFirebaseAdMobEvent.AD_CLOSED;
import static io.invertase.firebase.database.ReactNativeFirebaseAdMobEvent.AD_ERROR;
import static io.invertase.firebase.database.ReactNativeFirebaseAdMobEvent.AD_OPENED;
import static io.invertase.firebase.database.ReactNativeFirebaseAdMobEvent.AD_REWARDED_EARNED_REWARD;
import static io.invertase.firebase.database.ReactNativeFirebaseAdMobEvent.AD_REWARDED_LOADED;
public class ReactNativeFirebaseAdMobRewardedModule extends ReactNativeFirebaseModule {
private static final String SERVICE = "AdMobRewarded";
private static SparseArray<RewardedAd> rewardedAdArray = new SparseArray<>();
public ReactNativeFirebaseAdMobRewardedModule(ReactApplicationContext reactContext) {
super(reactContext, SERVICE);
}
private void sendRewardedEvent(String type, int requestId, String adUnitId, @Nullable WritableMap error, @Nullable WritableMap data) {
sendAdEvent(
ReactNativeFirebaseAdMobEvent.EVENT_REWARDED,
requestId,
type,
adUnitId,
error,
data
);
}
@ReactMethod
public void rewardedLoad(int requestId, String adUnitId, ReadableMap adRequestOptions) {
getCurrentActivity().runOnUiThread(() -> {
RewardedAd rewardedAd = new RewardedAd(getApplicationContext(), adUnitId);
RewardedAdLoadCallback adLoadCallback = new RewardedAdLoadCallback() {
@Override
public void onRewardedAdLoaded() {
RewardItem rewardItem = rewardedAd.getRewardItem();
WritableMap data = Arguments.createMap();
data.putString("type", rewardItem.getType());
data.putInt("amount", rewardItem.getAmount());
sendRewardedEvent(AD_REWARDED_LOADED, requestId, adUnitId, null, data);
}
@Override
public void onRewardedAdFailedToLoad(int errorCode) {
WritableMap error = Arguments.createMap();
String[] codeAndMessage = getCodeAndMessageFromAdErrorCode(errorCode);
error.putString("code", codeAndMessage[0]);
error.putString("message", codeAndMessage[1]);
sendRewardedEvent(AD_ERROR, requestId, adUnitId, error, null);
}
};
rewardedAd.loadAd(buildAdRequest(adRequestOptions), adLoadCallback);
rewardedAdArray.put(requestId, rewardedAd);
});
}
@ReactMethod
public void rewardedShow(int requestId, String adUnitId, ReadableMap showOptions, Promise promise) {
getCurrentActivity().runOnUiThread(() -> {
RewardedAd rewardedAd = rewardedAdArray.get(requestId);
boolean immersiveModeEnabled = false;
if (showOptions.hasKey("immersiveModeEnabled")) {
immersiveModeEnabled = showOptions.getBoolean("immersiveModeEnabled");
}
RewardedAdCallback adCallback = new RewardedAdCallback() {
@Override
public void onRewardedAdOpened() {
sendRewardedEvent(AD_OPENED, requestId, adUnitId, null, null);
}
@Override
public void onRewardedAdClosed() {
sendRewardedEvent(AD_CLOSED, requestId, adUnitId, null, null);
}
@Override
public void onUserEarnedReward(@NonNull RewardItem reward) {
WritableMap data = Arguments.createMap();
data.putString("type", reward.getType());
data.putInt("amount", reward.getAmount());
sendRewardedEvent(AD_REWARDED_EARNED_REWARD, requestId, adUnitId, null, data);
}
@Override
public void onRewardedAdFailedToShow(int errorCode) {
WritableMap error = Arguments.createMap();
String[] codeAndMessage = getCodeAndMessageFromAdErrorCode(errorCode);
error.putString("code", codeAndMessage[0]);
error.putString("message", codeAndMessage[1]);
sendRewardedEvent(AD_ERROR, requestId, adUnitId, error, null);
}
};
rewardedAd.show(getCurrentActivity(), adCallback, immersiveModeEnabled);
promise.resolve(null);
});
}
}

View File

@@ -34,6 +34,7 @@ public class ReactNativeFirebaseAdmobPackage implements ReactPackage {
modules.add(new ReactNativeFirebaseAdMobModule(reactContext));
modules.add(new ReactNativeFirebaseAdMobConsentModule(reactContext));
modules.add(new ReactNativeFirebaseAdMobInterstitialModule(reactContext));
modules.add(new ReactNativeFirebaseAdMobRewardedModule(reactContext));
return modules;
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
export default {
LOADED: 'rewarded_loaded',
EARNED_REWARD: 'rewarded_earned_reward',
};

View File

@@ -15,22 +15,19 @@
*
*/
import NativeError from '@react-native-firebase/app/lib/internal/NativeFirebaseError';
import { isFunction, isObject, isString, isUndefined } from '@react-native-firebase/common';
import {
getFirebaseRoot,
} from '@react-native-firebase/app/lib/internal';
import { isFunction, isString } from '@react-native-firebase/common';
import { getFirebaseRoot } from '@react-native-firebase/app/lib/internal';
import validateAdRequestOptions from '../validateAdRequestOptions';
import AdEventType from '../AdEventType';
import MobileAd from './MobileAd';
let _interstitialRequest = 0;
export default class InterstitialAd {
export default class InterstitialAd extends MobileAd {
static createForAdRequest(adUnitId, requestOptions) {
if (!isString(adUnitId)) {
throw new Error(
`firebase.admob() InterstitialAd.loadAd(*) 'adUnitId' expected an string value.`,
`firebase.admob() InterstitialAd.createForAdRequest(*) 'adUnitId' expected an string value.`,
);
}
@@ -38,60 +35,12 @@ export default class InterstitialAd {
try {
options = validateAdRequestOptions(requestOptions);
} catch (e) {
throw new Error(
`firebase.admob() InterstitialAd.createForAdRequest(_, *) ${e.message}.`,
);
throw new Error(`firebase.admob() InterstitialAd.createForAdRequest(_, *) ${e.message}.`);
}
const requestId = _interstitialRequest++;
const admob = getFirebaseRoot().admob();
return new InterstitialAd(admob, requestId, adUnitId, options);
}
constructor(admob, requestId, adUnitId, requestOptions) {
this._admob = admob;
this._requestId = requestId;
this._adUnitId = adUnitId;
this._requestOptions = requestOptions;
this._loading = false;
this._loaded = false;
this._onAdEvent = null;
console.log(`admob_interstitial_event:${adUnitId}:${requestId}`);
// needs to be in admob constructor
this._nativeListener = admob.emitter.addListener(
`admob_interstitial_event:${adUnitId}:${requestId}`,
this._handleAdEvent.bind(this),
);
}
_handleAdEvent(event) {
const { type, error } = event.body;
console.log('_handleAdEvent', event);
if (type === AdEventType.LOADED) {
this._loaded = true;
}
console.log('onAdEvent', this._onAdEvent);
if (this._onAdEvent) {
let nativeError = undefined;
if (error) {
nativeError = NativeError.fromEvent(error, 'admob');
}
this._onAdEvent(type, nativeError);
}
}
get adUnitId() {
return this._adUnitId;
}
get loaded() {
return this._loaded;
return new InterstitialAd('interstitial', admob, requestId, adUnitId, options);
}
load() {
@@ -104,32 +53,28 @@ export default class InterstitialAd {
this._admob.native.interstitialLoad(this._requestId, this._adUnitId, this._requestOptions);
}
onAdEvent(listener) {
if (!isFunction(listener)) {
onAdEvent(handler) {
if (!isFunction(handler)) {
throw new Error(
"firebase.admob() InterstitialAd.onAdEvent(*) 'listener' expected a function."
'firebase.admob() InterstitialAd.onAdEvent(*) \'handler\' expected a function.',
);
}
this._onAdEvent = listener;
return () => this._nativeListener.remove();
return this._setAdEventHandler(handler);
}
show(showOptions) {
if (!this.loaded) {
throw new Error(
"firebase.admob() InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown."
)
'firebase.admob() InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown.',
);
}
let options = {
immersiveModeEnabled: false,
};
// todo validate options
// todo validate options? common validator or local?
return this._admob.native.interstitialShow(
this._requestId,
options,
);
return this._admob.native.interstitialShow(this._requestId, options);
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import NativeError from '@react-native-firebase/app/lib/internal/NativeFirebaseError';
import AdEventType from '../AdEventType';
import RewardedAdEventType from '../RewardedAdEventType';
export default class MobileAd {
constructor(type, admob, requestId, adUnitId, requestOptions) {
this._type = type;
this._admob = admob;
this._requestId = requestId;
this._adUnitId = adUnitId;
this._requestOptions = requestOptions;
this._loading = false;
this._loaded = false;
this._onAdEventHandler = null;
this._nativeListener = admob.emitter.addListener(
`admob_${type}_event:${adUnitId}:${requestId}`,
this._handleAdEvent.bind(this),
);
}
_handleAdEvent(event) {
const { type, error, data } = event.body;
if (
type === AdEventType.LOADED ||
type === RewardedAdEventType.LOADED
) {
this._loaded = true;
}
if (this._onAdEventHandler) {
let nativeError = undefined;
if (error) {
nativeError = NativeError.fromEvent(error, 'admob');
}
this._onAdEventHandler(type, nativeError, data);
}
}
_setAdEventHandler(handler) {
this._onAdEventHandler = handler;
return () => this._nativeListener.remove();
}
get adUnitId() {
return this._adUnitId;
}
get loaded() {
return this._loaded;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2016-present Invertase Limited & Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this library except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { isFunction, isString } from '@react-native-firebase/common';
import { getFirebaseRoot } from '@react-native-firebase/app/lib/internal';
import validateAdRequestOptions from '../validateAdRequestOptions';
import MobileAd from './MobileAd';
let _rewardedRequest = 0;
export default class RewardedAd extends MobileAd {
static createForAdRequest(adUnitId, requestOptions) {
if (!isString(adUnitId)) {
throw new Error(
`firebase.admob() RewardedAd.createForAdRequest(*) 'adUnitId' expected an string value.`,
);
}
let options = {};
try {
options = validateAdRequestOptions(requestOptions);
} catch (e) {
throw new Error(`firebase.admob() RewardedAd.createForAdRequest(_, *) ${e.message}.`);
}
const requestId = _rewardedRequest++;
const admob = getFirebaseRoot().admob();
return new RewardedAd('rewarded', admob, requestId, adUnitId, options);
}
load() {
// Prevent multiple load calls
if (this._loading) {
return;
}
this._loading = true;
this._admob.native.rewardedLoad(this._requestId, this._adUnitId, this._requestOptions);
}
onAdEvent(handler) {
if (!isFunction(handler)) {
throw new Error(
'firebase.admob() RewardedAd.onAdEvent(*) \'handler\' expected a function.',
);
}
return this._setAdEventHandler(handler);
}
show(showOptions) {
if (!this.loaded) {
throw new Error(
'firebase.admob() RewardedAd.show() The requested RewardedAd has not loaded and could not be shown.',
);
}
let options = {
immersiveModeEnabled: false,
};
// todo validate options? common validator or local?
return this._admob.native.rewardedShow(this._requestId, this._adUnitId, options);
}
}

View File

@@ -511,6 +511,65 @@ export namespace Admob {
MA: 'MA';
}
/**
* Base call for InterstitialAd, RewardedAd and NativeAd.
*/
export class MobileAd {
/**
* The Ad Unit ID for this AdMob ad.
*/
adUnitId: string;
/**
* Whether the advert is loaded and can be shown.
*/
loaded: boolean;
/**
* Start loading the advert with the provided RequestOptions.
*
* It is recommended you setup ad event handlers before calling this method.
*
* #### Example
*
* ```js
*
* ```
*/
load(): void;
/**
* Listen to ad events. See AdEventTypes for more information.
*
* @param listener
*/
onAdEvent(listener: AdEventListener): Function;
}
/**
*
*/
export class InterstitialAd extends MobileAd {
/**
* Creates a new InterstitialAd instance.
*
* @param adUnitId The Ad Unit ID for the Interstitial. You can find this on your Google AdMob dashboard.
* @param requestOptions Optional RequestOptions used to load the ad.
*/
static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions): InterstitialAd;
/**
* Once loaded, call this method to show the advert on your app.
*
* #### Example
*
* ```js
*
* ```
*/
show(): Promise<void>;
}
/**
* The Firebase Admob service interface.
*
@@ -525,29 +584,6 @@ export namespace Admob {
* ```
*/
export class Module extends FirebaseModule {
/**
* Initializes the Google Mobile Ads SDK with the App ID provided to your firebase.json 'admob_app_id'.
*
* If your firebase.json `admob_delay_app_measurement_init` value is set to `true`, this method
* must be called before performing any AdMob related requests.
*
* Calling the initialize method if the SDK has already been initialized will resolve the promise.
*
* #### Example
*
* ```js
* import admob, { MaxAdContentRating } from '@react-native-firebase/admob';
*
* await admob.initialize({
* // Set all requests suitable for general audiences
* maxAdContentRating: MaxAdContentRating.G,
* });
* ```
*
* @param requestConfiguration An optional RequestConfiguration interface. If not provided, AdMob will initialize with default settings.
*/
initialize(requestConfiguration?: RequestConfiguration): Promise<void>;
/**
* Sets request options for all future ad requests.
*

View File

@@ -24,8 +24,10 @@ import {
import version from './version';
import AdsConsentDebugGeography from './AdsConsentDebugGeography';
import AdsConsentStatus from './AdsConsentStatus';
import MaxAdContentRating from './MaxAdContentRating';
import MaxAdContentRating from './MaxAdContentRating'
import AdEventType from './AdEventType';
import RewardedAdEventType from './RewardedAdEventType';
import validateAdRequestConfiguration from './validateAdRequestConfiguration';
import { isObject } from '@react-native-firebase/common';
@@ -44,7 +46,7 @@ const statics = {
const namespace = 'admob';
const nativeModuleName = ['RNFBAdMobModule', 'RNFBAdMobInterstitialModule'];
const nativeModuleName = ['RNFBAdMobModule', 'RNFBAdMobInterstitialModule', 'RNFBAdMobRewardedModule'];
class FirebaseAdMobModule extends FirebaseModule {
@@ -57,6 +59,13 @@ class FirebaseAdMobModule extends FirebaseModule {
event,
);
});
this.emitter.addListener('admob_rewarded_event', (event) => {
this.emitter.emit(
`admob_rewarded_event:${event.adUnitId}:${event.requestId}`,
event,
);
});
}
setRequestConfiguration(requestConfiguration) {
@@ -93,7 +102,7 @@ export default createModuleNamespace({
version,
namespace,
nativeModuleName,
nativeEvents: ['admob_interstitial_event'],
nativeEvents: ['admob_interstitial_event', 'admob_rewarded_event'],
hasMultiAppSupport: false,
hasCustomUrlOrRegionSupport: false,
ModuleClass: FirebaseAdMobModule,
@@ -108,8 +117,10 @@ export AdsConsentDebugGeography from './AdsConsentDebugGeography';
export AdsConsentStatus from './AdsConsentStatus';
export MaxAdContentRating from './MaxAdContentRating';
export AdEventType from './AdEventType';
export RewardedAdEventType from './RewardedAdEventType';
export AdsConsent from './AdsConsent';
export InterstitialAd from './ads/InterstitialAd';
export RewardedAd from './ads/RewardedAd';

View File

@@ -19,7 +19,7 @@
import React, { useEffect, Component } from 'react';
import { AppRegistry, Image, StyleSheet, View, Text } from 'react-native';
import { AdsConsent, InterstitialAd } from '@react-native-firebase/admob';
import { AdsConsent, InterstitialAd, RewardedAd } from '@react-native-firebase/admob';
import firebase from '@react-native-firebase/app';
function Root() {
@@ -42,23 +42,35 @@ function Root() {
// },
// });
// testing ssh - not sure the name
const interstitialAd = InterstitialAd.createForAdRequest('ca-app-pub-3940256099942544/1033173712', {
//
});
const rewardedAd = RewardedAd.createForAdRequest('ca-app-pub-3940256099942544/5224354917');
interstitialAd.onAdEvent((type, error) => {
console.log('>>>', type, error);
if (type === 'loaded') {
console.log('!!!!! show')
interstitialAd.show();
rewardedAd.onAdEvent(async (type, error, data) => {
console.log('>>>', type, error, data);
if (type === 'rewarded_loaded') {
rewardedAd.show();
}
});
setTimeout(() => {
interstitialAd.load();
}, 1);
rewardedAd.load();
// testing ssh - not sure the name
// const interstitialAd = InterstitialAd.createForAdRequest('ca-app-pub-3940256099942544/1033173712', {
// //
// });
// interstitialAd.onAdEvent(async (type, error) => {
// console.log('>>>', type, error);
// if (type === 'loaded') {
// console.log('!!!!! show')
// await interstitialAd.show();
// }
// });
//
// setTimeout(() => {
// interstitialAd.load();
// }, 1);
}
useEffect(() => {