Unity接入Adxmi广告步骤

  最近在接入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];
    }
}

kisence

潮落江平未有风。