개발/Android

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

준그래머 2023. 8. 3. 10:02
반응형

시작

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