android - 接听电话或电话停止响铃时关闭 Android 上的自定义来电屏幕

标签 android phone-call android-windowmanager

我想要一个自定义的来电屏幕,当有来电时显示,并在接听电话或电话停止响铃时关闭。

我已经在 Stackoverflow 上搜索了几篇文章,向我展示了如何实现它,到目前为止,我已经快完成了,在检查了每种方法在屏幕显示速度方面的优缺点后,我已经解决了关于 WindowManager 方法。

每当我调用 wm.removeView(ly) 时,我都会得到下面的堆栈

07-08 20:36:41.002  27547-27547/com.testtelephoney.customincomingcall E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.testtelephoney.customincomingcall, PID: 27547
java.lang.IllegalArgumentException: View=android.widget.LinearLayout{7e63aae V.E..... ......I. 0,0-0,0} not attached to window manager
        at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:402)
        at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:328)
        at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
        at com.testtelephoney.customincomingcall.MyPhoneStateListener.onCallStateChanged(MyPhoneStateListener.java:43)
        at android.telephony.PhoneStateListener$2.handleMessage(PhoneStateListener.java:392)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:145)
        at android.app.ActivityThread.main(ActivityThread.java:5832)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)

这是我的代码:

MyPhoneStateListener.java

import android.content.Context;
import android.graphics.PixelFormat;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;


public class MyPhoneStateListener extends PhoneStateListener{
    Context mContext;
    public MyPhoneStateListener(Context ct) {
        mContext = ct;
    }
    public void onCallStateChanged(int state,String incomingNumber){

        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT|WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);

        params.height= WindowManager.LayoutParams.MATCH_PARENT;
        params.width= WindowManager.LayoutParams.MATCH_PARENT;
        params.format=PixelFormat.TRANSPARENT;
        params.gravity= Gravity.TOP;

        LinearLayout ly;

        final LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ly=(LinearLayout)inflater.inflate(R.layout.activity_ic,null);


        switch (state){
            case TelephonyManager.CALL_STATE_IDLE:
                Log.d("DEBUG","IDLE");
                if(ly.getVisibility()== View.VISIBLE){
                    wm.removeView(ly);
                }
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.d("DEBUG","OFFHOOK");
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                Log.d("DEBUG","RINGING");
                wm.addView(ly,params);
                break;
        }
    }
}

服务接收者

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class ServiceReceiver extends BroadcastReceiver {
    public ServiceReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        MyPhoneStateListener phoneListener = new MyPhoneStateListener(context);
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
    }
}

AndroidManifest

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <receiver android:name=".ServiceReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
     </receiver>

最佳答案

我添加了一个标志来标记 View 已添加。当然,它确实需要改进。

 switch (state){
        case TelephonyManager.CALL_STATE_IDLE:
            Log.d("DEBUG","IDLE");
            if (viewCreated) {
                wm.removeView(ly);
                viewCreated = false;
            }
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:
            Log.d("DEBUG","OFFHOOK");
            break;
        case TelephonyManager.CALL_STATE_RINGING:
            Log.d("DEBUG","RINGING");
            if (!viewCreated){
                WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT|WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
                params.height= WindowManager.LayoutParams.MATCH_PARENT;
                params.width= WindowManager.LayoutParams.MATCH_PARENT;
                params.format=PixelFormat.TRANSPARENT;
                params.gravity= Gravity.TOP;

                ly=(LinearLayout)inflater.inflate(R.layout.activity_login,null);
                wm.addView(ly, params);
                viewCreated=true;
            }
            break;
    }

关于android - 接听电话或电话停止响铃时关闭 Android 上的自定义来电屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31302883/

相关文章:

java - 可以使用 java 读取来电吗?

android - 如何更改应用程序中使用的默认键盘的背景颜色?

android - 我们如何使用密码在 Android 中播放私有(private) Youtube 视频?

Android 拨号器应用程序

c# - WP 8.1 运行时代码,用于调用电话、发送短信和发送电子邮件(不是 Silverlight 8.1)

Android:使用动画移动位于窗口管理器上的 imageView

android - 窗口类型 2038 的权限被拒绝

java - 在 arrayadapter 中交换数据时从 Binder stub 实现中捕获 RuntimeException

android - 如何在Android中将 double 转换为货币格式

android - 是否有任何 Sqlite select 查询来获取两个表结果?