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() {
        @Override
        public 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;
    }


    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public 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;

    @Override
    public 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);
            }
        }
    }

    @Override
    public 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() {
                                    @Override
                                    public 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();
        }
    }
}

下载地址:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/774565.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

千万不能踏入的渠道管理五大误区!【附策略】

一、引言 在当今激烈的市场竞争环境中&#xff0c;有效的渠道管理是企业获得竞争优势的关键。然而&#xff0c;在实践过程中&#xff0c;不少企业因陷入管理误区而影响了市场拓展和品牌建设。本文旨在揭示渠道管理中常见的五大误区&#xff0c;并提供避免策略&#xff0c;帮助…

现代农业利器:土壤检测仪器的应用与未来

在现代农业发展的浪潮中&#xff0c;土壤检测仪器以其精准、高效的特点&#xff0c;成为了农业生产的得力助手。这些看似不起眼的设备&#xff0c;实际上在保障农产品质量、提高农业生产效率方面发挥着举足轻重的作用。 一、土壤检测仪器&#xff1a;现代农业的“眼睛” 土壤检…

科技云报道:人工智能“顶流”齐聚WAIC 2024,他们都做了什么?

科技云报道原创。 一个由智能驱动的未来世界长啥样&#xff1f; 从完成跨海跨城航线的“空中的士”、全无人驾驶汽车、实现奔跑功能的全尺寸通用人形机器人到百度文心一言、讯飞星火、阿里通义千问、华为盘古、商汤日日新等大模型&#xff0c;从智能制造引领的“灯塔工厂”到…

TTS文本转声音:fish-speech 推理、requests访问接口案例

参考: https://hub.docker.com/r/lengyue233/fish-speech https://speech.fish.audio/inference/#http-api 下载 下载模型: HF_ENDPOINT=https://hf-mirror.com huggingface-cli download fishaudio/fish-speech-1.2 --local-dir checkpoints/fish-speech-1.2下载的内容有…

GoodTask for Mac:优雅高效的任务管理助手

在快节奏的工作生活中&#xff0c;你是否需要一个优雅且高效的任务管理工具来助你一臂之力&#xff1f;GoodTask for Mac正是你的理想选择&#xff01; GoodTask以其简洁直观的界面设计&#xff0c;让你一眼就能看清所有的待办事项。你可以轻松创建任务、设置提醒&#xff0c;…

请查收!模拟电路精选书单一份(可下载)

在电子工程的广阔天地中&#xff0c;模拟电路设计是一门艺术&#xff0c;也是一种科学。它要求设计师不仅要有深厚的理论知识&#xff0c;还要有精湛的实践技能。随着技术的发展&#xff0c;模拟电路设计领域不断涌现新的理论、技术和工具&#xff0c;这使得学习和掌握模拟设计…

虚拟ECU:纯电动汽车发展下的新选择

人类文明的进步是一个不断自我否定、自我超越的过程。21世纪以来&#xff0c;随着科技进步和经济社会发展&#xff0c;能源和交通系统已从独立于自然环境的孤立系统&#xff0c;转变为与自然、技术、社会深度耦合的复杂系统。为实现可持续发展和应对气候变化&#xff0c;世界各…

JDBC 学习笔记+代码整理

Tip Idea自带可视界面&#x1f449;MySQL 图形化界面-CSDN博客 Idea2022无add Framework support选项&#x1f449;最新版IDEA:Add web Framework Support步骤/构建JavaWeb项目步骤_idea add framework support-CSDN博客 基本步骤 1.加载驱动包Driver 2.建立与数据库的连接C…

MYSQL 设置主从同步

效果图 主数据库表数据 从数据库表数据 mysql 数据库配置:主数据库 设置主数据 my.cnf vim /etc/mysql/my.cnf 配置内容 [mysqld] server-id=1 log-bin=mysql-bin # 不需要同步的表 binlog-ignore-db=mysql binlog-ignore-db=sys binlog-ignore-db=performance_schema bi…

Spire.PDF for .NET【文档操作】演示:以特定的缩放比例/百分比打开 PDF 文件

