自定义来电显示

作者: 黑泥卡 | 来源:发表于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();
                }
            }
        };
    

    后续

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

    相关文章

      网友评论

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

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