How to use Huawei Ads with AdMob Mediation(Official Flutter SDK)

Zübeyir Taruz
Huawei Developers
Published in
8 min readJun 13, 2023
Huawei Ads

Introduction

Hi everyone,

In this article we will talk about how to perform ad mediation using Huawei Ads adapter of AdMob in flutter applications. We will do the mediation process for the Android operating system and test it on the Android device. Before doing the integration, let me give you some information about Ad Mediation and AdMob.

Ad Mediation

Ad mediation is a system for managing more than one ad network in a way to get the best profit over a single sdk. Instead of adding the codes of all ad providers to your application, you can use the ads of different ad providers from one place by adding only the codes of the network that provides mediation (such as AdMob) and adding other ad providers (Huawei Ads, UnityAds…) from the panel of this network. This action increases competition among advertisers and in turn, your ad revenue increases.

AdMob

Google AdMob makes it easy for developers to earn money from their mobile apps with high-quality ads. AdMob maximizes the value of every impression by combining global advertiser demand, innovative ad formats, and advanced app monetization technology. AdMob helps maximize revenue with more advertiser demand that helps drive high CPMs and fill rates globally.

Huawei Ads Mediation with AdMob

Integration Process of Huawei Ads Adapter of AdMob

Now, we can start to talk about the integration process of Huawei Ads and AdMob flutter SDK through mediation. This process includes 3 parts :

  1. Configurations on Huawei Ads Console
  2. Configurations on AdMob Dashboard
  3. Development Process on Source Code

1. Configurations on Huawei Ads Console

With AdMob, Huawei mediation supports four basic ad units. These; banner ad, interstitial ad, rewarded ad and native ad types. In Huawei Ads platform, all we need to do is creating ad units of ad formats we want to use and keeping the ad unit IDs to use for next operations.

For details about creating ad unit in Huawei Ads Platform you can refer to this link.

2.Configurations on AdMob Dashboard

First go to AdMob Console login with your AdMob account. After login process, we will follow the steps below:

  • Adding App in AdMob Console
  • Creating Ad Units
  • Creating a Mediation Group

After registering on the platform, make sure you do all the operations on the platform. For details about above steps you can refer to this article.

3. Development Process on Source Code

Flutter uses plugins to provide access to a wide range of platform-specific services. Plugins enable you to access services and APIs on each platform. The google_mobile_ads plugin supports loading and displaying banner, interstitial, rewarded, and native ads using the AdMob API.

Add google_mobile_ads as a dependency to the pubspec.yaml file located at the root of the project for use in your application.

...

dependencies:
flutter:
sdk: flutter
# TODO: Add google_mobile_ads as a dependency
google_mobile_ads: ^3.0.0

...

Or you can do this by running the following command in the terminal.

flutter pub add google_mobile_ads

After performing console operations for Huawei Ads and AdMob, we need to add some dependency to our project. First, please add the following maven URLs to your project-level build.gradle file.

allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://developer.huawei.com/repo/' }
maven { url 'https://jitpack.io' }
}
}j

Then, add the following to in dependencies section of your application-level build.gradle file.

dependencies {
...
implementation 'com.huawei.hms:ads-prime:3.4.62.302'
implementation 'com.github.Explore-In-HMS:huawei.ads.admob_mediation:2.0.2'
implementation 'com.google.android.gms:play-services-ads:22.1.0'
}

Add your AdMob app ID (identified in the AdMob UI) to your app’s AndroidManifest.xml file.

<manifest>
...
<application>
...
<!-- Sample AdMob app ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
</application>

</manifest>

Initialization the Google Mobile Ads SDK

Before loading ads, you need to initialize the Google Mobile Ads SDK. Open the lib/main.dart file, and modify main function as below to initialize the SDK before the home page is loaded.

void main() {
// TODO: Initialize Google Mobile Ads SDK
MobileAds.instance.initialize();
runApp(const MyApp());
}

After initializing google mobile ads SDK, you can create a class called Ad Helper. In this class, you can set the ad unit ID you get from the AdMob console by platform (Android and IOS).

class AdHelper {
// Sample AdMob Ad Unit ID: ca-app-pub-3940256099942544/6300978111
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else if (Platform.isIOS) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else {
throw UnsupportedError('Unsupported platform');
}
}

static String get interstitialAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else if (Platform.isIOS) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else {
throw UnsupportedError('Unsupported platform');
}
}

