Android 获取设备序列号(SN)

前言

在 Android 应用开发中,获取设备唯一标识符(SN/序列号)是一个常见需求。

常见应用场景包括设备绑定、问题追踪、数据分析等。

从 Android 8.0(API 26)开始,推荐使用 Build.SERIAL 获取设备序列号。

实现

从 Android 8.0(API 26)开始,推荐使用 Build.SERIAL 获取设备序列号。

对于 Android 8.0 及以上设备,需要申请 READ_PHONE_STATE 权限。

使用 Manifest.permission.READ_PHONE_STATE 权限声明如下。

1
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

以下代码展示了如何安全地获取设备序列号,并自动申请权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat

class DeviceHelper(private val activity: AppCompatActivity) {

private var cachedSerial: String? = null
private var pendingResult: ((String) -> Unit)? = null

private val permissionLauncher = activity.registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
cachedSerial = if (isGranted) {
getSerialDirect() ?: ""
} else {
""
}
pendingResult?.invoke(cachedSerial!!)
pendingResult = null
}

fun getDeviceSerial(callback: (String) -> Unit) {
cachedSerial?.let {
callback(it)
return
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
cachedSerial = getSerialDirect() ?: ""
callback(cachedSerial!!)
return
}

when {
ContextCompat.checkSelfPermission(
activity,
Manifest.permission.READ_PHONE_STATE
) == PackageManager.PERMISSION_GRANTED -> {
cachedSerial = getSerialDirect() ?: ""
callback(cachedSerial!!)
}
else -> {
pendingResult = callback
permissionLauncher.launch(Manifest.permission.READ_PHONE_STATE)
}
}
}

private fun getSerialDirect(): String? {
return try {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
Build.SERIAL
} else {
Build.getSerial()
}
} catch (e: SecurityException) {
null
}
}
}

使用方式如下。

1
2
3
4
val deviceHelper = DeviceHelper(this)
deviceHelper.getDeviceSerial { serial ->
Log.d("DeviceInfo", "Serial: $serial")
}

总结

使用 Build.SERIAL 是官方推荐的方式,适用于 Android 8.0 及以上版本。

需要申请 READ_PHONE_STATE 权限,并在运行时做好权限检查。

做好空值处理和异常捕获,确保应用稳定性。