Membuat aplikasi panggilan

Aplikasi panggilan memungkinkan pengguna menerima atau melakukan panggilan audio atau video di perangkatnya. Aplikasi panggilan menggunakan antarmuka penggunanya sendiri untuk panggilan, bukan antarmuka aplikasi Telepon default, seperti yang ditunjukkan dalam screenshot berikut ini.

Contoh aplikasi panggilan
Contoh aplikasi panggilan yang menggunakan antarmuka penggunanya sendiri

Framework Android menyertakan paket android.telecom, berisi class yang membantu Anda membuat aplikasi panggilan sesuai dengan framework telekomunikasi. Membuat aplikasi sesuai dengan framework telekomunikasi memberikan manfaat sebagai berikut:

  • Aplikasi Anda bekerja sama sebagaimana mestinya dengan subsistem telekomunikasi bawaan dalam perangkat.
  • Aplikasi Anda bekerja sama sebagaimana mestinya dengan aplikasi panggilan lain yang juga mematuhi framework.
  • Framework ini membantu aplikasi Anda mengelola perutean audio dan video.
  • Framework ini membantu aplikasi Anda menentukan apakah panggilannya memiliki fokus.

Izin dan deklarasi manifes

Dalam manifest aplikasi Anda, deklarasikan bahwa aplikasi Anda menggunakan izin MANAGE_OWN_CALLS, READ_CALL_LOG, READ_PHONE_STATE, dan READ_PHONE_NUMBERS, seperti yang ditunjukkan dalam contoh berikut:

<manifest … >
    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
    <uses-permission android:name="android.permission.READ_CALL_LOG"/>

    <!-- Needed only if your calling app reads numbers from the `PHONE_STATE`
         intent action. The maxSdkVersion attribute is needed only if your
         calling app uses the getLine1Number() or getMsisdn() methods. -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"
                     android:maxSdkVersion="29"/>

    <!-- Needed only if your calling app uses the getLine1Number() or
         getMsisdn() methods. -->
    <uses-permission android:name="android.permissions.READ_PHONE_NUMBERS"/>
    …
</manifest>

Untuk mengetahui informasi selengkapnya tentang mendeklarasikan izin aplikasi, lihat Izin.

Anda harus mendeklarasikan layanan yang menentukan class yang mengimplementasikan class ConnectionService dalam aplikasi Anda. Subsistem telekomunikasi mengharuskan layanan mendeklarasikan izin BIND_TELECOM_CONNECTION_SERVICE agar dapat terikat. Contoh berikut menunjukkan cara mendeklarasikan layanan dalam manifes aplikasi Anda:

<service android:name="com.example.MyConnectionService"
    android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.ConnectionService" />
    </intent-filter>
</service>

Untuk mengetahui informasi selengkapnya tentang mendeklarasikan komponen aplikasi, termasuk layanan, lihat Komponen Aplikasi.

Mengimplementasikan layanan koneksi

Aplikasi panggilan Anda harus menyediakan implementasi class ConnectionService yang dapat diikat oleh subsistem telekomunikasi. Implementasi ConnectionService Anda harus mengganti metode-metode berikut:

onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)

Subsistem telekomunikasi memanggil metode ini untuk merespons aplikasi Anda yang memanggil placeCall(Uri, Bundle) untuk membuat panggilan keluar baru. Aplikasi Anda menampilkan instance baru dari implementasi class Connection (untuk mengetahui informasi selengkapnya, lihat Mengimplementasikan koneksi) untuk menunjukkan panggilan keluar yang baru. Anda dapat melakukan penyesuaian lebih lanjut pada koneksi keluar dengan melakukan tindakan berikut:

onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

Subsistem telekomunikasi memanggil metode ini saat aplikasi Anda memanggil metode placeCall(Uri, Bundle) dan panggilan keluar tidak dapat dilakukan. Untuk merespons situasi ini, aplikasi Anda harus memberi tahu pengguna (misalnya, menggunakan kotak notifikasi atau toast) bahwa panggilan keluar tidak dapat dilakukan. Ada kemungkinan aplikasi Anda tidak dapat melakukan panggilan jika ada panggilan darurat yang sedang berlangsung, atau jika ada panggilan berlangsung di aplikasi lain yang tidak dapat ditahan sebelum melakukan panggilan Anda.

onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)

Subsistem telekomunikasi memanggil metode ini saat aplikasi Anda memanggil metodeaddNewIncomingCall(PhoneAccountHandle, Bundle) untuk memberi tahu sistem tentang panggilan masuk baru dalam aplikasi Anda. Aplikasi menampilkan instance baru implementasi Connection (untuk mengetahui informasi selengkapnya, lihat Mengimplementasikan koneksi) untuk menunjukkan panggilan masuk baru. Anda dapat melakukan penyesuaian lebih lanjut pada koneksi masuk dengan melakukan tindakan berikut:

onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

Subsistem telekomunikasi memanggil metode ini saat aplikasi Anda memanggil metode addNewIncomingCall(PhoneAccountHandle, Bundle) untuk memberi tahu Telecom tentang panggilan masuk baru, tetapi panggilan masuk tidak diizinkan (untuk mengetahui informasi selengkapnya, lihat batasan panggilan). Aplikasi Anda harus otomatis menolak panggilan masuk, dengan opsi memposting notifikasi untuk memberi tahu pengguna tentang panggilan tak terjawab.

Mengimplementasikan koneksi

Aplikasi Anda harus membuat subclass Connection untuk menunjukkan panggilan di aplikasi. Anda harus mengganti metode berikut dalam implementasi:

onShowIncomingCallUi()

Subsistem telekomunikasi memanggil metode ini saat Anda menambahkan panggilan masuk baru dan aplikasi harus menampilkan UI panggilan masuknya.

onCallAudioStateChanged(CallAudioState)

Subsistem telekomunikasi memanggil metode ini untuk memberi tahu aplikasi Anda bahwa rute atau mode audio saat ini telah berubah. Pemanggilan ini merupakan respons terhadap perubahan mode audio menggunakan metode setAudioRoute(int) dalam aplikasi Anda. Metode ini juga dapat dipanggil jika sistem mengubah rute audio (misalnya, saat koneksi headset Bluetooth terputus).

onHold()

Subsistem telekomunikasi memanggil metode ini saat ingin menahan panggilan. Untuk merespons permintaan ini, aplikasi Anda harus menahan panggilan, lalu memanggil metode setOnHold() untuk memberi tahu sistem bahwa panggilan sedang ditahan. Subsistem telekomunikasi dapat memanggil metode ini saat layanan dalam panggilan, seperti Android Auto, yang menunjukkan panggilan Anda ingin menyampaikan permintaan pengguna untuk menahan panggilan. Sistem telekomunikasi juga memanggil metode ini jika pengguna membuat suatu panggilan aktif di aplikasi lain. Untuk mengetahui informasi selengkapnya tentang layanan dalam panggilan, lihat InCallService.

onUnhold()

Subsistem telekomunikasi memanggil metode ini saat ingin melanjutkan panggilan yang ditahan. Setelah melanjutkan panggilan, aplikasi harus memanggil metode setActive() untuk memberi tahu sistem bahwa panggilan sudah tidak ditahan. Subsistem telekomunikasi dapat memanggil metode ini saat layanan dalam panggilan, seperti Android Auto, yang menunjukkan panggilan Anda ingin menyampaikan permintaan untuk melanjutkan panggilan. Untuk mengetahui informasi selengkapnya tentang layanan dalam panggilan, lihat InCallService.

onAnswer()

Sistem telekomunikasi memanggil metode ini untuk memberi tahu aplikasi Anda bahwa panggilan masuk harus dijawab. Setelah menjawab panggilan, aplikasi harus memanggil metode setActive() untuk memberi tahu sistem bahwa panggilan telah dijawab. Subsistem telekomunikasi dapat memanggil metode ini saat aplikasi Anda menambahkan panggilan masuk baru dan sudah ada panggilan yang sedang berlangsung di aplikasi lain yang tidak dapat ditahan. Subsistem telekomunikasi menampilkan UI panggilan masuk atas nama aplikasi Anda pada situasi seperti ini. Framework ini memberikan metode overload yang memberikan dukungan guna menentukan status video untuk menjawab panggilan. Untuk informasi selengkapnya, lihat onAnswer(int).

onReject()

Subsistem telekomunikasi memanggil metode ini saat ingin menolak panggilan masuk. Setelah menolak panggilan, aplikasi harus memanggil setDisconnected(DisconnectCause) dan menentukan REJECTED sebagai parameter. Kemudian, aplikasi Anda harus memanggil metode destroy() untuk memberi tahu sistem bahwa aplikasi telah memproses panggilan. Subsistem telekomunikasi memanggil metode ini setelah pengguna menolak panggilan masuk dari aplikasi Anda.

onDisconnect()

Subsistem telekomunikasi memanggil metode ini saat ingin memutuskan panggilan. Setelah panggilan berakhir, aplikasi Anda harus memanggil metode setDisconnected(DisconnectCause) dan menetapkan LOCAL sebagai parameter untuk menunjukkan bahwa permintaan pengguna menyebabkan panggilan terputus. Kemudian, aplikasi Anda harus memanggil metode destroy() untuk memberi tahu subsistem telekomunikasi bahwa aplikasi telah memproses panggilan. Sistem dapat memanggil metode ini setelah pengguna memutuskan panggilan melalui layanan dalam panggilan lain seperti Android Auto. Sistem juga memanggil metode ini saat panggilan Anda harus diputus agar panggilan lain dapat dilakukan, misalnya, jika pengguna ingin melakukan panggilan darurat. Untuk mengetahui informasi selengkapnya tentang layanan dalam panggilan, lihat InCallService.

