带你封装自己的『权限管理』框架
2020/4/26 23:03:47
本文主要是介绍带你封装自己的『权限管理』框架,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍:
我的 Github 博客
本篇文章需要已经具备的知识:
Git
与Github
的基本使用Kotlin
语法基础Android
开发基础
学习清单:
- 如何封装自己的权限框架
- 将开源库发布到
JitPack
仓库的一整套流程
一.为什么要封装这套框架
我们在日常开发中,经常需要用到申请运行时权限的知识,于是,经常就写了下面的一大串代码
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ... //申请 CALL_PHONE 权限 if (ContextCompat.checkSelfPermission( this, Manifest.permission.CALL_PHONE ) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CALL_PHONE), 1) } else { call() } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { 1 -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { call() } else { Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show() } } } } 复制代码
麻鸭,头疼,这么多代码,不仅写着难受,看着更是头疼
![头疼](/upload/202004/26/202004262303463384.png)
这时候,如果这个世界简单点,纯粹点,就好了
XPermission.request( this, Manifest.permission.CALL_PHONE ) { allGranted, deniedList -> if (allGranted) { call() } else { Toast.makeText(this, "You denied $deniedList", Toast.LENGTH_SHORT).show() } } 复制代码
是不是感觉世界又友好了很多呢?这段代码比之前的代码量少了很多不说,逻辑更是清晰了很多鸭!
![滚来了](/upload/202004/26/202004262303463609.png)
很显然,上面用到了自己封装的框架,有可能你会一脸不屑:『这算啥?Github
上一堆权限申请框架,他们写的这个简洁又漂亮,功能又多又全,超帅的』
我想说:『是的,你说的对,虽然 Github
上有这么多,跑得又快又棒的轮子,但是,别人做的菜总归没有自己的香鸭!我们可以通过自己封装一个简单的权限申请框架开始,学习发布开源库到 Jitpack
/ Jcenter
的一整套流程,从而激发自己的学习兴趣,以后自己也多多造轮子(xia zhe teng)!成为 Android
界的轮子哥』
先为大佬送上笔者已经封装好的轮子:github.com/LoveLifeEve…
![XPermission](/upload/202004/26/202004262303465552.png)
![上车](/upload/202004/26/202004262303465806.png)
二.入坑之路
2.1 创建 Android
项目
新建一个空的 Android
项目
![创建项目](/upload/202004/26/202004262303466011.png)
2.2 创建 Github
项目
![建库](/upload/202004/26/202004262303466344.png)
然后,把该项目
clone
到一个上面已经创建的Android
项目的位置将克隆下来的所有文件全部复制到上一层目录(注意:复制的时候不要忘记复制
.git
文件)将克隆的
XPermission
目录删除执行一系列的
git add .
git commit -m "First commit"
git push origin master
操作
2.3 实现 XPermission
- 对着最顶层的
XPermission
,新建一个module
,选择Android Library
![新建 module](/upload/202004/26/202004262303466636.png)
看到 library
就行,如下
![新建 library 成功](/upload/202004/26/202004262303466900.png)
然后,我们思考下,运行时权限的实现思路,有以下三种:
- 将运行时权限的操作封装到
BaseActivity
中 - 提供一个透明的
Activity
来处理 - 提供一个隐藏的
Fragment
来处理
本文,将根据最后一个思路进行实现
2.3.1 创建 InvisibleFragment
//给 (Boolean, List<String>) -> Unit 指定一个别名 typealias PermissionCallback = (Boolean, List<String>) -> Unit class InvisibleFragment : Fragment() { //定义一个 callback 作为运行时权限申请结果的回调通知方式 private var callback: PermissionCallback? = null //定义申请权限的方法,vararg 表示可变长度的 permissions 参数列表 fun requestNow(cb: PermissionCallback, vararg permission: String) { callback = cb requestPermissions(permission, 1) } /** * 请求返回结果 * @param requestCode Int 请求码 * @param permissions Array<String> 权限 * @param grantResults IntArray 请求结果 */ override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { if (requestCode == 1) { // deniedList 用来记录被用户拒绝的权限 val deniedList = ArrayList<String>() for ((index, result) in grantResults.withIndex()) { if (result != PackageManager.PERMISSION_GRANTED) { deniedList.add(permissions[index]) } } // allGranted 用来标识是否所有申请的权限都已经授权 val allGranted = deniedList.isEmpty() //对申请权限的结果进行回调 callback?.let { it(allGranted, deniedList) } } } } 复制代码
- 首先,我们定义一个
callback
作为运行时权限申请结果的回调通知方式 - 然后,定义一个
requestNow
方法 - 最后重写
onRequestPermissionsResult
方法
![第一大步](/upload/202004/26/202004262303467340.png)
2.3.2 创建 XPermission
object XPermission { private const val TAG = "InvisibleFragment" fun request( activity: FragmentActivity, vararg permission: String, callback: PermissionCallback ) { val fragmentManager = activity.supportFragmentManager val existedFragment = fragmentManager.findFragmentByTag(TAG) val fragment = if (existedFragment != null) { existedFragment as InvisibleFragment } else { val invisibleFragment = InvisibleFragment() fragmentManager.beginTransaction().add(invisibleFragment, TAG).commitNow() invisibleFragment } //这里在 permission 前面加个星号的意思是:将数组转化为可变长度参数传递过去 fragment.requestNow(callback, *permission) } } 复制代码
相信代码大家都看得懂,所以笔者就不写很多注释了(其实是因为懒..)
2.4 测试
在
app\build.gradle
中引入library
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' //添加这行就行 implementation project(':library') } 复制代码
然后进行你喜欢的权限申请
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) makeCallBtn.setOnClickListener { XPermission.request(this, Manifest.permission.CALL_PHONE) { allGranted, deniedList -> if (allGranted) { call() } else { Toast.makeText(this, "You Denied $deniedList", Toast.LENGTH_SHORT).show() } } } } private fun call() { val intent = Intent(Intent.ACTION_CALL) intent.data = Uri.parse("tel:10086") startActivity(intent) } } 复制代码
如果可以的话,恭喜你,你已经成功一大步了
2.5 发布到 JitPack
2.5.1 JitPack
简介
JitPack 是一个网站,它允许你把 git
托管的 java
或 android
项目(貌似目前仅支持github
和码云),轻松发布到 jitpack
的 maven
仓库上,它所有内容都通过内容分发网络(CDN
)使用加密 https
连接获取
2.5.2 为什么用 JitPack
优点:打包比较简单,省时间,背靠 Github
这座大山
缺点:每次导入库的时候,都要先在根的 build.gradle
文件中添加 maven
![添加 maven](/upload/202004/26/202004262303467476.png)
2.5.3 步骤
- 在根的
build.gradle
中添加maven
插件
点击查看最新版本
buildscript { ext.kotlin_version = '1.3.71' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.5.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" //添加 maven 插件 classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } 复制代码
- 在
library
目录的build.gradle
下apply
插件和添加group
apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' //添加下面两行 apply plugin: 'com.github.dcendents.android-maven' //这里 LoveLifeEveryday 改为你的 github 账号名,我的是:LoveLifeEveryday group='com.github.LoveLifeEveryday' android { ... } 复制代码
- 同步一下
![同步](/upload/202004/26/202004262303467672.png)
- 在命令行中输入
gradlew install
,从而构建你的library
到你的本地maven
仓库
![gradlew install](/upload/202004/26/202004262303467877.png)
等待
BUILD SUCCESSFUL,
若BUILD FAIL
,说明构建失败,这时候你就要按照失败提示去排错,排错完后在执行一遍gradlew install
命令,直到出现BUILD SUCCESS
- 把代码提交到本地
git
仓库
git add .
和git commit -m “XX”
- 在本地
git
仓库打tag
git tag -a 1.0.0 -m "第一版" git push origin 1.0.0 复制代码
- 打开你的
libary
的github
界面,点击release
,如下:
![release](/upload/202004/26/202004262303468736.png)
- 点击
Draft a new release
,新建一个release
,如下:
![image-20200424182958983](/upload/202004/26/202004262303468971.png)
- 然后填信息,如下:
![填信息](/upload/202004/26/202004262303469439.png)
- 填好信息后,点击
publich release
,如下:
![](/upload/202004/26/202004262303469674.png)
- 用
GitHub
账号登陆、注册jitpack
- 登陆后,在地址栏中输入你的
library
的github
项目地址,然后点击Look Up
,如下:
![](/upload/202004/26/202004262303469898.png)
- 然后点击
Get it
,它会滚到下面去,你要滚回上面去,先等一会,等jitpack
那里构建完,会出现一个绿色的log
,则构建成功,如下:
![](/upload/202004/26/202004262303470162.png)
然后你就可以愉快的在项目中按照它的提示引用你的开源库
![](/upload/202004/26/202004262303470416.png)
- 点击那个
jitpack
,把它的链接复制到你的Readme
中去,如下:
![jitpack](/upload/202004/26/202004262303470543.png)
2.6 尝试使用你的框架
当然是在 app\build.gradle
中
//引用自己的开源库 implementation 'com.github.LoveLifeEveryday:XPermissions:1.0.0' 复制代码
然后尝试使用吧
![完成](/upload/202004/26/202004262303470621.png)
2.7 美化你的项目
一个优秀的开源项目,readme
一定不会差
鲁迅说:『虽然这些工作不会让你的项目变得牛逼,但会让你的项目变得漂亮,方便了其他人去了解你这个项目』
详细的美化操作,可以参考这篇文章:如何让你的 GitHub 项目表面上更专业
![好看](/upload/202004/26/202004262303470885.png)
三.我在使用中遇到的问题
3.1 在模拟器上 Call
权限申请无反应
- 发生情景:在逍遥模拟器上测试
Call
权限
至于我为什么要使用逍遥模拟器,这又是另一个故事了
- 解决:真机测试正常申请权限,于是百度了一波,发现很多模拟器没有
Call
这个权限(such as 夜神模拟器),我觉得原装的模拟器应该是可以正常运行的 - 结论:模拟器的锅
3.2 上传到 Jcenter
时 Failed
- 发生情景:执行上传命令的时候,运行到最后发生错误
- 错误:
* What went wrong: Execution failed for task ':utils:bintrayUpload'. > org.apache.http.NoHttpResponseException: The target server failed to respond 复制代码
- 过程:
Google
&&Baidu
- 结论:网络问题
- 结果:尝试了普通网络和 Ke Xue 上网,还是无法解决,转为使用
JitPack
如果想了解,怎么上传到
Jcenter
的话,可以看下这篇文章:AS上传Library到JCenter 教程+踩坑记录
![bug 退散](/upload/202004/26/202004262303471070.png)
如果文章对您有一点帮助的话,希望您能点一下赞,您的点赞,是我前进的动力
本文参考链接:
- 『Android 第一行代码 - 第三版』
- AS上传Library到JCenter 教程+踩坑记录
- 如何让你的 GitHub 项目表面上更专业
- 快速发布开源库到jitpack
这篇关于带你封装自己的『权限管理』框架的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-01-18android.permission.read_media_video
- 2024-01-18android_getaddrinfo failed eai_nodata
- 2024-01-18androidmo
- 2024-01-15Android下三种离屏渲染技术
- 2024-01-09Android 蓝牙使用
- 2024-01-06Android对接华为AI - 文本识别
- 2023-11-15代码安全之代码混淆及加固(Android)
- 2023-11-10简述Android语音播报TTS
- 2023-11-06Android WiFi工具类
- 2023-07-22Android开发未来的出路