?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組件,這樣可以統一管理統計事件。
最后,放出項目的源碼地址: