Я пытаюсь заставить приложение прослушивать звонки (входящие и исходящие), на данный момент я просто зарегистрировал получателя в манифесте, который отлично работал в Android ниже 9.0.
Однако проблема возникла, когда я тестировал приложение на Android oreo, я знаю, что некоторые трансляции были отключены.
Я попытался создать службу переднего плана, которая регистрирует получателя и прослушивает эту трансляцию, но снова она работала на версиях ниже oreo.
Я не знаю, что еще делать, мне нужно, чтобы это сработало, мне все равно, будет ли это нелегким способом, я не публикую это приложение, оно мне просто нужно для частного использования.
Резюме: мне нужно прослушивать звонки в Android-пироге, даже если приложение в данный момент не активно
манифест
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
MyReceiver
public class MyReceiver extends BroadcastReceiver {
private static Date callStartTime;
private static boolean isIncoming;
private static int lastState;
private static String savedNumber;
private static String savedOutgoingNumber;
private TelephonyManager tm;
@Override
public void onReceive(Context context, Intent intent) {
//We listen to two intents. The new outgoing call only tells us of an outgoing call. We use it to get the number.
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
}
else{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
Проблема в том, что он даже не вызывается на Android Oreo
Редактировать: я получил его на Android Oreo, но у него есть проблемы в Android пирог
Другое редактирование:
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PHONE_STATE");
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
CallListenerService.this.onReceive(intent);
}
};
registerReceiver(receiver, filter);
}
public void onReceive(Intent i){
if (i.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = i.getExtras().getString("android.intent.extra.PHONE_NUMBER");
}
else{
String stateStr = i.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = i.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(this, state, number);
}
}
Остальное не имеет значения, просто запустите действие в конце вызова, чтобы проверить, работает ли оно
Я добавил четырехземный сервис, который регистрирует получателей. Он работает на Android Oreo, но все еще имеет проблемы с Android пирогом.
Редактировать: решение состояло в том, чтобы смешать кучу ответов, пока они не сработали на каждом устройстве.
Я написал манифест декларации так:
<receiver
android:name=".MyReceiver"
android:enabled="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter android:priority="1000">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"
/>
</intent-filter>
</receiver>
на самом деле не знаю, что это сделал.
Более того, я использовал обычный широкополосный приемник, а не службу, опять же, я не знаю, что произошло, но вдруг это сработало на некоторых устройствах.
теперь последний штрих, я узнал, что я могу получить номер телефона, прочитав журнал звонков, поэтому я добавил следующий код:
protected void onMissedCall(final Context ctx, String number, Date start) {
if (PreferenceManager.getDefaultSharedPreferences(ctx).getBoolean("missed_calls", false)) {
if (number == null) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
final String phoneNumber = getLastCallNumber(ctx);
if (phoneNumber != null) {
Intent intent = new Intent(ctx, Dialog.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("number", phoneNumber);
intent.putExtra("missed_call", true);
ctx.startActivity(intent);
} else {
Toast.makeText(ctx, "cannot get phone number", Toast.LENGTH_SHORT).show();
}
}
}, 2000);
} else {
Intent intent = new Intent(ctx, Dialog.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("number", number);
intent.putExtra("missed_call", true);
ctx.startActivity(intent);
}
}
}
private String getLastCallNumber(Context context) {
Uri contacts = CallLog.Calls.CONTENT_URI;
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, "Permission denied can not get phone number", Toast.LENGTH_SHORT).show();
}
Cursor managedCursor = context.getContentResolver().query(
contacts, null, null, null, null);
int number = managedCursor.getColumnIndex( CallLog.Calls.NUMBER );
String phoneNumber = null;
if( managedCursor.moveToLast() == true ) {
phoneNumber = managedCursor.getString( number );
}
managedCursor.close();
return phoneNumber;
}
Я добавил строку if, которая проверяет, является ли номер нулевым, и, если это так, запускает обработчик, который запускается через 2 секунды после, после запуска обработчика я считываю последний номер из журнала вызовов.
Задержка в 2 секунды для номера, чтобы войти в журнал звонков, если вы попытаетесь прочитать его сразу, он не будет работать.