一文搞懂移動設備ID的那些事兒

在移動數字廣告領域,設備ID是用來追蹤用戶行為的最重要的標識。
對于開發者而言,設備ID的穩定性(尤其對于開放的安卓系統來說)以及統計分析和業務應用(變現和追蹤等)扮演了非常關鍵的角色。

作為一個膚淺的產品經理,我們這次主要介紹的設備ID包括:IMEI,MAC,IDFA,Android ID,OAID,UUID,openUDID,GAID,Serial Number等這些無論是國內和海外比較主流的移動設備的唯一標識碼或曾扮演重要角色的設備ID。
知道什么是設備ID不是最重要的,重要的是應用的場景,應用目的,以及如何應用,所以這次,我把設備ID分成國外主流和國內主流使用的場景,來分別介紹。

一、什么是設備ID?

設備ID是唯一的匿名標識符,由與單個特定移動設備或用戶相對應的數字和字母組成。

全球所有智能手機和平板電腦都有唯一的設備ID,該ID直接存儲在移動設備本身上。

設備ID可以通過任何已安裝的應用程序檢索,并用于準確衡量單個用戶采取的操作,即用于統計。

設備ID在用戶旅程和體驗的所有階段都發揮著重要作用,包括安裝歸因,應用內個性化,受眾群體細分和整體應用性能。

二、海外的主流設備ID

海外的設備ID比較統一,無論是programmatic advertising市場還是performance advertising市場,無論目的是targeting audience還是tracking user的后續行為和效果,都是這個標準的。
Android – Google廣告ID(GAID):Google Advertising ID是由Google Play服務提供的用戶可重置的唯一廣告ID。

iOS –廣告商身份(IDFA):Identifier For Advertising,iOS獨有的廣告標識符。

要么是傳了以上的兩種設備ID根據響應的設備類型,要么是不傳,也就是為空,再或者,是因為用戶選擇了don't track而展示的以0填充的設備ID(當然也有可能是假量導致的,各種各樣的fraud花樣,我們可以有時間再單獨聊)。

三、國內設備ID的應用現狀

國內的設備ID可以說五花八門,因為媒體傳的各式各樣,至今也沒有一個統一的機構對設備ID進行規范。
總體上,國內的廣告主偏向使用硬件地址或者穩定不變且不會被重置的設備ID。我們可以按照設備ID被在線廣告市場接受程度(唯一性和穩定性)去對市面上的設備ID排個優先級。
Android:

IMEI:International Mobile Equipment Identity,國際移動設備身份碼的縮寫。是由15位數字組成的“電子串號”,它與每臺手機一一對應,每個IMEI在世界上都是唯一的。

MAC地址:硬件標識符,包括WiFi mac地址和藍牙mac地址。Android 6.0之后被禁止。被禁止后開發者在APP端收集到的mac是亂碼或者02:00:00:00:00類似樣式的數據。

當然這個Mac地址可能會被不法分子通過線下收集處在打開WiFi情況下被探針的方式收集,然后匹配數據庫里的IMEI甚至手機號等個人信息,所以通過WIFI上網或WIFI AP探針SSID廣播都可以獲取到MAC地址。

Android ID是每一個新設備系統都會隨機的分配一個Andriod_ID,為64位數字。如果將設備恢復出廠設置、刷機,則會生成一個新的ID。通過Settings.Secure.ANDROID_ID獲取.

OAID: Open Anonymous Device Identifier, 由中國移動安全聯盟(MSA)最近開發,它代替了中國不受支持的Google Advertising ID,并取代了目前為止使用的IMEI / MEID,但還沒有被廣泛應用,希望可以用OAID取代現有的硬件相關的設備ID,使安卓設備的設備ID可以統一。

與GAID是對應的,所以可以重置OAID甚至完全禁用OAID,這是國內準備邁向隱私保護的第一步。

OAID支持的終端范圍:


微信截圖_20200427191413.png

對于不支持的版本,按原有邏輯走。

iOS:

IDFA:Identifier For Advertising,是Apple分配給用戶設備的隨機設備標識符。因為iOS設備封閉性比較好,無法取得其他硬件標識碼,所以這塊國內國外都比較統一。

另外,國內有很多做法是將一些獲取到的設備ID(IMEI,MAC等)做哈希,以表示我沒有獲取到用戶的隱私,所以衍生出來了IMEI MD5,IMEI SHA-1,MAC MD5,甚至是IDFA MD5,在我看來,就有點內味兒了,你自己感受一下。

其他:

除了上面主流的這些,還有下面這些設備ID,對于我這樣付錢的PM來講,遇到的比較少,不過我也羅列下,以免你碰到不認識。

UDID:原蘋果設備的唯一識別ID,它是40個字符組成。在IOS舊版本可以使用,但在IOS7.0以后版本蘋果停用了此ID,新版都無法獲取。

IDFV :是蘋果設備給單個APP自身用于追蹤用戶的唯一ID,這個IDFV在一個APP內是唯一的,跨APP就不唯一了,因此只能用于單個APP自身用于追蹤用戶行為。

UUID:Universally Unique Identifier,通用唯一識別碼。由于Andriod體系ID的復雜性,所以還有廠商會根據UUID生成標準在APP中生成UUID來使用,聽說微軟會用這個。

MEID:(Mobile Equipment Identifier) 移動設備識別碼是CDMA手機的身份識別碼,也是每臺CDMA手機或通訊平板唯一的識別碼。

Device ID:可以用系統提供的TelephonyManager服務來獲取,具有唯一性。其中又包括IMEI 和 MEID/ESN。具有通話功能Android設備才有,平板等設備沒有;

Serial Number:設備序列號,通過android.os.Build.SERIAL獲得。不穩定的唯一標識,依賴廠商的實現。

注:IMEI是聯通、移動手機的標識,MEID是電信手機的標識,但實際上,膚淺的小編并沒見過MEID,猜測可能是都傳在IMEI哈希過字段里了。

四、如何獲取設備ID

上面已經說過,設備ID主要用于統計數據和歸因,那么可能我們需要的設備ID需要具有唯一性和穩定性。

講一下國內外主流的幾個設備ID的獲取方法:

GAID:

adb shell setprop log.tag v & adb shell stop & adb shell start
2.打開get_gaid.bat文件。內容如下:
adb logcat -s tag GAID
3.打開核心即可獲取GAID```

OAID:

OAID的獲取其實在MSA的官網上根據官網的指導和郵件對方索取SDK就可以,目前最新的版本是2020年2月6日 miit_mdid_sdk_1.0.13,里面已經非常詳細了。

1)下載:

http://www.msa-alliance.cn/col.jsp?id=120

2)安裝

把 miit_mdid_x.x.x.aar 拷貝到項的 libs 目錄,并設置依賴,其中 x.x.x 代表版本號。

將 supplierconfig.json 拷貝到項目 assets 目錄下,并修改里邊對應內容,特別是需要設置 appid 的部分。需要設置 appid 的部分需要去對應廠商的應用商店里注冊自己的 app。

3)設置依賴。

```implementation files(‘libs/miit_mdid_x.x.x.aar’)```

4)混淆設置。

```-keep class com.bun.miitmdid.core.** {*;}```

5)設置 gradle 編譯選項,這塊可以根據自己對平臺的選擇進行合理配置。

```ndk {
        abiFilters 'armeabi-v7a', 'x86', 'arm64-v8a', 'x86_64', 'armeabi'
    }
    packagingOptions {
        doNotStrip "*/armeabi-v7a/*.so"
        doNotStrip "*/x86/*.so"
        doNotStrip "*/arm64-v8a/*.so"
        doNotStrip "*/x86_64/*.so"
        doNotStrip "armeabi.so"
    }```
5)初始化。

```public class APP extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        JLibrary.InitEntry(base);
    }
}```
6)設置回調
```public interface AppIdsUpdater {
        void OnValidId(@NonNull JSONObject ids);
    }```
7)設置調用類
 ```public class MiIdHelper implements IIdentifierListener {
    private boolean isSupport;
    private String oaid, vaid, aaid;

    public JSONObject getDeviceIds(Context cxt) {
        long startTime = System.currentTimeMillis();
        int code = CallFromReflect(cxt);
        long endTime = System.currentTimeMillis();
        long time = endTime - startTime;
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("description", descriptionCode(code));
            jsonObject.put("code", code);
            jsonObject.put("time", time);
            jsonObject.put("isSupport", isSupport);
            jsonObject.put("oaid", oaid);
            jsonObject.put("vaid", vaid);
            jsonObject.put("aaid", aaid);
        } catch (Exception e) {
            e.printStackTrace();
        }
         return jsonObject;
    }

    private int CallFromReflect(Context cxt) {
        return MdidSdkHelper.InitSdk(cxt, true, this);
    }


    @Override
    public void OnSupport(boolean isSupport, IdSupplier _supplier) {
        this.isSupport = isSupport;
        if (_supplier != null) {
            this.oaid = _supplier.getOAID();
            this.vaid = _supplier.getVAID();
            this.aaid = _supplier.getAAID();
            _supplier.shutDown();
        }
    }

    private String descriptionCode(int code) {
        switch (code) {
            case ErrorCode.INIT_ERROR_DEVICE_NOSUPPORT:
                return "DEVICE_NOSUPPORT";
            case ErrorCode.INIT_ERROR_LOAD_CONFIGFILE:
                return "LOAD_CONFIGFILE";
            case ErrorCode.INIT_ERROR_MANUFACTURER_NOSUPPORT:
                return "MANUFACTURER_NOSUPPORT";
            case ErrorCode.INIT_ERROR_RESULT_DELAY:
                return "RESULT_DELAY";
            case ErrorCode.INIT_HELPER_CALL_ERROR:
                return "HELPER_CALL_ERROR";
            default:
                return "SUCCESS";
        }
    }
}```

8)獲取OAID

```  MiIdHelper miIdHelper = new MiIdHelper();
    JSONObject result=miIdHelper.getDeviceIds(getApplicationContext());```
9)效果展示

```{
    "description":"SUCCESS",
    "code":0,
    "time":49,
    "isSupport":true,
    "oaid":"cf8cc008bb5adf96",
    "vaid":"f8239c19f92836f1",
    "aaid":"0115d997-c845-4e86-8fed-58c4fb246827"

}```
>來源:https://juejin.im/post/5df854745188251280061d3f

idfa:
``` #include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#import <AdSupport/AdSupport.h>

- (NSString *)zx_idfaString
{
    NSBundle *adSupportBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/AdSupport.framework"];
    [adSupportBundle load];
    
    if (adSupportBundle == nil)
    {
        return @"";
    }
    else
    {
        Class asIdentifierMClass = NSClassFromString(@"ASIdentifierManager");
        
        if(asIdentifierMClass == nil){
            return @"";
        }
        else
        {
            ASIdentifierManager *asIM = [[asIdentifierMClass alloc] init];
            
            if (asIM == nil) {
                return @"";
            }
            else{
                
                if(asIM.advertisingTrackingEnabled)
                {
                    return [asIM.advertisingIdentifier UUIDString];
                }
            }
        }
    }
}```
>來源:https://juejin.im/post/5bdbb926f265da391e58fa92


##總結:

國內設備ID統一任重而道遠;

國外用戶隱私倒是越來越嚴。

無論是前些年實施的歐盟的'GDPR',還是加州的'CCPA','COPPA',以及今年google逐步實施的三方cookie,可以說都對對應地區和用戶的用戶的隱私更加嚴格和個性化的保護,反過來對在線廣告行業卻是一個挑戰,行業需要升級,所以總會找到兩者兼顧的方面去做改進。

也希望國內的在線廣告的設備ID,包括OTT在內,逐漸走向在變現路上兼顧用戶隱私的正軌。
![image](https://upload-images.jianshu.io/upload_images/13766341-8ee60d86f2d6b265?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。