Quyền Android không hoạt động ngay cả khi tôi đã khai báo


167

Tôi đang cố gắng viết mã để gửi SMS từ một ứng dụng Android, nhưng khi tôi cố gắng gửi SMS, nó sẽ gửi lại cho tôi lỗi:

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)

Tôi đã kiểm tra nhưng tôi có quyền trong tệp kê khai, như sau:

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

Tôi đã tìm kiếm trên internet nhưng tất cả các lỗi là về <uses-permission/>cú pháp, bạn có thể giúp tôi được không?


Phiên bản Android nào bạn đang thử nghiệm?
CommonsWare

Tôi đang thử nghiệm trên Android 6.0
Nathan Loud ه

1
chắc chắn nó sẽ hoạt động trên một phiên bản dưới đây của Android. Có một triết lý mới về quyền trong Android 6.0
Fakher

Có một cú pháp đặc biệt cho Android 6? Làm thế nào tôi có thể chắc chắn rằng nó hoạt động trên phiên bản dưới đây?
Nathan Loud ه

trước đây của tôi targetsdkversionđã được 23cập nhật 27sau khi READ_SMSquyền cập nhật ứng dụng không hoạt động đã được kích hoạt. xin vui lòng giúp đỡ
Sagar

Câu trả lời:


237

(sau đây được trích từ một bài đăng trên blog của tôi về điều này )

Lý do lớn cho việc không nhận được sự cho phép của bạn hiện nay là vì dự án của bạn có targetSdkVersiontừ 23 trở lên và sự cho phép mà bạn đang yêu cầu là "nguy hiểm". Trong Android 6.0, điều này bao gồm:

  • 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

Đối với các quyền này, không chỉ targetSdkVersionứng dụng 23+ của bạn cần có <uses-permission>(các) yếu tố, mà bạn còn phải yêu cầu các quyền đó khi chạy từ người dùng trên thiết bị Android 6.0+, sử dụng các phương thức như checkSelfPermission()requestPermissions().

Như một cách giải quyết tạm thời, giảm xuống targetSdkVersiondưới 23 của bạn .

Tuy nhiên, cuối cùng, bạn sẽ có một số lý do để muốn bạn targetSdkVersiontừ 23 trở lên. Vào thời điểm đó, bạn sẽ cần điều chỉnh ứng dụng của mình để sử dụng hệ thống cấp phép thời gian chạy mới. Tài liệu Android có một trang dành riêng cho chủ đề này .


2
Cảm ơn bạn rất nhiều, tôi đã sử dụng các phương thức requestPermissions () và tôi đã làm việc rất tốt
Nathan Loud ه

Được rồi, tôi đã thử điều này trước đây nhưng không thể nhận được các phương thức ContextCompat.checkSelfPermission và ActivityCompat.requestPermissions, chúng cho tôi một lỗi 'không tìm thấy' trên các tên phương thức. Tôi đoán nó sẽ làm với một thư viện bị thiếu, nó dường như nằm trong gói v4 nhưng sự phụ thuộc lớp duy nhất của tôi là compile 'com.android.support:appcompat-v7:22.2.1'. Tôi có nên thay đổi điều này thành v4?
Ozzy

2
@Ozzy: Bạn cần có một thế hệ v23 của các thư viện hỗ trợ ( 23.x.y, đối với các giá trị hiện tại của x và y), thay vì v22 mà bạn hiện đang sử dụng.
CommonsWare

Cảm ơn, vì tương lai tôi đoán. Hiện tại tôi đã thay đổi mục tiêu trở lại thành v22 và mặc dù bộ lưu trữ thẻ SD được đặt thành 200MB trên trình giả lập, nó đã cho tôi thẻ SD không được gắn lỗi. Nhưng sau đó tôi đã kết nối điện thoại của mình ở chế độ nhà phát triển và mọi thứ đều hoạt động. Vì một số lý do, bộ nhớ thẻ SD hoạt động trên trình giả lập chạy v23 nhưng không phải v22.
Ozzy

3
@NathanLoud camera Bạn có phiền khi chia sẻ mã của mình thực hiện việc này không? Tôi đang ở trong cùng một chiếc thuyền và đang vật lộn để đưa nó vào hoạt động của mình.
dschuett

29

Trên cấp độ API 23, bạn sẽ được cung cấp theo chương trình một cách thực tế như:

    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

yêu cầu cấp phép thực tế (sau 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
}

"Nếu ứng dụng có quyền, phương thức checkSelfPermission () trả về PERMISSION_GRANTED và ứng dụng có thể tiến hành thao tác.

Nếu ứng dụng không có quyền, phương thức sẽ trả về PERMISSION_DENIED và ứng dụng phải yêu cầu người dùng cho phép rõ ràng. Bạn cần nhắc người dùng về quyền đó, như được hiển thị trong đoạn mã trên. Gọi requestPermissions () sẽ hiển thị hộp thoại Android tiêu chuẩn mà bạn không thể tùy chỉnh. "


