Android 使用BroadcastReceiver来监听手机来电

这篇具有很好参考价值的文章主要介绍了Android 使用BroadcastReceiver来监听手机来电。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、需求背景

客户在使用我公司的Flutter插件时,硬是要我们搞一个来电通知的功能,就很无语,我找了Flutter的一些插件,发现没有一个能实现这个功能的,最后只能通过Android来实现,我这个前端承受了不该承受的。

二、实现步骤

1. 添加权限

2. 创建一个类来继承BroadcastReceiver

3. 动态注册和注销广播

4. 检测电话状态,获取电话号码

5. 封装一个获取手机通讯录的方法

6. 判断通讯录中是否包含该电话号码,有就返回备注名称,否则返回电话号码

三、代码分享

1. 注册权限

在 AndroidManifest.xml 文件中添加权限,可能不需要这么多的权限,但是我为了以防万一还是加了这么多。

    <!--监听电话状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>

    <uses-permission android:name="android.permission.READ_CALL_LOG" />

    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.CALL_PHONE" />

2. 创建一个类来继承BroadcastReceiver

public class PhoneStateReceiver extends BroadcastReceiver {

    private static final String PHONE_STATE_RECEIVED = "android.intent.action.PHONE_STATE";
    private static int previousState = TelephonyManager.CALL_STATE_IDLE;

    private static PhoneStateReceiver receiver = new PhoneStateReceiver();

    /**
     * 注册
     *
     * @param context
     */
    public static void register(Context context) {
        IntentFilter filter = new IntentFilter();
        filter.setPriority(Integer.MAX_VALUE);
        filter.addAction(PHONE_STATE_RECEIVED);
        context.registerReceiver(receiver, filter);
    }

    /**
     * 注销
     *
     * @param context
     */
    public static void unregister(Context context) {
        context.unregisterReceiver(receiver);
    }

    @Override
    public void onReceive(final Context context, Intent intent) {
        // 来电处理逻辑
    }
}

 3. 动态注册和注销广播

我这里是在 ActivityAware 的生命周期中注册的,你可以根据实际情况进行注册,只要在应用运行时注册就行。

public class MoyoungBlePlugin implements ActivityAware {
    
    private Activity activity;

    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        activity = binding.getActivity();

        // 注册广播
        PhoneStateReceiver.register(activity);
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {
    }

    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
    }

    @Override
    public void onDetachedFromActivity() {
        // 注销广播
        PhoneStateReceiver.unregister(activity);
        activity = null;
    }

}

 4. 检测电话状态,获取电话号码

public class PhoneStateReceiver extends BroadcastReceiver {


    @Override
    public void onReceive(final Context context, Intent intent) {
        checkPhoneState(context, intent);
    }

    /**
     * 检测电话状态
     *
     * @param context
     * @param intent
     */
    private synchronized void checkPhoneState(Context context, Intent intent) {
        TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Service.TELEPHONY_SERVICE);
        int callState = telephonyManager.getCallState();
        Log.i(PhoneStateReceiver.class.getName(), "callState: " + callState);
        switch (callState) {
            case TelephonyManager.CALL_STATE_RINGING:   // 电话进来时
                // 获取电话号码
                String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                IncomingNumberManager.getInstance().sendIncomingNumber(context, incomingNumber);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:   // 接起电话时
                Log.i("checkPhoneState", "接电话");
                break;
            case TelephonyManager.CALL_STATE_IDLE:      //无任何状态时
                Log.i("checkPhoneState", "无任何状态");
                break;
        }
    }

}

5. 封装一个获取手机通讯录的方法

public class ContactUtils {

    private ContactUtils() {
    }