有时&#xff0c;我们可能需要在显示 PDF 文件时更改缩放比例以满足我们的要求。在本文中&#xff0c;我们将演示如何使用 Spire.PDF for .NET 以特定的缩放比例/百分比&#xff08;例如默认值、100% 或任何其他所需的缩放比例&#xff09;打开 PDF 文件。 Spire.PDF for .NET…

TAPD项目管理软件无法与企业微信进行关联

TAPD一段时间未使用后&#xff0c;需要重新启动&#xff0c;此时会出现你的企业微信尚未与TAPD账号关联的提示 解决方案&#xff1a;找到TAPD应用&#xff0c;先删除应用&#xff0c;然后再解除禁用即可

基于python 的动态虚拟主机

将自己电脑上的Python脚本文件上传到虚拟机/var/www/cgi-bin/目录下 [rootlocalhost conf.d]# cd /var/www/cgi-bin/ [rootlocalhost cgi-bin]# rz -E rz waiting to receive.编辑vhost.conf配置文件 [rootlocalhost conf.d]# vim vhost.conf<virtualhost 192.168.209.140…

消息中间件ApacheKafka在windows简单安装

一.背景 之前公司需要API网关管理软件ApacheShenYu&#xff0c;我相信把调用的记录都存到一个数据库。他支持日志推送到kafka&#xff0c;所以&#xff0c;我准备尝试一下通过kafka接收调用的日志信息。第一步&#xff0c;当然是安装kafka了。 二.ApacheKafka的下载 打开下载…

Docker-自定义镜像发布到DockerHub仓库、阿里云仓库

文章目录 推送镜像DockerHub仓库推送镜像阿里云仓库 更多相关内容可查看 推送镜像DockerHub仓库 在服务器中 使用 docker 登录命令 docker login -u 账户 #enter 后输入密码推送镜像到DockerHub docker push 镜像名:tag但个人不建议推送到DockHub上&#xff0c;毕竟不是咱自…

【Python机器学习】处理文本数据——停用词

删除没有信息量的单词有一种方法&#xff0c;就是舍弃那些出现次数太多以至于没有信息量的单词。 有两种主要方法&#xff1a; 1、使用特定语言的停用词&#xff08;stopword&#xff09;列表&#xff1b; 2、舍弃那些出现过于频繁的单词。 scikit-learn的feature_extracti…

gradle构建工具

setting.gradle // settings.gradle rootProject.name my-project // 指定根项目名称include subproject1, subproject2 // 指定子项目名称&#xff0c;可选jar包名称 方式一 jar {archiveBaseName my-application // 设置 JAR 文件的基本名称archiveVersion 1.0 // 设置…

阿里云RDS云数据库库表恢复操作

最近数据库中数据被人误删了,记录一下恢复操作方便以后发生时进行恢复. 1.打开控制台&#xff0c;进入云数据库实例. 2.进入实例后 &#xff0c;点击右侧的备份恢复&#xff0c;然后看一下备份时间点&#xff0c;中间这边都是阿里云自动备份的备份集&#xff0c;基本都是7天一备…

与Flat Ads相约ChinaJoy 2024,共探全球化增长

在当今全球数字化浪潮的推动下,游戏产业作为文化与技术融合的先锋,正以前所未有的速度跨越国界,开启全球化发展的新篇章。随着第二十一届ChinaJoy的临近,全球的目光再次聚焦于上海新国际博览中心,这里即将成为数字娱乐与科技创新碰撞与交融的璀璨舞台。 而在这场盛会上,Flat A…

Python酷库之旅-第三方库Pandas(004)

目录 一、用法精讲 5、pandas.DataFrame.to_csv函数 5-1、语法 5-2、参数 5-3、功能 5-4、返回值 5-5、说明 5-6、用法 5-6-1、代码示例 5-6-2、结果输出 6、pandas.read_fwf函数 6-1、语法 6-2、参数 6-3、功能 6-4、返回值 6-5、说明 6-6、用法 6-6-1、代码…

某积分商城任意金额支付漏洞分析利用及思考

扫码领取网安教程 大部分开发人员在开发时都会有一种思维惯性&#xff0c;传参处处有校验处处都可信&#xff0c;但这个等式并非恒成立 前言 这个漏洞是在工作中例行渗透测试的时候发现的&#xff0c;虽然前端做了防篡改措施&#xff0c;但这是很经典的没有后端校验导致的任意…