Ringkasan protokol inisiasi sesi

Mendeteksi eSIM dan kartu SIM

Mendeteksi kartu

Perangkat Android dengan kartu SIM dan eSIM menggunakan ID berikut dalam API telepon, termasuk [`TelephonyManager {/8}/reference/android/telephony/TelephonyManager) dan [`SubscriptionManager {/8}/reference/android/telephony/SubscriptionManager): * ID langganan: ID unik untuk langganan seluler. * Indeks atau ID slot logis: indeks unik yang merujuk pada slot SIM logis. ID slot logis dimulai dari 0 dan naik, tergantung jumlah slot aktif yang didukung pada perangkat. Misalnya, perangkat SIM ganda biasanya memiliki slot 0 dan slot 1. Jika perangkat memiliki beberapa slot fisik tetapi hanya mendukung satu slot aktif, perangkat tersebut hanya akan memiliki ID slot logis 0. * Indeks atau ID slot fisik: indeks unik yang merujuk pada slot SIM fisik. ID slot fisik dimulai dari 0 dan naik, tergantung jumlah slot fisik pada perangkat. Jumlah slot logis yang dimiliki perangkat berbeda dengan jumlah slot aktif yang dapat digunakan oleh perangkat. Misalnya, perangkat yang beralih antara mode SIM ganda dan SIM tunggal mungkin selalu memiliki dua slot fisik, tetapi dalam mode SIM tunggal, perangkat hanya akan memiliki satu slot logis. * ID Kartu: ID unik yang digunakan untuk mengidentifikasi UiccCard. ![Diagram penggunaan ID 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 ada kartu UICC fisik dengan profil aktif. * Di slot fisik 2 terdapat eUICC dengan profil aktif. * Slot fisik 1 saat ini tidak digunakan. ![Diagram penggunaan ID dalam kasus dengan tiga slot logis dan dua slot fisik](/images/guide/topics/connectivity/tel-ids-2.png) Pada diagram di atas: * Perangkat memiliki tiga slot logis. * Di slot fisik 0 ada kartu UICC fisik dengan profil aktif. * Dalam slot fisik 1 terdapat eUICC yang memiliki dua profil yang didownload, 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 layanan pengelolaan panggilan terintegrasi yang memungkinkan aplikasi dengan mudah menyiapkan panggilan suara keluar dan masuk, tanpa harus mengelola sesi, komunikasi tingkat transport, atau rekaman audio atau pemutaran 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 koneksi data (dengan layanan data seluler atau Wi-Fi). Ini berarti Anda tidak dapat menguji pada AVD—Anda hanya dapat menguji di 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 panggilan video. Jika Anda ingin mengimplementasikan panggilan VOIP menggunakan stack SIP seperti android.net.sip, lihat salah satu dari banyak alternatif open source modern sebagai dasar untuk setiap implementasi panggilan VOIP. Atau, Anda dapat menerapkan ConnectionService API untuk memberikan integrasi yang erat dari panggilan ini ke aplikasi Telepon di perangkat.

Antarmuka dan class SIP API

Berikut adalah ringkasan class dan satu antarmuka (SipRegistrationListener) yang disertakan dalam Android SIP API:

Class/Antarmuka Deskripsi
SipAudioCall Menangani panggilan audio Internet melalui SIP.
SipAudioCall.Listener Pemroses untuk peristiwa yang berkaitan dengan panggilan SIP, seperti saat panggilan diterima ("sedang berdering") atau panggilan sedang keluar ("sedang memanggil").
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 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 tidak dalam dialog.
SipSession.Listener Pemroses untuk peristiwa yang berkaitan dengan sesi SIP, seperti ketika sesi sedang didaftarkan ("saat mendaftar") atau panggilan sedang keluar ("sedang memanggil").
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, ingat bahwa fitur ini hanya didukung di Android 2.3 (API level 9) dan versi platform yang lebih baru. 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 aplikasi Anda hanya dapat diinstal di perangkat yang mampu mendukung SIP, tambahkan kode berikut ke manifes aplikasi Anda:

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

Ini akan mengindikasikan bahwa aplikasi Anda mewajibkan Android 2.3 atau yang lebih tinggi. Untuk mengetahui informasi selengkapnya, lihat Level API dan dokumentasi untuk elemen <uses-sdk>.

Untuk mengontrol cara memfilter aplikasi Anda dari perangkat yang tidak mendukung SIP (misalnya, di Google Play), tambahkan kode berikut ke manifes aplikasi Anda:

<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> lainnya mungkin juga diperlukan, bergantung pada implementasi Anda. Untuk mengetahui informasi selengkapnya, lihat dokumentasi untuk elemen <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 menangani hal-hal berikut dalam aplikasi 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 standar melibatkan satu atau beberapa pengguna, yang masing-masing memiliki akun SIP. Di aplikasi SIP Android, setiap akun SIP diwakili oleh objek SipProfile.

SipProfile menentukan profil SIP, termasuk akun SIP, serta informasi domain dan server. Profil yang dikaitkan dengan akun SIP di perangkat yang menjalankan aplikasi disebut profil lokal. Profil yang terhubung ke sesi ini disebut profil peer. Saat aplikasi SIP Anda login ke server SIP dengan SipProfile lokal, tindakan ini secara efektif akan mendaftarkan perangkat sebagai lokasi untuk mengirim panggilan SIP untuk alamat SIP Anda.

Bagian ini menunjukkan cara membuat SipProfile, mendaftarkannya dengan 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 filter intent 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. Kode ini melacak apakah SipProfile berhasil didaftarkan dengan penyedia layanan SIP Anda:

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 untuk membebaskan 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 membuat panggilan (" profil lokal"), dan alamat SIP yang valid untuk menerima panggilan (" profil peer").
  • Objek SipManager.

Untuk melakukan panggilan audio, Anda harus menyiapkan SipAudioCall.Listener. Sebagian besar interaksi klien dengan stack SIP terjadi melalui pemroses. Dalam cuplikan ini, Anda akan melihat cara SipAudioCall.Listener menyiapkan beberapa hal setelah panggilan dibuat:

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 melakukan panggilan. Metode SipManager makeAudioCall menggunakan parameter berikut:

  • Profil SIP lokal (pemanggil).
  • Profil SIP peer (pengguna yang dipanggil).
  • SipAudioCall.Listener untuk memproses peristiwa panggilan dari SipAudioCall. Nilai ini dapat berupa null, tetapi seperti yang ditunjukkan di atas, pemroses digunakan untuk menyiapkan beberapa hal setelah panggilan dibuat.
  • 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 dalam aplikasi:

  • 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 adalah IncomingCallReceiver.
  • Lakukan inisialisasi profil lokal (SipProfile) dengan intent tertunda yang mengaktifkan penerima Anda saat seseorang memanggil profil lokal.
  • Siapkan filter intent yang memfilter berdasarkan 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 yang masuk dan menyiarkan intent "panggilan masuk" (seperti yang ditentukan oleh aplikasi) saat menerima panggilan. Berikut adalah kode BroadcastReceiver yang dibuat subclass-nya 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

Saat menerima panggilan baru, layanan SIP akan mengirimkan intent dengan string tindakan yang disediakan oleh aplikasi. Di SipDemo, string tindakan ini adalah android.SipDemo.INCOMING_CALL.

Cuplikan kode dari SipDemo ini menunjukkan cara objek SipProfile dibuat dengan intent tertunda berdasarkan string tindakan android.SipDemo.INCOMING_CALL. 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 mengaktifkan penerima (IncomingCallReceiver). Anda dapat menentukan filter intent dalam file manifes aplikasi, atau melakukannya dalam kode seperti dalam metode onCreate() aplikasi contoh SipDemo 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 melalui nirkabel, sehingga Anda harus melakukan pengujian di 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:

  1. Di perangkat, hubungkan ke nirkabel (Setelan > Nirkabel & jaringan > Wi-Fi > Setelan Wi-Fi).
  2. Siapkan perangkat seluler untuk pengujian, seperti yang dijelaskan dalam Melakukan Pengembangan di Perangkat.
  3. Jalankan aplikasi Anda di perangkat seluler, seperti yang dijelaskan dalam Melakukan Pengembangan di Perangkat.
  4. Jika menggunakan Android Studio, Anda dapat melihat output log aplikasi dengan membuka konsol Log Peristiwa (View > Tool Windows > Event Log).
  5. Pastikan aplikasi Anda dikonfigurasi untuk otomatis meluncurkan Logcat saat berjalan:
    1. Pilih Run > Edit Configurations.
    2. Pilih tab Miscellaneous di jendela Run/Debug Configurations.
    3. Di bagian Logcat, pilih Show logcat automatically, lalu pilih OK.