// import gameConfig from "../../../config/gameConfig"; // import { // authorizeParams, // getUserInfoParams, // loadParams, // loginParams, // MiniGameApiBase, // ModalParams, // recordedGameScreenParams, // toastParams // } from "../miniGameBase/miniGameApiBase"; import { sys, Vec2, Node } from "cc"; import { MiniGameApiBase, getUserInfoParams, toastParams, loadParams, ModalParams, authorizeParams, loginParams, recordedGameScreenParams } from "./MiniGameApiBase"; import { GameCfg } from "../Config/GameCfg"; export interface TtRewardedVideoAdParam { // 名称 数据类型 属性 默认值 描述 adUnitId: string; //required 广告位 id } export interface TtVideoAd { // 通过 load 方法主动预加载广告内容。 // 此外,在显示广告出现问题时也可以尝试主动 load 一次。 // 该方法返回一个 Promise,如果广告已经自动拉取成功,调用该方法返回一个 resolved Promise; load: () => Promise; // 广告创建后默认是隐藏的,可以通过该方法显示广告。 该方法返回一个 Promise 对象。当广告组件正常获取素材时,该 Promise 对象会是一个 resolved Promise。当广告组件发生错误时,会是一个 rejected Promise,参数与error事件监听器获得的参数相同。 show: () => Promise; //绑定 load 事件的监听器,用户在手动调用 load 方法后,广告组件会预先加载。 广告组件成功拉取广告素材时会触发load事件的监听器。 //确保监听此事件时,开发者主动调用过 load 方法。 onLoad: (listener: Function) => void; // 解除绑定 load 事件的监听器。 offLoad: (listener: Function) => void; //绑定 error 事件的监听器。 广告组件拉取广告素材和其他情况下如果发生错误,会触发error事件的监听器。监听器会获得一个包含errCode和errMsg属性的对象参数。 // errCode 详情 onError: (listener: (error: any) => void) => void; // 解除绑定 error 事件的监听器。 offError: (listener: Function) => void; // 绑定 close 事件的监听器。 当用户点击了 Video 广告上的关闭按钮时,会触发close事件的监听器。监听器会获得一个包含isEnded属性的对象参数,表征用户是否完整观看了视频。 onClose: (listener: (res: { isEnded: boolean }) => void) => void; //解除绑定 close 事件的监听器。 offClose: (listener: Function) => void; // destroy: () => Promise; } const tt: any = window['tt']; export default class TtApi extends MiniGameApiBase { protected m_AppId: string = "tt20b55608bf84081c02"; protected m_Secret: string = ""; protected m_VideoAdIdIndex: number = 0; protected m_VideoAdIdList: string[] = ["23h6nffncfjm20ki5m"]; protected m_BannerAdIdIndex: number = 0; protected m_BannerAdId: string[] = []; protected m_InsertAdIdIndex: number = 0; protected m_InsertAdId: string[] = ["5ch1ssjoa29pmbe0me"]; protected m_videoAd: TtVideoAd = undefined; protected m_BannerAd: unknown = undefined; /** 录屏管理器 */ protected m_gameRecorder: any = null; validAppId(): void { console.log("tt-api-validAppId"); } ready(): void { if (GameCfg.SYSTEM_LOG) console.log("tt-api-ready"); this.m_gameRecorder = tt.getGameRecorderManager(); } getUserInfo(params: getUserInfoParams): void { tt.getUserInfo(params); } showToast(params: toastParams): void { tt.showToast(params); } showLoading(params: loadParams): void { tt.showLoading(params); } hideLoading(): void { tt.hideLoading(); } showModal(params: ModalParams): void { tt.showModal(params); } authorize(params: authorizeParams): void { params.success && params.success(); } login(params: loginParams): void { tt.login(params); } checkScene(successCB: Function, errorCB?: Function) { tt.checkScene({ scene: "sidebar", success: (res) => { console.log("check scene success: ", res.isExist); successCB && successCB() //成功回调逻辑 }, fail: (res) => { console.log("check scene fail:", res); //失败回调逻辑 errorCB && errorCB() } }); } navigateToScene(successCB: Function, errorCB?: Function) { tt.navigateToScene({ scene: "sidebar", success: (res) => { console.log("navigate to scene success"); // 跳转成功回调逻辑 successCB && successCB() }, fail: (res) => { console.log("navigate to scene fail: ", res); // 跳转失败回调逻辑 errorCB && errorCB() }, }); } getVideoAdId(): string { const id: string = this.m_VideoAdIdList[this.m_VideoAdIdIndex]; this.m_VideoAdIdIndex++; if (this.m_VideoAdIdIndex >= this.m_VideoAdIdList.length) { this.m_VideoAdIdIndex = 0; } return id; } loadAndShowVideoAd(successCB: () => void, errorCB?: (error: any) => void, completeCB?: () => void, reportAnalyticsExplain?: string): void { this.showLoading({ title: '请求中', mask: true }); const videoAdId = this.getVideoAdId(); console.log('tt 视频广告', videoAdId, reportAnalyticsExplain); //创建 视频 const videoAd: TtVideoAd = tt.createRewardedVideoAd({ adUnitId: videoAdId, }); //监听 视频关闭 let onCloseVideoAd = (res) => { // videoAd.offClose(onCloseVideoAd); console.log('tt 视频广告关闭', res); if (res && res.isEnded) { // 给予奖励 successCB(); // HttpRequest.post("https://game.renyouwangluo.cn/prod-api/ruoyi-ticktok/ticktok/Video_Message", { "openid": User.userData.openid, "mp_id": "tt833cf5811c08369602" }) // .then(() => { // console.log("上报一次!!!!") // }) // .catch(() => { // console.log("上报异常!!!!") // }); } else { errorCB('视频中途退出'); } completeCB && completeCB(); }; //重试 let onTryAgain = (e: any) => { videoAd.load().then(() => { videoAd.show().then(() => { this.hideLoading(); videoAd.onClose(onCloseVideoAd); }).catch((e) => {//展示异常 errorCB && errorCB('视频展示异常'); completeCB && completeCB(); }); }).catch((e) => {//加载异常 errorCB && errorCB('视频拉取异常02'); completeCB && completeCB(); }); } console.log('展示一次'); videoAd.load().then(() => { videoAd.show().then(() => { this.hideLoading(); videoAd.onClose(onCloseVideoAd); //展示异常 }).catch((e) => { console.log('重试一次'); onTryAgain(e); }) }).catch((e) => {//加载异常 errorCB && errorCB('视频拉取异常01'); completeCB && completeCB(); }); } getInsertAdId(): string { const id: string = this.m_InsertAdId[this.m_InsertAdIdIndex]; this.m_InsertAdIdIndex++; if (this.m_InsertAdIdIndex >= this.m_InsertAdId.length) { this.m_InsertAdIdIndex = 0; } return id; } showInsertAd(onAdClose: () => void, onFailed: () => void): void { console.log("加抖音 插屏 广告"); const adId = this.getInsertAdId(); let insertAd = tt.createInterstitialAd({ adUnitId: adId, }); insertAd.load(); insertAd.onLoad(() => { console.warn('插屏广告 加载完成'); insertAd.show().catch((err) => { console.warn('插屏广告 显示失败 :' + JSON.stringify(err)); insertAd.destroy(); insertAd = null; if (onFailed) { onFailed(); } }); }); insertAd.onError((err) => { console.warn('插屏广告 加载失败' + JSON.stringify(err)); insertAd.destroy(); insertAd = null; if (onFailed) { onFailed(); } }); insertAd.onClose(() => { console.warn('插屏广告 关闭'); if (insertAd != null) { insertAd.destroy(); insertAd = null; } if (onAdClose) { onAdClose(); } }); } getBannerAdId(): string { const id: string = this.m_BannerAdId[this.m_BannerAdIdIndex]; this.m_BannerAdIdIndex++; if (this.m_BannerAdIdIndex >= this.m_BannerAdId.length) { this.m_BannerAdIdIndex = 0; } return id; } showBannerAD(node: Node, successCB?: () => void, errorCB?: (error: any) => void, onCloseCB?: () => void, setBannerPos?: ({ screenWidth, screenHeight }: { screenWidth: any; screenHeight: any; }) => Vec2): void { } hideBanner() { // if (this.m_BannerAd != null) { // this.m_BannerAd.hide(); // } } protected m_gameRecordDate: number = 0; protected m_gameRecordUrl: string = undefined; recordedGameScreenStart(params: recordedGameScreenParams, onStart?: (res: any) => void): void { this.m_gameRecordDate = Date.now(); this.m_gameRecordUrl = null; this.m_gameRecorder.onStart((res) => { console.log('tt 录屏开始', res); onStart && onStart(res); }); this.m_gameRecorder.onStop((res: any) => { console.log('tt 录屏结束', res.videoPath); this.m_gameRecordUrl = res.videoPath; }); this.m_gameRecorder.start(params); } recordedGameScreenStop() { if (Date.now() - this.m_gameRecordDate < 3500) { return false; } this.m_gameRecorder.stop(); return true; } shareRecordedGameScreen(successCb?: () => void, failCb?: (e?: any) => void): void { if (this.m_gameRecordUrl) { tt.shareAppMessage({ channel: "video", // 转发内容类型 title: GameCfg.appName, desc: GameCfg.GAME_VIDEO_SHARE_DESC, extra: { hashtag_list: [GameCfg.appName], videoPath: this.m_gameRecordUrl, // 可替换成录屏得到的视频地址 videoTopics: [GameCfg.appName], video_title: GameCfg.GAME_VIDEO_SHARE_TITLE, withVideoId: true, defaultBgm: '', }, success: (res) => { // let shareGameRecord = getShareGameRecordReportData('分享成功'); // this.reportAnalytics(shareGameRecord.key, shareGameRecord.obj); console.log("tt 分享视频成功"); // console.log(res.videoId); console.log(res.shareWithShareBgmStatus); //回调参数 console.log("分享视频成功 4"); successCb && successCb(); }, fail: (e) => { // let shareGameRecord = getShareGameRecordReportData('分享失败'); // this.reportAnalytics(shareGameRecord.key, shareGameRecord.obj); console.log("tt 分享视频失败", e); failCb && failCb(e) } }); } else { failCb && failCb(null); console.log("tt 分享视频为空"); } } isHaveRecordedGameScreen(): boolean { return true; } getStorageSync(key: string) { let data = null; if (sys.isMobile) { if (window["tt"]) { try { data = window["tt"].getStorageSync(key) data = data == "" ? null : data } catch (error) { console.log(`get Storage ${key} fail`) } } } else { data = sys.localStorage.getItem(key) } return data } removeStorage (key?: string) { if (!key) { if (sys.isMobile) { if (window["tt"]) { window["tt"].clearStorage() } } else { sys.localStorage.clear() } } else { if (sys.isMobile) { if (window["tt"]) { window["tt"].removeStorage({ key: key }) } } else { sys.localStorage.removeItem(key); } } } getDeviceInfo(): any { if (window["tt"]) { let obj: any = window["tt"].getSystemInfoSync() return obj.model } let str: string = navigator.userAgent let res: RegExpMatchArray = str.match(/ipad/i) console.log("userAgent: ", str) if (res) return "ipad" if (sys.isBrowser && sys.os == sys.OS.IOS) { res = str.match(/iphone/i) if (res) return "iphone" if (window.screen.height > window.screen.width) return "ipad" return "mac" } return "" } setUnlockAllTime(time: number) { if (sys.isMobile) { if (window["tt"]) { window["tt"].setStorage({ key: "unit_unlock_all", data: time, success(res) { console.log("set unit_unlock_all success: ", res.data) }, fail(res) { console.log("set unit_unlock_all fail", res); } }) } } else { sys.localStorage.setItem("unit_unlock_all", time) } } getUnlockAllTime(call: Function) { if (sys.isMobile) { if (window["tt"]) { window["tt"].getStorage({ key: "unit_unlock_all", success(res) { console.log("get unit_unlock_all success: ", res) if (call) call(res.data); }, fail(res) { console.log("get unit_unlock_all fail: ", res) if (call) call(); } }) } else { if (call) call(); } } else { if (call) call(sys.localStorage.getItem("unit_unlock_all")) } } setUnitState(state?: string) { if (sys.isMobile) { if (window["tt"]) { window["tt"].setStorage({ key: "unit_state", data: state, success(res) { console.log("set unit_state success: ", res.data) }, fail(res) { console.log("set unit_state fail", res); } }) } } else { sys.localStorage.setItem("unit_state", state) } } /** * 打点 * @param eventName 事件名,注意不能超过 110 字符 * @param data 上报的数据 可选 {} */ reportAnalytics(eventName: string, data: { [key: string]: number | string | boolean } = {}) { if (window["tt"]) { window["tt"].reportAnalytics(eventName, data || {}); } } setSoundInfo(sound?: boolean, music?: boolean) { if (sys.isMobile) { if (window["tt"]) { window["tt"].setStorage({ key: "sound", data: JSON.stringify({ sound: sound, music: music }), success(res) { console.log("set sound success: ", res) }, fail(res) { console.log("set sound fail", res); } }) } } else { sys.localStorage.setItem("sound", JSON.stringify({ sound: sound, music: music })) } } async getLaunchOptionsSync(): Promise { return new Promise((resolve) => { const options = tt.getLaunchOptionsSync(); resolve(options); }); } }