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/>
構文に関するものでした。
(以下は これに関する私のブログ記事 )から抜粋したものです。
最近あなたの許可を得られない最大の理由はあなたのプロジェクトが23以上のtargetSdkVersion
を持ち、あなたが要求している許可が "危険"だからです。 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>
要素を持つ必要があるだけでなく、checkSelfPermission()
やrequestPermissions()
のようなメソッドを使って、実行時にAndroid 6.0+デバイス上のユーザーからそれらの権限を要求する必要があります。
一時的な回避策として、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);
}
}
実用的に許可を要求する(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
}
msgstr "" "アプリに許可がある場合、メソッドcheckSelfPermission()はPERMISSION_GRANTEDを返し、アプリは操作を続行できます。".
アプリに権限がない場合、メソッドはPERMISSION_DENIEDを返し、アプリはユーザーに明示的に権限を要求する必要があります。上記のコードに示すように、ユーザーにその許可を求めるプロンプトを出す必要があります。 requestPermissions()を呼び出すと、標準のAndroidダイアログが表示されます。これはカスタマイズできません。」
permisson
をManifest
で宣言しても機能しない場合は、Marshmallow
でタスクを実行していて、Marshmallow
の場合は、PermissonをRunTime
に設定しています。
このように
ActivityCompat.requestPermissions();
Sdk 23以降を使用している場合は、実行時の権限を確認する必要があります。
下のリンクをたどってください https://developer.Android.com/guide/topics/permissions/overview.html
いくつかのサンプルはパーミッションから始めるためにそこにもあります。
Androidをより安全にするためには、開発者はマニフェストで許可に言及する必要があり、また実行時にユーザーに作業を完了させるように依頼する必要があります。以下に記載されている危険許可区分に分類された許可
カレンダー
READ_CALENDAR
WRITE_CALENDAR
カメラ
CAMERA
取引先
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION
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
STORAGE
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
私の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.
}
}
Androidのバージョン "23"または "23+"を使用している場合、ユーザーの許可が必要なものにアクセスしようとすると、アプリにエラーが表示されます。 Androidマニフェストでアクセス許可を宣言している場合でも、実行時にアクセス許可を要求する必要があります。
これをチェックしてください: https://developer.Android.com/training/permissions/requesting.html
しかし、あなたが自分のアプリケーション全体を作成していて、どこでも変更したくないのであれば、ちょっとしたチートで十分です。
"Build.gradle"ファイルに行き、ターゲットのSdkのバージョンを22、21のように23未満に変更します。
CommonsWareの答えと一緒に、
SMS Message Limitを設定するためのセキュリティ設定(CM13でチェックしました)があります。これを "None"に設定すると、ランタイム中にSMS_SENDパーミッションを取得した後でも、OSはすべてのSMSに対してDialogをポップアップします。最良のことはこれを最大に設定することです。
最大数が十分でない場合は、根ざしたデバイスの最大レートを上げる方法があります。
そのため、メッセージを送受信するためのアプリを作成する必要がありましたが、許可が付与されているにもかかわらず、送信をクリックするたびに送信アクションがクラッシュしました。実行時アクセス許可を要求して許可しましたが、それでもプロセスにSMSを送信するための要求された許可がないというクラッシュが発生しました。付与された権限を以下から確認しました。
adb Shell dumpsys package <package-name>
私の許可申請の順序は
要求の順序を元に戻しましたが、問題なく動作します。これは完全に新しいアプリでテストされました(uninstall-> install - > test)。答えは奇妙に思えるかもしれませんが、ただそれを打ってください。
(それが示された方法で特定の順序で機能する場合、Androidにはバグがあるかもしれません!!)
あなたはあなたのメッセージにアクセスするためにこのコードを使うことができます
以下のコードを使用してダイアログを開きます。
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
未満に編集する
そして上記のコードはもう必要ありません。
NOTE
もちろんこれは事実ではなく、それは単なる教育的側面です
私は、外部記憶装置に書き込むための解決策もまた役立つことを願っています
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;
}
}