在Android本机来电屏幕上popup窗口,如真正的来电者Android应用程序

更新 – 2013年5月9日 *我尝试在广播接收器的onReceive方法中实现Toast,因为Toast是Android的本地组件,但它也不会在Android 4.1(Jelly Bean)中显示。

我的想法是在广播接收机的onReceive方法中实现Toast,然后根据我们的需要改变它的devise并调整它的显示持续时间。 但还有一个问题是, findViewById在广播接收器中不起作用,所以我认为我们必须编程一个LinearLayout来定制Toast。

更新奖金后,我还没有得到确切的东西,我正在寻找,但我会回到所有; 我正在努力。 无论如何,这个代码适用于大多数Android手机。 如果有人打算用它来解决这个问题,请写在这里,让大家都能从中受益。 感谢您的答复。

我正在开发一个广播接收器,用于在Android中接听来电,并且接收来电,我想在本地来电屏幕上popup一个popup窗口。

我完成了这个代码。 但现在的问题是,在Android 4.1(Jelly Bean)API级别17中,当手机响起时, PHONE_STATE将作为OFF HOOK ,如果我正在调用某个活动,则会被调用,但其下的代码不会得到执行。 我列出的代码:

我的广播接收器

 package com.example.popwindowonincomingcallscreen; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.TelephonyManager; import android.util.Log; public class IncomingBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.d("IncomingBroadcastReceiver: onReceive: ", "flag1"); String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); Log.d("IncomingBroadcastReceiver: onReceive: ", state); if (state.equals(TelephonyManager.EXTRA_STATE_RINGING) || state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { Log.d("Ringing", "Phone is ringing"); Intent i = new Intent(context, IncomingCallActivity.class); i.putExtras(intent); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); Wait.oneSec(); context.startActivity(i); } } } 

