欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?常見(jiàn)獲取設(shè)備標(biāo)識(shí)方法總結(jié)

 更新時(shí)間:2024年09月25日 15:19:36   作者:ChenYhong  
隨著Android系統(tǒng)版本更新,Google對(duì)用戶隱私保護(hù)增強(qiáng),限制獲取設(shè)備標(biāo)識(shí),文中測(cè)試DeviceID、ANDROID_ID、Serial、MAC地址等方法在不同API級(jí)別的表現(xiàn),感興趣的朋友跟隨小編一起看看吧

在最近的開(kāi)發(fā)工作中,有個(gè)功能點(diǎn)需要獲取設(shè)備標(biāo)識(shí)作為用戶ID,理想的標(biāo)識(shí)應(yīng)該是不可重置的。然而,在Android系統(tǒng)版本的不斷迭代中,Google對(duì)用戶隱私的保護(hù)力度持續(xù)加強(qiáng),針對(duì)獲取設(shè)備標(biāo)識(shí)方法的限制也越來(lái)越嚴(yán)格,官方建議盡量選用用戶可重置的唯一標(biāo)識(shí),例如AAID。

為了盡量滿足需求,對(duì)以往常見(jiàn)的四種獲取設(shè)備標(biāo)識(shí)的方法進(jìn)行了測(cè)試,本文對(duì)測(cè)試結(jié)果進(jìn)行記錄。

獲取設(shè)備標(biāo)識(shí)

DeviceID(IMEI、MEID)

穩(wěn)定的標(biāo)識(shí)符,即使恢復(fù)出廠設(shè)置也不會(huì)被重置。在不同版本的Android設(shè)備上,獲取DeviceID的方法及效果略有不同,下面分別介紹一下。

API 23-28

AndroidManifest中配置READ_PHONE_STATE權(quán)限,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <application
        ......
        >
        ......
    </application>
</manifest>

在API 23(Android6.0)到API 28(Android 9.0)的設(shè)備上,可以通過(guò)TelephonyManager.getDeviceId()方法獲取DeviceID。 另外在API 26(Android8.0)或更高版本的設(shè)備上,還可以通過(guò)TelephonyManager.getImei()TelephonyManager.getMeid()獲取設(shè)備標(biāo)識(shí)。需要在運(yùn)行時(shí)向用戶申請(qǐng)授予READ_PHONE_STATE權(quán)限。示例代碼如下:

class DeviceIdExampleActivity : AppCompatActivity() {
    private lateinit var binding: LayoutDeviceIdExampleActivityBinding
    private val deviceIdPermissionRequestLauncher = registerForActivityResult(/* contract = */ ActivityResultContracts.RequestPermission()) {
        // 無(wú)論是否授權(quán),都進(jìn)行獲取,作對(duì)比
        getDeviceID()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutDeviceIdExampleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }
        binding.btnGetDeviceId.setOnClickListener {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                deviceIdPermissionRequestLauncher.launch(Manifest.permission.READ_PHONE_STATE)
            } else {
                getDeviceID()
            }
        }
    }
    private fun getDeviceID() {
        val telephonyManager = getSystemService(TelephonyManager::class.java)
        val deviceIDStrBuilder = StringBuilder()
        try {
            deviceIDStrBuilder.append("deviceId:").append(telephonyManager.deviceId)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            try {
                // 設(shè)備類型為GSM且有權(quán)限獲取時(shí)不為空
                deviceIDStrBuilder.append("\nIMEI:").append(telephonyManager.imei)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            try {
                // 設(shè)備類型為CDMA且有權(quán)限獲取時(shí)不為空
                deviceIDStrBuilder.append("\nMEID:").append(telephonyManager.meid)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        binding.tvResultValue.text = deviceIDStrBuilder
    }
}

測(cè)試設(shè)備為Android Studio模擬器,API為28,測(cè)試效果如下:

API 29以上

從API 29(Android10.0)開(kāi)始,即使用戶授予READ_PHONE_STATE權(quán)限,上述三種方法返回值均為空字符串。

測(cè)試設(shè)備為Android Studio模擬器,API為29,測(cè)試效果如下:

在API 29以上也有仍能獲取Device ID的方法,需要與運(yùn)營(yíng)商或者手機(jī)廠商有深度合作,具體可以參考官方文檔

ANDROID_ID

設(shè)備首次啟動(dòng)時(shí)生成,恢復(fù)出廠設(shè)置時(shí)會(huì)被重置,無(wú)需任何權(quán)限即可獲取。獲取代碼如下:

class DeviceIdExampleActivity : AppCompatActivity() {
    private lateinit var binding: LayoutDeviceIdExampleActivityBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutDeviceIdExampleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }
        binding.btnGetAndroidId.setOnClickListener {
            binding.tvResultValue.text = "ANDROID_ID:${Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)}"
        }
    }
}

測(cè)試設(shè)備為Pixel 7,API為34,測(cè)試效果如下:

需要注意的是,根據(jù)查詢到的資料來(lái)看,不同廠商的設(shè)備可能會(huì)出現(xiàn)返回空值或者返回值相同的情況。另外,ANDROID_ID可以手動(dòng)進(jìn)行修改

