Android 广告聚合模块的设计与实现

demo地址

https://github.com/mayangming/AdGroupSample.git

广告聚合模块设计的整体思路

​ 设计一个模块需要从实际业务出发进行整体规划,凭空想象出来的模块逻辑必然会顾此失彼,不切实际,难以深入。本模块目的是为了整合世面上多种广告渠道,对外提供统一接口,由系统后台进行配置,来达到自由切换不同广告渠道的目的。

​ 由于各个渠道的广告厂家实现方式彼此不同,功能配置差异众多。所以该版本的第一版旨在消除差异,整合统一功能。后续功能则根据具体业务需要对各家功能进行特色化配置。

​ 该广告聚合模块初期只整合今日头条的穿山甲广告和腾讯的广点通广告中的开屏广告、激励视频广告、插屏广告和Banner广告。

广告聚合模块设计的代码思路

​ 顶层提供统一接口,中间由不同的厂商进行实现兼容,最上层根据不同配置生成对应的厂商实体,然后对其接口api进行包装,然后提供给外围应用使用该函数。其中的配置参数由接口提供,然后代码进行动态更改。本示例只提供大致代码实现方式,具体demo上传至github。

管理器代码

主要是用来对广告SDK进行全局初始化,这是根据SDK写的,SDK需要进行全局初始化,视情况编写

对外提供的管理类

/** SDK管理类
 *  需要在Application进行初始化
 * */
public class DqSdkManager{
    private static DqSdkManager dqSdkManager;
    private SDKAdBuild sdkAdBuild;
    static {
        dqSdkManager = new DqSdkManager();
    }
    public static DqSdkManager getInstance(){
        return dqSdkManager;
    }

    /**
     * 初始化广告SDK
     * 需要在使用之前进行初始化
     * */
    public void initSDKAd(@NonNull SDKAdBuild sdkAdBuild){
        this.sdkAdBuild = sdkAdBuild;
        switch (sdkAdBuild.type){
            case AD_TT:
                TTAdManagerHolder.init(context,sdkAdBuild);
                break;
            case AD_GDT:
                GDTADManagerHolder.get(context,sdkAdBuild.mAppId);
        }
    }

    public AdType getAdType(){
        return sdkAdBuild.type;
    }
}

基础配置类:

/**
 * 广告配置类
 * */
public class SDKAdBuild{
    //    public String mGDTAppId = "1110071026";// 必选参数,设置应用的AppId
//    public String mAppId = "1110071026";//广点通的APPID, 必选参数,设置应用的AppId
        public String mAppId = "5001121";//穿山甲的appId, 必选参数,设置应用的AppId
    public String mAppName = "APP测试媒体";// 必选参数,设置应用名称

    public AdType type = AdType.AD_TT;//广告类型

    //插屏广告
//    public static final String rewardAdCode = "945087494";//线上环境
//    public static final String rewardAdCode = "901121593";//测试环境
//   穿山甲插屏广告
//    public static final String interactionExpressAdCode = "945179313";//测试环境
    public static final String interactionExpressAdCode = "901121133";//测试环境

    //    广点通插屏广告
//    public static final String interactionExpressAdCode = "7021811287184079";//测试环境

    //穿山甲激励视频
    public static final String rewardAdCode = "901121365";//测试环境

    //广点通激励视频
//    public static final String rewardAdCode = "3091616226721647";//测试环境

    //穿山甲开屏广告
    public static final String splashAdCode = "801121648";//测试环境
    //广点通开屏广告
//    public static final String splashAdCode = "5081012267319394";//测试环境

    //穿山甲Banner广告
    public static final String bannerAdCode = "901121895";//Banner广告Id,下载
//   广点通Banner广告
//    public static final String bannerAdCode = "4081919278805485";//Banner广告Id,下载


}

上层使用方式

        SDKAdBuild sdkAdBuild = new SDKAdBuild();
        sdkAdBuild.mAppName = "斗圈";
        sdkAdBuild.type = AdType.AD_TT;//进行切换广告方式
        DqSdkManager.getInstance().initSDKAd(sdkAdBuild);




广点通广告管理器


/**
 * 腾讯广点通广告管理器
 */
public class GDTADManagerHolder {
    /**
     * @param application
     * @param appId 您在腾讯联盟开发者平台的APPID
     */
    public static void get(Context context, String appId){
        GDTADManager.getInstance().initWith(context, appId);
    }
}



今日头条穿山甲广告管理类

/**
 * 今日头条穿山甲广告管理类
 */
public class TTAdManagerHolder {

    private static boolean sInit;


    public static TTAdManager get() {
        if (!sInit) {
            throw new RuntimeException("TTAdSdk is not init, please check.");
        }
        return TTAdSdk.getAdManager();
    }

    public static void init(Context context,SDKAdBuild sdkAdBuild) {
        doInit(context,sdkAdBuild);
    }

