Android中使用Kotlin封装一个友盟统计工具类

 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.utils

import android.content.Context

import android.os.Bundle

import 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.utils

import android.annotation.SuppressLint

import android.content.Context

import com.umeng.analytics.MobclickAgent

import 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.utils

import android.annotation.SuppressLint

import android.app.Activity

import android.content.Context

import android.content.Intent

import android.content.pm.PackageManager

import android.net.Uri

import 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.说一下需要注意的问题:


 a.初始化一定要在用户同意隐私之后进行,要不然华为、google各大应用市场上架不会通过.

b.可以友盟崩溃统计需要设置统计类型和参数.

c.可以需要设置统计log开关,参考友盟官网,一般项目debug开启日志,release关闭日志。

d.可以设置统计模式,如果为PageMode.AUTO,Activity不需要单独设置,其他2个模式需要.

e.可以设置发送策略时间,默认为40秒

f.统计参数使用Map,Key值不能为空字符串或者null,必须填写,value可为空.

8.可以看到,使用的时候很方便,就一句话,参数也封装起来,不需要额外传递,当然这些参数只是基础的,后期可以根据实际情况传递相应参数,如果想做组件化,可以独立成模块,也可以放到Base组件,这样可以统一管理统计事件。

最后,放出项目的源码地址:

UmengStatisDemo: 友盟统计事件的使用demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容