You need to enable JavaScript to run this app.
导航
Android SDK集成
最近更新时间:2024.07.26 14:16:55首次发布时间:2022.10.31 09:54:30
一、简介

App 弹窗是 GMP ReachSDK 提供的弹窗触达功能。

二、SDK集成

1. 配置应用鉴权信息

需提供 Android 应用包名和应用签名然后在 GMP 后台配置(管理中心-消息管理-客户端SDK-鉴权配置),需保证与 app 的实际信息一致,可联系您的客户端开发人员获取。该项配置用于接口的安全鉴权校验,不会用于其他用途。
示例如下:

# Android包名
com.gmp.demo

# 获取Android应用签名 SHA256 fingerprint
12:9F:EE:EC:6B:8A:DA:77:35:13:D8:7B:BC:A8:F4:74:71:4D:95:6C:ED:91:9B:9E:18:B7:9A:BE:4E:45:B7:EF

然后到GMP后台配置相关信息
alt

alt

2. 集成 SDK

注意

弹窗 SDK 集成 Demo,可参考 https://www.volcengine.com/docs/6315/1130446
Demo 需要在 Config.kt 文件配置对应的参数才能获取到对应的数据

2.1 集成 Finder SDK

弹窗 SDK 依赖 Finder SDK 进行数据回流,在使用弹窗 SDK 前,请确保已经集成了 Finder SDK。并且 Finder SDK 版本在 6.16.1 及以上。
如果使用多 module,请确保弹窗 SDK 的 module 能引用到 Finder SDK 。

Finder Android SDK 接入指南

2.2 集成弹窗 SDK

Gradle 引入方式(推荐)

接入弹窗SDK,在 gradle 中添加依赖

  • Gradle 7.0 以下
// 在 project 级别的 build.gradle 中添加 maven 仓库
// 在 allprojects 的 repositories 中添加 maven 仓库
allprojects {
    repositories {
        maven {
            url 'https://artifact.bytedance.com/repository/Volcengine/'
        }
        // 其他仓库
    }
}
  • Gradle 7.0 及以上
// 在 project 级别的 setting.gradle 中添加 maven 仓库
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        // 省略其他
        maven{
            url 'https://artifact.bytedance.com/repository/Volcengine/'
        }
    }
}
  • 引入 SDK
//在app:build.gradle下添加
dependencies {
    // 最新版本请查看版本记录获取
    implementation 'com.bytedance.gmp:gmp_reach:${[new_version]}'

		// SDK 版本 >= 2.1.1 不需引入
    // 可替换为实际接入的 okhttp 版本,但最好使用该版本避免兼容性问题
    implementation "com.squareup.okhttp3:okhttp:3.12.4"
}

手动引入方式

推荐您远程引入SDK。如特殊情况需要手动引入,请补充阅读本小节。

请在 Android 弹窗、资源位SDK 版本记录 下载对应版本文件。

文件解压后需要把所有 aar,都添加到 libs 目录下

注意

SDK 版本 < 2.1.1 , 手动引入弹窗SDK aar 之后,记得要引入 okhttp3

implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])

// SDK 版本 >= 2.1.1 不需引入
// 可替换为实际接入的 okhttp 版本,但最好使用该版本避免兼容性问题
implementation "com.squareup.okhttp3:okhttp:3.12.4"

2.3 权限设置

//在AndroidManifest.xml中配置
<uses-permission android:name="android.permission.INTERNET"/>

3. 初始化 SDK

3.1 获取初始化必备id

3.1.1 获取项目id和应用id

在gmp首页,点击右上角头像-项目管理,即可进入项目后台页查看对应项目的项目id和应用id(项目id是初始化弹窗sdk的appid,应用id是用于初始化Finder SDK的appid)

3.1.2 获取主账号id(Saas版本)

进入火山引擎控制台,点击右上角头像 icon,红框中的账号 ID 即是 主账号id

3.1.3 获取弹窗应用id

在GMP首页,选择管理中心-通道管理-App弹窗-应用管理即可打开弹窗应用列表,最左侧一栏为弹窗应用id,将所选应用的弹窗应用id传入sdk初始化即可

3.1.4 获取弹窗应用id uuidType和deviceIdType

GMP 会根据 uuid 和 uuid type 对用户进行人群圈选,所以需要确保 SDK 中使用正确的 uuid 和 uuid type 。建议使用客户自有体系的用户 id 作为 uuid,并且 CDP ID 图谱中找到该 id 对应的 ID Code 作为 uuid type。
可以在 CDP 中,进入“数据融合-ID 图谱构建”界面中查看当前项目中的所有id type
alt
alt
alt

3.2 初始化

3.2.1 初始化(私有化版本)

首先您需要初始化 Finder SDK,具体可参考:初始化 Finder SDK (私有化版本) - 火山引擎,再初始化弹窗 SDK

注意

弹窗SDK 需要在 Application 类的 onCreate() 方法主进程主线程初始化。
弹窗SDK 请在 Application 中初始化,如果您的app中涉及隐私弹窗协议,只需要在隐私弹窗协议同意之后再更新用户画像既可。

GMP 域名为私有化部署域名 , 默认为 https://xxxxxx.com 。
如果租户名不为 gmp ,则需要拼接租户名,如: https://xxxxxx.com/gmpa

示例代码如下:

// Application
public void onCreate() {
		// Finder SDK 不需要区分进程,务必在多个进程都初始化
    initAppLog();
    // 弹窗、资源位 SDK 初始化只需要在主进程初始化既可—— 2.1.0.5-bugfix 及以上内部已经判断,外部可不需要判断
    if (ToolUtils.isMainProcess(this)) {
	      // 生成触达相关的配置(必选)
	      ReachConfig reachConfig = initReachConfig();
	      // 初始化 弹窗SDK
	      initGMPPopSDK(reachConfig);
    }
}

private ReachConfig initReachConfig() {
		return new ReachConfig.Builder()
				// 设置 gmp 项目id
        .setAppId(Config.INSTANCE.getGmpAppId())
        .setAppConfig(new IAppConfig() {
		         @NonNull
		         @Override
		         public String getHost() {
				         // 设置 GMP 的域名
		             return Config.INSTANCE.getGmpHost();
		         }
        })
        // 如果项目支持自动登录,用户画像已经存在,需要提前设置上
        .setUniqueUid(uuid)
        .setUniqueUidType(uuidType)
        //用于图片类型的加载,可以根据接口说明自行选择图片加载库;SDK版本 >= 2.1.1 已经废除,无须实现
        .setImageConfig(MyImageConfig.INSTANCE.getMyImageConfig())
        .build();
}


private void initGMPPopSDK(ReachConfig reachConfig) {
    //初始化弹窗sdk
    GMPPopupSDK.INSTANCE.initPopup(this, new PopupConfig.Builder()
            .setReachConfig(reachConfig)
            // 设置 GMP 弹窗id
            .setPopupAppId(Config.INSTANCE.getGmpPopupAppId())
            .build()
      );
}


3.3.2 初始化(Saas版本)

首先您需要初始化 Finder SDK,具体可参考:初始化 Finder SDK (Saas版本) - 火山引擎,再初始化弹窗 SDK

Saas GMP Host 为:https://gmp-saas-api.console.volcengine.com

注意

弹窗SDK 需要在 Application 类的 onCreate() 方法主进程主线程初始化。
弹窗SDK 请在 Application 中初始化,如果您的app中涉及隐私弹窗协议,只需要在隐私弹窗协议同意之后再更新用户画像既可。

java:
//Application
public void onCreate() {
		// Finder SDK 不需要区分进程,务必在多个进程都初始化
	  initAppLog();
    // 弹窗、资源位 SDK 初始化只需要在主进程初始化既可 —— 2.1.0.5-bugfix 及以上内部已经判断,外部可不需要判断
    if (ToolUtils.isMainProcess(this)) {
	      // 生成触达相关的配置(必选)
	      ReachConfig reachConfig = initReachConfigSaas();
	      // 初始化 弹窗SDK
	      initGMPPopSDK(reachConfig);
    }
}

