Help Center/Details/

New Cinema Ads

Introduction

Slip ads: Slip ads are a form of video advertising. Developers can set the advertising space before/during/after playing the video in their APP. The duration of the patch advertisement can be set to a fixed duration, such as 5s/15s, etc.; the fixed duration can also be unlimited, and the system returns the highest-profit advertisement within the range of 5-60s to help developers maximize revenue. Patch ads currently only support self-rendering. You can use the default CSJ player, or you can apply for the developer's own player.

Permission

Self-rendered patch ads: By default, permission is required
SDK version requirements: 3400 and above

Self-rendering patch request method

Create TTAdNative object

//创建TTAdNative对象,createAdNative(Context context) context需要传入Activity对象
TTAdNative mTTAdNative = TTAdSdk.getAdManager().createAdNative(this);

Create ad request type parameter AdSlot

AdSlot adSlot = new AdSlot.Builder()
        .setCodeId(codeId)
        .setImageAcceptedSize(640, 320) // 单位px
        .setAdCount(3) //请求广告数量为1到3条
        .build();

Parameter Description

参数 说明
setCodeId The code ID created by the platform starts with 9 and 9 digits
setAdCount The number of requests is 1-3, it is recommended to set 1
setImageAcceptedSize Set the size of the requested ad Unit: px

Request ad

mTTAdNative.loadStream(adSlot, new TTAdNative.FeedAdListener)Method to load SMD ads asynchronously

mTTAdNative.loadStream(adSlot, new TTAdNative.FeedAdListener() {
	//请求广告失败
    @Override
    public void onError(int code, String message) {

      }
    //请求广告成功
    @Override
   public void onFeedAdLoad(List<TTFeedAd> ads) {
                if (ads == null || ads.isEmpty()) {
                    return;
                }
                if (mStreamAdPlayer != null) {
                    mStreamAdPlayer.clear();
                }
                // 使用自定义播放器需要考虑为视频Url预加载
                // 各家开发者的视频播放器个有不同
                // 需要预加载请在通过ttFeedAd.getCustomVideo().getVideoUrl()拿到视频url之后自行预加载
                mStreamAdPlayer = new StreamAdPlayer(ads, mAdLayout);

            }
});

FeedAdListener Description

Callback Description
onError() Request failed callback
onFeedAdLoad() Request success callback

TTFeedAd Interface Description

public interface TTFeedAd {

    /**
     * 获取穿山甲logo,图片大小:80*80
     *
     * @return bitmap对象
     */
    Bitmap getAdLogo();

    /**
     * 广告标题
     *
     * @return
     */
    String getTitle();

    /**
     * 广告描述
     *
     * @return
     */
    String getDescription();

    /**
     * 广告来源
     *
     * @return
     */
    String getSource();

    /**
     * 广告图标Image
     *
     * @return
     */
    TTImage getIcon();

    /**
     * 广告图片Image list
     *
     * @return
     */
    List<TTImage> getImageList();

    /**
     * 得到Feed广告交互类型,贴片广告近为视频广告
     *
     * @return 2:在浏览器打开网页,3:在app中打开,4:下载应用,5:拨打电话 其它:未知类型
     */
    int getInteractionType();

    /**
     * 得到Feed广告图片模式
     *
     * @return 3 大图 2小图 4 组图 5 视频 其它:未知类型
     */
    int getImageMode();

    /**
     * 获取下载状态控制器
     */
    DownloadStatusController getDownloadStatusController();

    /**
     * 注册可点击的View,click/show会在内部完成
     *
     * @param container 渲染广告最外层的ViewGroup
     * @param clickView 可点击的View
     */
    void registerViewForInteraction(@NonNull ViewGroup container, @NonNull View clickView, AdInteractionListener listener);

    /**
     * 注册可点击的View,click/show会在内部完成
     *
     * @param container     渲染广告最外层的ViewGroup
     * @param clickViews    可点击的View的列表
     * @param creativeViews 用于下载或者拨打电话的View
     */
    void registerViewForInteraction(@NonNull ViewGroup container, @NonNull List<View> clickViews, @Nullable List<View> creativeViews, AdInteractionListener listener);

