Mobvista广告接入——最白话,手把手教你做系列。
Mobvista广告接入Unity。主要讲插屏,视频广告以及Native的使用。
首先Mobvista广告得SDK目前应该只能通过由服务商提供,必须有Mobvista平台的账号。
下面开始接Mobvista广告,仍然是两个步骤。
第一步:接Mobvista广告插件。
将MVUnityPlugin_XXX.unitypackage导入你的项目。
然后注意以下几点,不管集成哪种广告形式:
1、请一定要加入AndroidSDK里 /jar/下的mobvista_common和mobvista_alpha这两文件下的所有jar包和res文件下所有东西。
2、其中所有添加的jar包全部放到Plugins/Android/下,所有res文件全部放到Plugins/Android/res/下。
分广告形式集成说明:
如果只集成native形式的广告,需要导入unityplugin里的MVUnity.cs、MVNativeAdsUnity.cs,以及SDK里面jar目录下的mobvista_mvnative文件夹下的jar、res。
如果只集成appwall形式的广告,需要导入unityplugin里的MVUnity.cs、MVAppWallUnity.cs,以及SDK里面jar目录下的mobvista_appwall文件夹下的jar、res。
如果只集成rewardvideo形式的广告,需要导入unityplugin里的MVUnity.cs、MVRewardAdsUnity.cs,以及SDK里面jar目录下的mobvista_reward、mobvista_playercommon、mobvista_videocommon、mobvista_videojs、mobvista_mvjscommon文件夹下的jar、res。
如果只集成offerwall形式的广告,需要导入unityplugin里的MVUnity.cs、MVOfferWallUnity.cs,以及SDK里面jar目录下的mobvista_offerwall、mobvista_playercommon、mobvista_mvjscommon文件夹下的jar、res。
如果只集成interstitial形式的广告,需要导入unityplugin里的MVUnity.cs、MVInterstitialUnity.cs,以及SDK里面jar目录下的mobvista_interstital、mobvista_mvjscommon文件夹下的jar、res。
(Android对应的SDK文件和IOS对应的framework文件也由服务商提供)
重点:
1,如果项目里没有android-support-v4文件的话需要将android-support-v4放到Plugins/Android/下;
2,AndroidManifest程序入口位置需要修改成下图代码。
以上,第一步完成。
第二步:代码部分。
1,初始化SDK
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using AssemblyCSharpMVpass;public class MvInit : MonoBehaviour {//AppID和ApiKeyprivate const string MVSDKAppIDForiOS = "22050";private const string MVSDKApiKeyForiOS = "7c22942b749fe6a6e361b675e96b3ee9";private const string MVSDKAppIDForAndroid = "24282";private const string MVSDKApiKeyForAndroid = "7c22942b749fe6a6e361b675e96b3ee9";private const string MVSDKApplicationIdForAndroid = "";private static bool initMVSDKFlag = false;//初始化方法void InitMVSDK (){string appId = null;string apiKey = null;string applicationId = null;#if UNITY_ANDROIDappId = MVSDKAppIDForAndroid;apiKey = MVSDKApiKeyForAndroid;applicationId = MVSDKApplicationIdForAndroid;#elif UNITY_IPHONE || UNITY_IOSappId = MVSDKAppIDForiOS;apiKey = MVSDKApiKeyForiOS;applicationId = null;#endifMVUnity.InitMVSDKInUnity(appId,apiKey,applicationId);}// Use this for initialization//初始化MVSDK一次即可void Awake () {Debug.Log(Mathf.Atan2(1,1));if (!initMVSDKFlag) {InitMVSDK ();initMVSDKFlag = true;Debug.Log("MvSdkInit");}}
}
2,插屏广告
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using AssemblyCSharpMVpass;public class MvInterstitialAd : MonoBehaviour {private MVInterstitialUnity interstitialAd;private const string KInterstitialUnitIDForAndroid = "3667";private const string KInterstitialUnitIDForiOS = "3703";void Start () {string interstitialUnitId = null;#if UNITY_ANDROIDthis.name = "interstitialBridge";interstitialUnitId = KInterstitialUnitIDForAndroid;#elif UNITY_IPHONE || UNITY_IOSinterstitialUnitId = KInterstitialUnitIDForiOS;#endifinterstitialAd = new MVInterstitialUnity ();interstitialAd.InitInterstitialInUnity (interstitialUnitId, MVAdCategory.MVAD_CATEGORY_ALL);Debug.Log ("MVInterstitialUnity Init");}//加载广告方法public void LoadMvInterlAds(){if (interstitialAd != null) {#if UNITY_IPHONE || UNITY_IOSMVInterstitialUnity.InterstitialAdDidLoad = (delegate() {this.Log ("InterstitialAdDidLoad");});MVInterstitialUnity.InterstitialAdDidFailWithError = (delegate(string error) {this.Log ("InterstitialAdDidFailWithError: " + error);});#endifinterstitialAd.LoadInterstitialInUnity ();}}//显示广告方法public void ShowMvInterlAds(){if (interstitialAd != null){#if UNITY_IPHONE || UNITY_IOSMVInterstitialUnity.InterstitialAdShowSuccess = (delegate() {this.Log ("InterstitialAdShowSuccess");});MVInterstitialUnity.InterstitialAdShowFailed = (delegate(string error) {this.Log ("InterstitialAdShowFailed: " + error);});MVInterstitialUnity.InterstitialAdDidClick = (delegate() {this.Log ("InterstitialAdDidClick");});MVInterstitialUnity.InterstitialAdDidClosed = (delegate() {this.Log ("InterstitialAdDidClosed");});#endifinterstitialAd.ShowInterstitialInUnity ();}}/***************android callback area start**********************/#if UNITY_ANDROIDvoid onInterstitialLoadSuccess(String message){Debug.Log ("onInterstitialLoadSuccess :" + message);}void onInterstitialLoadFail(String errorMessage){Debug.Log("onInterstitialLoadFail :" + errorMessage);}void onInterstitialClosed(String message){Debug.Log("onInterstitialClosed :" + message);}#endif/***************android callback area end**********************/}
3,视频广告
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using AssemblyCSharpMVpass;public class MvRewardAds : MonoBehaviour {//Androidprivate const string KRewardUnitIDForAndroid = "2163";private const string KRewardIDForAndroid = "7";//iosprivate const string KRewardUnitIDForiOS = "607";private const string KRewardIDForiOS = "8794";private MVRewardAdsUnity rewardVideoAd1;void OnEnable (){// Listen to all events for illustration purposes#if UNITY_IPHONE || UNITY_IOSMVRewardAdsUnity.loadedEvent += RewardWallAdDidLoad;MVRewardAdsUnity.loadFailedEvent += RewardWallAdDidFailWithError;MVRewardAdsUnity.shownEvent += RewardWallAdShowSuccess;MVRewardAdsUnity.showFailedEvent += RewardWallAdShowFailWithError;MVRewardAdsUnity.clickEvent += RewardWallAdDidClick;MVRewardAdsUnity.rewardInfoEvent += RewardWallOnVideoAdDismissed;#endif}void OnDisable (){#if UNITY_IPHONE || UNITY_IOSMVRewardAdsUnity.loadedEvent -= RewardWallAdDidLoad;MVRewardAdsUnity.loadFailedEvent -= RewardWallAdDidFailWithError;MVRewardAdsUnity.shownEvent -= RewardWallAdShowSuccess;MVRewardAdsUnity.showFailedEvent -= RewardWallAdShowFailWithError;MVRewardAdsUnity.clickEvent -= RewardWallAdDidClick;MVRewardAdsUnity.rewardInfoEvent -= RewardWallOnVideoAdDismissed;#endif}void Start () {#if UNITY_ANDROIDthis.name = "rewardwallBridge";#endifrewardVideoAd1 = new MVRewardAdsUnity ();#if UNITY_ANDROIDstring rewardUnitId = KRewardUnitIDForAndroid;rewardVideoAd1.sharedInstanceForAndroid (rewardUnitId);#endif}//加载广告方法public void LoadMvRewardAds(){string rewardUnitId = null;#if UNITY_ANDROIDrewardUnitId = KRewardUnitIDForAndroid;#elif UNITY_IPHONE || UNITY_IOSrewardUnitId = KRewardUnitIDForiOS;#endifrewardVideoAd1.LoadVideoInUnity (rewardUnitId);}//显示广告方法public void ShowMvRewardAds(){string rewardUnitId = null;string rewardId = null;string userId = "Your UserId";#if UNITY_ANDROIDrewardUnitId = KRewardUnitIDForAndroid;rewardId = KRewardIDForAndroid;#elif UNITY_IPHONE || UNITY_IOSrewardUnitId = KRewardUnitIDForiOS;rewardId = KRewardIDForiOS;#endifif (rewardVideoAd1.IsVideoReadyToPlayInUnity (rewardUnitId)) {Debug.Log("rewardVideoAd is Ready, will play");rewardVideoAd1.ShowVideoInUnity (rewardUnitId, rewardId, userId);} else {Debug.Log("rewardVideoAd not Ready");}}/*************** rewardvideo callback area start**********************/#if UNITY_ANDROIDvoid onVideoLoadSuccess(string message){Debug.Log("RewardWallLoadSuccess:" + message);} void onShowFail(string errorMessage){Debug.Log("RewardWallShowFail:" + errorMessage);} void onVideoLoadFail(string message){Debug.Log("RewardWallVideoLoadFail:" + message);} void onAdShow(string message){Debug.Log("RewardWallAdShow:" + message); } void onAdClose(string message){MVRewardAdInfo rewardInfo = new MVRewardAdInfo ();rewardInfo = JsonUtility.FromJson<MVRewardAdInfo> (message);if (rewardInfo.converted == "1") {Debug.Log("RewardWallOnVideoAdClosed:" + rewardInfo.rewardName);}else{Debug.Log("RewardWallOnVideoAdClosed:" + "No Reward");}} #endif#if UNITY_IOS || UNITY_IPHONEvoid RewardWallAdDidLoad(string unitId){Debug.Log ("RewardWallAdDidLoad unitId:" + unitId);}void RewardWallAdDidFailWithError(string unitId,string errorMsg){Debug.Log ("RewardWallAdDidFailWithError: " + errorMsg + "unitId:" + unitId);}void RewardWallAdShowSuccess(string unitId){Debug.Log ("RewardWallAdShowSuccess unitId:" + unitId);}void RewardWallAdShowFailWithError(string unitId,string errorMsg){Debug.Log ("RewardWallAdShowFailed: " + errorMsg + "unitId:" + unitId);}void RewardWallAdDidClick(string unitId){Debug.Log ("RewardWallAdDidClick unitId:" + unitId);}void RewardWallOnVideoAdDismissed(string unitId,bool converted,MVRewardAdInfo rewardInfo){if(converted && rewardInfo != null){Debug.Log ("RewardWallOnVideoAdDismissed:" + rewardInfo.rewardName);}}#endif/*************** rewardvideo callback area end**********************/}
4,Native广告。用法参照FaceBookNative广告。
using AssemblyCSharpMVpass;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MvNativeAds : MonoBehaviour {public bool IsNativeMobvistaAdLoaded;//public GameObject CallBtn;//对应广告位的IDprivate MVNativeAdsUnity nativeAd;[Header("Text:")]public Text title;public Text socialContext;public Text InstallButtonText;[Header("Images:")]public Image panel;public Image coverImage;public Image iconImage;MVButton coverViewButtonForiOS;public Sprite IconImage { get; private set; }public Sprite CoverImage { get; private set; }public string unitId = "23085";MVCampaign campaignForCurrentAdView;// Use this for initializationvoid InitMVNativeAds(){MVAdCategory adCategory = MVAdCategory.MVAD_CATEGORY_GAME;//广告模板MVTemplate[] supportedTemplates = new MVTemplate[1];//模板类型supportedTemplates[0] = new MVTemplate() { templateType = MVAdTemplateType.MVAD_TEMPLATE_BIG_IMAGE, adsNum = 3 };this.name = "nativeBridge";//初始化unitIdnativeAd = new MVNativeAdsUnity();nativeAd.InitNativeAdsInUnity(unitId, "", 1, false, adCategory, supportedTemplates);#if UNITY_IPHONE || UNITY_IOS//register the AdsTappedCallback function nativeAd.AddAdsTappedCallBackForiOS();#endifthis.Log("MVNativeAdsUnity Init");}void DrwaMVButtonFullScreen(){Debug.Log("画个区域" + "DrwaMVButtonFullScreen");// react Area just the InstallButtonfloat x = 0;float y = 0;float widht = 716 * 1.2f;float height = 113 * 1.2f;Vector3 v3 = new Vector3(x, y, 0.0f);Vector2 v2 = new Vector2(widht, height);coverViewButtonForiOS = new MVButton();coverViewButtonForiOS.DrawMVButton(panel.transform, v3, v2, Color.red);coverViewButtonForiOS.Touched = (delegate (string campaign){Debug.Log("coverViewButtonForiOS Tapped");});}void RemoveAndroidCoverView(){
#if UNITY_ANDROIDif (nativeAd != null){if (this.campaignForCurrentAdView != null){nativeAd.UnRegisterViewForAndroid(this.campaignForCurrentAdView.index);}}
#endif}void Start(){
#if UNITY_ANDROIDthis.name = "nativeBridge";
#endifInitMVNativeAds();#if UNITY_IPHONE || UNITY_IOS//UI , draw coverView for Regist AdInstallButtonDrwaMVButtonJustForiOS ();
#endifLoadAd();}void OnGUI(){// Update GUI from native ad infoif (nativeAd != null && CoverImage != null){coverImage.sprite = CoverImage;}if (nativeAd != null && IconImage != null){iconImage.sprite = IconImage;}}//load Image With ImageUrlprivate static TextureFormat imageFormatRGBA32(){return TextureFormat.RGBA32;}private static TextureFormat imageFormatRGB24(){return TextureFormat.RGB24;}public IEnumerator LoadIconImage(string url){if (url != null){Texture2D texture = new Texture2D(4, 4, imageFormatRGBA32(), false);WWW www = new WWW(url);yield return www;www.LoadImageIntoTexture(texture);if (texture){IconImage = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));}}}public IEnumerator LoadCoverImage(string url){if (url != null){Texture2D texture = new Texture2D(4, 4, imageFormatRGB24(), false);WWW www = new WWW(url);yield return www;www.LoadImageIntoTexture(texture);if (texture){CoverImage = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));}}}public void LoadAd(){Debug.Log("加载广告");if (nativeAd != null){#if UNITY_IPHONE || UNITY_IOSMVNativeAdsUnity.NativeAdDidLoad = (delegate (MVCampaign[] list) {this.Log ("NativeAdDidLoad");if(list.Length > 0){MVCampaign campaign = list[0];this.campaignForCurrentAdView = campaign;StartCoroutine (LoadIconImage (campaign.iconUrl));StartCoroutine (LoadCoverImage (campaign.imageUrl));title.text = campaign.appName;socialContext.text = campaign.appDesc;InstallButtonText.text = campaign.adCall;// Binding the campaign to the CoverViewButton when you get the campaign or your adView will show.string json = JsonUtility.ToJson(campaign);if(nativeAd.nativeAdManager != IntPtr.Zero){coverViewButtonForiOS.RegistCampaign (nativeAd.nativeAdManager,json);}}});MVNativeAdsUnity.NativeAdDidFailWithError = (delegate(string error) {this.Log ("Native ad failed to load with error: " + error);});MVNativeAdsUnity.NativeAdDidClick = (delegate(MVCampaign campaign) {this.Log ("Ad Clicked: campaignId:" + campaign.adId);});MVNativeAdsUnity.NativeAdClickUrlWillStartToJump = (delegate(string clickUrl) {this.Log ("OnAdClickUrlWillStartToJumpCallBack.");});MVNativeAdsUnity.NativeAdClickUrlWillDidToJump = (delegate(string clickUrl) {this.Log ("OnAdClickUrlWillDidToJumpCallBack.");});MVNativeAdsUnity.NativeAdClickUrlWillDidToJumpError = (delegate(string finalUrl,string error) {this.Log ("OnAdClickUrlWillDidToJumpErrorCallBack.");});MVNativeAdsUnity.NativeAdImpressionWithType = (delegate(MVAdSourceType adSource) {this.Log ("NativeAdImpressionWithType: " + adSource );});#endif// Initiate a request to load an ad.nativeAd.LoadNativeAdsInUnity();}}public void RegisterUIView(){
#if UNITY_ANDROIDif (nativeAd != null){nativeAd.RegisterViewForAndroid(40, 60, 716, 113, this.campaignForCurrentAdView.index);}
#endif}public void UnRegisterUIView(){#if UNITY_ANDROIDif (nativeAd != null && this.campaignForCurrentAdView != null){nativeAd.UnRegisterViewForAndroid(this.campaignForCurrentAdView.index);}
#endif}/***************android callback area start**********************/#if UNITY_ANDROIDvoid callback_android_data(String json){this.Log("Ad loaded");MVCampaignArrayWrapper wrapper = JsonUtility.FromJson<MVCampaignArrayWrapper>(json);MVCampaign[] campaigns = wrapper.objects;if (campaigns.Length > 0){MVCampaign campaign = campaigns[0];this.campaignForCurrentAdView = campaign;StartCoroutine(LoadIconImage(campaign.iconUrl));StartCoroutine(LoadCoverImage(campaign.imageUrl));title.text = campaign.appName;socialContext.text = campaign.appDesc;InstallButtonText.text = campaign.adCall;RegisterUIView();}}void onAdLoadError(String errorMessage){this.Log("AdLoadError :" + errorMessage);}void onLoggingImpression(String adSource){MVAdSourceType source = (MVAdSourceType)Convert.ToInt32(adSource);this.Log("onLoggingImpression adSource:" + source);}void onAdLoadClick(String message){MVCampaign mvCampaign = new MVCampaign();mvCampaign = JsonUtility.FromJson<MVCampaign>(message);if (mvCampaign != null){this.Log("AdClick:" + mvCampaign.imageUrl);}}void onStartRedirection(String message){MVCampaignTrack campaignTrack = new MVCampaignTrack();campaignTrack = JsonUtility.FromJson<MVCampaignTrack>(message);if (campaignTrack != null){this.Log("StartRedirection:" + campaignTrack.campaign.imageUrl);this.Log("StartRedirection:" + campaignTrack.url);}}void onRedirectionFailed(String message){MVCampaignTrack campaignTrack = new MVCampaignTrack();campaignTrack = JsonUtility.FromJson<MVCampaignTrack>(message);if (campaignTrack != null){this.Log("RedirectionFailed:" + campaignTrack.campaign.imageUrl);this.Log("RedirectionFailed:" + campaignTrack.url);}}void onRedirectionFinished(String message){MVCampaignTrack campaignTrack = new MVCampaignTrack();campaignTrack = JsonUtility.FromJson<MVCampaignTrack>(message);if (campaignTrack != null){this.Log("FinishRedirection:" + campaignTrack.campaign.imageUrl);this.Log("FinishRedirection:" + campaignTrack.url);}}void onDownloadStart(String message){MVCampaign downloadCampaign = new MVCampaign();downloadCampaign = JsonUtility.FromJson<MVCampaign>(message);if (downloadCampaign != null){this.Log("DownloadStart:" + downloadCampaign.appName);}}void onDownloadFinish(String message){MVCampaign downloadCampaign = new MVCampaign();downloadCampaign = JsonUtility.FromJson<MVCampaign>(message);if (downloadCampaign != null){this.Log("DownloadFinish:" + downloadCampaign.appName);}}void onDownloadProgress(String progress){this.Log("DownloadProgress :" + progress);}void onInterceptDefaultLoadingDialog(String message){this.Log("InterceptDefaultLoadingDialog :" + message);}void onShowLoading(String message){MVCampaign showLoadingCampaign = new MVCampaign();showLoadingCampaign = JsonUtility.FromJson<MVCampaign>(message);if (showLoadingCampaign != null){this.Log("ShowLoading:" + showLoadingCampaign.appName);}}void onDismissLoading(String message){MVCampaign dismissLoadingCampaign = new MVCampaign();dismissLoadingCampaign = JsonUtility.FromJson<MVCampaign>(message);if (dismissLoadingCampaign != null){this.Log("DismissLoading:" + dismissLoadingCampaign.appName);}}
#endif/***************android callback area end**********************/private void Log(string s){s = "Log: " + s;Debug.Log(s);}private void OnDisable(){UnRegisterUIView();}}
以上插屏和视频广告替换成自己的广告ID即可。
Mobvista的Native广告在接入Unity中还有本身存在一些缺点,使用时需要根据自己需求做相应改动。
以上。
Mobvista广告接入——最白话,手把手教你做系列。相关推荐
- Vungle激励广告接入——最白话,手把手教你做系列。
首先Vungle是个广告插件.好像暂时只支持视频激励广告. 然后,申请ID不在赘述,要注意的是Vungle需要申请两个ID.对应环境初始化的ID和"VunglePlacementID&quo ...
- 关于IAP支付,谷歌和苹果订阅商品——最白话,手把手教你做系列。
简述:最近项目要接入订阅商品,这里总结一下公司大佬们的经验和我整理后脚本. 一.关于订阅 1,跟消耗性和非消耗性的购买类似,开发者账后后台建订阅型商品. 订阅型商品分两种,自动续订和非自动续订的,一般 ...
- Unity内IAP支付二次验证/服务器验证————最白话,手把手教你做系列。
之前的一篇写了Unity支付的IAP支付接入. 后来就出现了一些问题,数据统计的时候出现大量购买订单.但是实际上账户的钱却没有增加.@¥--&¥--*@¥&@初步判定可能存在部分用户通 ...
- C#获取目录下所有文件的列表——最白话,手把手教你做系列。
最近,在试着做一个Unity自动生成Ui的功能. 理论比较简单,通过拼接字符串生成脚本,都是Ok的,但为了更方便,就想顺便把文件路径也自动生成一下.即获取某个目录下所有预制体的文件目录. 于是就需要一 ...
- 在正方体的某一个面上随机一个点——最白话,手把手教你做系列。
问题需求 其实就是某个物体在随机运动,如果运动到正方形的某个面的上方的话,就在这个面上随机出来一个点降落下去. 解决方案 步骤1:物体向六个方向发射射线检测正方体位置. 射线检测,很简单,一句代码就不 ...
- 手把手教你做短视频去水印微信小程序(2-首页)
手把手教你做短视频去水印微信小程序系列教程(2-首页) 文章目录 手把手教你做短视频去水印微信小程序系列教程(2-首页) 前言 一.顶部banner 二.地址解析 1.整体代码 2. input框输入 ...
- 微信测试工程师手把手教你做弱网络模拟测试
微信测试工程师手把手教你做弱网络模拟测试 Posted by 腾讯优测 | 3,152 views 小优有话说: app研发不同于实验室里做研究,哪里有"理想环境". 理想里,用 ...
- 立创开源|手把手教你做个WiFi/蓝牙网关
我知道你也想要一个属于自己的WiFi/蓝牙网关 开源地址:ESP32 WiFi/蓝牙网关 ESP32 GetWay 工程说明 官方说明:安信可 Wi-Fi 家庭智能网关(ESP32-G)由安信可科技设 ...
- 手把手教你做关键词匹配项目(搜索引擎)---- 第九天
第九天 回顾: 8. 手把手教你做关键词匹配项目(搜索引擎)---- 第八天 7. 手把手教你做关键词匹配项目(搜索引擎)---- 第七天 6. 手把手教你做关键词匹配项目(搜索引擎)---- 第六天 ...
最新文章
- swift golang java,解决两数之和 (Javascript, Java, C#, Swift, Kotlin, Python,C++, Golang)
- 【Java数据库】使用properties资源文件,简化数据库连接
- ×××梦 最近要开始研究Excel 2010
- My97DatePicker日历的平面显示,不是文本框点击事件后显示
- 表达式计算:后缀表达式求解 以及 中缀表达式转换为后缀表达式
- js如何将跨域打开的窗口放到最前面_程序员的强迫症-便捷打开常用网站
- Android Studio配置,加快编译速度
- 排除包_冷水机压缩机压缩机常见故障和排除方法
- Google之海量数据的交互式分析工具Dremel
- NI Vision 开发环境
- 华为悦盒EC6018V9E线刷linux教程
- 爬虫实战 -- QQ空间自动点赞!太强了呀!
- 百面机器学习(5)——非监督学习
- 两台电脑实现串口通信
- jupyter 安装问题 No such notebook dir
- 蓝牙耳机BES2300P通过盒子获取/修改耳机状态信息
- 如何获取信息源、如何增长眼界?
- 机器学习讲堂 ACF 聚合通道检测
- HashMap结构图及特点
- 2021物理化学实验8:乙酸乙酯皂化反应动力学研究