-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved handling of Amazon Integration #407
Comments
I found a way to solve this issue with a minimal patch to the SDK. By setting the Amazon bid response in I just needed to make It would be great if this class could be made public in a future release. Meanwhile, I hotfixed it using |
@christianrank, we've released version 8.1.1 to support your Amazon integration and hope you won't need a patch to modify our package. Actually I'm curious about how you integrated Amazon with our APIs in #291 using You can either email it to me at [email protected] or post it here. Thank you! |
Hi, thanks for the release. Here is an overview of the integration I did for Banner and MREC: React Native: import React, { useEffect, useState } from 'react'
import ReactNative from 'react-native'
import { AdFormat, AdView, destroyNativeUIComponentAdView } from 'react-native-applovin-max'
const { RNTAdsAppLovin } = ReactNative.NativeModules
interface Props {
adFormat: AdFormat
adUnitId: string
amazonAdUnitId: string
}
export const AppLovinBannerPosition = (props: Props) => {
const {
adFormat,
adUnitId,
amazonAdUnitId,
} = props
const [adViewId, setAdViewId] = useState<number>()
useEffect(() => {
// fetch bids and preload ad view on native side
RNTAdsAppLovin.fetchBidsAndPreloadNativeUIComponentAdView(adFormat, amazonAdUnitId, adUnitId).then((newAdViewId: number) => {
setAdViewId(newAdViewId)
})
}, [])
useEffect(() => {
return () => {
if (!adViewId) {
return
}
// destroy ad view on unmount
destroyNativeUIComponentAdView(adViewId)
}
}, [adViewId])
if (!adViewId) {
return null
}
return (
<AdView
adViewId={adViewId}
adUnitId={adUnitId}
adFormat={adFormat}
// ...
/>
)
} Android (Java): // ...
public class RNTAdsAppLovin extends ReactContextBaseJavaModule {
private final ReactApplicationContext context;
public RNTAdsAppLovin(ReactApplicationContext reactContext) {
super(reactContext);
context = reactContext;
}
@Override
public String getName() {
return "RNTAdsAppLovin";
}
private void preloadNativeUIComponentAdView(String adUnitId, MaxAdFormat maxAdFormat, Object amazonResponse, Promise promise) {
Map<String, Object> localExtraParameters = new HashMap<String, Object>();
if (amazonResponse != null) {
// from getLocalExtraParameterKeyForAmazonResult
String className = amazonResponse.getClass().getSimpleName();
String localExtraParameterKeyForAmazon = "DTBAdResponse".equalsIgnoreCase( className ) ? "amazon_ad_response" : "amazon_ad_error";
localExtraParameters.put(localExtraParameterKeyForAmazon, amazonResponse);
}
// initialize adView with localExtraParameters and resolve promise on react native with the id
AppLovinMAXAdView.preloadNativeUIComponentAdView(adUnitId, maxAdFormat, null, null, null, localExtraParameters, promise, this.context);
}
private void fetchBids(MaxAdFormat maxAdFormat, String amazonSlotUuid, Consumer<Object> callback) {
AppLovinSdkUtils.Size rawSize = maxAdFormat.getSize();
DTBAdSize dtbSize = new DTBAdSize(rawSize.getWidth(), rawSize.getHeight(), amazonSlotUuid);
DTBAdRequest adLoader = new DTBAdRequest();
adLoader.setSizes(dtbSize);
adLoader.loadAd(new DTBAdCallback()
{
@Override
public void onSuccess(@NonNull final DTBAdResponse dtbAdResponse) {
callback.accept(dtbAdResponse);
}
@Override
public void onFailure(@NonNull final AdError adError) {
callback.accept(adError);
}
} );
}
@ReactMethod
public void fetchBidsAndPreloadNativeUIComponentAdView(String format, String amazonSlotUuid, String adUnitId, Promise promise) {
MaxAdFormat maxAdFormat = format.equals("BANNER") ? MaxAdFormat.BANNER : MaxAdFormat.MREC;
if (amazonSlotUuid == null) {
// no amazon slot provided, directly preload adView
this.preloadNativeUIComponentAdView(adUnitId, maxAdFormat, null, promise);
return;
}
// callback to run after fetchBids
Consumer<Object> callback = (Object amazonResult) -> {
this.preloadNativeUIComponentAdView(adUnitId, maxAdFormat, amazonResult, promise);
};
// fetchBids and forward amazonResult to callback
this.fetchBids(maxAdFormat, amazonSlotUuid, callback);
}
} iOS (Swift): // ...
@objc(RNTAdsAppLovin)
class RNTAdsAppLovin: NSObject {
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
func preloadNativeUIComponentAdView(_ adUnitId: String, _ maxAdFormat: MAAdFormat, _ amazonResponse: NSObject?, _ resolve: @escaping RCTPromiseResolveBlock, _ reject: @escaping RCTPromiseRejectBlock) {
var extraParameters: [String: Any] = [:]
var localExtraParameters: [String: Any] = [:]
if (amazonResponse != nil) {
// from localExtraParameterKeyForAmazonResult
let className = String(describing: type(of: amazonResponse))
let localExtraParameterKeyForAmazon = className == "DTBAdResponse" ? "amazon_ad_response" : "amazon_ad_error"
localExtraParameters[localExtraParameterKeyForAmazon] = amazonResponse
}
// initialize adView with localExtraParameters and resolve promise on react native with the id
AppLovinMAXAdView.preloadNativeUIComponentAdView(adUnitId, adFormat: maxAdFormat, placement: nil, customData: nil, extraParameters: extraParameters, localExtraParameters: localExtraParameters, withPromiseResolver: resolve, withPromiseRejecter: reject)
}
func fetchBids(_ format: String, _ maxAdFormat: MAAdFormat, _ amazonSlotUuid: String, _ callback: @escaping (_ amazonResponse: NSObject?) -> Void) {
let rawSize = maxAdFormat.size
let dtbSize: DTBAdSize = DTBAdSize(bannerAdSizeWithWidth: Int(rawSize.width), height: Int(rawSize.height), andSlotUUID: amazonSlotUuid)!
let amazonCallback: DTBAdCallback = AmazonAdsCallback() { (_ amazonResponse: NSObject) in
callback(amazonResponse)
}
let adLoader = DTBAdLoader()
adLoader.setAdSizes([dtbSize])
adLoader.loadAd(amazonCallback)
}
@objc
func fetchBidsAndPreloadNativeUIComponentAdView(_ format: String, amazonSlotUuid: String?, adUnitId: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
let maxAdFormat: MAAdFormat = format == "BANNER" ? MAAdFormat.banner : MAAdFormat.mrec
guard (amazonSlotUuid != nil) else {
// no amazon slot provided, directly preload adView
self.preloadNativeUIComponentAdView(adUnitId, maxAdFormat, nil, resolve, reject)
return
}
// fetchBids and forward amazonResult to callback
self.fetchBids(format, maxAdFormat, amazonSlotUuid!) { (_ amazonResponse: NSObject?) in
self.preloadNativeUIComponentAdView(adUnitId, maxAdFormat, amazonResponse, resolve, reject)
}
}
}
class AmazonAdsCallback: DTBAdCallback {
var callback: (_ amazonResponse: NSObject) -> Void
init(_ callback: @escaping (_ amazonResponse: NSObject) -> Void) {
self.callback = callback
}
func onSuccess(_ adResponse: DTBAdResponse!) {
self.callback(adResponse)
}
func onFailure(_ error: DTBAdError, dtbAdErrorInfo: DTBAdErrorInfo!) {
self.callback(dtbAdErrorInfo)
}
} |
@christianrank, thanks!!! |
Feature Description
I am currently integrating Amazon with the approach described in this PR: #291.
First of all, this should be part of the official docs. I had to be lucky to find that PR here. In the React-Native docs under "Preparing Mediated Networks", when you check the Amazon checkbox, there is only an example that works for a native integration (it assumes you have access to AdView).
Now the problem I found is, that the Amazon bid response is saved with the adUnitId.
If there are multiple ads with the same adUnitId on the same screen that load a bid simultaneously (that is the case in our implementation), how would it be secured that the bids of different adUnits don't overwrite each other? Bids can get lost and only the first position would get bids.
There needs to be a new, unique identifier, like positionId, that can be used instead of adUnitId to attach the bid. So every position can get the correct bid response attached.
The text was updated successfully, but these errors were encountered: