Android實現獲取本機手機號碼

和上次獲取設備序列號一樣,仍然是通過無障礙服務實現,在之前的代碼基礎上做了更新。代碼和demo如下:

package com.zwxuf.lib.devicehelper;import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.app.Application;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class DeviceHelper implements Application.ActivityLifecycleCallbacks {static final String TAG = "WADQ_DeviceHelper";static final String ACTION_ACQUIRE_SERIAL_SUCCESS = "zwxuf.intent.action.ACQUIRE_SERIAL_SUCCESS";static final String ACTION_ACQUIRE_PHONE_SUCCESS = "zwxuf.intent.action.ACQUIRE_PHONE_SUCCESS";private static Handler mHandler = new Handler(Looper.getMainLooper());private boolean isMsgReceiverEnabled;private OnAcquireSerialListener mOnAcquireSerialListener;private OnAcquirePhoneListener onAcquirePhoneListener;private Activity mActivity;private Application mApplication;public DeviceHelper(Activity mActivity) {this.mActivity = mActivity;mApplication = mActivity.getApplication();mApplication.registerActivityLifecycleCallbacks(this);}public void acquireSerial(OnAcquireSerialListener listener) {mOnAcquireSerialListener = listener;if (!isMsgReceiverEnabled) initMsgReceiver();AcquireSerialService.isSerialFound = false;AcquireSerialService.isStatusInfoFound = false;Intent intent = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mActivity.startActivity(intent);}public void acquirePhone(OnAcquirePhoneListener listener) {onAcquirePhoneListener = listener;if (!isMsgReceiverEnabled) initMsgReceiver();Intent intent = new Intent();intent.setClassName("com.android.phone", "com.android.phone.MSimMobileNetworkSettings");intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {mActivity.startActivity(intent);} catch (Exception e) {e.printStackTrace();Toast.makeText(mActivity, e.toString(), Toast.LENGTH_SHORT).show();}}private void releaseAcquireSerial() {List<Service> services = getServices();for (Service service : services) {if (service instanceof AcquireSerialService) {((AcquireSerialService) service).release();break;}}}private void releaseAcquirePhone() {List<Service> services = getServices();for (Service service : services) {if (service instanceof AcquirePhoneService) {((AcquirePhoneService) service).release();break;}}}private void initMsgReceiver() {IntentFilter filter = new IntentFilter();filter.addAction(ACTION_ACQUIRE_SERIAL_SUCCESS);filter.addAction(ACTION_ACQUIRE_PHONE_SUCCESS);mActivity.registerReceiver(mMsgReceiver, filter);isMsgReceiverEnabled = true;}private BroadcastReceiver mMsgReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (ACTION_ACQUIRE_SERIAL_SUCCESS.equals(intent.getAction())) {String serial = intent.getStringExtra("serial");if (mOnAcquireSerialListener != null) {mOnAcquireSerialListener.onAcquireSerial(serial);}} else if (ACTION_ACQUIRE_PHONE_SUCCESS.equals(intent.getAction())) {ArrayList<String> phoneNumbers = intent.getStringArrayListExtra("phones");if (onAcquirePhoneListener != null) {onAcquirePhoneListener.onAcquirePhone(phoneNumbers);}}releaseMsgReciever();}};private void releaseMsgReciever() {if (isMsgReceiverEnabled) {mActivity.unregisterReceiver(mMsgReceiver);isMsgReceiverEnabled = false;}}public void release() {releaseMsgReciever();mApplication.unregisterActivityLifecycleCallbacks(this);releaseAcquireSerial();releaseAcquirePhone();}public boolean canAcquireSerial() {return isServiceEnabled(mActivity, AcquireSerialService.class);}public boolean canAcquirePhone() {return isServiceEnabled(mActivity, AcquirePhoneService.class);}public void openAccessibilitySettings(final int requestCode) {Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);try {mActivity.startActivityForResult(intent, requestCode);} catch (Exception e) {e.printStackTrace();}}private static boolean isServiceEnabled(Context context, Class<? extends AccessibilityService> serviceClass) {if (serviceClass == null) {return false;}String serviceName = context.getPackageName() + "/" + serviceClass.getName();try {int enabled = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);if (enabled == 1) {String service = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);Log.i(TAG, service);return service != null && service.contains(serviceName);}} catch (Exception e) {e.printStackTrace();}return false;}static Handler getHandler() {return mHandler;}@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) {}@Overridepublic void onActivityStarted(Activity activity) {}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) {if (activity == mActivity) {release();}}private static List<Service> getServices() {List<Service> services = new ArrayList<>();Object mActivityThread = getActivityThread();try {Class mActivityThreadClass = mActivityThread.getClass();Field mServicesField = mActivityThreadClass.getDeclaredField("mServices");mServicesField.setAccessible(true);Object mServices = mServicesField.get(mActivityThread);if (mServices instanceof Map) {Map<IBinder, Service> arrayMap = (Map) mServices;for (Map.Entry<IBinder, Service> entry : arrayMap.entrySet()) {Service service = entry.getValue();if (service != null) {services.add(service);}}}} catch (Throwable e) {e.printStackTrace();}return services;}private static Object getActivityThread() {try {Class ActivityThread = Class.forName("android.app.ActivityThread");Method currentActivityThread = ActivityThread.getMethod("currentActivityThread");currentActivityThread.setAccessible(true);return currentActivityThread.invoke(null);} catch (Throwable e) {e.printStackTrace();}return null;}}

