Ringkasan framework Telecom

Kerangka kerja Android Telecom (juga dikenal sebagai "Telecom") mengelola audio dan panggilan video di perangkat yang didukung Android. Hal ini meliputi panggilan berbasis SIM, seperti panggilan telepon yang menggunakan kerangka kerja telepon, dan panggilan VoIP yang menerapkan API ConnectionService.

Komponen utama yang dikelola Telecom adalah ConnectionService dan InCallService.

Implementasi ConnectionService menggunakan teknologi seperti VoIP untuk terhubung panggilan ke pihak lain. Implementasi ConnectionService yang paling umum pada adalah telepon ConnectionService. Menghubungkan panggilan operator.

Implementasi InCallService menyediakan antarmuka pengguna untuk panggilan yang dikelola oleh Telekomunikasi dan memungkinkan pengguna mengontrol dan berinteraksi dengan panggilan ini. Paling sering implementasi umum InCallService adalah aplikasi ponsel yang dipaketkan dengan perangkat.

Telekomunikasi bertindak sebagai {i>switchboard<i}. Rute ini merutekan panggilan ConnectionService yang disediakan untuk antarmuka pengguna panggilan yang InCallService yang disediakan implementasi.

Anda mungkin ingin menerapkan Telecom API karena alasan berikut:

Membuat aplikasi telepon pengganti

Untuk membuat pengganti aplikasi telepon default di perangkat Android, mengimplementasikan InCallService API. Penerapan Anda harus memenuhi persyaratan berikut persyaratan:

  • Aplikasi tidak boleh memiliki kemampuan panggilan, dan hanya boleh terdiri dari pengguna untuk memanggil.
  • Aplikasi harus menangani semua panggilan yang diketahui oleh framework Telekomunikasi, dan tidak dilakukan asumsi tentang sifat panggilan. Misalnya, model tidak boleh mengasumsikan adalah panggilan telepon berbasis SIM, atau menerapkan pembatasan panggilan yang didasarkan pada salah satu ConnectionService, seperti penerapan telepon untuk panggilan video.

Untuk mengetahui informasi selengkapnya, lihat InCallService.

Mengintegrasikan solusi panggilan

Untuk mengintegrasikan solusi panggilan ke Android, Anda memiliki opsi berikut:

  • Implementasikan ConnectionService API yang dikelola sendiri: Opsi ini ideal bagi developer aplikasi panggilan mandiri yang tidak ingin untuk menampilkan panggilan mereka dalam aplikasi telepon default, maupun menampilkan panggilan lainnya di antarmuka pengguna mereka.

    Jika menggunakan ConnectionService yang dikelola sendiri, Anda membantu aplikasi untuk berinteroperasi tidak hanya dengan panggilan telepon asli pada perangkat, tetapi juga dengan aplikasi panggilan mandiri lain yang menerapkan API ini. Dikelola sendiri ConnectionService API juga mengelola pemilihan rute dan fokus audio. Untuk mengetahui detailnya, lihat Buat aplikasi panggilan.

  • Implementasikan ConnectionService API terkelola: Opsi ini memfasilitasi pengembangan solusi panggilan yang bergantung pada aplikasi telepon perangkat yang ada untuk menyediakan antarmuka pengguna untuk panggilan. Contohnya mencakup implementasi pihak ketiga untuk panggilan SIP dan panggilan VoIP layanan IT perusahaan mereka. Untuk detail selengkapnya, lihat getDefaultDialerPackage()

    ConnectionService saja hanya menyediakan cara untuk menghubungkan panggilan. Ini tidak memiliki antarmuka pengguna terkait.

  • Implementasikan InCallService dan ConnectionService API: Opsi ini ideal jika Anda ingin membuat Solusi panggilan berbasis ConnectionService, lengkap dengan penggunanya sendiri serta menampilkan semua panggilan Android lain dalam antarmuka pengguna yang sama. Jika Anda menggunakan pendekatan ini, penerapan InCallService tidak boleh membuat asumsi tentang sumber panggilan yang ditampilkannya. Selain itu, implementasi ConnectionService harus tetap berfungsi tanpa aplikasi telepon default yang disetel ke InCallService kustom.

Saring panggilan

Perangkat yang menjalankan Android 10 (API level 29) atau yang lebih baru memungkinkan aplikasi Anda untuk mengidentifikasi panggilan dari nomor yang tidak ada di buku alamat pengguna sebagai berpotensi spam panggilan telepon. Pengguna dapat memilih agar panggilan telepon spam ditolak secara diam-diam. Untuk menyediakan transparansi kepada pengguna saat mereka melewatkan panggilan, informasi tentang hal ini yang diblokir panggilan dicatat dalam log panggilan. Menggunakan Android 10 API akan menghilangkan persyaratan untuk memperoleh READ_CALL_LOG izin dari pengguna untuk memberikan penyaringan panggilan dan ID penelepon fungsionalitasnya.

Anda menggunakan CallScreeningService untuk menyaring panggilan. Panggil onScreenCall() untuk setiap panggilan masuk atau keluar baru bila nomor tersebut tidak ada dalam daftar kontak pengguna. Anda dapat memeriksa Objek Call.Details untuk informasi mengenai panggilan tersebut. Secara khusus, opsi getCallerNumberVerificationStatus() berisi informasi dari penyedia jaringan tentang nomor lainnya. Jika status verifikasi gagal, ini merupakan indikasi yang baik bahwa panggilan telah dari nomor yang tidak valid atau panggilan telepon yang berpotensi spam.

Kotlin

class ScreeningService : CallScreeningService() {
    // This function is called when an ingoing or outgoing call
    // is from a number not in the user's contacts list
    override fun onScreenCall(callDetails: Call.Details) {
        // Can check the direction of the call
        val isIncoming = callDetails.callDirection == Call.Details.DIRECTION_INCOMING

        if (isIncoming) {
            // the handle (e.g. phone number) that the Call is currently connected to
            val handle: Uri = callDetails.handle

            // determine if you want to allow or reject the call
            when (callDetails.callerNumberVerificationStatus) {
                Connection.VERIFICATION_STATUS_FAILED -> {
                    // Network verification failed, likely an invalid/spam call.
                }
                Connection.VERIFICATION_STATUS_PASSED -> {
                    // Network verification passed, likely a valid call.
                }
                else -> {
                    // Network could not perform verification.
                    // This branch matches Connection.VERIFICATION_STATUS_NOT_VERIFIED.
                }
            }
        }
    }
}

Java

class ScreeningService extends CallScreeningService {
    @Override
    public void onScreenCall(@NonNull Call.Details callDetails) {
        boolean isIncoming = callDetails.getCallDirection() == Call.Details.DIRECTION_INCOMING;

        if (isIncoming) {
            Uri handle = callDetails.getHandle();

            switch (callDetails.getCallerNumberVerificationStatus()) {
                case Connection.VERIFICATION_STATUS_FAILED:
                    // Network verification failed, likely an invalid/spam call.
                    break;
                case Connection.VERIFICATION_STATUS_PASSED:
                    // Network verification passed, likely a valid call.
                    break;
                default:
                    // Network could not perform verification.
                    // This branch matches Connection.VERIFICATION_STATUS_NOT_VERIFIED
            }
        }
    }
}

Setel fungsi onScreenCall() untuk memanggil respondToCall() untuk memberi tahu sistem bagaimana merespons panggilan baru itu. Fungsi ini mengambil CallResponse yang dapat digunakan untuk memberi tahu sistem agar memblokir panggilan, menolaknya seolah-olah dilakukan pengguna, atau membisukannya. Anda juga dapat memberi tahu sistem untuk melewati penambahan ini ke log panggilan perangkat secara keseluruhan.

Kotlin

// Tell the system how to respond to the incoming call
// and if it should notify the user of the call.
val response = CallResponse.Builder()
    // Sets whether the incoming call should be blocked.
    .setDisallowCall(false)
    // Sets whether the incoming call should be rejected as if the user did so manually.
    .setRejectCall(false)
    // Sets whether ringing should be silenced for the incoming call.
    .setSilenceCall(false)
    // Sets whether the incoming call should not be displayed in the call log.
    .setSkipCallLog(false)
    // Sets whether a missed call notification should not be shown for the incoming call.
    .setSkipNotification(false)
    .build()

// Call this function to provide your screening response.
respondToCall(callDetails, response)

Java

// Tell the system how to respond to the incoming call
// and if it should notify the user of the call.
CallResponse.Builder response = new CallResponse.Builder();
// Sets whether the incoming call should be blocked.
response.setDisallowCall(false);
// Sets whether the incoming call should be rejected as if the user did so manually.
response.setRejectCall(false);
// Sets whether ringing should be silenced for the incoming call.
response.setSilenceCall(false);
// Sets whether the incoming call should not be displayed in the call log.
response.setSkipCallLog(false);
// Sets whether a missed call notification should not be shown for the incoming call.
response.setSkipNotification(false);

