선언해도 Android 권한이 작동하지 않습니다


167

Android 앱에서 SMS를 보내는 코드를 작성하려고하는데 SMS를 보내려고하면 오류가 다시 발생합니다.

09-17 18:37:29.974  12847-12847/**.**.****E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: **.**.****, PID: 12847
java.lang.SecurityException: Sending SMS message: uid 10092 does not have android.permission.SEND_SMS.
        at android.os.Parcel.readException(Parcel.java:1599)
        at android.os.Parcel.readException(Parcel.java:1552)
        at com.android.internal.telephony.ISms$Stub$Proxy.sendTextForSubscriber(ISms.java:768)
        at android.telephony.SmsManager.sendTextMessageInternal(SmsManager.java:310)
        at android.telephony.SmsManager.sendTextMessage(SmsManager.java:293)
        at **.**.****.MainActivity$3.onClick(MainActivity.java:70)
        at android.view.View.performClick(View.java:5198)
        at android.view.View$PerformClick.run(View.java:21147)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

확인했지만 다음과 같이 매니페스트에 권한이 있습니다.

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-feature android:name="android.hardware.telephony"
    android:required="true"/>

<application
    android:exported="true"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

인터넷을 검색했지만 모든 오류가 <uses-permission/>구문 에 관한 것이 었습니다. 제발 도와 주시겠습니까?


어떤 Android 버전을 테스트하고 있습니까?
CommonsWare

나는 안드로이드 6.0에서 테스트하고있어
나단 Loudjani

1
확실히 그것은 아래 버전의 안드로이드에서 작동합니다. 안드로이드 6.0에는 새로운 권한 철학이 있습니다
Fakher

android 6에 대한 특별한 구문이 있습니까? 버전 아래에서 작동하는지 어떻게 확인할 수 있습니까?
Nathan Loudjani

내 이전 targetsdkversion은 앱 업데이트 권한이 작동하지 않는 것으로 23업데이트되었으며 이미 활성화되어 있습니다. 도와주세요27READ_SMS
Sagar

답변:


237

(다음은 내 블로그 게시물 에서 추출되었습니다 )

현재 귀하의 허가를받지 않는 가장 큰 이유는 귀하의 프로젝트가 targetSdkVersion23 이상이고 요청한 허가가 "위험"하기 때문입니다. Android 6.0에서는 다음이 포함됩니다.

  • ACCESS_COARSE_LOCATION
  • ACCESS_FINE_LOCATION
  • ADD_VOICEMAIL
  • BODY_SENSORS
  • CALL_PHONE
  • CAMERA
  • GET_ACCOUNTS
  • PROCESS_OUTGOING_CALLS
  • READ_CALENDAR
  • READ_CALL_LOG
  • READ_CELL_BROADCASTS
  • READ_CONTACTS
  • READ_EXTERNAL_STORAGE
  • READ_PHONE_STATE
  • READ_SMS
  • RECEIVE_MMS
  • RECEIVE_SMS
  • RECEIVE_WAP_PUSH
  • RECORD_AUDIO
  • SEND_SMS
  • USE_SIP
  • WRITE_CALENDAR
  • WRITE_CALL_LOG
  • WRITE_CONTACTS
  • WRITE_EXTERNAL_STORAGE

이러한 권한의 경우 targetSdkVersion23+ 앱에는 <uses-permission>요소가 있어야 할뿐만 아니라 런타임과 checkSelfPermission()and 같은 방법을 사용하여 Android 6.0 이상 기기의 사용자에게 해당 권한을 요청해야합니다 requestPermissions().

임시 해결 방법으로 targetSdkVersion23 이하로 떨어 뜨립니다 .

그러나 결국에는 targetSdkVersion23 세 이상이 되기를 원하는 이유 가 있습니다. 이때 새로운 런타임 권한 시스템을 사용하도록 앱을 조정해야합니다. Android 문서에는 이 주제 전용 페이지가 있습니다 .


2
나는 requestPermissions () 메소드를 사용하고 내가 잘 작동, 대단히 감사합니다
나단 Loudjani에게

좋아, 나는 이것을 전에 시도했지만 ContextCompat.checkSelfPermission 및 ActivityCompat.requestPermissions 메소드를 얻을 수 없었으며 메소드 이름에 '찾을 수 없음'오류가 발생합니다. 누락 된 라이브러리와 관련이 있다고 생각합니다 .v4 패키지에있는 것처럼 보이지만 유일한 gradle 종속성은 compile 'com.android.support:appcompat-v7:22.2.1'입니다. 이것을 v4로 변경해야합니까?
Ozzy

2
@Ozzy : 23.x.y현재 사용중인 v22가 아니라 v23 세대의 지원 라이브러리 ( x 및 y의 현재 값의 경우)에 있어야합니다.
CommonsWare

고마워, 미래에 나는 추측한다. 지금은 대상을 v22로 다시 변경했으며 에뮬레이터에서 SD 카드 저장소가 200MB로 설정되어 있어도 SD 카드 마운트 오류가 발생했습니다. 그러나 개발자 모드로 휴대 전화를 연결하면 모든 것이 작동합니다. 어떤 이유로 SD 카드 스토리지는 v22가 아닌 v23을 실행하는 에뮬레이터에서 작동합니다.
Ozzy

3
@NathanLoudjani 이것을 구현하는 코드를 공유 하시겠습니까? 나는 똑같은 보트에 있고 이것을 내 활동에 넣는 데 어려움을 겪고 있습니다.
dschuett

29

API 레벨 23 이상에서는 다음과 같이 프로그래밍 방식으로 실용적으로 제공됩니다.

    private static final int PERMISSION_REQUEST_CODE = 1;

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

        if (checkSelfPermission(Manifest.permission.SEND_SMS)
                == PackageManager.PERMISSION_DENIED) {

            Log.d("permission", "permission denied to SEND_SMS - requesting it");
            String[] permissions = {Manifest.permission.SEND_SMS};

            requestPermissions(permissions, PERMISSION_REQUEST_CODE);

        }
    }

7

실용적으로 권한 요청 (API 23 이후)

if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.SEND_SMS)
    != PackageManager.PERMISSION_GRANTED) {
    // Permission is not granted 
    // Ask for permision
    ActivityCompat.requestPermissions(this,new String[] { Manifest.permission.SEND_SMS}, 1); 
} 
else {
// Permission has already been granted
}

"앱에 권한이있는 경우 checkSelfPermission () 메서드는 PERMISSION_GRANTED를 반환하고 앱은 작업을 진행할 수 있습니다.

앱에 권한이없는 경우이 메서드는 PERMISSION_DENIED를 반환하며 앱은 사용자에게 명시 적으로 권한을 요청해야합니다. 위의 코드와 같이 사용자에게 해당 권한을 묻는 메시지가 표시되어야합니다. requestPermissions ()를 호출하면 사용자 정의 할 수없는 표준 Android 대화 상자가 나타납니다. "


이 줄을 어디에 둘까요? ActivityCompat.requestPermissions (this, new String [] {Manifest.permission.SEND_SMS}, 1); 그리고 1은 무엇을 의미합니까?
LizG


6

당신은 선언 할 때 permissonManifest그것은 당신이 작업을 수행하는 수단 작동하지 않을 것 MarshMallow과에 대한 MarshMallow당신에 Permisson를 설정을 RunTime.

이런 식으로

ActivityCompat.requestPermissions();

6

https://developer.android.com/guide/topics/permissions/overview.html 링크를 통해 이동 하십시오

권한을 시작하기 위해 일부 샘플도 제공됩니다.

안드로이드를보다 안전하게 만들려면 개발자는 매니페스트에 대한 권한을 언급해야하며 런타임에 사용자에게 요청하여 작업을 완료해야합니다. 아래에 언급 된 위험한 권한 섹션에 분류 된 권한입니다.

달력

READ_CALENDAR

WRITE_CALENDAR

카메라

CAMERA

콘택트 렌즈

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

위치

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

마이크로폰

RECORD_AUDIO

전화

READ_PHONE_STATE
READ_PHONE_NUMBERS
CALL_PHONE
ANSWER_PHONE_CALLS (must request at runtime)
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
ANSWER_PHONE_CALLS

센서

BODY_SENSORS

SMS

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

저장

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

2

내 MainActivity에 이것을 추가하여 문제를 해결했습니다.

       int MY_PERMISSIONS_REQUEST_READ_CONTACTS=0;
// Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.

            } else {

                // No explanation needed, we can request the permission.

                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_READ_CONTACTS);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }

2

Android 버전 "23"또는 "23+"를 사용하는 경우 사용자의 승인이 필요한 항목에 액세스하려고하면 앱에 오류가 표시됩니다. Android 매니페스트에서 해당 권한을 선언 한 경우에도 런타임시 권한을 요청해야합니다.

이것을 확인하십시오 : https://developer.android.com/training/permissions/requesting.html

그러나 전체 응용 프로그램을 만들고 모든 곳에서 변경하고 싶지 않은 경우 약간의 치트가 충분합니다.

"Build.gradle"파일로 이동하여 대상 Sdk 버전을 22, 21과 같이 23 미만으로 변경하십시오.


1

CommonsWare의 답변과 함께

SMS 메시지 제한을 설정하기위한 보안 설정 (CM13에서 확인)이 있습니다. 이것을 "없음"으로 설정하면, OS는 런타임에서 SMS_SEND 권한을 얻은 후에도 모든 SMS에 대한 대화 상자를 팝업합니다. 가장 좋은 것은 이것을 최대로 설정하는 것입니다.

최대 값이 충분하지 않으면 루팅 된 장치에서 최대 속도를 높이는 방법이 있습니다.


0

이 코드를 사용하여 메시지에 액세스 할 수 있습니다

아래 코드를 사용하여 대화 상자를 엽니 다.

ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    1);

아래와 같이 활동 결과를 얻으십시오.

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1: {

          // If request is cancelled, the result arrays are empty.
          if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.          
            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

또는 파일 build.gradle및 chanche 수를 targetSdkVersion보다 적게 편집 하고 23
더 이상 위의 코드가 필요하지 않습니다

참고
물론 이것은 사실이 아니며 단지 교육적인 측면 일뿐입니다


0

따라서 메시지를 보내고받을 앱을 만들어야했지만 권한이 부여 된 경우에도 보내기를 클릭 할 때마다 보내기 작업이 중단되었습니다. 런타임 권한을 요청하고 허용했지만 여전히 프로세스에 SMS를 보낼 수있는 권한이 없다는 충돌이 발생했습니다. 다음에서 부여 된 권한을 확인했습니다.

adb shell dumpsys package <package-name>

권한 요청 순서는

  1. RECEIVE_SMS
  2. 문자를 보내다

요청 순서를 되 돌렸고 제대로 작동합니다. 이것은 완전히 새로운 응용 프로그램 (uninstall-> install-> test)으로 테스트되었습니다. 대답은 이상하게 보일지 모르지만 그냥 쏴라.

(특정 순서대로 표시된 방식으로 작동하면 Android에 버그가있을 수 있습니다!)


0

외부 저장소에 쓰는 솔루션도 유용 할 수 있기를 바랍니다.

public  boolean checkPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                Timber.tag(LOG_TAG).e("Permission error. You have permission");
                return true;
            } else {
                Timber.tag(LOG_TAG).e("Permission error. You have asked for permission");
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                return false;
            }
        }
        else { 
            // for a stuff below api level 23
            Timber.tag(LOG_TAG).e("Permission error. You already have the permission");
            return true;
        }
    }

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.