Présentation du protocole SIP

Détecter les eSIM et les cartes SIM

Détecter des cartes

Les appareils Android équipés de cartes SIM et d'eSIM utilisent les identifiants suivants pour les services de téléphonie API, y compris [`TelephonyManager`](/reference/android/telephony/TelephonyManager) et [`SubscriptionManager`](/reference/android/telephony/SubscriptionManager): * ID d'abonnement: identifiant unique d'un abonnement mobile. * Index ou identifiant d'emplacement logique: index unique faisant référence à un emplacement de carte SIM logique. Les ID d'emplacements logiques commencent à 0 et augmentent en fonction du nombre de d'emplacements actifs compatibles sur un appareil. Par exemple, un appareil avec double carte SIM comporte l'emplacement 0 et l'emplacement 1. Si un appareil possède plusieurs emplacements physiques, mais seulement prend en charge un emplacement actif, il n'aura que l'ID d'emplacement logique 0. * Index ou ID d'emplacement physique: index unique faisant référence à un emplacement physique pour carte SIM. Les ID d'emplacements physiques commencent à 0 et augmentent en fonction du nombre d'emplacements physiques emplacements sur l'appareil. Cela diffère du nombre d'emplacements logiques qu'un périphérique possède, qui correspond au nombre d'emplacements actifs qu'un appareil peut obtenir utilisent. Par exemple, un appareil qui alterne entre une double carte SIM et une carte SIM unique. peut toujours avoir deux emplacements physiques, mais en mode SIM simple, un seul emplacement logique. * ID de carte: identifiant unique utilisé pour identifier une carte UiccCard. ![Schéma illustrant l'utilisation des ID dans un cas avec deux emplacements logiques et trois emplacements physiques](/images/guide/topics/connectivity/tel-ids.png) Dans le diagramme ci-dessus: * L'appareil possède deux emplacements logiques. * L'emplacement physique 0 contient une carte UICC physique avec un profil actif. * Dans l'emplacement physique 2, il y a un eUICC avec un profil actif. * L'emplacement physique 1 n'est pas utilisé actuellement. ![Schéma illustrant l'utilisation des ID dans un cas avec trois emplacements logiques et deux emplacements physiques](/images/guide/topics/connectivity/tel-ids-2.png) Dans le diagramme ci-dessus: * L'appareil dispose de trois emplacements logiques. * L'emplacement physique 0 contient une carte UICC physique avec un profil actif. * Dans l'emplacement physique 1, il y a un eUICC qui comporte deux profils téléchargés, tous deux actifs à l'aide de MEP (Multiple Enabled Profiles).

Présentation du protocole SIP

Android fournit une API compatible avec le protocole SIP (Session Initiation Protocol). Cela vous permet d'ajouter des fonctionnalités de téléphonie Internet basées sur SIP à vos applications. Android inclut une pile de protocoles SIP complète et une gestion des appels intégrée des services qui permettent aux applications de configurer facilement des appels vocaux sortants et entrants, sans avoir à gérer de sessions, de communication de niveau transport ou directement lors de l'enregistrement ou de la lecture.

Voici des exemples de types d'applications qui peuvent utiliser l'API SIP:

  • Visioconférence
  • Messagerie instantanée

Conditions requises et limites

Voici les conditions requises pour développer une application SIP:

  • Votre appareil mobile doit être équipé d'Android 2.3 ou version ultérieure.
  • SIP s'exécute via une connexion de données sans fil, votre appareil doit donc disposer d'un (via un service de données mobiles ou Wi-Fi). Cela signifie que vous Impossible d'effectuer un test sur un AVD (vous ne pouvez le tester que sur un appareil physique). Pour en savoir plus, consultez Tester les applications SIP
  • Chaque participant à la session de communication de l'application doit avoir un Compte SIP. De nombreux fournisseurs SIP différents proposent des comptes SIP.

Remarque:La bibliothèque android.net.sip n'est pas compatible avec les vidéos appels. Si vous souhaitez implémenter les appels VoIP à l'aide d'une pile SIP telle que android.net.sip, découvrez l'une des nombreuses solutions Open Source modernes comme base pour toute mise en œuvre des appels VoIP. Par ailleurs, vous pouvez mettre en œuvre ConnectionService API permettant d'intégrer étroitement ces appels au clavier de l'appareil l'application.

