본문 바로가기

Android/통화 화면 바꾸기

[Android/통화 화면 바꾸기] 2. 기본 전화 앱 등록하기

앞선 포스팅에서 통화 화면을 바꾸기 위해서는 두 가지의 조건이 필요하다고 했다.

1. 앱이 기본 전화 앱으로 등록되어야 함

2. InCallService가 구현되어 있어야 함

 

이번 포스팅은 앱을 기본 전화 앱으로 바꾸는 과정에 대해 작성해보려 한다.

 

기본 전화 앱이 되기 위한 조건

단순히 기본 앱 전환 인텐트를 날린다고 팝업이 뜨지는 않는다.

기본 앱의 종류에 따라 필요한 조건이 다른데 기본 전화 앱에서는 두 가지 intent filter를 manifest에 구현해야 한다.

1. action : dial, catergory : default

2. action : dial, catergory : default, scheme : "tel"

//example

Intent(Intent.ACTION_DIAL).let {
    startActivity(it)//1번
}

Intent(Intent.ACTION_DIAL).apply { 
    data = Uri.parse("tel:$phoneNumber")
}.let { 
    startActivity(it)//2번
}

각 intent filter에 대응되는 intent 호출이다.

두 호출을 앱에서 모두 받을 수 있어야 기본 전화 앱이 될 수 있다.

 

Manifest 정의하기

<activity
    android:name=".views.dialer.DialerActivity"
    android:exported="false">

    <intent-filter>
        <action android:name="android.intent.action.DIAL" />

        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.DIAL" />

        <category android:name="android.intent.category.DEFAULT" />

        <data android:scheme="tel" />
    </intent-filter>
</activity>

인텐트를 처리할 Activity를 따로 만들어서 위와 같이 인텐트 필터를 달아준다.

실제 인텐트를 처리하는 부분은 추후 포스팅에서 다룰 예정이다.

 

기본 전화 앱으로 등록하기

우선 정의해 두어야 할 변수들이다.

private val roleManager: RoleManager? by lazy {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        getSystemService(ROLE_SERVICE) as RoleManager
    } else null
}
private val telecomManager: TelecomManager by lazy { getSystemService(TELECOM_SERVICE) as TelecomManager }

기본 앱 전환 요청을 날릴 intent를 생성할 수 있는 RoleManager와 기본 앱으로 등록이 됐는지 확인할 수  있는 TelecomManager이다.

RoleManager는 api 29(Q)부터 사용할 수 있어 버전 분기하여 29 미만에서는 null을 반환한다.

Context가 생성된 후에 객체를 생성하기 위해 by lazy로 초기화해 주었다.

 

private val isDefaultDialer get() = packageName.equals(telecomManager.defaultDialerPackage)

현재 기본 전화 앱이 내가 만든 앱으로 등록이 되었는지 확인할 수 있는 변수이다.

변수 호출마다 기본 전화 앱인지 판단하기 위해 getter로 작성했다.

 

private val changeDefaultDialerIntent
    get() = if (isDefaultDialer) {
        Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
    } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            roleManager!!.createRequestRoleIntent(RoleManager.ROLE_DIALER)
        } else {
            Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER).apply {
            	putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
            }
        }
    }

기본 앱 전환을 위해 필요한 Intent를 생성하는 변수이다. 상황에 따라 세 종류의 인텐트가 반환된다.

우선 이미 앱이 기본 전화 앱으로 등록되어 있다면, 이를 바로 바꿀 수 있는 팝업이 뜨지 않는다.

따라서 변경해주기 위해 기본 앱 설정 화면을 띄워 사용자가 수동으로 바꾸게 해야 한다.

기본 전화 앱으로 등록되어 있지 않은 경우 버전에 따라 api 29 이상에서는 RoleManager로 Intent를 생성하고

api 29 미만에서는 TelecomManager에 정의된 문자열로 인텐트를 생성하고 앱의 패키지 명을 extra로 넣어준다.

 

private val changeDefaultDialerLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        binding.isDefaultDialer = isDefaultDialer
    }

 

기본 전화 앱으로 변경이 되었는지 결과를 확인하기 위한 콜백을 만드는 변수이다.

기존의 startActivityForResult가 deprecated 되면서 위와 같은 방식으로 onActivitiyResult 함수 대신에 정의해야 한다.

주의할 점은 Activity가 생성되는 시점에  위 객체가 같이 생성되어야 한다.

람다 함수 안에는 기존에 onActivityResult에 작성했던 것처럼 작성하면 되는데,

requestCode는 요청 날릴 때 콜백이 지정되므로 필요 없고, resultCode는 람다의 it 리시버로 접근할 수 있다.

다만 이 요청은 결과를 반환해주지는 않아서 정의해둔 isDefaultDialer 변수로 확인한다.

여기서는 바인딩에 만들어둔 boolean 변수에 값을 넣어 화면에 결과를 보여주고 있다.

xml 코드는 포스팅 하단의 깃허브 링크에서 확인 가능

버튼 리스너에 앞서 생성한 launcher 객체에 intent를 넘겨  호출해준다.

기존 방식에서 startActivityForResult와 같은 역할을 한다.

이 프로젝트에서는 databinding을 사용한다.

 

버튼을 클릭해 보면 위처럼 팝업이 뜬다. 사용하는 스마트폰에 따라 뜨는 방식은 달라질 수 있으나 기본 전화 앱을 변경할 수 있는 창이 뜰 것이다.

주의! 만약 앞서 AndroidManifest에 intent-filter를 제대로 달아주지 않았다면 저 팝업은 나타나지 않는다.

 

full source

https://github.com/raonian96/Custum-InCall-Display/tree/posting_2

 

GitHub - raonian96/Custum-InCall-Display

Contribute to raonian96/Custum-InCall-Display development by creating an account on GitHub.

github.com

작성된 코드의 풀 버전은 깃에 포스팅 번호 별로 태그를 만들어 정리해 두었습니다.

 

포스팅 관계 없이 레포지토리 자체 코드는 아래 링크에 있습니다.

https://github.com/raonian96/Custum-InCall-Display

 

GitHub - raonian96/Custum-InCall-Display

Contribute to raonian96/Custum-InCall-Display development by creating an account on GitHub.

github.com