前言
? 通過應用程式退出事件,可以分析應用程式的平均使用時長;通過應用程式的啟動事件,可以分析榷訓和新增,我們可以通過全埋點方式 SDK 實作應用程式的退出和啟動事件,
一、全埋點的簡介
? 目前、全埋點采集可以采集一下4個事件,
1、$AppEnd 事件:應用程式退出事件

2、$AppStart 事件:應用程式啟動事件

3、$AppViewScreen 事件: 應用程式內界面預覽事件,對于 iOS 來說就是切換不同的 UIViewController,
4、$AppClick 事件: 控制元件的點擊事件,比如點擊 UIButton 、UITableView 等,
預置事件:在 SDK 中自動采集的事件稱為預置事件,
二、應用程式退出
2.1 應用程式狀態:
? 一個標準的 iOS 程式在不同的時期會有不同的運行狀態,在 iOS 程式中常見的狀態有5中,如圖所示:

1、Not running:非運行狀態,指應用程式還沒有被啟動,或者已經被系統終止,
2、Inactive: 前臺非活躍狀態,指應用程式即將進入前臺狀態,
3、Active: 前臺活躍狀態,指應用程式正在前臺運行,可接受事件并進行處理,
4、Background: 進入后臺狀態,指應用程式進入后臺并可執行代碼,
5、Suspended: 掛起狀態,指應用程式進入后臺并沒有執行代碼,系統會自動將應用程式轉移到該狀態,掛起時,應用程式會保留在記憶體中,但不執行任何代碼,當系統出現記憶體不足情況時,系統會清除被掛起的應用程式,
? 在應用程式的狀態轉換程序中,系統會呼叫實作 UIApplicationDelegate 協議類的一些方法,并發送相應的本地通知(先呼叫方法,待回呼方法執行后,再發相應的通知),回呼方法和本地通知的對應關系如下表
| 回呼方法 | 本地通知 |
|---|---|
| - application:didFinishI aunchingWithOptions: | UIApplicationDidFinishLaunchingNotification |
| - applicationDidBecomeActive: | UIApplicationDidBecomeActiveNotification |
| - applicationWillResignActive: | UIApplicationWillResignActiveNotification |
| - applicationDidEnterBack ground:· | UIApplicationDidEnterBackgroundNotification |
| - applicationWillEnterForeground: | UIApplicationWillEnterForegroundNotificatio |
| - applicationWillTerminate: | UIApplicationWillTerminateNotification |
2.2 實作步驟
? 通過上面介紹的內容可知,當一個 iOS 應用程式退出時,就意味著該應用程式進入了“后臺”,即處于 Background 狀態,因此,對于實作 $AppEnd 事件的全埋點,我們只需要注冊監聽 UIApplicationDidEnterBackgroundNotification 通知,然后在收到通知時觸發 $AppEnd 事件,即可達到 $AppEnd 事件全埋點的效果,
第一步:注冊監聽 UIApplicationDidEnterBackgroundNotification 本地通知,
在 SensorsAnalyticsSDK.m 檔案中實作 - setupListeners 方法,用來監聽 UIApplicationDidEnterBackgroundNotification 本地通知,然后再相應的回呼方法中觸發 $AppEnd 事件,
- (void)setupListeners {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// 注冊監聽 UIApplicationDidEnterBackgroundNotification 本地通知
// 當應用程式進入后臺,呼叫通知方法
[center addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification {
NSLog(@"Application did enter background.");
// 觸發 AppEnd 事件
[self track:@"$AppEnd" properties:nil];
}
第二步:在 SensorsAnalyticsSDK.m 檔案中初始化 - init 方法中呼叫 - setupListeners,并在 - dealloc 方法中移除監聽,
- (instancetype)init {
self = [super init];
if (self) {
_automaticProperties = [self collectAutomaticProperties];
// 添加應用程式狀態監聽
[self setupListeners];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
第三步:測驗驗證
我們可以在 Xcode 中列印控制臺中查看如下的列印資訊,
{
"event" : "$AppEnd",
"time" : 1648520301691,
"propeerties" : {
"$model" : "x86_64",
"$manufacturer" : "Apple",
"$lib_version" : "1.0.0",
"$os" : "iOS",
"$app_version" : "1.0",
"$os_version" : "15.2",
"$lib" : "iOS"
}
}
三、應用程式啟動
應用程式的啟動,一般情況下,大致可以分為兩類場景:
? 冷啟動
? 熱啟動(從后臺恢復)
? 不管是冷啟動還是熱啟動,觸發 $AppStart 事件的時機,都可以理解成是當“應用程式開始進入前臺并處于活動狀態”,也即前文介紹的 Active 狀態,因此,為了實作 $AppStart 事件的全埋點,我們可以注冊監聽 UIApplicationDidBecomeActiveNotification 本地通知,然后在其相應的回呼方法里觸發 $AppStart 事件,
3.1 實作步驟
第一步:在 SensorsAnalyticsSDK.m 檔案 - setupListeners 方法中,添加 UIApplicationDidBecomeActiveNotification 本地通知,然后再相應的回呼方法中觸發 $AppStart 事件,
- (void)setupListeners {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// 注冊監聽 UIApplicationDidBecomeActiveNotification 本地通知
// 當應用程式進入前臺臺,呼叫通知方法
[center addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification {
NSLog(@"Application did enter active.");
// 觸發 AppEnd 事件
[self track:@"$AppStart" properties:nil];
}
第二步: 測驗驗證
? 可以在 Xcode 列印控制臺中查看下面的列印資訊,
{
"event" : "$AppStart",
"time" : 1648520708355,
"propeerties" : {
"$model" : "x86_64",
"$manufacturer" : "Apple",
"$lib_version" : "1.0.0",
"$os" : "iOS",
"$app_version" : "1.0",
"$os_version" : "15.2",
"$lib" : "iOS"
}
}
3.2 優化
問題:
通過測驗可以發現,仍有以下幾個特殊場景存在問題:
? 下拉通知欄并上滑,會觸發 $AppStart 事件
? 上滑控制中心并下拉,會觸發 $AppStart 事件
? 雙擊 Home 鍵進入切換應用程式頁面,最后又選擇當前應用程式,會觸發 $AppStart 事件
以上幾個場景均會觸發 $AppStart 事件,明顯與實際情況有所不符,
那這些現象是什么原因導致的呢?
我們繼續分析可以發現以下幾個現象:
? 下拉通知欄時,系統會發送 UIApplicationWillResignActiveNotification 通知;上滑通知欄時,系統會發送 UIApplicationDidBecomeActiveNotification 通知
? 上滑控制中心時,系統會發送 UIApplicationWillResignActiveNotification 通知;下拉控制中心時,系統會發送 UIApplicationDidBecomeActiveNotification 通知
? 雙擊 Home 鍵進入切換應用程式頁面時,系統會發送 UIApplicationWillResignActiveNotification 通知,然后選擇當前應用程式,系統會再發送 UIApplicationDidBecomeActiveNotification 通知
很容易總結出規律:在以上幾個場景下,系統均是先發送UIApplicationWillResignActiveNotification 通知,然后再發送 UIApplicationDidBecomeActiveNotification 通知,而我們又是通過注冊監聽 UIApplicationDidBecomeActiveNotification 通知來實作 $AppStart 事件全埋點,因此均會觸發 $AppStart 事件,
那如何解決這個問題呢?
在解決這個問題之前,我們先看另一個現象:不管是冷啟動還是熱啟動,系統均沒有發送 UIApplicationWillResignActiveNotification 通知,
因此,只要在收到 UIApplicationDidBecomeActiveNotification 通知時,判斷之前是否收到過 UIApplicationWillResignActiveNotification 通知,若沒有收到,則觸發 $AppStart 事件;若已收到,則不觸發 $AppStart 事件,這樣即可解決上面的問題,
優化方案:
第一步:在 SensorsAnalyticsSDK.m 檔案中添加 applicationWillResignActive 標記位,
/// 標記應用程式是否收到 UIApplicationWillResignActiveNotification 本地通知
@property (nonatomic, assign) BOOL applicationWillResignActive;
第二步:在 - setupListeners 方法中新增注冊監聽 UIApplicationWillResignActiveNotification 的本地通知,
- (void)setupListeners {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// 注冊監聽 UIApplicationDidEnterBackgroundNotification 本地通知
// 當應用程式進入后臺,呼叫通知方法
[center addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
// 注冊監聽 UIApplicationDidBecomeActiveNotification 本地通知
// 當應用程式進入前臺臺,呼叫通知方法
[center addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
// 注冊監聽 UIApplicationWillResignActiveNotification 本地通知
// 當應用程式進入前臺臺,呼叫通知方法
[center addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:nil];
}
- (void)applicationWillResignActive:(NSNotification *)notification {
// 設定標記位
self.applicationWillResignActive = YES;
}
第三步:在UIApplicationDidBecomeActiveNotification 的回呼方法中還原 applicationWillResignActive 的標記位
- (void)applicationDidBecomeActive:(NSNotification *)notification {
NSLog(@"Application did enter active.");
// 還原標記位
if (self.applicationWillResignActive) {
self.applicationWillResignActive = NO;
return;
}
// 觸發 AppStart 事件
[self track:@"$AppStart" properties:nil];
}
第四步:在 UIApplicationDidEnterBackgroundNotification 回呼方法中還原 applicationWillResignActive 的標記位
- (void)applicationDidEnterBackground:(NSNotification *)notification {
NSLog(@"Application did enter background.");
// 還原標記位
self.applicationWillResignActive = NO;
// 觸發 AppEnd 事件
[self track:@"$AppEnd" properties:nil];
}
第五步:測驗驗證
{
"event" : "$AppStart",
"time" : 1648533646735,
"propeerties" : {
"$model" : "x86_64",
"$manufacturer" : "Apple",
"$lib_version" : "1.0.0",
"$os" : "iOS",
"$app_version" : "1.0",
"$os_version" : "15.2",
"$lib" : "iOS"
}
}
四、應用程式被動啟動
? 被動啟動:我們把由 iOS 系統觸發的應用程式自動進入后臺運行的啟動稱之為(應用程式的)被動啟動,使用 $AppStartPassively 事件來表示,
4.1、Background modes
? 使用 Xcode 創建新的應用程式,默認情況下后臺重繪功能是關閉的,我們可以在 Capabilities 標簽中開啟 Background Modes,然后就可以勾選所需要的功能了,如下圖所示:

通過上圖可知,有如下幾種后臺運行模式,它們都會觸發被動啟動($AppStartPassively 事件),
1、Audio,AirPlay,and Picture in Picture : 音頻的播放,錄音,AirPlay及畫中畫的視頻播放
2、Location updates:此模式下,會由于地理位置變化而觸發應用程式啟動
3、Voice over IP : IP網路電話,通過對語音信號進行編碼數字化,然后轉換成IP資料包在TCP/IP網路上進行傳輸,從而達到在網路上進行語音通信的目的
4、External Accessory communication:此模式下,一些 MFi 外設通過藍牙或者 Lightning 接頭等方式與 iOS 設備連接,從而可在外設給應用程式發送訊息時,觸發對應的應用程式啟動
5、Uses Bluetooth LE accessories:此模式與 External Accessory communication 類似,只是無需限制 MFi 外設,而需要的是 Bluetooth LE 設備
6、Acts as a Bluetooth LE accessory:此模式下,iPhone 作為一個藍牙外設連接,可以觸發應用程式啟動
7、Background fetch:此模式下,iOS 系統會在一定的時間間隔內觸發應用程式啟動,去獲取應用程式資料
8、Remote notifications:此模式是支持靜默推送,當應用程式收到這種推送后,不會有任何界面提示,但會觸發應用程式啟動
9、Background processing: 后端處理
4.2 實作步驟
? 后臺用程式重繪拉起應用程式后,首先會回呼 AppDelegate 中的 -application:didFinishLaunchingWithOptions: 方法,因此,我們可以通過注冊監聽 UIApplicationgDidFinishLaunchingNotification 本地通知來采集被動啟動事件資訊,
第一步:在 - setupListeners 方法中添加 UIApplicationgDidFinishLaunchingNotification 本地通知,在回呼方法中上報資料,
- (void)setupListeners {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
// 注冊監聽 UIApplicationDidFinishLaunchingNotification 本地通知
// 當應用程式被動,呼叫通知方法
[center addObserver:self
selector:@selector(applicationDidFinishLaunching:)
name:UIApplicationDidFinishLaunchingNotification
object:nil];
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
// 觸發 AppStartPassively 事件
[self track:@"$AppStartPassively" properties:nil];
}
第二步:新增一個私有屬性 launchedPassively,標記應用程式是否處于被動啟動
/// 標記應用程式是否是被動啟動
@property (nonatomic, assign, getter=isLaunchedPassively) BOOL launchedPassively;
第三步:在 - init 初始化方法中,通過 backgroundTimeRemaining 屬性是否等于 UIApplicationBackgroundFetchIntervalNever 來設定
- (instancetype)init {
self = [super init];
if (self) {
_automaticProperties = [self collectAutomaticProperties];
// 設定是否需是被動啟動標記
_launchedPassively = UIApplication.sharedApplication.backgroundTimeRemaining != UIApplicationBackgroundFetchIntervalNever;
// 添加應用程式狀態監聽
[self setupListeners];
}
return self;
}
第四步:在 - applicationDidFinishLaunching 回呼方法中,如果 isLaunchedPassively 為 YES,再觸發 $AppStartPassively 事件
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
NSLog(@"Application did finish launching.");
// 當應用程式后臺運行時,觸發被動啟動事件
if (self.isLaunchedPassively) {
// 觸發 AppStartPassively 事件
[self track:@"$AppStartPassively" properties:nil];
}
}
第五步:測驗驗證
1、開啟 Background modes 中的 Background fetch 復選框
2、選擇 Demo Scheme , 一次單擊 Xcode 選單欄中的 Product -> Scheme -> Edit -> Scheme -> Run -> Options
3、勾選 Background Fetch 選項,然后點擊 Close 按鈕,運行 Demo
{
"event" : "$AppStartPassively",
"time" : 1648537321216,
"propeerties" : {
"$model" : "x86_64",
"$manufacturer" : "Apple",
"$lib_version" : "1.0.0",
"$os" : "iOS",
"$app_version" : "1.0",
"$os_version" : "15.2",
"$lib" : "iOS"
}
?
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/452076.html
標籤:其他