Classes et interfaces de l'API SIP

Voici un récapitulatif des classes et une interface (SipRegistrationListener) inclus dans le SIP Android API:

Classe/Interface Description
SipAudioCall Gère un appel audio Internet via SIP.
SipAudioCall.Listener Paramètre "Listener" pour les événements liés à un appel SIP, par exemple lorsqu'un appel est en cours reçu ("en cours de sonnerie") ou sortant ("en cours d'appel").
SipErrorCode Définit les codes d'erreur renvoyés lors des actions SIP.
SipManager Fournit des API pour les tâches SIP, telles que le lancement de connexions SIP, et fournit un accès aux services SIP associés.
SipProfile Définit un profil SIP, y compris un compte SIP, ainsi que des informations sur le domaine et le serveur.
SipProfile.Builder Classe d'assistance pour la création d'un SipProfile.
SipSession Représente une session SIP associée à une boîte de dialogue SIP ou à une transaction autonome. et non dans une boîte de dialogue.
SipSession.Listener Paramètre "Listener" pour les événements en lien avec une session SIP, par exemple lorsqu'une session est en cours d'enregistrement ("en cours d'enregistrement") ou qu'un appel est sortant ("en appel").
SipSession.State Définit les états des sessions SIP, tels que "enregistrement", "appel sortant" et "appel en cours".
SipRegistrationListener Interface qui écoute les événements d'enregistrement SIP.

Création du fichier manifeste...

