[android] BlockedNumbers (수신차단) 에 대해 알아보자.
https://source.android.com/docs/core/connect/block-numbers
#
Android N (7.0, API Level 24) 전에는 수신차단을 위해서는 특정 앱을 다운로드 받았어야 했음.
그러나 이런 앱들도 공식적으로 지원되는 API 가 없었기에 기대하는 만큼 작동하지 않았음.
몇몇 제조사들은 자체적인 수신차단 방법을 제공하곤 했지만, 유저가 단말을 변경하면 이 정보들은 날아가기 일쑤였음.
기능들을 나름 잘 제공하는 앱들을 사용하는 경우에도, 각각의 앱에서 중복으로 수신차단 번호를 등록해야 하는 수고로움도 있었음.
#
Android N (7.0, API Level 24) 에서는 BlockedNumberProvider 라는 content provider 가 제공됨.
이를 통해 번호를 등록하면, 해당 번호들로부터의 전화, SMS, MMS 등을 시스템에서 차단시켜주게 되었음.
관련있는 앱들이 이 기능을 사용하면서 통합적인 유저 경험을 제공할 수 있게 되었음.
기본 전화, 기본 메시지 앱, UICC-privileged 앱, system 과 동일 signature 를 가진 앱들이 blocked number list 를 읽고 쓸 수 있게 되었음.
시스템에 해당 값들이 저장되기 때문에, 어떤 기본전화, 기본 메시지 앱을 사용하던 간에 차단이 잘 되고, 새로운 단말로 교체하는 경우에도 해당 번호들을 유지할 수 있게 되었름.
#
기본 전화, 메시지 앱이 아닌 경우 TelecomManager.createManageBlockedNumbersIntent() 을 통해 block number 관리 Activity 를 띄울 수 있게 됨. (BlockedNumberContract.canCurrentUserBlockNumbers() 가 true 인 경우만)
// Framework 의 BlockedNumbersActivity 가 뜨게 됨.
Context.startActivity(telecomManager.createManageBlockedNumbersIntent(), null)
https://developer.android.com/reference/android/provider/BlockedNumberContract
#
Android N (7.0, API Level 24) 부터 등장
#
blocked number 에 대한 정보를 provider 로 제공함.
column 과 Uri 는 BlockedNumbers class 를 통해 제공.
blocked number 에 대한 message 와 call 은 platform 에 의해 버려짐. PhoneNumberUtils.isEmergencyNumber() 에 의한 긴급전화는 예외임.
CarrierConfigManager.KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT 는 유저가 emergency service 를 이용한 후 call, message 가 block 되지 않는 초 단위 값이 정의됨. 이 값이 1주일 이하일 경우 그 값이 그대로 사용됨. 값이 1주일 초과일 경우 기본값이 사용됨. 값이 음수일 경우 유저가 직접 block 을 다시 할 때까지 block 이 절대 되지 않음.
#
기본 SMS, 기본 전화 앱, Carrier 앱들만 read/write 가능.
BlockNumberContract.canCurrentUserBlockNumbers() 함수는 어떤 앱이든 호출할 수 있음.
(돼왕 : Carrier app 은 carrier specific 한 기능을 제공하는 service, https://developer.android.com/reference/android/service/carrier/CarrierService)
#
message 나 call 을 받을 수 있는 "주소" 를 저장함. 단순 전화번호가 아니라 email 등도 올 수 있음.
blocked number 는 BlockedNumbers.COLUMN_ORIGINAL_NUMBER 에 저장되어 있음.
phone number 의 normalized version 은 BlockedNumbers#COLUMN_E164_NUMBER 에 저장되어 있음.
system 은 이 두개의 column 안에 있는 정보를 기반으로 차단을 수행함.
#
BlockedNumbers.COLUMN_ORIGINAL_NUMBER 는 필수 column 이고, BlockedNumbers.COLUMN_E164_NUMBER 는 optional. 이 녀석은 제공되지 않으면 provider 가 알아서 채움. normalization 이 실패하거나 address 가 phoneNumber 가 아닐 경우 채워지지 않음.
만약 중복된 block number 을 insert 하려고 할 경우 replacing 이 수행됨.
val values = ContentValues().apply{ put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890")}
val uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values)
#
Update 는 지원되지 않음. Delete & Insert 로 처리해야 함.
#
Delete Sample Code
val values = ContentValues().apply { put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234567890")}
val uri = getContentResolver().insert(BlockedNumbers.CONTENT_URI, values)
getContentResolver().delete(uri, null, null)
#
특정 번호가 block 되었는지 보려면 BlockNumbers.isBlocked 함수를 호출하면 됨.
#
Block number query 는 아래와 같이 함.
val cursor = getContentResolver().query(BlockedNumbers.CONTENT_URI, arrayOf(BlockedNumbers.COLUMN_ID, BlockedNumbers.COLUMN_ORIGINAL_NUMBER,
BlockedNumbers.COLUMN_E164_NUMBER), null, null, null)
#
BlockNumberContract.unblock 함수를 이용해 unblock 할 수 있음.
#
앱은 blocked number provider 를 사용하기 전에 BlockNumberContract.canCurrentUserBlockNumbers() 를 반드시 체크해야 함.
만약 여기서 false 가 return 되면 모든 operation 에 대해 SecurityException 이 발생한다.
이 값이 false 이더라도, user 에 상관없이 시스템에 의한 call block 은 그대로 동작한다.
끝