sn获取方式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
sn = Build.getSerial();
} else {
sn = Build.SERIAL;
}
由于android系统限制,在Android 9及以上无法获取sn了,主要是系统源码里加了权限判断,非系统应用不允许获取了.
相关源码解读
Android 10源码
获取sn需要有系统权限,才能获取
private static final class DeviceIdentifiersPolicy
45 extends IDeviceIdentifiersPolicyService.Stub {
46 private final @NonNull Context mContext;
47
48 public DeviceIdentifiersPolicy(Context context) {
49 mContext = context;
50 }
51
52 @Override
53 public @Nullable String getSerial() throws RemoteException {
54 // Since this invocation is on the server side a null value is used for the
55 // callingPackage as the server's package name (typically android) should not be used
56 // for any device / profile owner checks. The majority of requests for the serial number
57 // should use the getSerialForPackage method with the calling package specified.
58 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
59 /* callingPackage */ null, "getSerial")) {
60 return Build.UNKNOWN;
61 }
62 return SystemProperties.get("ro.serialno", Build.UNKNOWN);
63 }
64
65 @Override
66 public @Nullable String getSerialForPackage(String callingPackage) throws RemoteException {
67 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
68 callingPackage, "getSerial")) {
69 return Build.UNKNOWN;
70 }
71 return SystemProperties.get("ro.serialno", Build.UNKNOWN);
72 }
73 }
源码路径:/frameworks/base/telephony/java/com/android/internal/telephony/TelephonyPermissions.java,检在checkReadDeviceIdentifiers()里检测饿了是否有系统权限
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
250 String callingPackage, String message) {
251 return checkCallingOrSelfReadDeviceIdentifiers(context,
252 SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage, message);
253 }
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
273 String callingPackage, String message) {
274 return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
275 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
276 }
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
295 String callingPackage, String message) {
296 return checkReadDeviceIdentifiers(context, TELEPHONY_SUPPLIER, subId,
297 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
298 }
@VisibleForTesting
308 public static boolean checkReadDeviceIdentifiers(Context context,
309 Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
310 String callingPackage, String message) {
311 // Allow system and root access to the device identifiers.
312 final int appId = UserHandle.getAppId(uid);
313 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
314 return true;
315 }
316 // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission.
317 if (context.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid,
318 uid) == PackageManager.PERMISSION_GRANTED) {
319 return true;
320 }
321 // If the calling package has carrier privileges for any subscription then allow access.
322 if (checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid)) {
323 return true;
324 }
325 // if the calling package is not null then perform the DevicePolicyManager device /
326 // profile owner and Appop checks.
327 if (callingPackage != null) {
328 // Allow access to an app that has been granted the READ_DEVICE_IDENTIFIERS app op.
329 long token = Binder.clearCallingIdentity();
330 AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
331 Context.APP_OPS_SERVICE);
332 try {
333 if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid,
334 callingPackage) == AppOpsManager.MODE_ALLOWED) {
335 return true;
336 }
337 } finally {
338 Binder.restoreCallingIdentity(token);
339 }
340 // Allow access to a device / profile owner app.
341 DevicePolicyManager devicePolicyManager =
342 (DevicePolicyManager) context.getSystemService(
343 Context.DEVICE_POLICY_SERVICE);
344 if (devicePolicyManager != null && devicePolicyManager.checkDeviceIdentifierAccess(
345 callingPackage, pid, uid)) {
346 return true;
347 }
348 }
349 return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
350 message);
351 }
Android 8.0源码
public @Nullable String getSerial() throws RemoteException {
57 if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
58 && mContext.checkCallingOrSelfPermission(
59 Manifest.permission.READ_PHONE_STATE)
60 != PackageManager.PERMISSION_GRANTED
61 && mContext.checkCallingOrSelfPermission(
62 Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
63 != PackageManager.PERMISSION_GRANTED) {
64 throw new SecurityException("getSerial requires READ_PHONE_STATE"
65 + " or READ_PRIVILEGED_PHONE_STATE permission");
66 }
67 return SystemProperties.get("ro.serialno", Build.UNKNOWN);
68 }
Android 7.0 Build.SERIAL源码
Build.java路径:
https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/os/Build.java
这种方式最终也是通过SystemProperties.get()获取的.
在android 7源码里还没有DeviceIdentifiersPolicyService.java,也就不能调用其getSerial().
//在android 10上 这个被取消了
public static final String SERIAL = getString("ro.serialno");
//但是在android 10 这个方法还是存在的
private static String getString(String property) {
return SystemProperties.get(property, UNKNOWN);
}