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 없이 빌드할 수 있었다.
댓글
댓글 쓰기