Android实现获取本机手机号码

news2024/11/26 23:36:34

和上次获取设备序列号一样,仍然是通过无障碍服务实现,在之前的代码基础上做了更新。代码和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();
        }
    }
}

下载地址:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中使用arima预测未来数据

看着已经存在的曲线图数据&#xff0c;想预估下后面曲线图的数据。 import java.util.Vector;public class AR {double[] stdoriginalData{};int p;ARMAMath armamathnew ARMAMath();/*** AR模型* param stdoriginalData* param p //p为MA模型阶数*/public AR(double [] stdori…

Dungeonborne延迟高?降低Dungeonborne延迟的方法分享

Dungeonborne是Mithril Interactive开发并发行的一款沉浸式第一人称 PvPvE 地下城探险游戏。Dungeonborne的魅力并不仅仅在于战斗和冒险。游戏中的剧情设计同样引人入胜&#xff0c;每个NPC都有自己独特的故事和背景&#xff0c;玩家在与他们交流的过程中&#xff0c;不仅能了解…

Tomcat(+Servlet)笔记+代码

Tomcat安装和配置 安装在不含中文的路径&#xff0c;路径不能太长 Apache 官网&#x1f447; Apache Tomcat - Welcome! 配置部分 点击下图红框处&#xff0c;找到Tomcat安装位置 添加项目的文件 配好的话&#xff0c;红框这里有个猫 代码部分 新建jsp文件&#xff0c;里…

【码银送书第二十二期】《Python数据分析从入门到精通(第2版)》

&#x1f490;大家好&#xff01;我是码银~&#xff0c;欢迎关注&#x1f490;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 前言 &#x1f340;丛书说明&#xff1a;“软件开发视频大讲堂‘’丛书第1版于2008年8月出版&#xff0c;因其编写细腻、易学实用…

字符串函数5-9题(30 天 Pandas 挑战)

字符串函数 1. 相关知识点1.5 字符串的长度条件判断1.6 apply映射操作1.7 python大小写转换1.8 正则表达式匹配2.9 包含字符串查询 2. 题目2.5 无效的推文2.6 计算特殊奖金2.7 修复表中的名字2.8 查找拥有有效邮箱的用户2.9 患某种疾病的患者 1. 相关知识点 1.5 字符串的长度条…

Orangepi配合IIC驱动OLED屏幕

目录 一、OLED屏幕 二、Orangepi的IIC接口及OLED屏幕硬件接线 2.1 Orangepi的IIC接口&#xff1a; 2.2 Orangepi与OLED屏幕硬件接线&#xff1a; 三、wiringPi库示例代码 3.1 wiringPi库OLED屏幕示例代码&#xff1a; 3.2 OLED显示自己想要的字符&#xff1a; 一、OLED屏…

E2.【C语言】练习:static部分

#include <stdio.h> int sum(int a) {int c 0;static int b 3;c 1;b 2;return (a b c); } int main() {int i;int a 2;for (i 0; i < 5;i){printf("%d ", sum(a));} } 求执行结果 c是auto类变量(普通的局部变量)&#xff0c;自动产生&#xff0c…

第26篇 寻找最大数<一>

Q&#xff1a;如何设计一段汇编语言子程序并调用来寻找一组数中的最大数呢&#xff1f; A&#xff1a;基本原理&#xff1a;可以使用子程序LARGE实现找到列表中最大数的功能。主程序通过寄存器将列表的条目数和起始地址作为参数传递给子程序&#xff0c;子程序通过寄存器将最大…

qt 如果把像素点数据变成一个图片

1.概要 图像的本质是什么&#xff0c;就是一个个的像素点&#xff0c;对与显示器来说就是一个二维数组。无论多复杂的图片&#xff0c;对于显示器来说就是一个二维数组。 2.代码 #include "widget.h"#include <QApplication> #include <QImage> #incl…

Springboot学习之用EasyExcel4导入导出数据(基于MyBatisPlus)

一、POM依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><m…

Linux系统之安装Ninvaders太空入侵者小游戏

Linux系统之安装Ninvaders太空入侵者小游戏 一、Ninvaders小游戏介绍1.1 Ninvaders小游戏简介1.2 项目预览 二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍 三、检查系统镜像源3.1 检查系统镜像源3.2 更新软件列表 四、安装Ninvaders4.1 安装Ninvaders4.2 启动Ninvaders游戏…

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、代码…

视频共享融合赋能平台LnyonCVS国标视频监控平台包含哪些功能

随着国内视频监控应用的迅猛发展&#xff0c;系统接入规模不断扩大。不同平台提供商的接入协议各不相同&#xff0c;导致终端制造商在终端维护时需要针对不同平台的软件版本提供不同的维护&#xff0c;资源造成了极大的浪费。 为响应国家对重特大事件通过视频监控集中调阅来掌…

数字信号处理实验二(模拟信号采样与重构及频谱分析FFT)

模拟信号采样与重构及频谱分析FFT&#xff08;2学时&#xff09; 要求&#xff1a; 对一模拟信号进行采样&#xff1b;对该采样信号进行重构&#xff1b;分析它们的频谱特征。目的&#xff1a; 熟悉MATLAB命令和编辑、运行、调试环境&#xff1b;掌握采样定理及对信号的频谱分析…

springboot高校合同信息管理系统-计算机毕业设计源码02888

摘要 随着高校规模的不断扩大和合作伙伴关系的增加&#xff0c;高校合同管理变得更加复杂和重要。传统的人工合同管理方式已经无法满足高校庞大的合同数量和复杂的合同流程需求。因此&#xff0c;借助信息技术来构建一个高校合同信息管理系统&#xff0c;并结合数据统计功能&am…

【数据分析】评估清理数据实战【淘宝母婴购物数据集】

概述 Ali_Mum_Baby 是一个数据集&#xff0c;其中包含 900 多万条儿童信息&#xff08;生日和性别&#xff09;&#xff0c;这些信息由消费者提供&#xff0c;他们分享这些信息是为了获得更好的推荐或搜索结果。 数据说明 它包含消费者在淘宝或天猫上提供的 9,000,000 多个儿…

新港海岸NCS8822 低功耗DP转VGA 分辨率支持1920*1200*60HZ

NCS8822描述&#xff1a; NCS8822是一个低功耗显示端口到vga转换器。NCS8822集成了一个与DP1.2兼容的接收器和一个高速三通道视频DAC。对于DP1.2输入&#xff0c;NCS8822支持1车道/2车道&#xff0c;也支持车道交换功能。对于VGA输出NCS8822&#xff0c;在60Hz帧率下对WUXGA&a…

【Linux系统】CUDA的安装与graspnet环境配置遇到的问题

今天在安装环境时遇到报错&#xff1a; The detected CUDA version (10.1) mismatches the version that was used to compile PyTorch (11.8). Please make sure to use the same CUDA versions. 报错原因&#xff1a;安装的cuda版本不对应&#xff0c;我需要安装cuda的版本…

西门子PLC1200--与电脑S7通讯

硬件构成 PLC为西门子1211DCDCDC 电脑上位机用PYTHON编写 二者通讯用网线&#xff0c;通讯协议用S7 PLC上的数据 PLC上的数据是2个uint&#xff0c;在DB1&#xff0c;地址偏移分别是0和2 需要注意的是DB块要关闭优化的块访问&#xff0c;否则是没有偏移地址的 PLC中的数据内…

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

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