Menangani skenario panggilan umum

Penggunaan API ConnectionService dalam alur panggilan melibatkan interaksi dengan class lain dalam paket android.telecom. Bagian berikut ini menjelaskan skenario panggilan umum dan cara aplikasi Anda menggunakan API untuk menanganinya.

Menjawab panggilan masuk

Alur untuk menangani panggilan masuk berubah saat ada panggilan di aplikasi lain ataupun tidak ada. Alasan adanya perbedaan dalam alur adalah karena framework telekomunikasi harus membuat beberapa batasan saat ada panggilan aktif di aplikasi lain untuk memastikan lingkungan stabil bagi semua aplikasi panggilan di perangkat. Untuk mengetahui informasi selengkapnya, lihat Batasan panggilan.

Tidak ada panggilan aktif di aplikasi lain

Untuk menjawab panggilan masuk saat tidak ada panggilan aktif di aplikasi lain, ikuti langkah-langkah berikut:

  1. Aplikasi Anda menerima panggilan masuk baru menggunakan mekanisme biasa.
  2. Gunakan metode addNewIncomingCall(PhoneAccountHandle, Bundle) untuk memberi tahu subsistem telekomunikasi tentang panggilan masuk baru.
  3. Subsistem telekomunikasi diikat ke implementasi ConnectionService aplikasi Anda dan meminta instance baru class Connection yang menunjukkan panggilan masuk baru menggunakan metode onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest).
  4. Subsistem telekomunikasi memberi tahu aplikasi Anda bahwa aplikasi harus menampilkan antarmuka pengguna panggilan masuk menggunakan metode onShowIncomingCallUi().
  5. Aplikasi Anda menampilkan UI panggilan masuk menggunakan notifikasi dengan intent layar penuh terkait. Untuk informasi selengkapnya, lihat onShowIncomingCallUi().
  6. Panggil metode setActive() jika pengguna menerima panggilan masuk, atau setDisconnected(DisconnectCause) yang menentukan REJECTED sebagai parameter diikuti panggilan ke metode destroy() jika pengguna menolak panggilan masuk.

Panggilan aktif di aplikasi lain yang tidak dapat ditahan

Untuk menjawab panggilan masuk saat ada panggilan aktif di aplikasi lain yang tidak dapat ditahan, ikuti langkah-langkah berikut:

  1. Aplikasi Anda menerima panggilan masuk baru menggunakan mekanisme biasa.
  2. Gunakan metode addNewIncomingCall(PhoneAccountHandle, Bundle) untuk memberi tahu subsistem telekomunikasi tentang panggilan masuk baru.
  3. Subsistem telekomunikasi diikat ke implementasi ConnectionService aplikasi Anda dan meminta instance baru objek Connection yang menunjukkan panggilan masuk baru menggunakan metode onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest).
  4. Subsistem telekomunikasi menampilkan UI panggilan masuk untuk panggilan masuk Anda.
  5. Jika pengguna menerima panggilan, subsistem telekomunikasi akan memanggil metode onAnswer(). Anda harus memanggil metode setActive() untuk menunjukkan kepada subsistem telekomunikasi bahwa panggilan telah tersambung.
  6. Jika pengguna menolak panggilan, subsistem telekomunikasi akan memanggil metode onReject(). Anda harus memanggil metode setDisconnected(DisconnectCause) yang menetapkan REJECTED sebagai parameter yang diikuti dengan panggilan ke metode destroy().

Melakukan panggilan keluar

Alur untuk melakukan panggilan keluar meliputi penanganan kemungkinan bahwa panggilan tidak dapat dilakukan karena batasan yang diberlakukan oleh framework telekomunikasi. Untuk mengetahui informasi selengkapnya, lihat Batasan panggilan.

