Android 穿山甲廣告聯盟接入


https://blog.csdn.net/unreliable_narrator/article/details/106637700

 

一、SDK接入

參考官方接入文檔,基於穿山甲版本號: 3.1.0.0
導入 aar 及 SDK 依賴的 jar 包

將本 SDK 壓縮包內的 open_ad_sdk.aar 復制到 Application Module/libs 文件夾(沒有的話須手動創建), 並將以下代碼添加到您 app 的

repositories {
    flatDir {
        dirs 'libs'
    }
}
depedencies {
    compile(name: 'open_ad_sdk', ext: ‘aar')
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
添加權限

穿山甲SDK建議您添加下述權限,並建議在您的隱私協議中向開發者聲明穿山甲SDK會獲取下述權限並應用於廣告投放。

<!--必要權限-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!--可選權限-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.GET_TASKS"/>

<!--可選,穿山甲提供“獲取地理位置權限”和“不給予地理位置權限,開發者傳入地理位置參數”兩種方式上報用戶位置,兩種方式均可不選,添加位置權限或參數將幫助投放定位廣告-->
<!--請注意:無論通過何種方式提供給穿山甲用戶地理位置,均需向用戶聲明地理位置權限將應用於穿山甲廣告投放,穿山甲不強制獲取地理位置信息-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- 如果有視頻相關的廣告且使用textureView播放,請務必添加,否則黑屏 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注意:穿山甲SDK不強制獲取以上權限,即使沒有獲取可選權限SDK也能正常運行;獲取以上權限將幫助穿山甲優化投放廣告精准度和用戶的交互體驗,提高eCPM。

為獲取更好的廣告推薦效果,以及提高激勵視頻廣告、下載類廣告等填充率,建議在廣告請求前,合適的時機調用 SDK 提供的方法,如在用戶第一次啟動您的 app 后的主界面時調用如下方法:

TTAdManager接口中的方法,context可以是Activity或Application
void requestPermissionIfNecessary(Context context);

  • 1
  • 2
  • 3
適配 Android7.0 及以上

如果您的應用需要在 Android7.0 及以上環境運行,請在 AndroidManifest 中添加如下代碼:

<provider
 android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
 android:authorities="${applicationId}.TTFileProvider"
 android:exported="false"
 android:grantUriPermissions="true">
<meta-data
     android:name="android.support.FILE_PROVIDER_PATHS"
     android:resource="@xml/file_paths" />
</provider>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在 res/xml 目錄下,新建一個 xml 文件 file_paths,在該文件中添加如下代碼:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="tt_external_root" path="." />
    <external-path name="tt_external_download" path="Download" />
    <external-files-path name="tt_external_files_download" path="Download" />
    <files-path name="tt_internal_file_download" path="Download" />
    <cache-path name="tt_internal_cache_download" path="Download" />
</paths>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
為了適配下載和安裝相關功能,在工程中引用的包 com.android.support:support-v4:24.2.0
使用24.2.0以及以上版本。
  • 1
  • 2
provider 配置

注意:單進程或多進程都必須配置

<provider
    android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
    android:authorities="${applicationId}.TTMultiProvider"
    android:exported="false" />
  • 1
  • 2
  • 3
  • 4
代碼混淆配置

如果您需要使用 proguard 混淆代碼,需確保不要混淆 SDK 的代碼。 請在 proguard.cfg 文件(或其他混淆文件)尾部添加如下配置:

-keep class com.bytedance.sdk.openadsdk.** { *; }
-keep public interface com.bytedance.sdk.openadsdk.downloadnew.** {*;}
-keep class com.pgl.sys.ces.* {*;}

  • 1
  • 2
  • 3
  • 4

注意

  • SDK 代碼被混淆后會導致廣告無法展現或者其它異常。

  • 本 SDK 最低支持 Android4.0 (API Level 14) 及以上版本。

  • targetSdkVersion API 23及以上,需要動態獲取權限,所以請確保調用本SDK的任何接口前,已經申請到了SDK要求的所有權限,否則SDK部分特性可能受限。

  • SDK中使用的so文件支持五種架構:x86,x86_64,armeabi,armeabi-v7a,arm64-v8a 如果您應用中支持的架構超出這 五種,請在build.gradle中使用abiFilters選擇支持的架構。

 ndk { // 設置支持的 SO 庫構架,注意這里要根據你的實際情況來設置 
        abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'armeabi'
      }
  • 1
  • 2
  • 3
SDK 初始化配置

開發者需要在 Application#onCreate()方法中調用以下代碼來初始化穿山甲 sdk。 目前 sdk 已支持多進程,必須在所有進程都初始化!

public class DemoApplication extends Application {
    public static String PROCESS_NAME_XXXX = "process_name_xxxx";

    @Override
    public void onCreate() {
        super.onCreate();

        //強烈建議在應用對應的Application#onCreate()方法中調用,避免出現content為null的異常
        TTAdSdk.init(context,
                            new TTAdConfig.Builder()
                                    .appId("5001121")
                                    .useTextureView(false) //使用TextureView控件播放視頻,默認為SurfaceView,當有SurfaceView沖突的場景,可以使用TextureView
                                    .appName("APP測試媒體")
                                    .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)
                                    .allowShowNotify(true) //是否允許sdk展示通知欄提示
                                    .allowShowPageWhenScreenLock(true) //是否在鎖屏場景支持展示廣告落地頁
                                    .debug(true) //測試階段打開,可以通過日志排查問題,上線時去除該調用
                                    .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI, TTAdConstant.NETWORK_STATE_4G) //允許直接下載的網絡狀態集合
                                    .supportMultiProcess(false) //是否支持多進程,true支持
                                    //.httpStack(new MyOkStack3())//自定義網絡庫,demo中給出了okhttp3版本的樣例,其余請自行開發或者咨詢工作人員。
                                    .build());

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
初始化接口說明
    /**
     *穿山甲sdk初始化入口
     *
     * @param context 必須是application context
     * @param config  初始化配置信息,必要參數
     * @return TTAdManager實例
     */
    public static TTAdManager init(Context context, TTAdConfig config);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
初始化配置參數說明:
    public static class TTAdConfig.Builder {
        private String mAppId;// 必選參數,設置應用的AppId
        private String mAppName;// 必選參數,設置應用名稱
        private boolean mIsPaid = false;// 可選參數,設置是否為計費用戶:true計費用戶、false非計費用戶。默認為false非計費用戶
        private int mGender = TTAdConstant.GENDER_UNKNOWN;// 可選參數,設置用戶性別。默認為未知TTAdConstant#GENDER_UNKNOWN
        private int mAge;// 可選參數,設置用戶年齡 **須大於0**
        private String mKeywords;// 可選參數,設置用戶畫像的關鍵詞列表 **不能超過為1000個字符**
        private String mData;// 可選參數,設置額外的用戶信息 **不能超過為1000個字符**
        private int mTitleBarTheme = TTAdConstant.TITLE_BAR_THEME_LIGHT;// 可選參數,設置落地頁主題,默認為TTAdConstant#TITLE_BAR_THEME_LIGHT
        private boolean mAllowShowNotify = true;// 可選參數,設置是否允許SDK彈出通知:true允許、false禁止。默認為true允許
        private boolean mIsDebug = false;// 可選參數,是否打開debug調試信息輸出:true打開、false關閉。默認false關閉
        private boolean mAllowShowPageWhenScreenLock = false;// 可選參數,設置是否允許落地頁出現在鎖屏上面:true允許、false禁止。默認為false禁止
        private int[] mDirectDownloadNetworkType;
        private boolean mIsUseTextureView = false;// 可選參數,設置是否使用texture播放視頻:true使用、false不使用。默認為false不使用(使用的是surface)
        private boolean mIsSupportMultiProcess = false;// 可選參數,設置是否支持多進程:true支持、false不支持。默認為false不支持
        private IHttpStack mHttpStack;//可選參數,設置外部網絡請求,默認為urlconnection
        private boolean mIsAsyncInit = false;//是否異步初始化sdk
        private TTCustomController mCustomController;//可選參數,可以設置隱私信息控制開關
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

二、加載廣告

創建廣告插槽。

  • 構建TTAdManager對象
    TTAdManager對象為整個SDK的入口接口,可用於廣告獲取、權限請求、版本號獲取
    TTAdManager ttAdManager = TTAdManagerHolder.get();

  • 申請部分權限 (建議每次廣告對象加載之后都需要申請一次 ps:開屏視頻不需要)
    TTAdManagerHolder.get().requestPermissionIfNecessary(this);

  • 創建TTAdNative對象(用於調用廣告請求接口)
    TTAdNative mTTAdNative = ttAdManager.createAdNative(getApplicationContext());

  • 構建AdSlot對象(廣告插槽),具體構建參數根據文檔來。

     AdSlot adSlot = new AdSlot.Builder()
             .setCodeId("廣告位id") //必選參數 設置您的CodeId
             .setSupportDeepLink(true)
             .setAdCount(1) //請求廣告數量為1到3條
             .setExpressViewAcceptedSize(expressViewWidth,expressViewHeight) //期望模板廣告view的size,單位dp
             .setImageAcceptedSize(350 ,500 )//這個參數設置即可,不影響模板廣告的size
             .build();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在創建廣告插槽的時候有一個必選參數廣告位id,那么這個值是從哪里來的,又有什么作用呢?

廣告類型

想要了解廣告位id從哪里來的,我們首先需要打開穿山甲廣告的管理后台:

創建新的應用:

建議為測試集成完畢后再把應用及對應的代碼位改成正式狀態。
應用ID 是對應demo中的APPID。

創建新的代碼位:

廣告位ID 對應demo中的CodeId。就是一個標識用來加載不同種類的廣告類型。
應用ID和代碼位ID是對應關系 一個應用可以對應多個代碼位ID。
注意:新建的廣告CodeId,要等一會兒使用,否則就會出現ID無效。

點擊新創建的應用的新建代碼位:

代碼位

可以看到有多種樣式的廣告進行選擇。

例如我想要創建一個banner廣告,則進入bannner廣告創建頁面。

可以看到對應的選項。

原生、自渲染和模板渲染的區別
  • 自渲染和原生渲染(已經被廢棄了):
    現在已經被廢棄了,簡單來說,就是穿山甲返回廣告的子元素,如標題,描述,圖片等,你自己拼裝成自己喜歡的界面展示。
  • 模板渲染廣告:
    目前申請的廣告樣式只有這一類,廣告用webview(網頁)展示。接入者在穿山甲后台,選擇自己需要的樣式進行顯示就可以,如:上圖下文,左圖右文等多種形式。也就是穿山甲會直接返回一個view 不支持獲取view的信息 開發者直接展示view即可。

三、展示廣告

開屏廣告

開屏廣告建議為用戶在進入 App 時展示的全屏廣告。開屏廣告為一個 View,寬高默認為 match_parent,注意開屏廣告 view:width >=70%屏幕寬;height >=50%屏幕高 ,否則會影響計費。

 TTAdNative adNative = TTAdManagerHolder.INSTANCE.get().createAdNative(this);

        AdSlot adSlot = new AdSlot.Builder()
                .setCodeId(CodeId)
                .setSupportDeepLink(true)
                .setImageAcceptedSize(DisplayUtils.getScreenWidth(this), DisplayUtils.getScreenHeight(this))
                .build();
        //加載
        adNative.loadSplashAd(adSlot, new TTAdNative.SplashAdListener() {
            @Override
            public void onError(int code, String message) {
                Log.d(TAG, "開屏廣告請求失敗" + message);
                dumpNextPage();
            }

            @Override
            public void onTimeout() {
                Log.d(TAG, "開屏廣告請求超時");
                dumpNextPage();
            }

            @Override
            public void onSplashAdLoad(TTSplashAd ad) {
                Log.d(TAG, "開屏廣告請求成功");
                if (ad == null) {
                    dumpNextPage();
                    return;
                }
                //獲取SplashView
                View view = ad.getSplashView();
                if (view != null && videoContainer != null && !LaunchActivity.this.isFinishing()) {
                    videoContainer.removeAllViews();
                    //把SplashView 添加到ViewGroup中,注意開屏廣告view:width >=70%屏幕寬;height >=50%屏幕高
                    videoContainer.addView(view);
                    //設置不開啟開屏廣告倒計時功能以及不顯示跳過按鈕,如果這么設置,您需要自定義倒計時邏輯
                    //ad.setNotAllowSdkCountdown();
                } else {
                    dumpNextPage();
                }

                //設置SplashView的交互監聽器
                ad.setSplashInteractionListener(new TTSplashAd.AdInteractionListener() {
                    @Override
                    public void onAdClicked(View view, int type) {
                        Log.d(TAG, "onAdClicked開屏廣告點擊");
                    }

                    @Override
                    public void onAdShow(View view, int type) {
                        Log.d(TAG, "onAdShow開屏廣告展示");
                    }

                    @Override
                    public void onAdSkip() {
                        Log.d(TAG, "onAdSkip開屏廣告跳過");
                        dumpNextPage();
                    }

                    @Override
                    public void onAdTimeOver() {
                        Log.d(TAG, "onAdTimeOver開屏廣告倒計時結束");
                        dumpNextPage();
                    }
                });
                //廣告交互類型未下載廣告,需要設置廣告下載監聽
                if (ad.getInteractionType() == TTAdConstant.INTERACTION_TYPE_DOWNLOAD) {
                    ad.setDownloadListener(new TTAppDownloadListener() {
                        boolean hasShow = false;

                        @Override
                        public void onIdle() {
                        }

                        @Override
                        public void onDownloadActive(long totalBytes, long currBytes, String fileName, String appName) {
                            if (!hasShow) {
                                Log.d(TAG, "開屏廣告下載中");
                                hasShow = true;
                            }
                        }

                        @Override
                        public void onDownloadPaused(long totalBytes, long currBytes, String fileName, String appName) {
                            Log.d(TAG, "開屏廣告下載暫停");
                        }

                        @Override
                        public void onDownloadFailed(long totalBytes, long currBytes, String fileName, String appName) {
                            Log.d(TAG, "開屏廣告下載失敗");
                        }

                        @Override
                        public void onDownloadFinished(long totalBytes, String fileName, String appName) {
                            Log.d(TAG, "開屏廣告下載完成");
                        }

                        @Override
                        public void onInstalled(String fileName, String appName) {
                            Log.d(TAG, "開屏廣告安裝完成");
                        }
                    });
                }
            }
        }, AD_TIME_OUT);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
信息流廣告

信息流廣告即app推薦頁/詳情頁中的原生圖文及視頻廣告,主要特點是精准算法推薦、原生體驗對用戶干擾低。

    /**
     * 加載feed廣告
     */
    private fun loadListAd() {
        val mTTAdNative = TTAdManagerHolder.get().createAdNative(this)
        TTAdManagerHolder.get().requestPermissionIfNecessary(this)
        //創建feed廣告請求類型參數AdSlot,具體參數含義參考文檔
        val adSlot = AdSlot.Builder()
            .setCodeId("945230381")
            .setSupportDeepLink(true)
            .setExpressViewAcceptedSize(250f, 300f) //期望模板廣告view的size,單位dp
            .setAdCount(3) //請求廣告數量為1到3條
            .build()
        //step5:請求廣告,調用feed廣告異步請求接口,加載到廣告后,拿到廣告素材自定義渲染
        mTTAdNative.loadNativeExpressAd(adSlot, object : TTAdNative.NativeExpressAdListener {
            override fun onError(code: Int, message: String) {
                Log.e("loadFeedAd", "code: : $code  message :$message")
            }

            override fun onNativeExpressAdLoad(ads: List<TTNativeExpressAd>?) {
                if (ads == null || ads.isEmpty()) {
                    Log.i("loadFeedAd", "on FeedAdLoaded: ad is null!")

                    return
                }
                Log.i("loadFeedAd", "FeedAdLoaded: ad is success===============" + ads.size)
                bindAdListener(ads)
            }
        })
    }

    private fun bindAdListener(ads: List<TTNativeExpressAd>) {
        for (ad in ads) {
            ad.setExpressInteractionListener(object :
                TTNativeExpressAd.ExpressAdInteractionListener {
                override fun onAdClicked(view: View, type: Int) {
                    Log.i("loadFeedAd", "廣告被點擊")
                }

                override fun onAdShow(view: View, type: Int) {
                    Log.i("loadFeedAd", "廣告展示")
                }

                override fun onRenderFail(view: View, msg: String, code: Int) {
                    Log.i("loadFeedAd", "$msg code:$code")
                }

                override fun onRenderSuccess(view: View, width: Float, height: Float) {
                    //返回view的寬高 單位 dp
                    Log.i("loadFeedAd", "渲染成功")
                }
            })
            ad.render()
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

注:模板類型的代碼位在設置AdSlot廣告對象的時候一定要設置該方法setExpressViewAcceptedSize

注:在廣告加載展示完畢后 在Activity的onDestroy方法中把廣告對象置為null

banner

Banner廣告可以在您設定刷新時間后自動刷新。也就是說,即使用戶停留在同一個屏幕上,他們也會 每隔一段時間就看到新的Banner廣告。

        val mTTAdNative = TTAdManagerHolder.get().createAdNative(this)
        TTAdManagerHolder.get().requestPermissionIfNecessary(this)
        val adSlot = AdSlot.Builder()
            .setCodeId("945230387")
            .setSupportDeepLink(true)
            .setExpressViewAcceptedSize(
                150f,
                300f
            ) //期望模板廣告view的size,單位dp
            .setAdCount(3) //請求廣告數量為1到3條
            .setNativeAdType(AdSlot.TYPE_BANNER)
            .build()

        mTTAdNative.loadBannerExpressAd(adSlot, object : TTAdNative.NativeExpressAdListener {
            override fun onNativeExpressAdLoad(ads: MutableList<TTNativeExpressAd>?) {
                if (ads == null || ads.isEmpty()) {
                    Log.i("loadFeedAd", "on FeedAdLoaded: ad is null!")
                    return
                }
                Log.i("loadFeedAd", "FeedAdLoaded: ad is success===============" + ads.size)
                bindAdListener(ads)
            }

            override fun onError(code: Int, message: String) {
                Log.i("loadFeedAd", "code: :$code  message :$message")
            }
        })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

四、注意事項

  1. 為何廣告轉化率低?
    發布前,一定要測試整個廣告的展示,下載,安裝,激活流程。如果廣告能展示就發布了,完全沒測試廣告后續流程,就會導致廣告的CPM非常低。廣告cpm依賴廣告展示后的后續轉化,如:點擊,下載,安裝,激活,注冊,充值等。

  2. 存儲權限,imei權限,定位權限是必須的嗎?
    3個權限都不是必須的,但是如果有的話,大大提高廣告的Ecpm。
    有了存儲權限,就可以推下載類的廣告;
    有了imei權限,就能跟蹤后期轉化;
    有了定位權限,就可以推更加精准的廣告。

  3. 如何屏蔽競品廣告?
    在穿山甲后台可設置。

穿山甲(巨量引擎)廣告接入
Android端穿山甲SDK集成
穿山甲廣告使用秘籍


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM