Visão geral do Session Initiation Protocol (SIP)

Detectar eSIMs e chips

Detectando cards

Dispositivos Android com chips e eSIMs usam os seguintes IDs na telefonia APIs, incluindo [`TelephonyManager`](/reference/android/telephony/TelephonyManager) e [`SubscriptionManager`](/reference/android/telephony/SubscriptionManager): * ID de assinatura: ID exclusivo para uma assinatura de dispositivo móvel. * Índice lógico de slot ou ID: índice exclusivo referente a um slot de chip lógico. Os IDs de slots lógicos começam em 0 e aumentam dependendo do número de com suporte nos slots ativos do dispositivo. Por exemplo, um dispositivo dual chip normalmente tem slots 0 e 1. Se um dispositivo tiver vários slots físicos, mas apenas for compatível com um slot ativo, ele terá apenas o ID de slot lógico "0". * Índice ou ID de slot físico: índice exclusivo referente a um slot de chip físico. Os IDs de slots físicos começam em 0 e aumentam de acordo com o número nos slots do dispositivo. Isso difere do número de slots lógicos de um dispositivo que corresponde ao número de slots ativos que um dispositivo pode usando. Por exemplo, um dispositivo que alterna entre dois chips e um único chip pode sempre ter dois slots físicos, mas no modo de chip único ele terá apenas um slot lógico. * ID do cartão: código exclusivo usado para identificar um UiccCard. ![Um diagrama de como os IDs são usados em um caso com dois slots lógicos e três slots físicos](/images/guide/topics/connectivity/tel-ids.png) No diagrama acima: * O dispositivo tem dois slots lógicos. * No slot 0 físico, há um cartão UICC físico com um perfil ativo. * No slot 2 físico, há um eUICC com um perfil ativo. * O slot físico 1 não está em uso no momento. ![Um diagrama de como os IDs são usados em um caso com três slots lógicos e dois slots físicos](/images/guide/topics/connectivity/tel-ids-2.png) No diagrama acima: * O dispositivo tem três slots lógicos. * No slot 0 físico, há um cartão UICC físico com um perfil ativo. * No slot físico 1, há um eUICC com dois perfis baixados, ambos ativos usando o MEP (vários perfis ativados).

Visão geral do protocolo de início de sessão

O Android oferece uma API compatível com o Protocolo de início de sessão (SIP, na sigla em inglês). Isso permite que você adicione recursos de telefonia via Internet baseados em SIP aos seus aplicativos. O Android inclui uma pilha de protocolos SIP completa e um gerenciamento de chamadas integrado serviços que permitem que os aplicativos configurem facilmente chamadas de voz recebidas e efetuadas, sem precisar gerenciar sessões, comunicações de transporte ou áudios gravar ou reproduzir diretamente.

Veja alguns exemplos dos tipos de aplicativos que podem usar a API SIP:

  • Videoconferência
  • Mensagem instantânea

Requisitos e limitações

Veja os requisitos para desenvolver um aplicativo com SIP:

  • Você precisa ter um dispositivo móvel com o Android 2.3 ou versão posterior.
  • Como o SIP é executado em uma conexão de dados sem fio, seu dispositivo precisa ter uma (com um serviço de dados móveis ou Wi-Fi). Isso significa que você Não é possível testar no AVD. Só é possível testar em um dispositivo físico. Para mais detalhes, consulte Como testar aplicativos SIP.
  • Cada participante da sessão de comunicação do aplicativo precisa ter Conta SIP. Há muitos provedores SIP diferentes que oferecem contas SIP.

Observação:a biblioteca android.net.sip não tem suporte a vídeos chamadas. Se você deseja implementar chamadas VOIP usando uma pilha SIP como android.net.sip, conheça um dos vários modelos de código alternativas como base para qualquer implementação de chamada VOIP. Como alternativa, é possível implementar ConnectionService API para fornecer uma integração forte dessas chamadas no Telefone do dispositivo app.

Classes e interfaces da API SIP

Este é um resumo das classes e de uma interface (SipRegistrationListener) incluídos no SIP do Android API:

Classe/interface Descrição
SipAudioCall Processa uma chamada de áudio de Internet por meio do SIP.
SipAudioCall.Listener Listener para eventos relacionados a uma chamada SIP, como quando uma chamada está sendo recebidas ("ao tocar") ou quando uma ligação for realizada ("ligando").
SipErrorCode Define os códigos de erro retornados durante ações SIP.
SipManager Fornece APIs para tarefas SIP, como iniciar conexões SIP, e fornece acesso a serviços SIP relacionados.
SipProfile Define um perfil SIP, incluindo uma conta SIP e informações de domínio e servidor.
SipProfile.Builder Classe auxiliar para a criação de um SipProfile.
SipSession Representa uma sessão SIP que está associada a uma caixa de diálogo SIP ou uma transação independente está fora de uma caixa de diálogo.
SipSession.Listener Listener para eventos relacionados a uma sessão SIP, como quando uma sessão está sendo registrada ("registrando") ou sendo efetuada ("ligando").
SipSession.State Define os estados de sessões SIP, como "registrando", "chamada realizada" e "em chamada".
SipRegistrationListener Uma interface que é um listener para eventos de registro SIP.

Criar um manifesto

Se você estiver desenvolvendo um aplicativo que usa a API SIP, lembre-se de que o tem suporte apenas no Android 2.3 (API de nível 9) e em versões mais recentes do na plataforma. Além disso, entre dispositivos com o Android 2.3 (nível 9 da API) ou versões mais recentes, nem todos os dispositivos oferecem suporte a SIP.

Para usar o SIP, adicione as seguintes permissões ao manifesto do seu aplicativo:

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

Para garantir que seu aplicativo só possa ser instalado em dispositivos compatíveis com SIP, adicione o seguinte ao comando manifesto do app:

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

Isso indica que o aplicativo requer o Android 2.3 ou posterior. Para mais informações, consulte Níveis de API e a documentação <uses-sdk> .

Para controlar como o aplicativo é filtrado em dispositivos sem suporte SIP (por exemplo, no Google Play), adicione o seguinte ao código manifesto do app:

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

Isso declara que seu aplicativo usa a API SIP. A declaração precisa inclua um atributo android:required que indica se você quer que o aplicativo seja filtrado de dispositivos que não oferecem suporte a SIP. Outras declarações <uses-feature> também podem ser necessárias. dependendo da implementação. Para mais informações, consulte a documentação para o <uses-feature> .

Se o aplicativo for projetado para receber chamadas, também será necessário definir um destinatário (subclasse BroadcastReceiver) no manifesto do aplicativo:

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

Veja trechos do manifesto 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>

Criar o SipManager

Para usar a API SIP, seu aplicativo precisa criar um objeto SipManager. A SipManager leva cuidar do seguinte no seu aplicativo:

  • Iniciar sessões SIP.
  • Iniciar e receber chamadas.
  • Registrar e cancelar o registro com um provedor SIP.
  • Verificar a conectividade da sessão.

Instancie um novo SipManager da seguinte forma:

Kotlin

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

Java

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

Como registrar-se com um servidor SIP

Um aplicativo SIP Android típico envolve um ou mais usuários, cada um dos quais tem uma conta SIP. Em um aplicativo SIP para Android, cada conta SIP é representada por um objeto SipProfile.

Um SipProfile define um perfil SIP, incluindo um SIP conta e informações de domínio e servidor. O perfil associado ao SIP no dispositivo que executa o aplicativo é chamada de de usuário. O perfil ao qual a sessão está conectada é chamado de perfil semelhante. Quando seu aplicativo SIP faz login no servidor SIP com o SipProfile local, ele registra efetivamente o dispositivo como o local para enviar chamadas SIP para seu endereço SIP.

Esta seção mostra como criar um SipProfile, registrá-lo com um servidor SIP e rastrear eventos de registro.

Crie um objeto SipProfile da seguinte forma:

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();

O trecho de código a seguir abre o perfil local para fazer chamadas e/ou receber chamadas SIP genéricas. O autor da chamada pode fazer chamadas subsequentes pelo mSipManager.makeAudioCall: Esse trecho também inicia a ação android.SipDemo.INCOMING_CALL, que será usado por uma intent quando o dispositivo recebe uma chamada (consulte Como configurar um filtro de intent para receber chamadas). Esta é a etapa de registro:

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);

Por fim, este código define um SipRegistrationListener no SipManager. Esta ação rastreia se o SipProfile foi registrado com o serviço SIP provedor:

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.");
    }
}

Quando seu aplicativo terminar de usar um perfil, ele deverá fechá-lo para liberar objetos associados na memória e cancele a inscrição do dispositivo no servidor. Por exemplo:

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);
     }
}

Fazer uma chamada de áudio

