web-dev-qa-db-ja.com

宣言しても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/>構文に関するものでした。

153
Nathan Loudjani

(以下は これに関する私のブログ記事 )から抜粋したものです。

最近あなたの許可を得られない最大の理由はあなたのプロジェクトが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のドキュメントは このトピック専用のページ です。

220
CommonsWare

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

        }
    }
26
user7176550

実用的に許可を要求する(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ダイアログが表示されます。これはカスタマイズできません。」

7
Dan Alboteanu

permissonManifestで宣言しても機能しない場合は、Marshmallowでタスクを実行していて、Marshmallowの場合は、PermissonをRunTimeに設定しています。

このように

ActivityCompat.requestPermissions();
6
Ironman

Sdk 23以降を使用している場合は、実行時の権限を確認する必要があります。

6

下のリンクをたどってください 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
5
Rishabh Saxena

私の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
Masquitos

Androidのバージョン "23"または "23+"を使用している場合、ユーザーの許可が必要なものにアクセスしようとすると、アプリにエラーが表示されます。 Androidマニフェストでアクセス許可を宣言している場合でも、実行時にアクセス許可を要求する必要があります。

これをチェックしてください: https://developer.Android.com/training/permissions/requesting.html

しかし、あなたが自分のアプリケーション全体を作成していて、どこでも変更したくないのであれば、ちょっとしたチートで十分です。

"Build.gradle"ファイルに行き、ターゲットのSdkのバージョンを22、21のように23未満に変更します。

2
Zohaib Hassan

CommonsWareの答えと一緒に、

SMS Message Limitを設定するためのセキュリティ設定(CM13でチェックしました)があります。これを "None"に設定すると、ランタイム中にSMS_SENDパーミッションを取得した後でも、OSはすべてのSMSに対してDialogをポップアップします。最良のことはこれを最大に設定することです。

最大数が十分でない場合は、根ざしたデバイスの最大レートを上げる方法があります。

1
Dumi Jay

そのため、メッセージを送受信するためのアプリを作成する必要がありましたが、許可が付与されているにもかかわらず、送信をクリックするたびに送信アクションがクラッシュしました。実行時アクセス許可を要求して許可しましたが、それでもプロセスにSMSを送信するための要求された許可がないというクラッシュが発生しました。付与された権限を以下から確認しました。

adb Shell dumpsys package <package-name>

私の許可申請の順序は

  1. RECEIVE_SMS
  2. SMSを送信

要求の順序を元に戻しましたが、問題なく動作します。これは完全に新しいアプリでテストされました(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および変更番号targetSdkVersion23未満に編集する
そして上記のコードはもう必要ありません。

NOTE
もちろんこれは事実ではなく、それは単なる教育的側面です

0
Amirhf

私は、外部記憶装置に書き込むための解決策もまた役立つことを願っています

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