    /**
     * 注册可点击的View,click/show会在内部完成,注册dislike按钮
     *
     * @param container     渲染广告最外层的ViewGroup
     * @param clickViews    可点击的View的列表
     * @param creativeViews 用于下载或者拨打电话的View
     * @param dislikeView   dislike按钮
     * @param listener      点击回调
     */
    void registerViewForInteraction(@NonNull ViewGroup container, @NonNull List<View> clickViews, @Nullable List<View> creativeViews, @Nullable View dislikeView, AdInteractionListener listener);

    /**
     * 设置下载监听器
     */
    void setDownloadListener(TTAppDownloadListener downloadListener);

    /**
     * 兼容下载类广告,使用activity申请权限
     */
    void setActivityForDownloadApp(@NonNull Activity activity);

    /**
     * 获取广告的view,如视频广告的view,在广告平台可设置是否自动播放、是否静音等。
     *
     * @return
     */
    View getAdView();
    
    /**
     * 信息流视频广告回调接口,仅适用于适用穿山甲播放器播放贴片视频广告
     */
    interface VideoAdListener {

        /**
         * 视频广告加载成功
         *
         * @param ad
         */
        void onVideoLoad(TTFeedAd ad);

        /**
         * 视频广告加载失败(原生MediaPlayer内部提供的错误类型)
         * @param errorCode 错误类型:
         *                  MEDIA_ERROR_UNKNOWN
         *                  MEDIA_ERROR_SERVER_DIED
         *
         * @param extraCode 额外错误信息
         *                  MEDIA_ERROR_IO
         *                  MEDIA_ERROR_MALFORMED
         *                  MEDIA_ERROR_UNSUPPORTED
         *                  MEDIA_ERROR_TIMED_OUT
         *                  MEDIA_ERROR_SYSTEM
         *
         */
        void onVideoError(int errorCode, int extraCode);

        /**
         * 视频广告播放回调
         *
         * @param ad
         */
        void onVideoAdStartPlay(TTFeedAd ad);

        /**
         * 视频广告暂停回调
         *
         * @param ad
         */
        void onVideoAdPaused(TTFeedAd ad);

        /**
         * 视频广告续播
         *
         * @param ad
         */
        void onVideoAdContinuePlay(TTFeedAd ad);
    }


    void setVideoAdListener(VideoAdListener videoAdListener);

}

SMD advertising behavior monitoring

Important!!! AdInteractionListener involves advertising billing, convertView must be called correctly and ViewGroup must be used

After loading the SMD ad, the access party needs to register the View that can be clicked in the SMD ad, that is, the TTFeedAd.registerViewForInteraction() method to realize the functional interaction and calculation of the ad.
Contains the registration of the graphic click area and the registration of the additional creative button click area. For landing page ads, the user clicks on the graphic ad area to jump to the corresponding landing page, and clicks on the additional creative area to perform operations such as phone calls and application downloads.

Note: If you need to click on the graphic area to download or make a call, please pass the view of the graphic area to the creativeViewList, the detailed code is as follows

The sample code of the registration click View example is as follows, the sample fragment is called in the BaseAdapter getView() method of Demo

/**
  * 注册可点击的View,click/show会在内部完成
  * @param container     渲染广告最外层的ViewGroup
  * @param clickViews    可点击的View的列表
  * @param creativeViews 用于下载或者拨打电话的View
  */
// 可以被点击的view, 也可以把convertView放进来意味整个item可被点击,点击会跳转到落地页
List<View> clickViewList = new ArrayList<View>();
clickViewList.add(convertView);
// 创意点击区域的view 点击根据不同的创意进行下载或拨打电话动作
//如果需要点击图文区域也能进行下载或者拨打电话动作,请将图文区域的view传入creativeViewList
List<View> creativeViewList = new ArrayList<View>();
creativeViewList.add(adViewHolder.mCreativeButton);
// 注册普通点击区域,创意点击区域。重要! 这个涉及到广告计费及交互,必须正确调用。convertView必须使用ViewGroup。
ad.registerViewForInteraction((ViewGroup) convertView, images, clickViewList, creativeViewList,adViewHolder.mDislike,new TTNativeAd.AdInteractionListener() {

    // 点击普通区域的回调
    @Override
    public void onAdClicked(View view, TTNativeAd ad) {

    }

    // 点击创意区域的回调
    @Override
    public void onAdCreativeClick(View view, TTNativeAd ad) {

    }

    // 广告曝光展示的回调
    @Override
    public void onAdShow(TTNativeAd ad) {

    }
});

