본문 바로가기
Android

[Android] 단말기 정보 가져오기

by 준그래머 2023. 8. 3.
반응형

시작

Android 11 버전 이상에서 TelephonyManager를 이용해 안드로이드 단말기의 정보를 가져오는 방법에 대해 정리해보려 한다. 가져오는 정보들을 통해 특정 기능들의 활성화 또는 비활성화 처리를 구분 할 수 있으니 응용할 곳이 많다고 할 수 있다.

 

권한 부여

단말기 정보를 가져오기 위해선 권한을 요청해야 하는데, 전화번호를 가져오는 권한은 아래처럼 변경되었다.

Android 11에서는 앱에서 전화번호를 읽을 때 사용하는 전화 관련 권한이 변경됩니다. 앱이 Android 11 이상을 타겟팅하고 다음 목록에 표시된 전화번호 API에 액세스해야 한다면 READ_PHONE_STATE 권한 대신 READ_PHONE_NUMBERS 권한을 요청해야 합니다.

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

 

클래스 파일에서 권한을 요청하는 부분에 안드로이드 버전에 따른 분기 처리를 해주도록 한다.

public boolean chkPermission() {
    // 위험 권한을 모두 승인했는지 여부
    boolean mPermissionsGranted = false;
    String[] mRequiredPermissions;
    // 사용자의 안드로이드 버전에 따라 권한을 다르게 요청합니다
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        // 11 이상인 경우
        mRequiredPermissions = new String[2];
        mRequiredPermissions[0] = Manifest.permission.READ_PHONE_NUMBERS;
        mRequiredPermissions[1] = Manifest.permission.READ_PHONE_STATE;
    }else{
        // 10 이하인 경우
        mRequiredPermissions = new String[1];
        mRequiredPermissions[0] = Manifest.permission.READ_PHONE_STATE;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // 필수 권한을 가지고 있는지 확인한다.
        mPermissionsGranted = hasPermissions(mRequiredPermissions);

        // 필수 권한 중에 한 개라도 없는 경우
        if (!mPermissionsGranted) {
            // 권한을 요청한다.
            ActivityCompat.requestPermissions(MainActivity.this, mRequiredPermissions, PERMISSIONS_REQUEST_CODE);
        }
    } else {
        mPermissionsGranted = true;
    }

    return mPermissionsGranted;
}

