打造通話應用程式

通話應用程式可讓使用者透過自己的裝置接聽或撥打語音或視訊通話 裝置。呼叫應用程式使用自己的使用者介面進行呼叫,而非使用 預設的「電話」應用程式介面,如以下螢幕截圖所示。

呼叫應用程式範例
範例:使用自己的使用者介面發出呼叫的應用程式

Android 架構包含 android.telecom 套件, 包含類別,可協助您根據電信服務建構呼叫應用程式 這個架構的重點在於根據電信架構建構應用程式, 以下優點:

  • 您的應用程式與 裝置。
  • 您的應用程式與其他同樣遵守 這個原則
  • 架構有助於應用程式管理音訊和影片轉送作業。
  • 架構有助應用程式判斷呼叫是否為焦點。

資訊清單宣告和權限

在應用程式資訊清單中,宣告應用程式使用 MANAGE_OWN_CALLS敬上 權限,如以下範例所示:

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

如要進一步瞭解如何宣告應用程式權限,請參閱 權限

您必須宣告服務,而該服務會指定實作 ConnectionService 類別。電信 子系統要求服務宣告 BIND_TELECOM_CONNECTION_SERVICE 權限 繫結至 Google Cloud 資源以下範例說明如何在 應用程式資訊清單:

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

如要進一步瞭解如何宣告應用程式元件 (包括服務),請參閱 應用程式元件

實作連線服務

呼叫應用程式必須提供 ConnectionService 類別實作,供電信子系統繫結。 您的 ConnectionService 實作應覆寫 方法如下:

onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)

電信子系統會呼叫這個方法來回應 應用程式呼叫 placeCall(Uri, Bundle) 即可建立新撥出電話。應用程式會傳回 Connection 類別實作的新例項 (詳情請參閱 實作連線),代表新的 撥出電話。如要進一步自訂連出連線,請執行 以下動作:

onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

當應用程式呼叫 placeCall(Uri, Bundle) 方法,而撥出電話無法進行時,電信子系統會呼叫這個方法 為因應這種情況,您的應用程式應告知使用者 ( 例如快訊方塊或浮動式訊息) 無法撥出電話 位置。如果應用程式正在進行通話,就無法撥打電話 或是其他正在撥打的應用程式中 請先等候,再撥打電話。

onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)

當應用程式呼叫 addNewIncomingCall(PhoneAccountHandle, Bundle) 方法時,電信子系統會呼叫這個方法 通知系統應用程式有新來電。您的應用程式會傳回 新的 Connection 實作例項 (針對 詳情請參閱「實作連線」一節) 代表新的來電您可以進一步自訂 來啟用這項功能:

onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)

當應用程式呼叫 addNewIncomingCall(PhoneAccountHandle, Bundle) 方法,向 Telecom 通知電信時,電信子系統會呼叫這個方法 新的來電,但禁止接聽來電 (瞭解詳情 相關資訊,請參閱呼叫限制條件)。您的應用程式應 以靜音方式拒接來電,並視需要發布通知通知 未接來電的使用者。

執行連線

應用程式應建立 Connection 的子類別, 代表應用程式中的呼叫您應該在 的實作:

onShowIncomingCallUi()

當您新增來電時,電信子系統會呼叫此方法 應用程式應會顯示來電 UI。

onCallAudioStateChanged(CallAudioState)

電信子系統會呼叫此方法,通知應用程式目前的音訊 路線或模式已變更呼叫此方法是為了因應您的應用程式變更 使用 setAudioRoute(int) 的音訊模式 方法。如果系統變更音訊路徑,也可能呼叫此方法 (例如藍牙耳機中斷連線時)。

onHold()

當電信子系統要保留通話時,會呼叫這個方法。 為回應這項要求,您的應用程式應保留呼叫,然後叫用 使用 setOnHold() 方法通知系統 通話要保留多久。電信子系統可以在下列情況呼叫此方法 顯示通話的通話服務,例如 Android Auto 並希望 轉發使用者要求,以便保留通話。電信子系統也會呼叫 當使用者在其他應用程式中進行呼叫時,此方法。如要 如需通話服務的相關資訊,請參閱 InCallService

