快手小程序-实现插屏广告的功能

快手小程序-实现插屏广告的功能

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();
  },
})
相关推荐
2501_920931703 小时前
React Native鸿蒙跨平台采用ScrollView的horizontal属性实现横向滚动实现特色游戏轮播和分类导航
javascript·react native·react.js·游戏·ecmascript·harmonyos
0思必得04 小时前
[Web自动化] Selenium处理动态网页
前端·爬虫·python·selenium·自动化
东东5165 小时前
智能社区管理系统的设计与实现ssm+vue
前端·javascript·vue.js·毕业设计·毕设
catino5 小时前
图片、文件的预览
前端·javascript
2501_920931706 小时前
React Native鸿蒙跨平台实现推箱子游戏,完成玩家移动与箱子推动,当所有箱子都被推到目标位置时,玩家获胜
javascript·react native·react.js·游戏·ecmascript·harmonyos
layman05287 小时前
webpack5 css-loader:从基础到原理
前端·css·webpack
半桔7 小时前
【前端小站】CSS 样式美学:从基础语法到界面精筑的实战宝典
前端·css·html
AI老李7 小时前
PostCSS完全指南:功能/配置/插件/SourceMap/AST/插件开发/自定义语法
前端·javascript·postcss
_OP_CHEN7 小时前
【前端开发之CSS】(一)初识 CSS:网页化妆术的终极指南,新手也能轻松拿捏页面美化!
前端·css·html·网页开发·样式表·界面美化
啊哈一半醒7 小时前
CSS 主流布局
前端·css·css布局·标准流 浮动 定位·flex grid 响应式布局