Android 전매점 - 페이지 탐색 이벤트
전매점도 무매점이라고 하는데, 자동매점이라고 한다.사용자의 모든 행위 데이터를 미리 자동으로 수집하는 것을 말한다.그리고 수집된 데이터에 따라 필요한 행위 데이터를 선별하여 분석할 수 있다.
채집된 이벤트 유형
전매점에서 채집하는 사건은 주로 다음과 같은 4가지 유형을 포함한다.
AppStart 이벤트
응용 프로그램의 시작을 가리키며, 냉각 시작과 열 시작을 포함한다.
AppEnd 이벤트
프로그램이 종료되는 것을 가리킨다. 프로그램의 정상적인 종료, 홈 키가 백엔드에 들어가고, 프로그램이 강살되고, 프로그램이 붕괴되는 것을 포함한다.
AppViewScreen 이벤트
응용 프로그램 페이지 탐색을 가리키며 안드로이드 응용 프로그램에서는Activity나Fragment의 전환을 가리킨다.
AppClick 이벤트
프로그램 컨트롤의 클릭 이벤트, 즉 View의 클릭 이벤트를 가리킨다.
AppViewScreen 전매점 방안
페이지 조회 이벤트는 서로 다른 Activity나Fragment를 전환하는 것을 말한다. Activity에 대한 방법
onResume()
은 이 페이지가 이미 표시되었음을 의미한다. 즉, 이 페이지가 조회되었다는 것이다.그래서 우리는 onResume()
방법에서 AppViewScreen 이벤트와 관련된 코드를 자동으로 처리하면 AppViewScreen 이벤트의 전매점을 해결할 수 있다.Application.ActivityLifecycleCallbacks
ActivityLifecycleCallbacks
는 Application
의 내부 인터페이스로 API14(Android4.0)부터 제공된다.Application
류는 이 인터페이스를 통해 일련의 리셋 방법을 제공하여 개발자가 Activity
의 모든 생명주기 사건을 집중적으로 처리할 수 있도록 한다.** Application**에서 제공하는 registerActivityLifecycleCallbacks
방법으로 ActivityLifecycleCallbacks
콜백을 등록할 수 있습니다.이 인터페이스에서 사용할 수 있는 방법을 살펴보겠습니다.
public interface ActivityLifecycleCallbacks {
void onActivityCreated(Activity activity, Bundle savedInstanceState);
void onActivityStarted(Activity activity);
void onActivityResumed(Activity activity);
void onActivityPaused(Activity activity);
void onActivityStopped(Activity activity);
void onActivitySaveInstanceState(Activity activity, Bundle outState);
void onActivityDestroyed(Activity activity);
}
Activity
onResume()
방법의 예를 들어 만약에 우리가 이 인터페이스를 등록했다면 안드로이드 시스템은Activity Lifecycle CallbacksonActivityResumed(Activity activity)
방법을 먼저 리셋한 다음Activity 자체onResume()
방법을 실행할 것이다.(참고: 하나의 Application은 여러 개의ActivityLifecycleCallbacks 콜백을 등록할 수 있습니다)이 방법을 사용하는 것 외에, 우리는BaseActivity를 정의한 다음에 다른Activity가 이BaseActivity를 계승하도록 생각할 수도 있습니다.근데 이게 문제가 될 거예요.만약에 우리가 응용 프로그램에 제3자 라이브러리를 통합하고 제3자 라이브러리의Activity를 사용한다면 우리는 이 페이지의 조회 이벤트를 감시할 수 없다.사용자가 정의한 BaseActivity를 계승할 수 없기 때문입니다.그래서 우리는 Application을 채택한다.Activity Lifecycle Callbacks, 그러나 이 방안은 API14+가 필요하지만, 현재 주류 기종은 모두 만족합니다.
코드 실전
1. 이벤트를 수집하는 데 사용할 도구류 SensorsDataAPI를 정의합니다.
//
class SensorsDataAPI private constructor(application: Application) {
// ID
private var mDeviceId: String = SensorsDataPrivate.getAndroidID(application.applicationContext)
// ,eg: , ,
private var mDeviceInfo: Map = SensorsDataPrivate.getDeviceInfo(application.applicationContext)
companion object {
//
const val SDK_VERSION = "1.0.0"
@Volatile
var instance: SensorsDataAPI? = null
private val TAG = this.javaClass.simpleName
/**
*
* @param application:Application
*/
fun init(application: Application) = instance ?: synchronized(this) {
//
instance ?: SensorsDataAPI(application).also { instance = it }
}
}
init {
// registerActivityLifecycleCallbacks
SensorsDataPrivate.registerActivityLifecycleCallbacks(application)
}
/**
*
* @param eventName:
* @param properties:
*/
fun track(@NonNull eventName: String, @Nullable properties: JSONObject?) {
try {
val jsonObject = JSONObject()
jsonObject.put("event", eventName)
jsonObject.put("device_id", mDeviceId)
val sendProperties = JSONObject(mDeviceInfo)
if (properties != null) {
SensorsDataPrivate.mergeJSONObject(properties, sendProperties)
}
jsonObject.put("properties", sendProperties)
jsonObject.put("time", System.currentTimeMillis())
Log.e(TAG, jsonObject.toString())
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
*
* @param activity : Activity
*/
fun ignoreAutoTrackActivity(activity: Class) {
SensorsDataPrivate.ignoreAutoTrackActivity(activity)
}
/**
*
* @param activity
*/
fun removeIgnoredActivity(activity: Class) {
SensorsDataPrivate.removeIgnoredActivity(activity)
}
}
SensorsDataPrivate
class SensorsDataPrivate {
companion object {
private val mDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.CHINA)
private val mIgnoredActivities = ArrayList()
/**
*
* @param activity
*/
fun trackAppViewScreen(activity: Activity) {
try {
if (mIgnoredActivities.contains(activity.javaClass.canonicalName)) {
return
}
val properties = JSONObject()
properties.put("activity", activity.javaClass.canonicalName)
SensorsDataAPI.instance?.track("AppViewScreen", properties)
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* androidID
* @param context
* @return String
*/
@SuppressLint("HardwareIds")
fun getAndroidID(context: Context): String {
var androidID = ""
try {
androidID = Settings.Secure.getString(
context.contentResolver,
Settings.Secure.ANDROID_ID
)
} catch (e: Exception) {
e.printStackTrace()
}
return androidID
}
/**
*
* @param context
* @return Map
*/
fun getDeviceInfo(context: Context): Map {
val deviceInfo = HashMap()
deviceInfo["lib"] = "Android"
deviceInfo["lib_version"] = SensorsDataAPI.SDK_VERSION
deviceInfo["os"] = "Android"
deviceInfo["os_version"] = Build.VERSION.RELEASE ?: "UNKNOWN"
deviceInfo["manufacturer"] = Build.MANUFACTURER ?: "UNKNOWN"
deviceInfo["model"] = if (TextUtils.isEmpty(Build.MODEL)) "UNKNOWN" else Build.MODEL.trim()
try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
deviceInfo["app_version"] = packageInfo.versionName
deviceInfo["app_name"] = context.resources.getString(packageInfo.applicationInfo.labelRes)
} catch (e: Exception) {
e.printStackTrace()
}
val displayMetrics = context.resources.displayMetrics
deviceInfo["screen_width"] = displayMetrics.widthPixels
deviceInfo["screen_height"] = displayMetrics.heightPixels
// map
return Collections.unmodifiableMap(deviceInfo)
}
/**
* Application.registerActivityLifecycleCallbacks
* @param application
*/
fun registerActivityLifecycleCallbacks(application: Application) {
application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity?) { }
override fun onActivityResumed(activity: Activity?) {
if (activity != null) {
trackAppViewScreen(activity)
}
}
override fun onActivityStarted(activity: Activity?) { }
override fun onActivityDestroyed(activity: Activity?) {}
override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) { }
override fun onActivityStopped(activity: Activity?) { }
override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { }
})
}
/**
*
* @param source
* @param dest :
*/
fun mergeJSONObject(source: JSONObject, dest: JSONObject) {
val propertiesIterator = source.keys()
while (propertiesIterator.hasNext()) {
val key = propertiesIterator.next()
val value = source.get(key)
if (value is Date) {
synchronized(mDateFormat) {
dest.put(key, mDateFormat.format(value))
}
} else {
dest.put(key, value)
}
}
}
/**
* Activity
* @param activity
*/
fun ignoreAutoTrackActivity(activity: Class) {
mIgnoredActivities.add(activity.canonicalName)
}
/**
* Activity
* @param activity
*/
fun removeIgnoredActivity(activity: Class) {
if (mIgnoredActivities.contains(activity.canonicalName)) {
mIgnoredActivities.remove(activity.canonicalName)
}
}
}
}
2. Application에서 매점 도구 클래스를 초기화합니다.
SensorsDataAPI.init(this)
참고:
AndroidManifest.xml
에 Application을 지정하는 것을 잊지 마십시오.위의 코드 설정을 통해 우리는 페이지를 시작할 때 자동으로 설정된 데이터를 수집합니다. 여기는 단지 로그 형식으로 수집한 데이터를 출력할 뿐입니다.
Log.e(TAG, jsonObject.toString())
{
"event": "AppViewScreen",
"device_id": "9e3077550b446ff0",
"properties": {
"app_name": "My Application",
"screen_width": 1080,
"screen_height": 1794,
"lib": "Android",
"os": "Android",
"app_version": "1.0",
"os_version": "9",
"model": "Android SDK built for x86",
"lib_version": "1.0.0",
"manufacturer": "Google",
"activity": "com.example.myapplication.MainActivity"
},
"time": 1563692439349
}
SensorsDataAPI에는
ignoreAutoTrackActivity
와 removeIgnoredActivity
가 위의 예에서 사용되지 않은 두 가지 방법이 있다.이 두 가지 방법을 통해 사건의 채집을 무시하고 복구할 수 있다.예: Android6.0+ 일부 권한은 동적 신청이 필요합니다. 사용자가 허용하든 금지하든 시스템은 현재Activity
onResume()
방법을 다시 리셋합니다.이렇게 하면 다시 페이지 조회 이벤트를 촉발할 수 있기 때문에 권한을 신청해야 하는 페이지에서는 현재의Activity를 무시하고 권한 신청이 끝난 후에 채집을 복원해야 한다.override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
SensorsDataAPI.instance?.ignoreAutoTrackActivity(MainActivity::class.java)
when (requestCode) {
//
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onStop() {
super.onStop()
SensorsDataAPI.instance?.removeIgnoredActivity(MainActivity::class.java)
}
페이지 조회 이벤트는 다른 이벤트의 매립점에 비해 비교적 쉽다. 주로 Application
ActivityLifecycleCallbacks
을 통해Activity의 생명주기 관련 방법의 리셋을 감시하여 매립점의 논리를 실현한다.Kotlin 실전
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.