我希望在电话响铃时打开我的自定义布局屏幕。我的 PhonecallReceiver 是
public class PhonecallReceiver extends BroadcastReceiver {
// The receiver will be recreated whenever android feels like it. We need a // static variable to remember data between instantiations Class<?> telephonyClass; Class<?> telephonyStubClass; Class<?> serviceManagerClass; Class<?> serviceManagerNativeClass; Method telephonyEndCall; Object telephonyObject; Object serviceManagerObject; private static int lastState = TelephonyManager.CALL_STATE_IDLE; private static Date callStartTime; private static boolean isIncoming; private static String savedNumber; // because the passed incoming is only
// valid in ringing
@Override public void onReceive(Context context, Intent intent) {
// We listen to two intents. The new outgoing call only tells us of an // outgoing call. We use it to get the number. if (intent.getAction()
.equals("android.intent.action.NEW_OUTGOING_CALL")) { savedNumber = intent.getExtras().getString(
"android.intent.extra.PHONE_NUMBER"); } else { String stateStr = intent.getExtras().getString(
TelephonyManager.EXTRA_STATE); String number = intent.getExtras().getString(
TelephonyManager.EXTRA_INCOMING_NUMBER); int state = 0; if (stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
state = TelephonyManager.CALL_STATE_IDLE; } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
state = TelephonyManager.CALL_STATE_OFFHOOK; } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
state = TelephonyManager.CALL_STATE_RINGING; }
onCallStateChanged(context, state, number); } }
// Derived classes should override these to respond to specific events of // interest protected void onIncomingCallStarted(Context ctx, String number, Date start) { Intent callIntent = new Intent(ctx, TaskBarView.class); callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ctx.startActivity(callIntent); System.out.println("=== onIncomingCallStarted"); }
protected void onOutgoingCallStarted(Context ctx, String number, Date start) { System.out.println("=== onOutgoingCallStarted"); }
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
System.out.println("=== onIncomingCallEnded"); }
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) { System.out.println("=== onOutgoingCallEnded"); }
protected void onMissedCall(Context ctx, String number, Date start) { System.out.println("=== onMissedCall"); }
// Deals with actual events
// Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when // it's answered, to IDLE when its hung up // Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when // hung up public void onCallStateChanged(Context context, int state, String number) { if (lastState == state) { // No change, debounce extras return; } switch (state) { case TelephonyManager.CALL_STATE_RINGING: isIncoming = true; callStartTime = new Date(); savedNumber = number; onIncomingCallStarted(context, number, callStartTime); break; case TelephonyManager.CALL_STATE_OFFHOOK: // Transition of ringing->offhook are pickups of incoming calls. // Nothing done on them if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime); } break; case TelephonyManager.CALL_STATE_IDLE: // Went to idle- this is the end of a call. What type depends on // previous state(s) if (lastState == TelephonyManager.CALL_STATE_RINGING) {
// Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime); } else if (isIncoming) {
onIncomingCallEnded(context, savedNumber, callStartTime,
new Date()); } else {
onOutgoingCallEnded(context, savedNumber, callStartTime,
new Date()); } break; } lastState = state; } }
当CALL_STATE_RINGING时,我只需打开TaskBarView Activity
public class TaskBarView extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent svc = new Intent(this, HUD.class);
startService(svc);
finish();
}
@Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
stopService(new Intent(this,HUD.class));
} }
然后我也使用服务来使用WindowManager绘制我的视图
public class HUD extends Service { View myView; Class<?> telephonyClass; Class<?> telephonyStubClass; Class<?> serviceManagerClass; Class<?> serviceManagerNativeClass; Method telephonyEndCall; Object telephonyObject; Object serviceManagerObject;
@Override public IBinder onBind(Intent intent) { return null; }
@Override public void onCreate() { super.onCreate(); Toast.makeText(getBaseContext(), "onCreate", Toast.LENGTH_LONG).show(); WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); myView = inflater.inflate(R.layout.activity_main, null);
Button btnClick = (Button) myView.findViewById(R.id.button1);
btnClick.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) {
disconnectCall();
return true; } });
// Add layout to window manager wm.addView(myView, params); }
public void disconnectCall() { try {
String serviceManagerName = "android.os.ServiceManager"; String serviceManagerNativeName = "android.os.ServiceManagerNative"; String telephonyName = "com.android.internal.telephony.ITelephony"; telephonyClass = Class.forName(telephonyName); telephonyStubClass = telephonyClass.getClasses()[0]; serviceManagerClass = Class.forName(serviceManagerName); serviceManagerNativeClass = Class.forName(serviceManagerNativeName); Method getService = // getDefaults[29]; serviceManagerClass.getMethod("getService", String.class); Method tempInterfaceMethod = serviceManagerNativeClass.getMethod(
"asInterface", IBinder.class); Binder tmpBinder = new Binder(); tmpBinder.attachInterface(null, "fake"); serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder); IBinder retbinder = (IBinder) getService.invoke(
serviceManagerObject, "phone"); Method serviceMethod = telephonyStubClass.getMethod("asInterface",
IBinder.class); telephonyObject = serviceMethod.invoke(null, retbinder); telephonyEndCall = telephonyClass.getMethod("endCall"); telephonyEndCall.invoke(telephonyObject); clearView();
} catch (Exception e) { e.printStackTrace(); } }
@Override public void onDestroy() { super.onDestroy(); clearView(); }
private void showCalllog(Context ctx) { // TODO Auto-generated method stub Intent showCallLog = new Intent(); showCallLog.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); showCallLog.setAction(Intent.ACTION_VIEW); showCallLog.setType(CallLog.Calls.CONTENT_TYPE); ctx.startActivity(showCallLog); } private void clearView() { Toast.makeText(getBaseContext(), "onDestroy", Toast.LENGTH_LONG).show(); if (myView != null) { ((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(myView); myView = null; //showCalllog(getApplicationContext()); } } }
我的manifest.xml文件是
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hdcallerid"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.hdcallerid.TaskBarView"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<intent-filter>
<action android:name="android.intent.action.ANSWER" />
</intent-filter>
</activity>
<activity
android:name="com.example.hdcallerid.test.PhineIntent"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Register the Broadcast receiver -->
<receiver
android:name="com.example.hdcallerid.PhonecallReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="com.example.hdcallerid.HUD"
android:exported="true" >
<intent-filter>
<action android:name="com.example.hdcallerid.HUD" />
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</service>
</application>