当前位置:   article > 正文

Android10以上实现获取设备序列号功能

Android10以上实现获取设备序列号功能

Android10以上实现获取设备唯一标识,目前只支持华为和荣耀设备。实现原理:通过无障碍服务读取序列号界面。

  1. public class DeviceHelper implements Application.ActivityLifecycleCallbacks {
  2. static final String TAG = "WADQ_DeviceHelper";
  3. static final String ACTION_ACQUIRE_SERIAL_SUCCESS = "zwxuf.intent.action.ACQUIRE_SERIAL_SUCCESS";
  4. private static Handler mHandler = new Handler(Looper.getMainLooper());
  5. private boolean isMsgReceiverEnabled;
  6. private OnAcquireSerialListener mOnAcquireSerialListener;
  7. private Activity mActivity;
  8. private Application mApplication;
  9. public DeviceHelper(Activity mActivity) {
  10. this.mActivity = mActivity;
  11. mApplication = mActivity.getApplication();
  12. mApplication.registerActivityLifecycleCallbacks(this);
  13. }
  14. public void acquireSerial(OnAcquireSerialListener listener) {
  15. mOnAcquireSerialListener = listener;
  16. if (!isMsgReceiverEnabled) initMsgReceiver();
  17. AcquireSerialService.isSerialFound = false;
  18. AcquireSerialService.isStatusInfoFound = false;
  19. Intent intent = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
  20. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  21. mActivity.startActivity(intent);
  22. }
  23. private void releaseAcquireSerial() {
  24. List<Service> services = getServices();
  25. for (Service service : services) {
  26. if (service instanceof AcquireSerialService) {
  27. ((AcquireSerialService) service).release();
  28. break;
  29. }
  30. }
  31. }
  32. private void initMsgReceiver() {
  33. IntentFilter filter = new IntentFilter(ACTION_ACQUIRE_SERIAL_SUCCESS);
  34. mActivity.registerReceiver(mMsgReceiver, filter);
  35. isMsgReceiverEnabled = true;
  36. }
  37. private BroadcastReceiver mMsgReceiver = new BroadcastReceiver() {
  38. @Override
  39. public void onReceive(Context context, Intent intent) {
  40. String serial = intent.getStringExtra("serial");
  41. if (mOnAcquireSerialListener != null) {
  42. mOnAcquireSerialListener.onAcquireSerial(serial);
  43. }
  44. releaseMsgReciever();
  45. }
  46. };
  47. private void releaseMsgReciever() {
  48. if (isMsgReceiverEnabled) {
  49. mActivity.unregisterReceiver(mMsgReceiver);
  50. isMsgReceiverEnabled = false;
  51. }
  52. }
  53. public void release() {
  54. releaseMsgReciever();
  55. mApplication.unregisterActivityLifecycleCallbacks(this);
  56. releaseAcquireSerial();
  57. }
  58. public boolean canAcquireSerial() {
  59. return isServiceEnabled(mActivity, AcquireSerialService.class);
  60. }
  61. public void openAcquireSerialSettings(final int requestCode) {
  62. Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
  63. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  64. try {
  65. mActivity.startActivityForResult(intent, requestCode);
  66. } catch (Exception e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. private static boolean isServiceEnabled(Context context, Class<? extends AccessibilityService> serviceClass) {
  71. if (serviceClass == null) {
  72. return false;
  73. }
  74. String serviceName = context.getPackageName() + "/" + serviceClass.getName();
  75. try {
  76. int enabled = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
  77. if (enabled == 1) {
  78. String service = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
  79. Log.i(TAG, service);
  80. return service != null && service.contains(serviceName);
  81. }
  82. } catch (Exception e) {
  83. e.printStackTrace();
  84. }
  85. return false;
  86. }
  87. static Handler getHandler() {
  88. return mHandler;
  89. }
  90. @Override
  91. public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
  92. }
  93. @Override
  94. public void onActivityStarted(Activity activity) {
  95. }
  96. @Override
  97. public void onActivityResumed(Activity activity) {
  98. }
  99. @Override
  100. public void onActivityPaused(Activity activity) {
  101. }
  102. @Override
  103. public void onActivityStopped(Activity activity) {
  104. }
  105. @Override
  106. public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
  107. }
  108. @Override
  109. public void onActivityDestroyed(Activity activity) {
  110. if (activity == mActivity) {
  111. release();
  112. }
  113. }
  114. private static List<Service> getServices() {
  115. List<Service> services = new ArrayList<>();
  116. Object mActivityThread = getActivityThread();
  117. try {
  118. Class mActivityThreadClass = mActivityThread.getClass();
  119. Field mServicesField = mActivityThreadClass.getDeclaredField("mServices");
  120. mServicesField.setAccessible(true);
  121. Object mServices = mServicesField.get(mActivityThread);
  122. if (mServices instanceof Map) {
  123. Map<IBinder, Service> arrayMap = (Map) mServices;
  124. for (Map.Entry<IBinder, Service> entry : arrayMap.entrySet()) {
  125. Service service = entry.getValue();
  126. if (service != null) {
  127. services.add(service);
  128. }
  129. }
  130. }
  131. } catch (Throwable e) {
  132. e.printStackTrace();
  133. }
  134. return services;
  135. }
  136. private static Object getActivityThread() {
  137. try {
  138. Class ActivityThread = Class.forName("android.app.ActivityThread");
  139. Method currentActivityThread = ActivityThread.getMethod("currentActivityThread");
  140. currentActivityThread.setAccessible(true);
  141. return currentActivityThread.invoke(null);
  142. } catch (Throwable e) {
  143. e.printStackTrace();
  144. }
  145. return null;
  146. }
  147. }
  1. public class AcquireSerialService extends AccessibilityService {
  2. static boolean isStatusInfoFound;
  3. static boolean isSerialFound;
  4. @Override
  5. public void onAccessibilityEvent(AccessibilityEvent event) {
  6. if (event.getPackageName() == null || event.getClassName() == null) {
  7. return;
  8. }
  9. String packageName = event.getPackageName().toString();
  10. String className = event.getClassName().toString();
  11. final AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
  12. if (nodeInfo != null) {
  13. if (!packageName.equals(getApplicationContext().getPackageName())) {
  14. enumChildNodeInfo(packageName, nodeInfo, 0);
  15. }
  16. }
  17. }
  18. @Override
  19. public void onInterrupt() {
  20. }
  21. private Runnable mScrollRunnalbe;
  22. private void enumChildNodeInfo(String packageName, AccessibilityNodeInfo nodeInfo, int level) {
  23. int count = nodeInfo.getChildCount();
  24. if (count > 0) {
  25. for (int i = 0; i < count; i++) {
  26. final AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);
  27. if (childNodeInfo == null) continue;
  28. if (childNodeInfo.isScrollable()) {
  29. childNodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
  30. }
  31. if (!isSerialFound) {
  32. String serial = getSerialByNodeInfo(packageName, childNodeInfo);
  33. if (serial != null && !serial.isEmpty()) {
  34. //获取到sn
  35. Log.i(DeviceHelper.TAG, serial);
  36. Intent intent = new Intent(DeviceHelper.ACTION_ACQUIRE_SERIAL_SUCCESS);
  37. intent.putExtra("serial", serial);
  38. sendBroadcast(intent);
  39. performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
  40. DeviceHelper.getHandler().postDelayed(new Runnable() {
  41. @Override
  42. public void run() {
  43. performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
  44. release();
  45. }
  46. }, 200);
  47. return;
  48. }
  49. enumChildNodeInfo(packageName, childNodeInfo, level + 1);
  50. }
  51. }
  52. }
  53. nodeInfo.recycle();
  54. }
  55. private String getSerialByNodeInfo(String packageName, AccessibilityNodeInfo nodeInfo) {
  56. if (nodeInfo.getText() == null) {
  57. return null;
  58. }
  59. String text = nodeInfo.getText().toString();
  60. if (text.equals("序列号")) {
  61. isStatusInfoFound = true;
  62. isSerialFound = true;
  63. if (mScrollRunnalbe != null) {
  64. DeviceHelper.getHandler().removeCallbacks(mScrollRunnalbe);
  65. mScrollRunnalbe = null;
  66. }
  67. return getValue(nodeInfo);
  68. } else if (packageName.equals("com.android.settings") && (text.equals("状态信息") || text.equals("状态消息")) && !isStatusInfoFound) {
  69. isStatusInfoFound = true;
  70. AccessibilityNodeInfo statusInfoParent = nodeInfo.getParent();
  71. while (statusInfoParent != null && !statusInfoParent.isClickable()) {
  72. statusInfoParent = statusInfoParent.getParent();
  73. }
  74. if (statusInfoParent != null) {
  75. final AccessibilityNodeInfo finalStatusInfoParent = statusInfoParent;
  76. DeviceHelper.getHandler().postDelayed(new Runnable() {
  77. @Override
  78. public void run() {
  79. finalStatusInfoParent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
  80. }
  81. }, 200);
  82. }
  83. }
  84. return null;
  85. }
  86. private String getValue(AccessibilityNodeInfo nodeInfo) {
  87. AccessibilityNodeInfo snLayout = nodeInfo.getParent();
  88. if (snLayout != null) {
  89. while (true) {
  90. List<AccessibilityNodeInfo> snSummaryList = snLayout.findAccessibilityNodeInfosByViewId("android:id/summary");
  91. if (snSummaryList != null && !snSummaryList.isEmpty()) {
  92. AccessibilityNodeInfo snSummary = snSummaryList.get(0);
  93. if (snSummary != null && snSummary.getText() != null) {
  94. return snSummary.getText().toString();
  95. }
  96. }
  97. snLayout = snLayout.getParent();
  98. if (snLayout == null) {
  99. break;
  100. }
  101. }
  102. }
  103. return null;
  104. }
  105. private String getNodeText(AccessibilityNodeInfo nodeInfo) {
  106. if (nodeInfo != null && nodeInfo.getText() != null) {
  107. return nodeInfo.getText().toString();
  108. } else {
  109. return null;
  110. }
  111. }
  112. public void release() {
  113. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  114. disableSelf();
  115. }
  116. }
  117. }

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  2. private DeviceHelper mDeviceHelper;
  3. private TextView tv_serial, tv_phone;
  4. @Override
  5. protected void onCreate(Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_main);
  8. tv_serial = findViewById(R.id.tv_serial);
  9. mDeviceHelper = new DeviceHelper(this);
  10. }
  11. @Override
  12. public void onClick(View v) {
  13. switch (v.getId()) {
  14. case R.id.bn_get_serial:
  15. getSerial();
  16. break;
  17. }
  18. }
  19. private void getSerial() {
  20. if (!mDeviceHelper.canAcquireSerial()) {
  21. new AlertDialog.Builder(this)
  22. .setMessage("没有开启无障碍服务")
  23. .setPositiveButton("去开启", new DialogInterface.OnClickListener() {
  24. @Override
  25. public void onClick(DialogInterface dialog, int which) {
  26. mDeviceHelper.openAcquireSerialSettings(1000);
  27. }
  28. })
  29. .setNegativeButton("取消", null)
  30. .create()
  31. .show();
  32. return;
  33. }
  34. mDeviceHelper.acquireSerial(new OnAcquireSerialListener() {
  35. @Override
  36. public void onAcquireSerial(String serial) {
  37. //Toast.makeText(MainActivity.this, serial, Toast.LENGTH_SHORT).show();
  38. tv_serial.setText("sn:" + serial);
  39. }
  40. });
  41. }
  42. }

下载地址:https://download.csdn.net/download/zzmzzff/89515671

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/792417
推荐阅读
相关标签
  

闽ICP备14008679号