AdInteractionListener Description

Callback Description
onAdClicked() Click on the common area to call back
onAdCreativeClick() Click the creative area to call back
onAdShow() Ad show callback

App download status controller

When the returned advertisement is of the application download type, that is, ad.getInteractionType() == TTAdConstant.INTERACTION_TYPE_DOWNLOAD, the access party can call the following sample code to access the Feed ad download controller:

private void bindDownLoadStatusController(AdViewHolder adViewHolder, final TTFeedAd ad) {
    final DownloadStatusController controller = ad.getDownloadStatusController();
    adViewHolder.mStopButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (controller != null) {
                controller.changeDownloadStatus();
                Toast.makeText(mContext, "改变下载状态", Toast.LENGTH_SHORT).show();
                Log.d(TAG, "改变下载状态");
            }
        }
        });
    adViewHolder.mRemoveButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (controller != null) {
                controller.cancelDownload();
                Toast.makeText(mContext, "取消下载", Toast.LENGTH_SHORT).show();
                Log.d(TAG, "取消下载");
            }
        }
    });
}
//下载监听设置
TTAppDownloadListener downloadListener = new TTAppDownloadListener() {
    //未开始下载
    @Override
    public void onIdle() {

     }
    /**
     * 下载中回调
     * @param totalBytes 安装包总字节数 -1 :未知
     * @param currBytes 当前已下载的字节数
     * @param fileName 下载文件名称
     * @param appName 当前下载的APP名
     */
    @SuppressLint("SetTextI18n")
    @Override
    public void onDownloadActive(long totalBytes, long currBytes, String fileName, String appName) {

    }

     /**
     * 下载暂停回调
     * @param totalBytes 安装包总字节数 -1 :未知
     * @param currBytes 当前已下载的字节数
     * @param fileName 下载文件名称
     * @param appName 当前下载的APP名
     */
    @SuppressLint("SetTextI18n")
    @Override
    public void onDownloadPaused(long totalBytes, long currBytes, String fileName, String appName) {

    }

     /**
     * 下载失败回调
     * @param totalBytes 安装包总字节数 -1 :未知
     * @param currBytes 当前已下载的字节数
     * @param fileName 下载文件名称
     * @param appName 当前下载的APP名
     */
    @Override
    public void onDownloadFailed(long totalBytes, long currBytes, String fileName, String appName) {

    }

     /**
     * 安装完成回调
     * @param fileName 下载文件名称
     * @param appName 当前下载的APP名
     */
    @Override
    public void onDownloadFinished(long totalBytes, String fileName, String appName) {

    }
    /**
     * 下载完成回调
     * @param totalBytes 安装包总字节数 -1 :未知
     * @param fileName 下载文件名称
     * @param appName 当前下载的APP名
     */
    @Override
    public void onInstalled(String fileName, String appName) {

    }

};

TTAppDownloadListener Description

Callback Description
onIdle() Binding download listener callback
onDownloadActive() Callback during download
onDownloadPaused() Download pause callback
onDownloadFailed() Download failed callback
onDownloadFinished() Download complete callback
onInstalled() Installation complete callback

Post ads use custom players

If the App has its own player, it can replace the default player in the SDK to play ads, but it needs to handle the life cycle and event callbacks.

Create advertising object package

class OneAd {
            // 开发者自定义的播放器View
            View adView;
            double duration;
            // 广告对象
            TTFeedAd ttFeedAd;
            public OneAd(View adView, double duration, TTFeedAd ttFeedAd) {
                this.adView = adView;
                this.duration = duration;
                this.ttFeedAd = ttFeedAd;
            }

            public void play() {
                if (adView instanceof VideoView) {
                    ((VideoView)adView).start();
                    if (ttFeedAd.getCustomVideo() != null) {
                        // 使用自定义播放器需要上报视频播放的埋点
                        ttFeedAd.getCustomVideo().reportVideoStart();
                    }
                }
            }