Para fazer uma chamada de áudio, é preciso ter o seguinte:

  • Um SipProfile que está fazendo a chamada (o "perfil local") e um endereço SIP válido para receber a chamada (o "perfil semelhante").
  • Um objeto SipManager.

Para fazer uma chamada de áudio, configure um SipAudioCall.Listener. Grande parte da interação do cliente a pilha SIP acontece por meio de listeners. Neste snippet, você vê como o SipAudioCall.Listener faz as configurações após a chamada ser estabelecida:

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.
   }
};

Depois de configurar o SipAudioCall.Listener, você poderá fazer a chamada. Método SipManager makeAudioCall usa os seguintes parâmetros:

  • Um perfil SIP local (o autor da chamada).
  • Um perfil SIP semelhante (o usuário que recebe a chamada).
  • Uma SipAudioCall.Listener para ouvir a ligação eventos de SipAudioCall. Pode ser null, mas, como mostrado acima, o listener é usado para definir as configurações quando a chamada é estabelecidos.
  • O valor de tempo limite, em segundos.

Exemplo:

Kotlin

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

Java

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

Receber chamadas

Para receber chamadas, um aplicativo SIP precisa incluir uma subclasse de BroadcastReceiver que possa responder a uma intent indicando que há uma chamada recebida. Portanto, você deve fazer o seguinte em seu aplicativo:

  • Em AndroidManifest.xml, declare um <receiver>. Em SipDemo, é <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
  • Implemente o destinatário, que é uma subclasse de BroadcastReceiver. Em SipDemo, é IncomingCallReceiver
  • Inicialize o perfil local (SipProfile) com uma intent pendente que dispara seu destinatário quando alguém liga para o perfil local.
  • Configure um filtro de intent que filtre pela ação que representa uma receber uma ligação. Em SipDemo, essa ação é android.SipDemo.INCOMING_CALL

Criar uma subclasse de BroadcastReceiver

Para receber chamadas, seu aplicativo SIP precisa ter a subclasse BroadcastReceiver. O O sistema Android processa chamadas SIP recebidas e transmite uma call" (conforme definido pelo aplicativo) ao receber uma ligação. Este é o BroadcastReceiver com subclasses do exemplo SipDemo (link em inglês).

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();
            }
        }
    }
}

Como configurar um filtro de intent para receber chamadas

Quando o serviço SIP recebe uma nova chamada, ele envia uma intent com a string de ação fornecida pelo aplicativo. No SipDemo, essa string de ação é android.SipDemo.INCOMING_CALL:

Este trecho de código da SipDemo (link em inglês) mostra como o objeto SipProfile é criado com uma intent pendente com base na a string de ação android.SipDemo.INCOMING_CALL. A O objeto PendingIntent vai realizar uma transmissão quando o SipProfile receber uma chamada:

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);

A transmissão será interceptada pelo filtro de intent, que acionará então o receptor (IncomingCallReceiver). É possível especificar uma intent filtrar no arquivo de manifesto do aplicativo ou em código, como em SipDemo método onCreate() do aplicativo de exemplo do Activity do aplicativo:

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);
       ...
    }
    ...
}

Testar aplicativos SIP

Para testar aplicativos SIP, você precisa do seguinte:

  • Um dispositivo móvel com o Android 2.3 ou versões posteriores. O SIP é executado em sem fio, então você precisa testar em um dispositivo real. Não é possível realizar os testes no AVD.
  • Uma conta SIP. Há muitos provedores SIP diferentes que oferecem contas SIP.
  • Se você fizer uma chamada, ela também precisará ser para uma conta SIP válida.

Para testar um aplicativo SIP:

  1. Em seu dispositivo, conecte-se a uma rede sem fio (Configurações > Redes sem fio e outras &gt; Wi-Fi > configurações de Wi-Fi).
  2. Configure seu dispositivo móvel para testes, conforme descrito em Executar apps em um dispositivo de hardware.
  3. Execute seu aplicativo no dispositivo móvel, conforme descrito em Executar apps em um dispositivo de hardware.
  4. Se estiver usando o Android Studio, é possível ver a saída do registro do aplicativo Abra o console do log de eventos (Exibir > Janelas de ferramentas > Log de eventos).
  5. Verifique se o aplicativo está configurado para iniciar o Logcat automaticamente ao ser executado:
    1. Selecione Run > Edit Configurations.
    2. Selecione a guia Miscellaneous na janela Run/Debug Configurations.
    3. Em Logcat, selecione Show logcat automaticamente e, em seguida, Selecione OK.