Mendeteksi eSIM dan kartu SIM
Mendeteksi kartu
Perangkat Android dengan kartu SIM dan eSIM menggunakan ID berikut di telepon API, termasuk [`TelephonyManagerTools/reference/android/telephony/TelephonyManager) dan [`SubscriptionManager tersendiri/reference/android/telephony/SubscriptionManager): * ID Langganan: ID unik untuk langganan seluler. * Indeks atau ID slot logis: indeks unik yang mengacu pada slot SIM logis. ID slot logis dimulai dari 0 dan meningkat tergantung pada jumlah slot aktif yang didukung di perangkat. Misalnya, perangkat SIM ganda biasanya slot 0 dan 1. Jika perangkat memiliki beberapa slot fisik tetapi hanya mendukung satu slot aktif, maka hanya ID slot logis 0. * Indeks atau ID slot fisik: indeks unik yang mengacu pada slot SIM fisik. ID slot fisik dimulai dari 0 dan naik tergantung pada jumlah slot pada perangkat. Ini berbeda dari jumlah slot logis yang ada di perangkat yang sesuai dengan jumlah slot aktif yang dapat dimiliki perangkat gunakan. Misalnya, perangkat yang beralih antara SIM ganda dan SIM tunggal mode selalu memiliki dua slot fisik, tetapi dalam mode SIM tunggal akan memiliki hanya satu slot logis. * ID Kartu: ID unik yang digunakan untuk mengidentifikasi UiccCard. ![Diagram tentang bagaimana ID digunakan dalam kasus dengan dua slot logis dan tiga slot fisik](/images/guide/topics/Connectivity/tel-ids.png) Dalam diagram di atas: * Perangkat memiliki dua slot logis. * Di slot fisik 0 terdapat kartu UICC fisik dengan profil aktif. * Di slot fisik 2 terdapat eUICC dengan profil aktif. * Slot fisik 1 saat ini tidak digunakan. ![Diagram tentang bagaimana ID digunakan pada kasus dengan tiga slot logis dan dua slot fisik](/images/guide/topics/Connectivity/tel-ids-2.png) Dalam diagram di atas: * Perangkat memiliki tiga slot logis. * Di slot fisik 0 terdapat kartu UICC fisik dengan profil aktif. * Dalam slot fisik 1 adalah eUICC yang memiliki dua profil yang diunduh, keduanya aktif menggunakan MEP (Multiple Enabled Profiles).
Ringkasan protokol pemulaian sesi
Android menyediakan API yang mendukung Protokol Pemulaian Sesi (SIP) Hal ini memungkinkan Anda menambahkan fitur telepon internet berbasis SIP ke aplikasi Anda. Android menyertakan stack protokol SIP lengkap dan pengelolaan panggilan terintegrasi layanan yang memungkinkan aplikasi mengatur panggilan suara keluar dan masuk dengan mudah, tanpa harus mengelola sesi, komunikasi tingkat transport, atau audio merekam atau memutar secara langsung.
Berikut adalah contoh jenis aplikasi yang menggunakan SIP API:
- Konferensi video
- Instant messaging
Persyaratan dan batasan
Berikut adalah beberapa persyaratan untuk mengembangkan aplikasi SIP:
- Anda harus memiliki perangkat seluler yang menjalankan Android 2.3 atau yang lebih baru.
- SIP berjalan melalui koneksi data nirkabel, sehingga perangkat Anda harus memiliki data (dengan layanan data seluler atau Wi-Fi). Ini berarti bahwa Anda tidak dapat diuji pada AVD—Anda hanya dapat mengujinya pada perangkat fisik. Untuk mengetahui detailnya, lihat Menguji aplikasi SIP.
- Setiap peserta dalam sesi komunikasi aplikasi harus memiliki Akun SIP. Ada banyak penyedia SIP berbeda yang menawarkan akun SIP.
Catatan: Library android.net.sip
tidak mendukung video
panggilan telepon. Jika Anda ingin menerapkan panggilan VOIP menggunakan stack SIP seperti
android.net.sip
, lihat salah satu dari banyak open source modern
alternatif sebagai dasar untuk
implementasi panggilan VOIP. Sebagai alternatif,
Anda dapat menerapkan
ConnectionService
API untuk memberikan integrasi erat panggilan ini ke Telepon perangkat
.
Antarmuka dan class SIP API
Berikut adalah ringkasan class dan satu antarmuka
(SipRegistrationListener
) yang disertakan dalam SIP Android
API:
Class/Antarmuka | Deskripsi |
---|---|
SipAudioCall |
Menangani panggilan audio Internet melalui SIP. |
SipAudioCall.Listener |
Pemroses untuk peristiwa yang berkaitan dengan panggilan SIP, seperti saat panggilan dilakukan diterima ("sedang berdering") atau panggilan keluar ("sedang menelepon"). |
SipErrorCode |
Menentukan kode error yang ditampilkan selama tindakan SIP. |
SipManager |
Menyediakan API untuk tugas SIP, seperti memulai koneksi SIP, dan memberikan akses ke layanan SIP yang terkait. |
SipProfile |
Menentukan profil SIP, termasuk informasi akun, domain, dan server SIP. |
SipProfile.Builder |
Class helper untuk membuat SipProfile. |
SipSession |
Mewakili sesi SIP yang terkait dengan dialog SIP atau transaksi mandiri bukan dalam dialog. |
SipSession.Listener |
Pemroses untuk peristiwa yang terkait dengan sesi SIP, seperti saat sesi didaftarkan ("sedang mendaftar") atau panggilan keluar ("sedang menelepon"). |
SipSession.State |
Menentukan status sesi SIP, seperti "mendaftar", "panggilan keluar", dan "dalam panggilan". |
SipRegistrationListener |
Antarmuka yang merupakan pemroses untuk peristiwa pendaftaran SIP. |
Membuat manifes
Jika Anda mengembangkan aplikasi yang menggunakan SIP API, ingatlah bahwa hanya didukung pada Android 2.3 (API level 9) dan versi yang lebih tinggi platform ini. Selain itu, di antara perangkat yang menjalankan Android 2.3 (API level 9) atau yang lebih tinggi, tidak semua perangkat akan menawarkan dukungan SIP.
Untuk menggunakan SIP, tambahkan izin berikut ke manifes aplikasi:
android.permission.USE_SIP
android.permission.INTERNET
Untuk memastikan bahwa aplikasi Anda hanya dapat diinstal pada perangkat yang yang mendukung SIP, tambahkan kode berikut ke kolom manifes:
<uses-sdk android:minSdkVersion="9" />
Ini akan mengindikasikan bahwa aplikasi Anda mewajibkan Android 2.3 atau yang lebih tinggi. Sebagai
informasi selengkapnya, lihat
Level API
dan dokumentasi untuk
<uses-sdk>
.
Untuk mengontrol cara memfilter aplikasi Anda dari perangkat yang tidak mendukung SIP (misalnya, di Google Play), tambahkan berikut ini ke manifes:
<uses-feature android:name="android.software.sip.voip" />
Ini akan menegaskan bahwa aplikasi Anda menggunakan SIP API. Deklarasi harus
menyertakan atribut android:required
yang menunjukkan apakah Anda
ingin aplikasi difilter dari perangkat yang tidak menawarkan dukungan SIP.
Deklarasi <uses-feature>
lain mungkin juga diperlukan,
tergantung pada implementasi Anda. Untuk informasi selengkapnya, lihat dokumentasi
untuk
<uses-feature>
.
Jika aplikasi Anda dirancang untuk menerima panggilan, Anda juga harus menentukan penerima (subclass BroadcastReceiver
) dalam manifes aplikasi:
<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
Berikut adalah cuplikan manifes 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>
Membuat SipManager
Untuk menggunakan SIP API, aplikasi Anda harus membuat objek SipManager
. SipManager
mengambil
hal-hal berikut dalam permohonan Anda:
- Memulai sesi SIP.
- Memulai dan menerima panggilan.
- Mendaftarkan dan membatalkan pendaftaran dengan penyedia SIP.
- Memverifikasi konektivitas sesi.
Buat instance SipManager
baru seperti berikut:
Kotlin
val sipManager: SipManager? by lazy(LazyThreadSafetyMode.NONE) { SipManager.newInstance(this) }
Java
public SipManager sipManager = null; ... if (sipManager == null) { sipManager = SipManager.newInstance(this); }
Mendaftar dengan Server SIP
Aplikasi SIP Android umumnya melibatkan satu atau beberapa pengguna, yang masing-masing
memiliki akun SIP. Di aplikasi Android SIP, setiap akun SIP
yang diwakili oleh objek SipProfile
.
SipProfile
menentukan profil SIP, termasuk SIP
akun, serta informasi
domain dan server. Profil yang terkait dengan SIP
akun di perangkat yang menjalankan aplikasi disebut akun lokal
profil Anda. Profil yang terhubung dengan sesi disebut
profil pembanding. Ketika aplikasi SIP Anda {i>
login<i} ke server SIP dengan
SipProfile
lokal, hal ini secara efektif mendaftarkan
sebagai lokasi pengiriman panggilan SIP untuk alamat SIP Anda.
Bagian ini menunjukkan cara membuat SipProfile
,
mendaftarkannya ke server SIP, dan melacak peristiwa pendaftaran.
Buat objek SipProfile
seperti berikut:
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();
Cuplikan kode berikut membuka profil lokal untuk melakukan panggilan dan/atau
menerima panggilan SIP umum. Pemanggil dapat melakukan panggilan berikutnya melalui
mSipManager.makeAudioCall
. Cuplikan ini juga menetapkan tindakan
android.SipDemo.INCOMING_CALL
, yang akan digunakan oleh intent
filter saat perangkat menerima panggilan (lihat Menyiapkan
filter intent untuk menerima panggilan). Berikut adalah langkah pendaftarannya:
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);
Terakhir, kode ini akan menetapkan SipRegistrationListener
di SipManager
. Tindakan ini melacak apakah SipProfile
berhasil didaftarkan dengan layanan SIP Anda
penyedia:
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."); } }
Setelah selesai menggunakan profil, aplikasi Anda harus menutupnya menjadi bebas objek terkait ke dalam memori dan membatalkan pendaftaran perangkat dari server. Contoh:
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); } }
Melakukan panggilan audio
Untuk melakukan panggilan audio, Anda harus memiliki:
SipProfile
yang melakukan panggilan ( "profil lokal"), dan alamat SIP yang valid untuk menerima panggilan ( "profil sejawat").- Objek
SipManager
.
Untuk melakukan panggilan audio, Anda harus menyiapkan SipAudioCall.Listener
. Sebagian besar interaksi klien dengan
tumpukan SIP terjadi melalui pemroses. Dalam cuplikan ini, Anda akan melihat cara SipAudioCall.Listener
menyiapkan beberapa hal setelah panggilan
ditetapkan:
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. } };
Setelah menyiapkan SipAudioCall.Listener
, Anda dapat
menelepon. Metode SipManager
makeAudioCall
menggunakan parameter berikut:
- Profil SIP lokal (pemanggil).
- Profil SIP peer (pengguna yang dipanggil).
SipAudioCall.Listener
untuk mendengarkan panggilan peristiwa dariSipAudioCall
. Dapat berupanull
, tetapi seperti yang ditampilkan di atas, pemroses digunakan untuk menyiapkan berbagai hal setelah panggilan mapan.- Nilai waktu tunggu, dalam detik.
Contoh:
Kotlin
val call: SipAudioCall? = sipManager?.makeAudioCall( sipProfile?.uriString, sipAddress, listener, 30 )
Java
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
Menerima panggilan
Untuk menerima panggilan, aplikasi SIP harus menyertakan subclass BroadcastReceiver
yang memiliki kemampuan untuk merespons intent
yang menunjukkan bahwa
ada panggilan masuk. Dengan demikian, Anda harus melakukan hal berikut
permohonan Anda:
- Di
AndroidManifest.xml
, deklarasikan<receiver>
. Di SipDemo, ini adalah<receiver android:name=".IncomingCallReceiver" android:label="Call Receiver" />
. - Implementasikan penerima, yakni subclass
BroadcastReceiver
. Di SipDemo, ini adalahIncomingCallReceiver
. - Inisialisasi profil lokal (
SipProfile
) dengan intent tertunda yang mengaktifkan penerima Anda saat seseorang memanggil profil lokal. - Siapkan filter intent yang memfilter menurut tindakan yang mewakili
panggilan masuk. Di SipDemo, tindakan ini adalah
android.SipDemo.INCOMING_CALL
.
Memasukkan BroadcastReceiver ke subclass
Untuk menerima panggilan, aplikasi SIP Anda harus memasukkan BroadcastReceiver
ke subclass.
Sistem Android menangani panggilan SIP masuk dan menyiarkan pesan "masuk
"" (sebagaimana didefinisikan oleh aplikasi) saat menerima
panggilan telepon. Berikut adalah
BroadcastReceiver
yang dibuat subclass
kode dari contoh 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(); } } } }
Menyiapkan filter intent untuk menerima panggilan
Ketika menerima panggilan baru, layanan SIP akan mengirimkan intent dengan
string tindakan yang disediakan oleh aplikasi. Dalam SipDemo, string tindakan ini
android.SipDemo.INCOMING_CALL
.
Cuplikan kode dari SipDemo ini menunjukkan cara objek SipProfile
dibuat dengan intent yang tertunda berdasarkan
string tindakan android.SipDemo.INCOMING_CALL
. Tujuan
Objek PendingIntent
akan melakukan siaran saat SipProfile
menerima panggilan:
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);
Siaran akan dicegat oleh filter intent, yang kemudian akan diaktifkan
penerima (IncomingCallReceiver
). Anda dapat menetapkan intent
memfilter di file manifes aplikasi, atau melakukannya dalam kode seperti dalam SipDemo
metode onCreate()
aplikasi contoh
dari Activity
aplikasi:
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); ... } ... }
Menguji aplikasi SIP
Untuk menguji aplikasi SIP, Anda memerlukan beberapa hal berikut:
- Perangkat seluler yang menjalankan Android 2.3 atau yang lebih tinggi. SIP berjalan selama nirkabel, jadi Anda harus mengujinya pada perangkat yang sebenarnya. Pengujian pada AVD tidak akan bekerja.
- Akun SIP. Ada banyak penyedia SIP berbeda yang menawarkan akun SIP.
- Jika Anda melakukan panggilan, panggilan tersebut juga harus dilakukan ke akun SIP yang valid.
Untuk menguji aplikasi SIP:
- Di perangkat, sambungkan ke nirkabel (Setelan > Nirkabel & jaringan > Wi-Fi > Setelan Wi-Fi).
- Siapkan perangkat seluler untuk pengujian, seperti yang dijelaskan dalam Melakukan Pengembangan di Perangkat.
- Jalankan aplikasi Anda di perangkat seluler, seperti yang dijelaskan dalam Melakukan Pengembangan di Perangkat.
- Jika menggunakan Android Studio, Anda dapat melihat output log aplikasi dengan membuka konsol Event Log (View > Tool Windows > Event Log).
- Pastikan aplikasi Anda dikonfigurasi untuk otomatis meluncurkan Logcat saat dijalankan:
- Pilih Run > Edit Configurations.
- Pilih tab Miscellaneous di jendela Run/Debug Configurations.
- Di bagian Logcat, pilih Show logcat automatically, lalu pilih OK.