Android sn获取&源码

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);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌枫158

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值