2015-07-08 1 views
1

Я хочу иметь пользовательский экран входящих вызовов, который отображается, когда есть входящий звонок, и увольняться, если на вызов отвечает, или телефон перестает звонить.Отклонение пользовательского экрана входящих вызовов на Android при ответе на вызов или прекращении звонка телефона

Я искал несколько сообщений в 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; 
     } 
    } 
} 

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> 

ответ

1

Я добавил флаг, чтобы отметить, что представление было добавлено. Это нужно улучшить с курса.

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

LY является локальной переменной. Вы создаете новый каждый раз, когда вызывается onCallStateChanged. Вам нужно сохранить макет, который вы добавили в диспетчер окон, в переменной уровня класса, чтобы вы могли удалить экземпляр созданного вами макета, а не только что созданный экземпляр.

+0

Я поместил wm и ly как переменные статического класса и созданный экземпляр wm в конструкторе, но та же проблема все еще существует :( – m4r0ck

Смежные вопросы