着信と発信を傍受できます。私の問題は、バージョン2.3.xでは機能しないことです。
ここに私のコード:
public class PhoneCallReceiver extends BroadcastReceiver {
/**
* Call back which fires off when the phone changes state.
*/
@Override
public void onReceive(Context context, Intent intent) {
//TODO
//===========
//here i need to chack the number
// Bundle b = intent.getExtras();
// String incommingNumber = b.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
// Additional Step
// Check whether this number matches with your defined Block List
// If yes, Reject the Call
//===========
/* examine the state of the phone that caused this receiver to fire off */
String phone_state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
// if (context.getSharedPreferences(Hc.PREFSNAME,0).getBoolean(Hc.PREF_CALL_ANSWER_TOOLS_KEY, true))
// {
logMe("Phone Ringing: the phone is ringing, scheduling creation call answer screen activity");
Intent i = new Intent(context, CallAnswerIntentService.class);
i.putExtra("delay", 100L);
context.startService(i);
logMe("Phone Ringing: started, time to go back to listening");
// } else {
// logMe("Phone Ringing: Call Answer tools disabled by user");
// }
}
if (phone_state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
// if (context.getSharedPreferences(Hc.PREFSNAME,0).getBoolean(Hc.PREF_SCREEN_GUARD_TOOLS_KEY, true))
// {
//TODO
Intent i = new Intent(context,InCallScreenGuardService.class);
i.putExtra("delay", 100L);
logMe("Phone Offhook: starting screen guard service");
context.startService(i);
// } else {
// logMe("Phone Offhook: In-Call Screen Guard disabled by user");
// }
}
if (phone_state.equals(TelephonyManager.EXTRA_STATE_IDLE))
{
// if (context.getSharedPreferences(Hc.PREFSNAME,0).getBoolean(Hc.PREF_SCREEN_GUARD_TOOLS_KEY, true))
// {
//TODO
Intent i = new Intent(context,InCallScreenGuardService.class);
logMe("Phone Idle: stopping screen guard service");
context.stopService(i);
// } else {
// logMe("Phone Idle: In-Call Screen Guard disabled by user");
// }
}
return;
}
この送信インテントはサービスに送信され、サービスは次のアクティビティにインテントを送信します。
public class CallAnswerActivity extends Activity {
/**
* whether or not to use the AIDL technique or
* the HEADSET_HOOK/package restart techniques
*/
private static final boolean USE_ITELEPHONY = true;
/**
* internal phone state broadcast receiver
*/
protected BroadcastReceiver r;
/**
* TelephonyManager instance used by this activity
*/
private TelephonyManager tm;
/**
* AIDL access to the telephony service process
*/
private com.android.internal.telephony.ITelephony telephonyService;
// ------------------------------------------------------------------------
// primary life cycle call backs
// ------------------------------------------------------------------------
/**
* main() :)
*/
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
debugLog("onCreate called");
setContentView(R.layout.callanswerscreen);
// grab an instance of telephony manager
tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
// connect to the underlying Android telephony system
if (USE_ITELEPHONY)
connectToTelephonyService();
// turn our idle phone state receiver on
registerReciever();
// touch screen return button
Button returnToCallScreen = (Button) findViewById(R.id.returnToCallScreen);
returnToCallScreen.setOnClickListener(new ReturnButtonOnClickListener());
// touch screen reject/ignore call button
Button rejectCall = (Button) findViewById(R.id.rejectCallButton);
// if (getSharedPreferences(Hc.PREFSNAME,0).getBoolean(Hc.PREF_ALLOW_REJECT_KEY, true))
rejectCall.setOnLongClickListener(new RejectCallOnLongClickListener());
// else
// rejectCall.setVisibility(View.GONE);
// touch screen answer button
Button answerButton = (Button) findViewById(R.id.answerCallButton);
// if (getSharedPreferences(Hc.PREFSNAME,0).getBoolean(Hc.PREF_ANSWER_WITH_BUTTON_KEY, true))
answerButton.setOnLongClickListener(new AnswerCallOnLongClickListener());
// else
// answerButton.setVisibility(View.GONE);
}
/**
* (re)register phone state receiver on resume, exit if the phone is idle
*/
@Override protected void onResume() {
super.onResume();
registerReciever();
if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
debugLog("phone is idle, stopping.");
exitCleanly();
}
}
/**
* unregister phone state receiver, schedule restart if not exiting at the users request
*/
@Override protected void onPause() {
super.onPause();
unHookReceiver();
if (!isFinishing())
{
debugLog("system forced pause occured, scheduling delayed restart");
Intent i = new Intent(getApplicationContext(), CallAnswerIntentService.class);
i.putExtra("delay", Hc.RESTART_DELAY);
startService(i);
}
}
// ------------------------------------------------------------------------
// Input event handler call backs
// ------------------------------------------------------------------------
/**
* Track ball press event handler that will answer a call
*/
@Override public boolean onTrackballEvent(MotionEvent event) {
switch(event.getAction())
{
case MotionEvent.ACTION_MOVE: return true;
case MotionEvent.ACTION_DOWN: answerCall(); return true;
default: debugLog("trackball event: "+event);
}
return super.dispatchTrackballEvent(event);
}
/**
* Camera button press event handler that will answer a call
*/
@Override public boolean dispatchKeyEvent(KeyEvent event) {
switch (event.getKeyCode())
{
case KeyEvent.KEYCODE_FOCUS: return true;
case KeyEvent.KEYCODE_CAMERA: answerCall(); return true;
default: debugLog("Unknown key event: "+event);
}
return super.dispatchKeyEvent(event);
}
/**
* Return button click listener will exit back to the
* phones stock answer call application.
*/
private class ReturnButtonOnClickListener implements OnClickListener {
public void onClick(View v) {
debugLog("returnToCallScreen onClick event");
exitCleanly();
}
}
/**
* Reject button long click listener will reject the
* incoming call.
*/
private class RejectCallOnLongClickListener implements OnLongClickListener {
public boolean onLongClick(View v){
debugLog("touch screen ignore call button onClick event");
ignoreCall();
exitCleanly();
return true;
}
}
/**
* Answer button long click listener will answer the
* incoming call.
*/
private class AnswerCallOnLongClickListener implements OnLongClickListener {
public boolean onLongClick(View v){
debugLog("touch screen answer button onClick event");
answerCall();
return true;
}
}
// ------------------------------------------------------------------------
// broadcast receivers
// ------------------------------------------------------------------------
/**
* register phone state receiver
*/
private void registerReciever() {
if (r != null) return;
r = new BroadcastReceiver() {
@Override
public void onReceive(Context c, Intent i) {
String phone_state = i.getStringExtra(TelephonyManager.EXTRA_STATE);
if (!phone_state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
debugLog("received "+phone_state+", time to go bye bye, thanks for playing!");
exitCleanly();
}
}
};
registerReceiver(r, new IntentFilter("android.intent.action.PHONE_STATE"));
}
/**
* unregister phone state receiver
*/
private void unHookReceiver() {
if (r != null)
{
unregisterReceiver(r);
r = null;
}
}
// ------------------------------------------------------------------------
// application methods
// ------------------------------------------------------------------------
/**
* get an instance of ITelephony to talk handle calls with
*/
@SuppressWarnings("unchecked") private void connectToTelephonyService() {
try
{
// "cheat" with Java reflection to gain access to TelephonyManager's ITelephony getter
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (com.android.internal.telephony.ITelephony) m.invoke(tm);
} catch (Exception e) {
e.printStackTrace();
debugLog("FATAL ERROR: could not connect to telephony subsystem");
debugLog("Exception object: "+e);
finish();
}
}
//
// answer call
//
/**
* answer incoming calls
*/
private void answerCall() {
if (USE_ITELEPHONY)
try {
answerCallAidl();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
else
answerCallHeadsetHook();
exitCleanly();
}
/**
* ACTION_MEDIA_BUTTON broadcast technique for answering the phone
*/
private void answerCallHeadsetHook() {
KeyEvent headsetHook = new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_HEADSETHOOK);
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, headsetHook);
sendOrderedBroadcast(mediaButtonIntent, null);
}
/**
* AIDL/ITelephony technique for answering the phone
*/
private void answerCallAidl() throws RemoteException {
telephonyService.silenceRinger();
telephonyService.answerRingingCall();
}
//
// ignore call
//
/**
* ignore incoming calls
*/
private void ignoreCall() {
if (USE_ITELEPHONY)
try {
ignoreCallAidl();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
else
ignoreCallPackageRestart();
}
/**
* package restart technique for ignoring calls
*/
private void ignoreCallPackageRestart() {
ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
am.restartPackage("com.android.providers.telephony");
am.restartPackage("com.android.phone");
}
/**
* AIDL/ITelephony technique for ignoring calls
*/
private void ignoreCallAidl() throws RemoteException {
telephonyService.silenceRinger();
telephonyService.endCall();
}
/**
* cleanup and exit routine
*/
private void exitCleanly() {
unHookReceiver();
moveTaskToBack(true);
finish();
}
2.3
のおかげでそれを動作させるために助けが必要です
この例外:
java.lang.SecurityException: Neither user 10156 nor current process has android.permission.MODIFY_PHONE_STATE.
at android.os.Parcel.readException(Parcel.java:1322)
at android.os.Parcel.readException(Parcel.java:1276)
at com.android.internal.telephony.ITelephony$Stub$Proxy.silenceRinger(ITelephony.java:1231)
at com.y_y_full.photo_dailer.CallAnswerActivity.answerCallAidl(CallAnswerActivity.java:281)
at com.y_y_full.photo_dailer.CallAnswerActivity.answerCall(CallAnswerActivity.java:256)
at com.y_y_full.photo_dailer.CallAnswerActivity.access$3(CallAnswerActivity.java:253)
at com.y_y_full.photo_dailer.CallAnswerActivity$AnswerCallOnLongClickListener.onLongClick(CallAnswerActivity.java:181)
at android.view.View.performLongClick(View.java:2556)
at android.widget.TextView.performLongClick(TextView.java:8358)
at android.view.View$CheckForLongPress.run(View.java:9128)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3691)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
at dalvik.system.NativeStart.main(Native Method)