onUnhold()

當電信子系統呼叫此方法時 要求恢復保留的通話。應用程式重新啟用後 呼叫,則應叫用 setActive() 方法,通知系統已經保留通話。電信 子系統可能會在通話服務 (例如 Android Auto) 時呼叫這個方法 ,表示來電要求恢復通話。適用對象 如要進一步瞭解通話服務,請參閱 InCallService

onAnswer()

電信子系統會呼叫這個方法 應用程式才能接聽來電。應用程式回應 呼叫,則應叫用 setActive() 方法,通知系統已經接聽呼叫。電信 子系統可以在應用程式新增來電並 其他應用程式已有進行中的通話,因此無法保留。 電信子系統會代表您的應用程式顯示來電 UI 在這些執行個體中架構提供超載的方法 支援指定接聽通話的視訊狀態。如要 相關資訊,請參閱 onAnswer(int)

onReject()

當電信子系統要拒絕來電時,會呼叫這個方法 呼叫。應用程式拒絕呼叫後,應呼叫 setDisconnected(DisconnectCause) 並指定 REJECTED 做為參數。您的應用程式應 然後呼叫 destroy() 方法 系統處理呼叫的應用程式。電信子系統呼叫 此方法。

onDisconnect()

當電信子系統要中斷通話時,就會呼叫這個方法。 呼叫結束時,應用程式應呼叫 setDisconnected(DisconnectCause) 方法,並指定 LOCAL 做為參數,表示 因使用者要求而導致通話中斷。這樣一來,應用程式應該就會呼叫 用於通知電信的 destroy() 方法 應用程式已處理此呼叫的子系統。系統可能會呼叫這個方法 使用者透過其他通話服務 (例如 Android Auto當必須呼叫此方法時,系統也會呼叫此方法 已中斷連線,允許撥打其他通話。例如,如果使用者希望 撥打緊急電話。如需進一步瞭解通話中服務,請參閱: InCallService

處理常見的呼叫情況

在呼叫中使用 ConnectionService API 流程涉及與 android.telecom 中的其他類別互動 套件。以下各節將說明常見的通話情境,以及 應用程式應使用 API 處理。

接聽來電

無論其他應用程式是否發出呼叫,處理來電的流程都會改變 不一定。流量的差異在於電信架構 必須建立一些限制條件, 確保裝置上所有呼叫的應用程式都能享有穩定的環境。如要 詳情請參閱呼叫限制

其他應用程式目前沒有進行中的通話

如要在其他應用程式目前沒有進行中的通話時接聽來電,請按照 步驟如下:

  1. 應用程式會透過一般機制接收新的來電。
  2. 使用 addNewIncomingCall(PhoneAccountHandle, Bundle) 方法 通知電信子系統有新來電。
  3. 電信子系統繫結至應用程式的 ConnectionService 實作項目,並要求新的例項 代表新傳入的 Connection 類別 呼叫 onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest) 方法。
  4. 電信子系統會通知應用程式,應顯示來電 透過 onShowIncomingCallUi() 方法建立使用者介面
  5. 您的應用程式使用與 全螢幕意圖詳情請參閱 onShowIncomingCallUi()
  6. 如果使用者已看過 setActive() 方法,請呼叫該方法。 接受來電,或 setDisconnected(DisconnectCause)REJECTED 指定為參數,後接 呼叫 destroy() 方法 拒接來電。

其他無法通話保留的應用程式進行中的通話

在其他應用程式有進行中的通話時,在無法接聽來電的情況下接聽來電 進入保留狀態,請按照下列步驟操作:

  1. 應用程式會透過一般機制接收新的來電。
  2. 使用 addNewIncomingCall(PhoneAccountHandle, Bundle) 方法 通知電信子系統有新來電。
  3. 電信子系統繫結至應用程式的 ConnectionService 實作項目,並要求新的例項 Connection 物件,代表新的 呼叫 onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest) 方法。
  4. 電信子系統會顯示來電的使用者介面。
  5. 如果使用者接受呼叫,電信子系統會呼叫 onAnswer() 方法。您應呼叫 setActive() 方法,以表示電信業者 呼叫的子系統。
  6. 如果使用者拒絕呼叫,電信子系統會呼叫 onReject() 方法。您應呼叫 setDisconnected(DisconnectCause) 方法,並將 REJECTED 指定為參數,後面加上 呼叫 destroy() 方法。

