I am writing an android app in which I need to answer an incoming call, do some work and then end the call. After all the Googling I could find two different ways to achieve this both of which do not work with recent versions of Android, specifically after 4.1, Jelly Bean.
I.) Access "com.android.internal.telephony.ITelephony" using Java Reflection in the Broadcast receiver for "android.intent.action.PHONE_STATE". Below sample code can be found in hundreds of related post:
public class PhoneCallReceiver extends BroadcastReceiver {
Context context = null;
private static final String TAG = "Phone call";
private ITelephony telephonyService;
@Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals("android.intent.action.PHONE_STATE"))
return;
Log.v(TAG, "Receving....");
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
try {
Log.v(TAG, "Get getTeleService...");
Class c = Class.forName(telephony.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(telephony);
telephonyService.silenceRinger();
Log.v(TAG, "Answering Call now...");
telephonyService.answerRingingCall();
Log.v(TAG, "Call answered...");
//telephonyService.endCall();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG,
"FATAL ERROR: could not connect to telephony subsystem");
Log.e(TAG, "Exception object: " + e);
}
}
}
The problem with this code is that
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
is required for this method to work, and this permission has been defined as "for system apps only" from android v 2.3. In short, normal user apps can not define this permission in the manifest file anymore.
II.) Another way is to simulate pushing of the Headset hook which makes Android answer the call. This is done by broadcasting the "Intent.ACTION_MEDIA_BUTTON" as shown in below code.
public class PhoneCallReceiver extends BroadcastReceiver {
Context context = null;
private static final String TAG = "Phone call";
@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));
context.sendOrderedBroadcast(answer, null);
Log.d(TAG, "Answered incoming call from: " + number);
}
return;
}
}
This method works till Android 4.1 after which android has restricted user apps from broadcasting "Intent.ACTION_MEDIA_BUTTON".
So my conclusion is that currently there is no way how we can achieve this in Android 4.1 or later.
Has anybody else found any other solution or workaround to this problem?
ITelephony method does not work on 4.4 and I find the headset/media button method still allows a fairly long ring before hangup.
This chaps blog post shows a new method that I have tested as working on 4.4.2 Galaxy s4 and HTC one mini that hangs up much more quickly and you don't get a missed call entry either.
http://aprogrammersday.blogspot.co.uk/2014/05/disconnect-block-drop-calls-android-4.html
The technique uses a runtime exec as below, apparently you may need to use a different number for some devices.
This works from Android 2.2 to 4.0 and now after adding the try catch to the last line it works for 4.1.2 and 4.2 Frankly speaking dont know how it works but it works for me.
This is working for me in Android 4.1.2 as well as i have tested on 4.2 This still gives an exception which is handled.
Edit for End Call
Hope this helps all the people looking for total solution for answer and end call.
My application has been using the following code to answer the phone for about 6 months:
I have tested this on Android Versions from 2.2 to 4.2.2. I have not seen a SecurityException broadcasting "Intent.ACTION_MEDIA_BUTTON" in my testing n a 4.2.2 device, nor have I seen crash reports from the Play Store indicating such exceptions are occurring.
I will say that this does not always work. It does not work on HTC devices due to the fact that HTC devices have a HeadsetObeserver that listen for the actually plugging in of a wired headset. Without this event, which it is currently a SecurityException for a third party app to broadcast, the HeadsetHook KeyEvent goes ignored.
The previous answers are misleading. The following code block does nothing:
except generate a SecurityException and catch it.
In the other answers where the code works, it is because of the KeyEvent.KEYCODE_HEADSETHOOK being broadcast.
Try this :
Add permissions in AndroidManifest.xml file as
Try this Answer for end the call using pro grammatically. Its working fine for me.
Call disconnecting using IT Telephony doesn't work on some devices like Samsung S Duos. But you can still make ringer silent :)