インターステンシャル広告をProviderパターンで実装してみた
この記事を見て、出来るようになること
(1)FutureBuilderを用いた初期化処理を実装できるようになる。
・初期化中の画面表示(InitializePage)
・初期化エラー時の画面表示(ErrorPage)
・完了時の画面表示(HomePage)
(2)インターステンシャル広告を任意のタイミングで表示できるようになる。
この記事ではカウンターが5の倍数になったタイミングで表示
画面イメージ
参考サイト
事前準備
1.providerパッケージを追加
flutter pub add provider
2.Google_mobile_adsパッケージを追加
flutter pub add google_mobile_ads
3.Info.plistに広告アプリIDを追加(xxxは各自のID)[for iOS]
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
</array>
4.AndroidMafifest.xmlに広告アプリIDを追加(xxxは各自のID)[for Android]
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~xxxxxxxxxx"/>
広告モデルのクラスを作成
lib/model/ad_Interstitial.dart
ポイント
・ChangeNotifierをMixinする(notifyListeners()を使うため)
・カウンターが5で割り切れる時に広告を表示する(showAdメソッド)
・広告表示後、次の広告を作成する(createAdメソッド)
import 'package:flutter/cupertino.dart';
import 'dart:io';
import 'package:google_mobile_ads/google_mobile_ads.dart';
class AdInterstitial with ChangeNotifier{
int num_of_attempt_load = 0;
bool ready = false;
int _counter = 0;
int get counter => _counter;
set counter(int value) {
_counter = value;
print(_counter);
notifyListeners();
if(_counter % 5 == 0){
// カウンターが5で割り切れる場合は、広告を表示する
showAd();
}
if(!ready){
createAd();
}
}
/**
* バナー広告
*/
InterstitialAd? _interstitialAd;
InterstitialAd? get interstitialAd => _interstitialAd;
set banner(InterstitialAd? value) {
_interstitialAd = value;
notifyListeners();
}
// create interstitial ads
void createAd() {
print("### 広告を作成します");
InterstitialAd.load(
adUnitId: interstitialAdUnitId,
request: const AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
// 広告が正常にロードされたときに呼ばれます。
onAdLoaded: (InterstitialAd ad) {
print('### add loaded');
_interstitialAd = ad;
num_of_attempt_load = 0;
ready = true;
// 連続で広告を表示するためにロードされたら表示するようにする
//showAd(); // showAdをcreateAdで呼び出す
},
// 広告のロードが失敗した際に呼ばれます。
onAdFailedToLoad: (LoadAdError error) {
num_of_attempt_load++;
_interstitialAd = null;
if (num_of_attempt_load <= 2) {
createAd();
}
},
),
);
}
// show interstitial ads to user
Future<void> showAd() async {
ready = false;
if (_interstitialAd == null) {
print('Warning: attempt to show interstitial before loaded.');
return;
}
_interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdShowedFullScreenContent: (InterstitialAd ad) {
print("ad onAdshowedFullscreen");
},
onAdDismissedFullScreenContent: (InterstitialAd ad) {
print("ad Disposed");
ad.dispose();
},
onAdFailedToShowFullScreenContent: (InterstitialAd ad, AdError aderror) {
print('$ad OnAdFailed $aderror');
ad.dispose();
createAd();
},
onAdImpression: (InterstitialAd ad) => print('$ad impression occurred.'),
);
// 広告の表示には.show()を使う
await _interstitialAd!.show();
_interstitialAd = null;
}
// 広告IDをプラットフォームに合わせて取得
static String get interstitialAdUnitId {
if (Platform.isAndroid) {
return ' ca-app-pub-3940256099942544/1033173712'; // android用のテスト広告ID(インターステンシャル)
} else if (Platform.isIOS) {
return 'ca-app-pub-3940256099942544/4411468910'; // ios用のテスト広告ID(インターステンシャル)
} else {
//どちらでもない場合は、テスト用を返す
return BannerAd.testAdUnitId;
}
}
}
main.dartを修正
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_ad_test/model/ad_Interstitial.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
late AdInterstitial adInterstitial;
/**
* 初期処理
*/
Future<void> _initializeApp(BuildContext context) async {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
adInterstitial = AdInterstitial();
adInterstitial.createAd(); // 初回広告を作成しておく
await Future.delayed(const Duration(milliseconds: 1000));// ダミー処理(初期化中の画面の動作確認のため)
// throw Exception("初期化処理エラー(ダミー)"); // 起動エラー発生時の動作確認用
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initializeApp(context),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if(snapshot.hasError){
// エラー発生時に表示するウィジェット
return ErrorPage(message: snapshot.error!.toString());
}
if (snapshot.connectionState == ConnectionState.done) {
// _initializeApp完了後に表示するウィジェット
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => adInterstitial,
),
],
child: HomePage(),
);
}
// _initializeApp処理中に表示するウィジェット
return InitializePage();
},
);
}
}
class InitializePage extends StatelessWidget {
String title = "Initializing...";
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, // 右上に表示される"debug"ラベルを消す
home: Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(title),
],
),
),
),
),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, // 右上に表示される"debug"ラベルを消す
home: Consumer<AdInterstitial>(
builder: (ctx, model, child) {
return Scaffold(
appBar: AppBar(
title: Text("インターステンシャル広告のデモ"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'5の倍数でインターステンシャル広告が表示されます',
),
Text(
model.counter.toString(),
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
model.counter++;
},
child: const Icon(Icons.add),
),
);
}),
);
}
}
class ErrorPage extends StatelessWidget {
final String? message;
String title = "予期しないエラーが発生しました";
ErrorPage({Key? key, required this.message}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, // 右上に表示される"debug"ラベルを消す
home: Scaffold(
appBar: AppBar(
title: Text("インターステンシャル広告のデモ"),
),
body: Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: Theme.of(context).textTheme.headline6,
),
Text(
message ?? "",
style: Theme.of(context).textTheme.bodyText2,
),
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton.extended(
onPressed: ()async{
String msg = title + "\n";
msg = msg + message! + "\n";
final data = ClipboardData(text: msg);
await Clipboard.setData(data);
},
icon: const Icon(Icons.copy),
label: Text("メッセージをコピーする"),
),
),
);
}
}
補足
・InitializePageを表示するために、初期化処理で以下の遅延を入れています。実際の開発では不要です。(あくまでもデバック用)
await Future.delayed(const Duration(milliseconds: 1000));// ダミー処理(初期化中の画面の動作確認のため)
・初期化エラー時の画面を確認する場合は、以下の処理を有効にしてください。(コメントを外してください)
// throw Exception("初期化処理エラー(ダミー)"); // 起動エラー発生時の動作確認用
この記事が気に入ったらサポートをしてみませんか?