Sensors (Android) - the whole process of integrating basic buried points

I remember that in the earliest days, I used Youmeng Family Bucket, I used Youmeng to bury points, and I used Youmeng to push. Correspondingly integrate the SDK of the corresponding platform

God strategy

Everything is subject to the official document , because with the version upgrade, the integration document may be more or less changed. This article only records the whole process of my integration of the basic buried points of Sensors

basic configuration

Basic configuration: covers the introduction of AGP and Sdk

  • For how to AGP 8.0+use the plug-in in the version and the common configuration of the plug-in, please refer to the SDK plug-in description .
  • Android Pluginneed Android Gradle Plugin 3.2.0+, 否则会导致元素点击事件和 Fragment 的页面浏览事件无法触发,App 和 H5 打通功能受影响.
  • Plug-in and SDK version dependencies:
    insert image description here

official configuration

Add the dependency in the file at projectthe level :build.gradleandroid-gradle-plugin2

buildscript {
    
    
    repositories {
    
    
		mavenCentral()
        jcenter()
    }
    dependencies {
    
    
		// 添加 gradle 3.2.0+ 依赖
        classpath 'com.android.tools.build:gradle:3.5.3'
        // 添加神策分析 android-gradle-plugin2 依赖
        classpath 'com.sensorsdata.analytics.android:android-gradle-plugin2:3.5.3'
    }
}

Apply plugin dependencies in your 主 module(app)file :build.gradlecom.sensorsdata.analytics.android

apply plugin: 'com.android.application'
// 应用 com.sensorsdata.analytics.android 插件
apply plugin: 'com.sensorsdata.analytics.android'

dependencies {
    
    
}

In the file 主 moduleof build.gradlethe add SDK 依赖:

apply plugin: 'com.android.application'
// 应用 com.sensorsdata.analytics.android 插件
apply plugin: 'com.sensorsdata.analytics.android'

dependencies {
    
    
   // 添加 Sensors Analytics SDK 依赖
   implementation 'com.sensorsdata.analytics.android:SensorsAnalyticsSDK:6.6.7'
}

Recommended version (as of 2023.6.30)

insert image description here


project configuration

The current project uses kts, not groovy, and the usage of the two may be slightly different

build.gradle(project)

@file:Suppress("UnstableApiUsage", "DSL_SCOPE_VIOLATION")

buildscript {
    
    
    dependencies {
    
    
        classpath("com.android.tools.build:gradle:7.4.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21")
        classpath("com.sensorsdata.analytics.android:android-gradle-plugin2:3.5.4")
    }
}

plugins {
    
    
	//若是感觉某个无用,可自行删除
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library) apply false
    alias(libs.plugins.kotlin.jvm) apply false
    id("org.jetbrains.kotlin.android") version "1.7.21" apply false
}

