190

I'm trying to write code to send an SMS from an Android app, but when I try to send the SMS it sends me back the error:

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)

I checked but I have the permissions in the manifest, as follows:

<?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>

I searched the internet but all the errors were about the <uses-permission/> syntax, could you help me please?

Min Phone
  • 3
  • 4
Nathan Loudjani
  • 2,056
  • 2
  • 11
  • 11

12 Answers12

256

(the following is extracted from a blog post of mine about this)

The big reason for not getting your permission nowadays is because your project has a targetSdkVersion of 23 or higher, and the permission that you are requesting is "dangerous". In Android 6.0, this includes:

  • ACCEPT_HANDOVER
  • ACCESS_BACKGROUND_LOCATION
  • ACCESS_MEDIA_LOCATION
  • ACTIVITY_RECOGNITION
  • ANSWER_PHONE_CALLS
  • 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

For these permissions, not only does your targetSdkVersion 23+ app need to have the <uses-permission> element(s), but you also have to ask for those permissions at runtime from the user on Android 6.0+ devices, using methods like checkSelfPermission() and requestPermissions().

As a temporary workaround, drop your targetSdkVersion below 23.

However, eventually, you will have some reason to want your targetSdkVersion to be 23 or higher. At that time, you will need to adjust your app to use the new runtime permission system. The Android documentation has a page dedicated to this topic.

Nikunj Paradva
  • 15,332
  • 5
  • 54
  • 65
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 2
    Thank you very much, I used the requestPermissions() methods and i worked well – Nathan Loudjani Sep 17 '15 at 17:15
  • Okay, I attempted this before but couldn't get the ContextCompat.checkSelfPermission and ActivityCompat.requestPermissions methods, they give me a 'not found' error on the method names. I'm guessing it's to do with a missing library, it seems to be in a v4 package but my only gradle dependency is `compile 'com.android.support:appcompat-v7:22.2.1'`. Should I change this to v4? – Ozzy Jan 06 '16 at 15:27
  • 2
    @Ozzy: You need to be on a v23 generation of the support libraries (`23.x.y`, for current values of x and y), rather than the v22 that you are presently using. – CommonsWare Jan 06 '16 at 15:48
  • Thanks, for future I guess. For now I changed the target back to v22 and even though SD card storage was set to 200MB on the emulator, it gave me SD card not mounted error. But then I connected my phone in developer mode and everything works. For some reason SD card storage works on the emulator running v23 but not v22. – Ozzy Jan 06 '16 at 15:54
  • 3
    @NathanLoudjani Would you mind sharing your code that implements this? I am in the exact same boat and am struggling putting this into my activity. – dschuett Jan 23 '16 at 03:52
  • @NathanLoudjani What did you end up doing? I am also pretty confused. – Ruchir Baronia Apr 09 '16 at 03:55
  • @CommonsWare So do we have to ask the user for the permission **every time** I need to use that functionality? Thanks – Ruchir Baronia Apr 09 '16 at 03:56
  • @RuchirBaronia: No. You only have to ask if you do not have the permission. Usually, you will only have to ask once, and the user will grant the permission. Conversely, if users decide not to grant you the permission, please try to degrade gracefully, or otherwise explain in detail that your app cannot work without the permission. – CommonsWare Apr 09 '16 at 11:34
  • even its happening in target version 21 too. its happening on 23 and above? or 21 and above.? – Happy Sep 06 '16 at 11:49
  • @Vji: "even its happening" -- I do not know what "its" is. "in target version 21 too" -- a `targetSdkVersion` of 21 does not require that the developer implement runtime permission support. "its happening on 23 and above?" -- I do not know what "its" is. You may wish to ask a separate Stack Overflow question, where you can provide a [mcve] and explain your concerns. – CommonsWare Sep 06 '16 at 13:12
  • Late to the party, hope you are still active. Where did you extract that list? I cannot find a list of dangerous/normal permissions in the android dev resoiurces.. – Leviathan Oct 12 '20 at 12:40
  • 1
    @Leviathan: At the time, I got that list from the docs, I think from the page that I link to at the end of the answer. Unfortunately, Google seems to have dropped that list, which is both unfortunate and typical. For an individual permission, its entry in `Manifest.permission` should show its protection level, (e.g., [`ACCESS_COARSE_LOCATION`](https://developer.android.com/reference/android/Manifest.permission#ACCESS_COARSE_LOCATION)). – CommonsWare Oct 12 '20 at 12:44
  • Yeah thanks @CommonsWare , I found that, too. But no way to filter there, so I don't know why they removed a clear grouped list. If we're on the topic, is there a way to explicity request permission for a regular permission? Our data protection law requires to ask for Push Notifications explicity before sending them, but afaik they can be received as soon as the app is installed and they are in the manifest. – Leviathan Oct 12 '20 at 12:56
  • 1
    @Leviathan: "is there a way to explicity request permission for a regular permission?" -- no, sorry. "Our data protection law requires to ask for Push Notifications explicity before sending them, but afaik they can be received as soon as the app is installed and they are in the manifest" -- that is not a permission. Have the receiver or service be disabled in the manifest, show your own dialog, and if the user agrees, enable the component. – CommonsWare Oct 12 '20 at 13:05
  • in this moment I found that in order to check the protection level for each permission directly from the Android documentation you have to go to: https://developer.android.com/reference/android/Manifest.permission#permission-of-interest, e.g. for CAMERA it's https://developer.android.com/reference/android/Manifest.permission#CAMERA – Antonino Oct 19 '20 at 08:03
33

Above API level 23 you will be given programmatically pragmatically like:

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

        }
    }
