前回は、GDPR同意取得の詳細フローを確認しました。今回は、そのコードを書いていきましょう。コードは私が試行錯誤で完成させたものですので、ガラパゴス化しているかもしれません。また、この記事には、極端な表現や矛盾や説明の不足や表現が一致しない箇所があるかもしれません。色々と大目に見ていただけると助かります。
はじめに
前回から今回まで2ヶ月ありましたので少しコードを簡素化できました。前回ご紹介したフローと今回のコードが一致しない場合は、申し訳ありません。今回(その5)と次回(その6)のコードを実装すると、Unityのエディタ上でゲームを再生したときに以下のデモ用フォームが表示されるはずです。差し当たってはデモ用フォームの表示を目指して頑張りましょう。
注意点
注意すべき点がいくつかあります。
1については後述します。2については事前作成しておかないと例えテストであっても同意フォームが実機で表示されずエラーになります。3については日本語の同意フォームを実機で表示すると高確率で通信が失敗します。英語バージョンを表示するようにしましょう。4についてはダミー広告だと同意取得後に広告が表示されないことがあります。落とし穴が満載ですね。
なお、AdMob管理画面の「プライバシーとメッセージ」の「欧州の規制」の「管理」ボタンを押した先で、「メッセージの作成」を行うことができます。以下のスクショを参考にしてください。
GDPR対応させたAdMob表示メソッド
GDPRに対応させたAdMob表示メソッド(=GDPR同意取得メソッド)は以下の通りです。次回の記事で説明するクラスやメソッドもありますが、気にせず全体を眺めてください。
// 広告が開始済みであることを示す
bool Ad_Already_Started = false;
// GDPRに対応させたAdMob表示メソッド
public void TryAdMob()
{
if (TryAdMob_Busy || Ad_Already_Started) return;
TryAdMob_Busy = true;
StartCoroutine(TryAdMob_Event());
}
// GDPRに対応させたAdMob表示メソッドのコアな部分
bool TryAdMob_Busy = false;
IEnumerator TryAdMob_Event()
{
Debug.Log($"TryAdMob Start");
// 1.インターネット接続確認++++++++++++++++++++++++++++++++++++++++
bool isOnline = false;
yield return InternetChecker.Check(x => isOnline = x);
if (!isOnline)
{
Debug.Log($"TryAdMob Internet NG");
goto CANCEL;
}
// 2.念の為広告表示可能か確認+++++++++++++++++++++++++++++++++++++++
if (ConsentInformation.CanRequestAds())
{
Debug.Log($"TryAdMob Ad Start");
yield return MakeAdRequest(); //広告を開始する
yield return AdFinalize();
goto CANCEL;
}
// 3.同意状態確認リクエスト++++++++++++++++++++++++++++++++++++++++
bool? updateOK = null;
yield return TryUpdate(x => updateOK = x); //これはダミー広告だと初回失敗する
if (updateOK == false)
{
Debug.Log($"TryAdMob Update NG");
goto CANCEL;
}
// 4.同意フォーム表示リクエスト++++++++++++++++++++++++++++++++++++++++
bool? canShowAd = null;
yield return TryShowForm(x => canShowAd = x); //デバッグの同意フォームは英語じゃないとエラーが返る
// 5.広告表示処理++++++++++++++++++++++++++++++++++++++++
if (canShowAd == true)
{
while (!ConsentInformation.CanRequestAds()) yield return new WaitForSeconds(0.1f); //広告可能になるまで待つ
yield return MakeAdRequest(); //広告を開始する
yield return AdFinalize();
}
Debug.Log($"TryAdMob FinalResult={canShowAd}");
CANCEL:
Debug.Log($"CanRequestAds = {ConsentInformation.CanRequestAds()}");
TryAdMob_Busy = false;
}
いかがでしょう。思っていた感じとは違いましたか?とにかく処理が多いので、このコードでは深いネストを避け、極力わかりやすくしたつもりです。人によっては逆効果だったら、ごめんなさい。では、コードを上から順に解説していきます。
TryAdMobメソッド
TryAdMobが、GDPRに対応したAdMob表示するためのメソッドです。TryAdMob_Busyは二重実行防止のインターロックです。また、Ad_Already_StartedがTrueのとき、つまり広告表示が開始されているときは、実行をキャンセルします。そして、コアな処理はTryAdMob_Eventに丸投げします。
TryAdMob_Eventメソッド
コアな処理を行うコルーチンのメソッドです。コルーチンのことをここでは詳しく解説しませんが、所定時間待機したり、複数の処理を同時並行に行ったりする仕組みだと思ってください。Googleのサーバーに投げたリクエストのレスポンスは、いつどのタイミングで戻ってくるかわからないですよね。だから、いつまでも待てるようにコルーチンを使用しているのです。詳細についてはググってください。このメソッドでは次の処理を上から順に行います。
では、処理を解説していきます。
インターネット接続しているか確認
isOnlineというboolで結果を受け取ります。インターネット接続確認のメソッドInternetChecker.Checkの引数に関数x => isOnline = xを与えて実行します。この関数はラムダ式の無名関数なので何だかわかりにくい印象がありますが、通常の関数として書き下すと、以下のようなありきたりなものだとわかります。
void Method(bool x)
{
isOnline = x;
}
コルーチンというのは実は、戻り値がとれない処理なんです。でも処理結果を返して欲しい。だから、コルーチンであるInternetChecker.Checkになんとかして処理結果を返してもらうために、処理結果を引数のisOnlineへ代入させるということをやっています。isOnlineを通して処理結果をメソッド外でも確認できるというわけです。isOnlineがFalseだった場合は、gotoでCANCELラベルまでジャンプしてTryAdMob_Eventを中止します。(InternetChecker.Checkについては後述します)
広告表示可能か確認
ConsentInformation.CanRequestAds()でGDPR的に広告表示可能状態かどうかを確認し、結果がTrueであればもうすでに広告表示可能ということなのでその場で広告の表示を開始します。Falseの場合はTryAdMob_Eventメソッドの処理を継続します。
同意状態確認リクエスト
updateOKというboolで結果を受け取ります。同意状態確認リクエストするコルーチンのメソッドTryUpdateに関数x => updateOK = xを与えて実行します。updateOKがFalseだった場合は、gotoでCANCELラベルまで処理をジャンプしてTryAdMob_Eventを中止します。
同意フォーム表示リクエスト
canShowAdというboolで結果を受け取ります。同意フォーム表示リクエストするコルーチンのメソッドTryShowFormに関数x => canShowAd = xを与えて実行します。
広告表示処理
canShowAdがTrueの場合のみ広告表示を開始します。
インターネット接続を確認するクラスの詳細
インターネット接続を確認するクラスInternetCheckerについてはkanのメモ帳様の記事を参考に作成しました(kanのメモ帳様の記事)。インターネット接続を確認する方法をGoogleなどで検索するとApplication.internetReachabilityを使用する記事ばかりが出てきます。しかし、前述の記事にもある通り、これは端末の接続設定のOnOff状態を表しているに過ぎません。実はUnityではインターネット接続確認メソッドは用意されていないので、自作するしかありません。前述の記事を参考にクラスを自作できるようであれば、自作してください。無理なようでしたら、次回以降の記事で私が説明しますのでしばらくお待ちください。
同意状態確認リクエストのメソッド詳細
同意状態確認リクエストのメソッドであるTryUpdateの中身は以下の通りです。
IEnumerator TryUpdate(Action<bool?> callback)
{
bool? updateOK = null;
//今の同意状態をサーバーへ確認(いずれにせよこれはAdMobには必須なようだ)
ConsentInformation.Update(MakeConsentParameters(), (FormError error) =>
{
if (error != null)
{
updateOK = false;
Debug.Log($"TryUpdate Err: {error.Message}");
}
else
{
updateOK = true;
}
});
while (updateOK == null) yield return null; //処理が完了するまで待つ
callback(updateOK);
}
TryUpdateの引数はboolを引数に持つデリゲートです。デリゲートというのは関数の変数のことです。updateOKはNull許容型のboolです。Null許容型のboolはNull, True, Falseの3つの状態を取ることができます。TryUpdateは、受け取ったデリゲートを実行することによって、updateOKの値をメソッド外に渡します。ConsentInformation.UpdateはGoogle純正の同意状態確認リクエストのメソッドです。ConsentInformation.Updateの処理結果にエラーがある時はupdateOKにFalseを入れ、正常ならばupdateOKにTrueを入れます。updateOKがNullでなくなるまでwhile (updateOK == null) yield return nullによって待機することで、ConsentInformation.Updateの処理の完了を監視しています。(なお、while (updateOK == null) yield return null;はwhile (updateOK == null){ yield return null;}を省略した書き方です。)
そして、同意フォームの表示に必要なパラメータを作成するメソッドであるMakeConsentParametersの中身は以下の通りです。
ConsentRequestParameters _Parameters = null;
ConsentRequestParameters MakeConsentParameters()
{
if (_Parameters != null) return _Parameters;
_Parameters = new ConsentRequestParameters
{
TagForUnderAgeOfConsent = false,
ConsentDebugSettings = new ConsentDebugSettings
{
DebugGeography = DebugGeography.EEA,
TestDeviceHashedIds = TestDevices,
}
};
return _Parameters;
}
static readonly List<string> TestDevices = new()
{
"テストデバイスID",
};
TagForUnderAgeOfConsentについては、ターゲットが13歳以上のアプリの場合、すなわちEUでGDPR同意フォームを表示する年齢以上の場合はfalseにしてください。13歳未満のアプリはtrueにしてください。我々のアプリではもちろんfalseですね!ConsentDebugSettingsは動作確認したいときだけ有効にし、動作確認が終わったらコメントアウトしてください。DebugGeography = DebugGeography.EEAを有効にすると日本にいながらGDPR同意フォームを表示することができます。ただし、実機の場合は、テストデバイスIDを正しく指定しないとGDPR同意フォームが表示されません。また、事前にAdMob管理画面から「メッセージの作成」をしておかないと表示されません。
同意フォーム表示リクエストのメソッド詳細
同意フォーム表示リクエストのメソッドであるTryShowFormの中身は以下の通りです。最初にConsentInformation.ConsentStatusを確認して結果に応じて処理を変えます。statusがConsentStatus.Requiredの時のみ、同意フォーム表示を行うようにしています。
IEnumerator TryShowForm(Action<bool?> callback)
{
var status = ConsentInformation.ConsentStatus;
Debug.Log($"TryShowForm CONSENTSTATUS={status}");
bool? canShowAd = null;
if (status == ConsentStatus.Obtained || status == ConsentStatus.NotRequired)
{
canShowAd = true;
callback(canShowAd);
}
else if (status == ConsentStatus.Required)
{
while (!ConsentInformation.IsConsentFormAvailable()) yield return new WaitForSeconds(0.1f);//同意フォームが可能になるまで待つ
Debug.Log("TryShowForm Start");
ConsentForm.LoadAndShowConsentFormIfRequired((FormError error) =>
{
if (error != null)
{
canShowAd = false;
Debug.Log($"TryShowForm Err: {error.Message}");
}
else
{
canShowAd = true;
}
});
while (canShowAd == null) yield return new WaitForSeconds(0.1f); //同意フォーム表示処理が完了するまで待つ
callback(canShowAd);
}
else
{
//念の為
canShowAd = false;
callback(canShowAd);
}
}
statusがConsentStatus.Requiredの場合は最初に、同意フォームが利用可能になるまで待ちます。可能になれば、ConsentForm.LoadAndShowConsentFormIfRequiredメソッドで同意フォームの表示を試みます。canShowAdはNull許容型のboolです。Null許容型のboolはNull, True, Falseの3つの状態を取ることができます。エラーがあるとcanShowAdにFalseを入れ、なければTrueを入れます。canShowAdがNullである限り、値が入るまで待機します。
終わりに
少し記事が長くなりましたので、中身を紹介していないクラスやメソッドは次回以降とします。また、GDPRの規則では同意後の同意取消しも必須となっていますので、その対応も次回以降とします。
コメント