我所呼吁的活动是:

 import android.app.Activity; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; import android.view.View.MeasureSpec; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; public class IncomingCallActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { try { Log.d("IncomingCallActivity: onCreate: ", "flag2"); */ After this line, the code is not executed in Android 4.1 (Jelly Bean) only/* // TODO Auto-generated method stub super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); getWindow().addFlags( WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); Log.d("IncomingCallActivity: onCreate: ", "flagy"); setContentView(R.layout.main); Log.d("IncomingCallActivity: onCreate: ", "flagz"); String number = getIntent().getStringExtra( TelephonyManager.EXTRA_INCOMING_NUMBER); TextView text = (TextView) findViewById(R.id.text); text.setText("Incoming call from " + number); } catch (Exception e) { Log.d("Exception", e.toString()); // TODO Auto-generated catch block e.printStackTrace(); } } } 

 try { Log.d("IncomingCallActivity: onCreate: ", "flag2"); } 

该代码不是在Android 4.1(果冻豆)执行,但在其他版本,它正在工作。

我尝试了几乎所有我能做的事情。 此代码在原生通话屏幕上显示半透明的活动,并且不会阻止后台控件,如拿起手机。 但是我想要它像真正的来电者。 我附上了一个快照,说明真正的来电者在来电屏幕上如何显示一个窗口。

我怎样才能实现Android应用程序的这个function?

这是一个真正的来电者如何工作:

在这里输入图像说明

我现在的输出:

在这里输入图像说明

我不知道你的自定义的graphics用户界面将总是在默认的GUI上,因为系统广播接收器和你的接收器都试图在屏幕上显示它的GUI。 我们不确定哪一个是第一个被调用的,但是让屏幕顶部的GUI成为一个棘手的工作就是当手机响了1-2秒钟之后调用你的活动。

 new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Intent intent = new Intent(context, AcceptReject.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } }, 2000); 

我希望它可以帮助你。

尝试super.onCreate方法之前的代码。 我想在调用super之后,代码被跳过了。 有时这种技巧为我工作。

我刚刚在Android 4.2(Jelly Bean)模拟器上testing过,它可以通过像truecaller一样阻塞整个来电屏幕来完美工作:

 public void onReceive(Context context, Intent intent) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams params = new WindowManager.LayoutParams( LayoutParams.MATCH_PARENT, 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 = LayoutParams.MATCH_PARENT; params.width = LayoutParams.MATCH_PARENT; params.format = PixelFormat.TRANSLUCENT; params.gravity = Gravity.TOP; LinearLayout ly = new LinearLayout(context); ly.setBackgroundColor(Color.RED); ly.setOrientation(LinearLayout.VERTICAL); wm.addView(ly, params); } 

在清单中:

 <receiver android:name="" android:enabled="true" > <intent-filter android:priority="-1"> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver> 

我正在尝试类似的方法,在来电屏幕上添加一个额外的button。

虽然我从PhoneStateListener调用代码,但是Sam Adams发布的答案正在为我工​​作。 除此之外,他的代码唯一真正的区别是我膨胀的布局:

 overlay = (RelativeLayout) inflater.inflate(R.layout.overlay, null); wm.addView(overlay, params); 

它正在模拟器以及HTC One S(运行Android 4.1.1)上工作。

你需要记住的是保持对你要添加的覆盖视图的引用,并且当电话回到空闲状态(当监听器获得TelephonyManager.CALL_STATE_IDLE时),再次移除它(在windowmanager实例上调用removeView()),否则你的覆盖将保持在屏幕上。

  WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if(overlay!=null) { wm.removeView(overlay); overlay = null; } 

我认为你不应该开始活动来达到所描述的结果。 您需要在其布局参数中设置LayoutParams.TYPE_SYSTEM_OVERLAY的单独视图。

您可以将该视图放置在屏幕上的任何位置,或者只是覆盖整个屏幕。

这里有几行代码:

  _av = new ActivatorView(this); _avLayoutParams = new WindowManager.LayoutParams(0, 0, 0, 0, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.OPAQUE); _avLayoutParams.screenBrightness = _fScreenBrightness = 20f; WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); wm.addView(_av, _avLayoutParams); 

https://bitbucket.org/gyrussolutions/yaab/src/f01cc8aff690cae1b1107287cb17835b8a3c1643/src/biz/gyrus/yaab/LightMonitorService.java?at=default#cl-338 – 完整的源代码,请考虑它的一个示例。

我也在研究它(我可能在这里理解你是错的)。 你想要实现的是在Android 4.2(果冻豆)中显示该活动。 我只是延迟显示活动。 我在不同的类中使用PhoneStateListener。 我可以在来电者屏幕上显示新的活动。 这是我的完整代码:

在这里输入图像说明

文件MyBroadcastReceiver.java

 public class MyBroadcastReceiver extends BroadcastReceiver { static CustomPhoneStateListener phoneStateListener; Context context; Intent intent; @Override public void onReceive(Context context, Intent intent) { this.context = context; this.intent = intent; // TODO Auto-generated method stub TelephonyManager telephonyManager = (TelephonyManager) context .getSystemService(Context.TELEPHONY_SERVICE); phoneStateListener = new CustomPhoneStateListener(context); telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); } } 

文件CustomPhoneStateListener.java

 public class CustomPhoneStateListener extends PhoneStateListener { // private static final String TAG = "PhoneStateChanged"; Context context; // Context to make Toast if required private AudioManager amanager; Intent i1; public CustomPhoneStateListener(Context context) { super(); this.context = context; i1 = new Intent(context, YourActivity.class); i1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); } @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: Toast.makeText(context, "Phone state Idle", Toast.LENGTH_LONG) .show(); break; case TelephonyManager.CALL_STATE_OFFHOOK: Toast.makeText(context, "Phone state Off hook", Toast.LENGTH_LONG) .show(); break; case TelephonyManager.CALL_STATE_RINGING: try { Thread.sleep(3000); context.startActivity(i1); } catch (Exception e) { e.getLocalizedMessage(); } default: break; } } 

和YourActivity将保持你创build的…注意:我也遇到了一些问题,他们在这里的代码也在这里。

  1. 当呼叫closures时(未接电话或拒绝),活动未被closures。
  2. 我不能点击活动(我想把一个button在那里为我的应用程序)
  3. 这只是第一次。 当我第二次打电话时,我的应用程序停止(我认为这是因为打电话被解雇时活动没有closures)

(帮助接受这些问题,谢谢,可以帮助一下)

UPDATE

这里是小演示的链接如何实现这一点。

  1. 当呼叫closures时(未接电话或拒绝),活动未被closures。 – 解决了
  2. 我无法点击活动(我想把一个button在那里为我的应用程序) – 解决
  3. 这只是第一次。 当我第二次打电话,我的应用程序停止(我认为这是因为活动没有被closures,当电话被解雇) – 已解决

我的方法:

  1. 使用接收器接收电话事件
  2. 使用服务进行覆盖

     ps:wmParams.type = WindowManager.LayoutParams.TYPE_PHONE; 

我们也遇到类似的问题,覆盖没有显示在一个设备上的引脚locking。 为我们工作的解决scheme如下:

 mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); mParams = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_SYSTEM_ERROR, LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT); 

这是造成差异的LayoutParams.TYPE_SYSTEM_ERROR

 new Handler().postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Intent i = new Intent(context, CallingIncoming.class); i.putExtras(intent); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK /*| Intent.FLAG_ACTIVITY_CLEAR_TASK*/); context.startActivity(i); } }, 450);//It will help you to delay your screen and after it your screen will be top of default app screen 

使用一个简单的广播接收机,并将此代码放入广播接收机:

 public void onReceive(final Context context, final Intent intent) { Log.v(LOG_TAG, "Receieved notification about network status"); WindowManager wm = (WindowManager) context.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.TRANSLUCENT; params.gravity = Gravity.TOP; LinearLayout ly = new LinearLayout(context); ly.setBackgroundColor(Color.RED); ly.setOrientation(LinearLayout.VERTICAL); wm.addView(ly, params); }