private ReachConfig initReachConfigSaas() {
    // 生成触达相关的配置(必选)
    return new ReachConfig.Builder()
            // 设置 gmp 项目id
            .setAppId(Config.INSTANCE.getGmpAppId())
            .setAppConfig(new IAppConfig() {
                @NonNull
                @Override
                public String getHost() {
                    // 设置 gmp saas 的域名
                    return "https://gmp-saas-api.console.volcengine.com";
                }
            })
            // 设置 gmp 主账号id
            .setMainAccountId(Config.INSTANCE.getGmpMainAccountId())
            // 如果项目支持自动登录,用户画像已经存在,需要提前设置上
		        .setUniqueUid(uuid)
		        .setUniqueUidType(uuidType)
            //用于图片类型的加载,可以根据接口说明自行选择图片加载库;SDK版本 >= 2.1.1 已经废除,无须实现
            .setImageConfig(MyImageConfig.INSTANCE.getMyImageConfig())
            .build();
}

private void initGMPPopSDK(ReachConfig reachConfig) {
    //初始化弹窗sdk
    GMPPopupSDK.INSTANCE.initPopup(this, new PopupConfig.Builder()
            .setReachConfig(reachConfig)
            // 设置 GMP 弹窗id
            .setPopupAppId(Config.INSTANCE.getGmpPopupAppId())
            .build()
      );
}


3.2.3 参数详情

下面必填项需确保正确传入 SDK,SDK 内部在初始化会进行校验,所有配置缺失则 SDK 内部会抛出异常。

  • ReachConfig 详细配置如下
