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

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

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();
  },
})
相关推荐
森林的尽头是阳光12 小时前
tree回显问题
javascript·vue.js·elementui
weixin_BYSJ198712 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
Highcharts.js13 小时前
如何下载使用Highcharts Grid 开发web可编辑表格
前端·人工智能·grid 表格·web 表格·在线编辑表格·highcharts表格安装·表格开发工具
用户629605932470513 小时前
从“浏览器根本区分不了”到真正实现:刷新不退出,关闭标签页自动退出,前端判断浏览器关闭和刷新
前端
qetfw13 小时前
MWU:Vue 3 + FastAPI 的 MaaFramework 跨平台 WebUI 源码
前端·vue.js·python·fastapi·开源项目·效率工具
mfxcyh13 小时前
Vue3+Ant Design Vue 实现手动异步文件上传(含大小校验、弹窗上传)
前端·javascript·vue.js
wordbaby13 小时前
Web端热敏标签打印完整解决方案(QZ Tray + 译维A42)
前端
swipe14 小时前
03|Axios 请求进了后端之后:Controller、Request、Response 是怎么接住它的?
前端·后端·全栈
meilindehuzi_a14 小时前
Vue3进阶基础:指令修饰符、v-model表单绑定、动态样式、计算属性与侦听器实战
前端·javascript·vue.js
csdn2015_14 小时前
vue 前端运行命令
前端·javascript·vue.js