마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

휴대폰번호를 출력하려고 합니다.

0 추천

휴대폰 번호를 추출하려고 하는데요.. (안드로이드 스튜디오)

getLine1Number(); 만 넣으면 앱 실행시 앱중지가 됩니다..

 

퍼미션

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

public class MainActivity extends AppCompatActivity {

    == 생략 == 
    @Override
    protected void onCreate(Bundle savedInstanceState) {

          TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
          String myNumber = mgr.getLine1Number(); //사용자 휴대폰 번호 반환

          == 생략 == 


    }

}

하루종일 검색해도 답이 나오지 않아 문의 드립니다.

혹시 다른 소스와 충돌이 이유일까요?

전체 소스는 길어서 생략했습니다.

 getLine1Number(); 만 넣으면 앱이 꺼지내요...

 

=====  수정 질문 =====

TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        try {
            userPhone = mgr.getLine1Number();
            userPhone = userPhone.replace("+82","0");
            Toast.makeText(getApplicationContext(), userPhone, Toast.LENGTH_LONG).show();
        }catch (Exception e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }

위처럼 했을때... 앱이 종료되는 현상은 없어졌는데.
Null 값이 넘어 오네요...
에러 메세지는 아래와 같습니다.

getLine1NumberForDisplay:Neither user 10603 nor current process has
android.permisstion.READ_PHONE_STATE,
android.permisstion.READ_SMS, or
android.permisstion.READ_PHONE_NUMBERS

그런데 퍼미션 설정은 모두 한 상태입니다.
 <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 <uses-permission android:name="android.permission.READ_SMS"/>

송투마이 (250 포인트) 님이 2020년 10월 19일 질문
송투마이님이 2020년 10월 19일 수정
에러 로그도 올려주시면 다른 분들이 답을 찾는데 도움이 되지 않을까요?
감사합니다..

TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        try {
            userPhone = mgr.getLine1Number();
            userPhone = userPhone.replace("+82","0");
            Toast.makeText(getApplicationContext(), userPhone, Toast.LENGTH_LONG).show();
        }catch (Exception e) {
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }

위처럼 했을때... 앱이 종료되는 현상은 없어졌는데.
Null 값이 넘어 오네요...
에러 메세지는 아래와 같습니다.

getLine1NumberForDisplay:Neither user 10603 nor current process has
android.permisstion.READ_PHONE_STATE,
android.permisstion.READ_SMS, or
android.permisstion.READ_PHONE_NUMBERS

그런데 퍼미션 설정은 모두 한 상태입니다.

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

2개의 답변

0 추천
혹시 디바이스가 SIM카드를 사용할 수 없거나 하는 하드웨어적으로 지원이 안되는 경우가 아닌가요?