参数类型是否必填描述
debugboolean切换 debug 模式,默认为 false,开启则会打印内部日志
appIdstringGMP 项目ID,可根据3.1.1指引获取
appConfiginterface配置请求域名
threadConfiginterface配置线程池策略 [详细见4.6]
ImageConfiginterface配置自定义的图片加载接口,SDK版本 >= 2.1.1 已经废除,无须实现 [详细见3.3]
uniqueUidstring用户画像id,存在用户画像时传入
uniqueUidTypestring用户画像id类型,存在用户画像时传入
UbaConfiginterface配置其他平台uba配置 [详细见4.7]
mainAccountIdstringsaas版本的主账号id,接入saas版本必须传入
finderInitConfigFinderInitConfig设置finder配置,如无特殊需求可不传入
enableRetryWhenServerErrorboolean设置当服务器请求失败后是否会自动重试(默认开启
deviceIdTypestring用户设备id类型,开启匿名(未登录)用户弹窗时需传入,否则请勿传入[详细见4.9]
  • 弹窗 SDK 详细配置如下
参数类型是否必填描述
popupAppIdstring弹窗应用id,在gmp页面获取(获取方式见3.1.3)
imageFormatListstring支持预加载的图片格式(详细见4.3.2
reachConfigReachConfig触达配置
anonymousPopupEnabledboolean设置是否需要支持匿名(未登录)用户弹窗(默认关闭)[详细见4.9]

3.3 图片加载接口说明(SDK版本 >= 2.1.1 已经废除,无须实现)

弹窗 SDK 需要业务实现图片加载接口,以便于 SDK 内部能正常加载图片
IImageConfig 接口 定义如下:

/**
 * 图片加载接口
 */
interface IImageConfig {
    /**
     * 获取 url 的图片 , 然后根据实际大小 通过 listen 返回
     *
     * @param viewWidth  图片View的宽度
     * @param viewHeight 图片View的高度
     * @param url        加载的 url
     * @param listener   回调 listener , 务必正确回调 listener 的 onSucceed 与 onFail
     */
    void getImage(int viewWidth, int viewHeight, String url, IImageListener listener);

    /**
     * 预加载图片业务可以自定义加载级别(到磁盘还是内存)
     * @param url 图片 url
     */
    void preloadImage(String url);

    /**
     * 检查图片是否在缓存中
     * @param uri 图片 uri
     */
    boolean isInMemoryOrDiskCache(Uri uri);

    //加载图片回调
    interface IImageListener {
        /**
         * 成功时回调加载后的 bitmap
         * @param bitmap 加载成功的 bitmap
         */
        void onSucceed(Bitmap bitmap);

        /**
         * 失败时回调错误信息
         * @param throwable 加载失败的异常
         */
        void onFail(Throwable throwable);
    }
}

图片加载接口示例

文档中给出了一种基于 Fresco 的图片加载实现,接入方可以根据自己实际使用的图片加载库实现该接口

在 gradle 中引入 Fresco 并在 application oncreate 中初始化 fresco
// Application
public void onCreate() {
		Fresco.initialize(context);
}
// 实现接口 IImageConfig
public class FrescoImageConfigJava implements IImageConfig {
    @Override
    public boolean isInMemoryOrDiskCache(Uri uri) {
        ImagePipeline imagePipeline = Fresco.getImagePipeline();
        return imagePipeline.isInBitmapMemoryCache(uri) || imagePipeline.isInDiskCacheSync(uri);
    }

    @Override
    public void getImage(int viewWidth, int viewHeight, String url, IImageListener imageListener) {
        ImageRequest imageRequest = ImageRequest.fromUri(Uri.parse(url));
        DataSource<CloseableReference<CloseableImage>> dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, null);
        dataSource.subscribe(new BaseBitmapDataSubscriber() {
            @Override
            protected void onNewResultImpl(@Nullable Bitmap bitmap) {
                if (bitmap == null) {
                    imageListener.onFail(new Throwable("bitmap empty"));
                    return;
                }
                float scaleSize = getScaleSize(bitmap, viewWidth, viewHeight);
                imageListener.onSucceed(Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() / scaleSize), (int) (bitmap.getHeight() / scaleSize), false));
            }

            @Override
            protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                imageListener.onFail(dataSource.getFailureCause());
            }
        }, CallerThreadExecutor.getInstance());
    }

    @Override
    public void preloadImage(String url) {
        if (url.isEmpty() || isDownloaded(Uri.parse(url))) {
            return;
        }
        ImageRequest imageRequest = ImageRequest.fromUri(Uri.parse(url));
        Fresco.getImagePipeline().prefetchToDiskCache(imageRequest, null);
    }

    private float getScaleSize(Bitmap bitmap, int viewWidth, int viewHeight) {
        float scaleWidth = bitmap.getWidth() / (viewWidth * 1.0f);
        float scaleHeight = bitmap.getHeight() / (viewHeight * 1.0f);
        return Math.max(scaleWidth, scaleHeight);
    }

    private boolean isDownloaded(Uri uri) {
        ImageRequest imageRequest = ImageRequest.fromUri(uri);
        if (imageRequest == null) {
            return false;
        }
        CacheKey cacheKey = Fresco.getImagePipeline().getCacheKeyFactory()
                .getEncodedCacheKey(imageRequest, null);
        return ImagePipelineFactory.getInstance()
                .getMainFileCache().hasKey(cacheKey);
    }
}


3.4 更新用户画像

如您的产品中有账户体系,请在用户登录后立即设置 uuid,以保证用户登录前后口径一致性。Finder SDK 登陆态变化可参考:Finder SDK 登陆态变化

除此之外,您还需要及时通知弹窗SDK用户画像的变化

警告

在SDK版本 >= 2.1.0 之后,更新用户画像只能通过手动更新,旧版升级上来的请改成手动更新模式
注意 : 务必在 AppLog.setUserUniqueID 设置前调用手动更新

2.1.0 以下版本需要为 ReachConfig 增加以下配置:

private ReachConfig initReachConfig() {
		FinderInitConfig finderConfig = new FinderInitConfig.Builder()
								// 设置自动更新为关闭
                .setAutoUpdateUser(false)
                .build();
		return new ReachConfig.Builder()
				// ...省略其他配置...
				// 关闭自动更新
				.setFinderInitConfig(finderConfig)
        .build();
}


