Pour détecter la réponse à un appel sortant, j'ai essayé de créer une PhoneStateListener
et d'écouter les CALL_STATE_RINGING
, CALL_STATE_OFFHOOK
et CALL_STATE_IDLE
de TelephonyManager
, à partir de cette question , mais cela ne semble pas fonctionner, comme expliqué ci-dessous.
D'abord, j'ai enregistré l'autorisation suivante dans le manifeste:
<uses-permission Android:name="Android.permission.PROCESS_OUTGOING_CALLS" />
Ensuite, une BroadcastReceiver
appelée OutCallLogger
qui intercepte l'événement NEW_OUTGOING_CALL
chaque fois qu'un appel sortant est effectué:
<receiver Android:name=".listener.OutCallLogger">
<intent-filter>
<action Android:name="Android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Ensuite, mon implémentation de OutCallLogger
. J'ai mis en place un booléen appelé noCallListenerYet
afin d'éviter d'attacher une nouvelle PhoneStateListener
à la TelephonyManager
chaque fois que onReceive()
est appelé.
public class OutCallLogger extends BroadcastReceiver {
private static boolean noCallListenerYet = true;
@Override
public void onReceive(final Context context, Intent intent) {
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
if (noCallListenerYet) {
final TelephonyManager tm = (TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE);
tm.listen(new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.d(This.LOG_TAG, "RINGING");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(This.LOG_TAG, "OFFHOOK");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(This.LOG_TAG, "IDLE");
break;
default:
Log.d(This.LOG_TAG, "Default: " + state);
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
noCallListenerYet = false;
}
}
}
Désormais, lorsque je passe un appel sortant dans mon appareil, CALL_STATE_RINGING
n'est JAMAIS appelé. Je reçois toujours des impressions de "IDLE" à "OFFHOOK" lorsque l'autre ligne sonne, rien lorsque l'appel est pris, et une impression de "IDLE" à nouveau lorsque l'appel est terminé.
Comment puis-je détecter de manière fiable lorsqu'un appel sortant est pris dans Android, ou est-ce même possible?
Depuis Android 5.0, cela est possible pour les applications système. Mais vous devez utiliser l'API Android cachée.
Je l'ai fait fonctionner comme ceci:
<uses-permission Android:name="Android.permission.READ_PRECISE_PHONE_STATE" />
<receiver Android:name=".listener.OutCallLogger">
<intent-filter>
<action Android:name="Android.intent.action.PRECISE_CALL_STATE" />
</intent-filter>
</receiver>
public class OutCallLogger extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getIntExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, -2) {
case PreciseCallState.PRECISE_CALL_STATE_IDLE:
Log.d(This.LOG_TAG, "IDLE");
break;
case PreciseCallState.PRECISE_CALL_STATE_DIALING:
Log.d(This.LOG_TAG, "DIALING");
break;
case PreciseCallState.PRECISE_CALL_STATE_ALERTING:
Log.d(This.LOG_TAG, "ALERTING");
break;
case PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
Log.d(This.LOG_TAG, "ACTIVE");
break;
}
}
}
Vous pouvez trouver tous les états d'appel possibles dans PreciseCallState.Java et tous les extras que l'intention contient dans TelephonyRegistry.Java .
Il semble que l'état SONNERIE ne soit atteint que par les appels entrants. Les appels sortants passent de IDLE à OFFHOOK. Il est donc impossible d'examiner l'état du téléphone.
Je pense que cela pourrait être possible en utilisant des fonctions internes, regardez ceci: Que représentent les différents états d’appel dans la pile de téléphonie Android?
S'il vous plaît payez votre attention à:
tm.listen(new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.d(This.LOG_TAG, "RINGING");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(This.LOG_TAG, "OFFHOOK");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(This.LOG_TAG, "IDLE");
break;
default:
Log.d(This.LOG_TAG, "Default: " + state);
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
Voyez-vous l'argument "incomingNumber"? Oui, ce code ne peut détecter votre état d'appel téléphonique que s'il y a un appel téléphonique entrant sur votre appareil.
Peut-être essayer d'utiliser CallManager? Consultez http://grepcode.com/file/repository.grepcode.com/Java/ext/com.google.Android/android/2.3.3_r1/com/Android/internal/telephony/CallManager.Java . J'ai également trouvé CallManager.Java parmi les fichiers SDK de mon ordinateur. Le texte suivant de la page liée semble prometteur:
Register for getting notifications for change in the Call State Call.State This is
called PreciseCallState because the call state is more precise than the Phone.State
which can be obtained using the Android.telephony.PhoneStateListener Resulting events
will have an AsyncResult in Message.obj. AsyncResult.userData will be set to the obj
argument here. The h parameter is held only by a weak reference.
1051
1052 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1053 mPreciseCallStateRegistrants.addUnique(h, what, obj);
1054 }
Je n'ai pas essayé de coder quoi que ce soit, donc je ne sais vraiment pas s'il peut faire ce que vous voulez, mais je suis curieux de savoir.