獲取手機號服務代碼:

package com.zwxuf.lib.devicehelper;import android.accessibilityservice.AccessibilityService;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class AcquirePhoneService extends AccessibilityService {private ArrayList<String> mPhoneNumbers = new ArrayList<>();private boolean mAcquireSuccess;@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {if (event.getPackageName() == null || event.getClassName() == null) {return;}String packageName = event.getPackageName().toString();String className = event.getClassName().toString();final AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo != null) {if (!packageName.equals(getApplicationContext().getPackageName())) {enumChildNodeInfo(nodeInfo, 0);}}}@Overridepublic void onInterrupt() {}private void enumChildNodeInfo(AccessibilityNodeInfo nodeInfo, int level) {//Dbg.print(TAG, StringUtils.generateStr(" ", level), nodeInfo.getClassName(), getNodeText(nodeInfo), nodeInfo.getViewIdResourceName());int count = nodeInfo.getChildCount();//Dbg.print("count=" + count);if (count > 0) {for (int i = 0; i < count; i++) {final AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i);if (childNodeInfo == null) continue;/*if (childNodeInfo.isScrollable()) {childNodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);}*/List<AccessibilityNodeInfo> nodeInfoList = childNodeInfo.findAccessibilityNodeInfosByViewId("android:id/title");if (nodeInfoList != null && !nodeInfoList.isEmpty()) {for (AccessibilityNodeInfo ni : nodeInfoList) {String text = getNodeText(ni);if (text == null) continue;if (text.startsWith("卡 1") || text.startsWith("卡 2")) {int start = text.lastIndexOf("(");int end = text.indexOf(")", start);if (start > 0 && start < end) {String number = text.substring(start + 1, end);if (number.startsWith("+86")) {number = number.substring(3);}if (isPhoneNumber(number) && !mPhoneNumbers.contains(number)) {mPhoneNumbers.add(number);}}if (!mPhoneNumbers.isEmpty() && !mAcquireSuccess) {mAcquireSuccess = true;//延時獲取第2個手機號DeviceHelper.getHandler().postDelayed(new Runnable() {@Overridepublic void run() {Intent intent = new Intent(DeviceHelper.ACTION_ACQUIRE_PHONE_SUCCESS);intent.putExtra("phones", mPhoneNumbers);sendBroadcast(intent);performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);release();}}, 500);}break;}}}enumChildNodeInfo(childNodeInfo, level + 1);}}nodeInfo.recycle();}private String getNodeText(AccessibilityNodeInfo nodeInfo) {if (nodeInfo != null && nodeInfo.getText() != null) {return nodeInfo.getText().toString();} else {return null;}}static boolean isPhoneNumber(String mobiles) {Pattern p = Pattern.compile("^(0|86|17951)?(13[0-9]|15[0-9]|17[0-9]|18[0-9]|14[0-9]|16[0-9]|19[0-9])[0-9]{8}$");Matcher m = p.matcher(mobiles);return m.matches();}public void release() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {disableSelf();}}
}

