✨
EXPOでATT許諾(iOS)が表示されない場合の対処法
はじめに
iOSにおいてApp Tracking Transparency(ATT)許諾プロンプトが表示されない問題について、解決方法を解説します。
問題
1. ios.infoPlist.NSUserTrackingUsageDescriptionに記載していない
ATT許諾プロンプトを表示するためには、app.json
等でios.infoPlist.NSUserTrackingUsageDescription
を記載する必要があります。
これがないとプロンプトが表示されません。
2. アプリがアクティブ状態でないとATT許諾プロンプトが表示されない
ATT許諾プロンプトは、アプリがアクティブな状態でなければ表示されません。したがって、アプリの初期化時にこのプロンプトを表示する場合、アプリがアクティブであることを確認する必要があります。
解決方法
1. NSUserTrackingUsageDescriptionの記載
まず、必要なパッケージをインストールします。
npx expo install expo-tracking-transparency
次に、app.json
or app.config.js
or app.config.ts
のいずれかにNSUserTrackingUsageDescriptionを記載します。
expo-tracking-transparencyプラグインの設定も必要です(たぶん)
app.config.ts
export default (): ExpoConfig => ({
// ...other
ios: {
infoPlist: {
NSUserTrackingUsageDescription:
"広告表示にのみ使用されます。許可しなくても機能制限等はございません。",
},
},
plugins: [
"expo-router",
[
"expo-tracking-transparency",
{
userTrackingPermission:
"広告表示にのみ使用されます。許可しなくても機能制限等はございません。",
},
],
],
});
2. アクティブ状態の確認と初期化
以下のカスタムフックを使用して、アプリがアクティブな状態であることを確認してからATT許諾プロンプトを表示します。
useAppInitialization
export const useAppInitialization = () => {
// AppStateの現在の状態を保持するためのref
const appState = useRef(AppState.currentState);
// アプリがアクティブかどうかを管理するstate
const [isActiveApp, setIsActiveApp] = useState<boolean>(
appState.current === "active",
);
// アプリの状態が変更されたときに実行
useEffect(() => {
// AppStateの変更を監視するリスナーを追加
const subscription = AppState.addEventListener("change", (nextAppState) => {
appState.current = nextAppState; // 現在の状態を更新
setIsActiveApp(appState.current === "active"); // アプリがアクティブかどうかを更新
});
return () => subscription.remove();
}, []);
// アプリが初期化されたかどうかを管理するstate
const [isInitializedApp, setIsInitializedApp] = useState<boolean>(false);
// アプリの初期化処理
useEffect(() => {
const initializeApp = async () => {
try {
// ATT許諾プロンプトを表示して許可を求める
await requestTrackingPermissionsAsync();
// 初期化が完了したことを示すためにstateを更新
setIsInitializedApp(true);
} catch (e) {
console.warn(e);
}
};
// アプリがアクティブな場合に初期化処理を実行
if (isActiveApp) {
initializeApp();
}
}, [isActiveApp]);
return {
isInitializedApp,
};
};
以下のコードをapp/_layout.tsx
に記載して、useAppInitializationフックを利用し、アプリの初期化が完了するまでコンポーネントのレンダリングを遅延させます。
app/_layout.tsx
export default function RootLayout() {
const { isInitializedApp } = useAppInitialization();
if (!isInitializedApp) {
return null;
}
return (
<ThemeProvider>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
</ThemeProvider>
);
}
おわりに
以上の手順を踏むことで、ATT許諾プロンプトが正しく表示されるようになります。
Discussion