在各类流氓肆虐的安卓生态环境中,6.0之前是只要一安装app就能获取到所有需要的权限了。
6.0之后,谷歌将权限分成了两种,一种普通权限,跟以前一样,AndroidManifest.xml
中声明了就可以用了
另一种是危险权限,在你的项目compileSdkVersion和targetSdkVersion均>=23的时候,这一类权限不仅需要在清单中声明,而且要在使用的时候向用户申请才行。如果还像6.0之前那样只是声明一下的话,分分钟崩给你看T.T~
1 2 3 4 5 6 java.lang.SecurityException getDeviceId: Neither user 10204 nor current process has android.permission.READ_PHONE_STATE... } 1 java.lang.RuntimeException:Unable to start activity ComponentInfo{com.aidebar.d8alarmclock/com.aidebar.d8alarmclock.activity.MainActivity}: java.lang.SecurityException: getDeviceId: Neither user 10204 nor current process has android.permission.READ_PHONE_STATE.2 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254 )3 ......
我自己测试的时候,MIUI不会崩。。清单中配置了就直接获取了权限,导致我没有第一时间发现这个bug···
权限组
权限
CALENDAR
READ_CALENDAR
WRITE_CALENDAR
CAMERA
CAMERA
CONTACTS
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE
RECORD_AUDIO
PHONE
READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS
BODY_SENSORS
SMS
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
看完成效果吧
布局就不写了,点击按钮获取权限,让用户授权,用户点击允许 或拒绝 我们都能获取到。
但这样就有个问题,当用户点击不在询问 的时候,就什么也不干了。。这样显然对app的正常运行是有影响的,所以我选择如果是这种情况,给他个SnackBar引导用户去设置里手动打开权限。
下面上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 package com.aidebar.demo;import android.Manifest;import android.app.Activity;import android.content.Intent;import android.content.SharedPreferences;import android.content.pm.PackageManager;import android.net.Uri;import android.os.Bundle;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.design.widget.Snackbar;import android.support.v4.app.ActivityCompat;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity implements View .OnClickListener { private Activity mActivity; public static final int REQUEST_CODE_PERMISSION = 1 ; public static final int REQUEST_CODE_PERMISSION_SETTING = 2 ; private Button btn; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); mActivity = this ; btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(this ); } private void requestPermission (String permission) { int hasPermission = ActivityCompat.checkSelfPermission(this , permission); if (hasPermission == PackageManager.PERMISSION_GRANTED) { ToastUtils.show(this ,"This permission is granted" ); }else { boolean shouldShowUI = ActivityCompat.shouldShowRequestPermissionRationale(this , permission); SharedPreferences sp = getSharedPreferences("LOCAL_DATAS" , MODE_PRIVATE); boolean is_first_get_permission = sp.getBoolean("is_first_request_permission" , true ); if (!shouldShowUI && !is_first_get_permission) { showSnackBar(); }else { ActivityCompat.requestPermissions(this , new String[]{permission}, REQUEST_CODE_PERMISSION); sp.edit().putBoolean("is_first_request_permission" ,false ).apply(); } } } @Override public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, @NonNull int [] grantResults) { switch (requestCode) { case REQUEST_CODE_PERMISSION: if (grantResults[0 ] == PackageManager.PERMISSION_GRANTED) { ToastUtils.show(this ,"you've granted the permission" ); }else { ToastUtils.show(this ,"you've denied the permission" ); } break ; } super .onRequestPermissionsResult(requestCode, permissions, grantResults); } private void showSnackBar () { Snackbar.make(btn,"need permission!" ,Snackbar.LENGTH_LONG) .setAction("go to setting" , new View.OnClickListener() { @Override public void onClick (View v) { Uri uri = Uri.fromParts("package" , mActivity.getPackageName(), null ); Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,uri); mActivity.startActivityForResult(intent, REQUEST_CODE_PERMISSION_SETTING); } }) .show(); } @Override public void onClick (View v) { switch (v.getId()) { case R.id.btn: requestPermission(Manifest.permission.READ_PHONE_STATE); break ; } } }
注释写的很详细啦,不多赘述,放在这以后要用回来拿~
有人问SnackBar为什么不是出现在屏幕底部的,请移步
EOF