通信フレームワークの概要

Android Telecom フレームワーク(別名: Telecom)は、音声と ビデオ通話を行えます。これには、 通話 テレフォニー フレームワークを使用する VoIP 呼び出し、 ConnectionService API。

Telecom が管理する主なコンポーネントは ConnectionServiceInCallService

ConnectionService の実装では、VoIP などの技術を使用して接続します。 通話できます。プラットフォームで最も一般的な ConnectionService の実装は、 スマートフォンはテレフォニー ConnectionService です。キャリア通話を接続する。

InCallService の実装は、によって管理される呼び出しのユーザー インターフェースを提供します。 ユーザーがこれらの通話の操作や操作を行えるようにします。最も InCallService の一般的な実装は、Google Pixel にバンドルされている通話アプリです。 できます。

通信事業者はスイッチボードの役割を果たす。ConnectionService の呼び出しをルーティングします。 実装では、呼び出し側のユーザー インターフェースに InCallService 必要があります。

Telecom API の実装が推奨される理由は次のとおりです。

代替の電話アプリを作成する

Android デバイスのデフォルトの電話アプリの代替アプリを作成するには: InCallService API を実装します。実装は次の要件を満たしている必要があります。 要件:

  • 通話機能を持たず、ユーザーのみで構成されている必要があります。 インターフェースです。
  • Telecom フレームワークが認識しているすべての通話を処理し、 コールの性質に関する前提条件があるとします。たとえば、 SIM ベースのテレフォニー通話であり、Google が実装する通話制限機能により、 テレフォニーの適用など、任意の 1 つの ConnectionService に基づく 制限されます。

詳細については、InCallService をご覧ください。

通話ソリューションを統合する

通話ソリューションを Android に統合するには、 次のオプションがあります。

  • セルフマネージド ConnectionService API を実装します。 スタンドアロン通話アプリのデベロッパーは、 デフォルトの電話アプリ内に通話を表示したり、他の通話を表示したりできます 確認できます

    セルフマネージド ConnectionService を使用すると、アプリで次のことを行えます。 デバイスのネイティブ電話と相互運用できるだけでなく、 スタンドアロン通話アプリと統合できます。セルフマネージド ConnectionService API は、音声ルーティングとフォーカスも管理します。詳しくは、 通話アプリを作成します

  • マネージド ConnectionService API を実装します。 この方法では、 通話用のユーザー インターフェースを提供する既存のデバイスの電話アプリケーション。 例としては、SIP 通話や VoIP 通話のサードパーティ実装などが挙げられます。 提供します。詳しくは getDefaultDialerPackage() をご覧ください。

    ConnectionService のみが提供するのは、呼び出しを接続する手段だけです。これは、 ユーザー インターフェースが関連付けられていません。

  • InCallService API と ConnectionService API の両方を実装します。 この方法は、独自のカスタム イメージを作成する 独自ユーザーによる ConnectionService ベースの通話ソリューション 他のすべての Android 呼び出しを同じユーザー インターフェースに表示します。 この方法を使用する場合は、InCallService の実装で 表示される通話の発生元についてなんらかの推測を行う。また、 ConnectionService の実装は、 デフォルトの電話アプリをカスタムの InCallService に設定。

コール スクリーニング

Android 10(API レベル 29)以降を搭載しているデバイスでは、アプリが ユーザーのアドレス帳に登録されていない番号からの通話がスパムの可能性がある できます。ユーザーは迷惑電話を通知なく拒否することを選択できます。より優れたカスタマーエクスペリエンスを ブロックした通話に関する情報、不在着信時のユーザー情報 通話は通話履歴に記録されます。Android 10 API を使用すると、 取得する必要があります。 READ_CALL_LOG 通話スクリーニングや発信者番号通知を行うため、ユーザーの許可を得る必要があります。 説明します。

使用するのは CallScreeningService コールをスクリーニングできます。呼び出し onScreenCall() 番号が 追加することもできます。詳しくは、 情報の Call.Details オブジェクト 概要です。具体的には getCallerNumberVerificationStatus() 関数には、他の番号に関するネットワーク プロバイダからの情報が含まれます。 確認ステータスが不合格だった場合は、コールが 迷惑電話の可能性があります。

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
            }
        }
    }
}

以下を呼び出すように onScreenCall() 関数を設定します。 respondToCall() 新しい着信への応答方法をシステムに指示しますこの関数は CallResponse パラメータを使用して、着信をブロックするようシステムに指示し、 サイレント モードに設定することもできます。この追加をスキップするようにシステムに指示することもできます。 通話がデバイスの通話履歴にも記録されます。

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());

CallScreeningService の実装をマニフェストに登録する必要があります。 適切なインテント フィルタと権限を付与して、システムがトリガーできるようにする 確認します。

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

通話を転送する

Android 10 以降を搭載したデバイスでは、通話インテントの管理方法が異なります Android 9 以前を搭載したデバイスAndroid 10 以降では、 ACTION_NEW_OUTGOING_CALL は非推奨になり、代わりに CallRedirectionService APICallRedirectionService は、以下を行うためのインターフェースを提供します。 Android プラットフォームが発信する発信の変更。例: サードパーティ アプリは通話をキャンセルし、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();
        }
    }
}

システムがサービスを開始できるように、マニフェストでこのサービスを登録する必要があります。 確認します。

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

リダイレクト サービスを使用するには、アプリで通話リダイレクト ロールをリクエストする必要があります RoleManager から。この場合、 アプリが通話のリダイレクトを処理できるようにする場合は、ユーザーに通知が送られます。アプリが このロールが付与されていない場合、リダイレクト サービスは使用されません。

ユーザーがアプリを起動したときに、アプリにこのロールが付与されているかどうかを確認する必要があります。 必要に応じてリクエストできます。RoleManager によって作成されたインテントを起動する。 その場合は必ず onActivityResult() 関数を使用してユーザーの選択を処理します。

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);
            }
        }
    }
}