build.gradle(主 module(app)

plugins {
    
    
    id("haapp.android.application")
    id("com.sensorsdata.analytics.android")
}

build.gradle(module)

哪个模块做相关的初始化操作,就在哪个模块引入 SDK

dependencies {
    
    
    implementation("com.sensorsdata.analytics.android:SensorsAnalyticsSDK:6.6.8")
}

Initialize the SDK

mainly covers 官方SDK初始化and项目初始化的基础封装

Official initialization

Apps in the general financial industry will involve compliance issues and can only be used after confirming user authorization;
delayed initialization of the SDK will lead to inaccurate collection of full buried points and abnormal functions of visualized full buried points and click analysis . If the app has compliance requirements, Refer to the Android compliance steps .

Synchronously call in the method of Applicationto initialize the SDK:onCreate()SensorsDataAPI.startWithConfigOptions()

String SA_SERVER_URL = "数据接收地址";

// 初始化配置
SAConfigOptions saConfigOptions = new SAConfigOptions(SA_SERVER_URL);
// 开启全埋点
saConfigOptions.setAutoTrackEventType(SensorsAnalyticsAutoTrackEventType.APP_CLICK |
                SensorsAnalyticsAutoTrackEventType.APP_START |     
                SensorsAnalyticsAutoTrackEventType.APP_END |       
                SensorsAnalyticsAutoTrackEventType.APP_VIEW_SCREEN)
				//开启 Log
				.enableLog(true);
/**
 * 其他配置,如开启可视化全埋点
 */
// 需要在主线程初始化神策 SDK
SensorsDataAPI.startWithConfigOptions(this, saConfigOptions);

The SDK requires a total of four permissions:
insert image description here

In order to simplify the integration steps, the SDK AndroidManifest.xmlhas registered the above four permissions in by default. If you want to remove the permission of SDK registration, you can use tools:node="remove"configuration. For tools:node="remove"detailed instructions, please refer to Google's official documentation , configuration code reference:

<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />

Project initialization

I only used the direct initialization API (very limited), for more APIs, you can go to the basic API function introduction

It can be written directly in Application, here is a management class encapsulated, which can be Applicationcalled directly in SensorManger.initSetting(context);对应的serviceUrl 地址(上报服务器)需要在神策后台查看一下,也可以让我方运营、神策运营告知一下,因为测试上报的服务器有所不同

import android.app.Activity
import android.app.Application
import android.content.Context
import com.sensorsdata.analytics.android.sdk.SAConfigOptions
import com.sensorsdata.analytics.android.sdk.SensorsAnalyticsAutoTrackEventType
import com.sensorsdata.analytics.android.sdk.SensorsDataAPI
import com.sensorsdata.analytics.android.sdk.core.business.exposure.SAExposureConfig
import org.json.JSONObject
import java.util.concurrent.Executors


internal object SensorManger {
    
    

	// 埋点数据对应的上报服务器,都是需要运营 或 神策方提供
    // 测试
    private const val serviceUrl = "https://xx.com.cn:8888"
    // 生产
    // private const val serviceUrl = "https://xx.com.cn"

    fun initSetting(application: Application) {
    
    
            init(application)
    }

    fun initSetting(activity: Activity) {
    
    
            init(activity)
    }

    private fun init(context: Context) {
    
    
        // 开启全埋点 其他配置,如开启可视化全埋点 需要在主线程初始化神策 SDK
        SensorsDataAPI.startWithConfigOptions(context, SAConfigOptions(serviceUrl).apply {
    
    
            // 开启全埋点
            autoTrackEventType = SensorsAnalyticsAutoTrackEventType.APP_START or
                    SensorsAnalyticsAutoTrackEventType.APP_END
            // 打开 SDK 的日志输出功能
            enableLog(BuildVariants.isDebug())
            // 开启 App 打通 H5
            enableJavaScriptBridge(true)
            // 传入 true 代表开启推送点击事件自动采集
            enableTrackPush(true)
        })
        trackAppInstall(context)
    }

    /**
     * 记录激活事件
     */
    private fun trackAppInstall(context: Context) {
    
    
        try {
    
    
            val properties = JSONObject()
            //这里的 DownloadChannel 负责记录下载商店的渠道,值应传入具体应用商店包的标记。如果没有为不同商店打多渠道包,则可以忽略该属性的代码示例。
            properties.put("DownloadChannel", getChannelName(context))
            // 触发激活事件
            // 如果您之前使用 trackInstallation() 触发的激活事件,需要继续保持原来的调用,无需改为 trackAppInstall(),否则会导致激活事件数据分离。
            SensorsDataAPI.sharedInstance().trackAppInstall(properties)
        } catch (e: Exception) {
    
    
            e.printStackTrace()
        }
    }

    /**
     * 获取渠道名,获取不到默认"android"
     */
    private fun getChannelName(context: Context?): String {
    
    
        var channelName: String? = null
        try {
    
    
            val packageManager: PackageManager? = context?.packageManager
            val applicationInfo: ApplicationInfo? = packageManager?.getApplicationInfo(
                context.packageName,
                PackageManager.GET_META_DATA
            )
            channelName = applicationInfo?.metaData?.get("CHANNEL_ID").toString()
        } catch (e: Exception) {
    
    
            e.printStackTrace()
        }
        return channelName ?: "android"
    }

    private val executor by lazy {
    
     Executors.newSingleThreadExecutor() }

    private fun execute(inv: () -> Unit) {
    
    
        executor.execute {
    
    
            try {
    
    
                inv.invoke()
            } catch (throwable: Throwable) {
    
    
                Timber.e(throwable)
            }
        }
    }

    fun track(eventName: String, properties: Map<String, String?>) = execute {
    
    
        val jsonObject = JSONObject()
        properties.entries.forEach {
    
    
            jsonObject.put(it.key.string(), it.value.string())
        }
        SensorsDataAPI.sharedInstance().track(eventName, jsonObject)
    }
}

Configure Scheme

What is Scheme?

  • It is an in-page jump protocol
  • By defining your own scheme protocol, you can easily jump to each page in the app
  • Through the scheme protocol, the server can be customized to tell the App to jump to the internal page of the APP

When using the Sensors system Debug 实时查看、App 点击分析、可视化全埋点等需要扫码的功能, you need to configure a certain Activity scheme. After configuration, you can scan the code to pull up the Activity page and establish a connection with the Sensors system to use related functions.

official configuration

SDK 5.2.2 and above

In AndroidManifestthe file, configure the following Activity, and replace the value of scheme with the value in your project

<!-- Android 12 需添加 android:exported="true"-->
<activity android:name="com.sensorsdata.analytics.android.sdk.dialog.SchemeActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
android:launchMode="singleTask">
        <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:scheme="您项目的 scheme" />
        </intent-filter>
</activity>

SDK version below 5.2.2

After obtaining the Scheme, AndroidManifestconfigure the Scheme in the Activity tag in the file, taking MainActivity as an example:

<activity android:name=".MainActivity">
<!-- 在 MainActivity 中配置 Scheme-->
	<intent-filter>
		<action android:name="android.intent.action.VIEW" />
		<category android:name="android.intent.category.BROWSABLE" />
		<category android:name="android.intent.category.DEFAULT" />
		<data
			android:scheme="您项目的 Scheme 值" />
	</intent-filter>
</activity> 

project configuration

The corresponding scheme地址needs to be checked in the background of Sensors, or you can let our operation and Sensors operation inform you

insert image description here

AndroidManifest

    <!-- Android 12 需添加 android:exported="true"-->
    <activity
        android:name="com.sensorsdata.analytics.android.sdk.dialog.SchemeActivity"
        android:configChanges="orientation|screenSize"
        android:exported="true"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />

            <category android:name="android.intent.category.BROWSABLE" />
            <category android:name="android.intent.category.DEFAULT" />
            <!-- 测试 -->
            <data android:scheme="l77777" />
            <!-- 生产 -->
            <!--<data android:scheme="l66666" />-->
        </intent-filter>
    </activity>

Get through APP and H5

version requirements

  • Android SDK v4.0.8 及以上版本
  • Android 插件 v3.2.4 及以上版本

When initializing the SDK, perform the following configurations to enable the App to get through the H5 function

// 开启 App 打通 H5
saConfigOptions.enableJavaScriptBridge(boolean isSupportJellyBean);

isSupportJellyBean : Whether to support API level 16 and below versions.

The open function is realized through the method of WebView addJavascriptInterface(), but in the version of API level 16 and below, addJavascriptInterface()the method has security holes, so please use it with caution.

The opening function requires both the App and H5 to be enabled to take effect. For the method of opening H5, please refer to App Opening H5 .

  • X5 内核Get through, add after initializationSensorsDataAPI.sharedInstance().showUpX5WebView(WebView,true);
  • UC 内核In addition to the above code, the WebView also needs to be added in the plug-in configuration: addUCJavaScriptInterface = truethis option, add our extension in the 主 modulelevel file as follows;build.gradle
sensorsAnalytics{
    
    
	addUCJavaScriptInterface=true
}

Because there is exactly this requirement in the project, this function has been turned on when we initialized

insert image description here


Practice Encapsulation

Here is just a simple packaging description. If you are interested, you can go to Sensors (Android) - learn project architecture based on exposure collection. Take a look

StatisticsEvent singleton tool - easy to call

object StatisticsEvent {
    
    

    /**
     * 神策埋点:测试
     */
    @JvmStatic
    fun test(param1: String?) {
    
    
        StatisticsService.service.test(param1)
    }
}

StatisticsService abstract class - statistics method

For related explanations of ServiceManager, you can learn the project architecture on the basis of exposure collection. Take a look, and I won’t repeat it here.

interface StatisticsService {
    
    

	// 这里是实例化该Service,因为Hilt原因,采用了注入方式;可自行改为
    companion object {
    
    
        @JvmStatic
        val service: StatisticsService by lazy {
    
     ServiceManager.queryStatisticsService() }
    }

    // 测试
    fun test(param1: String?)
 }

StatisticsServiceImpl concrete class - method implementation

internal class StatisticsServiceImpl @Inject constructor() : StatisticsService {
    
    

    override fun track(eventName: String?, properties: MutableMap<String, String?>.() -> Unit) {
    
    
        track(eventName, mutableMapOf<String, String?>().apply(properties))
    }

    override fun track(eventName: String?, properties: Map<String, String?>) {
    
    
        if (eventName.isNullOrEmpty()) return
        SensorManger.track(eventName, properties)
    }
    
    /**
     * 神策埋点:测试
     */
    override fun test(param1: String?) {
    
    
        val properties = mutableMapOf<String, String>()
        properties["param1"] = "下雨天"
        SensorManger.track(EventName.test, properties)
    }
}

EventName event name management

internal object EventName {
    
    
    const val test: String = "运营提供的埋点事件名称"     // 测试
  }

interest link

Another way to obtain interface instances in StatisticsServiceCNOOC (mainly using reflection, first obtain the instance, and then ARouterpass it back)

    companion object {
    
    
        @JvmStatic
        val service: StatisticsService? by lazy {
    
     ServiceManager.getService(StatisticsService::class.java) }
    }

ServiceManager gets Service

import com.alibaba.android.arouter.launcher.ARouter

class ServiceManager {
    
    
    companion object {
    
    

        @JvmStatic
        fun <T> getService(service: Class<out T>): T {
    
    
            return ARouter.getInstance().navigation(service)
        }

        @JvmStatic
        fun getService(path: String): Any {
    
    
            return ARouter.getInstance().build(path).navigation()
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_20451879/article/details/131471200