最近、iOSではiOS14.5からApp Tracking Transparency(名称が長いのでこの先はATTと略す)に対応しないと完全にIDFAの取得ができなくなりました
iOS 14.5以上サポートしているアプリではATT対応はもちろん必要ですが、サードパーティ製の広告SDKを使わずに会社独自の広告配信基盤などを持っている場合は標準ライブラリを使って広告IDを取得するケースがあると思います (基本、広告SDKが内部的に広告IDをよしなに取得してくれてるイメージ)
両OS含めてFlutterで取得する場合はどうすればいいかと気になり、調べたので簡単にまとめてみます
環境
- Flutter 2.0.4
- Dart 2.12.2
広告ID取得のパッケージ
スコア高め(Pub Point 110 / Popularity 80以上)とNull Safety対応しているかの点で以下の2つかなと思いました
使い分けに関してですが
- AAIDを取得したい →
advertising_id
- (あんまりないケースだと思いますが) iOS 14未満で
ASIdentifierManager
クラスの有効フラグも使ってIDFAを取得したい →advertising_id
- iOS 14以上でIDFA取得したい →
app_tracking_transparency
ちなみに advertising_idパッケージも内部的にATT対応( requestTrackingAuthorization メソッド呼んでるなど)しているのでiOS 14でも使えます
大まかな違いがATTのAuthorizationStatus
がFlutter側で使えるか使えないかになります
AAIDの取得
以下のパッケージをインストールします
dependencies:
flutter:
sdk: flutter
advertising_id: ^2.0.0
有効フラグは AdvertisingId.isLimitAdTrackingEnabled
AAIDは AdvertisingId.id
で
それぞれの値が返ってくるので以下のコードで実現できます
final _notAdID = '取得失敗用文字列';
Future<String> _getAdIDByAndroidPlatform() async {
try {
final isTrackingEnable = await AdvertisingId.isLimitAdTrackingEnabled;
// 有効でなければ取得しない
if (isTrackingEnable != null && !isTrackingEnable) {
return _notAdID;
}
final aaid = await AdvertisingId.id(true); // Future型で返ってくる
if (aaid == null) {
return _notAdID;
} else {
return aaid;
}
} catch (e) {
print(e);
return _notAdID;
}
}
ビルドして確認する際は
端末の設定アプリ > Google > 広告 の画面のスイッチボタンでオプトイン/オプトアウトして確認してください
IDFAの取得
以下の広告IDを取得するパッケージと端末情報を取得するパッケージをインストールします
dependencies:
flutter:
sdk: flutter
app_tracking_transparency: ^2.0.0+1
device_info: ^2.0.0
Flutterで以下のようなOSを判定するコードは存在しますが、
if (Platform.isAndroid) {
// Android
} else if (Platform.isIOS) {
// iOS
} else {
// 他プラットフォーム (例 Webとか)
}
OSのバージョンまで判定するコードが標準にはないです
device_infoパッケージを使ってOSバージョンを取得できるので、それを使ってバージョン判定するコードを自作できます
iOSでは以下のコードで端末のOSバージョンを取得できます
Future<String> getIOSOSVersion() async {
try {
final iOSInfo = await DeviceInfoPlugin().iosInfo;
return iOSInfo.systemVersion;
} on PlatformException {
// 失敗
}
}
また、3桁のバージョン比較はこちらの記事が参考になるのでこの記事では割愛します
app_tracking_transparency
パッケージでは以下の3つのことができます
- IDFAの取得
AppTrackingTransparency.getAdvertisingIdentifier()
- ATTのステータス
AppTrackingTransparency.trackingAuthorizationStatus
- ATTのパーミッションリクエスト
AppTrackingTransparency.requestTrackingAuthorization()
以下のコードで場合分けして取得するのがいいと思います
final _zeroID = '00000000-0000-0000-0000-000000000000';
final _notAdID = '取得失敗用文字列';
Future<String> _getAdIDByIOSPlatform() async {
try {
final osVersion = await deviceInfoRepository.getIOSOSVersion();
// iOS 14.5以上なら
if (/*バージョン判定コード*/) {
final TrackingStatus trackStatus =
await AppTrackingTransparency.trackingAuthorizationStatus;
// 初めての場合はATTのパーミッションリクエスト
if (trackStatus == TrackingStatus.notDetermined) {
final status =
await AppTrackingTransparency.requestTrackingAuthorization();
if (status == TrackingStatus.authorized) {
return AppTrackingTransparency.getAdvertisingIdentifier();
} else {
return _notAdID;
}
}
}
// iOS 14 ~ 14.5未満なら
if (/*バージョン判定コード*/) {
final status =
await AppTrackingTransparency.trackingAuthorizationStatus;
if (status == TrackingStatus.notDetermined ||
status == TrackingStatus.authorized) {
return AppTrackingTransparency.getAdvertisingIdentifier();
} else {
return _notAdID;
}
}
// iOS 14.0未満のバージョンは
final idfa = await AppTrackingTransparency.getAdvertisingIdentifier();
// 取得失敗すると00000~~が返ってくる
if (_zeroID == idfa) {
return _notAdID;
} else {
return idfa;
}
} catch (e) {
print(e);
return _notAdID;
}
}
気を付けるポイントは ATTは使用できますが、iOS 14.0 ~ 14.5未満の間ならパーミッションリクエストしなくても端末の設定に応じてIDFAができます
オプトアウトしている場合は Tracking.denied
が返ってきます
iOS 14未満の場合は文字列の比較をしてあげるとよいです
オプトアウトしている場合にIDFA取得しようとすると0000~が返ってくるので、文字列一致の判定でオプトイン/オプトアウトの判定できます
また、ATTのパーミッションのリクエストする際はInfo.plistで文言の設定も必要になってくるので忘れずに設定しましょう
<dict>
<key>NSUserTrackingUsageDescription</key>
<string>IDFA取得しますよ</string>
</dict>
初めてリクエストする際はこのように表示されます
もし何か間違っている箇所があれば気軽にご指摘お願いします