            public void stop() {
                if (adView instanceof VideoView) {
                    if (ttFeedAd.getCustomVideo() != null) {
                        // 使用自定义播放器需要上报视频播放结束的埋点
                        ttFeedAd.getCustomVideo().reportVideoBreak(((VideoView) adView).getCurrentPosition());
                    }
                }
            }

            public void pauseVideo() {
                if (adView instanceof VideoView) {
                    ((VideoView)adView).pause();
                    if (ttFeedAd.getCustomVideo() != null) {
                        // 使用自定义播放器需要上报视频暂停埋点
                        ttFeedAd.getCustomVideo().reportVideoPause(((VideoView) adView).getCurrentPosition());
                    }
                }
            }

            public void continueVideo() {
                if (adView instanceof VideoView) {
                    // Android 自带的VideoView继续播放有关键帧问题
                    // 请使用自己的播放器自行处理继续播放的问题
                    ((VideoView)adView).start();

                    if (ttFeedAd.getCustomVideo() != null) {
                        // 使用自定义播放器需要上报视频继续播放埋点
                        ttFeedAd.getCustomVideo().reportVideoContinue(((VideoView) adView).getCurrentPosition());
                    }
                }
            }
        }

Use custom player

        // StreamAdPlayer 的 getVideoTypeView

        public OneAd getVideoTypeView(final TTFeedAd ttFeedAd) {
            if (ttFeedAd == null || ttFeedAd.getCustomVideo() == null) {
                return null;
            }
            // 这里new出来的是就是自定义的播放器暂时使用android自带的播放器
            // 暂时使用android自带的播放器,开发者此处应该生成自己的播放器
            VideoView videoView = new VideoView(getApplicationContext());
            videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    // 播放器播放结束回调时,应该调用此处进行事件上报
                    if (ttFeedAd.getCustomVideo() != null) {
                        ttFeedAd.getCustomVideo().reportVideoFinish();
                    }
                }
            });
            // 设置Videourl
            videoView.setVideoURI(Uri.parse(ttFeedAd.getCustomVideo().getVideoUrl()));
            // 设置布局等
            ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
            videoView.setLayoutParams(layoutParams);

            ... 

            // 此处返回广告封装对象时,参数里传入播放器实例
            return new OneAd(videoView, ttFeedAd.getVideoDuration(), ttFeedAd);
        }

Video preload timing

mTTAdNative.loadStream(adSlot, new TTAdNative.FeedAdListener() {
            @Override
            public void onFeedAdLoad(List<TTFeedAd> ads) {

                ...

                // 使用自定义播放器需要考虑为视频Url预加载
                // 需要预加载请在此处通过ttFeedAd.getCustomVideo().getVideoUrl()拿到视频url之后自行预加载

                ...

            }
        });

Life cycle control


    // Activity中

    @Override
    protected void onPause() {
        super.onPause();
        if (mStreamAdPlayer != null) {
            mStreamAdPlayer.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mStreamAdPlayer != null) {
            mStreamAdPlayer.onResume();
        }
    }

    ...
    // StreamAdPlayer 类中

    public void onPause() {
        // 此处pauseVideo是为了通知自定义播放器暂停
        if (mNowPlayAd != null) {
            mNowPlayAd.pauseVideo();
        }
        mHandler.postDelayedPause();
    }

    public void onResume() {
        // 此处continueVideo是为了自定义播放器续播
        if (mNowPlayAd != null) {
            mNowPlayAd.continueVideo();
        }
        mHandler.postDelayedResume();
    }

CustomizeVideo

Method Description
getVideoUrl() Get video url
reportVideoStart() Report play start
reportVideoPause() Report playback pause
reportVideoContinue() Report and play continue
reportVideoFinish() Report the end of playback
reportVideoBreak() Report the playback suspension
reportVideoAutoStart() Report auto play
reportVideoStartError() Report start error
reportVideoError() Report an error during playback

Reference Demo

For self-rendered rendering patches, please refer to StreamActivity in Demo
Use custom player can refer to StreamCustomPlayerActivity in Demo

Self-rendering patch notes:

  1. AdInteractionListener involves advertising billing, and convertView must be called correctly. **ViewGroup must be used.
Did the content solve your problem?
Contact us