Ringkasan protokol inisiasi sesi

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 dari SipAudioCall. Dapat berupa null, 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 adalah IncomingCallReceiver.
  • 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:

  1. Di perangkat, sambungkan ke nirkabel (Setelan > Nirkabel & jaringan &gt; 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 Event Log (View > Tool Windows > Event Log).
  5. Pastikan aplikasi Anda dikonfigurasi untuk otomatis meluncurkan Logcat saat dijalankan:
    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.