最近更新:2022-2-23

SDK版本说明

  • 接入 JAd 所需要的基础库 JCore SDK 最低版本要求为 JCore3.2.0
  • 若用户为 JAd 与 JPush 两个极光产品的使用者,在接入 JAd SDK 时,建议将 JPush SDK 同步升级到 JPush4.6.6 及以上版本

SDK初始化配置

说明:

  • 极光联盟SDK需要在主进程中初始化

  • 涉及多进程WebView的使用,用户想要使用自己的数据路径,可以在SDK初始化之前调用WebView.setDataDirectorySuffix()

开发者需要在Application#onCreate()方法中调用初始化接口来初始化极光联盟SDK。SDK是支持多进程,为提升应用稳定性,建议开启SDK多进程。

          <!-- AndroidManifest.xml配置SDK支持多进程,可以通过继承UserSerice用户自定义一个Service组件,其中action需要保持不变 -->
<service
    android:name="cn.jiguang.ads.app.service.UserService"
    android:exported="false"
    android:process=":remote">
    <intent-filter>
        <action android:name="cn.jiguang.user.service.action" />
    </intent-filter>
</service>

        
此代码块在浮窗中显示

初始化SDK

public class MainApplication extends Application { private static final String TAG = "MainApplication"; @Override public void onCreate() { super.onCreate(); //配置 JAdApi.config(this, new JAdConfig.Builder() // 是否开启日志,默认false .setLoggerEnable(true) .build()); // 应用内广告初始化 JNativeAdApi.init(this); // 通知栏广告初始化 JNotifyAdApi.init(this); } }
          public class MainApplication extends Application {

    private static final String TAG = "MainApplication";

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

        //配置
        JAdApi.config(this, new JAdConfig.Builder()
                // 是否开启日志,默认false
                .setLoggerEnable(true)
                .build());

        // 应用内广告初始化
        JNativeAdApi.init(this);
        // 通知栏广告初始化
        JNotifyAdApi.init(this);
    }
}

        
此代码块在浮窗中显示

DEV拉取,SDK渲染

//第一步:构建拉取广告所需Slot JNativeAdSlot nativeAdSlot = new JNativeAdSlot.Builder() .setLoader(JNativeAdSlot.LOADER_DEV) .setRender(JNativeAdSlot.RENDER_SDK) .setAdPosition("广告位") .setAdStyle(adStyle)//adStyle类型,见类 JAdSlot .build(); //第二步:拉取 JNativeAdApi.loadNativeAd(context, nativeAdSlot, new OnNativeAdLoadListener() { @Override public void onError(JAdError error) { Toast.makeText(context, "广告拉取失败" + error.getMessage(), Toast.LENGTH_SHORT).show(); } @Override public void onLoaded(List ads) { Toast.makeText(context, "广告拉取成功", Toast.LENGTH_SHORT).show(); //第三步:加载广告后进行广告有效性校验,提升广告曝光效率 for (JNativeAd nativeAd : ads){ if(!ad.isValid()){ Logger.w(TAG, "sdk渲染广告校验不通过"); continue; } // sdk渲染 renderBySdk(nativeAd); break; } } }); //第四步:SDK渲染广告 private void renderBySdk(JNativeAd nativeAd) { nativeAd.render(); nativeAd.setOnNativeAdEventListener(new OnNativeAdEventListener() { @Override public void onError(JAdError error) { Toast.makeText(NativeAdActivity.this, "sdk渲染失败", Toast.LENGTH_SHORT).show(); } @Override public void onAdExposed(JNativeAd nativeAd1) { Toast.makeText(NativeAdActivity.this, "sdk渲染成功", Toast.LENGTH_SHORT).show(); } @Override public void onAdClicked(View view) { Toast.makeText(NativeAdActivity.this, "sdk渲染被点击", Toast.LENGTH_SHORT).show(); } }); }
              //第一步:构建拉取广告所需Slot
    JNativeAdSlot nativeAdSlot = new JNativeAdSlot.Builder()
                .setLoader(JNativeAdSlot.LOADER_DEV)
                .setRender(JNativeAdSlot.RENDER_SDK)
                .setAdPosition("广告位")
                .setAdStyle(adStyle)//adStyle类型,见类 JAdSlot
                .build();
    //第二步:拉取
    JNativeAdApi.loadNativeAd(context, nativeAdSlot, new OnNativeAdLoadListener() {
        @Override
        public void onError(JAdError error) {
            Toast.makeText(context, "广告拉取失败" + error.getMessage(), Toast.LENGTH_SHORT).show();
        }
                    
        @Override
        public void onLoaded(List<JNativeAd> ads) {
            Toast.makeText(context, "广告拉取成功", Toast.LENGTH_SHORT).show();
            
           //第三步:加载广告后进行广告有效性校验,提升广告曝光效率
            for (JNativeAd nativeAd : ads){
                if(!ad.isValid()){
                    Logger.w(TAG, "sdk渲染广告校验不通过");
                    continue;
                }
                
                // sdk渲染
                renderBySdk(nativeAd);
                break;
            }
        }
    });

