Aplikacja do rozmów pozwala użytkownikom odbierać i nawiązywać połączenia audio i wideo na urządzeniu. Aplikacje do wykonywania połączeń korzystają z własnego interfejsu użytkownika, a nie z domyślnego interfejsu aplikacji Telefon, jak widać na tym zrzucie ekranu.
Platforma Androida zawiera pakiet android.telecom
, który zawiera klasy pomagające utworzyć aplikację do rozmów zgodnie z platformą telekomunikacyjną. Tworzenie aplikacji zgodnie z zasadami telekomunikacji przynosi takie korzyści:
- Twoja aplikacja prawidłowo współpracuje z natywnym podsystemem telekomunikacyjnym na urządzeniu.
- Twoja aplikacja prawidłowo współpracuje z innymi aplikacjami do połączeń, które również są zgodne z tą platformą.
- Platforma pomaga aplikacji zarządzać routingiem audio i wideo.
- Platforma pomaga aplikacji określić, czy jej wywołania są najważniejsze.
Deklaracje i uprawnienia w pliku manifestu
W manifeście aplikacji zadeklaruj, że używa ona uprawnienia MANAGE_OWN_CALLS
, jak pokazano w tym przykładzie:
<manifest … >
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
</manifest>
Więcej informacji na temat deklarowania uprawnień aplikacji znajdziesz w sekcji Uprawnienia.
Musisz zadeklarować usługę, która określa klasę implementującą w Twojej aplikacji klasę ConnectionService
. Podsystem telekomunikacyjny wymaga, aby usługa zadeklarowała uprawnienie BIND_TELECOM_CONNECTION_SERVICE
, aby mogła się z nią powiązać. Ten przykład pokazuje, jak zadeklarować usługę w manifeście aplikacji:
<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>
Więcej informacji o deklarowaniu komponentów aplikacji, w tym usług, znajdziesz w artykule Komponenty aplikacji.
Wdrażanie usługi połączenia
Aplikacja wywołująca musi udostępniać implementację klasy ConnectionService
, z którą może powiązać podsystem telekomunikacyjny.
Twoja implementacja ConnectionService
powinna zastąpić te metody:
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
Podsystem telekomunikacyjny wywołuje tę metodę w odpowiedzi na wywołanie aplikacji
placeCall(Uri, Bundle)
, by utworzyć nowe połączenie wychodzące. Aplikacja zwraca nowe wystąpienie klasyConnection
(więcej informacji znajdziesz w artykule Wdrażanie połączenia), które jest reprezentowane przez nowe połączenie wychodzące. Połączenie wychodzące możesz dostosować, wykonując te czynności:- Aplikacja powinna wywoływać metodę
setConnectionProperties(int)
ze stałąPROPERTY_SELF_MANAGED
jako argumentem, aby wskazać, że połączenie pochodzi z aplikacji wywołującej. - Jeśli Twoja aplikacja obsługuje wstrzymywanie połączeń, wywołaj metodę
setConnectionCapabilities(int)
i ustaw argument na wartość maski bitowej stałychCAPABILITY_HOLD
iCAPABILITY_SUPPORT_HOLD
. - Aby ustawić nazwę elementu wywołującego, użyj metody
setCallerDisplayName(String, int)
, w której jako parametrint
powinna być widoczna nazwa elementu wywołującegoPRESENTATION_ALLOWED
. - Aby mieć pewność, że połączenie wychodzące ma odpowiedni stan wideo, wywołaj metodę
setVideoState(int)
obiektuConnection
i wyślij wartość zwróconą przez metodęgetVideoState()
obiektuConnectionRequest
.
- Aplikacja powinna wywoływać metodę
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
Podsystem telekomunikacyjny wywołuje tę metodę, gdy aplikacja wywołuje metodę
placeCall(Uri, Bundle)
, a nie można nawiązać połączenia wychodzącego. W takiej sytuacji aplikacja powinna poinformować użytkownika (np. za pomocą pola z alertem lub komunikatu toastu), że nie można nawiązać połączenia wychodzącego. Aplikacja może nie być w stanie nawiązać połączenia, jeśli trwa połączenie alarmowe lub jeśli w innej aplikacji trwa połączenie, którego nie można wstrzymać przed nawiązaniem połączenia.onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
Podsystem telekomunikacyjny wywołuje tę metodę, gdy aplikacja wywołuje metodę
addNewIncomingCall(PhoneAccountHandle, Bundle)
, by poinformować system o nowym wywołaniu przychodzącym. Aplikacja zwraca nowe wystąpienie implementacjiConnection
(więcej informacji znajdziesz w sekcji Wdrażanie połączenia), która będzie reprezentować nowe wywołanie przychodzące. Możesz jeszcze bardziej dostosować połączenie przychodzące, wykonując te czynności:- Aplikacja powinna wywoływać metodę
setConnectionProperties(int)
ze stałąPROPERTY_SELF_MANAGED
jako argumentem, aby wskazać, że połączenie pochodzi z aplikacji wywołującej. - Jeśli Twoja aplikacja obsługuje wstrzymywanie połączeń, wywołaj metodę
setConnectionCapabilities(int)
i ustaw argument na wartość maski bitowej stałychCAPABILITY_HOLD
iCAPABILITY_SUPPORT_HOLD
. - Aby ustawić nazwę elementu wywołującego, użyj metody
setCallerDisplayName(String, int)
, w której jako parametrint
powinna być widoczna nazwa elementu wywołującegoPRESENTATION_ALLOWED
. - Aby podać numer telefonu lub adres połączenia przychodzącego, użyj metody
setAddress(Uri, int)
obiektuConnection
. - Aby mieć pewność, że połączenie wychodzące ma odpowiedni stan wideo, wywołaj metodę
setVideoState(int)
obiektuConnection
i wyślij wartość zwróconą przez metodęgetVideoState()
obiektuConnectionRequest
.
- Aplikacja powinna wywoływać metodę
onCreateIncomingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
Podsystem telekomunikacyjny wywołuje tę metodę, gdy aplikacja wywołuje metodę
addNewIncomingCall(PhoneAccountHandle, Bundle)
, aby poinformować Telecom o nowym połączeniu przychodzącym, ale takie połączenie jest niedozwolone (więcej informacji znajdziesz w artykule o ograniczeniach dotyczących połączeń). Aplikacja powinna dyskretnie odrzucać połączenie przychodzące, opcjonalnie publikując powiadomienie informujące użytkownika o nieodebranym połączeniu.
Wdrażanie połączenia
Aplikacja powinna utworzyć podklasę klasy Connection
do reprezentowania wywołań w aplikacji. Zastąp te metody w swojej implementacji:
onShowIncomingCallUi()
Podsystem telekomunikacyjny wywołuje tę metodę, gdy dodajesz nowe połączenie przychodzące, a aplikacja powinna pokazywać interfejs połączeń przychodzących.
onCallAudioStateChanged(CallAudioState)
Podsystem telekomunikacyjny wywołuje tę metodę, aby poinformować aplikację o zmianie aktualnej trasy lub trybu dźwięku. Jest ono wywoływane w odpowiedzi na zmianę trybu dźwięku przez aplikację za pomocą metody
setAudioRoute(int)
. Ta metoda może być też wywoływana, gdy system zmieni trasę dźwięku (np. po rozłączeniu zestawu słuchawkowego Bluetooth).onHold()
Podsystem telekomunikacyjny wywołuje tę metodę, gdy chce wstrzymać połączenie. W odpowiedzi na to żądanie aplikacja powinna wstrzymać wywołanie, a następnie wywołać metodę
setOnHold()
, aby poinformować system o tym, że jest ono wstrzymywane. Podsystem telekomunikacyjny może wywołać tę metodę, gdy usługa w trakcie rozmowy, np. Android Auto, która pokazuje, że połączenie chce przekazać użytkownikowi prośbę o zawieszenie połączenia. Podsystem telekomunikacyjny wywołuje tę metodę również wtedy, gdy użytkownik aktywuje połączenie w innej aplikacji. Więcej informacji o usługach dostępnych w ramach rozmowy znajdziesz tutaj:InCallService
.onUnhold()
Podsystem telekomunikacyjny wywołuje tę metodę, gdy chce wznowić zawieszone połączenie. Po wznowieniu wywołania aplikacja powinna wywołać metodę
setActive()
, aby poinformować system, że wywołanie nie jest już wstrzymane. Podsystem telekomunikacyjny może wywołać tę metodę, gdy usługa w trakcie rozmowy, np. Android Auto, która pokazuje, że połączenie chce przekazać prośbę o jego wznowienie. Więcej informacji o usługach dostępnych w trakcie rozmowy znajdziesz tutaj:InCallService
.onAnswer()
Podsystem telekomunikacyjny wywołuje tę metodę, aby poinformować aplikację, że powinno zostać odebrane połączenie przychodzące. Gdy aplikacja odbierze wywołanie, powinna wywołać metodę
setActive()
, aby poinformować system, że wywołanie zostało odebrane. Podsystem telekomunikacyjny może wywołać tę metodę, gdy aplikacja doda nowe połączenie przychodzące, a w innej aplikacji trwa już połączenie, którego nie można wstrzymać. Podsystem telekomunikacyjny w tych instancjach wyświetla interfejs połączeń przychodzących w imieniu Twojej aplikacji. Platforma udostępnia metodę przeciążoną, która umożliwia określenie stanu wideo, w którym ma zostać odebrane połączenie. Więcej informacji:onAnswer(int)
.onReject()
Podsystem telekomunikacyjny wywołuje tę metodę, gdy chce odrzucić połączenie przychodzące. Gdy aplikacja odrzuci wywołanie, powinna wywołać
setDisconnected(DisconnectCause)
i określićREJECTED
jako parametr. Aplikacja powinna wywołać metodędestroy()
, aby poinformować system, że aplikacja przetworzyła wywołanie. Podsystem telekomunikacyjny wywołuje tę metodę, gdy użytkownik odrzucił połączenie przychodzące z aplikacji.onDisconnect()
Podsystem telekomunikacyjny wywołuje tę metodę, gdy chce zakończyć połączenie. Po zakończeniu wywołania aplikacja powinna wywołać metodę
setDisconnected(DisconnectCause)
i określićLOCAL
jako parametr wskazujący, że żądanie użytkownika spowodowało rozłączenie połączenia. Aplikacja powinna następnie wywołać metodędestroy()
, aby poinformować podsystem telekomunikacyjny, że aplikacja przetworzyła połączenie. System może wywołać tę metodę, gdy użytkownik rozłączy się, korzystając z innej usługi w trakcie rozmowy, na przykład Androida Auto. System wywołuje tę metodę również wtedy, gdy połączenie musi zostać rozłączone, aby można było nawiązać inne połączenie, np. gdy użytkownik chce nawiązać połączenie alarmowe. Więcej informacji o usługach dostępnych w trakcie rozmowy znajdziesz tutaj:InCallService
.
Typowe scenariusze rozmów
Wykorzystanie interfejsu ConnectionService
API w przepływie wywołań wymaga interakcji z innymi klasami w pakiecie android.telecom
. W kolejnych sekcjach opisano typowe scenariusze wywołań i sposób, w jaki aplikacja powinna używać interfejsów API do ich obsługi.
Odbieranie połączeń przychodzących
Sposób obsługi połączeń przychodzących zmienia się niezależnie od tego, czy są realizowane połączenia w innych aplikacjach. Powodem różnic w procesach jest to, że platforma telekomunikacyjna musi wprowadzić pewne ograniczenia w przypadku aktywnych połączeń w innych aplikacjach, aby zapewnić stabilne środowisko dla wszystkich aplikacji do rozmów na urządzeniu. Więcej informacji znajdziesz w artykule Ograniczenia dotyczące połączeń.
Brak aktywnych połączeń w innych aplikacjach
Aby odbierać połączenia przychodzące, gdy w innych aplikacjach nie ma aktywnych połączeń, wykonaj te czynności:
- Aplikacja odbiera nowe połączenie przychodzące za pomocą zwykłych mechanizmów.
- Użyj metody
addNewIncomingCall(PhoneAccountHandle, Bundle)
, aby poinformować podsystem telekomunikacyjny o nowym połączeniu przychodzącym. - Podsystem telekomunikacyjny wiąże się z implementacją
ConnectionService
Twojej aplikacji i żąda nowej instancji klasyConnection
reprezentującej nowe wywołanie przychodzące za pomocą metodyonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
. - Podsystem telekomunikacyjny informuje aplikację, że powinien wyświetlać interfejs połączeń przychodzących za pomocą metody
onShowIncomingCallUi()
. - Aplikacja wyświetla przychodzący interfejs za pomocą powiadomienia z powiązaną intencją pełnoekranową. Więcej informacji:
onShowIncomingCallUi()
. - Wywołaj metodę
setActive()
, jeśli użytkownik zaakceptuje wywołanie przychodzące, lubsetDisconnected(DisconnectCause)
, podając jako parametrREJECTED
, a następnie wywołanie metodydestroy()
, jeśli użytkownik odrzuci połączenie przychodzące.
Aktywne połączenia w innych aplikacjach, których nie można wstrzymać
Aby odbierać połączenia przychodzące, gdy w innych aplikacjach są aktywne połączenia, których nie można wstrzymać, wykonaj te czynności:
- Aplikacja odbiera nowe połączenie przychodzące za pomocą zwykłych mechanizmów.
- Użyj metody
addNewIncomingCall(PhoneAccountHandle, Bundle)
, aby poinformować podsystem telekomunikacyjny o nowym połączeniu przychodzącym. - Podsystem telekomunikacyjny wiąże się z implementacją
ConnectionService
Twojej aplikacji i żąda nowej instancji obiektuConnection
reprezentującego nowe wywołanie przychodzące za pomocą metodyonCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)
. - Podsystem telekomunikacyjny wyświetla interfejs połączenia przychodzącego.
- Jeśli użytkownik zaakceptuje wywołanie, podsystem telekomunikacyjny wywołuje metodę
onAnswer()
. Wywołaj metodęsetActive()
, aby wskazać podsystemowi telekomunikacyjnemu, że połączenie zostało nawiązane. - Jeśli użytkownik odrzuci połączenie, podsystem telekomunikacyjny wywołuje metodę
onReject()
. Wywołaj metodęsetDisconnected(DisconnectCause)
, podając jako parametrREJECTED
, a po nim wywołanie metodydestroy()
.
Nawiązywanie połączeń wychodzących
Proces nawiązywania połączenia wychodzącego obejmuje radzenie sobie z możliwością nawiązania połączenia z powodu ograniczeń nałożonych przez platformę telekomunikacyjną. Więcej informacji znajdziesz w artykule Ograniczenia dotyczące połączeń.
Aby nawiązać połączenie wychodzące, wykonaj te czynności:
- Użytkownik inicjuje połączenie wychodzące w Twojej aplikacji.
- Użyj metody
placeCall(Uri, Bundle)
, aby poinformować podsystem telekomunikacyjny o nowym połączeniu wychodzącym. Weź pod uwagę te kwestie związane z parametrami metody:- Parametr
Uri
podaje adres, pod który jest wykonywane wywołanie. W przypadku zwykłych numerów telefonu użyj schematu identyfikatora URItel:
. - Parametr
Bundle
umożliwia podawanie informacji o aplikacji wywołującej poprzez dodanie obiektuPhoneAccountHandle
aplikacji do dodatkuEXTRA_PHONE_ACCOUNT_HANDLE
. Aplikacja musi dostarczać obiektPhoneAccountHandle
przy każdym wywołaniu wychodzącym. - Parametr
Bundle
pozwala też określić, czy połączenie wychodzące zawiera wideo przez podanie wartościSTATE_BIDIRECTIONAL
w dodatkowymEXTRA_START_CALL_WITH_VIDEO_STATE
. Pamiętaj, że podsystem telekomunikacyjny domyślnie kieruje połączenia wideo na głośnik.
- Parametr
- Podsystem telekomunikacyjny jest powiązany z implementacją
ConnectionService
Twojej aplikacji. - Jeśli aplikacja nie może nawiązać połączenia wychodzącego, podsystem telekomunikacyjny wywołuje metodę
onCreateOutgoingConnectionFailed(PhoneAccountHandle, ConnectionRequest)
, aby poinformować aplikację, że nie można obecnie nawiązać połączenia. Aplikacja powinna informować użytkownika, że nie można nawiązać połączenia. - Jeśli Twoja aplikacja może nawiązać połączenie wychodzące, podsystem telekomunikacyjny wywołuje metodę
onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
. Aplikacja powinna zwrócić wystąpienie klasyConnection
reprezentujące nowe połączenie wychodzące. Więcej informacji o właściwościach, które należy ustawić w połączeniu, znajdziesz w artykule o implementowaniu usługi połączenia. - Po nawiązaniu połączenia wywołaj metodę
setActive()
, aby poinformować podsystem telekomunikacyjny, że połączenie jest aktywne.
Kończenie połączenia
Aby zakończyć połączenie, wykonaj te czynności:
- Wywołaj parametr
setDisconnected(DisconnectCause)
, który wysyłaLOCAL
jako parametr, jeśli użytkownik zakończył połączenie, lub wyślijREMOTE
jako parametr, jeśli druga strona zakończyła połączenie. - Wywołaj metodę
destroy()
.
Ograniczenia dotyczące połączeń
Aby zapewnić użytkownikom spójną i prostą obsługę połączeń, platforma telekomunikacyjna wymusza pewne ograniczenia dotyczące zarządzania połączeniami na urządzeniu. Załóżmy na przykład, że użytkownik zainstalował 2 aplikacje wywołujące, które implementują samodzielnie zarządzany interfejs API ConnectionService
: FooTalk i BarTalk. W takim przypadku obowiązują te ograniczenia:
Na urządzeniach z interfejsem API na poziomie 27 lub niższym tylko jedna aplikacja może prowadzić trwające wywołanie w danym momencie. To ograniczenie oznacza, że gdy użytkownik prowadzi rozmowę za pomocą aplikacji FooTalk, aplikacja BarTalk nie może zainicjować ani odebrać nowego połączenia.
Na urządzeniach z interfejsem API na poziomie 28 lub wyższym, jeśli zarówno FooTalk i BarTalk deklarują uprawnienia
CAPABILITY_SUPPORT_HOLD
, jak iCAPABILITY_HOLD
, użytkownik może utrzymywać więcej niż jedno trwające wywołanie, przełączając się między aplikacjami, aby zainicjować kolejne wywołanie lub je odebrać.Jeśli użytkownik wykonuje zwykłe połączenia zarządzane (np. we wbudowanej aplikacji Telefon lub Telefon), nie może uczestniczyć w połączeniach z aplikacji do wykonywania połączeń. Oznacza to, że jeśli użytkownik regularnie rozmawia przez operatora komórkowego, nie może jednocześnie uczestniczyć w rozmowach FooTalk ani BarTalk.
Gdy użytkownik wybierze połączenie alarmowe, podsystem telekomunikacyjny rozłączy się z aplikacją.
Aplikacja nie może odbierać ani nawiązywać połączeń, gdy użytkownik dzwoni w trakcie połączenia alarmowego.
Jeśli w aplikacji do rozmów przychodzących jest inne połączenie przychodzące, odebranie tego spowoduje zakończenie trwającego połączenia w innej aplikacji. Aplikacja nie powinna wyświetlać interfejsu użytkownika do wykonywania połączeń przychodzących. Platforma telekomunikacyjna wyświetla interfejs połączeń przychodzących i informuje użytkownika, że odebranie nowego połączenia spowoduje zakończenie trwającej rozmowy. Oznacza to, że jeśli użytkownik będzie w trakcie rozmowy w FooTalk, a aplikacja BarTalk odbiera połączenie przychodzące, platforma telekomunikacyjna informuje użytkownika o nowym połączeniu przychodzącym w usłudze BarTalk i odebranie połączenia z BarTalk zakończy jego rozmowę.