import { useState, useCallback, useRef, useEffect } from 'react'; import { createPlatformFactory, RewardedVideoAd, RewardedVideoCloseCb, RewardedVideoErrorCb } from "../platforms"; // 广告奖励回调函数类型 type AdRewardCallback = () => void; // 广告 Hook 返回接口 interface UseAdReturn { showAd: () => void; loadAd: () => void; loading: boolean; adAvailable: boolean; // 广告是否可用 } // 广告 Hook 配置选项 interface UseAdOptions { onReward?: AdRewardCallback; // 观看完整广告后的奖励回调 onClose?: (isEnded: boolean) => void; // 广告关闭回调,传入是否完整观看 } // 创建平台广告实例 export function useAd(options?: UseAdOptions): UseAdReturn { const factory = createPlatformFactory() const [loading, setLoading] = useState(true); const [adAvailable, setAdAvailable] = useState(false); const [adLoaded, setAdLoaded] = useState(false); // 广告是否已加载完成 const adRef = useRef(null); const platform = factory.getPlatform() // 检查当前平台是否支持广告 const isAdSupportedPlatform = platform === 'bytedance'; useEffect(() => { // 如果当前平台不支持广告,直接设置为不可用状态 if (!isAdSupportedPlatform) { console.log(`当前平台 ${platform} 未开通广告,跳过广告初始化`); setAdAvailable(false); setLoading(false); return; } try { adRef.current = factory.createRewardedVideoAd(); const ad = adRef.current!; // 检查广告是否可用 if (ad.canUse && !ad.canUse()) { console.warn('广告功能不可用,可能是流量主未开通'); setAdAvailable(false); setLoading(false); return () => { }; // 返回空的清理函数 } setAdAvailable(true); // 广告关闭回调处理 const onClose: RewardedVideoCloseCb = (res) => { console.log('广告关闭:', res); setLoading(false); // 广告播放后需要重新加载 setAdLoaded(false); if (adRef.current) { console.log('广告播放结束,重新加载下一个广告'); adRef.current.load(); } // 判断用户是否完成播放 const isEnded = Boolean(res?.isEnded); if (isEnded) { // 播放完成的业务逻辑 console.log('用户观看完整广告,给予奖励'); // 执行奖励回调 options?.onReward?.(); // 可以在这里处理以下业务: // 1. 发放奖励(积分、道具等) // 2. 解锁功能或内容 // 3. 统计完成观看数据 // 4. 触发下一步操作 } else { // 未完成播放的处理 console.log('用户未完整观看广告'); // 可以处理以下场景: // 1. 提示用户观看完整广告才能获得奖励 // 2. 记录未完成播放的统计 // 3. 可能的重试提示 } // 执行关闭回调,传入是否完整观看 options?.onClose?.(isEnded); } // 广告加载错误回调处理 const onError: RewardedVideoErrorCb = (res) => { console.error('广告错误:', res); setLoading(false); setAdLoaded(false); // 加载失败,重置加载状态 // 根据错误类型判断广告是否不可用 const errorCode = res?.errCode; if (errorCode && ['1004', '1008', '1009', 1004, 1008, 1009].includes(errorCode)) { console.warn('广告服务不可用,可能是流量主未开通或被暂停'); setAdAvailable(false); } } // 广告加载成功回调处理 const onLoad = () => { console.log('广告加载成功'); setLoading(false); setAdLoaded(true); // 标记广告已加载完成 } // 绑定广告事件监听 ad.onLoad(onLoad); ad.onClose(onClose); ad.onError(onError); // 立即预加载广告 console.log('开始预加载广告'); ad.load(); // 清理函数:组件卸载时移除事件监听和销毁广告实例 return () => { if (adRef.current) { adRef.current.offClose(onClose) adRef.current.offError(onError) adRef.current.offLoad(onLoad) adRef.current.destroy(); } }; } catch (error) { console.error('初始化广告失败:', error); setAdAvailable(false); setLoading(false); return () => { }; // 返回空的清理函数 } }, [options, isAdSupportedPlatform, platform]); // 显示广告方法 const showAd = useCallback(() => { // 如果当前平台不支持广告,直接给予奖励并触发关闭回调 if (!isAdSupportedPlatform) { console.log(`当前平台 ${platform} 未开通广告,直接给予奖励`); options?.onReward?.(); options?.onClose?.(true); // 模拟广告播放完成 return; } if (!adAvailable) { console.warn('广告不可用,跳过广告播放'); // 如果广告不可用,直接给予奖励 options?.onReward?.(); options?.onClose?.(true); // 模拟广告播放完成 return; } if (!adLoaded) { console.warn('广告尚未加载完成,请稍等'); // 广告还在加载中,先尝试重新加载 if (adRef.current) { console.log('重新加载广告'); adRef.current.load(); setLoading(true); } return; } if (adRef.current) { setLoading(true); try { adRef.current.show(); } catch (error) { console.error('显示广告失败:', error); setLoading(false); // 如果显示失败,也给予奖励作为降级处理 options?.onReward?.(); options?.onClose?.(true); // 模拟广告播放完成 } } }, [adAvailable, adLoaded, options, isAdSupportedPlatform, platform]); // 加载广告方法 const loadAd = useCallback(() => { // 如果当前平台不支持广告,直接跳过加载 if (!isAdSupportedPlatform) { console.log(`当前平台 ${platform} 未开通广告,跳过广告加载`); return; } if (adRef.current) { setLoading(true); setAdLoaded(false); // 重置加载状态 console.log('手动加载广告'); adRef.current.load(); } }, [isAdSupportedPlatform, platform]); return { showAd, loadAd, loading, adAvailable }; }