Приложение сбрасывает входящий звонок и сохраняет номер звонящего. Все нормально работало, но появилась проблема на Samsung j3 (Android 7.0), логирование происходит (в приложенном коде убрал его), а звонок не сбрасывается.
В чем может быть проблема?
Пермишены:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
Класс, который должен сбрасывать звонок:
public class CallReceiver extends BroadcastReceiver implements ITelephony {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
String phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (phoneState.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
ITelephony telephonyService;
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
try {
Class c = Class.forName(telephony.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(telephony);
if (telephonyService != null)
telephonyService.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public boolean endCall() {
return false;
}
@Override
public void answerRingingCall() {
}
@Override
public void silenceRinger() {
}
}
P.S. У меня нет устройства, на котором проблема воспроизводится, на моих девайсах все работает.
UPD:
Я изучаю проблему на англоязычном SO, нашел человека с похожей проблемой. Опять же догадка, ибо о проблеме мне сообщил юзер, а у меня нет устройств Самсунг.
В его случае при таком же методе сброса звонка возникает ошибка, что нужен пермишен MODIFY_PHONE_STATE
, который есть только у системных приложений.
В таком случае я не понимаю, почему на устройствах OnePlus 6 и Xiaomi Mi Max 3 с Android 9.0 и Xiaomi Mi Max 2 с Android 8.0 приложение работает без этого пермишена, а на Samsung j3 со "старым" Android 7.0 возникает такая проблема? Как в таком случае на нем работают "черные списки" с Google Play и т.д.? Буду рад любым подсказкам по этой теме.
Приложенный способ не удалось заставить работать на Samsung-устройствах.
Как подметили в комментариях, производители часто немного меняют систему, а способ с ITelephony
скорее хак, чем нормальное решение, поэтому его неработоспособность на Samsung вполне нормальное явление. Проблема действительно была в пермишене MODIFY_PHONE_STATE
, который никак нельзя получить.
Есть рабочее решение для Android 6.0+. Приложение должно заменить стандартное приложение для звонков (default call dialer). Это делается довольно просто, в итоге Android сам будет передавать звонки приложению, а там уже можно их сбрасывать. Прикладываю код на kotlin
.
В первую очередь в манифест нужно добавить intent filters
в AndroidManifest.xml
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<data android:scheme="tel" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
</intent-filter>
и добавить сервис для обработки звонков
<service
android:name=".CallService"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true"/>
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
Так же при запуске приложения нужно убедиться, что оно установлено как стандартное для звонков и в случае необходимости сделать себя текущим приложением для звонков:
if (getSystemService(TelecomManager::class.java).defaultDialerPackage != packageName) {
Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
.let(::startActivity)
}
Код сервиса:
class CallService : InCallService() {
override fun onCallAdded(call: Call) {
OngoingCall.call = call
val number = call.details.handle.schemeSpecificPart // номер телефона
// тут можно логировать и вообще что угодно
OngoingCall.hangup() // сбросить вызов
}
override fun onCallRemoved(call: Call) {
OngoingCall.call = null
}
}
В целом эта тема достаточно хорошо раскрыта, есть статьи, например:
Android default dialer replacement (part I)
Android default dialer replacement (part II)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Делал по примеру телеграмм бота, но он у меня не запускаетсяхотя делал 1 в 1
Не получается из href извлечь содержимый URL с помощью XPath
Подскажите, как установить 3D pdf модель на сайт? Выглядит примерно так: 3D модель можно двигать курсором в разных направленияхСколько искал...
учусь верстать сайтыНашел макет сайта в интернете