自定义来电显示

作者: 黑泥卡 | 来源:发表于2017-09-20 16:52 被阅读93次

Android 自定义来电显示

自定义来电显示主要完成两个操作:

  1. 监听来电广播
  2. 使用WindowManager完成来电信息展示

监听来电广播

1. 添加权限

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

2.定义广播接收器

首先要在manifest中注册静态广播

<receiver android:name=".PhoneReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PHONE_STATE" />
    </intent-filter>
</receiver>

自定义广播接收器:

public class PhoneReceiver extends BroadcastReceiver {
    private Context mContext;
    
    @Override
    public void onReceive(Context context, Intent intent) {
        mContext = context;
        //拨打电话
        if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
            final String phoneNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            Log.i("PhoneReceiver", "phoneNum: " + phoneNum);
        } else {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
            tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
        }
    }

    final PhoneStateListener listener = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
                //电话等待接听
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.i("PhoneReceiver", "CALL IN RINGING :" + incomingNumber);
                    PluginUtils.getSqLiteOpenHelperByName("evo_moblie");
                    WindowUtils.showPopupWindow(mContext.getApplicationContext(), incomingNumber);
                    break;
                //电话接听
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.i("PhoneReceiver", "CALL IN ACCEPT :" + incomingNumber);
                    WindowUtils.hidePopupWindow();
                    break;
                //电话挂机
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.i("PhoneReceiver", "CALL IDLE");
                    WindowUtils.hidePopupWindow();
                    break;
            }
        }
    };
}

使用WindowManager完成来电信息展示

自定义展示界面并设置按键监听

public class CallIDView extends RelativeLayout {
    //构造器
    ...
    
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                || event.getKeyCode() == KeyEvent.KEYCODE_SETTINGS) {
            if (mOnKeyListener != null) {
                mOnKeyListener.onKey(this, KeyEvent.KEYCODE_BACK, event);
                return true;
            }
        }
        return super.dispatchKeyEvent(event);
    }

    OnKeyListener mOnKeyListener = null;

    @Override
    public void setOnKeyListener(OnKeyListener l) {
        mOnKeyListener = l;
        super.setOnKeyListener(l);
    }
}

界面 xml:

<com.imagjs.plugin.jsplugin.callerid.CallIDView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:gravity="center">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/textViewPhoneNum"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
            />

        <TextView
            android:id="@+id/textViewPhoneName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="陈大大"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
            />
    </LinearLayout>
</com.imagjs.plugin.jsplugin.callerid.CallIDView>

创建 WindowUtils 类,来管理 Window 的显示和隐藏。

public class WindowUtils {

    private static final String LOG_TAG = "WindowUtils";
    private static View mView = null;
    private static WindowManager mWindowManager = null;
    private static Context mContext = null;
    public static Boolean isShown = false;

    /**
     * 显示弹出框
     *
     * @param context
     */
    public static void showPopupWindow(final Context context, String phoneNum) {
        if (isShown) {
            Log.i(LOG_TAG, "return cause already shown");
            return;
        }

        isShown = true;
        Log.i(LOG_TAG, "showPopupWindow");

        // 获取应用的Context
        mContext = context.getApplicationContext();
        // 获取WindowManager
        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

        mView = setUpView(context, phoneNum);
        //在创建View时注册Receiver
        IntentFilter homeFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        mContext.getApplicationContext().registerReceiver(mHomeListenerReceiver, homeFilter);

        final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        // 类型
        // 设置window type
        params.type = WindowManager.LayoutParams.TYPE_PHONE;
        // 设置flag
        // 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View收不到Back键的事件
        params.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN|WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;;
        // | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        // 不设置这个弹出框的透明遮罩显示为黑色
        params.format = PixelFormat.TRANSLUCENT;
        // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口
        // 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按
        // 不设置这个flag的话,home页的划屏会有问题
        params.width = WindowManager.LayoutParams.MATCH_PARENT;
        params.height = WindowManager.LayoutParams.MATCH_PARENT;
        params.gravity = Gravity.CENTER;
        mWindowManager.addView(mView, params);
        Log.i(LOG_TAG, "add view");
    }

    /**
     * 隐藏弹出框
     */
    private static void hidePopupWindow() {
        Log.i(LOG_TAG, "hide " + isShown + ", " + mView);
        if (isShown && null != mView) {
            Log.i(LOG_TAG, "hidePopupWindow");
            mWindowManager.removeView(mView);
            isShown = false;
            mContext.getApplicationContext().unregisterReceiver(mHomeListenerReceiver);
        }

    }

    private static CallIDView setUpView(final Context context, String phoneNum) {
        CallIDView callIDView = (CallIDView) LayoutInflater.from(context).inflate(R.layout.callid_window_manager, null);
        TextView textViewPhoneNum = callIDView.findViewById(R.id.textViewPhoneNum);
        textViewPhoneNum.setText(phoneNum);
        callIDView.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View view, int i, KeyEvent keyEvent) {
                switch (keyEvent.getKeyCode()) {
                    case KeyEvent.KEYCODE_BACK:
                        hidePopupWindow();
                        return true;
                    default:
                        return false;
                }
            }
        });
        return callIDView;
    }

    //监听home键
    private static BroadcastReceiver mHomeListenerReceiver = new BroadcastReceiver() {
        final String SYSTEM_DIALOG_REASON_KEY = "reason";
        final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
            if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
                    && reason != null && reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                hidePopupWindow();
            }
        }
    };

后续

接下来只要匹配上你的通讯录数据就可以了。

相关文章

  • 自定义来电显示

    Android 自定义来电显示 自定义来电显示主要完成两个操作: 监听来电广播 使用WindowManager完成...

  • 来电显示

    刚刚手机来电,一看来电显示是“市民热线”几个字,我接了这个电话,电话那头传来一位女子甜美的声音,以调查疫情为名,问...

  • 来电显示

    他,不时向门口望过去,显得有些焦燥,快十二点了,还不见她的踪影。 不是为了见她,他不会回到C城。也不会包...

  • 非血缘关系的姐姐

    许久未响动的电话铃声,经过两三秒间飞速接听,看来电显示,是我之前的老板,又被我们默契的自定义为姊妹,或心灵相通的朋...

  • Android开发:自定义来电显示页面,挂断接听

    CompatCallHepler 我适配的是三星盖乐世7.0的手机,应该是和爆炸的同款。 参考这篇博客,挂断好使,...

  • 来电显示监听

  • 【短篇故事】来电显示

    分手后还可以做朋友吗?曾经爱得死去活来一杯果汁都要两人喝,分手时恨得不共戴天怀疑是不是喝了过期饮料。爱的时候是老房...

  • 三星S7/S7e接不到电话解决方法

    中午点了外卖,外卖小哥说打不通电话,我用自己电话试了试,能打通但是没有来电显示 重启,依然没有来电显示 我的卡是移...

  • 和家人一起的感觉不一样

    随着沙漠骆驼响起,来电显示提醒着家里来电了。

  • 苦难是本涂鸦——来电显示

    窗外一片枯黄的树叶随着凉凉的风飘下,忘记关掉的窗户,让屋子里飘进了不少的枯叶。 习惯性的摸出手机看...

网友评论

    本文标题:自定义来电显示

    本文链接:https://www.haomeiwen.com/subject/xmmosxtx.html