그리고 Toast를 사용하지 마시고 브레이크 포인트를 설정하셔서 디버깅을 해보세요. 그래야 정확한 Exception을 발견하시는데도 도움이 되고, 릴리즈하실 때는 어차피 Toast 지우실 테니 아예 사용하지 않으시면 굳이 두번 작업을 안하셔도 되구요.
spark (226,380 포인트) 님이 2020년 10월 20일 답변
현재 사용하고 있는 휴대폰이라 전화번호도 있고, SIM카드도 사용할 수 있습니다.
분명 READ_PHONE_STATE 퍼미션도 설정했는데,  전화권한이 허용되지 않는것 같습니다.
혹시 해당 폰에 폰넘버가 세팅이 되어 있나요? 디바이스 세팅에 전화번호를 설정하는 곳이 있는데, 여기에 세팅이 되어 있어야 null이 안나온다네요. 디폴트는 아무 것도 설정되지 않습니다.
디바이스셋팅이라함은 개인 휴대폰 설정 > 휴대폰 정보에 전화번호 써있는걸 말씀하신건지요? 그렇다면 전화번호가 적혀 있습니다~~
혹시 런타임 퍼미션은 요청해 보셨나요?
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
안드로이드 6.0 이상에서는 런타임 퍼미션이 추가됐기 때문에 한번 확인해 보세요.
제가 초보자라 런타임 퍼미션을 확인하고 적용하는 방법을 몰라서 검색해서 아래 처럼 해보았는데 잘 안되더라구요...

        String phoneNumber = "";
        TelephonyManager mTelephonyManager = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
        /* int MY_PERMISSTION_REQUEST_READ_CONTACTS = 1; */
        int MY_PERMISSTION_REQUEST_READ_PHONE_STATE = 1;
        if(mTelephonyManager != null) {
            if(Build.VERSION.SDK_INT >= 23){

                if(ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(this, "전화 권한이 허용되지 않았습니다.", Toast.LENGTH_SHORT).show();

                    if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)){
                        ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.READ_PHONE_STATE}, MY_PERMISSTION_REQUEST_READ_PHONE_STATE);

                        String telNumber = mTelephonyManager.getLine1Number();
                        phoneNumber = telNumber.replace("+82", "0");

                    }else{

                    }

                }else if(mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_UNKNOWN || mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_ABSENT){
                    Toast.makeText(this, "유심이 없거나, 알 수 없는 유심입니다.", Toast.LENGTH_SHORT).show();
                    moveTaskToBack(true);
                    finish();
                    android.os.Process.killProcess(android.os.Process.myPid());
                }else{
                    String telNumber = mTelephonyManager.getLine1Number();
                    phoneNumber = telNumber.replace("+82", "0");
                }
            }else{
                String telNumber = mTelephonyManager.getLine1Number();
                phoneNumber = telNumber.replace("+82", "0");
            }
        }

Toast 주석 풀었을때 "전화 권한이 허용되지 않았습니다" 라고 나옵니다..

도움 좀 부탁드립니다~~
0 추천

https://developer.android.com/training/permissions/requesting#java 를 보시면 자세한 설명이 나와 있구요, 저도 매일 쓰는 부분이 아니라서 해당 문서를 참조했어요. AndroidX Result API를 사용하도록 문서가 업데이트 된 것 같네요. 하시다가 막히는게 생기시면 저 사이트로 가셔서 디테일한 내용을 확인하시길 바래요.

대충 아랫처럼 퍼미션을 핸들링하는 클래스를 하나 만들어 봤습니다. 여러군데서 사용할 수 있는 기능이므로 Generlaization하면 훨씬 더 좋겠죠.

public class PermissionResolver {

    private final int PERMISSION_REQUEST_CODE = 1004;

    private final Activity activity;
    private String[] wantedPermissions;
    private int minSdkVersion = Build.VERSION_CODES.M;
    private PermissionResolverCallback callback;

    private PermissionResolver(Activity activity) {
        this.activity = activity;
    }

    public static PermissionResolver with(Activity activity) {
        return new PermissionResolver(activity);
    }

    public PermissionResolver want(String[] wantedPermissions) {
        this.wantedPermissions = wantedPermissions;
        return this;
    }

    public PermissionResolver minSdk(int minSdkVersion) {
        this.minSdkVersion = minSdkVersion;
        return this;
    }

    public PermissionResolver callback(PermissionResolverCallback callback) {
        this.callback = callback;
        return this;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public void requestPermission() {
        TelephonyManager telephonyManager = OSUtil.getTelephonyManager(activity.getApplicationContext());
        if (telephonyManager == null) {
            callback.onError(new SystemServiceNotFoundException("Cannot find TelephonyManager"));
            return;
        }

        if (!isSdkSupported()) {
            callback.onSdkNotSupported();
            return;
        }

        if (allPermissionsGranted()) {
            callback.onPermissionsResolved();
            return;
        }

        ActivityCompat.requestPermissions(activity, getUnresolvedPermissions(), PERMISSION_REQUEST_CODE);
    }

    private boolean allPermissionsGranted() {
        return  getUnresolvedPermissions().length == 0;
    }

    private boolean isSdkSupported() {
        return OSUtil.isSdkGreaterEqualThan(minSdkVersion);
    }

    @NotNull
    private String[] getUnresolvedPermissions() {
        List<String> result = new ArrayList<>();
        for (String permission : wantedPermissions) {
            boolean granted = ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED;
            if (!granted) {
                result.add(permission);
            }
        }

        return result.toArray(new String[]{});
    }


    public void onRequestPermissionsResult(int requestCode, String[] requestedPermissions) {
        if (requestCode != PERMISSION_REQUEST_CODE) return;

        if (requestedPermissions.length == 0) {
            callback.onPermissionsCancelled();
            return;
        }
;
        if (allPermissionsGranted()) {
            callback.onPermissionsResolved();
            return;
        }

        callback.onPermissionsDenied(unresolvedPermissions);
    }

}


public interface PermissionResolverCallback {
    void onError(Exception e);

