本帖最后由 xiaoqing 于 2015-12-7 09:52 编辑
google刚刚推出的6.0新特性,新特性中增加了全新的权限系统,通过深圳的问答网,我们一起来看看深圳师生对这个问题的探讨。
学生问题: 打电话的操作,为什么运行在6.0上就会崩溃呢? 老师问题:
前言:当targetSdkVersion 和系统同时大于等于api23,即6.0(M)时,像我们之前的所请求的权限操作,即会无效。依然会报SecurityException。这是由于android6.0采用全新的权限系统。根据谷歌官网介绍:file:///C:/Users/yuqiqi/Documents/My%20Knowledge/temp/1667869a-3f85-43a9-9ea1-a244b031472b_4_files/1d6ef9a9-6f99-440b-a639-e6f83633b717.png
在android6.0之后,app安装时不再回向用户请求权限,而是在app运行时,需要用到某个权限的时候,才向用户请求。如果不请求,即使你在清单文件中注册了权限,程序也依然会崩溃!(已经上线的app不用担心,由于那些app的targetSdkVersion小于23,系统默认和以前一样处理。)
权限分组:在新的权限系统中,权限被分组为:
| | android.permission-group.CALENDAR | - android.permission.READ_CALENDAR
- android.permission.WRITE_CALENDAR
| android.permission-group.CAMERA | - android.permission.CAMERA
| android.permission-group.CONTACTS | - android.permission.READ_CONTACTS
- android.permission.WRITE_CONTACTS
- android.permission.GET_ACCOUNTS
| android.permission-group.LOCATION | - android.permission.ACCESS_FINE_LOCATION
- android.permission.ACCESS_COARSE_LOCATION
| android.permission-group.MICROPHONE | - android.permission.RECORD_AUDIO
| android.permission-group.PHONE | - android.permission.READ_PHONE_STATE
- android.permission.CALL_PHONE
- android.permission.READ_CALL_LOG
- android.permission.WRITE_CALL_LOG
- com.android.voicemail.permission.ADD_VOICEMAIL
- android.permission.USE_SIP
- android.permission.PROCESS_OUTGOING_CALLS
| android.permission-group.SENSORS | - android.permission.BODY_SENSORS
| android.permission-group.SMS | - android.permission.SEND_SMS
- android.permission.RECEIVE_SMS
- android.permission.READ_SMS
- android.permission.RECEIVE_WAP_PUSH
- android.permission.RECEIVE_MMS
- android.permission.READ_CELL_BROADCASTS
| android.permission-group.STORAGE | - android.permission.READ_EXTERNAL_STORAGE
- android.permission.WRITE_EXTERNAL_STORAGE
|
这样做的意义在于:当组内的一项权限被允许之后,组内其他权限也即被默认允许。
普通权限普通权限:app在安装时,如果以下权限在清单文件中有注册,则系统会默认授予。在app运行时也不需要每次都检查权限,用户也不可以取消这些权限。
- android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
- android.permission.ACCESS_NETWORK_STATE
- android.permission.ACCESS_NOTIFICATION_POLICY
- android.permission.ACCESS_WIFI_STATE
- android.permission.ACCESS_WIMAX_STATE
- android.permission.BLUETOOTH
- android.permission.BLUETOOTH_ADMIN
- android.permission.BROADCAST_STICKY
- android.permission.CHANGE_NETWORK_STATE
- android.permission.CHANGE_WIFI_MULTICAST_STATE
- android.permission.CHANGE_WIFI_STATE
- android.permission.CHANGE_WIMAX_STATE
- android.permission.DISABLE_KEYGUARD
- android.permission.EXPAND_STATUS_BAR
- android.permission.FLASHLIGHT
- android.permission.GET_PACKAGE_SIZE
- android.permission.INTERNET
- android.permission.KILL_BACKGROUND_PROCESSES
- android.permission.MODIFY_AUDIO_SETTINGS
- android.permission.NFC
- android.permission.READ_SYNC_SETTINGS
- android.permission.READ_SYNC_STATS
- android.permission.RECEIVE_BOOT_COMPLETED
- android.permission.REORDER_TASKS
- android.permission.REQUEST_INSTALL_PACKAGES
- android.permission.SET_TIME_ZONE
- android.permission.SET_WALLPAPER
- android.permission.SET_WALLPAPER_HINTS
- android.permission.SUBSCRIBED_FEEDS_READ
- android.permission.TRANSMIT_IR
- android.permission.USE_FINGERPRINT
- android.permission.VIBRATE
- android.permission.WAKE_LOCK
- android.permission.WRITE_SYNC_SETTINGS
- com.android.alarm.permission.SET_ALARM
- com.android.launcher.permission.INSTALL_SHORTCUT
- com.android.launcher.permission.UNINSTALL_SHORTCUT
现在我们知道了,程序员们需要警惕的就是权限组中的权限啦!!!
比如向SDK中写入数据的权限,我们需要如何去手动请求呢?通过查询官方文档https://developer.android.com/tr ... ons/requesting.html,可知:1.首先我们需要检查系统是否已经授予了该app此项权限,通过调用ContextCompat.checkSelfPermission(Context context,String permission)方法可以实现。checkSelfPermission()方法会返回两个值:
PERMISSION_GRANTED授予 PERMISSION_DENIED拒绝 2.如果checkSelfPermission()返回值为 PERMISSION_DENIED,那么这时候,我们需要调用ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission)方法,来检测是否需要展示 请求权限的弹框。file:///C:/Users/yuqiqi/Documents/My%20Knowledge/temp/1667869a-3f85-43a9-9ea1-a244b031472b_4_files/e97a15a3-135a-4ce2-b211-e4cf5bbd853a.png
官方已经说的很清楚了:- MainActivity AppCompatActivity {
- = = (Bundle savedInstanceState) {
- .onCreate(savedInstanceState)setContentView(R.layout.)}
- (View view) {
- askPermisssion()() {
- Intent intent = Intent()intent.setAction(Intent.)intent.setData(Uri.())startActivity(intent)} {
- Toast.(MainActivity.Toast.).show()}
- }
- () {
- permissionCheck = ContextCompat.(MainActivity.Manifest.permission.)(permissionCheck == PackageManager.) {
- (ActivityCompat.(MainActivity.Manifest.permission.)) {
- Log.()ActivityCompat.(MainActivity.String[]{Manifest.permission.})} {
- Log.()ActivityCompat.(MainActivity.String[]{Manifest.permission.})}
- }
- }
- (requestCodeString[] permissions[] grantResults) {
- (requestCode) {
- : {
- (grantResults.> && grantResults[] == PackageManager.) {
- = } {
- = }
- }
- }
- }
- (View view) {
- Toast.(Toast.).show()}
- }
复制代码
关于第三方开源框架,快速实现运行时权限: 第一步: 根据github中的redme添加gradle file:///C:/Users/yuqiqi/Documents/My%20Knowledge/temp/26d16685-7715-4386-9cb9-7972a278d923_4_files/ad13b730-f4fb-44be-a1cb-f1446ecae986.png
第二步: 现在可以使用两个必须的注解了 file:///C:/Users/yuqiqi/Documents/My%20Knowledge/temp/26d16685-7715-4386-9cb9-7972a278d923_4_files/204c4f59-b44b-40fe-b866-1f50942f59f3.png
第三步: 运行后发现依然报错,通过下载zip包,找到xxxSimple,查看他的代码,发现还有一个关键方法MainActivityPermissionsDispatcher,但是还不能调用,我们通过看这个Simple项目的两个build.gradle发现,还需要添加两个东西 file:///C:/Users/yuqiqi/Documents/My%20Knowledge/temp/26d16685-7715-4386-9cb9-7972a278d923_4_files/3c4f2c78-f781-4b6a-9057-7915de8a87cb.png
- @RuntimePermissionspublic class MainActivity extends AppCompatActivity { private Button mBt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBt = (Button) findViewById(R.id.bt); } public void onClick(View view){ MainActivityPermissionsDispatcher.callPhoneWithCheck(MainActivity.this); } @NeedsPermission(Manifest.permission.CALL_PHONE) void callPhone(){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); intent.setData(Uri.parse("tel://110")); startActivity(intent); } }
- buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.3.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7' classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0' classpath 'com.novoda:bintray-release:0.3.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }} allprojects { repositories { jcenter() }} task clean(type: Delete) { delete rootProject.buildDir}
- apply plugin: 'com.android.application'
- apply plugin: 'android-apt'
-
- android {
- compileSdkVersion 23
- buildToolsVersion "23.0.2"
-
- defaultConfig {
- applicationId "com.itheima.call3"
- minSdkVersion 21
- targetSdkVersion 23
- versionCode 1
- versionName "1.0"
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
- }
-
- dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:23.1.0'
- compile 'com.android.support:design:23.1.0'
-
- compile 'com.github.hotchemi:permissionsdispatcher:1.2.1@aar'
- apt 'com.github.hotchemi:permissionsdispatcher-processor:1.2.1'
- }
复制代码
|