Chúng ta sẽ đặt dòng này ở đâu? ActivityCompat.requestPermissions (này, Chuỗi mới [] {Manifest-01.SEND_SMS}, 1); và 1 đề cập đến cái gì?
LizG

6

Nếu bạn đang sử dụng sdk 23 trở lên thì bạn phải kiểm tra quyền thời gian chạy.


6

khi bạn khai báo permissontrong Manifestvà nó không hoạt động có nghĩa là bạn đang thực hiện công tác trong MarshMallowMarshMallowbạn đã thiết lập Permisson tại RunTime.

thích cách này

ActivityCompat.requestPermissions();

6

Vui lòng đi qua liên kết dưới đây, https://developer.android.com/guide/topics/permissions/overview.html

Một số mẫu cũng có sẵn ở đó để bắt đầu với các quyền.

Để làm cho Android an toàn hơn bây giờ, các nhà phát triển phải đề cập đến quyền trong bảng kê khai cũng như họ phải yêu cầu người dùng cũng như trong thời gian chạy để hoàn thành công việc. Chúng được phân loại trong phần cho phép nguy hiểm được đề cập dưới đây

LỊCH

READ_CALENDAR

WRITE_CALENDAR

MÁY ẢNH

CAMERA

LIÊN LẠC

READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS

VỊ TRÍ

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION

CÁI MIC CỜ RÔ

RECORD_AUDIO

ĐIỆN THOẠI

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

CẢM BIẾN

BODY_SENSORS

tin nhắn

SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS

LƯU TRỮ

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

2

Tôi đã thêm nó vào MainActivity, giải quyết vấn đề của tôi

       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

Nếu bạn đang sử dụng phiên bản Android "23" hoặc "23+", thì ứng dụng sẽ hiển thị cho bạn các lỗi khi bạn đang cố truy cập bất cứ thứ gì cần có sự cho phép của người dùng. Bạn phải yêu cầu quyền vào thời gian chạy ngay cả khi bạn đã khai báo các quyền đó trong tệp kê khai Android.

Kiểm tra điều này: https://developer.android.com/training/permissions/requesting.html

Nhưng nếu bạn đã tạo toàn bộ ứng dụng của mình và không muốn thay đổi ở mọi nơi thì một chút gian lận sẽ là đủ.

Chuyển đến tệp "Build.gradle" và thay đổi phiên bản Sdk đích thành dưới 23, như 22, 21.


1

Cùng với câu trả lời của CommonsWare,

Có Cài đặt bảo mật (tôi đã kiểm tra trên CM13) để đặt Giới hạn tin nhắn SMS. Nếu bạn đặt thành "Không", HĐH sẽ bật Hộp thoại cho mọi SMS, ngay cả sau khi có được quyền SMS_SEND trong thời gian chạy. Điều tốt nhất là đặt điều này đến tối đa.

Nếu mức tối đa là không đủ, có nhiều cách để tăng tốc độ tối đa trên thiết bị đã root.


0

Bạn có thể sử dụng mã này để truy cập tin nhắn của mình

Mở Hộp thoại bằng mã bên dưới:

ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    1);

Nhận kết quả Hoạt động như sau:

@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
    }
}

hoặc chỉnh sửa tập tin build.gradlevà số lượng targetSdkVersionít hơn 23
Và không còn cần mã ở trên

LƯU Ý
Tất nhiên đây không phải là trường hợp và nó chỉ là một khía cạnh giáo dục


0

Vì vậy, tôi đã phải tạo một ứng dụng để gửi và nhận tin nhắn nhưng hành động gửi bị sập bất cứ khi nào tôi nhấp vào gửi mặc dù quyền đã được cấp. Tôi đã yêu cầu quyền thời gian chạy và cho phép họ, nhưng tôi vẫn gặp phải sự cố rằng quy trình không có quyền yêu cầu gửi SMS. Tôi đã kiểm tra các quyền được cấp từ:

adb shell dumpsys package <package-name>

Thứ tự yêu cầu cấp phép của tôi là

  1. RECEIVE_SMS
  2. GỬI TIN NHẮN

Tôi hoàn nguyên thứ tự yêu cầu và nó hoạt động tốt. Điều này đã được thử nghiệm với một ứng dụng hoàn toàn mới (gỡ cài đặt-> cài đặt -> kiểm tra). Câu trả lời có vẻ kỳ lạ nhưng chỉ cần cho nó một shot.

(Nếu nó hoạt động theo cách hiển thị theo một thứ tự nhất định, thì Android có thể có lỗi !!)


0

Tôi hy vọng giải pháp ghi vào bộ nhớ ngoài cũng sẽ hữu ích

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

Danh sách tất cả các quyền có thể được tìm thấy với Giải thích tại

Manifest-01

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.