    //第四步:SDK渲染广告
    private void renderBySdk(JNativeAd nativeAd) {
        nativeAd.render();
        nativeAd.setOnNativeAdEventListener(new OnNativeAdEventListener() {
            @Override
            public void onError(JAdError error) {
                Toast.makeText(NativeAdActivity.this, "sdk渲染失败", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdExposed(JNativeAd nativeAd1) {
                Toast.makeText(NativeAdActivity.this, "sdk渲染成功", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdClicked(View view) {
                Toast.makeText(NativeAdActivity.this, "sdk渲染被点击", Toast.LENGTH_SHORT).show();
            }
        });
    }

        
此代码块在浮窗中显示

DEV拉取,DEV渲染

//第一步:构建拉取广告所需 JNativeAdSlot nativeAdSlot = new JNativeAdSlot.Builder() .setLoader(JNativeAdSlot.LOADER_DEV) .setRender(JNativeAdSlot.RENDER_DEV) .setAdPosition("广告位") .setAdStyle(adStyle)//adStyle类型,见类 JAdSlot .setAdCount(1)//目前DEV渲染仅支持一条 .build(); //第二步:拉取 JNativeAdApi.loadNativeAd(context, nativeAdSlot, new OnNativeAdLoadListener() { @Override public void onError(JAdError error) { Toast.makeText(context, "广告拉取失败" + error.getMessage(), Toast.LENGTH_SHORT).show(); } @Override public void onLoaded(List ads) { Toast.makeText(context, "广告拉取成功", Toast.LENGTH_SHORT).show(); // 取出广告 JNativeAd nativeAd = ads.get(0); // dev渲染 renderByDev(nativeAd); } }); //第三步:dev渲染 private void renderByDev(JNativeAd nativeAd) { String title = nativeAd.getTitle(); String content = nativeAd.getContent(); String imageUrl = ""; List imageList = nativeAd.getImageList(); if (imageList != null && !imageList.isEmpty()) { imageUrl = imageList.get(0).getUrl(); } View adView = null; TextView adTitle = null; TextView adContent = null; ImageView adImage = null; Button adConfirm = null; int adStyle = getAdStyle(); switch (adStyle) { case JNativeAdSlot.STYLE_BANNER: adView = LayoutInflater.from(NativeAdActivity.this).inflate(R.layout.view_banner, adContainer, false); adTitle = adView.findViewById(R.id.tv_banner_title); adContent = adView.findViewById(R.id.tv_banner_content); adImage = adView.findViewById(R.id.iv_banner_image); adView.findViewById(R.id.iv_banner_cancel).setOnClickListener(this); break; case JNativeAdSlot.STYLE_FLOAT: adView = LayoutInflater.from(NativeAdActivity.this).inflate(R.layout.view_float, adContainer, false); adImage = adView.findViewById(R.id.iv_float_image); adView.findViewById(R.id.iv_float_cancel).setOnClickListener(this); break; case JNativeAdSlot.STYLE_MODAL: adView = LayoutInflater.from(NativeAdActivity.this).inflate(R.layout.view_modal, adContainer, false); adTitle = adView.findViewById(R.id.tv_modal_title); adContent = adView.findViewById(R.id.tv_modal_content); adImage = adView.findViewById(R.id.iv_modal_image); adView.findViewById(R.id.iv_modal_cancel).setOnClickListener(this); adConfirm = adView.findViewById(R.id.btn_modal); break; default: return; } if (adTitle != null) { adTitle.setText(title); } if (adContent != null) { adContent.setText(content); } if (adImage != null) { Glide.with(NativeAdActivity.this).load(imageUrl).into(adImage); } adContainer.removeAllViews(); adContainer.addView(adView); LinkedList clickViews = new LinkedList<>(); clickViews.add(adContainer); clickViews.add(adConfirm); //第四步:设置回调监听 nativeAd.setOnNativeAdEventListener(adContainer, clickViews, new OnNativeAdEventListener() { @Override public void onError(JAdError error) { Toast.makeText(NativeAdActivity.this, "dev渲染失败" + error.getMessage(), Toast.LENGTH_SHORT).show(); } @Override public void onAdExposed(JNativeAd nativeAd1) { Toast.makeText(NativeAdActivity.this, "dev渲染成功", Toast.LENGTH_SHORT).show(); } @Override public void onAdClicked(View view) { Toast.makeText(NativeAdActivity.this, "dev渲染被点击", Toast.LENGTH_SHORT).show(); } }); }
              //第一步:构建拉取广告所需
    JNativeAdSlot nativeAdSlot = new JNativeAdSlot.Builder()
                .setLoader(JNativeAdSlot.LOADER_DEV)
                .setRender(JNativeAdSlot.RENDER_DEV)
                .setAdPosition("广告位")
                .setAdStyle(adStyle)//adStyle类型,见类 JAdSlot
                .setAdCount(1)//目前DEV渲染仅支持一条
                .build();
    //第二步:拉取
    JNativeAdApi.loadNativeAd(context, nativeAdSlot, new OnNativeAdLoadListener() {
        @Override
        public void onError(JAdError error) {
            Toast.makeText(context, "广告拉取失败" + error.getMessage(), Toast.LENGTH_SHORT).show();
        }
                    
        @Override
        public void onLoaded(List<JNativeAd> ads) {
            Toast.makeText(context, "广告拉取成功", Toast.LENGTH_SHORT).show();
            // 取出广告
            JNativeAd nativeAd = ads.get(0);
            // dev渲染
            renderByDev(nativeAd);
        }
    });
    
    //第三步:dev渲染
    private void renderByDev(JNativeAd nativeAd) {
        String title = nativeAd.getTitle();
        String content = nativeAd.getContent();
        String imageUrl = "";
        List<JAdImage> imageList = nativeAd.getImageList();
        if (imageList != null && !imageList.isEmpty()) {
            imageUrl = imageList.get(0).getUrl();
        }
        View adView = null;
        TextView adTitle = null;
        TextView adContent = null;
        ImageView adImage = null;
        Button adConfirm = null;

        int adStyle = getAdStyle();
        switch (adStyle) {
            case JNativeAdSlot.STYLE_BANNER:
                adView = LayoutInflater.from(NativeAdActivity.this).inflate(R.layout.view_banner, adContainer, false);
                adTitle = adView.findViewById(R.id.tv_banner_title);
                adContent = adView.findViewById(R.id.tv_banner_content);
                adImage = adView.findViewById(R.id.iv_banner_image);
                adView.findViewById(R.id.iv_banner_cancel).setOnClickListener(this);
                break;
            case JNativeAdSlot.STYLE_FLOAT:
                adView = LayoutInflater.from(NativeAdActivity.this).inflate(R.layout.view_float, adContainer, false);
                adImage = adView.findViewById(R.id.iv_float_image);
                adView.findViewById(R.id.iv_float_cancel).setOnClickListener(this);
                break;
            case JNativeAdSlot.STYLE_MODAL:
                adView = LayoutInflater.from(NativeAdActivity.this).inflate(R.layout.view_modal, adContainer, false);
                adTitle = adView.findViewById(R.id.tv_modal_title);
                adContent = adView.findViewById(R.id.tv_modal_content);
                adImage = adView.findViewById(R.id.iv_modal_image);
                adView.findViewById(R.id.iv_modal_cancel).setOnClickListener(this);
                adConfirm = adView.findViewById(R.id.btn_modal);
                break;
            default:
                return;
        }
        if (adTitle != null) {
            adTitle.setText(title);
        }
        if (adContent != null) {
            adContent.setText(content);
        }
        if (adImage != null) {
            Glide.with(NativeAdActivity.this).load(imageUrl).into(adImage);
        }
        adContainer.removeAllViews();
        adContainer.addView(adView);

        LinkedList<View> clickViews = new LinkedList<>();

        clickViews.add(adContainer);
        clickViews.add(adConfirm);
        
        //第四步:设置回调监听
        nativeAd.setOnNativeAdEventListener(adContainer, clickViews, new OnNativeAdEventListener() {
            @Override
            public void onError(JAdError error) {
                Toast.makeText(NativeAdActivity.this, "dev渲染失败" + error.getMessage(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdExposed(JNativeAd nativeAd1) {
                Toast.makeText(NativeAdActivity.this, "dev渲染成功", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onAdClicked(View view) {
                Toast.makeText(NativeAdActivity.this, "dev渲染被点击", Toast.LENGTH_SHORT).show();
            }
        });
    }

        
此代码块在浮窗中显示

黑白名单或页面定向配置

对于有需要在指定页面展示应用内广告需求的用户,如果指定页面为Fragment,则需要用户调用接口类 JAdApi 以下两个接口进行动态控制。

/** * 进入Fragment页面,调用该接口 * @param context ApplicationContext * @param fragmentName Fragment页面完整类名(this.getClass().getCanonicalName()) */ public static void onFragmentResumed(Context context, String fragmentName) /** * 退出Fragment页面,调用该接口 * @param context * @param fragmentName */ public static void onFragmentPaused(Context context, String fragmentName)
           /**
 * 进入Fragment页面,调用该接口
 * @param context ApplicationContext
 * @param fragmentName Fragment页面完整类名(this.getClass().getCanonicalName())
 */
public static void onFragmentResumed(Context context, String fragmentName)
    
 /**
 * 退出Fragment页面,调用该接口
 * @param context
 * @param fragmentName
 */
public static void onFragmentPaused(Context context, String fragmentName)

        
此代码块在浮窗中显示

如果仅只需对Activity页面进行动态控制,则不需要开发者调用接口控制,SDK会根据对Activity的生命周期监听,进行动态控制处理。

注:为了保持更好控制效果,以及更好兼容后续的动态配置调整(黑名单替换为白名单, 或白名单换为设置黑名单),建议对每个Fragment页面完成动态配置接口的调用。

因为,Android添加Fragment方式共有四种,而每种不同的添加方式,需要对Fragment的处理方式也有不一样。下面就针对Fragment的四种方式,指定在指定Fragment展示in app控制方式,分别进行讨论。

Fragment使用方式 是否可以监听到Fragment生命周期 极光动态指定展示页面接口调用方式
方式一:add/show/hide 无法监听生命周期 Fragment内的onFragmentResume与onHiddenChaned回调调用
方式二:ViewPager 无法监听生命周期 Fragment内的setUserVisibleHint回调调用
方式三:replace 可以监听生命周期 Fragment内的生命周期回调onResume与onPause调用
方式四:attach/detach 可以监听生命周期 同上

具体控制接口调用方式如下:

1、add/show/hide方式

在需要动态控制的Fragment页面(配置为黑名单页面),

1)在Fragment的onCreateView回调函数中调用动态控制接口,并要求传入参数。

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { String classname = this.getClass().getCanonicalName(); JAdApi.onFragmentResumed(MyApplication.gContext, classname); return inflater.inflate(R.layout.black_fragment, container, false); }
          @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    String classname = this.getClass().getCanonicalName();
    JAdApi.onFragmentResumed(MyApplication.gContext, classname);
    return inflater.inflate(R.layout.black_fragment, container, false);
}     

        
此代码块在浮窗中显示

2)在Fragment的onHiddenChaned回调接口中,调用动态控制接口,并按要求传入参数。

@Override public void onHiddenChanged(boolean hidden) { String classname = this.getClass().getCanonicalName(); if(!hidden){//context传application context JAdApi.onFragmentResumed(MyApplication.gContext, classname); }else{//hide JAdApi.onFragmentPaused(MyApplication.gContext, classname); } super.onHiddenChanged(hidden); }
          @Override
public void onHiddenChanged(boolean hidden) {
    String classname = this.getClass().getCanonicalName();
    if(!hidden){//context传application context
        JAdApi.onFragmentResumed(MyApplication.gContext, classname);
    }else{//hide
        JAdApi.onFragmentPaused(MyApplication.gContext, classname);  
    } 
    
    super.onHiddenChanged(hidden);
}     

        
此代码块在浮窗中显示

2、ViewPager方式

1)在Fragment的setUserVisibleHint回调接口中,调用动态控制接口,并按要求传入参数。

@Override public void setUserVisibleHint(boolean isVisibleToUser) { String classname = this.getClass().getCanonicalName(); if(isVisibleToUser){ //传application context JAdApi.onFragmentResumed(MyApplication.gContext, classname); }else{//hide JPushInterface.onFragmentPause(MyApplication.gContext, classname); } super.setUserVisibleHint(isVisibleToUser); }
          @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    String classname = this.getClass().getCanonicalName();
    if(isVisibleToUser){
        //传application context
        JAdApi.onFragmentResumed(MyApplication.gContext, classname);
    }else{//hide
        JPushInterface.onFragmentPause(MyApplication.gContext, classname);  
    } 
    
    super.setUserVisibleHint(isVisibleToUser);
}    

        
此代码块在浮窗中显示

3、replace方式或attach/detach方式

在添加Fragment内的生命周期回调接口中,调用动态页面配置接口。

@Override public void onResume() {//传application context String classname = this.getClass().getCanonicalName(); JAdApi.onFragmentResumed(MyApplication.gContext, classname); super.onResume(); } @Override public void onPause() { String classname = this.getClass().getCanonicalName(); JPushInterface.onFragmentPause(MyApplication.gContext, classname); super.onPause(); }
          @Override
public void onResume() {//传application context
    String classname = this.getClass().getCanonicalName();
    JAdApi.onFragmentResumed(MyApplication.gContext, classname);
    super.onResume();
}

@Override
public void onPause() {
    String classname = this.getClass().getCanonicalName();
    JPushInterface.onFragmentPause(MyApplication.gContext, classname);  
    super.onPause();
}

        
此代码块在浮窗中显示

DEV拉取,错误码对照表

errorCode code含义 解决方案
0 有广告返回 正常拉取广告
7001 未知异常 多尝试几次,如若仍出现该错误,请联系技术支持
7002 程序内部错误 多尝试几次,如若仍出现该错误,请联系技术支持
7003 接口请求超频 不要过于频繁请求接口,请稍后再试
7004 黑名单页面不请求 不要在配置为黑名单的页面进行广告请求
7005 网络异常 检查当前网络状态
7006 请求超时 检查当前网络状态,请多尝试几次
7007 后台不允许请求 应用当前处于后台,不允许进行广告请求
7008 广告业务关闭 该应用当前广告业务关闭,如需开通,请联系商务
7009 极光广告下发方式关闭 该应用极光广告下发方式关闭,如需开通,请联系商务
7010 透明页面不允许请求 应用当前透明页面,不允许进行广告请求
7011 曝光次数频控 广告曝光超过当天最大次数限制,无法返回广告
7012 曝光间隔频控 当前下发广告与上次曝光广告时间小于最小的曝光间隔时间,无法返回广告
8001 无in app data 多拉几次,若依旧没填充,登录联盟后台确认广告位是否设置了过于严格的过滤规则
8002 后台返回请求超频率 不要过于频繁请求接口,请稍后再试
8003 请求样式不支持 广告样式已通过广告位进行控制,请求时无需指定样式
8004 服务器内部错误 基本不会发生,如出现请重试
8005 请求模式不匹配,未开通拉取权限 广告位只支持极光主动下发或者开发者拉取这两种模式二选一,需确认广告下发方式与广告位配置的下发方式是否一致
8006 业务未开通或者加载运营配置异常 请确认appkey和代码位的业务状态为开启
8007 运营无可用广告位 请通过联盟管理后台创建可用广告位
8008 广告位曝光频控内部错误 基本不会发生,如出现请重试
8009 广告位曝光间隔频控 请求过于频繁,请稍后再试
8010 广告位曝光次数频控 该用户已达到当日曝光上限,请更换设备再试
8011 uid下发频控内部错误 该用户已达到下发次数上限,请更换设备再试
8012 uid下发间隔频控 请求过于频繁,请稍后再试
8013 uid下发次数频控 该用户下发次数已达上限,请更换设备再试
8014 请求超时 请检查网络状况
8015 extra请求参数不合法 请求参数不合法,请查看集成文档
8016 样式不匹配 广告位只支持极光主动下发或者开发者拉取这两种模式二选一,需确认广告下发方式与广告位配置的下发方式是否一致
8017 无可用推广目的 广告位推广目的配置异常,请更换广告位再试
8018 测试广告位非测试uid 请将广告位切换为正式状态
8019 查询不到Imei信息 设备信息获取失败,请稍后再试
8020 设备信息不完整 设备信息获取失败,请稍后再试
8021 无可用模板 广告位推广目的配置异常,请更换广告位再试
8022 无sequence id 请求异常,请重试
8023 非自渲染请求 请用自渲染广告位请求自渲染接口
8024 广告素材不合法 请求异常,请重试
8025 adType有指定轻推送或者InApp但与实际场景不符 请求异常,请重试
8026 不属于通道设定的灰度比例 该用户不在灰度范围内,暂无法请求广告
8027 流量定向过滤 该用户不在投放范围内,无法请求广告
8028 uid曝光间隔频控filtered by uid exposure time、duplicate req 请求过于频繁,请稍后再试
8029 通道vip 该用户为媒体VIP用户,无法请求广告
8030 重复请求 重复请求
8031 sdk版本太低,无支持的模板 SDK版本过低,请更新SDK版本
8032 敏感词过滤 敏感词过于严格,请登录联盟管理后台修改敏感词
8033 自渲染业务未开通 请联系商务开启自渲染权限
文档内容是否对您有帮助?

Copyright 2011-2022, jiguang.cn, All Rights Reserved. 粤ICP备12056275号-13 深圳市和讯华谷信息技术有限公司

在文档中心打开