撥打電話

撥打電話的流程需要處理 無法發出 呼叫,因為電信架構限制。 詳情請參閱「呼叫限制」。

如要撥打電話,請按照下列步驟操作:

  1. 使用者在您的應用程式中撥出電話。
  2. 使用 placeCall(Uri, Bundle) 方法通知 新的撥出電話的電信子系統。採取下列行動 方法參數的注意事項:
    • Uri 參數代表 正在進行通話。如果是一般電話號碼,請使用 tel: URI 配置。
    • Bundle 參數可讓您提供 ,將應用程式的 PhoneAccountHandle 物件新增至 EXTRA_PHONE_ACCOUNT_HANDLE 額外項目,藉此呼叫呼叫應用程式。您的 應用程式必須為每個撥出電話提供 PhoneAccountHandle 物件。
    • Bundle 參數也可讓您指定 撥出電話加入視訊畫面,方法是指定 EXTRA_START_CALL_WITH_VIDEO_STATE 額外項目中的 STATE_BIDIRECTIONAL 值。 考量到這一點,電信子系統預設會將視訊通話轉接給 擴音模式。
  3. 電信子系統會繫結至應用程式的 ConnectionService
  4. 如果應用程式無法撥打電話,進行電話子系統通話 將 onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest) 方法 通知應用程式,目前無法接聽來電。您的應用程式 應告知使用者無法撥打電話。
  5. 如果應用程式可以撥打電話,便會進行電信子系統通話 onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest) 方法。應用程式應傳回 Connection 類別的執行個體,代表新的撥出電話。適用對象 進一步瞭解應在連結中設定的屬性 請參閱「實作連線服務」。
  6. 撥出電話後,呼叫 setActive() 方法通知電信子系統 通話是否正在運作。

結束通話

如要結束通話,請按照下列步驟操作:

  1. 如果使用者有使用者,請呼叫傳送 LOCAL 做為參數的 setDisconnected(DisconnectCause) 終止通話,或傳送 REMOTE 給你 。
  2. 呼叫 destroy() 方法。

呼叫限制

為了確保使用者享有一致且簡易的通話體驗,「電信」應用程式 架構會強制執行一些管理裝置上的呼叫限制。適用對象 舉例來說,假設使用者安裝了兩個 自行管理的 ConnectionService API、FooTalk 和 BarTalk。在此情況下,系統會套用以下限制條件:

  • 在搭載 API 級別 27 以下版本的裝置上,只有一個應用程式能維護 接聽程式。這項限制意味著 進行中的通話時,BarTalk 應用程式無法啟動或接聽 重新撥號。

    在搭載 API 級別 28 以上版本的裝置上 (如果同時有 FooTalk 和 BarTalk 宣告 CAPABILITY_SUPPORT_HOLD敬上 和 CAPABILITY_HOLD。 設定完成後,使用者就能透過 切換應用程式以發起或接聽其他通話。

  • 如果使用者採用一般的受管理通話 (例如使用 內建「電話」或「撥號」應用程式),則使用者無法加入來自以下對象的通話: 通話應用程式。換句話說,如果使用者透過 也無法同時進行 FooTalk 或 BarTalk 通話。

  • 如果使用者撥打電話, 撥打緊急電話。

  • 當使用者正在撥打緊急電話時,您的應用程式無法接聽或撥打電話。

  • 當你的應用程式收到通話時,其他通話應用程式中是否正在進行通話 接聽來電後, 或其他應用程式。應用程式不應顯示其一般的來電使用者介面。 電信架構會顯示來電的使用者介面,並通知 接聽新來電的使用者將結束目前的通話。這個 表示使用者正在進行 FooTalk 通話,而 BarTalk 應用程式收到 來電時,電信架構會通知使用者, 接聽 BarTalk 通話,接聽 BarTalk 通話則會結束 FooTalk 來電。