RuntTimePermissionTestActivity.java html
classpath 'com.android.tools.build:gradle:3.0.0'
compile 'com.android.support:appcompat-v7:26.+'java
ERROR: java.lang.SecurityException: Sending SMS message: uid 10078 does not have android.permission.SEND_SMS.
查android 官網發現,When run on Android 6.0 (API 23),or targetSdkVersion Android 6.0 (API 23),danger permission須要動態申請權限。android
Android 6.0 (API 23) 開始,引入了normal permissions(普通權限) 和dangerous permissions(危險權限) 的概念。git
On all versions of Android, your app needs to declare both the normal and the dangerous permissions it needs in its app manifest, as described in Declaring Permissions. However, the effect of that declaration is different depending on the system version and your app's target SDK level:github
● If the device is running Android 5.1 (API level 22)or lower, or your app's target SDKis 22 or lower(targetSdkVersion <=22) : If you list a dangerous permission in your manifest, the user has to grant the permission when they install the app; if they do not grant the permission, the system does not install the app at all.
● If the device is running Android 6.0 (API level 23) or higher, and your app's target SDK is 23 or higher (targetSdkVersion >=23): The app has to list the permissions in the manifest, and it must request each dangerous permission it needs while the app is running. The user can grant or deny each permission, and the app can continue to run with limited capabilities even if the user denies a permission request.
Note: Beginning with Android 6.0 (API level 23), users can revoke permissions from any app at any time, even if the app targets a lower API level. You should test your app to verify that it behaves properly when it's missing a needed permission, regardless of what API level your app targets.Note: Your app still needs to explicitly request every permission it needs, even if the user has already granted another permission in the same group. In addition, the grouping of permissions into groups may change in future Android releases. Your code should not rely on the assumption that particular permissions are or are not in the same group.安全
https://developer.android.google.cn/training/permissions/requesting.htmlapp
https://developer.android.com/guide/topics/permissions/requesting.html#normal-dangerousless
When device is running Android 6.0 (API level 23) or higher, and your app's target SDK is 23 or higher (targetSdkVersion >=23)異步
RuntTimePermissionTestActivity.javaide
RuntTimePermissionTestActivity.java 以SEND_SMS(發送短信)、RECEIVE_SMS(使用SMSReceiver接收短信)、permission_group.SMS 爲例子。
SMS是Short Messaging Service(短消息服務)的縮寫,是一種使用移動設備能夠發送和接收文本信息的技術。
PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(getContext(), permission)
true,已經受權,直接執行doSendMessage。
false,沒有受權,執行下一步檢查是否須要顯示請求權限緣由。
PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(getContext(), Manifest.permission.SEND_SMS)
PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(getContext(), Manifest.permission.SEND_SMS) && PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECEIVE_SMS)
PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(getContext(), Manifest.permission_group.SMS)
true,須要顯示請求權限緣由,顯示一個dialog/Snarkbar,容許用戶作選擇。
false,不須要顯示請求權限緣由,直接執行requestPermissions。
ActivityCompat.shouldShowRequestPermissionRationale(getContext(), Manifest.permission.SEND_SMS)
ActivityCompat.shouldShowRequestPermissionRationale(getContext(), Manifest.permission.SEND_SMS) && ActivityCompat.shouldShowRequestPermissionRationale(getContext(), Manifest.permission.RECEIVE_SMS)
ActivityCompat.shouldShowRequestPermissionRationale(getContext(), Manifest.permission_group.SMS)
ActivityCompat.requestPermissions 調用後,在onRequestPermissionsResult()中根據requestCode判斷是否grandted,並作對應處理。
public static void requestPermissions(final @NonNull Activity activity,final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode)
說明:
(1) permissions:是一個String[],能夠放一個或多個permission。
(2) requestCode:在onRequestPermissionsResult()中處理。每次請求request permissions時requestCode設置要不一樣。
ActivityCompat.requestPermissions(getContext(), new String[]{Manifest.permission.SEND_SMS}, REQUEST_CODE_4_REQUEST_PERMISSIONS_4_SEND_MESSAGE);
ActivityCompat.requestPermissions(getContext(), new String[]{Manifest.permission.SEND_SMS,Manifest.permission.RECEIVE_SMS}, REQUEST_CODE_4_REQUEST_PERMISSIONS_4_SEND_RECEIVE_MESSAGE);
ActivityCompat.requestPermissions(getContext(), new String[]{Manifest.permission_group.SMS}, REQUEST_CODE_4_REQUEST_PERMISSIONS_GROUP_4_SMS)
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Log.d(TAG, "onRequestPermissionsResult: requestCode=" + requestCode); switch (requestCode) { case REQUEST_CODE_4_REQUEST_PERMISSIONS_4_SEND_MESSAGE: { onRequestPermissionsResult4SendMessage(requestCode, permissions, grantResults); break; } default: // other 'case' lines to check for other permissions this app might request super.onRequestPermissionsResult(requestCode, permissions, grantResults); break; } } private void onRequestPermissionsResult4SendMessage(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (REQUEST_CODE_4_REQUEST_PERMISSIONS_4_SEND_MESSAGE != requestCode) { Log.e(TAG, "onRequestPermissionsResult4SendMessage: requestCode is wrong"); return; } // Check if the only required permission has been granted // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 受權了,執行task,此處是發送短信操做。 doSendMessage(); // Send message permission has been granted, Message can be sent. Log.i(TAG, "Send message permission has now been granted. Can send message."); // 受權了,給出對應提示信息。 showPermissionAvailable4SendMessage(); } else { // permission denied, boo! Disable the functionality that depends on this permission. Log.i(TAG, "Send message permission was NOT granted."); // 沒有被受權,給出對應提示信息。 showPermissionsNotGranted(); } }
6 總結
例如,申請Manifest.permission.SEND_SMS權限時,用戶已經受權了Manifest.permission.SEND_SMS權限,系統則會自動受權group SMS中的全部權限,再也不詢問用戶;
checkSelfPermission和requestPermissions從API 23才加入,低於23版本,須要在運行時判斷。
使用Support Library v4中提供的方法,能夠避免判斷。
ContextCompat.checkSelfPermission ActivityCompat.requestPermissions ActivityCompat.shouldShowRequestPermissionRationale
例如:使用ContextCompat.checkSelfPermission , 而不是Activity.checkSelfPermission()。google 官網推薦這種方式。
-https://developer.android.com/guide/topics/permissions/requesting.html#normal-dangerous
PS: 中國訪問, 把com -> google.cn 就能夠打開了。
EasyPermissions
rxpermissions
android send sms
snackbars:
Android Support v4,v7,v13的區別以及 v4,v7包衝突問題
謝謝瀏覽
歡迎你們交流,留言、指點。
文中有誤,歡迎你們指出來。我會更正過來。