以下配置在各个SDK版本均要配置
登录用户

// 手动更新用户画像,需要在合适的时机及时调用,如账号切换
// 更新弹窗SDK用户画像,务必在 AppLog.setUserUniqueID 设置前调用   
GMPPopupSDK.INSTANCE.updateUUid(Config.INSTANCE.getGmpUuid(),Config.INSTANCE.getGmpUuIdType());
// 更新 FinderSDK uuid
AppLog.setUserUniqueID(Config.INSTANCE.getGmpUuid(), Config.INSTANCE.getGmpUuIdType());


退出登录

// 更新弹窗SDK用户画像,务必在 AppLog.setUserUniqueID 设置前调用   
GMPPopupSDK.INSTANCE.updateUUid("","");
// 更新 FinderSDK uuid
AppLog.setUserUniqueID(null,null);


3.5 弹窗状态监听

弹窗 SDK 提供了弹窗状态的回调监听,接入方可以通过该回调监听弹窗弹出/关闭/弹窗按钮点击行为,并且可以拦截对应的点击事件

设置弹窗状态监听

// 在 initGMPPopSDK 之后设置
private void setGMPPopWindowStatusListener() {
    GMPPopupSDK.INSTANCE.setPopupWindowStatusListener(new PopupWindowStatusListener() {

        /**
         * 弹窗展示时回调
         * @param popupWindowControl GMP弹窗控制接口 // SDK >= 2.1.2 增加
         */
        @Override
        public void onPopupWindowShow(IPopupWindowControl popupControl) {
        }

        /**
         * 弹窗关闭时回调
         */
        @Override
        public void onPopupWindowDismiss() {

        }

        /**
         * 弹窗中配置了跳转链接的按钮/图片被点击且拦截了弹窗的点击事件时回调
         * 只有当 interceptPopupWindowClick 返回为 true 时回调
         * @param url 点击的内容
         */
        @Override
        public void onPopupWindowClick(@NonNull String url) {

        }

        /**
         * 是否拦截弹窗的点击事件
         * @param url 点击的内容
         * @return 返回值为true代表由接入方处理跳转逻辑
         *  为false则会由sdk启动内嵌h5页处理跳转逻辑(必须是http开头的链接)
         */
        @Override
        public boolean interceptPopupWindowClick(@NonNull String url) {
            return false;
        }

				/**
				 * SDK 版本 >= 2.1.1 才存在
				 * 准备触达弹窗:真实弹窗的之前会回调该接口
				 * @return true 表示准备好了,触达即将开始,弹出弹窗;false 表示不进行触达,不弹出
				 */
				@Override
				public boolean popupWindowShouldShow() {
				    return true;
				}

				
        /**
	       * SDK 版本 >= 2.1.2 才存在
		     * 弹窗前解析自定义规则,配置了自定义规则才会回调到这个接口
		     * 回调在子线程
		     * @param json 透传json 可能为null
		     * @param callback 可以弹窗回调true,否则回调false。
		     */
		     @Override
		    public void popupWindowShowJudgeFromClient( @Nullable JSONObject json, ClientRuleStrategyCallback callback) {
		        // 如果本地不处理json内容,回调 true 即可
		        callback.showPopupWindow(true);
		        // 需要处理json示例
		        /**
		        if( json != null || json 解析,并且可以处理 ) {
		            // 网络请求、本地判断等操作 之后
		            if(可以弹窗) {
		                callback.showPopupWindow(true);
		            }else{
		                callback.showPopupWindow(false);
		            }
		        }else{
		            // 不能进行弹窗
		            callback.showPopupWindow(false);
		        }
		         **/
		    }
		    });
}



移除弹窗状态监听

SDK内部会持有该listener的强引用,因此在不需要用到的时候请及时移除它

GMPPopupSDK.INSTANCE.removePopupWindowStatusListener();


4. 其他可选配置

4.1 弹窗预览