Serial(序列號(hào))

設(shè)備硬件序列號(hào),通常在沒(méi)有root的情況下不會(huì)重置,在不同版本的Android設(shè)備上,獲取Serial的方法及效果略有不同,下面分別介紹一下。

API 23-25

在API 23-25版本的設(shè)備上無(wú)需配置權(quán)限,獲取代碼如下:

class DeviceIdExampleActivity : AppCompatActivity() {
    private lateinit var binding: LayoutDeviceIdExampleActivityBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutDeviceIdExampleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }
        binding.btnGetDeviceSerial.setOnClickListener {
            try {
                binding.tvResultValue.text = "deviceSerial:${Build.SERIAL}"
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

測(cè)試設(shè)備為Android Studio模擬器,API為25,測(cè)試效果如下:

API 26-28

從API 26(Android8.0)開(kāi)始,android.os.Build.SERIAL總是返回UNKNOWN,改為使用android.os.Build.getSerial()方法獲取,另外還需配置READ_PHONE_STATE權(quán)限并且在運(yùn)行時(shí)動(dòng)態(tài)申請(qǐng)用戶授權(quán)。示例代碼如下:

class DeviceIdExampleActivity : AppCompatActivity() {
    private lateinit var binding: LayoutDeviceIdExampleActivityBinding
    private val serialPermissionRequestLauncher = registerForActivityResult(/* contract = */ ActivityResultContracts.RequestPermission()) {
        // 無(wú)論是否授權(quán),都進(jìn)行獲取,作對(duì)比
        getSerial()
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutDeviceIdExampleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }
        binding.btnGetDeviceSerial.setOnClickListener {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                serialPermissionRequestLauncher.launch(Manifest.permission.READ_PHONE_STATE)
            } else {
                getSerial()
            }
        }
    }
    private fun getSerial() {
        val serialStrBuilder = StringBuilder()
        try {
            serialStrBuilder.append("Build.SERIAL:").append(Build.SERIAL)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                serialStrBuilder.append("\nBuild.getSerial():").append(Build.getSerial())
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        binding.tvResultValue.text = serialStrBuilder
    }
}

測(cè)試設(shè)備為Android Studio模擬器,API為28,測(cè)試效果如下:

API 29以上

從API 29(Android10.0)開(kāi)始,獲取Serial和獲取DeviceID一樣,文中列舉的方法無(wú)法正常獲取,但官方也提供了相應(yīng)的解決方法。

測(cè)試設(shè)備為Android Studio模擬器,API為29,測(cè)試效果如下:

MAC地址

用于標(biāo)識(shí)網(wǎng)絡(luò)接口的硬件地址,通常在設(shè)備出廠時(shí)分配。有root權(quán)限時(shí)可以進(jìn)行修改,因此存在重復(fù)的可能性。在不同版本的Android設(shè)備上,獲取MAC地址的效果略有不同,下面分別介紹一下。

API 23-28

使用NetworkInterface.getNetworkInterfaces()方法來(lái)獲取MAC地址,無(wú)需任何權(quán)限,示例代碼如下:

class DeviceIdExampleActivity : AppCompatActivity() {
    private lateinit var binding: LayoutDeviceIdExampleActivityBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutDeviceIdExampleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }
        binding.btnGetMacAddress.setOnClickListener {
            val networkInterfaces = NetworkInterface.getNetworkInterfaces()
            while (networkInterfaces.hasMoreElements()) {
                val network = networkInterfaces.nextElement()
                if (network.name == "wlan0") {
                    binding.tvResultValue.text = "macAddress:${network.hardwareAddress?.joinToString(":") { macAddress -> String.format("%02X", macAddress) }}"
                    break
                }
            }
        }
    }
}

測(cè)試設(shè)備為samsung Galaxy S8,API為28,測(cè)試效果如下:

關(guān)閉WI-FI

WI-FI

熱點(diǎn)

API 29

獲取代碼和上面一致,但是從API 29(Android10.0)開(kāi)始,連接不同的WI-FI時(shí)會(huì)獲取到不同的MAC地址。

測(cè)試設(shè)備為samsung Galaxy S9,API為29,測(cè)試效果如下:

WI-FI

熱點(diǎn)

API 30以上

從API 30(Android11.0)開(kāi)始,已無(wú)法獲取到MAC地址。

測(cè)試設(shè)備為Pixel 7,API為34,測(cè)試效果如下:

小結(jié)

文中測(cè)試的四種設(shè)備標(biāo)識(shí),確定不會(huì)重復(fù)的應(yīng)該只有DeviceId和MAC地址,但是二者從API 29開(kāi)始也都不可靠了。當(dāng)然,在市面上仍然有不少API 29以下的設(shè)備,在選擇唯一標(biāo)識(shí)方案時(shí),低版本的設(shè)備仍然可以采用DeviceID或MAC地址,高版本則采用官方推薦的AAID等方案。

到此這篇關(guān)于Android 常見(jiàn)獲取設(shè)備標(biāo)識(shí)方法現(xiàn)狀的文章就介紹到這了,更多相關(guān)Android設(shè)備標(biāo)識(shí)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論