    void onSdkNotSupported();

    void onPermissionsCancelled();

    void onPermissionsResolved();

    void onPermissionsDenied(String[] unresolvedPermissions);
}


public class OSUtil {

    public static TelephonyManager getTelephonyManager(Context context) {
        return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }
     
    public static boolean isSdkGreaterEqualThan(int apiLevel) {
        return Build.VERSION.SDK_INT >= apiLevel;
    }
}



public class PermissionUtil {

    private final static String[] PHONE_NUMBER_PERMISSION_OREO = new String[]{
            Manifest.permission.READ_PHONE_NUMBERS,
            Manifest.permission.READ_PHONE_STATE};

    private final static String[] PHONE_NUMBER_PERMISSION = new String[]{
            Manifest.permission.READ_PHONE_STATE};


    @NonNull
    public static String[] getReadPhoneNumberPermissions() {
        return OSUtil.isSdkGreaterEqualThan(Build.VERSION_CODES.O) ?
                PHONE_NUMBER_PERMISSION_OREO : PHONE_NUMBER_PERMISSION;
    }

}

 

PermissionResolver는 activity, callback 등등이 초기화가 필요하기 때문에 requestPermission하시기 전에 validation을 해주는 것도 좋을 것 같구요. 현재 수락이 안된 퍼미션을 구하는 부분은 Java8 stream API를 온전히 쓰실 수 있다면 그걸 사용하는 게 더 깔끔할 것 같습니다.

사용은 이런 식으로 하면 됩니다.

private PermissionResolver permissionResolver;
        
        permissionResolver = PermissionResolver.with(this)
                .minSdk(Build.VERSION_CODES.M)
                .want(PermissionUtil.getReadPhoneNumberPermissions())
                .callback(new PermissionResolverCallback() {
                    @Override
                    public void onError(Exception e) {
                         // 필요한 처리
                    }

                    @Override
                    public void onSdkNotSupported() {
                         // 필요한 처리
                    }

                    @Override
                    public void onPermissionsCancelled() {
                          // 필요한 처리
                    }

                    @Override
                    public void onPermissionsResolved() {
                         // 필요한 처리
                    }

                    @Override
                    public void onPermissionsDenied(String[] unresolvedPermissions) {
                         // 필요한 처리
                    }
                });

        permissionResolver.requestPermission();



@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        permissionResolver.onRequestPermissionsResult(requestCode, permissions);
    }

테스트를 안해 본 온전한 코드가 아니므로, 그대로 copy & paste 하지 마시고 개념을 이해하신 다음, 필요한 부분은 보완해 가시길 바랍니다. 

 먼저, 아랫처럼 Result API를 사용하기 추가하시면 좀 더 직관적인 코드를 작성하실 수 있습니다. 사용법은 첫라인의 링크에 나와 있습니다.

dependencies {
    def activity_version = "1.1.0"

    // Java language implementation
    implementation "androidx.activity:activity:$activity_version"
    // Kotlin
    implementation "androidx.activity:activity-ktx:$activity_version"
}

 

spark (226,380 포인트) 님이 2020년 10월 24일 답변
spark님이 2020년 10월 25일 수정
아 감사합니다...
spark님 덕분에 잘 처리했습니다~~
...