public boolean hasPermissions(String[] permissions) {
    // 필수 권한을 가지고 있는지 확인한다.
    for (String permission : permissions) {
        Log.d(TAG, "permission Name: " + permission + ", checkCallingOrSelfPermission: " + checkCallingOrSelfPermission(permission) + ", PERMISSION_GRANTED: " + PackageManager.PERMISSION_GRANTED);
        if (checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}

Build.VERSION_CODES.R 이상인 경우 READ_PHONE_NUMBERS와 READ_PHONE_STATE 권한을 요청하고 아닌 경우는 READ_PHONE_STATE 하나만 요청하는 방식으로 구현한다.

 

단말기 정보 가져오기

단말기 정보는 TelephonyManager 를 통해 가져올 예정이며 IMEI 같은 priv 권한이 필요한 데이터는 제외 했다.

public void getDeviceInfo(){
    // READ_PHONE_NUMBERS 또는 READ_PHONE_STATE 권한을 허가 받았는지 확인
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {

        return;
    }
    // 유니크한 단말 번호 >>> Android ID 사용
    @SuppressLint("HardwareIds") String android_id = Settings.Secure.getString(this.getContentResolver(),Settings.Secure.ANDROID_ID);

    TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    @SuppressLint("HardwareIds")
    String text = "음성통화 상태 : [ getCallState ] >>> " + tm.getCallState() + "\\n"
            + "음성통화 상태 : [ getCallState ] >>> " + tm.getCallState() + "\\n"
            + "데이터통신 상태 : [ getDataState ] >>> " + tm.getDataState() + "\\n"
            + "전화번호 : [ getLine1Number ] >>> " + tm.getLine1Number() + "\\n"
            + "통신사 ISO 국가코드 : [ getNetworkCountryIso ] >>> "+tm.getNetworkCountryIso() + "\\n"
            + "통신사 ISO 국가코드 : [ getSimCountryIso ] >>> "+tm.getSimCountryIso() + "\\n"
            + "망사업자 MCC+MNC : [ getNetworkOperator ] >>> "+tm.getNetworkOperator() + "\\n"
            + "망사업자 MCC+MNC : [ getSimOperator ] >>> "+tm.getSimOperator() + "\\n"
            + "망사업자명 : [ getNetworkOperatorName ] >>> "+tm.getNetworkOperatorName() + "\\n"
            + "망사업자명 : [ getSimOperatorName ] >>> "+tm.getSimOperatorName() + "\\n"
            + "SIM 카드 상태 : [ getSimState ] >>> "+tm.getSimState() + "\\n"
            + "데이터 네트워크 상태 : [ getDataNetworkType ] >>> "+tm.getDataNetworkType() + "\\n"
            + "네트워크 상태 : [ getNetworkType ] >>> "+tm.getNetworkType() + "\\n"
            + "음성 네트워크 상태 : [ getVoiceNetworkType ] >>> "+tm.getVoiceNetworkType() + "\\n"
            + "TelephonyManager.NETWORK_TYPE_LTE: " + TelephonyManager.NETWORK_TYPE_LTE + "\\n"
            + "Android_ID >>> "+android_id;
    tv.setText(text);
}

 

전체 코드

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSIONS_REQUEST_CODE = 22;
    private static final String TAG = "확인";
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = findViewById(R.id.tv);

        if (chkPermission()) {
            // 휴대폰 정보는 TelephonyManager 를 이용
            getDeviceInfo();
        }

    }

    public void getDeviceInfo(){
        // READ_PHONE_NUMBERS 또는 READ_PHONE_STATE 권한을 허가 받았는지 확인
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_NUMBERS) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        // 유니크한 단말 번호 >>> Android ID 사용
        @SuppressLint("HardwareIds") String android_id = Settings.Secure.getString(this.getContentResolver(),Settings.Secure.ANDROID_ID);

        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        @SuppressLint("HardwareIds")
        String text = "음성통화 상태 : [ getCallState ] >>> " + tm.getCallState() + "\\n"
                + "음성통화 상태 : [ getCallState ] >>> " + tm.getCallState() + "\\n"
                + "데이터통신 상태 : [ getDataState ] >>> " + tm.getDataState() + "\\n"
                + "전화번호 : [ getLine1Number ] >>> " + tm.getLine1Number() + "\\n"
                + "통신사 ISO 국가코드 : [ getNetworkCountryIso ] >>> "+tm.getNetworkCountryIso() + "\\n"
                + "통신사 ISO 국가코드 : [ getSimCountryIso ] >>> "+tm.getSimCountryIso() + "\\n"
                + "망사업자 MCC+MNC : [ getNetworkOperator ] >>> "+tm.getNetworkOperator() + "\\n"
                + "망사업자 MCC+MNC : [ getSimOperator ] >>> "+tm.getSimOperator() + "\\n"
                + "망사업자명 : [ getNetworkOperatorName ] >>> "+tm.getNetworkOperatorName() + "\\n"
                + "망사업자명 : [ getSimOperatorName ] >>> "+tm.getSimOperatorName() + "\\n"
                + "SIM 카드 상태 : [ getSimState ] >>> "+tm.getSimState() + "\\n"
                + "데이터 네트워크 상태 : [ getDataNetworkType ] >>> "+tm.getDataNetworkType() + "\\n"
                + "네트워크 상태 : [ getNetworkType ] >>> "+tm.getNetworkType() + "\\n"
                + "음성 네트워크 상태 : [ getVoiceNetworkType ] >>> "+tm.getVoiceNetworkType() + "\\n"
                + "TelephonyManager.NETWORK_TYPE_LTE: " + TelephonyManager.NETWORK_TYPE_LTE + "\\n"
                + "Android_ID >>> "+android_id;
        tv.setText(text);
    }

    public boolean chkPermission() {
        Log.d(TAG, "SDK version: " + Build.VERSION.SDK_INT);

        // 위험 권한을 모두 승인했는지 여부
        boolean mPermissionsGranted = false;
        String[] mRequiredPermissions;
        // 사용자의 안드로이드 버전에 따라 권한을 다르게 요청합니다
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // 11 이상인 경우
            mRequiredPermissions = new String[2];
            mRequiredPermissions[0] = Manifest.permission.READ_PHONE_NUMBERS;
            mRequiredPermissions[1] = Manifest.permission.READ_PHONE_STATE;
        }else{
            // 10 이하인 경우
            mRequiredPermissions = new String[1];
            mRequiredPermissions[0] = Manifest.permission.READ_PHONE_STATE;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 필수 권한을 가지고 있는지 확인한다.
            mPermissionsGranted = hasPermissions(mRequiredPermissions);

            // 필수 권한 중에 한 개라도 없는 경우
            if (!mPermissionsGranted) {
                // 권한을 요청한다.
                ActivityCompat.requestPermissions(MainActivity.this, mRequiredPermissions, PERMISSIONS_REQUEST_CODE);
            }
        } else {
            mPermissionsGranted = true;
        }

        return mPermissionsGranted;
    }

    public boolean hasPermissions(String[] permissions) {
        // 필수 권한을 가지고 있는지 확인한다.
        for (String permission : permissions) {
            Log.d(TAG, "permission Name: " + permission + ", checkCallingOrSelfPermission: " + checkCallingOrSelfPermission(permission) + ", PERMISSION_GRANTED: " + PackageManager.PERMISSION_GRANTED);
            if (checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSIONS_REQUEST_CODE) {
            // 권한을 모두 승인했는지 여부
            boolean chkFlag = false;
            // 승인한 권한은 0 값, 승인 안한 권한은 -1을 값으로 가진다.
            for (int g : grantResults) {
                if (g == -1) {
                    chkFlag = true;
                    break;
                }
            }

            // 권한 중 한 개라도 승인 안 한 경우
            if (chkFlag){
                Toast.makeText(getApplicationContext(), "권한 실패했습니다.", Toast.LENGTH_SHORT).show();
            }
            else getDeviceInfo();
        }
    }
}

 

참조

 

TelephonyManager  |  Android Developers

 

developer.android.com

 

Android 11의 권한 업데이트  |  Android 개발자  |  Android Developers

Android 11의 권한 업데이트 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Android 11에서는 사용자가 위치, 마이크, 카메라에 관해 더욱 세분화된 권한을 지정

developer.android.com

 

반응형