static String get rewardedAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else if (Platform.isIOS) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else {
throw UnsupportedError('Unsupported platform');
}
}

static String get nativeAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else if (Platform.isIOS) {
return 'ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy';
} else {
throw UnsupportedError('Unsupported platform');
}
}
}

Banner Ad

First of all, the _loadBannerAd() method was written. In this method, after the ad unit ID, banner size and listener are set, a banner ad request is sent. We called this method in initState(). Thus, our banner ad will be loaded after our page is opened.

class BannerPage extends StatefulWidget {
const BannerPage({Key? key}) : super(key: key);

@override
State<BannerPage> createState() => _BannerPageState();
}

class _BannerPageState extends State<BannerPage> {

BannerAd? _bannerAd;

@override
void initState() {
super.initState();
_loadBannerAd();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
margin: const EdgeInsets.only(top: 500),
child: Column(
children: [
if (_bannerAd != null)
Align(
alignment: Alignment.topCenter,
child: SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!)),
),
],
),
),
),
);
}

void _loadBannerAd() {
BannerAd(
adUnitId: AdHelper.bannerAdUnitId,
request: const AdRequest(),
size: AdSize.banner,
listener: BannerAdListener(
onAdLoaded: (ad) {
setState(() {
_bannerAd = ad as BannerAd;
});
},
onAdFailedToLoad: (ad, err) {
debugPrint('Failed to load a banner ad: ${err.message}');
ad.dispose();
},
),
).load();
}

}

Interstitial Ad

In the page design, we have placed 1 button that will display the interstitial advertisement when clicked on it. Of course, the ad must be loaded before it can be displayed. We did the loading of the ad in initState() as we do with any ad type. When the user clicks the button, the _showInterstitialAd() method works. This method checks if the ad is loaded and displays the ad accordingly.

class InterstitialPage extends StatefulWidget {
const InterstitialPage({Key? key}) : super(key: key);

@override
State<InterstitialPage> createState() => _InterstitialPageState();
}

class _InterstitialPageState extends State<InterstitialPage> {

InterstitialAd? _interstitialAd;

@override
void initState() {
super.initState();
_loadInterstitialAd();
}

@override
Widget build(BuildContext context) {
return Scaffold(

body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [

Container(
margin: const EdgeInsets.only(top: 160),
child: getFloatingButtons,
),
],
),
),
);
}

Widget get getFloatingButtons {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [

FloatingActionButton(
heroTag: "btn2",
backgroundColor: Colors.red,
onPressed: _showInterstitialAd,
child: const Icon(Icons.play_arrow),
),

],
);
}

void _loadInterstitialAd() {
InterstitialAd.load(
adUnitId: AdHelper.interstitialAdUnitId,
request: const AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (InterstitialAd ad) {
debugPrint('$ad loaded');
_interstitialAd = ad;
},
onAdFailedToLoad: (LoadAdError error) {
debugPrint('InterstitialAd failed to load: $error.');
},
));
}

void _showInterstitialAd() {
if (_interstitialAd == null) {
debugPrint('Warning: attempt to show interstitial before loaded.');
return;
}
_interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (InterstitialAd ad) =>
debugPrint('ad onAdShowedFullScreenContent.'),
onAdDismissedFullScreenContent: (InterstitialAd ad) {
debugPrint('$ad onAdDismissedFullScreenContent.');
ad.dispose();
_loadInterstitialAd();
},
onAdFailedToShowFullScreenContent: (InterstitialAd ad, AdError error) {
debugPrint('$ad onAdFailedToShowFullScreenContent: $error');
ad.dispose();
_loadInterstitialAd();
},
);
_interstitialAd!.show();
}

}

Rewarded Ad

We designed the page design just like in the interstitial advertisement. In this section, when the page is opened for the first time, our rewarded ad will be loaded and our ad will be displayed when we press the button. Rewarded advertising is usually used in games to give a reward to the user after watching the entire ad. Thanks to the _rewardedAd!.show() function, we can understand that the user is watching the entire ad.

class RewardedPage extends StatefulWidget {
const RewardedPage({Key? key}) : super(key: key);

@override
State<RewardedPage> createState() => _RewardedPageState();
}

