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 deSipAudioCall
. Pode sernull
, 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:
- Em seu dispositivo, conecte-se a uma rede sem fio (Configurações > Redes sem fio e outras > Wi-Fi > configurações de Wi-Fi).
- Configure seu dispositivo móvel para testes, conforme descrito em Executar apps em um dispositivo de hardware.
- Execute seu aplicativo no dispositivo móvel, conforme descrito em Executar apps em um dispositivo de hardware.
- 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).
- Verifique se o aplicativo está configurado para iniciar o Logcat automaticamente ao ser executado:
- Selecione Run > Edit Configurations.
- Selecione a guia Miscellaneous na janela Run/Debug Configurations.
- Em Logcat, selecione Show logcat automaticamente e, em seguida, Selecione OK.