快手小程序-实现插屏广告的功能
1.快手小程序插屏广告官方文档链接:https://open.kuaishou.com/docs/develop/api-next/ad/ks.createInterstitialAd.html
2.ks.getEnterOptionsSync api的官方文档链接:https://open.kuaishou.com/docs/develop/api-next/basic/app/ks.getEnterOptionsSync.html
快手官方说明调用插屏广告的时候为了用户的体验,不能一进页面就显示广告,需要获取广告显示的时间,也就是ks.getEnterOptionsSync 这个api,在这个最早显示时间之后才能进行展示广告。
直接上代码,在插屏广告的js文件中:
javascript
let interstitialAd = null;
let appLaunchTime = 0;
let minDisplayTimestamp = 0;
page({
async onLoad(options) {
// 记录应用启动时间(如果还没有记录)
if (!appLaunchTime) {
appLaunchTime = Date.now();
}
// 获取启动参数中的最小展示时间
try {
const time = ks.getEnterOptionsSync();
minDisplayTimestamp = time.minDisplayTimestamp || 0;
} catch (err) {
minDisplayTimestamp = 0;
}
},
onUnload() {
interstitialAd?.destroy();
interstitialAd = null;
},
// 检查是否到达可展示时间
checkAdDisplayTime() {
const now = Date.now();
// 如果 minDisplayTimestamp 存在且大于当前时间,说明还不能展示
if (minDisplayTimestamp && minDisplayTimestamp > now) {
const waitTime = minDisplayTimestamp - now;
// console.log(`需要等待 ${waitTime}ms 后才能展示广告`);
return waitTime;
}
// 默认最小等待时间(应用启动后至少5秒,页面加载后至少3秒)
const minWaitAfterLaunch = 5000; // 5秒
const timeSinceLaunch = now - appLaunchTime;
if (timeSinceLaunch < minWaitAfterLaunch) {
const waitTime = minWaitAfterLaunch - timeSinceLaunch;
// console.log(`应用启动后需要等待 ${waitTime}ms`);
return waitTime;
}
return 0; // 可以立即展示
},
// 加载插屏广告(优化版)
adshowLoad() {
return new Promise((resolve, reject) => {
// 如果已有实例,先检查是否已加载
if (interstitialAd) {
// 尝试调用 load 确保广告已加载
interstitialAd.load()
.then(() => {
// console.log('插屏广告已重新加载');
resolve(true);
})
.catch((err) => {
// console.log('插屏广告重新加载失败,创建新实例');
// 如果加载失败,销毁旧实例,创建新的
interstitialAd.destroy();
interstitialAd = null;
this.createInterstitialAd(resolve, reject);
});
return;
}
// 创建新的广告实例
this.createInterstitialAd(resolve, reject);
});
},
// 创建插屏广告实例
createInterstitialAd(resolve, reject) {
interstitialAd = ks.createInterstitialAd({
type: 100033847,
unitId: 100176781,
});
let isResolved = false;
interstitialAd.onLoad(() => {
// console.log('插屏广告加载成功');
if (!isResolved) {
isResolved = true;
resolve(true);
}
});
interstitialAd.onError(({ errCode, errMsg }) => {
// console.error('插屏广告加载失败:', errCode, errMsg);
if (!isResolved) {
isResolved = true;
reject(new Error(`错误码: ${errCode}, 错误信息: ${errMsg}`));
}
});
interstitialAd.onClose(() => {
// console.log('插屏广告已关闭');
// 广告关闭后延迟销毁
setTimeout(() => {
if (interstitialAd) {
interstitialAd.destroy();
interstitialAd = null;
}
}, 1000);
});
// 显式调用 load 方法加载广告
interstitialAd.load().catch((err) => {
// console.error('调用 load 方法失败:', err);
if (!isResolved) {
isResolved = true;
reject(err);
}
});
},
// 安全的广告展示方法
async safeShowInterstitialAd(retryCount = 0) {
const maxRetries = 3; // 最大重试次数
try {
// 1. 检查广告展示时机
const waitTime = this.checkAdDisplayTime();
if (waitTime > 0) {
// console.log(`广告展示时机未到,等待 ${waitTime}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
// 2. 加上用户自定义的延迟
// if (userDelay > 0) {
// console.log(`用户自定义延迟 ${userDelay}秒`);
// await new Promise(resolve => setTimeout(resolve, userDelay * 1000));
// }
// 3. 加载广告
await this.adshowLoad();
// 4. 广告加载成功后,再等待至少2秒(快手要求)
const minWaitAfterLoad = 2000; // 2秒
// console.log(`广告加载完成,等待 ${minWaitAfterLoad}ms 后展示`);
await new Promise(resolve => setTimeout(resolve, minWaitAfterLoad));
// 5. 再次检查时机(避免加载过程中时间变化)
const finalCheck = this.checkAdDisplayTime();
if (finalCheck > 0) {
// console.log(`最终检查,还需等待 ${finalCheck}ms`);
await new Promise(resolve => setTimeout(resolve, finalCheck));
}
// 6. 展示广告(捕获 show 方法的错误)
try {
await interstitialAd?.show();
return true;
} catch (showError) {
// show 方法也可能抛出 1006 错误
const showErrorMsg = showError.message || '';
const showErrorCode = showError.errorCode || '';
if ((showErrorCode === 1006 || showErrorMsg.includes('too early')) && retryCount < maxRetries) {
const retryDelay = (retryCount + 1) * 3000;
await new Promise(resolve => setTimeout(resolve, retryDelay));
// 递归重试
return await this.safeShowInterstitialAd( retryCount + 1);
}
// 其他错误直接抛出
throw showError;
}
} catch (error) {
console.error('展示广告失败:', error);
// 检查是否是 1006 错误(时间太早)
// const errorMsg = error.message || error.errMsg || '';
const errorCode = error.errorCode || '';
if ((errorCode === 1006) && retryCount < maxRetries) {
const retryDelay = (retryCount + 1) * 3000; // 每次重试增加3秒延迟
await new Promise(resolve => setTimeout(resolve, retryDelay));
// 递归重试
return await this.safeShowInterstitialAd( retryCount + 1);
}
return false;
}
},
// 在你的业务逻辑中调用
async showRewardedVideoAd() {
// 使用安全的广告展示方法
const success = await this.safeShowInterstitialAd();
},
})
