web-dev-qa-db-fra.com

Impossible de détecter quand un appel sortant est pris dans Android

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_RINGINGn'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?

23
Matthew Quiros

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 .

10
Tim S.

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?

3
1087427

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.

1
user1593800

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.

1
hBrent