// Call this function to provide your screening response.
respondToCall(callDetails, response.build());

Anda harus mendaftarkan implementasi CallScreeningService dalam manifes dengan filter intent dan izin yang sesuai sehingga sistem dapat memicu data dengan benar.

<service
    android:name=".ScreeningService"
    android:permission="android.permission.BIND_SCREENING_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.CallScreeningService" />
    </intent-filter>
</service>

Mengalihkan panggilan

Perangkat yang menjalankan Android 10 atau yang lebih tinggi mengelola intent panggilan secara berbeda dari perangkat yang menjalankan Android 9 atau yang lebih rendah. Pada Android 10 dan yang lebih tinggi, ACTION_NEW_OUTGOING_CALL siaran tidak digunakan lagi dan diganti dengan CallRedirectionService Compute Engine API. CallRedirectionService menyediakan antarmuka yang dapat Anda gunakan untuk mengubah panggilan keluar yang dilakukan oleh platform Android. Misalnya, pihak ketiga aplikasi dapat membatalkan panggilan dan mengalihkannya melalui VoIP.

Kotlin

class RedirectionService : CallRedirectionService() {
    override fun onPlaceCall(
        handle: Uri,
        initialPhoneAccount: PhoneAccountHandle,
        allowInteractiveResponse: Boolean
    ) {
        // Determine if the call should proceed, be redirected, or cancelled.
        val callShouldProceed = true
        val callShouldRedirect = false
        when {
            callShouldProceed -> {
                placeCallUnmodified()
            }
            callShouldRedirect -> {
                // Update the URI to point to a different phone number or modify the
                // PhoneAccountHandle and redirect.
                redirectCall(handle, initialPhoneAccount, true)
            }
            else -> {
                cancelCall()
            }
        }
    }
}

Java

class RedirectionService extends CallRedirectionService {
    @Override
    public void onPlaceCall(
            @NonNull Uri handle,
            @NonNull PhoneAccountHandle initialPhoneAccount,
            boolean allowInteractiveResponse
    ) {
        // Determine if the call should proceed, be redirected, or cancelled.
        // Your app should implement this logic to determine the redirection.
        boolean callShouldProceed = true;
        boolean callShouldRedirect = false;
        if (callShouldProceed) {
            placeCallUnmodified();
        } else if (callShouldRedirect) {
            // Update the URI to point to a different phone number or modify the
            // PhoneAccountHandle and redirect.
            redirectCall(handle, initialPhoneAccount, true);
        } else {
            cancelCall();
        }
    }
}

Anda harus mendaftarkan layanan ini dalam manifes agar sistem dapat memulainya dengan benar.

<service
    android:name=".RedirectionService"
    android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.CallRedirectionService"/>
    </intent-filter>
</service>

Untuk menggunakan layanan pengalihan, aplikasi Anda harus meminta peran pengalihan panggilan dari RoleManager. Ini akan menanyakan pengguna jika mereka ingin mengizinkan aplikasi Anda menangani pengalihan panggilan. Jika aplikasi Anda tidak diberi peran ini, layanan pengalihan Anda tidak digunakan.

Anda harus memeriksa apakah aplikasi memiliki peran ini saat pengguna meluncurkan aplikasi sehingga Anda dapat memintanya sesuai kebutuhan. Anda meluncurkan intent yang dibuat oleh RoleManager, jadi pastikan Anda mengganti onActivityResult() untuk menangani pilihan pengguna.

Kotlin

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Tell the system that you want your app to handle call redirects. This
        // is done by using the RoleManager to register your app to handle redirects.
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            val roleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager
            // Check if the app needs to register call redirection role.
            val shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) &&
                    !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION)
            if (shouldRequestRole) {
                val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION)
                startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE)
            }
        }
    }

    companion object {
        private const val REDIRECT_ROLE_REQUEST_CODE = 1
    }
}

Java

class MainActivity extends AppCompatActivity {
    private static final int REDIRECT_ROLE_REQUEST_CODE = 0;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Tell the system that you want your app to handle call redirects. This
        // is done by using the RoleManager to register your app to handle redirects.
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
            RoleManager roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE);
            // Check if the app needs to register call redirection role.
            boolean shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) &&
                    !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION);
            if (shouldRequestRole) {
                Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION);
                startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE);
            }
        }
    }
}