驳回Android上的自定义来电屏幕时,电话被接听或电话停止振铃 [英] Dismissing a custom incoming call screen on Android when the call is answered or the phone stops ringing

查看:398
本文介绍了驳回Android上的自定义来电屏幕时,电话被接听或电话停止振铃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想有一个自定义来电屏幕,显示了当有来电时,如果呼叫被应答或得到驳回了电话停止振铃。

我搜索#2几个职位给我看​​我如何可以实现,到目前为止,我几乎没有和屏幕被如何快速显示方面检查每一种方法的利弊后,我已经谈妥在窗口管理器的方法。

每当我称之为 wm.removeView(LY)我得到以下

堆栈

  20 07-08:36:41.002 27547-27547 / com.testtelephoney.customincomingcall E / AndroidRuntime:致命异常:主要
工艺:com.testtelephoney.customincomingcall,PID:27547
java.lang.IllegalArgumentException异常:查看= {android.widget.LinearLayout 7e63aae V.E ..... ......我。 0,0-0,0}不附着于窗口管理
        在android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:402)
        在android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:328)
        在android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:84)
        在com.testtelephoney.customincomingcall.MyPhoneStateListener.onCallStateChanged(MyPhoneStateListener.java:43)
        在android.telephony.PhoneStateListener $ 2.handleMessage(PhoneStateListener.java:392)
        在android.os.Handler.dispatchMessage(Handler.java:102)
        在android.os.Looper.loop(Looper.java:145)
        在android.app.ActivityThread.main(ActivityThread.java:5832)
        在java.lang.reflect.Method.invoke(本机方法)
        在java.lang.reflect.Method.invoke(Method.java:372)
        在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:1399)

下面是我的code:

MyPhoneStateListener.java

 进口android.content.Context;
进口android.graphics.PixelFormat;
进口android.telephony.PhoneStateListener;
进口android.telephony.TelephonyManager;
进口android.util.Log;
进口android.view.Gravity;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.WindowManager;
进口android.widget.LinearLayout;
进口android.widget.RelativeLayout;
公共类MyPhoneStateListener扩展PhoneStateListener {
    上下文mContext;
    公共MyPhoneStateListener(上下文CT){
        mContext =克拉;
    }
    公共无效onCallStateChanged(INT状态,弦乐incomingNumber){        窗口管理WM =(窗口管理器)mContext.getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams PARAMS =新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;        最后LayoutInflater吹气=(LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LY =(的LinearLayout)inflater.inflate(R.layout.activity_ic,NULL);
        开关(州){
            案例TelephonyManager.CALL_STATE_IDLE:
                Log.d(调试,空闲);
                如果(ly.getVisibility()== View.VISIBLE){
                    wm.removeView(LY);
                }
                打破;
            案例TelephonyManager.CALL_STATE_OFFHOOK:
                Log.d(调试,摘机);
                打破;
            案例TelephonyManager.CALL_STATE_RINGING:
                Log.d(调试,振铃);
                wm.addView(LY,则params);
                打破;
        }
    }
}

ServiceReceiver

 进口android.content.BroadcastReceiver;
进口android.content.Context;
进口android.content.Intent;
进口android.telephony.PhoneStateListener;
进口android.telephony.TelephonyManager;公共类ServiceReceiver扩展广播接收器{
    公共ServiceReceiver(){
    }    @覆盖
    公共无效的onReceive(上下文的背景下,意图意图){
        // TODO:当广播接收器接收这种方法被称为
        //一个Intent广播。
        MyPhoneStateListener phoneListener =新MyPhoneStateListener(背景);
        TelephonyManager电话=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
    }
}

AndroidManifest

 <使用许可权的android:NAME =android.permission.GET_ACCOUNTS/>
    <使用许可权的android:NAME =android.permission.READ_PROFILE/>
    <使用许可权的android:NAME =android.permission.READ_CONTACTS/>
    <使用许可权的android:NAME =android.permission.SYSTEM_ALERT_WINDOW/>
    <接收机器人:名字=。ServiceReceiver>
            &所述;意图滤光器>
                <作用机器人:名字=android.intent.action.PHONE_STATE/>
            &所述; /意图滤光器>
     < /接收器>


解决方案

我添加了一个标志,以纪念该视图已被添加。它确实需要关闭过程改进。

 开关(州){
        案例TelephonyManager.CALL_STATE_IDLE:
            Log.d(调试,空闲);
            如果(viewCreated){
                wm.removeView(LY);
                viewCreated = FALSE;
            }
            打破;
        案例TelephonyManager.CALL_STATE_OFFHOOK:
            Log.d(调试,摘机);
            打破;
        案例TelephonyManager.CALL_STATE_RINGING:
            Log.d(调试,振铃);
            如果(!viewCreated){
                WindowManager.LayoutParams PARAMS =新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;
            }
            打破;
    }

I want to have a custom incoming call screen that shows up when there is an incoming call, and get dismissed if the call is answered or the phone stops ringing.

I've searched several posts on Stackoverflow to show me how can I implement that, and so far I am nearly there and after checking pros and cons of each approach in terms of how fast the screen gets shown, I've settled on the WindowManager approach.

Whenever I call wm.removeView(ly) I get the stack below

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)

Here is my code:

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;
        }
    }
}

ServiceReceiver

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>

解决方案

I've added a flag to mark that the view has been added. It does need to be improved off course.

 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上的自定义来电屏幕时,电话被接听或电话停止振铃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