点击预览弹窗后,接入方可以通过扫一扫获取到弹窗的id,将其传入SDK的预览弹窗接口,可以在调用预览接口的页面立刻弹出对应弹窗,调用SDK预览接口示例如下

GMPPopupSDK.INSTANCE.preViewPopupWindow("windowId");

在gmp平台管理中心-通道管理-app弹窗,找到需要预览的弹窗扫码即可获取到对应弹窗的windowId

4.2 禁用弹窗

在某些沉浸式场景(如视频播放)或已弹窗场景可以禁止弹窗SDK的弹窗以避免对用户的体验带来干扰(关闭后需要在允许弹窗的场景再次调用来重新启用弹窗功能)

// enablePopup 是否禁用弹窗
// closeShowingPopupWindow 是否关闭正在显示的弹窗,默认为false(enablePopup为false才生效)
GMPPopupSDK.INSTANCE.setPopupEnableStatus(enablePopup,closeShowingPopupWindow);

4.3 图片预加载

4.3.1 预加载等级

为了降低弹窗弹出的时延,弹窗SDK支持对即将弹出的弹窗中的图片进行预加载,接入方可以根据自身需求设置不同等级的图片预加载

字段说明类型

ImagePreLoadLevel

弹窗SDK图片预加载等级,默认值 ONLY_BACKGROUND
可选项:

  • NONE: 不对任何图片进行预加载
  • ONLY_BACKGROUND: 对弹窗或蒙层的背景图片进行预加载(默认)
  • ONLY_IMAGE: 对图片/按钮控件的图片进行预加载
  • ALL: 对所有图片进行预加载

enum

GMPPopupSDK.INSTANCE.setPopupImagePreLoadLevel(ImagePreLoadLevel.ALL);


4.3.2 预加载图片格式

// 默认可加载的图片格式
List<String> DEFAULT_IMAGE_FORMAT = Arrays.asList("gif", "png", "jpg", "jpeg", "webp", "svp", "psd", "bmp", "tif");

// 如需修改可在初始化时设置imageFormat
GMPPopupSDK.INSTANCE.initPopup(this,
        new PopupConfig.Builder()
                .setReachConfig(reachConfig)
                // 设置 GMP 弹窗id
                .setPopupAppId(Config.INSTANCE.getGmpPopupAppId())
                // 可选: 设置允许预加载的图片格式
                .setImageFormatList(DEFAULT_IMAGE_FORMAT)
                .build()
);


4.4 设置弹窗补偿(版本>=2.1.0)

APP弹窗是事件触发型的通道,在客户端本地完成弹窗的触发,「app弹窗」的触发可能在以下场景下触发失败;

触发弹窗时命中勿扰配置;
触发弹窗时用户侧为弱网不境;触发弹窗时遭遇其他未知异常。
当前触发失败后本次触达任务就结束了,因此在触发弹窗时允许设置补偿机制使本次触发失败的弹窗任务在下一次事件触发时尝试进行弹窗。
设置弹窗补偿的示例代码如下

// 如需修改可在初始化时设置imageFormat
GMPPopupSDK.INSTANCE.initPopup(this,
        new PopupConfig.Builder()
                 // 省略其他配置.....
				         // 设置开启弹窗补偿
				        .setEnablePopupCompensate(true)
                .build()
);


4.5 设置轮询间隔(版本>=2.1.0)

最新版本的弹窗 SDK 是通过轮询的方式来更新弹窗规则的,默认的轮询间隔是 300 秒。如果您对弹窗任务实时性有着更高事实性的要求,可以在初始化弹窗 SDK 时传入 pollingInterval 自定义轮询的时间间隔。(小于等于0不轮询)

GMPPopupSDK.INSTANCE.initPopup(this,
        new PopupConfig.Builder()
                 // 省略其他配置.....
				         // 设置轮询间隔, 单位秒 , 小于等于0 不轮询 , 内部默认轮询间隔 300s
				        .setPollingInterval(600)
                .build()
);

4.6 线程调度策略

支持在初始化 ReachConfig 中设置 IThreadConfig 用于管理线程调度

