Android 33 と iOS 14 に対応するの、すごく疲れた。
Unity 2019 を使っていたが、Unity 2023 に変更した。
さらに修正 2023/11/26
ATT ダイアログをIDFA ダイアログに変更👇
🏕️ Environment
Unity 2023.2.1.f1
Gradle が標準で最新版が使える方が今後良い為
Easy Mobile Pro v2.19.0
Easy mobile Pro の最新版がこれ、すでに廃止されている
GoogleMobileAds-v7.3.1
Easymobile Pro の最新版と互換性のあるメソッド名を使っているもののうち最新版だったので
MetaAudienceNetworkUnityAdapter-3.9.1
公式がGoogleMobileAds-v7.3.0 でテスト確認済みの為
com.google.play.review-1.8.1
Easy mobile Pro の in-app-review が古くAndroid 33 にてクラッシュする原因だった。こちらの公式パッケージを代わりに使う
com.google.play.core-1.8.2
com.google.play.review-1.8.1 を使う時に必要
❓ Issues
Android 33 にてクラッシュしてしまう
iOS14 でビルドできない
👏 Solve
解決方法を順番に説明する
1. 🫥 Easy mobile Pro の修正
EasyMobileDependencies.xml の 18~22 を Uncomment する。このandroid.play:core
を入れているとAndroid 31~ でクラッシュしてしまう。
<!-- <androidPackage spec="com.google.android.play:core:1.6.+">
<repositories>
<repository>https://maven.google.com</repository>
</repositories>
</androidPackage> -->
プロジェクト内に android.core
が名前に含まれるファイルがある場合全部削除する。
注意
このファイルはin-app-review
に関与している。削除するとEasy mobile pro を使ったin-app-review
は機能しない。
2. 🌟 in-app-review
機能の追加
com.google.play.review-1.8.1
com.google.play.core-1.8.2
の2つのunitypackage を公式からダウンロード後、import する。
その後、Force resolve する。
独自の in-app-review
スクリプトを作成する。
定義側
using System.Collections;
using UnityEngine;
public static class AppReview
{
public static IEnumerator Request()
{
#if UNITY_IOS
UnityEngine.iOS.Device.RequestStoreReview();
#elif UNITY_ANDROID
var reviewManager = new Google.Play.Review.ReviewManager();
var requestFlowOperation = reviewManager.RequestReviewFlow();
yield return requestFlowOperation;
if (requestFlowOperation.Error != Google.Play.Review.ReviewErrorCode.NoError)
{
// エラー処理が必要な場合ここに追加
Debug.LogError(requestFlowOperation.Error);
yield break;
}
var playReviewInfo = requestFlowOperation.GetResult();
var launchFlowOperation = reviewManager.LaunchReviewFlow(playReviewInfo);
yield return launchFlowOperation;
if (launchFlowOperation.Error != Google.Play.Review.ReviewErrorCode.NoError)
{
// エラー処理が必要な場合ここに追加
Debug.LogError(launchFlowOperation.Error);
yield break;
}
#else
Debug.Log("RequestReview Not supported.");
#endif
yield break;
}
}
呼び出し側
using UnityEngine;
public class ReviewManager : MonoBehaviour
{
public void ReviewDialogDown()
{
// Show the rating dialog with default behavior
StartCoroutine(AppReview.Request());
}
}
3. 🎬 Admob package の修正
iOS SDK version 9.13.0 を使っているので、iOS 14 ビルドのためには以下の対応が必要。これをしないとビルドできない。
<iosPods>
- <iosPod name="Google-Mobile-Ads-SDK" version="~> 9.11">
+ <iosPod name="Google-Mobile-Ads-SDK" version="9.13">
<sources>
<source>https://github.com/CocoaPods/Specs</source>
</sources>
</iosPod>
</iosPods>
5. 👣 ATT 対応(App Tracking Transparency)
GoogleMobileAds-v8~
以降は標準でATT対応される。ただ今回は、Easy mobile pro の関係でv7.3.1
を使っているので、スクリプトで設計する必要がある。
定義側
⚠️ Assets > Plugin > iOS
に配置する。
廃止 `RequestAttDialog.mm`
#import <Foundation/Foundation.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
//この範囲のコードはCで書かれてるよってこと
#ifdef __cplusplus
extern "C" {
#endif
//ATTダイアログを表示するメソッド
void requestIDFA() {
if (@available(iOS 14, *)){
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
// Tracking authorization completed. Start loading ads here.
// [self loadAd];
}];
}
}
#ifdef __cplusplus
}
#endif
🆕
import Foundation
import AppTrackingTransparency
import UserMessagingPlatform
extension UIViewController {
static func getFrontViewController() -> UIViewController? {
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
let vc = keyWindow?.rootViewController
guard let _vc = vc?.presentedViewController else {
return vc
}
return _vc
}
}
public class UmpPlugins {
public static func requestIDFA() {
if #available(iOS 14, *) {
// UMPRequestParameters
let parameters = UMPRequestParameters()
// 許諾年齢未満であるか?
parameters.tagForUnderAgeOfConsent = false
// 事前許諾プロンプトの提示状況をリクエスト
// メインスレッドで呼ぶ必要あり
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
with: parameters,
completionHandler: { error in
if let error = error {
// エラー
debugPrint(error.localizedDescription)
} else {
// 事前許諾プロンプトが利用可能かチェック
let formStatus = UMPConsentInformation.sharedInstance.formStatus
// UMPFormStatus.unknown:0 不明
// UMPFormStatus.available:1 利用可能
// UMPFormStatus.unavailable:2 利用不可
if formStatus == .available {
DispatchQueue.main.async {
// プロンプトをロード
UmpPlugins.loadIDFA()
}
}
}
}
)
}
}
private static func loadIDFA() {
// プロンプトの提示が必要
guard let vc = UIViewController.getFrontViewController() else {
return
}
UMPConsentForm.loadAndPresentIfRequired(from: vc)
}
}
@_cdecl("requestIDFA")
public func requestIDFA()
{
return UmpPlugins.requestIDFA()
}
定義側 2️⃣
⚠️ Assets > Editor
に配置する。
#if UNITY_IOS
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using UnityEngine;
public class AddElementsInfoplist
{
[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath)
{
// Info.plist に Privacy - Tacking Usage Description(NSUserTrackingUsageDescription)を追加する(ステップ2)
string infoPlistPath = buildPath + "/Info.plist";
PlistDocument infoPlist = new PlistDocument();
infoPlist.ReadFromFile(infoPlistPath);
PlistElementDict root = infoPlist.root;
root.SetString("NSUserTrackingUsageDescription", "あなた様の好みに合わせた広告を表示するために使用されます!!!!");
infoPlist.WriteToFile(infoPlistPath);
// PBXProjectクラスというのを用いてAppTrackingTransparency.frameworkを追加していきます(ステップ3)
string pbxProjectPath = PBXProject.GetPBXProjectPath(buildPath);
PBXProject pbxProject = new PBXProject();
pbxProject.ReadFromFile(pbxProjectPath);
string targetGuid = pbxProject.GetUnityFrameworkTargetGuid();
pbxProject.AddFrameworkToProject(targetGuid, "AppTrackingTransparency.framework", true);
pbxProject.WriteToFile(pbxProjectPath);
}
}
#endif
定義側 3️⃣
using System.Runtime.InteropServices;
public class ShowAttDialog
{
#if UNITY_IOS
[DllImport("__Internal")]
private static extern int requestIDFA();
//public staticにしているのd外部ファイルで「ShowAttDialog.RequestIDFA()」とすれば呼び出せます
public static void RequestIDFA()
{
requestIDFA();
}
#endif
}
呼び出し側
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using EasyMobile;
using UnityEngine.SceneManagement;
public class AwakeManager : MonoBehaviour
{
private void Awake()
{
#if UNITY_IOS
ShowAttDialog.RequestIDFA();
#endif
}
}
Package Manager の Localization に NSUserTrackingUsageDescription を設定しておく
6. 🔨 iOS build 対応
全て ENABLE_BITCODE = NO
にする必要がある。以下のファイルをAssets/Editor
内に設定する。
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.IO;
public class OnPostBuildProcess : MonoBehaviour
{
[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget buildTarget, string path)
{
if (buildTarget == BuildTarget.iOS)
{
processForiOS(path);
}
}
static void processForiOS(string path)
{
string pbxPath = PBXProject.GetPBXProjectPath(path);
PBXProject pbx = new PBXProject();
pbx.ReadFromString(File.ReadAllText(pbxPath));
string target = pbx.GetUnityMainTargetGuid();
pbx.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
target = pbx.GetUnityFrameworkTargetGuid();
pbx.SetBuildProperty(target, "ENABLE_BITCODE", "NO");
File.WriteAllText(pbxPath, pbx.WriteToString());
}
}
7. ⚙️ その他 Unity での設定項目
-
もちろん Target API Level を
Android 33
に設定 -
package manager
Unity Ads SDKに関する項目を削除(使わないから) -
app icon
の修正、特にadaptive icon
のデザイン - privacy policy URL をアプリ内に追記
-
Package Manager
>Localization
を導入して l10n の実装 - Twitter icon を 𝕏 icon に変更
- Instagram URL -> TikTok URL に変更
できれば
-
in-app-purchase
機能の追加
8. 🌐 Web上での対応
- Admob のメディエーション紐付け
- データセーフティの申告
できれば
- Admob の GDPR 画面を設定
おしまい
おつです。