Zoe
  • 27,060
  • 21
  • 118
  • 148
user7176550
  • 1,501
  • 14
  • 19
10

request permission pragmatically (after 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
}

"If the app has the permission, the method checkSelfPermission() returns PERMISSION_GRANTED, and the app can proceed with the operation.

If the app does not have the permission, the method returns PERMISSION_DENIED, and the app has to explicitly ask the user for permission. You need to prompt the user for that permission, as shown in the above code. Calling requestPermissions() brings up a standard Android dialog, which you cannot customize."

Dan Alboteanu
  • 9,404
  • 1
  • 52
  • 40
  • Where would we put this line? ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_SMS},1); and what does the 1 refer to? – LizG Oct 02 '18 at 22:46
8

Please go through the link below, 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
Paolo
  • 20,112
  • 21
  • 72
  • 113
Rishabh Saxena
  • 1,765
  • 15
  • 26
7

If you are using sdk 23 or higher then you must check run time permissions.

6

when you declare permisson in Manifest and it's not work means you are performing Task in MarshMallow and for MarshMallow you have set Permisson at RunTime.

like this way

ActivityCompat.requestPermissions();
Harshad Pansuriya
  • 20,189
  • 8
  • 67
  • 95
2

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.

Zohaib Hassan
  • 984
  • 2
  • 7
  • 11
1

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.

Dumi Jay
  • 1,057
  • 10
  • 10
1

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.
            }
        }
Masquitos
  • 554
  • 4
  • 22
1

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;
        }
    }
Harshad Pansuriya
  • 20,189
  • 8
  • 67
  • 95
SergeyYu
  • 354
  • 1
  • 5
  • 20
1

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

  • Yes... Great!! ALHAMDULILLAH. This worked PERFECTLY. By requesting permission in the order you suggested. Here is a sample: ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.ReadPhoneState, Manifest.Permission.SendSms, Manifest.Permission.ReadSms, Manifest.Permission.ReceiveSms }, 0); – Momodu Deen Swarray Apr 08 '23 at 23:22
0

if you API level greater than 26 you should add permission to your code like that:

class MainActivity : AppCompatActivity() {

    val cManageSMS=cManageSMS() // <-- initialize your SMS handling class
    ...
    override fun onCreate(savedInstanceState: Bundle?) {

    // Adding permission
    var myPermission: Array<String> = arrayOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS)
    ActivityCompat.requestPermissions(this, myPermission,1)

    // Call to your readSms() method (important! readSms method should be after permission setting!)
    cManageSMS.readSms()
    ...
helvete
  • 2,455
  • 13
  • 33
  • 37
alchemist
  • 37
  • 3