Разрешение Android не работает, даже если я это объявил
Я пытаюсь написать код для отправки 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/>
синтаксис, не могли бы вы помочь мне, пожалуйста?
15 ответов
(следующее извлечено из моего блога об этом)
Основная причина не получить ваше разрешение в настоящее время заключается в том, что ваш проект имеет targetSdkVersion
от 23 или выше, и запрашиваемое вами разрешение "опасно". В 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
Для этих разрешений не только ваш targetSdkVersion
23+ приложение должно иметь <uses-permission>
элемент (ы), но вы также должны запросить эти разрешения во время выполнения у пользователя на устройствах Android 6.0+, используя такие методы, как checkSelfPermission()
а такжеrequestPermissions()
,
В качестве временного решения, бросьте targetSdkVersion
ниже 23
Однако, в конце концов, у вас будет какая-то причина хотетьtargetSdkVersion
быть 23 или выше. В то же время вам необходимо настроить приложение для использования новой системы разрешений во время выполнения. В документации 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);
}
}
Пожалуйста, перейдите по ссылке ниже, 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
Запросить разрешение прагматично (после 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 или выше, вы должны проверить разрешения во время выполнения.
Когда вы объявляете permisson
в Manifest
и это не работа означает, что вы выполняете задание в MarshMallow
и для MarshMallow
вы установили Permisson на RunTime
,
вот так
ActivityCompat.requestPermissions();
Я добавил это к моей основной деятельности, которая решает мою проблему
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.
}
}
Если вы используете версию Android "23" или "23+", то приложение покажет вам ошибки, когда вы пытаетесь получить доступ ко всему, что требует разрешения пользователя. Вы должны запросить разрешения во время выполнения, даже если вы объявили эти разрешения в манифесте Android.
Проверьте это: https://developer.android.com/training/permissions/requesting.html
Но если вы создали свое приложение целиком и не хотите вносить изменения в любом месте, то небольшого обмана будет достаточно.
Перейдите к файлу "Build.gradle" и измените целевую версию Sdk на менее 23, например, 22, 21.
Надеюсь решение для записи на внешнее хранилище тоже будет полезно
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;
}
}
Наряду с ответом CommonsWare,
Существует настройка безопасности (я проверял на CM13), чтобы установить предел SMS-сообщения. Если для этого параметра установлено значение "Нет", ОС будет открывать диалоговое окно для каждого SMS-сообщения, даже после получения разрешения SMS_SEND во время выполнения. Лучше всего установить это на максимум.
Если максимума недостаточно, существуют способы увеличения максимальной скорости на рутованном устройстве.
Поэтому мне пришлось создать приложение для отправки и получения сообщений, но действие отправки вызывало сбой при каждом нажатии кнопки "Отправить", хотя разрешение было предоставлено. Я запросил разрешения времени выполнения и разрешил их, но все же я столкнулся с сбоем, что у процесса нет запрошенного разрешения на отправку SMS. Я проверил предоставленные разрешения от:
adb shell dumpsys package <package-name>
Порядок моего запроса на разрешения был
- RECEIVE_SMS
- ОТПРАВИТЬ СМС
Я изменил порядок запроса, и он работает нормально. Это было проверено с совершенно новым приложением (удаление -> установить -> тестирование). Ответ может показаться странным, но просто попробуйте.
(Если он работает в указанном порядке в определенном порядке, то в Android может быть ошибка!!)
если ваш уровень API выше 26, вам следует добавить разрешение в свой код следующим образом:
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()
...
Список всех разрешений можно найти с пояснениями на
Вы можете использовать этот код для доступа к своим сообщениям
Откройте диалог, используя код ниже:
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
И больше не нужен код выше
НОТА
Конечно, это не так, и это просто образовательный аспект
Как SDK 23 или выше вводит новый способ запроса разрешений, так что если вы работаете в Marshmallow, он покажет эту ошибку.
Решение: Установите targetSdkVersion ниже 23 в файле манифеста, как этотandroid:targetSdkVersion="21"