    /**
     * 通过号码查询联系人名字
     *
     * @param context
     * @param number
     * @return
     */
    public static String getContactName(Context context, String number) {
        // 判断是否有通讯录权限
        if (!hasSelfPermissions(context, Manifest.permission.READ_CONTACTS)) {
            return number;
        }

        if (TextUtils.isEmpty(number)) {
            return null;
        }

        final ContentResolver resolver = context.getContentResolver();

        Uri lookupUri;
        String[] projection = new String[]{ContactsContract.PhoneLookup._ID,
                ContactsContract.PhoneLookup.DISPLAY_NAME};
        Cursor cursor = null;
        try {
            lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                    Uri.encode(number));
            cursor = resolver.query(lookupUri, projection, null, null, null);
        } catch (Exception ex) {
            ex.printStackTrace();
            try {
                lookupUri = Uri.withAppendedPath(
                        android.provider.Contacts.Phones.CONTENT_FILTER_URL,
                        Uri.encode(number));
                cursor = resolver.query(lookupUri, projection, null, null, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        String ret = null;
        if (cursor != null && cursor.moveToFirst()) {
            ret = cursor.getString(1);
            cursor.close();
        }

        return ret;
    }

    public static boolean hasSelfPermissions(Context context, String... permissions) {
        for (String permission : permissions) {
            if (permissionExists(permission) && !hasSelfPermission(context, permission)) {
                return false;
            }
        }
        return true;
    }

    private static boolean permissionExists(String permission) {
        // Check if the permission could potentially be missing on this device
        Integer minVersion = MIN_SDK_PERMISSIONS.get(permission);
        // If null was returned from the above call, there is no need for a device API level check for the permission;
        // otherwise, we check if its minimum API level requirement is met
        return minVersion == null || Build.VERSION.SDK_INT >= minVersion;
    }

    @SuppressLint("WrongConstant")
    private static boolean hasSelfPermission(Context context, String permission) {
        try {
            if (permission.equals(PERMISSION_UPDATE_BAND_CONFIG[0])) {//android 11需要单独判断存储权限
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {//30 android 11
                    return Environment.isExternalStorageManager();
                }
            }

            return PermissionChecker.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
        } catch (RuntimeException t) {
            return false;
        }
    }

}

6. 判断通讯录中是否包含该电话号码,有就返回备注名称,否则返回电话号码

public class IncomingNumberManager {

    private IncomingNumberManager() {
    }

    public static IncomingNumberManager getInstance() {
        return Holder.INSTANCE;
    }

    private static class Holder {
        private static final IncomingNumberManager INSTANCE = new IncomingNumberManager();
    }

    /**
     * 来电号码
     *
     * @param context
     * @param number
     */
    public void sendIncomingNumber(Context context, final String number) {
        if (TextUtils.isEmpty(number)) {
            return;
        }

        String contactName = null;
        try {
            contactName = ContactUtils.getContactName(context, number);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (!TextUtils.isEmpty(contactName)) {
            // 如果通讯录中有该电话号码的逻辑
        } else {
            // 如果没有该电话号码的逻辑
        }
    }


    /**
     * 挂断电话
     */
    public void endCall() {
        // 挂断电话的逻辑
    }
}

注意:在使用时,必须要开启应用的电话、 联系人和通话记录权限,否则监听不到。

四、参考文案

android 拨打电话、 监听来电、监听呼出电话的功能实现_安卓 监控拨号呼出_Mars-xq的博客-CSDN博客

Android读取联系人的姓名及电话号码_android上述系统联系人数据库的相关信息,编写一个程序,用于读取系统联系人的姓名_NULL____的博客-CSDN博客

Android获取通讯录 - 简书文章来源地址https://www.toymoban.com/news/detail-779741.html

到了这里,关于Android 使用BroadcastReceiver来监听手机来电的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手机来电显示私密号码怎么回事?

      手机来电显示私密号码是很多用户经常遇到的问题,那么手机来电显示私密号码怎么回事呢? 原因 手机来电显示私密号码一般有以下几种原因: 对方使用了网络电话或开通了隐藏号码服务。网络电话是一种通过互联网进行通话的服务,一般情况下,网络电话不会显示来电

    2024年02月05日
    浏览(157)
  • unity监听手机自带截屏(Android)

    参考 Unity监听手机自带截屏(支持Android10及以上) - 简书 Unity实现监听手机自带的截屏事件的实现,首先从Android获取到手机截图的图片路径,在通过Android将路径传给Unity,Unity再根据路径加载截屏的图片。 An... https://www.jianshu.com/p/67af95458679 发现cursor数据一直为空,最后发现

    2024年02月11日
    浏览(31)
  • Android之 BroadcastReceiver广播接收器详解

    一 四大组件 1.1 Activity组件,它一个单独的窗口,程序流程都必须在Activity中运行。 1.2 service组件,用于在后台完成用户指定的操作。 1.3 content provider组件,会为所有的应用准备一个内容窗口,并且保留数据库、文件。 1.4 broadcast receiver组件,是程序之间传递信息时的一种机制

    2024年02月06日
    浏览(32)
  • 苹果手机怎么设置来电铃声?4个步骤,快速学会

    相信有不少的小伙伴使用的手机是苹果手机。苹果手机虽然好用,但是每次来电的铃声都太过吵闹,有的小伙伴想要换一个苹果手机的来电铃声,却不知道应该怎么设置。苹果手机怎么设置来电铃声?本篇文章,小编将会以图文教学的方式,详细的教大家如何设置苹果手机来

    2024年02月11日
    浏览(29)
  • 手机开启这项功能,来电时自动播报对方姓名和号码,便捷实用

    随着智能手机的普及,我们的生活变得越来越便捷。然而,当我们正在忙碌或者手头没有手机时,突然来了一个电话,我们可能会错过重要的电话或者在不方便接听的情况下错失机会。但是,如果你开启了来电语音报号和姓名功能,手机会在来电时自动播报来电者的名字和号

    2024年04月28日
    浏览(107)
  • 简单步骤:Android studio 内容提供者 - 实现建立手机通讯录界面,读取系统联系人

    提示:本篇文章将会尽量保持精简,同时请诸位敲写代码时保持耐心,三连是最大的支持! 文章目录 前言 一、项目介绍 二、使用步骤 1.创建程序 2.添加 recyclerview-v7 库 3.放置界面控件 4.搭建界面布局 5.封装实体类 6.编写数据适配器 7.实现显示界面数据功能 8.去掉默认标题栏

    2024年02月08日
    浏览(37)
  • android自定义来电秀UI

    简单来电秀功能,效果如图: 底部附上demo  一、新建一个 PhoneCallService服务,在服务中监听来电等状态,且控制UI显示 二、在MainActivity中设置应用为默认来电主题,与权限设置 三、增加一个来电展示的自定义UI页面PhoneCallActivity,可根据需求更改 四、来电页面UI中布局文件

    2024年01月15日
    浏览(31)
  • Android App开发手机阅读中实现平滑翻书效果和卷曲翻书动画实战(附源码 简单易懂 可直接使用)

    需要图片集和源码请点赞关注收藏后评论区留言~~~ 与纸质书籍类似,手机上的电子书也有很多页,逐页浏览可采用翻页视图,然而翻页视图犹如一幅从左到右的绵长画卷,与现实生活中上下层叠的书籍并不相像,若想让手机电子书更贴近纸质书的阅读体验,就需要重新设计上

    2024年02月16日
    浏览(31)
  • Android Socket使用TCP协议实现手机投屏

    本节主要通过实战来了解Socket在TCP/IP协议中充当的是一个什么角色,有什么作用。通过Socket使用TCP协议实现局域网内手机A充当服务端,手机B充当客户端,手机B连接手机A,手机A获取屏幕数据转化为Bitmap,通过Socket传递个手机B显示。 实现效果: Socket 是应用层与TCP/IP协议族通

    2024年02月13日
    浏览(32)
  • 利用Api接口实现手机网络连接断开的监听

    在今天的移动互联网时代,手机已经成为了人们不可或缺的重要工具,而手机的联网状态也是我们经常需要关注的一个问题。我们需要保证手机网络处于正常的连接状态,但是有时候,由于种种原因,手机的网络可能会断开,这时我们需要及时发现,并进行相应的处理措施。

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包