    //step1:接入网盟广告sdk的初始化操作,详情见接入文档和穿山甲平台说明
    private static void doInit(Context context,SDKAdBuild sdkAdBuild) {
        if (!sInit) {
            TTAdSdk.init(context, buildConfig(sdkAdBuild));
            sInit = true;
        }
    }

    private static TTAdConfig buildConfig(SDKAdBuild sdkAdBuild) {
        return new TTAdConfig.Builder()
                .appId(sdkAdBuild.mAppId)
                .useTextureView(true) //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景,可以使用TextureView
                .appName(sdkAdBuild.mAppName)
                .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)
                .allowShowNotify(true) //是否允许sdk展示通知栏提示
                .allowShowPageWhenScreenLock(true) //是否在锁屏场景支持展示广告落地页
                .debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
                .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI, TTAdConstant.NETWORK_STATE_3G) //允许直接下载的网络状态集合
                .supportMultiProcess(false)//是否支持多进程
                //.httpStack(new MyOkStack3())//自定义网络库,demo中给出了okhttp3版本的样例,其余请自行开发或者咨询工作人员。
                .build();
    }
}

开屏广告功能实现

开屏广告接口实现

public interface AdSplashCompatIpc {
    /**
     * 加载开屏广告
     * @param adCode 广告位ID
     * @param timeOut 超时时间
     * @param splashAdListener 加载监听
     */
    void loadSplash(String adCode, int timeOut, SdkSplashIpc splashAdListener);

    /**
     * 加载开屏广告
     * @param adCode 广告位ID
     * @param splashAdListener 加载监听
     */
    void loadSplash(String adCode, SdkSplashIpc splashAdListener);

    /**
     * 显示开屏引导页的广告
     * @param container
     */
    void showSplashAd(ViewGroup container);
}

开屏广告包装类实现

/**
 * 开屏广告包装类
 */
public class SplashAdCompat implements AdSplashCompatIpc{
    private AdType adType = AdType.AD_TT;
    private AdSplashIpc adSplashIpc;
    public SplashAdCompat(Activity context) {
        this.adType = DqSdkManager.getInstance().getAdType();
        switch (adType){
            case AD_GDT:
                adSplashIpc = new GDTSplashAd(context);
                break;
            case AD_TT:
                adSplashIpc = new TTSplashAd(context);
                break;
        }
    }

    @Override
    public void loadSplash(String adCode, int timeOut, SdkSplashIpc splashAdListener) {
        adSplashIpc.loadSplash(adCode,timeOut,splashAdListener);
    }

    @Override
    public void loadSplash(String adCode, SdkSplashIpc splashAdListener) {
        adSplashIpc.loadSplash(adCode,splashAdListener);
    }

    @Override
    public void showSplashAd(ViewGroup container) {
        adSplashIpc.showSplashAd(container);
    }
}

开屏广告基础类

/**
 * 开屏广告基础类
 */
public abstract class AdSplashIpc implements AdSplashCompatIpc{
    private Context context;

    public AdSplashIpc(Context context) {
        this.context = context;
    }
}

广点通开屏广告具体实现

/**
 * 广点通开屏广告
 */
public class GDTSplashAd extends AdSplashIpc{
    private SplashAD splashAD;
    private Activity activity;
    public GDTSplashAd(Activity activity) {
        super(activity);
        this.activity = activity;
    }

    @Override
    public void loadSplash(String adCode, int timeOut, SdkSplashIpc splashAdListener) {
        splashAD = new SplashAD(activity,adCode,splashAdListener.getGDTAdListener(),timeOut);
        splashAD.fetchAdOnly();
    }

    @Override
    public void loadSplash(String adCode, SdkSplashIpc splashAdListener) {
        splashAD = new SplashAD(activity,adCode,splashAdListener.getGDTAdListener());
        splashAD.fetchAdOnly();
    }

    @Override
    public void showSplashAd(ViewGroup container) {
        splashAD.showAd(container);
    }
}

今日头条穿山甲广告具体实现

/**
 * 穿山甲开屏广告
 * */
public class TTSplashAd extends AdSplashIpc{
//    private Context context;
    private TTAdNative mTTAdNative;
    private SdkSplashIpc sdkSplashIpc;
    public TTSplashAd(Context context){
        super(context);
        mTTAdNative = TTAdManagerHolder.get().createAdNative(context);
    }

    /**
     * @param adCode 广告ID
     */
    public void loadSplash(String adCode, SdkSplashIpc splashAdListener){
        loadSplash(adCode,3000,splashAdListener);
    }
    /**
     * @param adCode 广告ID
     * @param timeOut 广告超时时间,默认3000秒
     */
    public void loadSplash(String adCode, int timeOut, SdkSplashIpc splashAdListener){
        this.sdkSplashIpc = splashAdListener;
        //step3:创建开屏广告请求参数AdSlot,具体参数含义参考文档
        AdSlot adSlot = new AdSlot.Builder()
//                .setCodeId("801121648")
                .setCodeId(adCode)
                .setSupportDeepLink(true)
                .setImageAcceptedSize(1080, 1920)
                .build();
        //step4:请求广告,调用开屏广告异步请求接口,对请求回调的广告作渲染处理
        mTTAdNative.loadSplashAd(adSlot, splashAdListener.getTtAdListener(),timeOut);
    }

