Rileva eSIM e schede SIM
Rilevamento delle schede
I dispositivi Android con schede SIM e eSIM utilizzano i seguenti ID nel servizio di telefonia API, tra cui ["TelephonyManager"](/reference/android/telephony/TelephonyManager) e ["SubscriptionManager"](/reference/android/telephony/SubscriptionManager): * ID abbonamento: ID univoco di un abbonamento mobile. * Indice o ID dello slot logico: indice univoco che fa riferimento a uno slot della SIM logica. Gli ID slot logici iniziano da 0 e aumentano in base al numero di slot attivi supportati su un dispositivo. Ad esempio, un dispositivo dual SIM in genere ha gli slot 0 e 1. Se un dispositivo ha più slot fisici, ma solo supporta uno slot attivo, avrà solo l'ID slot logico 0. * Indice o ID dello slot fisico: indice univoco che fa riferimento a uno slot fisico della SIM. Gli ID degli slot fisici iniziano da 0 e aumentano in base al numero di slot fisici slot sul dispositivo. È diverso dal numero di slot logici su un dispositivo che corrisponde al numero di slot attivi di cui può disporre un dispositivo che utilizzano. Ad esempio, un dispositivo che passa dalla modalità dual SIM a quella singola SIM e viceversa può avere sempre due slot fisici, mentre in modalità SIM singola avrà uno slot logico. * ID carta: ID univoco utilizzato per identificare una UiccCard. ![Un diagramma di come gli ID vengono utilizzati in una richiesta con due slot logici e tre slot fisici](/images/guide/topics/connectivity/tel-ids.png) Nel diagramma riportato sopra: * Il dispositivo ha due slot logici. * Nello slot fisico 0 è presente una scheda UICC fisica con un profilo attivo. * Nello slot fisico 2 è presente una eUICC con un profilo attivo. * Lo slot fisico 1 non è attualmente in uso. ![Un diagramma di come gli ID vengono utilizzati in un caso con tre slot logici e due slot fisici](/images/guide/topics/connectivity/tel-ids-2.png) Nel diagramma riportato sopra: * Il dispositivo ha tre slot logici. * Nello slot fisico 0 è presente una scheda UICC fisica con un profilo attivo. * Nello slot fisico 1 c'è una eUICC che ha due profili scaricati, entrambi attivi mediante MEP (Multiple Enabled Profiles).
Panoramica del protocollo di avvio della sessione
Android mette a disposizione un'API che supporta il protocollo SIP (Session Initiation Protocol). Ciò ti consente di aggiungere alle tue applicazioni funzionalità di telefonia internet basate su SIP. Android include uno stack di protocollo SIP completo e una gestione delle chiamate integrata che permettono alle applicazioni di configurare facilmente le chiamate vocali in entrata e in uscita, senza dover gestire sessioni, comunicazioni a livello di trasporto o audio registrare o riprodurre direttamente i contenuti.
Ecco alcuni esempi dei tipi di applicazioni che potrebbero utilizzare l'API SIP:
- Videoconferenze
- Messaggistica immediata
Requisiti e limitazioni
Di seguito sono riportati i requisiti per lo sviluppo di un'applicazione SIP:
- Devi avere un dispositivo mobile con Android 2.3 o versioni successive.
- Il protocollo SIP viene eseguito tramite una connessione dati wireless, quindi il dispositivo deve disporre di una connessione dati (con un servizio dati mobile o Wi-Fi). Ciò significa che non possono eseguire test sulla durata di visualizzazione media: il test può essere eseguito solo su un dispositivo fisico. Per maggiori dettagli, vedi Test delle applicazioni SIP.
- Ciascun partecipante alla sessione di comunicazione dell'applicazione deve avere un Account SIP. Esistono diversi fornitori SIP che offrono account SIP.
Nota: la raccolta android.net.sip
non supporta i video.
chiamate. Se vuoi implementare le chiamate VOIP utilizzando uno stack SIP come
android.net.sip
, dai un'occhiata a una delle tante moderne applicazioni
alternative come base per qualsiasi implementazione di chiamate VoIP. In alternativa,
puoi implementare
ConnectionService
API per fornire una stretta integrazione di queste chiamate nel Telefono del dispositivo
dell'app.
Classi e interfacce dell'API SIP
Ecco un riepilogo dei corsi e un'interfaccia
(SipRegistrationListener
) inclusi nel SIP di Android
API:
Classe/interfaccia | Descrizione |
---|---|
SipAudioCall |
Gestisce una chiamata audio internet tramite SIP. |
SipAudioCall.Listener |
Listener di eventi relativi a una chiamata SIP, ad esempio quando è in corso una chiamata ricevuto ("squillo") o una chiamata in uscita ("in chiamata"). |
SipErrorCode |
Definisce i codici di errore restituiti durante le azioni SIP. |
SipManager |
Fornisce API per attività SIP, ad esempio l'avvio di connessioni SIP e fornisce l'accesso ai servizi SIP correlati. |
SipProfile |
Definisce un profilo SIP, incluse le informazioni di un account SIP, di dominio e di server. |
SipProfile.Builder |
lezione di supporto per la creazione di un profilo SIP. |
SipSession |
Rappresenta una sessione SIP associata a una finestra di dialogo SIP o a una transazione autonoma non all'interno di una finestra di dialogo. |
SipSession.Listener |
Listener di eventi relativi a una sessione SIP, ad esempio quando una sessione viene registrata ("in registrazione") o in uscita ("in chiamata"). |
SipSession.State |
Definisce gli stati della sessione SIP, ad esempio "registrazione", "chiamata in uscita" e "in chiamata". |
SipRegistrationListener |
Un'interfaccia che funge da listener per gli eventi di registrazione SIP. |
Creazione del manifest in corso...
Se stai sviluppando un'applicazione che utilizza l'API SIP, ricorda che la classe è supportata soltanto su Android 2.3 (livello API 9) e versioni successive di della piattaforma. Inoltre, tra i dispositivi con Android 2.3 (livello API 9) o versioni successive, non tutti i dispositivi offrono il supporto SIP.
Per utilizzare SIP, aggiungi le seguenti autorizzazioni al file manifest dell'applicazione:
android.permission.USE_SIP
android.permission.INTERNET
Per assicurarti che l'applicazione possa essere installata solo su dispositivi che in grado di supportare SIP, aggiungi quanto segue all'interfaccia manifest:
<uses-sdk android:minSdkVersion="9" />
Questo indica che la tua applicazione richiede Android 2.3 o versioni successive. Per
ulteriori informazioni, vedi
Livelli API
e la documentazione per gli sviluppatori
<uses-sdk>
.
Per controllare in che modo la tua applicazione viene filtrata dai dispositivi che non supportano SIP (ad esempio su Google Play), aggiungi quanto segue al manifest:
<uses-feature android:name="android.software.sip.voip" />
Indica che la tua applicazione utilizza l'API SIP. La dichiarazione dovrebbe
includi un attributo android:required
che indichi se
Vuoi che l'applicazione venga filtrata dai dispositivi che non offrono supporto SIP.
Potrebbero essere necessarie anche altre dichiarazioni <uses-feature>
.
a seconda dell'implementazione. Per ulteriori informazioni, consulta la documentazione
per
<uses-feature>
.
Se l'applicazione è progettata per ricevere chiamate, devi anche definire un ricevitore (sottoclasse BroadcastReceiver
) nel file manifest dell'applicazione:
<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
Ecco alcuni estratti del manifest 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>
Creazione di SipManager
Per utilizzare l'API SIP, l'applicazione deve creare un oggetto SipManager
. SipManager
richiede
nella tua applicazione:
- Avvio delle sessioni SIP.
- Avvio e ricezione di chiamate.
- Registrazione e annullamento della registrazione con un provider SIP.
- Verifica della connettività della sessione in corso...
Crea un'istanza per un nuovo SipManager
nel seguente modo:
Kotlin
val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) { SipManager.newInstance(this) }
Java
public SipManager sipManager = null; ... if (sipManager == null) { sipManager = SipManager.newInstance(this); }
Registrazione con un server SIP
Una tipica applicazione SIP Android coinvolge uno o più utenti, ognuno dei quali
ha un account SIP. In un'applicazione SIP Android, ogni account SIP
rappresentato da un oggetto SipProfile
.
Un SipProfile
definisce un profilo SIP, incluso un SIP
l'account, il dominio e le informazioni del server. Il profilo associato al SIP
l'account di servizio sul dispositivo su cui è in esecuzione l'applicazione è chiamato
profilo. Il profilo a cui è connessa la sessione è chiamato
profilo peer. Quando l'applicazione SIP accede al server SIP con
il SipProfile
locale, questo registra in modo efficace
dispositivo come posizione a cui inviare le chiamate SIP per il tuo indirizzo SIP.
Questa sezione spiega come creare un SipProfile
,
registrarlo con un server SIP e monitorare gli eventi di registrazione.
Puoi creare un oggetto SipProfile
nel seguente modo:
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();
Il seguente estratto di codice apre il profilo locale per effettuare chiamate e/o
la ricezione di chiamate SIP generiche. Il chiamante può effettuare chiamate successive utilizzando
mSipManager.makeAudioCall
. Questo estratto definisce anche l'azione
android.SipDemo.INCOMING_CALL
, che verrà utilizzata da un intent
filtra quando il dispositivo riceve una chiamata (vedi Configurazione
un filtro per intent per ricevere chiamate). Questo è il passaggio di registrazione:
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);
Infine, questo codice imposta un SipRegistrationListener
in SipManager
. Monitora se SipProfile
è stato registrato correttamente con il tuo servizio SIP
fornitore:
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 l'applicazione ha finito di utilizzare un profilo, dovrebbe chiuderlo gli oggetti associati in memoria e annullare la registrazione del dispositivo dal server. Per esempio:
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); } }
Effettuare una chiamata audio
Per effettuare una chiamata audio, devi disporre di quanto segue:
- Un
SipProfile
che sta effettuando la chiamata (il "profilo locale") e un indirizzo SIP valido per ricevere la chiamata (il "profilo peer"). - Un oggetto
SipManager
.
Per effettuare una chiamata audio, devi configurare un SipAudioCall.Listener
. Gran parte dell'interazione del cliente con
lo stack SIP avviene tramite listener. In questo snippet puoi vedere come viene configurato SipAudioCall.Listener
al termine della chiamata
data di creazione:
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. } };
Dopo aver configurato SipAudioCall.Listener
, puoi
effettuare la chiamata. Il metodo SipManager
makeAudioCall
richiede i seguenti parametri:
- Un profilo SIP locale (il chiamante).
- Un profilo SIP peer (l'utente chiamato).
- Un
SipAudioCall.Listener
per ascoltare la chiamata eventi daSipAudioCall
. Può esserenull
, ma, come mostrato sopra, il listener viene utilizzato per configurare le impostazioni una volta che la chiamata viene la creazione di un progetto. - Il valore di timeout, in secondi.
Ad esempio:
Kotlin
val call: SipAudioCall? = sipManager?.makeAudioCall( sipProfile?.uriString, sipAddress, listener, 30 )
Java
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
Ricevere chiamate
Per ricevere chiamate, un'applicazione SIP deve includere una sottoclasse BroadcastReceiver
in grado di rispondere a un intent
a indicare che c'è una chiamata in arrivo. Pertanto, devi eseguire le seguenti operazioni
la tua applicazione:
- In
AndroidManifest.xml
, dichiara<receiver>
. In SipDemo,<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
. - Implementa il ricevitore, che è una sottoclasse di
BroadcastReceiver
. In SipDemo,IncomingCallReceiver
. - Inizializza il profilo locale (
SipProfile
) con un intent in attesa che attiva il destinatario quando qualcuno chiama il profilo locale. - Configura un filtro per intent che filtri in base all'azione che rappresenta un
chiamata in arrivo. In SipDemo, questa azione
android.SipDemo.INCOMING_CALL
.
BroadcastRicevir per la creazione di sottoclassi
Per ricevere chiamate, l'applicazione SIP deve avere la sottoclasse BroadcastReceiver
. La
Il sistema Android gestisce le chiamate SIP in arrivo e trasmette il messaggio "In arrivo
call" intent (come definito dall'applicazione) quando riceve
una chiamata. Ecco la sottoclasse
BroadcastReceiver
dall'esempio 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(); } } } }
Configurare un filtro per intent per ricevere chiamate
Quando il servizio SIP riceve una nuova chiamata, invia un intent con
stringa di azione fornita dall'applicazione. In SipDemo, questa stringa di azione è
android.SipDemo.INCOMING_CALL
.
Questo estratto di codice da SipDemo mostra come viene creato l'oggetto SipProfile
con un intent in attesa basato su
la stringa di azioni android.SipDemo.INCOMING_CALL
. La
L'oggetto PendingIntent
eseguirà una trasmissione quando l'SipProfile
riceve una chiamata:
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 trasmissione verrà intercettata dal filtro per intent, che verrà quindi attivato
il destinatario (IncomingCallReceiver
). Puoi specificare un intent
filtrare nel file manifest dell'applicazione o farlo nel codice come in SipDemo
metodo onCreate()
dell'applicazione di esempio
dei Activity
dell'applicazione:
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); ... } ... }
Test delle applicazioni SIP
Per testare le applicazioni SIP, occorre quanto segue:
- Un dispositivo mobile con Android 2.3 o versioni successive. Esecuzioni SIP oltre wireless, quindi devi testarlo su un dispositivo reale. I test sulla durata di visualizzazione media non funzionano.
- Un account SIP. Esistono diversi fornitori SIP che offrono account SIP.
- Se stai effettuando una chiamata, deve essere anche a un account SIP valido.
Per testare un'applicazione SIP:
- Sul dispositivo, connettiti alla rete wireless (Impostazioni > Wireless e reti) > Wi-Fi > impostazioni Wi-Fi).
- Configura il dispositivo mobile per i test, come descritto nella sezione Sviluppare su un dispositivo.
- Esegui l'applicazione sul tuo dispositivo mobile, come descritto nella sezione Sviluppo su un dispositivo.
- Se utilizzi Android Studio, puoi visualizzare l'output del log dell'applicazione aprendo la console Log eventi (Visualizza > Finestre strumenti > Registro eventi).
- Assicurati che l'applicazione sia configurata per avviare automaticamente Logcat durante l'esecuzione:
- Seleziona Esegui > Modifica configurazioni.
- Seleziona la scheda Varie nella finestra Configurazioni esecuzione/debug.
- In Logcat, seleziona Mostra logcat automaticamente, quindi Seleziona OK.