Дозвіл на Android не працює, навіть якщо я його заявив


167

Я намагаюся написати код, щоб надіслати SMS з програми Android, але коли я намагаюся надіслати 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

Я тестую на android 6.0
Nathan Loudjani

1
напевно, він буде працювати на нижній версії Android. В андроїд 6.0 з'явилася нова філософія дозволів
Fakher

Чи є спеціальний синтаксис для android 6? Як я можу бути впевнений, що він працює на нижній версії?
Натан Луджані

мій попередній targetsdkversionбув 23оновлений , щоб 27після оновлення програми READ_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>елементи, але ви також повинні запитувати ці дозволи у користувача на пристроях Android 6.0+, використовуючи такі методи, як checkSelfPermission()і requestPermissions().

Як тимчасове вирішення, опустіть targetSdkVersionнижче 23.

Однак, зрештою, у вас з’явиться якась причина, щоб ви хотіли, щоб ваше targetSdkVersionбуло 23 або більше. У той час вам потрібно буде налаштувати додаток, щоб використовувати нову систему дозволів виконання. Документація на Android має сторінку, присвячену цій темі .


2
Дуже дякую, я використав методи requestPermissions (), і я добре працював
Nathan Loudjani

Гаразд, я намагався це зробити раніше, але не зміг отримати методи ContextCompat.checkSelfPermission та ActivityCompat.requestPermissions, вони дають мені помилку "не знайдено" у назвах методів. Я здогадуюсь, що це стосується відсутньої бібліотеки, схоже, вона є в v4-пакеті, але моя єдина залежність від gradle compile 'com.android.support:appcompat-v7:22.2.1'. Чи слід змінити це на v4?
Озі

2
@Ozzy: Вам потрібно бути в поколінні V23 бібліотек підтримки ( 23.x.yдля поточних значень x і y), а не v22, який ви зараз використовуєте.
CommonsWare

Дякую, я думаю, на майбутнє Наразі я змінив ціль назад на v22, і навіть незважаючи на те, що для емулятора зберігання SD-картки було встановлено 200MB, це дозволило мені помилково не встановити карту SD. Але потім я підключив свій телефон у режимі розробника і все працює. Чомусь зберігання SD-карт працює на емуляторі, що працює в v23, але не v22.
Ozzy

3
@NathanLoudjani Чи не проти поділитися кодом, який реалізує це? Я в точно такому ж човні і намагаюся вкласти це у свою діяльність.
dschuett

29

Вище рівня 23 API вам буде надано програмно прагматично, як:

    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 (це нова String [] {Manifest.permission.SEND_SMS}, 1); і про що йдеться у 1?
LizG


6

коли ви оголошуєте permissonв Manifestі це не працює засіб ви виконуєте завдання в MarshMallowі MarshMallowви встановили в згоди автора RunTime.

як це

ActivityCompat.requestPermissions();

6

Перейдіть за посиланням нижче https://developer.android.com/guide/topics/permissions/overview.html

Деякі зразки також доступні для початку роботи з дозволами.

Щоб зробити Android більш безпечним, зараз розробникам доводиться згадувати дозвіл у маніфесті, а також вони повинні просити користувачів, як і в проміжок часу, щоб виконати роботу. Вони є дозволом, віднесеним до категорії небезпечних дозволів, про які йдеться нижче

КАЛЕНДАР

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

СМС

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 на менше 23, наприклад 22, 21.


1

Поряд з відповіддю CommonsWare,

Існує налаштування безпеки (я перевірив CM13), щоб встановити ліміт SMS-повідомлень. Якщо встановити цей параметр на "Немає", ОС з'явиться діалоговим вікном для кожного SMS, навіть після отримання дозволу SMS_SEND під час виконання. Найкраще встановити це на максимумі.

Якщо максимуму недостатньо, є способи підвищення максимальної швидкості на вкоріненому пристрої.


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і чанчів targetSdkVersionменше, ніж 23
І більше не потрібен код вище

ПРИМІТКА
Звичайно, це не так, а це лише освітній аспект


0

Тож мені довелося створити додаток для надсилання та отримання повідомлень, але дія надсилання припинялася кожного разу, коли я натискав на відправку, хоча дозвіл був наданий. Я попросив дозволу на виконання та дозволив їх, все-таки я зіткнувся з аварією, що процес не має запитуваного дозволу на надсилання SMS. Я перевірив надані дозволи від:

adb shell dumpsys package <package-name>

Порядок мого запиту на отримання дозволів був

  1. RECEIVE_SMS
  2. SEND_SMS

Я повернув порядок запиту, і він працює чудово. Це було перевірено новим додатком (видалення -> встановлення -> тест). Відповідь може здатися дивною, але просто спробуйте.

(Якщо він працює показаним способом у певному порядку, то в 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;
        }
    }

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.