下載地址:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42109.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42109.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42109.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

css 選擇器匯總

目錄 所有選擇器偽類選擇器 所有選擇器 選擇器用法id選擇器#myid類選擇器.myclassname標簽選擇器div,h1,p相鄰選擇器h1p子選擇器ul > li后代選擇器li a通配符選擇器*屬性選擇器a[rel“external”]偽類選擇器a:hover, li:nth-child 偽類選擇器 在CSS3中新增了一個結構偽類選…

Bpuzzle V1.2 支持任意圖片!BlueLife Puzzle (bPuzzle) 是一款簡單的游戲,通過按正確的順序滑動拼圖塊來玩

BlueLife Puzzle (bPuzzle) 是一款簡單的游戲&#xff0c;通過按正確的順序滑動拼圖塊來玩。將您選擇的圖像拖放到主窗口或使用文件菜單選擇默認圖像。如果圖片格式是 JPG&#xff0c;大小無關緊要&#xff0c;但如果是 Png&#xff0c;則應為 800600 像素&#xff0c;然后 bPu…

nginx配置嘗試

from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import JSONResponse, FileResponse, HTMLResponse import logging import os from datetime import datetime import uvicorn# 初始化日志 logging.basicConfig(filenamefile_server.lo…

詳細的講解一下網絡變壓器應用POE ,AT BT AF BF的概念,做電路連接指導分析

網絡變壓器在應用POE&#xff08;Power over Ethernet&#xff09;技術時&#xff0c;承擔著重要的角色。它不僅負責數據的傳輸&#xff0c;同時也為網絡設備提供電力。在IEEE 802.3標準中&#xff0c;定義了幾個與POE相關的標準&#xff0c;包括802.3af、802.3at、802.3bt等&a…

智慧景區解決方案PPT(89頁)

智慧景區解決方案摘要 解決方案概述智慧景區解決方案旨在利用現代信息技術解決景區管理機構面臨的保護與發展矛盾&#xff0c;推動服務職能轉變&#xff0c;促進旅游產業跨越式發展&#xff0c;實現旅游經營增長和管理成本優化。 宏觀政策背景國家旅游局發布的《“十三五”全國…

VideoAgent——使用大規模語言模型作為代理來理解長視頻

概述 論文地址&#xff1a;https://arxiv.org/pdf/2403.10517 本研究引入了一個新穎的基于代理的系統&#xff0c;名為 VideoAgent。該系統以大規模語言模型為核心&#xff0c;負責識別關鍵信息以回答問題和編輯視頻。VideoAgent 在具有挑戰性的 EgoSchema 和 NExT-QA 基準上進…

TD-MPC(Temporal Difference Model Predictive Control)人形機器人行走舉例

td-mpc控制機器人行走舉例 TD-MPC(Temporal Difference Model Predictive Control)是一種結合了時序差分學習和模型預測控制的強化學習方法,特別適用于控制復雜系統如人形機器人行走任務。TD-MPC通過使用模型預測控制(MPC)在已學到的環境模型中進行多步預測和優化,再結合…

數據特征采樣在 MySQL 同步一致性校驗中的實踐

作者&#xff1a;vivo 互聯網存儲研發團隊 - Shang Yongxing 本文介紹了當前DTS應用中&#xff0c;MySQL數據同步使用到的數據一致性校驗工具&#xff0c;并對它的實現思路進行分享。 一、背景 在 MySQL 的使用過程中&#xff0c;經常會因為如集群拆分、數據傳輸、數據聚合等…

qt 播放視頻

在 Qt 中播放視頻&#xff0c;你可以使用 Qt Multimedia 模塊。這個模塊提供了處理音頻和視頻內容的功能。以下是一個簡單的例子&#xff0c;展示了如何使用 QMediaPlayer 和 QVideoWidget 來播放視頻&#xff1a; 包含必要的頭文件&#xff1a; #include <QMediaPlayer&g…

容器:queue(隊列)

以下是關于queue容器的總結 1、構造函數&#xff1a;queue [queueName] 2、添加、刪除元素: push() 、pop() 3、獲取隊頭/隊尾元素&#xff1a;front()、back() 4、獲取棧的大小&#xff1a;size() 5、判斷棧是否為空&#xff1a;empty() #include <iostream> #include …

