mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Update AdMob extension to handle Consent & Tracking Authorization on iOS (#7431)
* Admob will now initialize 2 seconds after the app loads, giving more control to when it starts. This is particularily helpful for App Store validations, with Tracking Authorization message. * New conditions are available to know AdMob initialization status: "AdMob initializing" and "AdMob Initialized". * New action to stop the auto-initialization: "Prevent AdMob auto initialization" and new action to trigger the initialization: "Initialize AdMob manually". * Typically, you'd prevent the initialization at the beginning of the scene, and trigger it manually when a user interacts with a button or something, so you can control when they'll see the consent messages.
This commit is contained in:
@@ -38,7 +38,7 @@ module.exports = {
|
||||
.setName('Consent Cordova plugin')
|
||||
.setDependencyType('cordova')
|
||||
.setExportName('cordova-plugin-consent')
|
||||
.setVersion('3.0.0-alpha.8')
|
||||
.setVersion('3.0.0-alpha.9')
|
||||
.onlyIfOtherDependencyIsExported('AdMob Cordova plugin');
|
||||
|
||||
extension
|
||||
@@ -93,6 +93,68 @@ module.exports = {
|
||||
.setIncludeFile('Extensions/AdMob/admobtools.js')
|
||||
.setFunctionName('gdjs.adMob.setTestMode');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'PreventAdmobAutoInitialization',
|
||||
_('Prevent AdMob auto initialization'),
|
||||
_(
|
||||
'Prevent AdMob from initializing automatically. You will need to call "Initialize AdMob" action manually.\n' +
|
||||
'This is useful if you want to control when the consent dialog will be shown (for example, after the user has accepted your game terms).'
|
||||
),
|
||||
_('Prevent AdMob auto initialization'),
|
||||
'',
|
||||
'JsPlatform/Extensions/admobicon24.png',
|
||||
'JsPlatform/Extensions/admobicon16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/AdMob/admobtools.js')
|
||||
.setFunctionName('gdjs.adMob.preventAdmobAutoInitialization');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'InitializeAdmob',
|
||||
_('Initialize AdMob manually'),
|
||||
_(
|
||||
'Initialize AdMob manually. This will trigger the consent dialog if needed, and then load the ads.\n' +
|
||||
'Use this action if you have disabled the auto init and want to control when the consent dialog will be shown.'
|
||||
),
|
||||
_('Initialize AdMob'),
|
||||
'',
|
||||
'JsPlatform/Extensions/admobicon24.png',
|
||||
'JsPlatform/Extensions/admobicon16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/AdMob/admobtools.js')
|
||||
.setFunctionName('gdjs.adMob.initializeAdmob');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
'AdmobInitializing',
|
||||
_('AdMob initializing'),
|
||||
_('Check if AdMob is initializing.'),
|
||||
_('AdMob is initializing'),
|
||||
'',
|
||||
'JsPlatform/Extensions/admobicon24.png',
|
||||
'JsPlatform/Extensions/admobicon16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/AdMob/admobtools.js')
|
||||
.setFunctionName('gdjs.adMob.isAdmobInitializing');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
'AdmobInitialized',
|
||||
_('AdMob initialized'),
|
||||
_('Check if AdMob has been initialized.'),
|
||||
_('AdMob has been initialized'),
|
||||
'',
|
||||
'JsPlatform/Extensions/admobicon24.png',
|
||||
'JsPlatform/Extensions/admobicon16.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/AdMob/admobtools.js')
|
||||
.setFunctionName('gdjs.adMob.isAdmobInitialized');
|
||||
|
||||
// App Open
|
||||
extension
|
||||
.addCondition(
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace gdjs {
|
||||
declare var admob: any;
|
||||
declare var cordova: any;
|
||||
declare var consent: any;
|
||||
|
||||
export namespace adMob {
|
||||
const logger = new gdjs.Logger('AdMob');
|
||||
@@ -108,26 +109,119 @@ namespace gdjs {
|
||||
let rewardedVideoRewardReceived = false; // Becomes true when the video is closed and the reward is received.
|
||||
let rewardedVideoErrored = false; // Becomes true when the video fails to load.
|
||||
|
||||
let npaValue = '0'; // TODO: expose an API to change this and also an automatic way using the consent SDK.
|
||||
let npaValue = '0'; // 0 means that the user has consented to personalized ads, 1 means that the user has not consented to personalized ads.
|
||||
|
||||
let setupTimeoutId: NodeJS.Timeout | null = null;
|
||||
|
||||
const askForConsentAndInitializeAdmob = async () => {
|
||||
if (admobStarted) {
|
||||
logger.warn('AdMob is already started.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isStarting) {
|
||||
logger.warn('AdMob is already starting.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.info('Starting AdMob.');
|
||||
isStarting = true;
|
||||
|
||||
if (cordova.platformId === 'ios') {
|
||||
try {
|
||||
/*
|
||||
trackingStatus:
|
||||
0 = notDetermined
|
||||
1 = restricted
|
||||
2 = denied
|
||||
3 = authorized
|
||||
*/
|
||||
let trackingStatus = await consent.trackingAuthorizationStatus();
|
||||
|
||||
// If tracking is not determined, we ask the user for tracking authorization.
|
||||
if (trackingStatus === 0) {
|
||||
trackingStatus = await consent.requestTrackingAuthorization();
|
||||
}
|
||||
|
||||
// If tracking is restricted or denied, we set npaValue to 1.
|
||||
if (trackingStatus === 1 || trackingStatus === 2) {
|
||||
npaValue = '1';
|
||||
}
|
||||
|
||||
// otherwise, we set npaValue to 0.
|
||||
npaValue = '0';
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
'Error while asking for tracking authorization, continuing:',
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// ConsentStatus:
|
||||
// Unknown = 0,
|
||||
// Required = 1,
|
||||
// NotRequired = 2,
|
||||
// Obtained = 3,
|
||||
const consentStatus = await consent.getConsentStatus();
|
||||
if (consentStatus === consent.ConsentStatus.Required) {
|
||||
await consent.requestInfoUpdate();
|
||||
}
|
||||
await consent.loadAndShowIfRequired();
|
||||
} catch (error) {
|
||||
logger.error('Error while asking for consent, continuing:', error);
|
||||
}
|
||||
|
||||
// We should be looking at canRequestAds to know if we can request ads or not.
|
||||
// But as we want to be able to test ads in debug or if the consent didn't work,
|
||||
// we ignore this value for now.
|
||||
// const canRequestAds = await consent.canRequestAds();
|
||||
if (true) {
|
||||
await admob.start();
|
||||
|
||||
logger.info('AdMob successfully started.');
|
||||
isStarting = false;
|
||||
admobStarted = true;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error while starting AdMob:', error);
|
||||
isStarting = false;
|
||||
admobStarted = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Admob initialization listener
|
||||
document.addEventListener(
|
||||
'deviceready',
|
||||
async () => {
|
||||
// Obtain user consent ?
|
||||
|
||||
logger.info('Starting AdMob.');
|
||||
isStarting = true;
|
||||
|
||||
await admob.start();
|
||||
|
||||
logger.info('AdMob successfully started.');
|
||||
isStarting = false;
|
||||
admobStarted = true;
|
||||
setupTimeoutId = setTimeout(async () => {
|
||||
isStarting = false; // Reset to false, as it will be set to true in askForConsentAndInitializeAdmob.
|
||||
await askForConsentAndInitializeAdmob();
|
||||
// Wait a bit before starting admob, to avoid the consent appearing too soon.
|
||||
}, 2000);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
export const preventAdmobAutoInitialization = () => {
|
||||
if (setupTimeoutId) {
|
||||
isStarting = false;
|
||||
clearTimeout(setupTimeoutId);
|
||||
setupTimeoutId = null;
|
||||
}
|
||||
};
|
||||
|
||||
export const initializeAdmob = async () => {
|
||||
preventAdmobAutoInitialization();
|
||||
await askForConsentAndInitializeAdmob();
|
||||
};
|
||||
|
||||
export const isAdmobInitialized = () => admobStarted;
|
||||
export const isAdmobInitializing = () => isStarting;
|
||||
|
||||
/**
|
||||
* Helper to know if we are on mobile and admob is correctly initialized.
|
||||
*/
|
||||
@@ -334,6 +428,7 @@ namespace gdjs {
|
||||
position: atTop ? 'top' : 'bottom',
|
||||
size: bannerRequestedAdSizeType,
|
||||
offset: 0,
|
||||
npa: npaValue,
|
||||
});
|
||||
|
||||
banner.on('load', () => {
|
||||
|
Reference in New Issue
Block a user