phoneStateListener, TelephonyCallback 이란?
스마트폰에서 네트워크 상태를 감지하는 리스너, 콜백 함수입니다.
phoneStateListener는 안드로이드 API 버전 12 이후로부터 deprecated 되었습니다.
이유를 찾아보려 했으나 잘 모르겠습니다... 혹시 찾으면 추가할 예정입니다...
그래도 API 12 레벨 이전 앱을 개발한다면 PhoneStateListener 도 사용해야할 수 도 있습니다.
PhoneStateListener
PhoneStateListener 를 사용할 때 중요한 클래스는TelephonyManager입니다.
이 클래스의 listen 메서드를 통해서 리스너를 동작시킬 수 있습니다.
listen 메서드의 두번째 매개변수를 통해 원하는 휴대전화 정보를 가져올 수 있습니다.
만약 여러개를 가져오고 싶다면 or 연산자로 묶으면 되는데, 사용 가능한 이벤트는 안드로이드 개발자 사이트를 참조.
https://developer.android.com/reference/android/telephony/PhoneStateListener
listen 메서드의 구조는 아래와 같습니다. 첫번째 인자로 리스너, 두번째 인자로 이벤트를 받습니다.
public void listen(PhoneStateListener listener, int events) {
throw new RuntimeException("Stub!");
}
PhoneStateListener 사용전 권한설정이 필요합니다.
그래서 AndroidManifest.xml 중 아래의 코드가 추가되어야 합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="co.kr.package">
<!-- 권한 추가 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- 스마트폰 상태 를 얻기 위한 권한설정 -->
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> <!-- TelephonyManager 사용을 위한 권한설정 : 네트워크 제공국가, 사업자, 전화번호 확인-->
<application
...(후략)
</manifest>
PhoneStateListener의 사용 예시
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 안드로이드 12 이전 버전에서 사용하던 휴대폰 상태 정보 리스너
// 13버전 이후로는 사용이 불가함.
val phoneStateListener = object : PhoneStateListener() {
// 통화 전달 상태 변경
override fun onCallForwardingIndicatorChanged(cfi: Boolean) { TODO(); }
// 통화 상태 변경
override fun onCallStateChanged(state: Int, phoneNumber: String?) { TODO(); }
// 기지국 위치 변경
override fun onCellLocationChanged(location: CellLocation?) { TODO();}
// 데이터 송수신 활동
override fun onDataActivity(direction: Int) {TODO();}
// 데이터 연결상태
override fun onDataConnectionStateChanged(state: Int) { TODO(); }
// 메세지 대기 상태 변경
override fun onMessageWaitingIndicatorChanged(mwi: Boolean) { TODO(); }
// 단말기의 서비스 상태
override fun onServiceStateChanged(serviceState: ServiceState?) {
val tag = "PHONE SERVICE >>>>>>>> "
// ServiceState에 작성된 프로퍼티
// mVoiceRegState
// mDataRegState
// mChannelNumber
// duplexMode()
// mCellBandwidths -> [] 배열의 형태
when(serviceState?.state){
ServiceState.STATE_EMERGENCY_ONLY -> {Log.d(tag, "EMERGENCY")};
ServiceState.STATE_OUT_OF_SERVICE -> {Log.d(tag, "OOS")};
ServiceState.STATE_POWER_OFF -> {Log.d(tag, "POWER_OFF")}
ServiceState.STATE_IN_SERVICE -> { Log.d(tag, "IN_SERVICE") };
}
}
// 신호 세기 변경 시
override fun onSignalStrengthChanged(asu: Int) { TODO(); }
}
val manager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager;
manager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
}
}
TelephonyCallback
안드로이드 API 버전 12 이후 phoneStateListener를 대체하는 콜백함수입니다.
TelephonyCallback도 사용전 권한설정이 필요합니다.
마찬가지로 AndroidManifest.xml 중 아래의 코드가 추가되어야 합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="co.kr.package">
<!-- 권한 추가 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- 스마트폰 상태 를 얻기 위한 권한설정 -->
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> <!-- TelephonyManager 사용을 위한 권한설정 : 네트워크 제공국가, 사업자, 전화번호 확인-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 휴대폰 네트워크 접속 권한 -->
<application
...(후략)
</manifest>
TelephonyCallback의 사용 예시
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 12버전 이후부터 , 전화 상태 감지하는 방법
// TelephonyCallback
// 휴대전화 정보를 얻는 방법 1.
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager;
val callBackTag = "TelephonyCallback >> "
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
telephonyManager.registerTelephonyCallback(
mainExecutor,
object : TelephonyCallback(), TelephonyCallback.CallStateListener {
override fun onCallStateChanged(state: Int) {
when(state) {
TelephonyManager.CALL_STATE_IDLE -> { Log.d(callBackTag, "state : $state");} // 통화 대기 상태
TelephonyManager.CALL_STATE_OFFHOOK -> { Log.d(callBackTag, "state : $state");} // 통화 중인 상태
TelephonyManager.CALL_STATE_RINGING -> { Log.d(callBackTag, "state : $state");} // 벨이 울리는 상태
}
}
}
)
}
Log.d("NETWORK :::: ", "state : ${isNetworkAvailable()}");
// 휴대전화 정보를 얻는 법 2
val networkReq : NetworkRequest
= NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
val conManager:ConnectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager;
conManager.requestNetwork(networkReq, object:ConnectivityManager.NetworkCallback(){
val tag = "NetworkCallback2 :::: "
override fun onAvailable(network: Network) {
super.onAvailable(network)
Log.d(tag, "네트워크 사용 가능")
}
override fun onUnavailable() {
super.onUnavailable()
Log.d(tag, "네트워크 사용 불가능")
}
})
}
// 휴대전화 정보를 얻은 후 결과를 boolean으로 리턴하는 함수
// 여기서 코드를 편집하여 상태값 자체를 출력할 수도 있다.
private fun isNetworkAvailable():Boolean{
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = connectivityManager.activeNetwork?: return false;
val actNetwork = connectivityManager.getNetworkCapabilities(network)?:return false; // 이 값이 null 이면 현재 스마트폰이 네트워크에 접속할 수 없는 상태임을 의미
return when {
actNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
Log.d("WIFI", "WIFI")
true;
}
actNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)->{
Log.d("CELLULAR", "CELLULAR");
true
}
else -> false;
}
}else {
return connectivityManager.activeNetworkInfo?.isConnected?:false;
}
}
}
TelephonyCallback의 프로퍼티에 대한 자세한 설명은 아래의 개발자 사이트에 나와 있습니다.
https://developer.android.com/reference/android/telephony/TelephonyCallback
휴대전화 정보를 얻는 법 1에서 사용한 TelephonyManager의 프로퍼티들은 아래의 사이트를 참조하면 됩니다.(엄청 많음)
개발하려는 어플리케이션에 따라 적당히 when 절에 분기를 추가해서 로직을 작성하면 될 것 같습니다.
https://developer.android.com/reference/android/telephony/TelephonyManager
'모바일(Mobile) > 안드로이드(Android)' 카테고리의 다른 글
[TIP] 안드로이드 컴포즈 환경에서 토스 결제 API 사용하기 (0) | 2023.09.05 |
---|---|
[TIPS] 안드로이드 컴포즈(Compose) 환경에서 local.properties 파일로 key 값 관리하기 with KTS (0) | 2023.08.31 |
[Android] 안드로이드와 컴포넌트 (안드로이드를 구성하는 원소들) (0) | 2023.07.07 |
[Android] 안드로이드란?, 안드로이드와 컴파일 (feat. DEX) (0) | 2023.07.07 |
[ANDROID] 안드로이드의 네트워크 통신 (HTTP 통신, Volley) (0) | 2022.12.15 |