본문 바로가기

Android/통화 화면 바꾸기

[Android/통화 화면 바꾸기] 1. 기본 앱, 대체 앱이란?

Intent부터 짚고 가자

스마트폰을 사용하다 보면 어떤 액션에 의해 다른 앱으로 이동이 가능한 경우가 있다.

 

하이퍼링크 처리된 사이트 링크나 전화번호 등을 클릭할 경우,

장소 검색 결과에서 전화 걸기 버튼을 클릭할 경우,

광고나 검색 결과에서 특정 앱을 다운로드하기 위해 클릭하면 플레이스토어로 이동하는 경우,

사진 첨부 버튼을 누르면 갤러니나 카메라로 이동하는 경우,

쿠팡, 인스타 등의 앱을 모바일 웹 브라우저로 보고 있으면 설치된 앱으로 이동하거나 설치하게 플레이 스토어로 이동시키는 경우 등등..

 

이를 안드로이드 개발자 입장에서 생각한다면 Intent에 의해 가능한 일이다.

 

처음으로 Intent를 접하는 상황은 대부분 startActivity(Intent intent)를 사용하면서 경우이다.

한 Activity에서 다른 Activity로 이동하는 경우 intent객체를 이용해 이동할 Activity를 지정하여 파라미터로 넣어준다.

 

위에서 나열된 상황들도 다른 앱이라는 조건을 뺀다면 어떤 Activity(위에서는 주로 웹 브라우저)에서 다이얼 화면, 플레이 스토어의 특정 앱 화면, 갤러리나 카메라 화면 등등 각 앱의 특정 Activity를 띄우는 상황이다. 

 

이 경우는 명시적 인텐트로 넘기는 것이고, 이 포스팅에서 중요한 것은 암시적 인텐트이다.

 

암시적 인텐트는 어떤 Activity를 실행할지 지정하는 것이 아니라, 어떤 작업을 실행할지를 지정해준다.

//JAVA
//출처 : https://developer.android.com/training/camera/photobasics?hl=ko#TaskCaptureIntent
static final int REQUEST_IMAGE_CAPTURE = 1;

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    }
}

 

위처럼 사진을 찍는다는 행동을 지정을 하여 startActivity를 하게 된다.

 

어떤 액티비티를 지정하지 않아도 되는 이유는 사진으로 설명이 가능하다.

 

사진의 설명처럼 시스템이 Intent에 지정한 내용과 일치하는 Intent filter를 설치된 모든 앱의 각 AndroidManifest.xml에서 <intent-filter>와 비교하여 일치하는 Activity를 실행한다.

 

이때 일치하는 Activity가 여러 개라면 팝업으로 어떤 앱을 실행할 것인지 선택할 수 있는 창이 뜨게 된다.

 

명시적 인텐트, 암시적 인텐트, 인텐트 필터에 대한 내용이 궁금하다면 아래의 링크 참고
인텐트 및 인텐트 필터

 

인텐트 및 인텐트 필터  |  Android 개발자  |  Android Developers

An Intent is a messaging object you can use to request an action from another app component . Although intents facilitate communication between components in several ways, there are three fundamental use cases: An Activity represents a single screen in…

developer.android.com

 

그래서 기본 앱은 뭐길래?

아무튼 굳이 인텐트를 언급한 이유는 하나다.

설정에서 볼 수 있듯이 기본 앱과 링크를 여는 앱은 조금 다르다.

그리고 포스팅 작성하며 알게 된 사실인데 놀랍게도 카메라는 기본 앱이 아니다.

 

1번 캡처에서는 시스템이 기본 앱으로 지정할 수 있는 목록을 볼 수 있고, 2번 캡처에서는 어떤 기본 앱으로 지정할 수 있는 앱들을 확인할 수 있다. 3번 캡처는 기본 앱은 아니지만 암시적 인텐트를 수신할 수 있는 앱들을 확인하는 목록으로 보인다.

 

다음 포스팅에서 생성한 프로젝트를 기본 앱으로 등록하는 과정을 진행할 텐데, 그때 이용될 클래스가 RoleManager이다.

다음은 android.app.role.RoleManager 클래스의 주석 내용이다.

중요한 내용들을 해석해 보자면

1. 기본 앱은 os 업데이트로 인해 변경될 수 있으니 isRoleAvailable(String) 함수로 체크할 것

2. 어떤 역할을 여러 앱이 수행할 수 있어도 역할을 수행할 수 있는 것은 일부이다.

3. 어떤 역할의 기본 앱으로 등록되기 위해서는 Manifest에서 역할에 필요한 요구조건이 충족되어야 한다.

4. 어떤 역할의 기본 앱으로 등록되기 위해서는 사용자의 명시적인 동의가 필요하다.(기본 앱 전환 인텐트로 팝업을 띄워 앱이 선택되어야 함)

5. 어떤 역할의 기본 앱이 되면 역할별로 특정 권한이 부여될 수 있고, 기본 앱에서 박탈된다면(다른 앱이 기본 앱으로 선택되는 경우) 획득한 권한은 취소된다.

