当前位置: 首页 > news >正文

微信小程序和抖音小程序的分享和广告接入代码

开发完成小程序或者小游戏之后,我们为什么要接入分享和广告视频功能,主要原因有以下几个方面。

微信小程序和抖音小程序接入分享和广告功能主要基于以下几个原因:

  1. 用户获取与增长:分享功能可以帮助用户将小程序内容传播给更多人,从而扩大用户基础。通过社交网络的分享,能够吸引更多潜在用户使用小程序。

  2. 增强用户互动:分享功能可以提升用户之间的互动,增加用户粘性。用户在分享内容时,往往会带来新的使用场景和体验,这样可以促进用户的积极参与。

  3. 商业变现:广告功能为小程序提供了一种商业变现的方式。通过广告,开发者可以获得收入,从而支持小程序的持续运营与发展。

目前大部分小程序和小游戏都是靠广告变现,所以接入广告的代码是所有开发者必不可少的环节了,下面给大家讲解一下如何加入分享和广告接入的代码。

文章最后整合了一个工具类,有需要的朋友可以直接复制使用.

微信小程序

分享功能
  1. 在页面逻辑中设置分享:

  • 在小程序的页面代码中,使用 onShareAppMessage 函数设置分享内容:

  • 
    Page({  onShareAppMessage: function () {  return {  title: '分享标题',  path: '/pages/example/example?id=123',  imageUrl: '/images/share.png' // 可选  };  }  
    });

    2. 用户触发分享:

  • 可以在页面中添加一个分享按钮,使用 wx.showShareMenu 显示分享菜单:

  • 
    wx.showShareMenu({  withShareTicket: true // 可选,是否使用带分享票据的分享  
    });
    广告接入
  • 1,接入广告组件:
    • 在小程序的页面中引入广告组件,例如 banner 广告:

    • 
      <ad unit-id="你的广告位ID" />

      由于广告目前是各大平台的主要收入来源,所以微信和抖音都是花了很大的力气让开发者尽可能地简单接入广告代码。就这样一句代码,加到你的小程序里面,他就会源源不断地输送广告。

    • 输送的广告完全是依靠大数据,你喜欢看什么,就给你推什么广告。

        

2,初始化广告:

  • 在对应的 JavaScript 文件中,您可以监控广告加载事件:

  • 
    const adInstance = wx.createBannerAd({  adUnitId: '你的广告位ID',  style: {  left: 0,  top: 0,  width: 300  }  
    });  adInstance.onLoad(() => {  console.log('广告加载成功');  
    });  adInstance.onError((err) => {  console.error('广告加载失败', err);  
    });

    抖音小程序

    分享功能
  • 在页面中设置分享行为:

    • 在 页面 的 JS 文件中,使用 onShareAppMessage

    • 
      Page({  onShareAppMessage: function () {  return {  title: '抖音小程序分享',   path: '/pages/example/example?id=123',  };  }  
      });

      2.主动分享:

    • 通过按钮或其他触发事件调用 my.share 方法:

    • 
      my.share({  title: '分享标题',  url: '分享链接',  success: (result) => {  console.log(result);  },  fail: (error) => {  console.error(error);  }  
      });
      广告接入
    • 引入广告组件:

      • 在页面的 HTML 代码中添加广告组件:

      • 
        <ad unit-id="你的广告位ID" />

        广告初始化和监控:

        通过 JavaScript 控制广告的加载和监控

      • const ad = my.createBannerAd({  adUnitId: '你的广告位ID',  style: {  top: 0,  left: 0,  width: '100%',  },  
        });  ad.onLoad(() => {  console.log('广告加载成功');  
        });  ad.onError((err) => {  console.error('广告加载失败', err);  
        });

虽然看起来非常简单,但是实际上开发起来还是不方便,所以我写了一套完整的小游戏开发的工具类,满足了各大平台的要求.包括登录,分享,插屏广告,激励广告,banner广告,抖音侧边栏功能.

/*** 小游戏平台SDK工具封装,目前只支持微信和抖音平台*/
export namespace MiniGameSdk {interface ISize {width: number;height: number;}export interface IPosition {top: number;left: number;}export function isWechat(): boolean {//@ts-ignorereturn window.wx !== null && window.wx !== undefined;}export function isBytedance(): boolean {//@ts-ignorereturn window.tt !== null && window.tt !== undefined;}// 支付宝平台export function isAli(): boolean {//@ts-ignorereturn window.my !== null && window.my !== undefined;}function getSysWinSize(): ISize {let sys: any;if (isWechat()) {// @ts-ignoresys = wx.getSystemInfoSync();} else if (isBytedance()) {// @ts-ignoresys = tt.getSystemInfoSync();}let size: ISize = { width: 0, height: 0 };if (sys) {size.width = sys.windowWidth;size.height = sys.windowHeight;}return size;}/*** 插屏广告。微信抖音都支持!*/class ADInterstitial {private _adUid: string;private _interstitial: any;get aduid() {return this._adUid;}constructor(adUid: string) {this._adUid = adUid;}show() {// @ts-ignoreif (isWechat() && !wx.createInterstitialAd) {console.warn('wechat unsupport interstitial AD!');this._interstitial = null;return;}// @ts-ignoreif (isBytedance() && !tt.createInterstitialAd) {console.warn('bytedance unsupport interstitial AD!');this._interstitial = null;return;}if (this._interstitial) {this._interstitial.load();} else {if (isWechat()) {// @ts-ignorethis._interstitial = wx.createInterstitialAd({ adUnitId: this._adUid });} else if (isBytedance()) {// @ts-ignorethis._interstitial = tt.createInterstitialAd({ adUnitId: this._adUid });} else {this._interstitial = null;}this._interstitial?.onLoad(() => {console.log('load interstitial ad success');this._interstitial.show().catch((err: any) => {console.log('catch interstitial ad error:', err);});});this._interstitial?.onError((err: any) => {console.log('interstitial ad on error:', err);});}}destory() {this._interstitial?.destroy();}}class ADBanner {private _adUid: string;private _banner: any;get aduid() {return this._adUid;}/*** 抖音和微信都支持* 横幅广告。预估宽度默认为300,预估高度为140。如果你不确定就按默认值来。* @param adUid 广告UID,后端配置* @param isTop 是否在屏幕顶部展示。内部会自动居中计算位置。* @param bannerWidth 横幅广告的预估宽度。默认300* @param autoShow 广告加载完成后是否立刻显示,默认为不显示*/constructor(adUid: string, param: boolean | IPosition, bannerWidth: number = 300, autoShow: boolean = false) {this._adUid = adUid;this.create(autoShow, bannerWidth, param); // 默认300比较合适}private create(autoShow: boolean, bannerWidth: number, param: boolean | IPosition) {if (!isWechat() && !isBytedance()) {this._banner = null;return;}this.destroy();let winSize = getSysWinSize();let height = bannerWidth * 0.4;let top = 0, left = 0;if (typeof param === "boolean") {left = (winSize.width - bannerWidth) / 2top = param ? 5 : (winSize.height - height);} else {left = param.left;top = param.top;}let params = {adUnitId: this._adUid,adIntervals: 30,// 自动刷新频率不能小于30秒style: { left: left, top: top, width: bannerWidth }}if (isWechat()) {// @ts-ignorethis._banner = wx.createBannerAd(params);} else if (isBytedance()) {// @ts-ignorethis._banner = tt.createBannerAd(params);} else {this._banner = null;}this._banner?.onError((err: any) => {console.log('ad banner error:', err);});this._banner?.onLoad(() => {autoShow && this._banner.show();});}show() {this._banner?.show();}hide() {this._banner?.hide();}destroy() {this._banner?.destroy();}}class ADCustom {private _adUid: string;private _adCustom: any;get aduid() {return this._adUid;}/*** 由于原生模板广告在微信服务后端可以定制宽度大小,个数,缩放比例等,所以位置调整要根据设置的宽度来定。抖音不支持!* @param adUid 广告UID,后端配置* @param top 从左上角开始,距离屏幕顶部的距离。注意:这个数据为设备屏幕宽度width。如果需要获取屏幕的像素,需要乘以设备像素比Pixel-Ratio,例如iPhone 13 Pro的Pixel-Ratio为3,像素为Width*3。* @param left 从左上角开始,距离屏幕最左边的距离。注意:这个数据为设备屏幕宽度width。如果需要获取屏幕的像素,需要乘以设备像素比Pixel-Ratio,例如iPhone 13 Pro的Pixel-Ratio为3,像素为Width*3。* @param scale 原生模板广告的尺寸,默认为1,即100%。此值在微信服务后端广告中获得,默认为100%,目前有100%,90%,80%三种,一般情况不用修改。若有修改,记得传入值,例如90%就传入0.9。*/constructor(adUid: string, top: number = 0, left: number = 0, scale: number = 1.0) {this._adUid = adUid;this.createCustomAd(top, left, scale);}private createCustomAd(top: number, left: number, scale: number) {if (!isWechat()) { // only wechat support custom adthis._adCustom = null;console.log('Only wechat support Custom Ad');return;}this.destroy();// 原生模板5个应用宽度为375,若设置了缩放比例,则宽度也需要设置// let width = 375 * this._scale;// let newLeft = (sys.windowWidth - width) / 2;// let newTop = sys.windowHeight / 2; // 120是预估高度// @ts-ignorethis._adCustom = wx.createCustomAd({adUnitId: this._adUid,style: { left: left, top: top, fixed: true }});this._adCustom?.onError((err: any) => {console.log('ad custom error:', err);});}show() {this._adCustom?.show();}hide() {this._adCustom?.hide();}destroy() {this._adCustom?.destroy();}}/*** 视频广告用户点击行为结果*/export enum EAdVideoResult {/*** 用户看完了广告,游戏可发放奖励。*/ACCEPT,/*** 用户中途关闭了广告,即未看完状态。不可发放奖励。*/REJECT,/*** 广告组件内部发生了错误。不可发放奖励。*/ERROR,}class ADVideo {private _adUid: string;private _adVideo: any = null;get aduid() {return this._adUid;}constructor(adUid: string) {this._adUid = adUid;}/*** 由于微信和抖音视频广告机制不同,微信可以看的视频广告个数只有0和1个,抖音平台则可以看0~maxVideoCount* @param onResult 两个参数:第一个res是EAdVideoResult定义,第二count是用户看了多少个视频广告。* @param target onResult的拥有者* @param maxVideoCount 可以连续看最大视频个数,可最大化商业效率。默认为3个。* @returns */show(onResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3): void {let callback = (state: EAdVideoResult, count: number) => {onResult?.call(target, state, count);}if (!isWechat() && !isBytedance()) {callback(EAdVideoResult.ACCEPT, 1);this._adVideo = null;return;}let onAdVideoClosed = (res: any) => {this._adVideo?.offClose(onAdVideoClosed);if (isWechat()) {if (res && res.isEnded || res === undefined) {callback(EAdVideoResult.ACCEPT, 1);} else {callback(EAdVideoResult.REJECT, 0);}} else if (isBytedance()) {let resConverted = res as { isEnded: boolean, count: number };if (resConverted && resConverted.count > 0) {callback(EAdVideoResult.ACCEPT, resConverted.count);} else {callback(EAdVideoResult.REJECT, 0);}}}this._adVideo?.offClose(onAdVideoClosed);if (isWechat()) {// @ts-ignorethis._adVideo = wx.createRewardedVideoAd({adUnitId: this._adUid});} else if (isBytedance()) {// @ts-ignorethis._adVideo = tt.createRewardedVideoAd({adUnitId: this._adUid,multiton: true,multitonRewardMsg: ['多1次奖励', '再多一次奖励', '再多一次奖励'],multitonRewardTimes: maxVideoCount,});} else {this._adVideo = null;}this._adVideo?.onLoad(() => {console.log('Ad load success');});this._adVideo?.onError((err: { errMsg: string, errCode: number }) => {console.log('Ad video error:', err);callback(EAdVideoResult.ERROR, 0);});this._adVideo?.onClose(onAdVideoClosed);console.info("广告2");this._adVideo?.show().catch(() => {this._adVideo?.load().then(() =>this._adVideo?.show()).catch((err: { errMsg: string, errCode: number }) => {console.log('Catch video ad error:', err);callback(EAdVideoResult.ERROR, 0);});});}destory() {this._adVideo?.destory();}}export enum EAdBannerLocation {/*** 屏幕顶部*/TOP,/*** 屏幕底部*/BOTTOM,}export class AdvertManager {private static _instance: AdvertManager;static get instance(): AdvertManager {if (!AdvertManager._instance) {AdvertManager._instance = new AdvertManager();}return AdvertManager._instance;}private _video: ADVideo;private _interstitial: ADInterstitial;private _banner: ADBanner;private _customs: Record<string, ADCustom> = {};private constructor() {}/*** 预加载横幅广告,不会显示。只有你在调用showBanner时才会显示。* 可重复调用,但是会销毁上一次的实例。一般情况,全局有一个就行了,太多占用内存,而且没必要。* @param adUid 广告UID* @param location 位置有两种情况:1、可以传入枚举值,默认上方; 2、可以自定义位置传入IPosition,注意IPosition中的top和left跟平台的top,left是一致(没有乘以设备像素比ratio),需要开发者自己调试位置* @param scale 默认为跟屏幕一样的宽度,可以通过设置缩放比例来调整大小。当然,平台有规定最大或最小宽度,函数内部会自动计算。*/public loadBanner(adUid: string, location: EAdBannerLocation | IPosition = EAdBannerLocation.TOP, scale: number = 1.0) {this._banner?.destroy();let size: ISize = getSysWinSize();// 当 style.width 小于 300 时,会取作 300。 当 style.width 大于屏幕宽度时,会取作屏幕宽度。let width = size.width * scale;width = width < 300 ? 300 : width; // 最小值矫正width = width > size.width ? size.width : width; //最大值矫正this._banner = typeof location === 'number' ? new ADBanner(adUid, location === EAdBannerLocation.TOP, width, false) : new ADBanner(adUid, location, width, false);}/*** 显示横幅广告*/public showBanner() {if (this._banner) {this._banner.show();} else {console.warn('MiniGameSDK: banner is null, you must call loadBanner(...) first!');}}/*** 隐藏横幅广告*/public hideBanner() {this._banner?.hide();}/*** 弹出插屏广告* @param adUid 广告单元id*/public showInterstitial(adUid: string) {if (this._interstitial && this._interstitial.aduid === adUid) {this._interstitial.show();} else {this._interstitial?.destory();this._interstitial = new ADInterstitial(adUid);this._interstitial.show();}}/*** 加载原生模板广告,不会显示。只有你在调用showCustom时才会显示。* 由于原生模板广告在微信服务后端可以定制宽度大小,个数,缩放比例等,所以位置调整要根据设置的宽度来定。抖音不支持本函数,会调用无效!* @param adUid 广告ID* @param location 位置有两种情况:1、可以传入枚举值,默认上方; 2、可以自定义位置传入IPosition,注意IPosition中的top和left跟平台的top,left是一致(没有乘以设备像素比ratio),需要开发者自己调试位置* @param scale 缩放比例,默认是1,即不缩放。这个缩放并不是自己填,而是根据微信MP后台你配置的原生模板广告的缩放比例填,目前有100%,90%,80%三种,一般情况不用修改。若有后台修改,记得传入值,例如90%就传入0.9。*/public loadCustom(adUid: string, location: IPosition = { top: 0, left: 0 }, scale: number = 1) {// this._custom?.destroy();// this._custom = new ADCustom(adUid, location.top, location.left, scale);if (this._customs[adUid]) {console.log(`${adUid} has been loaded.`);return;}this._customs[adUid] = new ADCustom(adUid, location.top, location.left, scale);}/*** 显示自定义广告。* @param adUid 广告的唯一标识符。使用此标识符来查找和显示特定的自定义广告。* * 此方法尝试根据提供的adUid显示一个自定义广告。如果给定的adUid对应的自定义广告已加载,* 则调用该广告的显示方法。如果广告未加载,则在控制台输出警告信息。*/public showCustom(adUid: string) {if (this._customs[adUid]) {this._customs[adUid].show();} else {console.warn(`You have not load ${adUid} of Custom AD, can not show!`);}}/*** 隐藏指定的自定义广告单元* * 此方法用于隐藏通过广告单元标识符(adUid)指定的自定义广告。如果指定的广告单元已加载并显示,* 则将其隐藏;如果广告单元未加载,则在控制台输出警告信息。* * @param adUid 广告单元标识符,用于唯一标识一个自定义广告单元。*/public hideCustom(adUid: string) {if (this._customs[adUid]) {this._customs[adUid].hide();} else {console.warn(`You have not load ${adUid} of Custom AD, can not hide!`);}}/*** 由于微信和抖音视频广告机制不同,微信可以看的视频广告个数只有0和1个,抖音平台则可以看0~maxVideoCount* @param adUid 广告ID。如果与上一次UID不同,则内部会重新创建实例。开发者完全不用关心这个细节。* @param onVideoResult 两个参数:第一个res是EAdVideoResult定义,第二count是用户看了多少个视频广告。 * @param target onVideoResult的拥有者* @param maxVideoCount 最大视频个数。默认是3,仅对抖音平台生效。微信平台看完视频count的结果永远是1或0*/public showVideo(adUid: string, onVideoResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3) {if (this._video && this._video.aduid === adUid) {console.info('show','进来了');this._video.show(onVideoResult, target, maxVideoCount);} else {this._video?.destory();this._video = new ADVideo(adUid);this._video.show(onVideoResult, target, maxVideoCount);}}/*** 销毁内部所有实例,清空内存*/public destroyAll() {this._banner?.destroy();this._banner = null;this._interstitial?.destory();this._interstitial = null;this._video?.destory();this._video = null;if (this._customs) {for (let val in this._customs) {this._customs[val]?.destroy();}this._customs = {};}}}export enum EGameClubIcon {/** 绿色图标 */GREEN = 'green',/** 红色图标 */WHITE = 'white',/** 有黑色圆角背景的白色图标 */DARK = 'dark',/** 有白色圆角背景的绿色图标 */LIGHT = 'light'}export class GameClub {private static _instance: GameClub;static get instance(): GameClub {if (!this._instance) {this._instance = new GameClub();}return this._instance;}private _club: any;private constructor() {}/*** 创建游戏圈按钮* @param icon * @param position * @param size * @param openLink */create(icon: EGameClubIcon = EGameClubIcon.GREEN, position: IPosition = { top: 0, left: 0 }, size: ISize = { width: 40, height: 40 }, openLink?: string) {if (isWechat()) {// @ts-ignorethis._club = wx.createGameClubButton({icon: icon,style: {left: position.left,top: position.top,width: size.width,height: size.height},openlink: openLink});}}show() {this._club?.show();}hide() {this._club?.hide();}destory() {this._club?.destroy();}}/*** 振动类型*/export enum EVirbrateType {/*** 短振动*/SHORT,/*** 长振动*/LONG}/*** 平台常用API合集*/export class API {private static _loginCode: string = null;private static _loginAnonymousCode: string = null;private static _hasInitWechatCloudFunction: boolean = false;/*** 分享app给朋友,微信小游戏分享是没有onSuccess回调的。* @param title 标题* @param description 细节描述信息 * @param imageUrl 图片地址* @param query 查询信息* @param onSuccess 抖音会回调,微信不会回调*/static shareAppToFriends(title: string, description: string = '', imageUrl?: string, query?: string, onSuccess?: () => void) {if (isWechat()) {try {//@ts-ignorewx.shareAppMessage({title: title,imageUrl: imageUrl,query: query,});} catch (err) {console.log(`share faild: ${err}`);}}if (isBytedance()) {//@ts-ignoreconsole.info('字节分享方法');tt.shareAppMessage({title: title,desc: description,imageUrl: imageUrl ?? '',query: query ?? '',success(res: any) {console.log('share success:', res);onSuccess?.();},fail(res: any) {console.log('share fail:', res);}});}}/*** 显示提示信息* @param title 标题* @param duration 时长(单位:秒)* @returns */static showToast(title: string, duration: number = 2) {if (isWechat()) {// @ts-ignorewx.showToast({title: title,icon: 'success',duration: duration * 1000});}if (isBytedance()) {//@ts-ignorett.showToast({title: title,duration: duration * 1000,success(res: any) {console.log(`${res}`);},fail(res: any) {console.log(`showToast调用失败`);},});}}/*** 设备震动效果,默认为短震动。注意:可能一些机型不会生效,具体看平台方的说明* @param type MiniGameSdk.API.EVirbrateType*/static vibrate(type: EVirbrateType = EVirbrateType.SHORT) {if (isWechat()) {switch (type) {case EVirbrateType.SHORT://@ts-ignorewx.vibrateShort({success(res: any) {console.log('vibrate success:', res);},fail(res: any) {console.log('vibrateShort failed', res);},});break;case EVirbrateType.LONG://@ts-ignorewx.vibrateLong({success(res: any) {console.log('vibrate success', res);},fail(res: any) {console.log(`vibrateLong failed`, res);},});break;default:break;}}if (isBytedance()) {switch (type) {case EVirbrateType.SHORT://@ts-ignorett.vibrateShort({success(res: any) {console.log('vibrate success:', res);},fail(res: any) {console.log('vibrateShort failed', res);},});break;case EVirbrateType.LONG://@ts-ignorett.vibrateLong({success(res: any) {console.log('vibrate success', res);},fail(res: any) {console.log(`vibrateLong failed`, res);},});break;default:break;}}}/*** 重启小游戏*/static reboot() {if (isWechat()) {//@ts-ignorewx.restartMiniProgram({success: () => {console.log('restart success');},fail: () => {console.log('restart failed');}})}if (isBytedance()) {try {// @ts-ignorett.restartMiniProgramSync();} catch (error) {console.log(`restartMiniProgramSync`, error);}}}/*** 退出小游戏*/static exit() {if (isWechat()) {//@ts-ignorewx.exitMiniProgram({success: () => {console.log('exit success');},fail: () => {console.log('exit failed');}});}if (isBytedance()) {// @ts-ignorett.exitMiniProgram({success(res: any) {console.log("exit success:", res?.data);},fail(res: any) {console.log("exit fail:", res?.errMsg);},});}}/*** 显示转发按钮。通常在刚进入游戏的时候调用。* 主要是打开平台“...”这个按钮里面的分享菜单,一般默认是关闭的,需要调用这个函数打开。可以让用户分享你的游戏入口。*/static showShareMenu() {if (isWechat()) {//@ts-ignorewx.showShareMenu({withShareTicket: true,menus: ['shareAppMessage', 'shareTimeline'],success: () => { },fail: () => { },complete: () => { }});}if (isBytedance()) {//@ts-ignorett.showShareMenu({success(res: any) {console.log("show menu is showing");},fail(err: any) {console.log("showShareMenu:", err.errMsg);},complete(res: any) {console.log("showShareMenu complete");},});}}/*** 微信小游戏:跳转到另外一款小游戏* 抖音小游戏:跳转到指定的视频界面* @param targetId 微信小游戏appid或者视频界面*/static navigateTo(targetId: string, onSuccess?: () => void) {if (isWechat()) {// @ts-ignorewx.navigateToMiniProgram({appId: targetId,extraData: {foo: 'bar'},envVersion: 'develop',success(res: any) {onSuccess?.();}});}if (isBytedance()) {// @ts-ignorett.navigateToVideoView({videoId: targetId,success: (res: any) => {onSuccess?.();},fail: (err: any) => {console.log("bytedance navigateToVideoView fail", err);},});}}/*** 小游戏平台登录功能。微信返回code,抖音返回code和anonymousCode。用于登录的凭证,需要把这个code传回你的服务器程序中去调用code2Session* @param callback (code, anonymousCode) 第一个参数为code,微信和抖音都支持;第二个参数为匿名设备ID,仅抖音支持,失败都返回null*/static login(callback: (code: string, anonymousCode: string) => void) {let loginPlatform = () => {if (isWechat()) {//@ts-ignorewx.login({success: (res: { code: any; errMsg: any; }) => {if (res.code) {API._loginCode = res.code;API._loginAnonymousCode = null;callback?.(API._loginCode, API._loginAnonymousCode);} else {console.log('login error:', res.errMsg)}},fail: () => {API._loginCode = null;API._loginAnonymousCode = null;callback?.(API._loginCode, API._loginAnonymousCode);console.log('login fail')}});} else if (isBytedance()) {//@ts-ignorett.login({force: true,success(res: any) {console.log(`login ${res.code} ${res.anonymousCode}`);if (res.code) {API._loginCode = res.code?.toString();API._loginAnonymousCode = res.anonymousCode?.toString();callback?.(API._loginCode, API._loginAnonymousCode);} else {console.log('login error:', res.errMsg)}},fail(res: any) {API._loginCode = null;API._loginAnonymousCode = null;callback?.(API._loginCode, API._loginAnonymousCode);console.log(`login fail`, res);},});} else {API._loginCode = null;API._loginAnonymousCode = null;callback?.(API._loginCode, API._loginAnonymousCode);console.log('not mini game platform, login codes are all null');}}if (!API._loginCode) {loginPlatform();} else {if (isWechat()) {//@ts-ignorewx.checkSession({success() {console.log(`session is valid, use current code:`, API._loginCode);callback?.(API._loginCode, API._loginAnonymousCode);},fail() {console.log(`session expired`);loginPlatform();}});} else if (isBytedance()) {//@ts-ignorett.checkSession({success() {console.log(`session is valid, user current code: ${API._loginCode}, ${API._loginAnonymousCode}`);callback?.(API._loginCode, API._loginAnonymousCode);},fail() {console.log(`session expired`);loginPlatform();},});} else {console.log('not mini game platform, login null');callback?.(null, null);}}}/*** 调用微信云函数。由于参数需要自定义,所以为any,需要自行解释。函数只完成通道和处理一场的作用* @param callback 返回云函数调用结果。需要检查返回参数是否为空,失败的时候为空* @param name 云函数的名字* @param data 云函数的内容*/static callWechatCloudFunction(callback: (res: any) => void, name: string, data: {}) {if (!isWechat()) {console.log('Not wechat platform, not support callWechatCloudFunction');return;}this.login((code: string, anonymousCode: string) => {if (!API._hasInitWechatCloudFunction) {//@ts-ignorewx.cloud.init();API._hasInitWechatCloudFunction = true;}//@ts-ignorewx.cloud.callFunction({name: name,data: data,success: (res: any) => callback?.(res),fail: (err: any) => {console.log('wechat cloud function error:', err);callback?.(null);}});});}/*** 存储用户信息,数据量不能大。可以考虑用于分数排行榜。用户之间可共享排行数据。* @param key * @param value */static setUserCloudStorage(key: string, value: string) {if (isWechat()) {// @ts-ignorewx.setUserCloudStorage({KVDataList: [{ key: key, value: value }],success: () => console.log(`set cloud storage success:${key}, value:${value}`),fail: (err: any) => console.log('set cloud storage error:', err)});}if (isBytedance()) {// @ts-ignorett.setUserCloudStorage({KVDataList: [{ key: key, value: value, }],success: () => console.log(`set cloud storage success:${key}, value:${value}`),fail: (err: any) => console.log('set cloud storage error:', err)});}}}/*** 抖音侧边栏专属接口*/export class BytedanceSidebar {/*** 本游戏在抖音环境下启动监控,需要放在全局环境中,保证能第一时间启动。因为可能监听抖音失败(抖音小游戏官方的说明)!* @param onResult 包含一个boolean参数的函数* @param target 上述函数的拥有者,如果是类的成员函数,需要传入this。普通或匿名函数忽略即可。*/static listenFromSidebar(onResult: (success: boolean) => void, target?: any) {if (!isBytedance()) {onResult?.call(target, false);return;}// @ts-ignorett.onShow((res: any) => {console.log('onShow launch res:', res);if (res.scene === '021036') {onResult?.call(target, true);console.log('launch from sidebar');} else {onResult?.call(target, false);console.log('NOT launch from douyin sidebar!');}});// @ts-ignorelet options = tt.getLaunchOptionsSync();if (options && options.scene === '021036') {onResult?.call(target, true);}}/*** 检测抖音侧边栏是否存在* @param onResult 包含一个boolean参数的函数* @param target 上述函数的拥有者,如果是类的成员函数,需要传入this。普通或匿名函数忽略即可。* @returns */static checkSideBar(onResult: (success: boolean) => void, target?: any) {if (!isBytedance()) {onResult?.call(target, false);return;}//@ts-ignorett.checkScene({scene: "sidebar",success: (res: any) => {console.log("check scene success: ", res.isExist);onResult?.call(target, <boolean>res.isExist);},fail: (res: any) => {console.log("check scene fail:", res);onResult?.call(target, false);}});}/*** 跳转到抖音侧边栏* @param onResult 包含一个boolean参数的函数* @param target 上述函数的拥有者,如果是类的成员函数,需要传入this。普通或匿名函数忽略即可。* @returns */static navigateToSidebar(onResult: (success: boolean) => void, target?: any) {if (!isBytedance()) {console.log("not douyin platform!");onResult?.call(target, false);return;}// @ts-ignorett.navigateToScene({scene: "sidebar",success: () => {console.log("navigate success");onResult?.call(target, true);},fail: (res: any) => {console.log("navigate failed reason:", res);onResult?.call(target, false);},});}}}

 

相关文章:

微信小程序和抖音小程序的分享和广告接入代码

开发完成小程序或者小游戏之后&#xff0c;我们为什么要接入分享和广告视频功能&#xff0c;主要原因有以下几个方面。 微信小程序和抖音小程序接入分享和广告功能主要基于以下几个原因&#xff1a; 用户获取与增长&#xff1a;分享功能可以帮助用户将小程序内容传播给更多人&…...

中断系统的原理

一、介绍 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的。中断是指‌CPU在正常运行程序时&#xff0c;由于内部或外部事件的发生&#xff0c;导致CPU中断当前运行的程序&#xff0c;转而去执行其他程序的过程。‌ 中断可以是硬件产生的&#xff0c;也可以是…...

安装Rust

Rust 是一种系统级编程语言&#xff0c;旨在提供高性能和内存安全&#xff0c;同时避免常见的编程错误。 由 Mozilla Research 推出&#xff0c;Rust 自推出以来因其独特的设计理念和强大的功能而在开发者社区中迅速获得了广泛的关注和采用。 curl --proto ‘https’ --tlsv1.2…...

vite学习教程05、vite+vue2构建本地 SVG 图标

文章目录 前言一、构建本地SVG图标详细步骤1、安装开发依赖2、配置vite2.1、配置vite.config.js2.2、封装vite引入插件脚本 解决报错&#xff1a;can not find package fast-glob imported 二、实际应用应用1&#xff1a;未封装&#xff0c;直接vue应用应用2&#xff1a;封装vu…...

机器学习——自监督学习与无监督学习

# 机器学习中的自监督学习与无监督学习 在机器学习的世界中&#xff0c;监督学习、无监督学习和自监督学习都是重要的学习方法。本文将聚焦于自监督学习与无监督学习&#xff0c;探讨它们的原理、应用场景以及技术细节&#xff0c;并通过大量代码示例来揭示这些方法的内在工作…...

2003经典绝版100%仿盛大服务端火炬引擎原版

;中国游戏制作 本版本为中国游戏制作小组推出的第一个版本&#xff0c;有什么不完美的地方还请大家多多指教&#xff01;&#xff01;&#xff01; 与盛大逼真&#xff01;&#xff01;&#xff01; 本版本M2Server采用“梦幻风”以及“冰眼”M2Server修改器修改的 2004/1/…...

银河麒麟服务器:更新软件源

银河麒麟服务器&#xff1a;更新软件源 1、使用场景2、操作步骤3、注意事项 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 1、使用场景 当需要安装最新软件或修改软件源配置后&#xff0c;需更新软件源以获取最新软件包信息。 2、操作步…...

字节跳动收购Oladance耳机:强化音频技术,加速VR/AR生态布局

字节跳动收购Oladance耳机&#xff1a;加码VR/AR领域布局 近日&#xff0c;字节跳动宣布已完成对开放式耳机品牌Oladance的收购&#xff0c;实现了对该品牌的100%控股。这一收购标志着字节跳动在AI硬件领域的进一步扩展和深化&#xff0c;特别是对其VR/AR领域布局的重要加码。 …...

Android SystemUI组件(11)SystemUIVisibility解读

该系列文章总纲链接&#xff1a;专题分纲目录 Android SystemUI组件 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节持续迭代之前章节思维导图&#xff0c;主要关注左侧最上方SystemUiVisibility解读部分即可。 本章节主要讲解SystemUiVisibility的概念及其相…...

JSON 全知全解:深入探索 JSON 的奥秘

目录 一、JSON 基础认知&#xff08;一&#xff09;JSON 的定义与历史&#xff08;二&#xff09;JSON 的语法规则&#xff08;三&#xff09;JSON 与 JS 对象的关系 二、JSON 在不同语言中的用法&#xff08;一&#xff09;JavaScript 中的 JSON 操作&#xff08;二&#xff0…...

CSS | 响应式布局之媒体查询(media-query)详解

media type(媒体类型)是CSS 2中的一个非常有用的属性&#xff0c;通过media type我们可以对不同的设备指定特定的样式&#xff0c;从而实现更丰富的界面。media query(媒体查询)是对media type的一种增强&#xff0c;是CSS 3的重要内容之一。随着移动互联网的发展&#xff0c;m…...

并查集的模拟实现

简化版本 class UnionFindSet { public:UnionFindSet(size_t n):_ufs(n, -1){}void Union(int x1, int x2){int root1 FindRoot(x1);int root2 FindRoot(x2);// 如果本身就在一个集合就没必要合并了if (root1 root2)return;// 控制数据量小的往大的集合合并if (abs(_ufs[roo…...

如何高效删除 MySQL 日志表中的历史数据?实战指南

在处理高并发的物联网平台或者其他日志密集型应用时&#xff0c;数据库中的日志表往往会迅速增长&#xff0c;数据量庞大到数百GB甚至更高&#xff0c;严重影响数据库性能。如何有效管理这些庞大的日志数据&#xff0c;特别是在不影响在线业务的情况下&#xff0c;成为了一项技…...

请散户股民看过来,密切关注两件大事

明天股市要开市&#xff0c;不仅散户股民期盼节后股市大涨&#xff0c;上面也同样想在节后来上一个“开门红”。 为此&#xff0c;上面没休假&#xff0c;关起门来办了两件大事&#xff0c;这两天发布消息已提前预热了。 两件大事如下&#xff1a; 一是&#xff0c;上交所10…...

设计模式之外观模式(Facade)

一、外观模式介绍 外观模式( Facade Pattern)&#xff0c;也叫门面模式&#xff0c;是一个 “结构型” 设计模式。 外观模式的原始定义是&#xff1a;为子系统中的一组接口提供统一的接口。它定义了一个更高级别 的接口&#xff0c;使子系统更易于使用。 外观模式&#xff0c;是…...

解锁 Python 嵌套字典的奥秘:高效操作与实战应用指南

文章目录 前言&#x1f340;一、 什么是 Python 字典&#xff1f;1.1 字典的语法 &#x1f340;二、 字典的基本操作2.1 字典的创建2.2 访问字典中的值2.3 添加或修改键值对2.4 删除字典中的键值对 &#x1f340;三、 字典的遍历操作3.1 遍历字典的键3.2 遍历字典的值3.3 同时遍…...

联想服务器配置阵列、安装操作系统

文章目录 [toc]1.配置阵列2.制作启动盘3.安装系统 1.配置阵列 1.根据提示进入BIOS设置&#xff08;F1&#xff09; 2.系统设置 3.存储 4.第四步可以看到raid卡信息 5.Main Menu 6.Configuration Management 7.Create Virtual Drive 8.Select RAID Level raid5 9.Select Drives…...

【深度强化学习】DDPG实现的4个细节(OUNoise等)

文章目录 前言一、论文内容简述创新点&#xff08;特点&#xff0c;与DQN的区别&#xff09;&#xff1a;可借鉴参数&#xff1a;细节补充&#xff1a; 二、细节1&#xff1a;weight_decay原理代码 三、细节2&#xff1a;OUNoise原理代码 四、细节3&#xff1a;ObsNorm原理代码…...

算法工程师重生之第二十二天(递增子序列 全排列 全排列 II 重新安排行程 N皇后 解数独 总结 )

参考文献 代码随想录 一、非递减子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作…...

css的选择器及优先级

一、css选择器 CSS选择器是用来选择HTML文档中的元素&#xff0c;并为它们应用样式规则的工具。CSS选择器有很多种&#xff0c;可以根据元素的类名、ID、属性、伪类、伪元素、标签等来选择元素。以下是一些常见的CSS选择器及其用法&#xff1a; 1. ID选择器&#xff1a; 根据…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...