一個簡單的spring+kafka生產者

1. pom <dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency>2. 生產者 import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; impo…

https 自簽證書相關生成csr文件、p12文件、crt文件、jks文件、key文件、pem文件

文章目錄 前言https 自簽證書相關生成csr文件、p12文件、crt文件、jks文件、key文件、pem文件1, 檢查openssl的版本2. 生成私鑰和證書簽署請求 (CSR)3. 生成自簽名證書4. 將證書和私鑰轉換為 PKCS12 格式的密鑰庫5. 創建信任庫 (Truststore)6. 將 PKCS12 文件轉換為 JKS 文件7.…

IDEA安裝IDE Eval Reset插件,30天自動續期,無限激活

第一步&#xff1a; 下載idea 注意&#xff1a;版本要是2021.2.2以下 第二步&#xff1a;快捷鍵CtrlAlts打開設置 第三步&#xff1a;打開下圖中藍色按鈕 第四步&#xff1a;點擊彈窗的 “” &#xff0c;并輸入 plugins.zhile.io 點擊 “ok” 第五步&#xff1a;搜索IDE Ea…

前端必修技能:高手進階核心知識分享 - CSS mix-blend-mode 圖片混合模式詳解

標簽定義及使用說明 mix-blend-mode 屬性描述了元素的內容應該與元素的直系父元素的內容和元素的背景如何混合。 語法 mix-blend-mod: 使用mix-blend-mode 各種混合模式實例 注意: Internet Explorer 或 Edge 瀏覽器不支持 mix-blend-mode 屬性。 &#xff08;還是那個熟…

AJAX-個人版-思路步驟整理版

前置知識&#xff1a;老式的web創建工程方法就是創建項目然后添加web工件&#xff0c;然后添加lib依賴如&#xff1a;tomcat,servlet&#xff0c;等。 傳統請求 對于傳統請求操作&#xff1a;整體流程也就是創建靜態頁面&#xff0c; <!DOCTYPE html> <html lang&q…

CSS技巧:用CSS繪制超寫實的酷炫徽章緞帶效果,超漂亮,超酷炫

為什么要用CSS來畫個徽章&#xff1f;這貨腦子進水了吧&#xff01; 今天在電腦前設計&#xff0c;要做徽章效果。突然覺得可以嘗試用css實現近似的效果。說干就干&#xff0c;打開編輯器&#xff0c;讓我的手指頭活躍起來&#xff01; 技術要點 通過多個圓形嵌套和漸變屬性…

【Rust練習】1.變量綁定與解構

地址&#xff1a;https://practice-zh.course.rs/variables.html &#x1f31f; 變量只有在初始化后才能被使用 // 修復下面代碼的錯誤并盡可能少的修改 fn main() {let x: i32; // 未初始化&#xff0c;但被使用let y: i32; // 未初始化&#xff0c;也未被使用println!(&quo…

WIN32核心編程 - 線程操作(一) 線程信息 - 線程控制

公開視頻 -> 鏈接點擊跳轉公開課程博客首頁 -> 鏈接點擊跳轉博客主頁 目錄 Thread Thread Control 創建 - Create 執行 - Execute 掛起 - Suspend 恢復 - Resume 終止 - Terminate 遠程 - Remote Thread Info GetCurrentThread/Id GetThreadContext CreateToo…

Vue iview-ui 被tooltip包裹的標題,點擊跳轉后,提示框不消失

tooltip包裹的標題&#xff0c;點擊跳轉后&#xff0c;提示框不消失 就會有這種顯示問題 下面這種錯誤方法不可行&#xff0c;解決辦法往下翻 css寫得沒錯&#xff0c;問題出在Javascript當中的 getElementsByClassName(“xxabc”)&#xff0c; 這個方法得到的是一個由class&q…

【Android】【WIFI】檢查 SDIO 設備的狀態

檢查 SDIO 設備的狀態 要檢查 Android 設備上 SDIO 設備的狀態&#xff0c;可以使用 ADB 命令來獲取系統信息。以下是一些示例命令&#xff1a; 列出 SDIO 設備 adb shell cat /proc/devices | grep sdio檢查 SDIO 模塊是否加載 adb shell lsmod | grep sdio獲取 SDIO 相關的…