Android BlockedNumberProvider를 통한 수신 차단 시스템 커스터마이징

Android 환경에서 전화는 누구나 접근 가능한 개방형 통신 채널입니다. 이로 인해 원치 않는 스팸 전화나 메시지로부터 사용자를 보호하는 기능은 필수적입니다. Android 7.0(Nougat) 이전에는 표준 API의 부재로 인해 서드파티 앱들이 수신 차단을 구현하는 데 한계가 있었으나, 7.0 버전부터 BlockedNumberProvider가 도입되면서 시스템 차원의 통합 관리가 가능해졌습니다.

BlockedNumberProvider 개요

BlockedNumberProvider는 차단된 전화번호 목록을 저장하고 관리하는 Android 시스템의 핵심 Content Provider입니다. 이를 통해 시스템 앱뿐만 아니라 권한을 가진 앱들이 일관된 차단 목록을 공유하고 활용할 수 있습니다.

주요 제공 기능은 다음과 같습니다.

  • 번호 등록: 특정 번호를 차단 목록에 추가합니다.
  • 번호 삭제: 기존 차단 목록에서 특정 번호를 제거합니다.
  • 상태 조회: 특정 번호가 현재 차단된 상태인지 확인합니다.
  • 전체 관리: 저장된 모든 차단 번호 리스트를 조회하고 관리합니다.

ADB를 활용한 BlockedNumberProvider 제어

개발 및 디버깅 시 ADB(Android Debug Bridge) 명령어를 사용하여 차단 데이터베이스를 직접 조작할 수 있습니다.

# 차단된 번호 전체 목록 조회
adb shell content query --uri content://com.android.blockednumber/blocked

# 특정 번호 차단 목록에 추가
adb shell content insert --uri content://com.android.blockednumber/blocked --bind original_number:s:'01012345678'

# 차단 목록에서 특정 ID(예: 1번) 삭제
adb shell content delete --uri content://com.android.blockednumber/blocked/1

프레임워크 수정을 통한 모르는 번호 차단 구현

단순히 DB에 등록된 번호 외에, 연락처에 없는 '모르는 번호'를 일괄 차단해야 하는 요구사항이 있을 수 있습니다. 이를 위해서는 Android Framework 내의 BlockedNumberProvider.java 소스 코드를 수정해야 합니다.

핵심 로직은 isBlocked 메서드 내에서 결정됩니다. 이 메서드는 특정 번호가 수신되었을 때 차단 여부를 불리언 값으로 반환합니다.

다음은 isBlocked 메서드의 구조를 재구성한 예시입니다.

private boolean isBlocked(String targetAddress) {
    // 번호가 비어있는 경우 차단하지 않음
    if (TextUtils.isEmpty(targetAddress)) {
        Log.d(TAG, "isBlocked: 번호가 비어 있어 차단하지 않습니다.");
        return false;
    }

    // 국가 코드 등을 반영한 표준 형식(E164)으로 변환
    final String normalizedNumber = Utils.getE164Number(getContext(), targetAddress, null);

    // 기본적으로 데이터베이스에서 차단 여부를 조회하는 로직
    final Cursor cursor = mDbHelper.getReadableDatabase().rawQuery(
            "SELECT " + BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER + 
            " FROM " + BlockedNumberDatabaseHelper.Tables.BLOCKED_NUMBERS +
            " WHERE " + BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "=?1",
            new String[]{targetAddress}
    );

    boolean existsInDb = (cursor != null && cursor.getCount() > 0);
    
    if (cursor != null) {
        cursor.close();
    }

    // 모르는 번호 차단 정책이 활성화되어 있다면 추가 로직 수행
    // 예: 연락처 DB에 존재하지 않는 번호일 경우 true 반환 로직 추가 가능
    
    return existsInDb;
}

모르는 번호를 차단하기 위해서는 위 로직에 연락처 존재 여부를 확인하는 ContactProvider 조회 쿼리를 결합하거나, 특정 정책 설정(Settings Secure/Global) 값을 참조하여 DB에 없는 번호일 경우 무조건 true를 반환하도록 분기 처리함으로써 시스템 레벨의 차단 기능을 확장할 수 있습니다.

태그: Android-Framework BlockedNumberProvider Telephony AOSP java

7월 23일 20:02에 게시됨