Unity接入Adset广告_IOS详解
一.创建Adset账户
Adset官网:
https://www.shenshiads.com
注册成功后会进入审核状态,注意看微信24小时内会有专门的人加你的微信,然后询问你一些问题才可以审核通过,创建一个群聊小组,有什么问题(技术、相关问题等)可以在里面讨论。
然后就可以创建媒体和广告位,不懂的地方问相关人员就可以了,这里不再赘述。
二.配置Unity工程
1.配置场景
2.Canvas对象添加UIManager.cs代码
UIManager.cs代码如下:
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
private static UIManager instance;
public static UIManager Instance
{
get
{
if(instance == null)
{
instance = GameObject.FindObjectOfType<UIManager>();
}
return instance;
}
}
public Text numText;
public Button splashBtn;
public Button rewardBtn;
[DllImport("__Internal")]
private static extern void SplashBtnOnClick();
[DllImport("__Internal")]
private static extern void RewardBtnOnClick();
private void Awake()
{
if(splashBtn == null)
{
splashBtn = transform.Find("SplashBtn").GetComponent<Button>();
}
if(rewardBtn == null)
{
rewardBtn = transform.Find("RewardBtn").GetComponent<Button>();
}
}
// Start is called before the first frame update
void Start()
{
splashBtn.onClick.AddListener(SplashBtnOnClick);
rewardBtn.onClick.AddListener(RewardBtnOnClick);
}
public void UpdateCoinNum(string numTxt)
{
numText.text = numTxt;
}
}
3.OCCall对象添加OCCall.cs代码
OCCall.cs代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OCCall : MonoBehaviour
{
private int rewardCoinNum = 10;
private int myCoinNum = 0;
public void GetCoin()
{
Debug.Log("ObjecC调用到了:" + myCoinNum);
myCoinNum += rewardCoinNum;
UIManager.Instance.UpdateCoinNum(myCoinNum.ToString());
}
}
4.打包成Xcode文件
4.1 在工程Asset下新建一个Editor(不然代码会报错)文件夹创建BuildCallback.cs代码
BuildCallback.cs代码如下:
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.IO;
public class BuildCallback : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
int IOrderedCallback.callbackOrder { get { return 0; } }
System.DateTime startTime;
//打包前事件
void IPreprocessBuildWithReport.OnPreprocessBuild(BuildReport report)
{
startTime = System.DateTime.Now;
Debug.Log("开始打包 : " + startTime);
}
//打包后事件
void IPostprocessBuildWithReport.OnPostprocessBuild(BuildReport report)
{
System.TimeSpan buildTimeSpan = System.DateTime.Now - startTime;
Debug.Log("打包成功,耗时 : " + buildTimeSpan);
}
//回调 打包后处理
[PostProcessBuild(1)]
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
{
if (target != BuildTarget.iOS)
{
return;
}
var projPath = pathToBuiltProject + "/Unity-iPhone.xcodeproj/project.pbxproj";
var proj = new PBXProject();
proj.ReadFromFile(projPath);
//var targetGUID = proj.TargetGuidByName("Unity-iPhone");
//var targetGUID = proj.GetUnityMainTargetGuid();
var targetGUID = proj.GetUnityFrameworkTargetGuid();
proj.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-ObjC");
proj.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-l\"c++\"");
proj.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-l\"c++abi\"");
proj.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-l\"sqlite3\"");
proj.AddBuildProperty(targetGUID, "OTHER_LDFLAGS", "-l\"z\"");
//proj.SetBuildProperty(targetGUID, "ENABLE_BITCODE", "NO");
// framework to project
proj.AddFrameworkToProject(targetGUID, "SafariServices.framework", false);
proj.AddFrameworkToProject(targetGUID, "CFNetwork.framework", false);
proj.AddFrameworkToProject(targetGUID, "AVFoundation.framework", false);
proj.AddFrameworkToProject(targetGUID, "WebKit.framework", false);
proj.AddFrameworkToProject(targetGUID, "StoreKit.framework", false);
proj.AddFrameworkToProject(targetGUID, "Security.framework", false);
proj.AddFrameworkToProject(targetGUID, "CoreTelephony.framework", false);
proj.AddFrameworkToProject(targetGUID, "SystemConfiguration.framework", false);
proj.AddFrameworkToProject(targetGUID, "QuartzCore.framework", false);
proj.AddFrameworkToProject(targetGUID, "CoreLocation.framework", false);
proj.AddFrameworkToProject(targetGUID, "AdSupport.framework", false);
proj.AddFrameworkToProject(targetGUID, "Accelerate.framework", false);
proj.AddFrameworkToProject(targetGUID, "ImageIO.framework", false);
proj.AddFrameworkToProject(targetGUID, "CoreMotion.framework", false);
proj.AddFrameworkToProject(targetGUID, "CoreMedia.framework", false);
proj.AddFrameworkToProject(targetGUID, "MediaPlayer.framework", false);
proj.AddFrameworkToProject(targetGUID, "MobileCoreServices.framework", false);
proj.AddFrameworkToProject(targetGUID, "MessageUI.framework", false);
proj.AddFrameworkToProject(targetGUID, "libxml2.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libz.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libsqlite3.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libc++.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libresolv.9.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libxml2.2.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libiconv.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libbz2.1.0.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libz.1.2.5.tbd", false);
proj.AddFrameworkToProject(targetGUID, "libc++abi.tbd", false);
proj.AddFrameworkToProject(targetGUID, "AudioToolbox.framework", false);
proj.AddFrameworkToProject(targetGUID, "CoreGraphics.framework", false);
proj.AddFrameworkToProject(targetGUID, "DeviceCheck.framework", false);
proj.WriteToFile(projPath);
var plistPath = Path.Combine(pathToBuiltProject, "Info.plist");
var plist = new PlistDocument();
plist.ReadFromFile(plistPath);
PlistElementDict rootDict = plist.root;
plist.root.SetBoolean("NSAppTransportSecurity", true);
plist.root.SetString("NSUserTrackingUsageDescription", "该标识符将用于向您投放个性化广告");
//plist.root.SetString("NSPhotoLibraryAddUsageDescription", "需要相册权限");
//plist.root.SetString("NSPhotoLibraryUsageDescription", "需要相册权限");
//plist.root.SetString("NSCalendarsUsageDescription", "需要日历权限");
//plist.root.SetString("NSMicrophoneUsageDescription", "录制屏幕需要麦克风权限");
//plist.root.SetString("NSCameraUsageDescription", "需要相机权限");
//plist.root.SetString("NSLocationWhenInUseUsageDescription", "需要定位权限");
//PlistElementArray queriesSchemes = rootDict.CreateArray("LSApplicationQueriesSchemes");
//queriesSchemes.AddString("douyinsharesdk");
//queriesSchemes.AddString("douyinopensdk");
//queriesSchemes.AddString("snssdk1128");
//queriesSchemes.AddString("toutiaoopensdk");
plist.WriteToFile(plistPath);
UnityEngine.Debug.Log("Xcode 后续处理完成");
}
}
这样引入第三方依赖SDK会省很多事情
注意:这里面的具体配置请参考下写的 《三.配置Xcode工程》 里面写的内容
三.配置Xcode工程
1.下载IOS Demo
登录后点击SDK接入
然后点击Demo下载
2.将OSET.framework和第三方依赖SDK导入 到工程下.
将下列SDK拖入到工程中,同时对应.bundle资源文件也添加到工程(SDK demo中提供)
Frameworks:
·OSETSDK.framework
OSETSDK.bundle
BUAdSDK.framework
BURelyFoundation.framework
CSJAdSDK.framework
CSJAdSDK.bundle
(可 pod ‘Ads-CN’, ‘~> 5.0.0.5’)
ABUAdSDK.framework
ABUAdCsjAdapter.framework
BeiZiSDK.framework
BeiZiFoundation.framework
(可 pod ‘BeiZiSDK/BeiZiSDK’)
GDTMobSDK
(可 pod ‘GDTMobSDK’,‘~> 4.14.30’)
WindSDK.framework
WindFoundation.framework
Sigmob.bundle
(可 pod ‘SigmobAd-iOS’, ‘~> 4.9.1’)
KSAdSDK.framework (Embed设置为’Embed & Sign’)
KSAdSDK.bundle
(可pod配置,手动导入KSAdSDK.framework后 path指向 KSAdSDK.podspec文件路径 pod ‘KSAdSDK’, :path => ‘./xxxx/Frameworks’)
BaiduMobAdSDK.framework
baidumobadsdk.bundle
(可pod pod ‘BaiduMobAdSDK’ , ‘~> 5.101’)
PUADSDK.framework
(可pod pod ‘PUADSDK’ , ‘~> 3.3.1’)
IBXSDK.framework(可选-OSETIntegralWall(任务墙类型需要,不需要可以不引入))
IBXSDK.bundle(可选-OSETIntegralWall(任务墙类型需要))
打开Unity中导出的Xcode工程
在Libraries下新建一个Plugins文件夹
打开下载好的iOS Demo
找到framework文件夹
把里面的东西全部倒入到我们的UnityXcode中新建的Plugins文件夹下
3.PodFile配置
找到iOS Demo工程文件目录下的Podfile
将Podfile拷贝到UnityXcode到工程目录下
修改Podfile的内容,例如:
platform:ios , '10.0'
target 'Unity-iPhone' do
pod 'KSAdSDK', :path => '/Users/pengyulin/Workspaces/iOS/ad/AdSet4/Libraries/Plugins'
end
注意:这里的 pod ‘KSAdSDK’, :path => ‘@’ @这里填的是你的KSAdSDK.podspec文件所在的位置
然后Pod
打开终端找到Podfile文件所在位置
cd xxx/xxx 然后回车
再输入pod install回车
然后打开workspace
4.配置 Info.plist
设置允许Http连接,在工程的 Info.plist 文件中,设置 App Transport Security Settings
选项下 Allow Arbitrary Loads 值为 YES,对应 plist 内容为:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
在您的应用的Info.plist文件中,添加一个字符串SKAdNetworkItems键,如
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>58922NB4GD.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>238da6jt44.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>r3y5dwb26t.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>f7s53z58qe.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>x2jnk7ly8j.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>22mmun2rn5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>27a282f54n.skadnetwork</string>
</dict>
</array>
支持苹果 ATT:从 iOS 14 开始,若开发者设置 App Tracking Transparency 向用户申请跟踪授权,在用户授权之前IDFA 将不可用。
如果用户拒绝此请求,应用获取到的 IDFA 将自动清零,可能会导致您的广告收入的降低 要获取 App Tracking Transparency 权限,请更新您的 Info.plist,添加 NSUserTrackingUsageDescription 字段和自定义文案描述
<key>NSUserTrackingUsageDescription</key>
<string>该标识符将用于向您投放个性化广告</string>
注意:以上方式可通过配置Unity Project Builder或者以下方式更快
5.其他配置
将KSAdSDK.framewoek Embed & Sign
设置Enable BitCode为False
这样环境就配置好了。
6.相关OC代码的写入
在 UnityXcode项目文件夹下找到UnityAppController.h文件 #import 以下头文件
#import <OSETSDK/OSETSDK.h>
在 UnityXcode项目文件夹下找到UnityAppController.m文件 #import xxx.以下头文件
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
#import "GDTSDKConfig.h"
#import <WindSDK/WindSDK.h>
#import <KSAdSDK/KSAdSDK.h>
#import <BUAdSDK/BUAdSDK.h>
#import <BaiduMobAdSDK/BaiduMobAdSetting.h>
#import <ABUAdSDK/ABUAdSDK.h>
#import <BeiZiSDK/BeiZiSDK.h>
展示授权弹窗需要调用requestTrackingAuthorizationWithCompletionHandler:方法。
在 UnityXcode项目文件夹下找到UnityAppController.m文件在applicationDidBecomeActive方法中添加如下代码:
//适配ios15 ios15获取广告追踪权限要写在applicationDidBecomeActive 否则ios15 不弹框可能会被拒
if (@available(iOS 14, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
// Tracking authorization completed. Start loading ads here.
}];
} else {
// Fallback on earlier versions
}
初始化SDK
在 UnityXcode项目文件夹下找到UnityAppController.m在- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法中添加如下代码:
//SDK配置日志 用户唯一标识符 推荐设置 (和激励视频广告Userid 不共用) 此userid 仅用于日志, 激励视频userid 仅用作激励视频回调
[OSETManager configureLogsWithUid:@"6126"];
//SDK初始化 appKey
[OSETManager configure:@"11555062B6B2FB94"];
NSLog(@"开始初始化");
//打开日志模式
[OSETManager openDebugLog];
NSLog(@"OSETSDKVersion %@ = ",[OSETManager version]);
NSString *idfa = [[ASIdentifierManager sharedManager].advertisingIdentifier UUIDString];
NSLog(@"%@",idfa);
NSLog(@"KSAdSDK %@ = ",[KSAdSDKManager SDKVersion]);
NSLog(@"WindSDK %@ = ",[WindAds sdkVersion]);
NSLog(@"GDTAdSDK %@ = ",[GDTSDKConfig sdkVersion]);
NSLog(@"BUAdSDK %@ = ",[BUAdSDKManager SDKVersion]);
NSLog(@"BDAdSDK %@ = ",SDK_VERSION_IN_MSSP);
NSLog(@"AUBAdSDK %@ = ",[ABUAdSDKManager SDKVersion]);
NSLog(@"BeiZiSDK %@ = ",[BeiZiSDKManager sdkVersion]);
//声音问题
[GDTSDKConfig enableDefaultAudioSessionSetting:NO];
将iOS Demo中的BaseViewController.h 、BaseViewController.m 、RewardVideoViewController.h 、RewardVideoViewController.m 、SplashViewController.h 、SplashViewController.m添加到Unity Xcode工程中Plugins文件夹下
在Plugins文件夹下,新建UnityCall.h代码如下
//
// UnityCall.h
// UnityFramework
//
// Created by xxx on 2023/6/15.
//
@interface UnityCall : NSObject
@end
#ifdef __cplusplus
extern "C" {
#endif
void SplashBtnOnClick();
void RewardBtnOnClick();
#ifdef __cplusplus
} // extern "C"
#endif
在Plugins文件夹下,新建UnityCall.m代码如下
//
// UnityCall.m
// UnityFramework
//
// Created by 彭昱林 on 2023/6/15.
//
#import <Foundation/Foundation.h>
#import "UnityCall.h"
#import "RewardVideoViewController.h"
#import "SplashViewController.h"
#import <OSETSDK/OSETSDK.h>
#import "AdManager.h"
@interface UnityCall ()<OSETRewardVideoAdDelegate>
@property(nonatomic,strong)UICollectionView * collectionView;
@property(nonatomic,strong)NSArray * data;
@property (nonatomic,strong) OSETSuspendAd * suspendAd;
@property (nonatomic,strong) OSETRewardVideoAd *rewardVideoAd;
@end
void SplashBtnOnClick(){
NSLog(@"调用到了SplashBtnOnClick");
AdManager *am = [AdManager shareInstance];
[am splashAdVideoShow];
}
void RewardBtnOnClick(){
NSLog(@"调用到了RewardBtnOnClick");
AdManager *am = [AdManager shareInstance];
[am rewardVideoShow];
}
在Plugins文件夹下,新建AdManager.h代码如下
//
// AdManager.h
// UnityFramework
//
// Created by 彭昱林 on 2023/6/15.
//
#import <UIKit/UIKit.h>
#import "RewardVideoViewController.h"
#import "SplashViewController.h"
@interface AdManager : UIViewController <OSETSplashAdDelegate,OSETRewardVideoAdDelegate>
@property (retain, nonatomic) UIWindow* window;
@property (nonatomic,strong) OSETSplashAd * splashAd;
@property (nonatomic,strong) OSETRewardVideoAd *rewardVideoAd;
+ (instancetype)shareInstance;
-(void)rewardVideoShow;
-(void)splashAdVideoShow;
@end
在Plugins文件夹下,新建AdManager.m代码如下
//
// AdManager.m
// UnityFramework
//
// Created by 彭昱林 on 2023/6/15.
//
#import <Foundation/Foundation.h>
#import "AdManager.h"
static AdManager *manager = nil;
@implementation AdManager
+ (instancetype)shareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[AdManager alloc] init];
manager.window = [UIApplication sharedApplication].keyWindow;
});
return manager;
}
-(void)rewardVideoShow{
self.rewardVideoAd = [[OSETRewardVideoAd alloc] initWithSlotId:@"5E268349378BAD81BC6BA0F7FE78D656" withUserId:@""];
self.rewardVideoAd.delegate = self;
NSLog(@"开始请求激励广告");
//E80DABEF5FD288492D4A9D05BF84E417
//[self.rewardVideoAd loadAdData];
//[self.rewardVideoAd showFromRootViewController:self];
//[UIApplication sharedApplication].keyWindow.rootViewController]
[self.rewardVideoAd showFromRootViewController:self.window.rootViewController];
}
/// 激励视频加载成功
- (void)rewardVideoDidReceiveSuccess:(id)rewardVideoAd slotId:(NSString *)slotId{
NSLog(@"激励视频加载成功%@",slotId);
}
/// 激励视频加载失败
- (void)rewardVideoLoadToFailed:(id)rewardVideoAd error:(NSError *)error{
NSLog(@"激励视频加载失败%@",error);
}
/// 激励视频点击
- (void)rewardVideoDidClick:(id)rewardVideoAd{
NSLog(@"激励视频点击");
}
/// 激励视频关闭
- (void)rewardVideoDidClose:(id)rewardVideoAd checkString:(NSString *)checkString{
NSLog(@"激励视频关闭");
self.rewardVideoAd.delegate = nil;
self.rewardVideoAd = nil;
}
//激励视频播放出错
- (void)rewardVideoPlayError:(id)rewardVideoAd error:(NSError *)error{
NSLog(@"激励视频播放出错");
}
//激励视频播放结束
- (void)rewardVideoPlayEnd:(id)rewardVideoAd checkString:(NSString *)checkString{
NSLog(@"激励视频播放结束");
}
//激励视频开始播放
- (void)rewardVideoPlayStart:(id)rewardVideoAd checkString:(NSString *)checkString{
NSLog(@"激励视频开始播放");
}
//激励视频奖励
- (void)rewardVideoOnReward:(id)rewardVideoAd checkString:(NSString *)checkString{
NSLog(@"激励视频奖励");
UnitySendMessage("OCCall", "GetCoin", "");
}
-(void)splashAdVideoShow{
//开屏广告
UIImageView *imageView = [UIImageView new];
imageView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 100);
imageView.image = [UIImage imageNamed:@"logo"];
imageView.contentMode = UIViewContentModeCenter;
imageView.backgroundColor = [UIColor whiteColor];
self.splashAd = [[OSETSplashAd alloc] initWithSlotId:@"18666EAA65EC1969E90E982DCA2CB2DD"
window:self.window
bottomView:imageView];
self.splashAd.delegate = self;
NSLog(@"开始请求开屏广告");
[self.splashAd loadAdDataAndShow];
}
/// 开屏关闭
/// 注意:开屏广告横屏的时候放不出来
- (void)splashDidClose:(id)splashAd{
NSLog(@"开屏关闭");
self.splashAd.delegate = nil;
self.splashAd = nil;
}
@end
可能遇到的问题
问题一
编译报错
‘/Users/pengyulin/Workspaces/iOS/ad/AdSet5/Libraries/Plugins/KSAdSDK.framework/KSAdSDK’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file ‘/Users/pengyulin/Workspaces/iOS/ad/AdSet5/Libraries/Plugins/KSAdSDK.framework/KSAdSDK’ for architecture arm64
问题二
编译报错
Command CodeSign failed with a nonzero exit code.
两个证书冲突所致
Budle Identifier不同也会出现以上问题。
问题三
上传报错
The operation couldn’t be completed. (DVFFoundation.DVTCodeSignerError error 0.)
相关日志如下图:
Unity FrameWork没有Sign
问题四
上传报错
先CD到目录(xxx/xxx.framework)下 lipo -info xxxxx 例
lipo -info KsAdSDK
移除模拟器架构
lipo -remove x86_64 KsAdSDK -o KsAdSDK
lipo -remove i386 KsAdSDK -o KsAdSDK