可以实现这个接口用于管理线程,SDK 中提供了线程池作为默认实现

java:

interface IThreadConfig{
		// 主线程 handler
    Handler getMainHandler();
	  // 子线程 handler
    Handler getBackgroundHandler();
}
new ReachConfig.Builder()
        // 省略其他配置.....
        // 接口实现参考例子,请按照项目中实际配置
        // 设置线程调度策略 , 可以配置项目自己的线程池 , 防止后台过多线程执行
        .setThreadConfig(new IThreadConfig() {
            @NonNull
            @Override
            public Handler getMainHandler() {
                return new Handler(Looper.getMainLooper());
            }

            @NonNull
            @Override
            public Handler getBackgroundHandler() {
                HandlerThread ht = new HandlerThread("BackgroundHandler");
                ht.start();
                return new Handler(ht.getLooper());
            }
        })
        .build();


4.7 其他平台uba配置

如果你没有使用 Finder 作为 uba , 而是使用了别的平台的 uba ,

若使用 Finder SDK 进行数据上报,则无需关注此部分。若确认不使用 Finder SDK 上报数据,而是使用自己的 UBA 库进行数据上报,则需要实现 IUBAConfig 接口并初始化注入到 SDK 中。

4.7.1 实现 IUBAConfig 接口

IUBAConfig 接口定义 如下

public interface IUBAConfig {
    /**
     * 获取设备id(设备唯一标识)
     * @return
     */
    @NonNull
    String getDid();

    /**
     * 获取基准id(用户唯一标识)
     * @return
     */
    @NonNull
    String getBaseId();

    /**
     * 上报事件
     * @param eventName 事件名
     * @param jsonObject 事件属性
     * @return
     */
    void onEvent(@NotNull String eventName, @NotNull JSONObject jsonObject);

    /**
     * 获取AB实验参数
     * Params:
     * @param abKey - 实验标识
     * @param defaultValue - 默认值
     * @return 实验参数
     */
    @Nullable
    Object getABConfig(@NotNull String abKey, Object defaultValue);

    /**
     * 获取 Uba 的通参
     * @return 
     */
    @Nullable
    JSONObject getUbaCommonParams();
}

4.7.1 设置 UBAConfig

new ReachConfig.Builder()
        // 省略其他配置.....
        // 设置项目用到的 uba 系统, 默认接入为 finder
        .setUbaConfig(new IUBAConfig() {
            @NonNull
            @Override
            public String getDid() {
                return "";
            }

            @NonNull
            @Override
            public String getBaseId() {
                return "";
            }

            @Override
            public void onEvent(@NonNull String s, @NonNull JSONObject jsonObject) {

            }

            @Nullable
            @Override
            public <T> T getABConfig(@NonNull String s, T t) {
                return null;
            }

            @Nullable
            @Override
            public JSONObject getUbaCommonParams() {
                return null;
            }
        })
        // 设置 debug 输出日志
        .debug(true)
        .build();


4.7.2 传入埋点事件

弹窗SDK 内部会默认 Finder 读取需要上报的埋点事件 , 而使用了别的 uba 之后, 需要把上报的埋点事件传入, 让弹窗SDK 内部可以正常消费事件并顺利弹窗

GMPPopupSDK.INSTANCE.reportEventForPopupWindow("eventName" , new JSONObject());


4.8 关闭正在显示的GMP弹窗

在某些场景下想关闭正在显示的GMP弹窗时,可通过以下方法进行关闭

GMPPopupSDK.INSTANCE.closeShowingPopupWindow();

4.9 匿名用户弹窗(SDK版本>=2.1.4)

SDK默认不开启匿名用户弹窗,即用户需要在登录情况下弹窗,未登录不弹窗。
如果需要支持匿名(未登录)用户弹窗,可通过以下方式开启

//ReachConfig 里面设置设备ID类型
new ReachConfig.Builder()
    // 省略其他配置.....
    .setDeviceIdType(deviceIdType)