class _RewardedPageState extends State<RewardedPage> {
int amount = 0;
RewardedAd? _rewardedAd;

@override
void initState() {
super.initState();
_loadRewardedAd();
}

@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
"Remaining Token: $amount",
style: const TextStyle(color: Colors.blue, fontSize: 18),
),
const Spacer(),
ElevatedButton(
onPressed: _showRewardedAd,
style: ElevatedButton.styleFrom(
backgroundColor:
Colors.red, // Text Color (Foreground color)
),
child: const Text(
"EARN TOKEN",
style: TextStyle(color: Colors.white),
),
)
],
),
],
),
)
]),
),
);
}

void _loadRewardedAd() {
RewardedAd.load(
adUnitId: AdHelper.rewardedAdUnitId,
request: const AdRequest(),
rewardedAdLoadCallback: RewardedAdLoadCallback(
onAdLoaded: (RewardedAd ad) {
debugPrint('$ad loaded.');
_rewardedAd = ad;
},
onAdFailedToLoad: (LoadAdError error) {
debugPrint('RewardedAd failed to load: $error');
_rewardedAd = null;
},
));
}

void _showRewardedAd() {
if (_rewardedAd == null) {
debugPrint('Warning: attempt to show rewarded before loaded.');
return;
}
_rewardedAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (RewardedAd ad) =>
debugPrint('ad onAdShowedFullScreenContent.'),
onAdDismissedFullScreenContent: (RewardedAd ad) {
debugPrint('$ad onAdDismissedFullScreenContent.');
ad.dispose();
_loadRewardedAd();
},
onAdFailedToShowFullScreenContent: (RewardedAd ad, AdError error) {
debugPrint('$ad onAdFailedToShowFullScreenContent: $error');
ad.dispose();
_loadRewardedAd();
},
);

_rewardedAd!.setImmersiveMode(true);
_rewardedAd!.show(
onUserEarnedReward: (AdWithoutView ad, RewardItem reward) {
setState(() {
amount++;
});
debugPrint(
'$ad with reward $RewardItem(${reward.amount}, ${reward.type})');
});
}
}

Native Ad

In fact, the structure of a native ad is similar to a banner ad. Therefore, when the page is first opened, we load the ad after the ad unit ID and listener is set. If the ad is loaded, we display it.

class NativeAdsPage extends StatefulWidget {
const NativeAdsPage({Key? key}) : super(key: key);

@override
State<NativeAdsPage> createState() => _NativeAdsPageState();
}

class _NativeAdsPageState extends State<NativeAdsPage> {

NativeAd? _nativeAd;

@override
void initState() {
super.initState();
_loadNativeAd();
}

void _loadNativeAd() {
NativeAd(
adUnitId: AdHelper.nativeAdUnitId,
request: const AdRequest(),
listener: NativeAdListener(
onAdLoaded: (Ad ad) {
debugPrint('$NativeAd loaded.');
setState(() {
_nativeAd = ad as NativeAd;
});
},
onAdFailedToLoad: (Ad ad, LoadAdError error) {
debugPrint('$NativeAd failedToLoad: $error');
ad.dispose();
},
onAdOpened: (Ad ad) => debugPrint('$NativeAd onAdOpened.'),
onAdClosed: (Ad ad) => debugPrint('$NativeAd onAdClosed.'),
),
nativeTemplateStyle: NativeTemplateStyle(
templateType: TemplateType.medium,
mainBackgroundColor: Colors.white12,
callToActionTextStyle: NativeTemplateTextStyle(
size: 16.0,
),
primaryTextStyle: NativeTemplateTextStyle(
textColor: Colors.black38,
backgroundColor: Colors.white70,
),
),
).load();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
_nativeAd != null
? Container(
height: 400,
width: 400,
padding: const EdgeInsets.all(8),
child: AdWidget(ad: _nativeAd!),
)
: const SizedBox.shrink(),
],
),
),
);
}
}

Take care to use the listener features of the ads while integrating all four ad types. In this way, we get information about the status of the ads, and when we encounter an error, it is easier for us to find the reason.

Ads Mediation(Huawei) Screenshots

Conclusion

  • We demonstrated the process of ad reconciliation and integration of AdMob ads on Flutter using the AdMob Flutter Plugin and the Huawei Ads Adapter.
  • It can do Ad Mediation on Flutter using Huawei Ads and AdMob Platforms.
  • By using the ads mediation process, you can show Huawei ads in your games and applications and increase your earnings.
  • You can access the Huawei Ads Adapter source code from this link.

References

--

--