Reputation: 1560
The solution mentioned here talks about how to set this up with the ATTrackingManager class, however, that is not exposed directly to React Native.
Using the react-native-tracking-transparency package is causing an issue for me at build time:
"Undefined symbols _RCTRegisterModule"
because it only works if you do not include use_flipper! in your podfile... so I am stuck and do not want to patch-package as recommended in solutions here (which imply a fix has already been merged, but I still see "Undefined symbols _RCTRegisterModule" when building with this...
Wondering if there is any wrapper for the ATTrackingManager class for React Native?
Upvotes: 9
Views: 12761
Reputation: 1014
Our team got reject from Apple because we use Firebase analytics.Apple asked to implement App Tracking Transparency alert. For request App Tracking Transparency permissions For React Native CLI,
Install react-native-permissions
3. Create firebase.json file in root folder
{
"react-native": {
"analytics_auto_collection_enabled": false
}
}
!Important ,if you need request other permissions ,for example for request push notifications add delay between requests, in other case you ll risk to get reject from Apple with explanation
Your app uses the AppTrackingTransparency framework, but we are unable to locate the App Tracking Transparency permission request
import { PERMISSIONS, request, RESULTS } from 'react-native-permissions';
const requestPermissionTransparency = async () => {
return await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY);
};
const delay = (ms: number | undefined) => new Promise((res) => setTimeout(res, ms));
export const usePermissions = () => {
const dispatch = useAppDispatch();
useEffect(() => {
(async () => {
await delay(1000); ==== //Important to add if you need other requset
if (IS_IOS) {
const result = await requestPermissionTransparency();
if (result === RESULTS.GRANTED) {
await firebase.analytics().setAnalyticsCollectionEnabled(true);
} else {
await firebase.analytics().setAnalyticsCollectionEnabled(false);
}
}
})();
}, [dispatch]);
};
Upvotes: 2
Reputation: 1560
Found a solution after asking some colleagues who have worked around this before and posting if anyone else is running into this issue...
in info.plist make sure to have a NSUserTrackingUsageDescription key. This is the text that shows when requesting permissions:
<key>NSUserTrackingUsageDescription</key>
<string>This app uses device identifiers to track marketing attribution and app usage. Your data is kept confidential and is not shared with any 3rd parties or advertising partners.</string>
Add the Tracking pod to your podfile:
platform :ios, '12.4'
target 'RNPath' do
config = use_native_modules!
use_frameworks!
...
# add next line
pod 'Permission-AppTrackingTransparency', :path => "#{permissions_path}/AppTrackingTransparency"
...
end
end
run pod install and pod update from the ios folder of your project to make that change take affect
cd ios && pod install && pod update
Then use the react-native-permissions package to request tracking permissions when app state becomes active
in App.js
.
.
.
import { PERMISSIONS, RESULTS, request } from 'react-native-permissions';
export default function () {
.
.
.
const handleAppStateChange = async (nextAppState) => {
if (nextAppState == 'active') {
request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY)
.then(async (result) => {
if (result == RESULTS.GRANTED) {
console.log('Tracking!');
// do something related to tracking
} else {
console.log('Not Tracking!');
}
})
.catch((error) => {
console.log('error in request tracking permissions: ', error);
});
}
}
useEffect(() => {
let subscription = AppState.addEventListener('change', handleAppStateChange);
return () => {
subscription.remove();
};
}, []);
.
.
.
return <App/>
This is nice because it is called every time the app is foregrounded the permission is re-checked so if they have enabled/disabled it from the phone's settings it will take notice and react accordingly.
Worth noting that this request fails if you don't make sure the application's state is "active" and if it is "backgrounded" or "inactive" it can return unavailable and then might never be presented to the user and stay in that state which is far less than ideal since it will never be allowed, so that's why I'm checking for "active" in that last code segment.
Upvotes: 7