Si vous développez une application qui utilise l'API SIP, n'oubliez pas que cette fonctionnalité n'est compatible qu'avec Android 2.3 (niveau d'API 9) ou version ultérieure de la plate-forme. De plus, sur les appareils équipés d'Android 2.3 (niveau d'API 9) ou version ultérieure, tous les appareils ne sont pas compatibles avec le SIP.

Pour utiliser SIP, ajoutez les autorisations suivantes au fichier manifeste de votre application:

  • android.permission.USE_SIP
  • android.permission.INTERNET

Pour vous assurer que votre application ne peut être installée que sur les appareils compatible SIP, ajoutez ce qui suit au répertoire fichier manifeste:

<uses-sdk android:minSdkVersion="9" />

Cela signifie que votre application nécessite Android 2.3 ou une version ultérieure. Pour Pour en savoir plus, consultez Niveaux d'API ainsi que la documentation <uses-sdk> .

Pour contrôler la manière dont votre application est exclue des appareils non compatibles SIP (par exemple, sur Google Play), ajoutez les éléments suivants au fichier manifeste:

<uses-feature android:name="android.software.sip.voip" />

Cela indique que votre application utilise l'API SIP. La déclaration doit incluent un attribut android:required qui indique si que l'application soit exclue des appareils qui n'offrent pas de prise en charge SIP. D'autres déclarations <uses-feature> peuvent également être nécessaires, en fonction de votre implémentation. Pour en savoir plus, consultez la documentation pour le <uses-feature> .

Si votre application est conçue pour recevoir des appels, vous devez également définir un destinataire (sous-classe BroadcastReceiver) dans le fichier manifeste de l'application:

<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />

Voici des extraits du fichier manifeste SipDemo:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.android.sip">
  ...
     <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
  ...
  <uses-sdk android:minSdkVersion="9" />
  <uses-permission android:name="android.permission.USE_SIP" />
  <uses-permission android:name="android.permission.INTERNET" />
  ...
  <uses-feature android:name="android.software.sip.voip" android:required="true" />
  <uses-feature android:name="android.hardware.wifi" android:required="true" />
  <uses-feature android:name="android.hardware.microphone" android:required="true" />
</manifest>

Création de SipManager...

Pour utiliser l'API SIP, votre application doit créer un objet SipManager. SipManager prend s'occupe des éléments suivants dans votre application:

  • Lancement de sessions SIP.
  • Émission et réception d'appels
  • Enregistrement et annulation de l'enregistrement auprès d'un fournisseur SIP...
  • Vérification de la connectivité de la session...

Instanciez un nouveau SipManager comme suit:

Kotlin

val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) {
    SipManager.newInstance(this)
}

Java

public SipManager sipManager = null;
...
if (sipManager == null) {
    sipManager = SipManager.newInstance(this);
}

Enregistrement auprès d'un serveur SIP

Une application SIP Android typique implique un ou plusieurs utilisateurs, chacun dispose d'un compte SIP. Dans une application SIP Android, chaque compte SIP est représentées par un objet SipProfile.

Un SipProfile définit un profil SIP, y compris un SIP les informations sur le compte, le domaine et le serveur. Profil associé au SIP sur l'appareil qui exécute l'application s'appelle la localisation profil. Le profil auquel la session est connectée s'appelle profil pair. Lorsque votre application SIP se connecte au serveur SIP avec le SipProfile local, qui enregistre effectivement le comme l'emplacement vers lequel envoyer les appels SIP pour votre adresse SIP.

Cette section explique comment créer un SipProfile, l'enregistrer auprès d'un serveur SIP et suivre les événements d'enregistrement.

Pour créer un objet SipProfile, procédez comme suit:

Kotlin

private var sipProfile: SipProfile? = null
...

val builder = SipProfile.Builder(username, domain)
        .setPassword(password)
sipProfile = builder.build()

Java

public SipProfile sipProfile = null;
...

SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
sipProfile = builder.build();

L'extrait de code suivant ouvre le profil local permettant de passer des appels et/ou de recevoir des appels SIP génériques. L'appelant peut effectuer les appels suivants via mSipManager.makeAudioCall Cet extrait définit également l'action android.SipDemo.INCOMING_CALL, qui sera utilisé par un intent lorsque l'appareil reçoit un appel (voir la section Configuration un filtre d'intent pour recevoir des appels). Voici l'étape d'inscription:

Kotlin

val intent = Intent("android.SipDemo.INCOMING_CALL")
val pendingIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA)
sipManager?.open(sipProfile, pendingIntent, null)

Java

Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
sipManager.open(sipProfile, pendingIntent, null);

Enfin, ce code définit un SipRegistrationListener sur SipManager. Permet de savoir si le SipProfile a bien été enregistré auprès de votre service SIP fournisseur:

Kotlin

sipManager?.setRegistrationListener(sipProfile?.uriString, object : SipRegistrationListener {

    override fun onRegistering(localProfileUri: String) {
        updateStatus("Registering with SIP Server...")
    }

    override fun onRegistrationDone(localProfileUri: String, expiryTime: Long) {
        updateStatus("Ready")
    }

    override fun onRegistrationFailed(
            localProfileUri: String,
            errorCode: Int,
            errorMessage: String
    ) {
        updateStatus("Registration failed. Please check settings.")
    }
})

Java

sipManager.setRegistrationListener(sipProfile.getUriString(), new SipRegistrationListener() {

    public void onRegistering(String localProfileUri) {
        updateStatus("Registering with SIP Server...");
    }

    public void onRegistrationDone(String localProfileUri, long expiryTime) {
        updateStatus("Ready");
    }

    public void onRegistrationFailed(String localProfileUri, int errorCode,
        String errorMessage) {
        updateStatus("Registration failed.  Please check settings.");
    }
}

Lorsque votre application utilise un profil, elle doit le fermer comme étant libre. les objets associés en mémoire et annuler l'enregistrement de l'appareil sur le serveur. Exemple :

Kotlin

fun closeLocalProfile() {
    try {
        sipManager?.close(sipProfile?.uriString)
    } catch (ee: Exception) {
        Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee)
    }
}

Java

public void closeLocalProfile() {
    if (sipManager == null) {
       return;
    }
    try {
       if (sipProfile != null) {
          sipManager.close(sipProfile.getUriString());
       }
     } catch (Exception ee) {
       Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
     }
}

Passer un appel audio

Pour passer un appel audio, vous devez:

  • Un SipProfile qui effectue l'appel (le "profil local") et d'une adresse SIP valide pour recevoir l'appel (les "profil pair").
  • Un objet SipManager.

Pour passer un appel audio, vous devez configurer un SipAudioCall.Listener. Une grande partie de l'interaction du client avec la pile SIP se fait par les écouteurs. Dans cet extrait, SipAudioCall.Listener configure les choses une fois l'appel terminé établi:

Kotlin

var listener: SipAudioCall.Listener = object : SipAudioCall.Listener() {

    override fun onCallEstablished(call: SipAudioCall) {
        call.apply {
            startAudio()
            setSpeakerMode(true)
            toggleMute()
        }
    }

    override fun onCallEnded(call: SipAudioCall) {
        // Do something.
    }
}

Java

SipAudioCall.Listener listener = new SipAudioCall.Listener() {

   @Override
   public void onCallEstablished(SipAudioCall call) {
      call.startAudio();
      call.setSpeakerMode(true);
      call.toggleMute();
         ...
   }

   @Override

   public void onCallEnded(SipAudioCall call) {
      // Do something.
   }
};

Après avoir configuré SipAudioCall.Listener, vous pouvez : passer l'appel. La méthode SipManager makeAudioCall utilise les paramètres suivants:

  • Un profil SIP local (l'appelant).
  • Un profil SIP du pair (l'utilisateur appelé).
  • Un SipAudioCall.Listener pour écouter l'appel événements de SipAudioCall. Il peut s'agir de null, mais comme indiqué ci-dessus, l'écouteur est utilisé pour configurer les éléments une fois que l'appel est établi.
  • Valeur du délai avant expiration, en secondes.

Exemple :

Kotlin

val call: SipAudioCall? = sipManager?.makeAudioCall(
        sipProfile?.uriString,
        sipAddress,
        listener,
        30
)

Java

call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);

Recevoir des appels

Pour recevoir des appels, une application SIP doit inclure une sous-classe de BroadcastReceiver capable de répondre à un intent. indiquant la présence d'un appel entrant. Vous devez donc procéder comme suit dans votre application:

  • Dans AndroidManifest.xml, déclarez un <receiver> Dans SipDemo, il s'agit <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
  • Implémentez le récepteur, qui est une sous-classe de BroadcastReceiver. Dans SipDemo, il s'agit IncomingCallReceiver
  • Initialisez le profil local (SipProfile) avec une intent en attente qui déclenche votre récepteur lorsqu'un utilisateur appelle le profil local.
  • Configurez un filtre d'intent qui filtre les données en fonction de l'action qui représente appel entrant. Dans SipDemo, cette action est android.SipDemo.INCOMING_CALL

Sous-classement de BroadcastReceiver

Pour recevoir des appels, votre application SIP doit sous-classer BroadcastReceiver. Le système Android gère les appels SIP entrants et diffuse un message appeler l'intent (tel que défini par l'application) lorsqu'elle reçoit lors d'un appel. Voici la sous-classe BroadcastReceiver de l'exemple SipDemo.

Kotlin

/**
 * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity.
 */
class IncomingCallReceiver : BroadcastReceiver() {

    /**
     * Processes the incoming call, answers it, and hands it over to the
     * WalkieTalkieActivity.
     * @param context The context under which the receiver is running.
     * @param intent The intent being received.
     */
    override fun onReceive(context: Context, intent: Intent) {
        val wtActivity = context as WalkieTalkieActivity

        var incomingCall: SipAudioCall? = null
        try {
            incomingCall = wtActivity.sipManager?.takeAudioCall(intent, listener)
            incomingCall?.apply {
                answerCall(30)
                startAudio()
                setSpeakerMode(true)
                if (isMuted) {
                    toggleMute()
                }
                wtActivity.call = this
                wtActivity.updateStatus(this)
            }
        } catch (e: Exception) {
            incomingCall?.close()
        }
    }

    private val listener = object : SipAudioCall.Listener() {

        override fun onRinging(call: SipAudioCall, caller: SipProfile) {
            try {
                call.answerCall(30)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

Java

/**
 * Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity.
 */
public class IncomingCallReceiver extends BroadcastReceiver {
    /**
     * Processes the incoming call, answers it, and hands it over to the
     * WalkieTalkieActivity.
     * @param context The context under which the receiver is running.
     * @param intent The intent being received.
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        SipAudioCall incomingCall = null;
        try {
            SipAudioCall.Listener listener = new SipAudioCall.Listener() {
                @Override
                public void onRinging(SipAudioCall call, SipProfile caller) {
                    try {
                        call.answerCall(30);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
            incomingCall = wtActivity.sipManager.takeAudioCall(intent, listener);
            incomingCall.answerCall(30);
            incomingCall.startAudio();
            incomingCall.setSpeakerMode(true);
            if(incomingCall.isMuted()) {
                incomingCall.toggleMute();
            }
            wtActivity.call = incomingCall;
            wtActivity.updateStatus(incomingCall);
        } catch (Exception e) {
            if (incomingCall != null) {
                incomingCall.close();
            }
        }
    }
}

Configurer un filtre d'intent pour recevoir des appels

Lorsque le service SIP reçoit un nouvel appel, il envoie un intent avec fournie par l'application. Dans SipDemo, cette chaîne d'action est android.SipDemo.INCOMING_CALL

Cet extrait de code de SipDemo montre comment l'objet SipProfile est créé avec un intent en attente basé sur la chaîne d'action android.SipDemo.INCOMING_CALL. La L'objet PendingIntent effectue une diffusion lorsque SipProfile reçoit un appel:

Kotlin

val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) {
    SipManager.newInstance(this)
}

var sipProfile: SipProfile? = null
...

val intent = Intent("android.SipDemo.INCOMING_CALL")
val pendingIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA)
sipManager?.open (sipProfile, pendingIntent, null)

Java

public SipManager sipManager = null;
public SipProfile sipProfile = null;
...

Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
sipManager.open(sipProfile, pendingIntent, null);

La diffusion sera interceptée par le filtre d'intent, qui se déclenchera le récepteur (IncomingCallReceiver). Vous pouvez spécifier un intent dans le fichier manifeste de votre application, ou dans le code comme dans SipDemo la méthode onCreate() de l'exemple d'application du Activity de l'application:

Kotlin

class WalkieTalkieActivity : Activity(), View.OnTouchListener {
    ...
    lateinit var callReceiver: IncomingCallReceiver
    ...

    override fun onCreate(savedInstanceState: Bundle) {
        val filter = IntentFilter().apply {
            addAction("android.SipDemo.INCOMING_CALL")
        }
        callReceiver = IncomingCallReceiver()
        this.registerReceiver(callReceiver, filter)
        ...
    }
    ...
}

Java

public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
...
    public IncomingCallReceiver callReceiver;
    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {

       IntentFilter filter = new IntentFilter();
       filter.addAction("android.SipDemo.INCOMING_CALL");
       callReceiver = new IncomingCallReceiver();
       this.registerReceiver(callReceiver, filter);
       ...
    }
    ...
}

Tester les applications SIP

Pour tester les applications SIP, vous avez besoin des éléments suivants:

  • Un appareil mobile équipé d'Android 2.3 ou version ultérieure. Exécution de SIP sur sans fil. Vous devez donc le tester sur un appareil réel. Les tests sur AVD ne fonctionneront pas.
  • Un compte SIP. De nombreux fournisseurs SIP différents proposent des comptes SIP.
  • Si vous passez un appel, celui-ci doit également être destiné à un compte SIP valide.

Pour tester une application SIP:

  1. Sur votre appareil, connectez-vous à un réseau sans fil en sélectionnant Paramètres > Sans fil et réseaux. &gt; Wi-Fi > paramètres Wi-Fi).
  2. Configurez votre appareil mobile pour les tests, comme décrit dans la section Développer sur un appareil.
  3. Exécutez votre application sur votre appareil mobile, comme décrit dans la section Développer sur un appareil.
  4. Si vous utilisez Android Studio, vous pouvez afficher la sortie du journal de l'application en en ouvrant la console du journal des événements (View > Tool Windows > Event Log [Vue > Fenêtres d'outil > Journal des événements]).
  5. Assurez-vous que votre application est configurée pour lancer Logcat automatiquement lorsqu'elle s'exécute: <ph type="x-smartling-placeholder">
      </ph>
    1. Sélectionnez Exécuter > Modifier les configurations.
    2. Sélectionnez l'onglet Miscellaneous (Divers) dans la fenêtre Run/Debug Configurations (Configurations d'exécution/de débogage).
    3. Sous Logcat, sélectionnez Afficher Logcat automatiquement, puis sélectionnez OK.