Я пишу приложение для Android, в котором мне нужно ответить на входящий звонок, выполнить некоторую работу и затем завершить вызов. После всего Googling я мог найти два разных способа достижения этого, оба из которых не работают с последними версиями Android, особенно после 4.1, Jelly Bean.
I.) Доступ к "com.android.internal.telephony.ITelephony" с использованием Java Reflection в приемнике Broadcast для "android.intent.action.PHONE_STATE". Ниже пример кода можно найти в сотнях связанных сообщений:
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);
}
}
}
Проблема с этим кодом заключается в том, что
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
требуется, чтобы этот метод работал, и это разрешение было определено как "только для системных приложений" от android v 2.3. Короче говоря, обычные пользовательские приложения больше не могут определять это разрешение в файле манифеста.
II.) Другой способ - имитировать нажатие на крючок гарнитуры, что заставляет Android отвечать на вызов. Это делается путем трансляции "Intent.ACTION_MEDIA_BUTTON", как показано ниже.
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;
}
}
Этот метод работает до Android 4.1, после которого андроид ограничил пользовательские приложения от трансляции "Intent.ACTION_MEDIA_BUTTON".
Итак, я пришел к выводу, что в настоящее время мы не можем добиться этого в Android 4.1 или новее.
Кто-нибудь еще нашел какое-либо другое решение или обходное решение этой проблемы?