




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】android如何獲取設(shè)備唯一標(biāo)識(shí)
這篇文章主要介紹了android如何獲取設(shè)備唯一標(biāo)識(shí),具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓在下帶著大家一起了解一下。具體如下:/**
*
deviceID的組成為:渠道標(biāo)志+識(shí)別符來源標(biāo)志+hash后的終端識(shí)別符
*
*
渠道標(biāo)志為:
*
1,andriod(a)
*
*
識(shí)別符來源標(biāo)志:
*
1,
wifi
mac地址(wifi);
*
2,
IMEI(imei);
*
3,
序列號(hào)(sn);
*
4,
id:隨機(jī)碼。若前面的都取不到時(shí),則隨機(jī)生成一個(gè)隨機(jī)碼,需要緩存。
*
*
@param
context
*
@return
*/
public
static
String
getDeviceId(Context
context)
{
StringBuilder
deviceId
=
new
StringBuilder();
//
渠道標(biāo)志
deviceId.append("a");
try
{
//wifi
mac地址
WifiManager
wifi
=
(WifiManager)
context.getSystemService(Context.WIFI_SERVICE);
WifiInfo
info
=
wifi.getConnectionInfo();
String
wifiMac
=
info.getMacAddress();
if(!isEmpty(wifiMac)){
deviceId.append("wifi");
deviceId.append(wifiMac);
PALog.e("getDeviceId
:
",
deviceId.toString());
return
deviceId.toString();
}
//IMEI(imei)
TelephonyManager
tm
=
(TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
String
imei
=
tm.getDeviceId();
if(!isEmpty(imei)){
deviceId.append("imei");
deviceId.append(imei);
PALog.e("getDeviceId
:
",
deviceId.toString());
return
deviceId.toString();
}
//序列號(hào)(sn)
String
sn
=
tm.getSimSerialNumber();
if(!isEmpty(sn)){
deviceId.append("sn");
deviceId.append(sn);
PALog.e("getDeviceId
:
",
deviceId.toString());
return
deviceId.toString();
}
//如果上面都沒有,
則生成一個(gè)id:隨機(jī)碼
String
uuid
=
getUUID(context);
if(!isEmpty(uuid)){
deviceId.append("id");
deviceId.append(uuid);
PALog.e("getDeviceId
:
",
deviceId.toString());
return
deviceId.toString();
}
}
catch
(Exception
e)
{
e.printStackTrace();
deviceId.append("id").append(getUUID(context));
}
PALog.e("getDeviceId
:
",
deviceId.toString());
return
deviceId.toString();
}
/**
*
得到全局唯一UUID
*/
public
static
String
getUUID(Context
context){
SharedPreferences
mShare
=
getSysShare(context,
"sysCacheMap");
if(mShare
!=
null){
uuid
=
mShare.getString("uuid",
"");
}
if(isEmpty(uuid)){
uuid
=
UUID.randomUUID().toString();
saveSysMap(context,
"sysCacheMap",
"uuid",
uuid);
}
PALog.e(tag,
"getUUID
:
"
+
uuid);
return
uuid;
}有時(shí)需要對(duì)用戶設(shè)備進(jìn)行標(biāo)識(shí),所以希望能夠得到一個(gè)穩(wěn)定可靠并且唯一的識(shí)別碼。雖然Android系統(tǒng)中提供了這樣設(shè)備識(shí)別碼,但是由于android系統(tǒng)版本、廠商定制系統(tǒng)中的Bug等限制,穩(wěn)定性和唯一性并不理想。而通過其他硬件信息標(biāo)識(shí)也因?yàn)橄到y(tǒng)版本、手機(jī)硬件等限制存在不同程度的問題。下面收集了一些“有能力”或“有一定能力”作為設(shè)備標(biāo)識(shí)的串碼。DEVICE_ID這是Android系統(tǒng)為開發(fā)者提供的用于標(biāo)識(shí)手機(jī)設(shè)備的串號(hào),也是各種方法中普適性較高的,可以說幾乎所有的設(shè)備都可以返回這個(gè)串號(hào),并且唯一性良好。這個(gè)DEVICE_ID可以同通過下面的方法獲?。篢elephonyManager
tm
=
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String
DEVICE_ID
=
tm.getDeviceId();假設(shè)我們確實(shí)需要用到真實(shí)設(shè)備的標(biāo)識(shí),可能就需要用到DEVICE_ID。在以前,我們的Android設(shè)備是手機(jī),這個(gè)DEVICE_ID可以同通過TelephonyManager.getDeviceId()獲取,它根據(jù)不同的手機(jī)設(shè)備返回IMEI,MEID或者ESN碼,但它在使用的過程中會(huì)遇到很多問題:非手機(jī)設(shè)備:如果只帶有Wifi的設(shè)備或者音樂播放器沒有通話的硬件功能的話就沒有這個(gè)DEVICE_ID權(quán)限:獲取DEVICE_ID需要READ_PHONE_STATE權(quán)限,但如果我們只為了獲取它,沒有用到其他的通話功能,那這個(gè)權(quán)限有點(diǎn)大才小用bug:在少數(shù)的一些手機(jī)設(shè)備上,該實(shí)現(xiàn)有漏洞,會(huì)返回垃圾,如:zeros或者asterisks的產(chǎn)品MACADDRESS可以使用手機(jī)Wifi或藍(lán)牙的MAC地址作為設(shè)備標(biāo)識(shí),但是并不推薦這么做,原因有以下兩點(diǎn):硬件限制:并不是所有的設(shè)備都有Wifi和藍(lán)牙硬件,硬件不存在自然也就得不到這一信息。獲取的限制:如果Wifi沒有打開過,是無法獲取其Mac地址的;而藍(lán)牙是只有在打開的時(shí)候才能獲取到其Mac地址。獲取WifiMac地址:獲取藍(lán)牙Mac地址:SimSerialNumber裝有SIM卡的Android2.3設(shè)備,可以通過下面的方法獲取到SimSerialNumber:TelephonyManager
tm
=
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String
SimSerialNumber
=
tm.getSimSerialNumber();注意:對(duì)于CDMA設(shè)備,返回的是一個(gè)空值!ANDROID_ID在設(shè)備首次啟動(dòng)時(shí),系統(tǒng)會(huì)隨機(jī)生成一個(gè)64位的數(shù)字,并把這個(gè)數(shù)字以16進(jìn)制字符串的形式保存下來,這個(gè)16進(jìn)制的字符串就是ANDROID_ID,當(dāng)設(shè)備被wipe后該值會(huì)被重置??梢酝ㄟ^下面的方法獲?。篿mport
vider.Settings;
String
ANDROID_ID
=
Settings.System.getString(getContentResolver(),
Settings.System.ANDROID_ID);ANDROID_ID可以作為設(shè)備標(biāo)識(shí),但需要注意:廠商定制系統(tǒng)的Bug:不同的設(shè)備可能會(huì)產(chǎn)生相同的ANDROID_ID:9774d56d682e549c。廠商定制系統(tǒng)的Bug:有些設(shè)備返回的值為null。設(shè)備差異:對(duì)于CDMA設(shè)備,ANDROID_ID和TelephonyManager.getDeviceId()返回相同的值。它在Android<=2.1orAndroid>=2.3的版本是可靠、穩(wěn)定的,但在2.2的版本并不是100%可靠的SerialNumberAndroid系統(tǒng)2.3版本以上可以通過下面的方法得到SerialNumber,且非手機(jī)設(shè)備也可以通過該接口獲取。String
SerialNumber
=
android.os.Build.SERIAL;以上幾種方式都或多或少存在一定的局限性或者Bug,如果并不是確實(shí)需要對(duì)硬件本身進(jìn)行綁定,使用自己生成的UUID也是一個(gè)不錯(cuò)的選擇,因?yàn)樵摲椒o需訪問設(shè)備的資源,也跟設(shè)備類型無關(guān)。InstalltionID這種方式的原理是在程序安裝后第一次運(yùn)行時(shí)生成一個(gè)ID,該方式和設(shè)備唯一標(biāo)識(shí)不一樣,不同的應(yīng)用程序會(huì)產(chǎn)生不同的ID,同一個(gè)程序重新安裝也會(huì)不同。所以這不是設(shè)備的唯一ID,但是可以保證每個(gè)用戶的ID是不同的??梢哉f是用來標(biāo)識(shí)每一份應(yīng)用程序的唯一ID(即InstalltionID),可以用來跟蹤應(yīng)用的安裝數(shù)量等。GoogleDeveloperBlog提供了這樣的一個(gè)框架:public
class
Installation
{
private
static
String
sID
=
null;
private
static
final
String
INSTALLATION
=
"INSTALLATION";
public
synchronized
static
String
id(Context
context)
{
if
(sID
==
null)
{
File
installation
=
new
File(context.getFilesDir(),
INSTALLATION);
try
{
if
(!installation.exists())
writeInstallationFile(installation);
sID
=
readInstallationFile(installation);
}
catch
(Exception
e)
{
throw
new
RuntimeException(e);
}
}
return
sID;
}
private
static
String
readInstallationFile(File
installation)
throws
IOException
{
RandomAccessFile
f
=
new
RandomAccessFile(installation,
"r");
byte[]
bytes
=
new
byte[(int)
f.length()];
f.readFully(bytes);
f.close();
return
new
String(bytes);
}
private
static
void
writeInstallationFile(File
installation)
throws
IOException
{
FileOutputStream
out
=
new
FileOutputStream(installation);
String
id
=
UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
}設(shè)備唯一ID上文可以看出,Android系統(tǒng)中并沒有可以可靠獲取所有廠商設(shè)備唯一ID的方法,各個(gè)方法都有自己的使用范圍和局限性,這也是目前流行的Android系統(tǒng)版本過多,設(shè)備也是來自不同廠商,且沒有統(tǒng)一標(biāo)準(zhǔn)等原因造成的。從目前發(fā)展來看,Android系統(tǒng)多版本共存還會(huì)持續(xù)較長的時(shí)間,而Android系統(tǒng)也不會(huì)被某個(gè)設(shè)備生產(chǎn)廠商壟斷,長遠(yuǎn)看Android基礎(chǔ)系統(tǒng)將會(huì)趨于穩(wěn)定,設(shè)備標(biāo)識(shí)也將會(huì)作為系統(tǒng)基礎(chǔ)部分而標(biāo)準(zhǔn)化,屆時(shí)這一問題才有望徹底解決。目前的解決辦法,比較可行的是一一適配,在保證大多數(shù)設(shè)備方便的前提下,如果獲取不到,使用其他備選信息作為標(biāo)識(shí),即自己再封裝一個(gè)設(shè)備ID出來,通過內(nèi)部算法保證盡量和設(shè)備硬件信息相關(guān),以及標(biāo)識(shí)的唯一性??偨Y(jié)綜合以上所述,為了實(shí)現(xiàn)在設(shè)備上更通用的獲取設(shè)備唯一標(biāo)識(shí),我們可以實(shí)現(xiàn)這樣的一個(gè)類,為每個(gè)設(shè)備產(chǎn)生唯一的UUID,以ANDROID_ID為基礎(chǔ),在獲取失敗時(shí)以TelephonyManager.getDeviceId()為備選方法,如果再失敗,使用UUID的生成策略。重申下,以下方法是生成DeviceID,在大多數(shù)情況下InstalltionID能夠滿足我們的需求,但是如果確實(shí)需要用到DeviceID,那可以通過以下方式實(shí)現(xiàn):import
android.content.Context;
import
android.content.SharedPreferences;
import
vider.Settings.Secure;
import
android.telephony.TelephonyManager;
import
java.io.UnsupportedEncodingException;
import
java.util.UUID;
public
class
DeviceUuidFactory
{
protected
static
final
String
PREFS_FILE
=
"device_id.xml";
protected
static
final
String
PREFS_DEVICE_ID
=
"device_id";
protected
static
UUID
uuid;
public
DeviceUuidFactory(Context
context)
{
if(
uuid
==null
)
{
synchronized
(DeviceUuidFactory.class)
{
if(
uuid
==
null)
{
final
SharedPreferences
prefs
=
context.getSharedPreferences(
PREFS_FILE,
0);
final
String
id
=
prefs.getString(PREFS_DEVICE_ID,
null
);
if
(id
!=
null)
{
//
Use
the
ids
previously
computed
and
stored
in
the
prefs
file
uuid
=
UUID.fromString(id);
}
else
{
final
String
androidId
=
Secure.getString(context.getContentResolver(),
Secure.ANDROID_ID);
//
Use
the
Android
ID
unless
it's
broken,
in
which
case
fallback
on
deviceId,
//
unless
it's
not
available,
then
fallback
on
a
random
number
which
we
store
//
to
a
prefs
file
try
{
if
(!"9774d56d682e549c".equals(androidId))
{
uuid
=
UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
}
else
{
final
String
deviceId
=
((TelephonyManager)
context.getSystemService(
Context.TELEPHONY_SERVICE
)).getDeviceId();
uuid
=
deviceId!=null
?
UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"))
:
UUID.randomUUID();
}
}
catch
(UnsupportedEncodingException
e)
{
throw
new
RuntimeException(e);
}
//
Write
the
value
out
to
the
prefs
file
prefs.edit().putString(PREFS_DEVICE_ID,
uuid.toString()
).commit();
}
}
}
}
}
/**
*
Returns
a
unique
UUID
for
the
current
android
device.
As
with
all
UUIDs,
this
unique
ID
is
"very
highly
likely"
*
to
be
unique
across
all
Android
devices.
Much
more
so
than
ANDROID_ID
is.
*
*
The
UUID
is
generated
by
using
ANDROID_ID
as
the
base
key
if
appropriate,
falling
back
on
*
TelephonyManager.getDeviceID()
if
ANDROID_ID
is
known
to
be
incorrect,
and
finally
falling
back
*
on
a
random
UUID
that's
persisted
to
SharedPreferences
if
getDeviceID()
does
not
return
a
*
usable
value.
*
*
In
some
rare
circumstances,
this
ID
may
change.
In
particular,
if
the
device
is
factory
reset
a
new
device
ID
*
may
be
generated.
In
addition,
if
a
user
upgrades
their
phone
from
certain
buggy
implementations
of
Android
2.2
*
to
a
newer,
non-buggy
version
of
Android,
the
device
ID
may
change.
Or,
if
a
user
uninstalls
your
app
on
*
a
device
that
has
neither
a
proper
Android
ID
nor
a
Device
ID,
this
ID
may
change
on
reinstallation.
*
*
Note
that
if
the
code
falls
back
on
using
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 教育機(jī)構(gòu)代理記賬人員保密與職業(yè)操守合同
- 餐飲簽單掛賬配送合同范本
- 生態(tài)農(nóng)業(yè)園區(qū)場地租賃合同終止與農(nóng)產(chǎn)品合作協(xié)議
- 優(yōu)酷視頻職業(yè)中藥師課件
- 民宿承租合同協(xié)議書范本
- 消防處罰課件視頻
- 小學(xué)生學(xué)習(xí)關(guān)聯(lián)詞語課件
- 道閘轉(zhuǎn)讓合同協(xié)議書
- 2025屆四川省成都市實(shí)驗(yàn)中學(xué)英語八年級(jí)第二學(xué)期期中聯(lián)考模擬試題含答案
- 消防基礎(chǔ)常識(shí)課件
- 移動(dòng)基站物業(yè)協(xié)調(diào)方案
- 巖土錨桿技術(shù)規(guī)程課件
- 技術(shù)服務(wù)合同(中國科技部范本)
- VDA6.3過程審核檢查表(中英文版)
- 城市軌道交通客運(yùn)組織電子教案(全)完整版課件整套教學(xué)課件
- GB∕T 33917-2017 精油 手性毛細(xì)管柱氣相色譜分析 通用法
- 高壓氧治療操作規(guī)程以及護(hù)理常規(guī)
- 高中人教物理選擇性必修二專題05 單雙桿模型-學(xué)生版
- 二手車評(píng)估作業(yè)表簡單實(shí)際樣本
- 人民幣小學(xué)學(xué)具圖
- 新能源汽車的研究論文
評(píng)論
0/150
提交評(píng)論