Today, I was researching on a how to answer incoming call in android 2.3 automatically. My first thought was using "ITelephony.aidl" and call the answerRingingCall(). When i looked into more details answerRingingCall() function all requires MODIFY_PHONE_STATE permission which is marked as a as "signatureOrSystem" which is mentioned here
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=commit;h=f4ece2086f3b7060edc4b93a12f04c9af648867a
and here
http://code.google.com/p/android/issues/detail?id=15031
bummer. Then thought of a another work-around and bluetooth headset popuped to my mind. In this all I had to do was to call start new intent with ACTION_UP. It worked!
here is the soulution
BroadcastReceiver PhoneState = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals("android.intent.action.PHONE_STATE")) return;
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Intent answer = new Intent(Intent.ACTION_MEDIA_BUTTON);
answer.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
sendOrderedBroadcast(answer, null);
}
return;
}};
// Update on 2011-09-27
In Android 2.3.3 HTC Sensation this piece of code does not work. Reason is in 2.3.3 I found a HeadsetObserver listening for actual bluetooth plug-in event. So you need to send a Intent pretending there is a headset connected already. To fix this problem you need to send the ACTION_HEADSET_PLUG Intent before calling the above code.
Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");
// froyo and beyond trigger on buttonUp instead of buttonDown
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
headSetUnPluggedintent.putExtra("state", 1); // 0 = unplugged 1 = Headset with microphone 2 = Headset without microphone
headSetUnPluggedintent.putExtra("name", "Headset");
// TODO: Should we require a permission?
sendOrderedBroadcast(headSetUnPluggedintent, null);
// Update on 2012-04-27
Lot of people are asking me how to end call, here is the code
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
getContext().sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
// Update on 2012 - 08 - 21
This method no longer works on Android Jelly Bean (4.1.1) and possibly later versions. Google has blocked 3rd party apps from broadcasting Intent.ACTION_MEDIA_BUTTON.
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.HEADSET_PLUG from pid=30943, uid=10064
Android 1 : Me 0
Freakin' great, thanks, it worked on my emulator, I hope it will work on my boss' phone!!!
ReplyDeleteGreat!
ReplyDeleteOnce the call is answered, can one play an audio file to the incoming call? Any way around?
my case also same
Delete@Sanjay
ReplyDeleteOnly way I can think of is to play the audio file in loudspeaker mode.
hey dude I tried your workout on HTC desire, but didn't work. Am I doing something wrong !!!
ReplyDeleteHello - I am also trying on HTC with no results. Did you manage?
ReplyDeletei am using HTC Desire V it's not working and also i tried in 2.3.6 also not working
DeleteWhat is your Android version and phone model ?
ReplyDeleteHTC Sensation. 2.3.4
ReplyDeleteI also tried on the HTC desire 2.3.3
I have not tested this code on HTC Desire 2.3.3 but I have tested this code on HTC Sensation. 2.3.4.
ReplyDeleteDid you try the code I updated on 2011-09-27 for sensation? Easy-way to diagnose this issue is to use a headset. Call the phone and answer using headset. Look at the LogCat view. You can see the keys Android passing when answer a call. Take it and try to simulate.
Hi, thanks for you solution. It works on my HTC Desire HD. Now I'm wondering if it is possible to use the same way to end or reject a call?
ReplyDeleteDid you succeed in rejecting call?
Deleteprivate void endCall2() {
DeleteIntent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
getContext().sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
}
This is how to End Call. - tested on LG Optimus 2.3
Thanks! I cant get the code above to answer my call - I am using an HTC Incrediable. Any idea?
DeleteI tested and the only function not working in 2.3.x Itelephony is answerRingingCall() and silenceRinger() so i would recommend you keep using the endCall() function.
DeleteThis comment has been removed by the author.
DeleteUse a BroadcastReceiver to get the outgoing call state and set setResultData(null); You should be fine.
DeleteHi i use this code for end call
Deleteprivate void endCall2() {
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
getContext().sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
}
but i am not able to end call after receving the call it will end the call when incoming call comes but not working when i accept the call......pls any solution
Hi, unfortunately this is not working on HTC DesireS, Android version-2.3.5
ReplyDeleteAny help please!?
Thanks, vamsi
Can you post a simple app that works ?
ReplyDeleteBecause i trying a tonn of variation on my HTC Desire HD 2.3.5 and it's not working :(
PLease up the application i have the same error
ReplyDeleteplease upload source!
ReplyDeleteAll of this is working perfectly fine on the Samsung Galaxy GB 2.3.6, but I am seeing that after the call is answered programmatically, there is around 2 sec delay between when the Call state is switched from ringing to active to when the actual voice is heard from calling party.
ReplyDeleteSo basically it seems that the app sends an ordered broadcast and immediately switches over from Ringing to Active mode, but the actual android InCallScreen activity doesn't take over this broadcast and hence the delay.
Can we reduce this delay somehow, so that the transition is smooth ?
This code works great! But I would like my app to patch incoming calls through to the speaker automatically. Any suggestions??
ReplyDeleteI have tried:
1) Using an Audio Manager to alter the incoming audio stream
*AudioManager.setMode(MODE_IN_CALL);
2) Using an Audio Manager to turn on the speaker before and after answering the call
*AudioManager.setSpeakerphoneOn(true);
3) Unplugging the "headset" after taking the incoming call
*Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
*headSetUnPluggedintent.putExtra("state", 0); // 0 = unplugged 1 = Headset with microphone 2 = Headset without microphone
*context.sendOrderedBroadcast(headSetUnPluggedintent, null);
But none of this is working. Any suggestions????
Thanks for the code. It works really well. I am currently testing on android 4.0 and the activity crashes because of the ACTION_HEADSET_PLUG permission. And I cant find a permission to work with it. Any idea??
ReplyDeletein my test in 4.0.4 version it works without permission error. in manifest I set android.permission.READ_PHONE_STATE and android.permission.MODIFY_PHONE_STATE of course
DeleteSorry , I don´t know what I was doing wrong but it does work fine until 4.1 that i know. Thanks
DeleteAudioManager audioManager = (AudioManager)getBaseContext().getSystemService(Context.AUDIO_SERVICE);
ReplyDeleteaudioManager.setSpeakerphoneOn(true);
works well, but you have to make some 1000ms delay after answering. and of course: android.permission.MODIFY_AUDIO_SETTING
Hi JAN.GER,
ReplyDeletethanks so much for your reply. I have tried so many different things, but still no luck. I am developing on API Level 10, Android 2.3.4
The class that I have created which answers incoming calls extends BroadcastReceiver. So when I created my AudioManager using your suggested code, I got an error that said the "getBaseContext()" method is not defined for my class. In order to made things work I had to do:
audioManager = (AudioManager) ((ContextWrapper) context).getBaseContext().getSystemService(Context.AUDIO_SERVICE);
I'm not sure if this is equivalent, but it does not produce any errors. Then my app MUST silence the phone ringer when receiving an incoming call so I do:
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
I'm not sure if this plays a role in my audio not patching through to the speaker or not? Then, to answer calls, I do:
1) Intent answer = new Intent(Intent.ACTION_MEDIA_BUTTON);
2) answer.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
3) context.sendOrderedBroadcast(answer,
"android.permission.CALL_PRIVILEGED");
4) SystemClock.sleep(900);
5) audioManager.setSpeakerphoneOn(true);
But again, this still does not work for me. I have tried many values for the time delay....anywhere from 200ms to 2000ms. Perhaps there is a better way to create a time delay?
And in my manifest file, I believe I have all the necessary phone/audio permissions. Also, I am registering my call receiver class like this:
Should I be registering this differently?
Also, another problem that I am having is that when the cell phone receives incoming calls, it tries to perform the same steps as my custom call receiver class (even though my app is not being launched/used). I do not want this to happen. The phone should answer calls normally when my app is not in use.
Any suggestions??? And again, I really appreciate your help thus far :-)
I'm not sure what happened to the rest of my post, but it should look like this:
ReplyDeleteAnd in my manifest file, I believe I have all the necessary phone/audio permissions. Also, I am registering my call receiver class like this:
1) < receiver android:name=".helpers.CallReceiver">
2) < intent-filter>
3) < action
android:name="android.intent.action.PHONE_STATE">< /action>
4) < /intent-filter>
5) < /receiver>
Should I be registering this differently?
Using the following seems to work on JellyBean(4.1) despite the last broadcast being disallowed, hope this helps someone:
ReplyDeleteIntent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");
// froyo and beyond trigger on buttonUp instead of buttonDown
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
headSetUnPluggedintent.putExtra("state", 1); // 0 = unplugged 1 =
// Headset with
// microphone 2 =
// Headset without
// microphone
headSetUnPluggedintent.putExtra("name", "Headset");
if (Build.VERSION.SDK_INT < 16) {
//Not allowed on JellyBean, but the rest seems to work
context.sendOrderedBroadcast(headSetUnPluggedintent, null);
}
The ITelephony method of answer and endCall shown elsewhere also works on 4.1
Deletethanks
DeleteOn the HTC One X 4.1 the above broadcast method does not work (although it works on other 4.1 devices). I tried with the ITelephony method but I am receiving a security error. Do you have any ideas?
Deletegreat post & workaround ... i have been testing in android 2.3.3 and it really works fine .. thanks .. keep up with great work :)
ReplyDeleteGreat post...helped me a lot..am using ics 4.0.4 in my xperia neo v. Call answering works perfects but call rejecting doesnt work. any pointers?
ReplyDeleteHello,
ReplyDeleteI'm not a dev, I'm using tasker and unfortunately the "take call" funtion does not work on my HTC Sensation (Android 4.0.3) due to a permission error. Is it possible you could give me a Java Script I could execute on tasker to bypass this Permission error I get (I guess it is the one you mention in your post).
Thanks
I am having the same answer call problem with Tasker. Also the stream media to call action doesn't work on my htc desire hd. a Java script alternative would be great.
Deletei was testing this on emulator but its not working....is it only work for device..........
ReplyDeleteThanks Aruna, Since last 8 days I was strugling this problem. Im having Optimus One with 2.3.3 & your code work perfectly for me to reject call.
ReplyDeletepublic static void answerPhoneHeadsethook(Context context) {
// Simulate a press of the headset button to pick up the call
// SettingsClass.logMe(tag, "Simulating headset button");
Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");
}
I have tried to use end call code but it gives on the getContext() method, how to resolve it?
ReplyDeleteor where is this method id defined?
I am having the same problem with Tasker. Also the stram media to call action doesn't work on my htc desire hd. a Java script alternative would be great.
ReplyDeleteCan anybody send me full working code, please. This code don't answer on call. I tested on Android 2.3.3 and 4.1.2. And I need this so much!
ReplyDeleteHi,
ReplyDeleteFinally works,
I have tested on HTC One V (Android 4.0)
Please find my Phone state listener http://pastebin.com/wcnNEN5P
Thank you very much for your support
I want to answer a call through my app.
ReplyDeletecan you help me?
plz send me code...
Email id: R62r64@gmail.com
thanking you...
Any update for kitkat 4.4.2?
ReplyDeleteThank you so much...It helped a lot
ReplyDeletenot working for lollipop,,, plz help
ReplyDelete