그럼 대체 전화 앱은?

사실 [기본 앱]은 당연히 정식 명칭이지만, [대체 앱]은 정식 명칭이 아니다.

예를 들어 T전화 앱을 기본 전화 앱으로 등록한다면 T전화 앱이 기본 전화 앱이 될 뿐, 대체 전화 앱이라는 명칭이 붙지는 않는다.

 

그저 앞으로 포스팅에서 의미의 구분을 위해 쓰게 될 단어일 뿐이다.

따라서 여기서 정의한 대체 전화 앱이란 스마트폰을 샀을 때 깔려있는 기본 전화 앱 대신

기본 앱으로 등록하여 사용할 수 있는 앱을 뜻한다.

 

유명한 대체 전화 앱으로는 T전화 앱이나 후후 앱이 있다.

우선 전화 앱이 가지는 화면은 크게 다이얼(키패드) 화면, 통화 기록, 주소록, 통화 화면 등이 있다. 

두 앱 모두 다이얼(키패드) 화면, 주소록, 통화 기록 화면이 있다.

 

차이점으로는 T전화는 전화에 관련된 모든 플로우를 앱 자체에서 제공한다.

그중 통화를 걸거나 받을 때, 통화 중일 때 나타나는 통화 화면은 T전화만 제공하고 후후는 기본 전화 앱의 통화 중 화면으로 제공한다.

 

이처럼 같은 전화 앱이라도 구현에 따라 어떤 화면까지 앱에서 제공할지가 달라진다.

 

사실 다이얼, 주소록 화면은 암시적 인텐트를 배우는 기본 예제로 사용될 정도로 암시적 인텐트로 원하는 액션을 호출하는 기능을 사용한다면 기본 전화 앱으로 등록되지 않았더라도 화면 구현해서 같은 기능을 하도록 만들 수 있다.

물론 기존에 등록되어있던 주소록과 통화 기록목록까지 불러오려면 단순 암시적 인텐트로는 구현이 안되지만,

잔화 앱으로 등록이 안되어 있더라도 CALL_LOG 등의 권한을 이용하여 기록을 불러올 수 있다고 알고 있다(아마도..?).

 

다만 통화 화면은 무조건 기본 전화 앱으로 등록된 앱에서 띄울 수 있다.

착각할 수 있는 게 전화 앱은 주소록, 통화 기록, 다이얼 화면을 보여주고 전화를 걸고 받는 화면은 시스템이 제공하는 화면이라고 생각할 수 있으나, T전화 앱을 기본 전화 앱으로 등록하여 이용해 보면 T전화가 제공하는 통화 화면으로 전화를 걸고 받는 것을 확인할 수 있다. 

 

통화 화면 가로채기

그렇다면 통화 중 화면은 어떻게 자체적으로 띄울 수 있을까?

 

조금 복잡하긴 하지만, 일단 내가 만든 앱에서 통화 화면을 띄우기 위해서는 무조건 앱이 기본 전화 앱으로 등록되어야 하는 것은 맞다.

 

그러나 후후의 경우 기본 전화 앱으로 등록되어 있다고 하더라도 원래의 통화 화면으로 전화를 걸고 받는다.

그렇다면 대체 전화 앱이 통화 화면을 제공을 안 한다면 스마트폰을 샀을 때 깔려 있던 전화 앱이 통화 화면을 띄운다는 것을 알 수 있다.

 

예시로 대체 전화 앱을 개발하면서 통화 화면을 띄웠는데 앱에서 크래시가 난다면 원래 전화 앱의 통화 화면으로 전환되었던 경험이 있다.

전화 앱이 크래시가 난다고 전화가 끊기거나 인터페이스가 사라지면 안 되니까 기존의 전화 앱만큼은 예외적으로 기본 전화 앱이 아니더라도 통화 화면을 띄울 수 있는 것이 나닌가 싶다.

 

아무튼 기본 전화 앱은 필수 조건이고 여기에 더해 InCallService라는 서비스를 상속받은 서비스를 구현하면 그제야 통화 화면을 가로채 내가 만든 앱에서 Activity를 띄울 수 있다.

수신, 발신이 발생한다면 InCallService를 상속받은 Service에서 이를 캐치할 수 있고, 여기서 Activity를 띄우고 전화를 수락하고 거절하고 통화를 종료하고 하는 등의 액션을 Activity를 통해 인터페이스를 제공하고 처리할 수 있다.

 

앞으로 이어질 포스팅에서는 기본 전화 앱으로 등록하는 과정부터 자체 액티비티를 통화 상황에 맞게 띄우고

전화를 걸고 받고 끊고 하는 액션과 통화 중 키패드 입력(ars), 스피커 모드, 음소거 등등

원래의 전화 앱이 하던 모든 일중 녹음을 제외하고(정책의 이슈..) 차근차근 작성해보려 한다.