前言:

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'


友盟统计ios 使用 友盟统计工具_友盟统计ios 使用

友盟统计ios 使用 友盟统计工具_android_02

2.初始化:这里只是写了一个例子,所以隐私合规没有处理,真正项目需要用户同意隐私协议后才能初始化。

友盟统计ios 使用 友盟统计工具_友盟统计ios 使用_03

友盟统计ios 使用 友盟统计工具_1024程序员节_04

3.友盟工具类:

友盟统计ios 使用 友盟统计工具_android_05

友盟统计ios 使用 友盟统计工具_bc_06

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.友盟统计事件工具类:

友盟统计ios 使用 友盟统计工具_android_07

友盟统计ios 使用 友盟统计工具_bundle_08

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的事件:

友盟统计ios 使用 友盟统计工具_bc_09

友盟统计ios 使用 友盟统计工具_友盟统计ios 使用_10

/** * 用户打开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
}


友盟统计ios 使用 友盟统计工具_友盟统计ios 使用_11

友盟统计ios 使用 友盟统计工具_bc_12

5.手机信息工具类:

友盟统计ios 使用 友盟统计工具_bundle_13

友盟统计ios 使用 友盟统计工具_友盟统计ios 使用_14

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.统计事件的使用:

友盟统计ios 使用 友盟统计工具_bc_15

友盟统计ios 使用 友盟统计工具_bc_16

class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        //打开App统计事件        UmengEventUtil.toOpenApp(this)    }}


7.说一下需要注意的问题:

友盟统计ios 使用 友盟统计工具_android_17

友盟统计ios 使用 友盟统计工具_1024程序员节_18

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