TelephonyManager.listen() Deprecated!

TelephonyManager.listen() Deprecated! TelephonyCallback으로 마이그레이션하기 (Java)

Android SDK를 최신 버전으로 업데이트하면 Android Studio에서 다양한 Deprecated 경고를 볼 수 있다.

그중 하나가 바로 TelephonyManager.listen() 이다.

기존에는 전화 상태나 데이터 연결 상태 등을 확인하기 위해 대부분 PhoneStateListener와 listen() 메서드를 사용했다.

하지만 Android 12(API 31)부터는 TelephonyCallback 사용이 권장되며, 최신 SDK에서는 listen() 메서드가 Deprecated로 표시된다.

이번 글에서는 기존 코드를 TelephonyCallback으로 변경하는 방법과 실제 적용하면서 주의했던 점을 정리해 보려고 한다.


왜 변경해야 할까?

기존 방식은 다음과 같았다.

TelephonyManager telephonyManager =
        (TelephonyManager) getSystemService(TELEPHONY_SERVICE);

telephonyManager.listen(
        phoneStateListener,
        PhoneStateListener.LISTEN_CALL_STATE
);

이 방식은 오랫동안 사용되어 왔지만 Android 12(API 31)부터 Deprecated 되었다.

Google에서는 기능별 Callback 인터페이스를 사용하는 TelephonyCallback 방식으로 변경할 것을 권장하고 있다.

SDK 36으로 변경하더라도 기존 코드가 바로 동작하지 않는 것은 아니지만, 앞으로의 호환성을 위해서는 변경하는 것이 좋다.


기존 PhoneStateListener 코드

예를 들어 전화 상태를 감시하는 코드는 다음과 같다.

PhoneStateListener listener =
        new PhoneStateListener() {

    @Override
    public void onCallStateChanged(int state, String phoneNumber) {

        switch (state) {

            case TelephonyManager.CALL_STATE_IDLE:

                break;

            case TelephonyManager.CALL_STATE_RINGING:

                break;

            case TelephonyManager.CALL_STATE_OFFHOOK:

                break;

        }

    }

};

그리고 등록은 다음과 같이 수행했다.

telephonyManager.listen(
        listener,
        PhoneStateListener.LISTEN_CALL_STATE
);

TelephonyCallback으로 변경하기

먼저 Callback 클래스를 생성한다.

private class CallStateCallback extends TelephonyCallback
        implements TelephonyCallback.CallStateListener {

    @Override
    public void onCallStateChanged(int state) {

        switch (state) {

            case TelephonyManager.CALL_STATE_IDLE:

                break;

            case TelephonyManager.CALL_STATE_RINGING:

                break;

            case TelephonyManager.CALL_STATE_OFFHOOK:

                break;

        }

    }

}

Callback 등록

등록 방법도 변경되었다.

기존에는

telephonyManager.listen(...)

을 사용했지만

이제는

telephonyManager.registerTelephonyCallback(
        getMainExecutor(),
        callback
);

을 사용한다.

예를 들면

CallStateCallback callback = new CallStateCallback();

telephonyManager.registerTelephonyCallback(
        getMainExecutor(),
        callback
);

Executor를 반드시 전달해야 한다는 점이 기존 방식과 가장 큰 차이점이다.


Callback 해제

Activity가 종료될 때는 Callback도 반드시 해제해야 한다.

telephonyManager.unregisterTelephonyCallback(callback);

보통은

onDestroy()

또는

onStop()

에서 해제하는 경우가 많다.


Android 11 이하도 함께 지원해야 한다면?

많은 프로젝트는 아직 minSdk가 23 또는 24이다.

때마침, 현재 작업하고 있는 프로젝트는 minSdk가 23으로 설정되어 있다.

이 경우에는 API 레벨에 따라 분기 처리를 해야 한다.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {

    telephonyManager.registerTelephonyCallback(
            getMainExecutor(),
            callback
    );

} else {

    telephonyManager.listen(
            listener,
            PhoneStateListener.LISTEN_CALL_STATE
    );

}

이렇게 하면 Android 12 이상에서는 새로운 API를 사용하고, 이전 버전에서는 기존 코드를 사용할 수 있다.


실제 적용하면서 겪었던 문제

1. Executor를 전달해야 한다

기존에는 단순히 listen()만 호출하면 되었지만

새로운 API는 Executor가 필요하다.

대부분의 Activity에서는

getMainExecutor()

를 사용하면 된다.


2. Callback 해제를 잊기 쉽다

등록만 하고

unregisterTelephonyCallback()

를 호출하지 않으면 메모리 누수가 발생할 수 있다.

Lifecycle에 맞춰 반드시 해제하는 것이 좋다.


3. 권한을 다시 확인해야 한다

전화 상태를 읽으려면

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

권한이 필요하다.

Android 6.0 이상에서는 런타임 권한도 함께 요청해야 한다.


4. 전화번호는 대부분 얻을 수 없다

예전에는

SubscriptionInfo.getNumber()

등을 이용하여 전화번호를 가져오는 경우가 있었다.

하지만 최신 Android에서는 개인정보 보호 정책 때문에 대부분의 일반 앱은 실제 전화번호를 얻을 수 없다.

통신사 앱이나 시스템 앱이 아니라면 null이 반환되는 경우가 많다.

따라서 전화번호를 이용하는 로직이 있다면 다른 방식으로 변경하는 것을 고려해야 한다.


변경 전후 비교

기존 방식

새로운 방식

PhoneStateListener

TelephonyCallback

listen()

registerTelephonyCallback()

LISTEN_* 플래그

Callback 인터페이스

Executor 없음

Executor 필요

listen(…, LISTEN_NONE)

unregisterTelephonyCallback()


마이그레이션 체크리스트

SDK를 변경할 때는 다음 항목을 확인하는 것을 추천한다.

  • TelephonyManager.listen() 검색
  • PhoneStateListener 검색
  • LISTEN_* 플래그 검색
  • TelephonyCallback으로 변경
  • Callback 해제 추가
  • Runtime Permission 확인
  • Android 12 이상 실기기 테스트

마무리

TelephonyManager.listen()은 아직 완전히 제거된 것은 아니지만 이미 Deprecated 상태이다.

새로운 프로젝트라면 처음부터 TelephonyCallback을 사용하는 것이 좋으며, 기존 프로젝트도 SDK를 업데이트하는 시점에 함께 마이그레이션하는 것을 추천한다.

이번 프로젝트에서는 API 레벨에 따라 분기 처리하여 Android 12 이상에서는 TelephonyCallback, 그 이하에서는 기존 PhoneStateListener를 사용하도록 변경하였다.

덕분에 기존 기능은 유지하면서 최신 SDK에서도 Warning 없이 빌드할 수 있었다.

댓글

이 블로그의 인기 게시물

Android SDK 36 대응 - Edge-to-edge 예외 설정이 더 이상 동작하지 않는 이유와 해결 방법

Android SDK 35 → 36 마이그레이션에서 실제 수정한 항목 7가지

Android Predictive Back 적용하기