I am writing an Android application in which I need to answer an incoming call, do some work, and then end the call. After all Googling, I could find two different ways to achieve this, both of which do not work with the latest versions of Android, especially after 4.1, Jelly Bean.
I.) Access to "com.android.internal.telephony.ITelephony" using Java Reflection in the Broadcast receiver for "android.intent.action.PHONE_STATE". Below code example can be found in hundreds of related posts:
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...");
The problem with this code is that
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
this method is required to work, and this permission has been defined as "only for system applications" from android v 2.3. In short, regular user applications can no longer define this permission in the manifest file.
II.) Another way is to simulate a click on the hook of the headset, which causes Android to answer the call. This is done by broadcasting "Intent.ACTION_MEDIA_BUTTON" as shown below.
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 before Android 4.1, after which the android restricted user applications from broadcasting "Intent.ACTION_MEDIA_BUTTON".
So, I came to the conclusion that at the moment we can not achieve this in Android 4.1 or later.
Has anyone else found any other solution or workaround for this problem?