development

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

big-blog 2020. 6. 6. 07:58
반응형

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


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/>구문 에 관한 것이 었습니다. 제발 도와 줄 수 있습니까?


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

현재 귀하의 허가를받지 않는 가장 큰 이유는 귀하의 프로젝트가 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 문서에는 이 주제 전용 페이지가 있습니다 .


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);

        }
    }

실용적으로 권한 요청 (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 대화 상자가 나타납니다. "


SDK 23 이상을 사용하는 경우 런타임 권한을 확인해야합니다.


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

이런 식으로

ActivityCompat.requestPermissions();

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

Some samples are also available there to get start with the permissions.

To make android more secure now developers has to mention permission in manifest as well as they should have to ask user as well in run time to get the work done. They are permission categorized in dangerous permission section which are mention below

CALENDAR

READ_CALENDAR

WRITE_CALENDAR

CAMERA

CAMERA

CONTACTS

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

LOCATION

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

MICROPHONE

RECORD_AUDIO

PHONE

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

SENSORS

BODY_SENSORS

SMS

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

STORAGE

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

I added this to my MainActivity, that resolve my problem

       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.
            }
        }

If you are using Android version "23" or "23+", then app will show you errors when you are trying to access anything which requires user's permission. You have to ask for permissions at run-time even if you have declared those permissions in Android manifest.

Check this: https://developer.android.com/training/permissions/requesting.html

But if you have created your whole application and don't want to change at every place then a little cheat will be sufficient.

Go to "Build.gradle" file and change the target Sdk version to less than 23, like 22, 21.


Along with CommonsWare's answer,

There is a Security Setting (I checked on CM13) to set SMS Message Limit. If you set this to "None", OS will popup a Dialog for every SMS, even after obtaining SMS_SEND permission in the runtime. Best thing is to set this to maximum.

If the maximum is not enough, there are ways to increases the maximum rate on a rooted device.


You can use this code to access your messages

Open a Dialog using the code below:

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

Get the Activity result as below:

@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
    }
}

or edit file build.gradle and chanche number targetSdkVersion less than 23
And no longer need the code above

NOTE
Of course this is not the case, and it's just an educational aspect


So i had to create an app to send and receive messages but the send action crashed whenever i clicked on send even though the permission was granted . I had requested runtime permissions and allowed them, still i faced a crash that the process doesnt have the requested permission to send SMS . I had checked the granted permissions from :

adb shell dumpsys package <package-name>

The order of my request for permissions was

  1. RECEIVE_SMS
  2. SEND_SMS

I reverted the order of request and it works fine . This was tested with a complete new app(uninstall-> install -> test). The answer may seem weird but just give it a shot .

(If it works in the shown way in a certain order, then Android might have a bug!!)


I hope the solution to write to external storage will be useful too

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;
        }
    }

참고URL : https://stackoverflow.com/questions/32635704/android-permission-doesnt-work-even-if-i-have-declared-it

반응형