文章目錄
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();
}
});