您好,登錄后才能下訂單哦!
最近有網友發現友盟的數據統計里面,活躍用戶的數量有點不大對勁,跟啟動次數相比,嚴重偏少。sdk的使用方式沒啥好說的,就那么簡單幾步,應該不會是sdk設置的問題。于是就從友盟關于活躍用戶的定義開始,著手分析這個問題。
活躍用戶的定義:打開應用的用戶即為活躍用戶,不考慮用戶的使用情況。
從上面的文章,了解到Umeng里面對用戶的定義:友盟將一個獨立的設備視為一個用戶,然而每個獨立的用戶是通過UMID來進行唯一標識的。然而UMID又是神馬鬼東西?簡單來說就是友盟會在第一次安裝的時候生成一個UMID,當ID生成以后友盟會盡量保證這個UMID不會發生變化。
在應用對應的存儲目錄下面,我們可以找到這個UMID的身影:
ngeIdentity.json這個文件來說,cat一下里面的內容,應該可以看到:
筆者發現公司里多臺設備的UMID都居然是一個相同的UMID值,WTF!!!也同樣是上面這串神秘的代碼:528c8e6cd4a3c6598999a0e9df15ad32。
這個時候就需要查一下UMID的生成方式了,從上面那篇UMID方案解析的文章中,可以了解到Android系統中與UMID相關的幾個ID:imei、mac地址、android_id。有了這些關鍵點,我們就可以開始去反編譯友盟的sdk包并進行下一步的搜索了(這里反編譯了友盟最新的jar包:umeng-analytics-v6.0.1.jar)。。。果然,使用上面這幾個關鍵字,很快就搜索到了一些關鍵的代碼:
段代碼邏輯比較簡單(由于筆者所調試系統<23,故省略了一部分代碼),首先TelephonyManager.getDeviceId()獲取imei,若取不到則調用u(context)函數獲取下一個字符串,若再取不到,則獲取android_id。其實這里可以猜測到,u()中返回的字符串應該就是mac地址,我們來看下函數u()的邏輯代碼:
果然,函數u(context)就是返回wifi的mac地址的。那么,回到剛剛的那個問題,到底那串神秘的UMID是528c8e6cd4a3c6598999a0e9df15ad32根據啥來生成的?看著這格式有點像md5。然后把機器上的imei、mac地址、android_id都打印了出來:
突然發現公司設備上打印出來的mac地址都是00:00:00:00:00:00(因為木有wifi模塊,只有ethernet模塊,囧!!!),怒將其轉為md5,正是上面的串代碼。
可是,為啥當mac地址是00:00:00:00:00:00的時候,不去選擇android_id呢?回去仔細看代碼,發現友盟用的是坑爹的TextUtils.isEmpty()來判斷mac地址的有效性,跪了,上面那串明明就是無效的mac地址好么?只能說代碼寫得不嚴謹。。。
至此,代碼及原因分析完畢。當一些Android平板設備統一返回相同的mac地址,如00:00:00:00:00:00時(有可能是沒有wifi模塊;也有可能是山寨機出現這種情況的時候),友盟將會將其數據識別成同一用戶,并且將會造成嚴重的MAC地址漂移。
作為比較,我們來看一下友盟的競爭對手shareinstall的渠道統計代碼!
首先,我們開看看shareinstall的web集成步驟:
<!-- 建議直接引用下面的js鏈接,以便得到最及時的更新,我們將持續跟蹤各種主流瀏覽器的變化,為您提供最好的服務-->
<script type="text/javascript" src="//www.shareinstall.com/js/page/shareinstall.min.js"></script>
<script type="text/javascript">
//錯誤處理:確保app始終能正常的安裝
var timer = setTimeout(
function() {
var button = document.getElementById("downloadButton");
button.style.visibility = "visible";
button.onclick = function() {
var ua = navigator.userAgent;
if (ua.indexOf(" MicroMessenger/") > -1) {
//微信中顯示遮罩提示在瀏覽器中打開或進入應用寶
var div = document.createElement("div");
div.innerHTML = "<div style="font-size:2rem;color:#fff;text-align:center;"
+"position:fixed;left:0;top:0;background:rgba(0,0,0,0.5);filter:alpha(opacity=50);"
+"width:100%;height:100%;z-index:10000;">點擊右上角在瀏覽器中打開</div>";
document.body.appendChild(div);
} else {
if (ua.indexOf("Android") > -1) {
//直接下載apk
//window.location="apk地址";
} else if (ua.indexOf("iPhone") > -1 || ua.indexOf("iPad") > -1
|| ua.indexOf("iPod") > -1) {
//直接進入appstore
//window.location="appstore地址";
}
}
}
}, 5000);
//shareinstall初始化,初始化時將與shareinstall服務器交互,應盡可能早的調用
/*web頁面向app傳遞的json數據(json string/js Object),應用被拉起或是首次安裝時,通過相應的
android/ios api可以獲取此數據*/
var data = ShareInstall.parseUrlParams();//shareinstall.js中提供的工具函數,解析url中的所有查詢參數
new ShareInstall({
appKey : 'F6BKAREBHF22EB',
onready : function() {
//shareinstall已成功回調,清除定時器
clearTimeout(timer);
timer = null;
var m = this, button = document.getElementById("downloadButton");
button.style.visibility = "visible";
/*用戶點擊某個按鈕時(假定按鈕id為downloadButton),安裝app*/
button.onclick = function() {
m.wakeupOrInstall();
}
}
}, data);
</script>
shareinstall提供完整的javascript api,方便Web開發者實現完全自主的設計。
再開看看shareinstall的代碼配置(測試):
如果做測試,獲取參數,則必須在Appdelegate.h加上如下測試代碼。
#pragma mark 將oc數據類型轉成NSString
-(NSString *)DataTOjsonString:(id)object
{
if (!object) {
return null;
}
NSString *jsonString = null;
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object
options:NSJSONWritingPrettyPrinted
error:&error];
if (! jsonData) {
NSLog(@"Got an error: %@", error);
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return jsonString;
}
使用Shareinstall 控制中心提供的渠道統計時,在App用戶注冊完成后調用,可以統計渠道注冊量。
警告:必須在注冊成功的時調用[ShareInstallSDK reportRegister] 方法,否則可能導致注冊統計不準。
由上比較得知,shareinstall與友盟最大的優勝點就在于首先實現完全自主。這很大一部分是因為它們一開始實現目的就有差別。例如:友盟針對一項SDK下載,需要同時下載3個包,而shareinstall則可以一鍵完成;而在集成上,友盟面對不同的項目需要不同的操作,過程過于繁瑣。而shareinstall通過 URL Scheme 和 Universal Links 實現在不同瀏覽器中拉起APP,應用集成造成的代碼冗余少,集成簡單。攜參安裝實現個性化,渠道統計更精確。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。