一、前言:
由于海外小说需要埋点,来测试用户的习惯和喜好,调研采用Amplitude埋点
官网图片.png二、使用:
1、引入sdk
//amplitude埋点引入
implementation 'com.amplitude:analytics-android:1.+'
2、初始化SDK
/**
* amplitude埋点初始化
*/
var amplitude: Amplitude? = null
/**
* 设置单个点击事件-所有属性
*/
var userStates = "未登录"
fun initAmplitude() {
val configuration =
Configuration("apiKey", BWNApplication.applicationContext)
configuration.defaultTracking = DefaultTrackingOptions.ALL
//埋点主对象
amplitude = Amplitude(configuration)
//当多个APP使用同一个apiKey时,setUserId 不要指定,否则用户活跃数,一直是1
//amplitude?.setUserId("com.xxxx.helloword")
//日志输出模式
amplitude?.logger?.logMode = Logger.LogMode.DEBUG
}
注意:当多个APP使用同一个apiKey时,若是写死setUserId 好像没有sessions 事件,否则用户活跃数,一直是1,还有若是setUserId 设置为null后者为空,就会埋点上报失败(error: Invalid id length for user_id or device_id),userId或者deviceId为空或者是无效的。我们只要不设置setUserId就可以了。
// DefaultTrackingOptions.ALL指定有sessions ,screenViews 事件
val ALL = DefaultTrackingOptions(
sessions = true,
appLifecycles = true,
deepLinks = true,
screenViews = true
)
3、清除公共属性
fun clearCommonAttribute() {
identify?.clearAll();
}
4、设置公共属性
fun setCommonAttribute(
userId: String? = null
) {
//设置公共属性(每次都要重新创建,否则 amplitude?.identify(item) 不生效)
var identify = Identify()
identify?.let { item ->
//{用户ID}/“未登录”
userId?.let {
amplitude?.setUserId(it)
item.set("cmn_user_id", it)
}?: kotlin.run {
//因为每次重新创建的Identify对象,所以为null也要设置值
item.set("cmn_user_id", UserUtils.getUID())
}
//--------不变的值---------
//APP版本
item.set("cmn_app_version", "V${BuildConfig.VERSION_NAME}")
//平台
item.set("cmn_platform", "安卓")
//设置所有属性
amplitude?.identify(item)
//打印所有属性
MyToash.Log("amplitude","--: ${item.properties.toString()}")
}
}
所有属性值
{$set={cmn_user_id=88087173, cmn_login_type=Google, cmn_user_type=老用户, cmn_member_status=会员, cmn_coins_number=15617, cmn_freecoins_number=425, cmn_books_number=7, cmn_app_name=CrazyNovels, cmn_app_version=V1.1.2, cmn_platform=安卓}}
注意:Identify()设置公共属性(每次都要重新创建,否则 amplitude?.identify(item) 不生效)
5、点击事件上报
fun setSingleClickAttribute(eventType: String, map: HashMap<String, String>? = null) {
MyToash.Log("amplitude","上报事件:${eventType} --上报参数:${map}")
map?.let {
// var ev = EventOptions()
amplitude?.track(eventType, it)
} ?: kotlin.run {
amplitude?.track(eventType)
}
}
三、完成代码
import android.os.Build
import androidx.annotation.RequiresApi
import com.amplitude.android.Amplitude
import com.amplitude.android.Configuration
import com.amplitude.android.DefaultTrackingOptions
import com.amplitude.android.events.Identify
import com.amplitude.common.Logger
import com.youjiakeji.yjkjreader.BuildConfig
import com.youjiakeji.yjkjreader.base.BWNApplication
import com.youjiakeji.yjkjreader.base.BaseKey
import com.youjiakeji.yjkjreader.constant.CommonConstantUtils
import com.youjiakeji.yjkjreader.ui.utils.MmkvUtils
import com.youjiakeji.yjkjreader.ui.utils.MyToash
import com.youjiakeji.yjkjreader.utils.UserUtils
import java.text.SimpleDateFormat
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.collections.HashMap
/**
* 全局公共埋点
*/
object CommonAmplitudeUtils {
/**
* amplitude埋点初始化
*/
var amplitude: Amplitude? = null
/**
* 设置单个点击事件-所有属性
*/
var userStates = "未登录"
fun initAmplitude() {
val configuration =
Configuration("xxxxxxxxxxxxxxxxxxxxxx", BWNApplication.applicationContext)
configuration.defaultTracking = DefaultTrackingOptions.ALL
//埋点主对象
amplitude = Amplitude(configuration)
//当多个APP使用同一个apiKey时,setUserId 不要指定,否则用户活跃数,一直是1
// amplitude?.setUserId("com.hhhh.helloword")
//日志输出模式
amplitude?.logger?.logMode = Logger.LogMode.DEBUG
}
/**
* 设置公共属性 -key:String,value:String
*/
fun setCommonAttribute(
userId: String? = null,
cmnLoginType: String? = null,
registTime: String? = null,
cmnMemberStatus: String? = null,
cmnCoinsNumber: String? = null,
cmnFreecoinsNumber: String? = null,
cmnBooksNumber: String? = null
) {
//设置公共属性(每次都要重新创建,否则 amplitude?.identify(item) 不生效)
var identify = Identify()
identify.let { item ->
//{用户ID}/“未登录”
userId?.let {
item.set("cmn_user_id", it)
} ?: kotlin.run {
item.set("cmn_user_id", UserUtils.getUID())
}
//登录类型- “Google”/“Facebook”/“Apple”/“游客”/“未登录”
cmnLoginType?.let {
item.set("cmn_login_type", it)
} ?: kotlin.run {
item.set("cmn_login_type", appIsUserStatus())
}
//用户类型- “新用户”/“老用户”/“未登录”
registTime?.let {
item.set("cmn_user_type", it)
} ?: kotlin.run {
item.set("cmn_user_type", userStates)
}
//用户会员状态 - “会员”、“非会员”、“未登录”
cmnMemberStatus?.let {
item.set("cmn_member_status", it)
} ?: kotlin.run {
item.set("cmn_member_status", appIsVip())
}
//用户书币数量 - {书币数量}/“未登录”
cmnCoinsNumber?.let {
item.set("cmn_coins_number", it)
} ?: kotlin.run {
item.set("cmn_coins_number", appCoinNum())
}
//用户免费书币数量 - {免费书币数量}/“未登录”
cmnFreecoinsNumber?.let {
item.set("cmn_freecoins_number", it)
} ?: kotlin.run {
item.set("cmn_freecoins_number", appFreeCoinNum())
}
//用户藏书数量 - {收藏书籍数量}
cmnBooksNumber?.let {
item.set("cmn_books_number", it)
} ?: kotlin.run {
item.set("cmn_books_number", appBookCollectNum())
}
//--------不变的值---------
//APP名称 - “CrazyNovels”/“疯狂小说”/“夜色小说”
item.set("cmn_app_name", "CrazyNovels")
//APP版本
item.set("cmn_app_version", "V${BuildConfig.VERSION_NAME}")
//平台
item.set("cmn_platform", "安卓")
//设置所有属性
amplitude?.identify(item)
//打印所有属性
MyToash.Log("amplitude", "--: ${item.properties.toString()}")
}
}
/**
* 清除所有公共属性
* isLogout:是否是退出APP
*/
fun setClearAllCommonAttribute(isLogout: Boolean) {
if (isLogout) {
userStates = "未登录"
setCommonAttribute("未登录", "未登录", "未登录", "未登录", "未登录", "未登录", "0")
//设置vip
MmkvUtils.encode(CommonConstantUtils.IS_VIP, false)
//收藏数量
MmkvUtils.encode(CommonConstantUtils.APP_BOOK_COLLECT_NUM, 0)
//书币
MmkvUtils.encode(CommonConstantUtils.APP_BOOK_COIN_NUM, 0)
//免费书币
MmkvUtils.encode(CommonConstantUtils.APP_BOOK_FREE_COIN_NUM, 0)
//注册时长
MmkvUtils.encode(CommonConstantUtils.APP_REGISTER_TIME, 0)
//置空
MmkvUtils.encode(BaseKey.SP_BOOK_NAME, "")
} else if (UserUtils.isLogin()) {
//登录状态
setCommonAttribute(
UserUtils.getUID(), appIsUserStatus(), null,
appIsVip(), appCoinNum(), appFreeCoinNum(), appBookCollectNum()
)
} else {
//未登录状态
userStates = "未登录"
setCommonAttribute("未登录", "未登录", "未登录", "未登录", "未登录", "未登录", "0")
}
}
/**
* 获取
*/
var map1: HashMap<String, String>? = null
var map2: HashMap<String, String>? = null
var lastNum = 1;
fun getHashMap(): HashMap<String, String> {
if (map1 == null) {
map1 = HashMap<String, String>()
map2 = HashMap<String, String>()
}
if (lastNum == 1) {
lastNum = 2
map2?.clear()
return map2!!
} else {
lastNum = 1
map1?.clear()
return map1!!
}
}
fun setSingleClickAttribute(eventType: String, map: HashMap<String, String>? = null) {
//“新用户”/“老用户”/“未登录”
if (userStates != "老用户") {
var localUserStates = isNewOldUser()
if (localUserStates != userStates) {
userStates = localUserStates
//及时更新用户状态
setCommonAttribute(registTime = userStates)
}
}
MyToash.Log("amplitude", "上报事件:${eventType} --上报参数:${map}")
map?.let {
// var ev = EventOptions()
amplitude?.track(eventType, it)
} ?: kotlin.run {
amplitude?.track(eventType)
}
}
//----------------------------------下方是公共属性值的计算---------------------------------
/**
* 新增一个收藏数
*/
fun setAddCollection() {
var newbookCollectNum = MmkvUtils.decodeInt(CommonConstantUtils.APP_BOOK_COLLECT_NUM)
var collection = newbookCollectNum + 1
//更新收藏数
CommonAmplitudeUtils.setCommonAttribute(
cmnBooksNumber = CommonAmplitudeUtils.appBookCollectNum(
collection
)
)
}
/**
* 用户类型
*/
fun appIsUserStatus(type: Int? = null): String {
//登录方式
var newType = 0
type?.let {
newType = type
MmkvUtils.encode(CommonConstantUtils.APP_LOGIN_TYPE, type)
} ?: kotlin.run {
newType = MmkvUtils.decodeInt(CommonConstantUtils.APP_LOGIN_TYPE)
}
return if (newType == 1) "Facebook" else "Google"
}
/**
* 书币
*/
fun appCoinNum(coin: Int? = null): String {
var newCoin = 0
coin?.let {
newCoin = coin
MmkvUtils.encode(CommonConstantUtils.APP_BOOK_COIN_NUM, coin)
} ?: kotlin.run {
newCoin = MmkvUtils.decodeInt(CommonConstantUtils.APP_BOOK_COIN_NUM)
}
return "${newCoin}"
}
/**
* 免费书币
*/
fun appFreeCoinNum(freeCoin: Int? = null): String {
var newfreeCoin = 0
freeCoin?.let {
newfreeCoin = freeCoin
MmkvUtils.encode(CommonConstantUtils.APP_BOOK_FREE_COIN_NUM, freeCoin)
} ?: kotlin.run {
newfreeCoin = MmkvUtils.decodeInt(CommonConstantUtils.APP_BOOK_FREE_COIN_NUM)
}
return "${newfreeCoin}"
}
/**
* 收藏数
*/
fun appBookCollectNum(bookCollectNum: Int? = null): String {
var newbookCollectNum = 0
bookCollectNum?.let {
newbookCollectNum = bookCollectNum
MmkvUtils.encode(CommonConstantUtils.APP_BOOK_COLLECT_NUM, bookCollectNum)
} ?: kotlin.run {
newbookCollectNum = MmkvUtils.decodeInt(CommonConstantUtils.APP_BOOK_COLLECT_NUM)
}
return "${newbookCollectNum}"
}
/**
* 是否是会员
* 1、会员;其它非会员
*/
fun appIsVip(isVip: Int? = null): String {
var newVip = 0
//保存Vip- “会员”、“非会员”、“未登录”
var vipStatus = "非会员"
isVip?.let {
newVip = it
} ?: kotlin.run {
newVip = if (MmkvUtils.decodeBoolean(CommonConstantUtils.IS_VIP)) 1 else 0
}
vipStatus = if (newVip === 1) {
MmkvUtils.encode(CommonConstantUtils.IS_VIP, true)
"会员"
} else {
MmkvUtils.encode(CommonConstantUtils.IS_VIP, false)
"非会员"
}
return vipStatus
}
/**
* 判断是新用户还是老用户
* “新用户”/“老用户”/“未登录”
*/
@RequiresApi(Build.VERSION_CODES.O)
fun isNewOldUser(regTime: Long? = null): String {
var newRegTime: Long = 0
if (regTime == null) {
//获取时长
newRegTime = MmkvUtils.decodeLong(CommonConstantUtils.APP_REGISTER_TIME)
} else {
newRegTime = regTime
}
if (newRegTime > 0L) {
val dateTime =
LocalDateTime.ofInstant(Instant.ofEpochSecond(newRegTime), ZoneId.systemDefault())
val formatter = DateTimeFormatter.ofPattern("yyyyMMdd")
val formattedDate = dateTime.format(formatter)
//本地UTC时间
var utcTimestamp = getUTCTime()
// Log.d("lyy","---formattedDate:${formattedDate}")
// Log.d("lyy","---utcTimestamp:${utcTimestamp}")
if (utcTimestamp == formattedDate) {
return "新用户"
} else {
return "老用户"
}
} else {
return "未登录"
}
}
/**
* Android中获取UTC时间
*/
fun getUTCTime(): String {
// 创建一个SimpleDateFormat对象,指定日期时间格式-yyyy-MM-dd HH:mm:ss
val sdf = SimpleDateFormat("yyyyMMdd")
// 设置时区为UTC
sdf.timeZone = TimeZone.getTimeZone("UTC")
// 格式化日期时间为字符串
var time = sdf.format(Date())
// val date2 = sdf.parse(time)
// val utcTimestamp = date2.time/1000
return time
// Log.d("lyy","---utcTimestamp:${utcTimestamp}")
}
}
网友评论