最近在接入ADxmi的广告SDK,遇到了几个坑,把步骤和坑都记录在此。最下面附代码。
接入Android步骤
1.新建Android工程,选择AndroidLibrary
2.导入两个库classes.jar和AdxmiSdk2.1.02017-09-12.jar
3.添加类ADxmi.java,代码
4.在Gradle里添加代码,代码
5.执行exportJar 导出jar包
6.在Unity中调用我们的jar,代码
接入Ios步骤
1.在Plugins/IOS下导入三个文件,代码
2.导出Ios工程
3.在导出工程中增加
* libz.tbd
* libsqlite3.0.tbd
* WebKit.framework
* AdxmiMergeSDK.framework (这个与下面两个只选一个)
* AdxmiInterstitialAd.framework
* AdxmiVideoAd.framework
* 针对不同的广告类型再接入不同的广告联盟SDK
4. info.plist 文件中添加如下键值对
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
5.在项目 Build Settings 中的设置Other Linker Flags添加”-ObjC”
遇到的坑
1.导入到Unity项目中时,jar包必需显示有导入设置的选项,否则一定是获取不到的,解决办法:重新导入库文件,导入到项目中的时候一定要导入到Plugins/Android/下的libs、bin等特殊文件夹里的一个,否则仍然会导入失败。
2.要仔细查看找不到的类的名字,有时候类其实是找到了,但是在类构造的过程中有类找不到,也可能出现一个找不到目标类的报错,但是这个类的名字有细微的不同。
3.AndroidManifest文件,要放在Plugins/Android/下,不能放在其他路经,(或者说第一个AndroidManifest文件要放在这个路径下,此处待考证)
4.去掉android.permission.READ_PHONE_STATE权限,去掉项目中的SystemInfo.deviceUniqueIdentifier。
5.去掉android.permission.RECORD_AUDIO权限,去掉项目中的Microphone类。
附
类ADxmi.java源码
package slime.funycat.com.adxmisdk;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.adxmi.android.AdError;
import com.adxmi.android.AdxmiInterstitial;
import com.adxmi.android.AdxmiInterstitialListener;
import com.adxmi.android.AdxmiSdk;
import com.adxmi.android.AdxmiVideoAd;
import com.adxmi.android.AdxmiVideoAdListener;
import com.adxmi.android.VideoReward;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by GaiKai on 2017/9/18.
*/
public class ADxmi
{
public static String CallBackObjectName;
public static String CallBackFunctionName;
public static ADxmi instance;
public ADxmi()
{
}
public static void Init(String ObjName,String functionName)
{
Log.d("Unity","Recevice static Init! ObjName ->" + ObjName + "<- functionName ->" + functionName + "<-");
CallBackObjectName = ObjName;
CallBackFunctionName = functionName;
if (instance == null)
{
instance = new ADxmi();
}
}
private static void SendMessage(String param)
{
Log.d("Unity","SendMessage ->" + param + "<-");
UnityPlayer.UnitySendMessage(CallBackObjectName, CallBackFunctionName, param);
}
// com.internal.fileexplorer
private static String sAppId = "e8b19f2e0955d0b9";
private static String sAppSecret = "7539c5ae9890df4a";
public void Init(String appID,String appSecret,boolean isDebug)
{
Log.d("Unity","Recevice Init! appID ->" + appID + "<- appSecret ->" + appSecret + "<- isDebug " + isDebug);
sAppId = appID;
sAppSecret = appSecret;
// if(UnityPlayer.currentActivity.getMainLooper().pr)
try
{
UnityPlayer.currentActivity.getMainLooper().prepare();
}
catch (Exception e)
{}
mHandler = new Handler(UnityPlayer.currentActivity.getMainLooper());
//Initialization application
AdxmiSdk.init(UnityPlayer.currentActivity, sAppId, sAppSecret);
//设置userid
// AdxmiSdk.setUserId(this,"your_user_id");
// 打开调试开关,正式发布时可以关闭
//Open debug switch, can be closed when officially released
AdxmiSdk.setDebugLogEnable(isDebug);
}
public void Dispose()
{
mAdxmiInterstitialAd.destroy();
mAdxmiVideoAd.onDestroy();
}
//Handler,用于线程与UI交互
//Handler,For thread and UI interaction
private Handler mHandler;
private AdxmiInterstitial mAdxmiInterstitialAd;
private AdxmiVideoAd mAdxmiVideoAd;
/**
* 加载插屏广告--可以在Unity3d中直接调用
* load InterstitialAd,can call the method directly in unity3d
*/
public void loadInterstitialAd(String InterstitialID)
{
mAdxmiInterstitialAd = new AdxmiInterstitial(UnityPlayer.currentActivity, InterstitialID);
mAdxmiInterstitialAd.setListener(mAdxmiInterstitialListener);
ULog("Recevice loadInterstitialAd! InterstitialID ->" + InterstitialID + "<- ");
mHandler.post(new Runnable() {
@Override
public void run() {
if (mAdxmiInterstitialAd != null) {
mAdxmiInterstitialAd.load();
}
}
});
}
/**
* 展示插屏广告--可以在Unity3d中直接调用
* show InterstitialAd,can call the method directly in unity3d
*/
public void showInterstitialAd() {
ULog("showInterstitialAd");
mHandler.post(new Runnable() {
@Override
public void run() {
if (mAdxmiInterstitialAd != null && mAdxmiInterstitialAd.isReady()) {
mAdxmiInterstitialAd.show();
ULog("showInterstitialAd ==> show()");
}
else
{
ULog("mAdxmiInterstitialAd != null && mAdxmiInterstitialAd.isReady()");
}
}
});
}
private AdxmiInterstitialListener mAdxmiInterstitialListener = new AdxmiInterstitialListener() {
@Override
public void onLoadSuccess(AdxmiInterstitial adxmiInterstitial) {
ULog("Interstitial" + "-->" + "onLoadSuccess");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","LoadSuccess");
data.put("ADType","Interstitial");
data.put("Status","LoadSuccess");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onLoadFail(AdxmiInterstitial adxmiInterstitial, AdError adError) {
ULog("Interstitial" + "-->" + "onLoadFail" + "-->" + adError.getMessage());
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","LoadFailed");
data.put("ADType","Interstitial");
data.put("Status","LoadFailed");
data.put("Message",adError.getMessage());
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onShowSuccess(AdxmiInterstitial adxmiInterstitial) {
ULog("Interstitial" + "-->" + "onShowSuccess");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","ShowSuccess");
data.put("ADType","Interstitial");
data.put("Status","ShowSuccess");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onClick(AdxmiInterstitial adxmiInterstitial) {
ULog("Interstitial" + "-->" + "onClick");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","Click");
data.put("ADType","Interstitial");
data.put("Status","Click");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onClose(AdxmiInterstitial adxmiInterstitial) {
ULog("Interstitial" + "-->" + "onClose");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","Close");
data.put("ADType","Interstitial");
data.put("Status","Close");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
};
/**
* 加载视频广告--可以在Unity3d中直接调用
* load VideoAd,can call the method directly in unity3d
*/
public void loadVideoAd(String VideoID) {
mAdxmiVideoAd = new AdxmiVideoAd(UnityPlayer.currentActivity, VideoID);
mAdxmiVideoAd.setListener(mAdxmiVideoAdListener);
ULog("loadVideoAd");
mHandler.post(new Runnable() {
@Override
public void run() {
if (mAdxmiVideoAd != null) {
mAdxmiVideoAd.load();
ULog("mAdxmiVideoAd ==> load");
}
else
{
ULog("mAdxmiVideoAd == null");
}
}
});
}
/**
* 展示视频广告--可以在Unity3d中直接调用
* show VideoAd,can call the method directly in unity3d
*/
public void showVideoAd() {
ULog("showVideoAd");
mHandler.post(new Runnable() {
@Override
public void run() {
if (mAdxmiVideoAd != null && mAdxmiVideoAd.isReady()) {
mAdxmiVideoAd.show();
}
}
});
}
AdxmiVideoAdListener mAdxmiVideoAdListener = new AdxmiVideoAdListener()
{
@Override
public void onVideoLoaded(AdxmiVideoAd adxmiVideoAd) {
ULog("video" + "-->" + "onVideoLoaded");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","LoadSuccess");
data.put("ADType","Video");
data.put("Status","LoadSuccess");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onVideoShow(AdxmiVideoAd adxmiVideoAd) {
ULog("video" + "-->" + "onVideoShow");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","ShowSuccess");
data.put("ADType","Video");
data.put("Status","ShowSuccess");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onVideoStarted(AdxmiVideoAd adxmiVideoAd) {
ULog("video" + "-->" + "onVideoStarted");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","VideoStart");
data.put("ADType","Video");
data.put("Status","VideoStart");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onVideoClosed(AdxmiVideoAd adxmiVideoAd) {
ULog("video" + "-->" + "onVideoClosed");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","Close");
data.put("ADType","Video");
data.put("Status","Close");
jo.put("Data",data);
SendMessage(jo.toString());
}
catch (JSONException e)
{
e.printStackTrace();
}
}
@Override
public void onVideoRewarded(AdxmiVideoAd adxmiVideoAd, VideoReward reward) {
ULog("video --> onRewarded! currency: amount:");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","VideoRewarded");
data.put("ADType","Video");
data.put("Status","VideoRewarded");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onVideoClick(AdxmiVideoAd adxmiVideoAd) {
ULog("video" + "-->" + "onVideoClick");
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","Click");
data.put("ADType","Video");
data.put("Status","Click");
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onVideoLoadFailed(AdxmiVideoAd adxmiVideoAd, AdError error) {
ULog("video" + "-->" + "onVideoLoadFailed:" + error.getCode() + error.getMessage());
try {
JSONObject jo = new JSONObject();
JSONObject data = new JSONObject();
jo.put("FunctionName","LoadFailed");
data.put("ADType","Video");
data.put("Status","LoadFailed");
data.put("Message","Code:" + error.getCode() +" Message:"+ error.getMessage());
jo.put("Data",data);
SendMessage(jo.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
};
private void ULog(String msg) {
Log.e("Unity", msg);
}
}
AndroidStudio 导出Jar代码
dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.0.0' testCompile 'junit:junit:4.12' compile files('libs/AdxmiSdk_2.1.0_2017-09-12.jar') compile files('libs/classes.jar') } task deleteOldJar(type: Delete) { delete 'build/outputs/ADxmiSDK.jar' } task exportJar(type: Copy) { from('build/intermediates/bundles/release/') into('build/libs/') include('classes.jar') rename ('classes.jar', 'ADxmiSDK.jar') } exportJar.dependsOn(deleteOldJar, build)
Unity调用代码
public class AndroidImpl : AdxmiSDKImpl
{
private AndroidJavaObject ssdk;
public AndroidImpl(GameObject go)
{
Debug.Log("AndroidImpl ===>>> AndroidImpl");
try
{
AndroidJavaClass jc = new AndroidJavaClass("slime.funycat.com.adxmisdk.ADxmi");
jc.CallStatic("Init", go.name, "_Callback");
ssdk = jc.GetStatic("instance");
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
public override void GetSDKVerison()
{
}
public override void Init(string appId, string appSecret, bool isDebug)
{
Debug.Log("AndroidImpl ===>>> InitSDK === " + appId);
if (ssdk != null)
{
ssdk.Call("Init", appId, appSecret,isDebug);
}
if (ssdk != null)
{
ssdk.Call("loadInterstitialAd", appId);
}
}
public override void LoadInterstitialAd(string InterstitialID)
{
if (ssdk != null)
{
ssdk.Call("loadInterstitialAd", InterstitialID);
}
}
public override void LoadVideoAd(string VideoID)
{
if (ssdk != null)
{
ssdk.Call("loadVideoAd", VideoID);
}
}
}
IOS 广告接入代码
MyUMVideo.h
#import "Foundation/Foundation.h"
#import "AdxmiMergeSDK/AdxmiVideoAd.h"
#import "AdxmiMergeSDK/AdxmiInterstitialAd.h"
#import "AdxmiMergeSDK/AdxmiVideoAd.h"
@interface MyUMVideo : NSObject
<
AdxmiInterstitialDelegate,
AdxmiVideoDelegate>
+ (MyUMVideo*) SharedInstance;
- (void) initUmVideoAdAndInterstitialAd;
- (void) loadUmVideoAd;
- (void) showUmVideoAd;
- (void) loadUmInterstitialAd;
- (void) showUmInterstitialAd;
@property (nonatomic , strong) AdxmiVideoAd *videoAd;
@property (nonatomic , strong) AdxmiInterstitialAd *interstitialAd;
@property UIViewController *myviewController;
@property BOOL m_bShowingVideo;
@end
MyUMVideo.m
//
// MyUMVideo.m
// youmi
//
// Created by xstudio on 12/09/2017.
// Copyright © 2017 xstudio. All rights reserved.
//
#import "MyUMVideo.h"
@implementation MyUMVideo
+ (MyUMVideo*)SharedInstance
{
static MyUMVideo *single = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
single = [[self alloc]init];
});
return single;
}
- (void) initUmVideoAdAndInterstitialAd
{
_myviewController = [[[UIApplication sharedApplication].delegate window] rootViewController];
[AdxmiBaseSDK registerAppid:@"24a9185f3124f9c1" appsecret:@"1dda2d6fac1b0697"];
[AdxmiBaseSDK setLogLevel:AdxmiSDKLogLevelDebug];
_m_bShowingVideo = false;
}
- (void) loadUmVideoAd
{
if (self.videoAd) {
[self.videoAd destroy];
}
self.videoAd=[[AdxmiVideoAd alloc] initSlotId:@"320697942286240422"];
[self.videoAd setDelegate:self];
[self.videoAd load];
_m_bShowingVideo = false;
}
- (void)showUmVideoAd
{
if(_m_bShowingVideo == false)
{
_m_bShowingVideo = true;
_myviewController = [[[UIApplication sharedApplication].delegate window] rootViewController];
[self.videoAd show:_myviewController];
}
}
#pragma mark videoDelegate
- (void)onVideoLoaded:(AdxmiVideoAd *)videoAd {
//[self.videoAd show:_myviewController];
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"LoadSuccess\",\"Data\": {\"Status\": \"LoadSuccess\",\"ADType\": \"Video\"}}");
}
- (void)onVideoShow:(AdxmiVideoAd *)videoAd {
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"ShowSuccess\",\"Data\": {\"Status\": \"ShowSuccess\",\"ADType\": \"Video\"}}");
}
- (void)onVideoStarted:(AdxmiVideoAd *)videoAd {
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"VideoStart\",\"Data\": {\"Status\": \"VideoStart\",\"ADType\": \"Video\"}}");
}
- (void)onVideoClosed:(AdxmiVideoAd *)videoAd {
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"Close\",\"Data\": {\"Status\": \"Close\",\"ADType\": \"Video\"}}");
}
- (void)onVideoLoadFailed:(AdxmiVideoAd *)videoAd
error:(AdxmiError *)error {
NSString *content = [NSString stringWithFormat:@"{\"FunctionName\": \"LoadFailed\",\"Data\": {\"Status\": \"LoadFailed\",\"ADType\": \"Video\",\"Message\":\"%@\"}}", error.description];
UnitySendMessage("AdxmiSDK", "_Callback", [content UTF8String]);
}
- (void)onVideoRewarded:(AdxmiVideoAd *)videoAd
reward:(AdxmiVideoReward *)videoAdReward {
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"VideoRewarded\",\"Data\": {\"Status\": \"VideoRewarded\",\"ADType\": \"Video\"}}");
}
- (void)onVideoClick:(AdxmiVideoAd *)videoAd {
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"Click\",\"Data\": {\"Status\": \"Click\",\"ADType\": \"Video\"}}");
}
- (void) loadUmInterstitialAd
{
if (self.interstitialAd) {
[self.interstitialAd destroy];
}
self.interstitialAd=[[AdxmiInterstitialAd alloc] initSlotId:@"330897942297724427"];
//[self.interstitialAd setAdSource:source];
[self.interstitialAd setDelegate:self];
[self.interstitialAd load];
//[AdxmiViewBuild showLoad:YES];
}
- (void)showUmInterstitialAd
{
//[AdxmiViewBuild showLoad:NO];
_myviewController = [[[UIApplication sharedApplication].delegate window] rootViewController];
[self.interstitialAd show:_myviewController];
}
#pragma mark - AdxmiInterstitialDelegate
- (void)onLoadSuccess:(nonnull AdxmiInterstitialAd *)interstitialAd{
//[AdxmiViewBuild showLoad:NO];
//[self.interstitialAd show:_myviewController];
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"LoadSuccess\",\"Data\": {\"Status\": \"LoadSuccess\",\"ADType\": \"Interstitial\"}}");
}
- (void)onLoadFail:(nonnull AdxmiInterstitialAd *)interstitialAd error:(nonnull AdxmiError *)error{
//[AdxmiViewBuild showLoad:NO];
//[AdxmiViewBuild showErr:error.description rootCtrl:_myviewController];
NSString *content = [NSString stringWithFormat:@"{\"FunctionName\": \"LoadFailed\",\"Data\": {\"Status\": \"LoadFailed\",\"ADType\": \"Interstitial\",\"Message\":\"%@\"}}", error.description];
UnitySendMessage("AdxmiSDK", "_Callback", [content UTF8String]);
}
- (void)onShowSuccess:(nonnull AdxmiInterstitialAd *)interstitialAd{
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"ShowSuccess\",\"Data\": {\"Status\": \"ShowSuccess\",\"ADType\": \"Interstitial\"}}");
}
- (void)onClick:(nonnull AdxmiInterstitialAd *)interstitialAd{
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"Click\",\"Data\": {\"Status\": \"Click\",\"ADType\": \"Interstitial\"}}");
}
- (void)onClose:(nonnull AdxmiInterstitialAd *)interstitialAd{
UnitySendMessage("AdxmiSDK", "_Callback", "{\"FunctionName\": \"Close\",\"Data\": {\"Status\": \"Close\",\"ADType\": \"Interstitial\"}}");
}
@end
UMVideoAd.mm
#import "MyUMVideo.h"
extern "C"
{
void initUmVideoAdAndInterstitialAd()
{
[[MyUMVideo SharedInstance] initUmVideoAdAndInterstitialAd];
}
}
extern "C"
{
void loadUmVideoAd()
{
[[MyUMVideo SharedInstance] loadUmVideoAd];
}
}
extern "C"
{
void showUmVideoAd()
{
[[MyUMVideo SharedInstance] showUmVideoAd];
}
}
extern "C"
{
void loadUmInterstitialAd()
{
[[MyUMVideo SharedInstance] loadUmInterstitialAd];
}
}
extern "C"
{
void showUmInterstitialAd()
{
[[MyUMVideo SharedInstance] showUmInterstitialAd];
}
}