//PopupConfig开启匿名用户弹窗开关 
GMPPopupSDK.INSTANCE.initPopup(
    this,
    new PopupConfig.Builder()
            // 省略其他配置.....
				    // 设置开启弹窗补偿
				    .setEnablePopupCompensate(true)
            .build()
);

5. 触发弹窗

5.1 配置弹窗任务

在GMP首页,选择用户触达-消息触达-新增触达任务,选择App弹窗通道并选择在 3.1.3 中获取的弹窗应用,配置任务对应的事件及筛选条件如下图所示

5.2 客户端上报事件

Finder

在app上使用finder sdk上报对应的事件及参数

JSONObject body = new JSONObject();
body.put("param_name_1", "param_value_1");
body.put("param_name_2", "param_value_2");
// ......
AppLog.onEventV3(eventName, body);


其他 UBA

GMPPopupSDK.INSTANCE.reportEventForPopupWindow("eventName" ,new JSONObject());


6. 合规处理(隐私政策初始化的处理)

弹窗SDK 务必在 Application 中初始化,如果您的app中涉及隐私弹窗协议,只需要在隐私弹窗协议同意之后再更新用户画像即可(见3.4)。即在隐私弹窗协议同意之后调用 GMPPopupSDK.INSTANCE.updateUUid(xxx,xxx) 即可。

三、常见问题

1. 弹窗没有正常弹出

当弹窗没有按预期正常弹出时,接入方可以按照下列顺序进行排查

  • 检查弹窗SDK是否正常初始化,是否正常触发了 xxx 接口来拉取任务列表
    (xxx 为 2.1.0 以及以上:/openapi/v3/rule_engine/get_popup_rule_list;2.1.0 以下:/openapi/v1/app_window/getAppWindowTask)

  • 抓包查看 xxx 接口是否正确下发配置的任务(如无下发则检查appId、popupAppId是否正确配置,以及当前用户是否在任务的圈选人群中)
    (xxx 为 2.1.0 以及以上:/openapi/v3/rule_engine/get_popup_rule_list;2.1.0 以下:/openapi/v1/app_window/getAppWindowTask)

  • 开启sdk调试模式,日志过滤"Popup",查看是否有"开始消费事件${eventName}"对应事件的消费日志(如果没有则代表此时SDK没有进行事件消费,检查配置是否有问题)

  • 开启sdk调试模式,日志过滤"Popup",查看是否有"触发勿扰/频控"的日志(如果有则代表该任务被频控/勿扰限制无法弹窗)

  • 开启sdk调试模式,日志过滤"Popup",查看是否有"事件${eventName}满足弹窗条件"的日志(如果有则代表该事件成功匹配上某个任务且未被频控勿扰所拦截,即将进行弹窗渲染)

  • 开启sdk调试模式,日志过滤"Popup",查看是否有弹窗失败相关日志(如果有则代表弹窗渲染过程出现问题)

  • 开启日志后,查询 SDK 有没有内部报错,

    • 如: OKHttp 的错误排查下项目是否引入了 OKHttp 的库(SDK 版本 < 2.1.1 需要引入)
    • 如:kotlin.jvm.internal.FunctionReferenceImpl 错误,SDK 内Kotlin语法太高级,Java项目无法识别,请 onCall 我们。
    • 其他错误,请 onCall 我们。
  • 可以正常弹出不带图片的弹窗,但是弹不出带图片的弹窗,查看 IImageConfig 是否实现有误,getImage的listener是否正确回调 onSuccess 、 onFail 。(SDK 版本 < 2.1.1 需要确保该接口必须实现)

2. 编译问题

  • AndroidX 项目引入SDK后,报 app:checkDebugDuplicateClasses 错误。请在gradle.properties文件下增加
android.useAndroidX=true
android.enableJetifier=true
  • 编译遇到:Error while executing java process with main class com.google.devtools.build.android.desugar.Desugar with arguments。尝试使用 aar 的方式手动引入。
四、埋点说明

GMP弹窗SDK埋点说明文档

★版本记录

Android 弹窗、资源位SDK 版本记录