    /**
     * 显示广告
     * @param container
     */
    @Override
    public void showSplashAd(ViewGroup container) {
        container.removeAllViews();
        container.addView(sdkSplashIpc.getDefaultTTSplashAd().getSplashView());
    }
}

广告加载过程接口监听

/**
 * 开屏广告加载监听
 */
public abstract class SdkSplashIpc {
    TTAdNative.SplashAdListener ttAdListener;
    DefaultTTSplashAd defaultTTSplashAd;
    SplashADListener gdtADListener;
    long millisUntilFinished = 0;
    public abstract void splashOnError(int i, String s);
    public abstract void splashOnTimeout();
    /**
     * 加载完成
     */
    public abstract void splashComplete();

    /**
     * 跳过
     */
    public abstract void OnAdSkip();
    /**
     * 倒计时结束
     */
    public abstract void OnAdTimeOver();

    public SdkSplashIpc() {
        ttAdListener = new TTAdNative.SplashAdListener(){
            @Override
            public void onError(int i, String s) {
                splashOnError(i,s);
            }

            @Override
            public void onTimeout() {
                splashOnTimeout();
            }

            @Override
            public void onSplashAdLoad(final TTSplashAd ttSplashAd) {
                defaultTTSplashAd = new DefaultTTSplashAd(){
                    @NonNull
                    @Override
                    public View getSplashView() {
                        Log.e("YM","getSplashView");
                        return ttSplashAd.getSplashView();
                    }
                };
                ttSplashAd.setSplashInteractionListener(new TTSplashAd.AdInteractionListener(){
                    @Override
                    public void onAdClicked(View view, int i) {

                    }

                    @Override
                    public void onAdShow(View view, int i) {
                        Log.e("YM","onAdShow");
                    }

                    @Override
                    public void onAdSkip() {
                        Log.e("YM","onAdSkip");
                        OnAdSkip();
                    }

                    @Override
                    public void onAdTimeOver() {
                        Log.e("YM","onAdTimeOver");
                        OnAdTimeOver();
                    }
                });
//                splashSplashView(defaultTTSplashAd);
//                splashBuild.container.removeAllViews();
//                splashBuild.container.addView(ttSplashAd.getSplashView());
                splashComplete();
            }
        };


        gdtADListener = new SplashADListener() {
            @Override
            public void onADDismissed() {
                Log.e("YM","onADDismissed");
                if (500 >= millisUntilFinished){//小于等于500的时候是时间到期了,因为时间计算不会精确到0
                    OnAdTimeOver();
                }else {//时间不为0时候是点击跳过的操作
                    OnAdSkip();
                }
                millisUntilFinished = 0;
            }

            @Override
            public void onNoAD(AdError adError) {
                Log.e("YM","onNoAD:"+adError.getErrorCode()+"---message:"+adError.getErrorMsg());
                splashOnError(adError.getErrorCode(),adError.getErrorMsg());
            }

            @Override
            public void onADPresent() {
                Log.e("YM","onADPresent");
            }

            @Override
            public void onADClicked() {
                Log.e("YM","onADClicked");
            }

            @Override
            public void onADTick(long l) {
                Log.e("YM","onADTick:"+l);
                millisUntilFinished = l;
            }

            @Override
            public void onADExposure() {
                Log.e("YM","onADExposure");
            }

            @Override
            public void onADLoaded(long l) {
                Log.e("YM","onADLoaded");
//                splashSplashView(defaultTTSplashAd);
                splashComplete();
            }
        };
    }

    public TTAdNative.SplashAdListener getTtAdListener() {
        return ttAdListener;
    }

    public SplashADListener getGDTAdListener() {
        return gdtADListener;
    }

    public DefaultTTSplashAd getDefaultTTSplashAd() {
        return defaultTTSplashAd;
    }
}

开屏广告上层调用方式

SplashAdCompat splashAdCompat = new SplashAdCompat(this);
splashAdCompat.loadSplash(SDKAdBuild.splashAdCode, 3000, new SdkSplashIpc() {
    //        splashAd.loadSplash("838455362", 3000, new SdkSplashInter() {

    @Override
    public void splashComplete() {
        mSplashContainer.setVisibility(View.VISIBLE);
        splashAdCompat.showSplashAd(mSplashContainer);
    }

    @Override
    public void splashOnError(int i, String s) {
        Log.e("YM","出错");
    }

    @Override
    public void splashOnTimeout() {
        Log.e("YM","超时");
    }

    @Override
    public void OnAdSkip() {
        Log.e("YM","跳过");
        goToMainActivity();
    }

    @Override
    public void OnAdTimeOver() {
        Log.e("YM","倒计时结束");
        goToMainActivity();
    }
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章