前言:
Android中事件统计是很常见的需求,最近做了一些封装,可以很好地看出统计事件的详细数据,使用也很方便简单,代码如下:
1.在App的build.gradle目录下添加友盟统计依赖:
implementation 'com.umeng.umsdk:common:9.4.0' // (必选)版本号
implementation 'com.umeng.umsdk:asms:1.4.0' // asms包依赖(必选)
implementation 'com.umeng.umsdk:apm:1.4.0' // apm包依赖(可选)
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'
2.初始化:这里只是写了一个例子,所以隐私合规没有处理,真正项目需要用户同意隐私协议后才能初始化。
3.友盟工具类:
package com.example.umengdemo.utilsimport android.content.Contextimport android.os.Bundleimport com.umeng.analytics.MobclickAgent
import com.umeng.commonsdk.BuildConfig
import com.umeng.commonsdk.UMConfigure
import com.umeng.umcrash.UMCrash
/**
* @auth: njb
* @date: 2021/10/21 15:06
* @desc: 友盟工具类
*/
class UmengUtils private constructor() {
/**
* 友盟初始化方法
*/
fun init(context: Context) {
//集成Umeng崩溃
val bundle = Bundle()
bundle.putBoolean(UMCrash.KEY_ENABLE_CRASH_JAVA, true)
bundle.putBoolean(UMCrash.KEY_ENABLE_CRASH_NATIVE, true)
bundle.putBoolean(UMCrash.KEY_ENABLE_CRASH_UNEXP, true)
bundle.putBoolean(UMCrash.KEY_ENABLE_ANR, false)
bundle.putBoolean(UMCrash.KEY_ENABLE_PA, false)
bundle.putBoolean(UMCrash.KEY_ENABLE_LAUNCH, false)
bundle.putBoolean(UMCrash.KEY_ENABLE_MEM, false)
UMCrash.initConfig(bundle)
//设置友盟log开关,默认为false
UMConfigure.setLogEnabled(BuildConfig.DEBUG)
//初始化组件化基础库, 统计SDK
UMConfigure.init(context, UM_APP_KEY, UM_APP_CHANNEL, UMConfigure.DEVICE_TYPE_PHONE, null)
//设置统计模式
MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO)
//设置发送策略时间为40秒
MobclickAgent.setSessionContinueMillis((1000 * 40).toLong())
}
companion object {
val UM_APP_KEY = "617236e8e0f9bb492b3974f4"
val UM_APP_CHANNEL = "android"
val EVENT_ID = "event_compile"
@Volatile
var mInstance: UmengUtils? = null
fun getInstance(): UmengUtils? {
if (mInstance == null) {
synchronized(UmengUtils::class.java) {
if (mInstance == null) {
mInstance = UmengUtils()
}
}
}
return mInstance
}
}
}
4.友盟统计事件工具类:
package com.example.umengdemo.utilsimport android.annotation.SuppressLintimport android.content.Contextimport com.umeng.analytics.MobclickAgentimport java.util.*
/**
* @auth: njb
* @date: 2021/10/14 14:03
* @desc: 友盟事件统计工具类
*/
object UmengEventUtil {
//设备id
private const val DEVICEID = "deviceid"
//imsi
private const val IMSI = "imsi"
//mac地址
private const val MAC = "mac"
//手机类型
private const val PHONE_MODEL = "phone_model"
//手机系统版本
private const val PHONE_VERSION = "phone_version"
//用户id
private const val USERID = "userId"
//手机号
private const val PHONE = "phone"
//邮箱
private const val EMAIL = "email"
//版本号
private const val VERSION_CODE = "version_code"
//版本名称
private const val VERSION_NAME = "version_name"
//当前时间
private const val CURRENT_TIME = "current_time"
//用户登录事件
private const val USER_LOGIN = "User_Login"
//用户退出事件
private const val USER_SIGN_OUT = "User_Sign_Out"
//用户打开App事件
private const val OPEN_APP = "Open_App"
/**
* 用户打开App事件
*
* @param context
*/
fun toOpenApp(context: Context?) {
val map = getInstallMap(context)
MobclickAgent.onEvent(context, OPEN_APP, map)
}
/**
* 用户安装app事件
*
* @param ctx
* @return
*/
@SuppressLint("MissingPermission")
fun getInstallMap(ctx: Context?): HashMap<String, String> {
val map = HashMap<String, String>()
setBaseMap(ctx, map)
map[PHONE_MODEL] = CommonUtils.getPhoneModel()
map[PHONE_VERSION] = CommonUtils.getVersionRelease()
map[CURRENT_TIME] =
TimeUtils.parserTimeToYmdHmSpace(System.currentTimeMillis())
return map
}
/**
* 设置拍照基本参数
*
* @param context
* @param map
* @return
*/
private fun setBaseMap(
context: Context?,
map: HashMap<String, String>
): HashMap<String, String> {
val userId = "user_id"
if (userId != null) {
map[USERID] = userId //userId
}
val versionCode = CommonUtils.getVersionName(context)
if (versionCode != null) {
map[VERSION_CODE] = versionCode //版本号
}
val currentTime = System.currentTimeMillis()
//当前时间
map[CURRENT_TIME] =
TimeUtils.parserTimeToYmdHmSpace(currentTime)
//手机型号
map[PHONE_MODEL] = CommonUtils.getPhoneModel()
return map
}
}
封装一个打开app的事件:
/** * 用户打开App事件 * * @param context */fun toOpenApp(context: Context?) {
val map = HashMap<String, String>()
setBaseMap(context,map)
MobclickAgent.onEvent(context, OPEN_APP, map)
}
统计参数有手机型号、app版本号、当前时间、用户id等,这些参数可以根据产品需求进行统一封装,方便后期查看数据,其他人接手一看就明白又那些参数,统计事件的含义。
/** * 设置基本参数 * * @param context * @param map * @return
*/
private fun setBaseMap(
context: Context?,
map: HashMap<String, String>
): HashMap<String, String> {
val userId = "user_id"
if (userId != null) {
map[USERID] = userId //userId
}
val versionCode = CommonUtils.getVersionName(context)
if (versionCode != null) {
map[VERSION_CODE] = versionCode //版本号
}
val currentTime = System.currentTimeMillis()
//当前时间
map[CURRENT_TIME] =
TimeUtils.parserTimeToYmdHmSpace(currentTime)
//手机型号
map[PHONE_MODEL] = CommonUtils.getPhoneModel()
return map
}
5.手机信息工具类:
package com.example.umengdemo.utilsimport android.annotation.SuppressLintimport android.app.Activityimport android.content.Contextimport android.content.Intentimport android.content.pm.PackageManagerimport android.net.Uriimport android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
import android.os.Build
import android.text.TextUtils
import android.util.Log
import java.net.Inet6Address
import java.net.InetAddress
import java.net.NetworkInterface
import java.net.SocketException
import java.util.*
/**
* @auth: njb
* @date: 2021/7/15 14:03
* @desc: 获取版本及手机信息工具类
*/
object CommonUtils {
/**
* 获取版本号(内部识别号) = 101
*
* @param context
* @return
*/
fun getVersionCode(context: Context): Int {
return try {
val pi = context.packageManager.getPackageInfo(context.packageName, 0)
pi.versionCode
} catch (e: PackageManager.NameNotFoundException) {
// TODO Auto-generated catch block
e.printStackTrace()
0
}
}
/**
* 获取版本号 = "1.0.1";
*
* @param context
* @return
*/
fun getVersionName(context: Context): String {
return try {
val pi = context.packageManager.getPackageInfo(context.packageName, 0)
pi.versionName
} catch (e: PackageManager.NameNotFoundException) {
// TODO Auto-generated catch block
e.printStackTrace()
"未知版本"
}
}
/**
* 根据Wifi信息获取本地Mac
*
* @param context
* @return
*/
@SuppressLint("HardwareIds")
fun getLocalMacAddressFromWifiInfo(context: Context): String? {
var info: WifiInfo? = null
try {
val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
info = wifi.connectionInfo
} catch (e: Exception) {
e.printStackTrace()
}
return info?.macAddress
}// skip ipv6
/**
* 获取ip地址
*
* @return
*/
val hostIP: String
get() {
var hostIp = ""
try {
val nis: Enumeration<*> = NetworkInterface.getNetworkInterfaces()
var ia: InetAddress? = null
while (nis.hasMoreElements()) {
val ni = nis.nextElement() as NetworkInterface
val ias = ni.inetAddresses
while (ias.hasMoreElements()) {
ia = ias.nextElement()
if (ia is Inet6Address) {
continue // skip ipv6
}
val ip = ia.hostAddress
if ("127.0.0.1" != ip) {
hostIp = ia.hostAddress
break
}
}
}
} catch (e: SocketException) {
Log.e("e", "SocketException")
e.printStackTrace()
}
return hostIp
}
/**
* 获取手机型号
*
* @return
*/
val phoneModel: String
get() {
val model = Build.MODEL
return if (TextUtils.isEmpty(model)) {
""
} else model
}
/**
* 获取手机系统版本号
*
* @return
*/
val versionRelease: String
get() {
val version = Build.VERSION.RELEASE
return if (TextUtils.isEmpty(version)) {
""
} else version
}
/**
* 是否有访问所有文件的权限
*
* @param activity
* @return
*/
fun isRequestAllFileManager(activity: Activity?): Boolean {
/* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
//手机版本为Android11且没有申请权限跳转新页面申请权限,有权限则去做相应工作
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + AppUtils.getPackageName(activity)));
activity.startActivity(intent);
return false;
}*/
return true
}
/**
* 检测是否安装支付宝
* @param context
* @return
*/
fun isAliPayInstalled(context: Context): Boolean {
val uri = Uri.parse("alipays://platformapi/startApp")
val intent = Intent(Intent.ACTION_VIEW, uri)
val componentName = intent.resolveActivity(context.packageManager)
return componentName != null
}
/**
* 检测是否安装微信
* @param context
* @return
*/
fun isWeChatInstalled(context: Context): Boolean {
val packageManager = context.packageManager // 获取packagemanager
val packageInfo = packageManager.getInstalledPackages(0) // 获取所有已安装程序的包信息
for (i in packageInfo.indices) {
val pn = packageInfo[i].packageName
if (pn == "com.tencent.mm") {
return true
}
}
return false
}
}
6.统计事件的使用:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //打开App统计事件 UmengEventUtil.toOpenApp(this) }}
7.说一下需要注意的问题:
7.1.初始化一定要在用户同意隐私之后进行,要不然华为、google各大应用市场上架不会通过.
7.2.可以友盟崩溃统计需要设置统计类型和参数.
7.3.可以需要设置统计log开关,参考友盟官网,一般项目debug开启日志,release关闭日志.
7.4.可以设置统计模式,如果为PageMode.AUTO,Activity不需要单独设置,其他2个模式需要.
7.5.可以设置发送策略时间,默认为40秒.
7.6.统计参数使用Map,Key值不能为空字符串或者null,必须填写,value可为空.
8.可以看到,使用的时候很方便,就一句话,参数也封装起来,不需要额外传递,当然这些参数只是基础的,后期可以根据实际情况传递相应参数,如果想做组件化,可以独立成模块,也可以放到Base组件,这样可以统一管理统计事件。
9.最后,放出项目的源码地址:
UmengStatisDemo: 友盟统计事件的使用demo