Android 6.0 运行时权限封装之路
来源:互联网 发布:湖南工业大学网络认证 编辑:程序博客网 时间:2024/05/16 22:03
前言
时间如梭,总在不经意间流逝。经常会想,毕业到现在我都干了些什么,该有什么样的追求?
运行时权限
运行时权限是 Android 6.0 (SDK 23)新特性,更好的保护了用户的隐私。
如果你build.gradle
文件中声明targetSdkVersion
为23及以上
:
defaultConfig { applicationId "xxxx"//you applicationId minSdkVersion 14 targetSdkVersion 23//23及以上 versionCode 1 versionName "1.0" multiDexEnabled true }
用到的隐私权限就要进行申请;反之小于23
,默认授予AndroidManifest.xml
中的所有申请权限。
注意: 需要用到的权限必须在 AndroidManifest.xml 文件中申明。
权限的分类
Google
将权限分为两类,一类是Normal Permissions
,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、获取wifi连接状态、访问网络等;另一类是Dangerous Permission
,一般是涉及到用户隐私的,需要用户进行授权,比如获取位置信息、读取sdcard、访问通讯录等。最后会附上权限 Android 权限一栏。
危险权限Dangerous Permissions
如下图:
你也可以通过adb
命令进行权限查看:
adb shell pm list permissions
危险权限查看:
adb shell pm list permissions -d -g
dangerous permissions
是分组的,那么这么分组又会有什么影响呢?
如果你申请某个危险的权限,假设你的app
已经被用户授权了同一组的某个危险权限比如READ_CONTACTS
,那么WRITE_CONTACTS
和GET_ACCOUNTS
危险权限也同样被授权了,而不需要用户再次去申请。同样弹出的申请权限dialog
文本说明也是对整个权限组的说明,而不是单个权限。
权限处理流程
AndroidManifest.xml申明权限
在AndroidManifest.xml
文件下申明读的联系人权限:
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
检查SDK版本
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; }
如果targetSdkVersion
版本小于23,不需要进行权限的处理。
检查申明的权限是否已经被授权
if (checkSelfPermission(requestPermission) != PackageManager.PERMISSION_GRANTED) { //未被授权 } else { //已授权 }
如果未被授权,则需要申明授权处理。
申请授权
requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final int requestCode)
第一个参数是 activity
第二个参数是申请授权的权限组
第三个参数是请求码(如果不理解可以参考startActivityForResult()
方法)
权限回调处理
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSON_REQUESTCODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 申请权限已经授权 } else { // 申请权限未授权 } } }
参数grantResults
申请权限返回的状态信息。
这里还有一个方法需要说明一下:
public boolean shouldShowRequestPermissionRationale(String permission)
当用户第一次勾选了【禁止后不再询问】勾选框,并点击【禁止】按钮,第二次申请该权限返回true
的方法,一般给于用户提示缺少改权限。\n\n请点击\”设置\”-\”权限\”-打开所需权限进行处理。
打开设置代码:
private void startAppSettings() { Intent intent = new Intent( Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); }
在实际开发中可能会几个权限同时需要授权处理,如定位需要位置权限,访问 sdcard 。若单个申请则会显得很麻烦。所以我这里单独的提取了一个抽象类用于权限的处理,并把返回结果延迟到它的子类进行处理。对的,这里用了模板模式。具体看以下代码:
public abstract class CheckPermissionsActivity extends AppCompatActivity {
首先申明CheckPermissionsActivity
为抽象类。
public abstract void requestPermissionResult(boolean allowPermission);
申明抽象方法,并把allowPermission
是否授予权限设置为参数。
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSON_REQUESTCODE) { if (verifyPermissions(grantResults)) { requestPermissionResult(true); } else { requestPermissionResult(false); showMissingPermissionDialog(); } } }
最后我们在回调函数中传递参数给requestPermissionResult
抽象方法。下面我们来看看一个具体的例子。文章的最后已经附上了源码。
获取通讯录案例
package com.github.permissondemo;import android.Manifest;import android.app.LoaderManager;import android.content.CursorLoader;import android.content.Loader;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.provider.ContactsContract;import android.util.Log;public class MainActivity extends CheckPermissionsActivity implements LoaderManager.LoaderCallbacks<Cursor> { static final String[] PROJECTION = new String[]{ContactsContract.Data._ID, ContactsContract.Data.DISPLAY_NAME}; String mCurFilter; static String TAG; protected String[] needContactsPermissions = { Manifest.permission.READ_CONTACTS }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TAG = getClass().getName(); requestPermission(); } private void requestPermission() { if (!mayRequestPermission(needContactsPermissions)) { return; } initLoader(); } @Override public void requestPermissionResult(boolean allowPermission) { if (allowPermission) { initLoader(); } } private void initLoader() { getLoaderManager().initLoader(0, null, this); } @Override public Loader<Cursor> onCreateLoader(int i, Bundle bundle) { Uri baseUri; if (mCurFilter != null) { baseUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI , Uri.encode(mCurFilter)); } else { baseUri = ContactsContract.Contacts.CONTENT_URI; } String select = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND (" + ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1) AND (" + ContactsContract.Contacts.DISPLAY_NAME + " != '' ))"; CursorLoader loader = new CursorLoader(MainActivity.this, baseUri, PROJECTION, select, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { if (cursor == null) { return; } while (cursor.moveToNext()) { String[] names = cursor.getColumnNames(); for (String str : names) { String contacts = cursor.getString(cursor.getColumnIndex(str)); Log.e(TAG, "contacts=" + contacts); } } } @Override public void onLoaderReset(Loader<Cursor> loader) { }}
如上案例,运行时权限的处理非常方便,只需要两步:
- 第一步请求权限处理:
private void requestPermission() { if (!mayRequestPermission(needContactsPermissions)) { return; } initLoader();//读取联系人 }
- needContactsPermissions 参数表示:申请的权限字符数组。
如果你需要申请定位,调摄像头或其它的危险权限,请 initLoader();
替换成定位,开启摄像头的方法。
- 第二步请求权限的回调处理:
@Override public void requestPermissionResult(boolean allowPermission) { if (allowPermission) { initLoader();//读取联系人 } }
- allowPermission 参数表示:用户是否允许申请的权限,true 允许;false 拒绝。
如果你需要申请定位,调摄像头或其它的危险权限,请 initLoader();
替换成定位,开启摄像头的方法。
看下运行效果:
点击【始终允许】:
快速,简单,便捷,只需要你复制 CheckPermissionsActivity
类到你的项目中,需要申请权限的 Activity
继承于它。
可能你会说为啥不使用:
插件生成权限处理呢?
真心觉得不好用。
用哪种方式,取决于自己。
最后祝愿大家,每天适当休息下,不要一直敲代码,起来动一动。感觉自己就是每天坐太久,身体不如以前好了。
若有什么疑问请留言。源码地址
Android 权限一栏
- Android 6.0 运行时权限封装之路
- Android 6.0 运行时权限封装框架
- Android 6.0 运行时权限简洁封装
- Android 6.0 运行时权限简洁封装
- Android 6.0 运行时权限封装
- Android 6.0运行时权限的改变及封装
- Android 6.0运行时权限 baseactivity简单封装
- Android 6.0 运行时权限 fragment的简单封装 basefragment
- Android 6.0运行时权限处理与封装(一)
- Android M系统运行时权限封装
- android——运行时权限封装
- Android 6.0改动之运行时权限
- Android之6.0 权限申请封装
- Android6.0运行时权限(二)之封装
- Android 运行时权限高阶--封装(听课笔记)
- 对Android运行时权限的简单封装
- android 6.0以后的运行时权限申请及封装 相关记录
- Android 6.0运行时权限
- DataGuard 日常维护
- 关于在eclipes中配置tomcat不能显示主页面问题
- android 开发环境搭建
- 边缘检测算法——图像处理
- rw_程序是怎样跑起来的 1-6章
- Android 6.0 运行时权限封装之路
- 欢迎使用CSDN-markdown编辑器
- Java中加载配置文件的方法总结
- C#调用dll提示"试图加载格式不正确的程序"解决方法(转)
- python操作mongo
- bitmap拼接、截图
- mycat 调优
- weblogic部署
- 几种2.4G无线数传模块电路