Untuk melakukan panggilan keluar, ikuti langkah-langkah berikut:

  1. Pengguna memulai panggilan keluar dari dalam aplikasi Anda.
  2. Gunakan metode placeCall(Uri, Bundle) untuk memberi tahu subsistem telekomunikasi tentang panggilan keluar. Lihat pertimbangan berikut untuk parameter metode:
    • Parameter Uri menunjukkan alamat tempat panggilan dilakukan. Untuk nomor telepon reguler, gunakan skema URI tel:.
    • Parameter Bundle memungkinkan Anda memberi informasi tentang aplikasi panggilan Anda dengan menambahkan objek PhoneAccountHandle aplikasi pada tambahan EXTRA_PHONE_ACCOUNT_HANDLE. Aplikasi Anda harus memberikan objek PhoneAccountHandle untuk setiap panggilan keluar.
    • Parameter Bundle juga memungkinkan Anda menentukan apakah panggilan keluar melibatkan video dengan menentukan nilai STATE_BIDIRECTIONAL dalam tambahan EXTRA_START_CALL_WITH_VIDEO_STATE. Perlu diingat bahwa secara default, subsistem telekomunikasi mengalihkan panggilan video ke speaker ponsel.
  3. Subsistem telekomunikasi diikat ke implementasi ConnectionService aplikasi Anda.
  4. Jika aplikasi Anda tidak dapat melakukan panggilan keluar, subsistem telekomunikasi akan memanggil metode onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest) untuk memberi tahu aplikasi bahwa panggilan tidak dapat dilakukan saat ini. Aplikasi Anda harus memberi tahu pengguna bahwa panggilan tidak dapat dilakukan.
  5. Jika aplikasi Anda dapat melakukan panggilan keluar, subsistem telekomunikasi akan memanggil metode onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest). Aplikasi Anda harus menampilkan instance class Connection untuk menunjukkan panggilan keluar yang baru. Untuk mengetahui informasi selengkapnya tentang properti yang harus ditetapkan dalam koneksi, lihat Mengimplementasikan layanan koneksi.
  6. Setelah panggilan keluar tersambung, panggil metode setActive() untuk memberi tahu subsistem telekomunikasi bahwa panggilan telah aktif.

Mengakhiri panggilan

Untuk mengakhiri panggilan, ikuti langkah-langkah berikut:

  1. Panggil setDisconnected(DisconnectCause) yang mengirim LOCAL sebagai parameter jika pengguna menghentikan panggilan, atau kirim REMOTE sebagai parameter jika pihak lain menghentikan panggilan.
  2. Panggil metode destroy().

Batasan panggilan

Untuk memastikan pengalaman telepon yang konsisten dan sederhana bagi pengguna Anda, framework telekomunikasi menerapkan beberapa batasan untuk mengelola panggilan pada perangkat. Misalnya, anggaplah pengguna telah menginstal aplikasi panggilan yang mengimplementasikan API ConnectionService secara mandiri, yaitu FooTalk dan BarTalk. Jika demikian, batasan berikut berlaku:

  • Di perangkat yang beroperasi pada API level 27 atau yang lebih rendah, hanya satu aplikasi yang dapat mempertahankan panggilan yang sedang berlangsung pada waktu tertentu. Batasan ini berarti bahwa meskipun pengguna sedang melakukan panggilan menggunakan aplikasi FooTalk, aplikasi BarTalk tidak dapat memulai atau menerima panggilan baru.

    Di perangkat yang beroperasi pada API level 28 atau yang lebih tinggi, jika FooTalk dan BarTalk mendeklarasikan izin CAPABILITY_SUPPORT_HOLD dan CAPABILITY_HOLD, pengguna dapat melakukan lebih dari satu panggilan sekaligus dengan beralih antara dua aplikasi untuk memulai atau menjawab panggilan lain.

  • Jika pengguna terlibat dalam panggilan biasa yang dikelola (misalnya, menggunakan aplikasi Telepon bawaan), pengguna tidak dapat berada dalam panggilan yang berasal dari aplikasi panggilan. Artinya, jika pengguna sedang melangsungkan panggilan biasa menggunakan operator selulernya, mereka tidak dapat melakukan panggilan FooTalk atau BarTalk secara bersamaan.

  • Subsistem telekomunikasi memutuskan panggilan aplikasi Anda jika pengguna melakukan panggilan darurat.

  • Aplikasi Anda tidak dapat menerima atau melakukan panggilan saat pengguna sedang melakukan panggilan darurat.

  • Jika ada panggilan berlangsung dalam aplikasi panggilan lain saat aplikasi Anda menerima panggilan masuk, menerima panggilan masuk akan mengakhiri panggilan yang sedang berlangsung di aplikasi lain. Aplikasi Anda sebaiknya tidak menampilkan antarmuka pengguna panggilan masuk seperti biasanya. Framework telekomunikasi menampilkan antarmuka pengguna panggilan masuk dan memberi tahu pengguna bahwa menerima panggilan baru akan mengakhiri panggilan yang sedang berlangsung. Artinya, jika pengguna sedang dalam panggilan FooTalk dan aplikasi BarTalk menerima panggilan masuk, framework telekomunikasi memberi tahu pengguna bahwa ada panggilan masuk BarTalk dan menjawab panggilan BarTalk akan mengakhiri panggilan FooTalk.