前语

本文现已收录到我的 Github 个人博客,欢迎大佬们光临舍间:

我的 Github 博客

本篇文章需求现已具备的常识:

  • GitGithub 的基本运用
  • Kotlin 语法根底
  • Android 开发根底

学习清单:

  • 怎样封装自己的权限结构
  • 将开源库发布_ % 7 y 1 J W Z wJitPack 库房的一整套流程

一.为什么要封装这套结构

咱们在日常开发中,L , X u常常需t 0 0 ~ z O Q求用到恳求运转时权限的常识,所以,常常就写了下面的一大串代码


override fun onCreate(savedIn0 ? y . N 3stanceState: Bund x : * Gdle?) {
super.onCreate(savedInstanceState)
setContentView(R.l6 C %ayout.activity_main)
...
//恳求 CALL_PHONE 权限
if (ContextCompat.checkSelfPermission(
this,
Manifest.permissioA d H z %n.CALL_PHONE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(this, arrayOf(Manife: O T m _ } Est.permission.CALL_PHONE), 1)
} else {
call()
}
}
override fun onRequesG 4 K 2 T AtPermissio8 R 7 FnsResult(
requestCode: Int,
permissiog N ` d L (ns: A8 h Xrray<out String>,
gra; ! dntResults: IntArray
) {
super.onRequestPermissionsResult(requesF d Z  C p 6 1tCode, permissions, grantResul, F S d $ m @ Wts)
when (requestCode) {
1 -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
call()
} else {
Toast.makeText(this, "You denied the p[ a 0 ( B Kermission9 E ^ 4", Toast.LENGTH_SHORT).show()
}
}
}
}

麻鸭,头疼,这么多代码,不只写着难过,看着更是头疼

带你封装自己的『权限管理』框架

这时候,假如这个国际简略点,纯粹点,就好了

XPermission.request(
this,
M% Q ~ J Panifest.perN K ] ? | [ *mission.CALL_PHONE
) { allGranted, deniedList ->
if (allGranted) {
call()
} else {
Toast.makeTG 9 0 u w dext(this, "You denied $deniedList", Toast.LENGTH_SHORT).show()
}
}

是不是感觉国际又友好了许多呢?这段代码比之前的代码量少了许多不说,逻辑更是清晰了许多鸭!

带你封装自己的『权限管理』框架

很显然,上面用到了自己封装的结构,有或许你会一脸不屑:『这算啥?Github 上一堆权限恳求结构,他们写的这个简练又美丽,功能又多又全,超帅的』

我想说:『是的,你说的对,虽然 G. . y l 1 X W ; hithub 上有这么多,跑得又快又棒的轮子,但是,他人做的菜总归没有自己的香鸭!咱们能够经过自己封装一个简略的权限恳求结构开端,学习发布开源库到 Jitpack / Jcenter 的一整套流程,从而激发自己的学7 M [ d , j ; p _习兴趣,今后自己也多多造轮子(xia zhe teng)!成为 An. : a R Adroid 界的轮6 O / G # P u子哥』

先为大佬送上笔者现已封装好的p L #轮子:githuby P L :.com/LoveLifeEve…

带你封装自己的『权限管理』框架
带你封装自己的『权限管理』框架

二.入坑之路

2.1 创立 Android 项目

新建一个空的 Android/ v % A G& : Q [ j o S =

带你封装自己的『权限管理』框架

2.2 创立 Github 项目

带你封装自己的『权限管理』框架
  • 然后,把该项目 clone 到一个上面现已创立的 Android 项目的位置

  • 将克隆下来的一切文件全部仿制到上一层目录(注意:仿制的时候不要忘记仿制 .gm f _ !it 文件)

  • 将克隆的, M @ 8 L w XPermission 目录删除

  • 执行一系列的 git add . git c| q gommit -m "Firsth 9 [ t G s t commit" git push origin master 操作

2.3 完成 XPermission

  1. 对着最顶层的 XPermission ,新建一) 3 . z module ,选择 Android Library
带你封装自己的『权限管理』框架

看到 library 就行,如下

带你封装自己的『权限管理』框架

然后,咱们思考下,运转时权限的完成思路,有以下三种:

  • 将运转时权限的操作封装到 BaseActivity# b =
  • 提供一个通明的 Actj , _ livity 来处理
  • 提供一个隐藏的 Fragment 来处理

本文,将依据最终一个思路进s s ! T A Y –行完成

2.3.1 创立 Invisiba M ~ l +leFragmenW p S L . l E ; }t

//给  (Boolean, List<String&g. 1 H i Y # B dt;) -> Unit 指定一个别名
typealias PermissionCallback = (Boolean, List<String>) -> Unit
class InvisibleFrM V L e t 4agment : Fragment() {
//B J V | U | 6界说一个 callback 作为运转时权( w  I限恳求成果的回调h w r S u ~告诉办法E $ d ^ z
private var callback: PermissionCallback? = null
//界说恳求权限的办法,vararg 表明可变长度的 permissions 参数列z ] : ^ . w Q N ,
fun requestNow(cb: PermissionCallback, vararg permission: String) {
callback = cb
requestPermissions(permission, 1)
}
/**o # ? 4 p
* 恳求返回成果
* @param requestCode Inq E P = : 6t 恳求码
* @param permissions Array<Su + jtring> 权限
* @paramS t y ^ h 0 + I 3 grantResq Z + f 8 , # * lults IntArray 恳求6 Y l D成果
*/
override fun6 Q u Q ^ onRequestPermissionsResult(
requestCode: IntE 1 v x B , [,
permissionS D t I es: A/ - & _ & Y S nrrm ! 9 - %ay<String>,
grantResults: IntAL F [ 3 l C rrray
) {
if (requestCode == 1) {
// deniedList 用来记载被用户拒绝的权限
val deniedList = ArrayList<String>(q L F =)
for ((index, result) in grantResults.withIndex()) {
if (result != PackageManager.PERMISSION_GRANTED) {
deniedList.add(permissions9 d - K . ? : A ][index])
}
}
// allGranted 用来标识是否一切恳求的权限都现已授权
val allGrk U p 5 anted = deniedList.isEmpty()
//对恳求权限的成果进行回E y i G 9 _ d
callback?.let { it(alU ! &lGranted, de( U y E niedList) }
}
}
}
  • 首要,咱们界说一个 callbac] } K K A Wk 作为运转时权限恳求成果的回调告诉办法
  • 然后,界说一个W # o requestNow 办法
  • 最终重写 onRequestPermissionsResult 办法
带你封装自己的『权限管理』框架

2.3.2 创立 XPermission

object XPermission {
private const val TAG = "InvisibleFragment"
fun request(
activity: FragmentActivity,
vara% i C T F + c Wrg permission: String,
callb[ $ P 1 1ack: Pj E 5ermissionCallback
) {
val fragment* 3 L ,Man# ; 0 - 9 Pager =l , ? X b V e h activity.supportFragmentManager
val existedFragment = fragmentManager.findFrag 9 ; $ e [ H WmentByTag(TAG)
val fragment = if (existedFragment != null) {
existedFragment as InvisibleFragment
} else {
val invisibleFragment = InvisibleFragment()
fragmentManager.beginTransaction().add(invisibleFragv G p ` } ment, TAG).commitNG Q D *  {ow()
invisibleFragment
}
//这里在 permission 前面加个星号的意思h L O o 1 | ?是:将数组转化为可变长度参数传递曩昔
frH  * / 4 pagment.requestNow(callback, *permission)
}
}

相信代码我T ` Q们都看得懂,所以笔者就不写许多注释了(其实是因为懒..)

2.4 测验

appbuild.gradle 中引入 libn W qrary

dependencie? f L &s {
implement% 2 pation fileTrf 7  ee(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.u ~ ~ A p y P F |kotlin:kotlin-stdlib-j6 u O 6 a sdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testIm] 0 G Q f V C n bplementaI e | 6 *tion 'junit:junit:4.12'
androidTestImplementation 'androidx.J Z c ] q q y /test.ext:junit:1.1.1'
androidTestImplementatiov I ) v F = A n 'androidx.test.espresso:espresso-core:3.2.0'
//增加这行就行
implementatiof / = 9 x Dn project(':library')
}

然后进行你喜爱的权限恳求

claK I Y t S Oss MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInst$ T e R t s | T )anceState( ` _ ? ^)
setCok % x ? ?ntentView(R.layout.activity_main)
makeCaf g _ w s 7 9 dllBtn.setOp P knClickListener {
XPermission.request(ta f 9 2 = b i T 5hiu a ) Ts, Manifest.permission.CALL_PHONE) { allGranted, deniedLis W x = O |t -&G W I m 3 D Q ~ -gt;
if (allGranted) {
call()
} else {
Toast.makeText(this, "You  Denied $deniedList", Toast.LENP 7 {GTH_SHORT).show()
}
}
}
}
private fun call() {
val iY k z  [ } V Yntent = Intent(I: K + M = @ E {ntent.ACTION_CM _ 4 1ALL)
ie . j } d U 3 o $ntent.data = Uri.parse("tel:100866 N c ]")
startActivity(intent)
}
}

假如能够的话,恭喜你,你现已成功一大步了

2.5 发P # 0 ` B ,布到 JitPack

2.5.1 JitPack 简介

JitPack 是一个网站,它答应你把 git 保管的 javaandroid 项目(貌似现在仅支持github和码云),轻松发布到 jitpackmaven 库房上,它一切内容都经过内容分发网络(CDN7 . X ~运用加密 https 连接获取

2.5.2 为什么用 JitPack

长处:打包比较简略,省时间,背靠 Github 这座大山

缺陷:每次导入库的时候,都要先在根的 build.gradle 文件中增加 maven

带你封装自己的『权限管理』框架

2J D V 4 [ s f B.5.3 步骤

  • 在根的 build.gradle 中增加 mavR ) q pen 插件

点击查看最新版本

buildscr, e : q h ? lipt {
ext.kotli% x 3 Wn_a L ( l Wversion = '1.3.71'C 8 I ` r
repositories {
google()
jc9 - / } Kenter()
}
dependencies {
clasZ + b Qspc l ! )ath 'com.android.tools.build:gradle:3.V S D5.3'
classpath i : P { f v T B"org.jetbrains.kotlin:kotlinw T Q u-gradle-plugin:$kotlin_versir ` ] = o jon"
//增加 maven 插件
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
// NOTL w { = 5 / v E: D5 w U {o not place youD S l s z L 9r a2 s J l S j 6 { )pplication dependencies here; they belong
// in the individual module build.gradle files
}
}
  • l_ H h U e l r fibrary目录的 build.gradleapply 插件和增加 g { : m uroup
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extension= # r  k e i V ]s'
//增加下面两行
apply plugin: 'com.github.dcenN G r d o *dents.android-maven'
//这里 LoveLifeEveryday 改为你的 github 账号名,我的是:LoveLifeEveryday
group=1 L H % J b'com.github.LoveLifeEveryday'
android {
...
}
  • 同步一下
带你封装自己的『权限管理』框架
  • 在命令行中输入 gradlew installD z L h F y ,从而构建你的 library 到你的本地 maven 库房
带你封装自己的『权限管理』框架

等待 BUILD SUCCESSFUL,BUILD FAIL,说明构建失利,这时候你就要依照失利提示去排错,排错完后在执行一遍 gradlew install 命令,直到呈现 BUILD SUCCESS

  • 把代码提交到本地 gitS ? J j I N

git add .gi* . | 1 D k Ot commit -m “XX”

  • 在本地 git 库房打 tag
git tag -a 1.0.0 -m "榜首版"* * d
git push origin 1.0.0
  • 打开你的 libarygithub 界面,点击 releaseq ) i 8 u 4 8,如下:
带你封装自己的『权限管理』框架
  • 点击 Draft a new release,新建一个 release,如下:
带你封装自己的『权限管理』框架
  • 然后填信息,如下:
带你封装自己的『权限管理』框架
  • 填好信息4 ] & i p后,点击publichU i = . , ^ - c B rel/ s i S x ; q R ,ease,如下:
带你封装自己的『权限管理』框架
  • GitHub 账号登陆、注册 jitpack
  • 登陆后,在地址栏中输入你的 lV m ?ibrarygithub 项目地址,然后点击 Look Up ,如下:
带你封装自己的『权限管理』框架
  • 然后点击 Get it,它会滚到下面去,你要滚回上面去,先等一会,等 jitpack 那里构建完,会呈现一个绿色的 log,则构建成功U A { F K @ H,如下:
带你封装自己的『权限管理』框架

然后你就能够愉快的在项目中依照它的提示引证你的开源库

带你封装自己的『权限管理』框架
  • 点击那个 jitpack ,把它的链接仿制到你的 Readme 中去,如下:
带你封装自己的『权限管理』框架

2.6 测验( c y运用你的结构

G 1 H H Q ) n然是在 appbuild.gradle

//引证自f , @ 己的开源库
implementa` T ! Y & a 5 =tionC  Y 'com.github.LoveLifeEveryday:XPermissiona 1 U 7 ) U 5 |s:1.0.0'

然后测验运用吧m } ^ ~ ` g J

带你封装自己的『权限管理』框架

2.7 美化你的项目

一个优异的开源项目,read_ y # 5 2 F l s @me 必定不会差

鲁迅说:『虽然这些作业不会让你的项目变得牛逼,但会让你的项目变得美丽,方便了其) v R – b 6 G d他人去了解你这个项目』

详细的美化操作,能够参考这篇文! Z c 0 Z ) F章:怎样让你的 GitHub 项目表面上更专业

带你封装自己的『权限管理』框架

三.我在运用中遇到的问题m S 6 ( @ +

3.1 在模拟器上 Call 权限恳求无反响

  • 发作情N X % Y Z I b景:在逍遥模* / = m 8 q r拟器上测验 Call 权限

至于我为什么要运用逍遥模拟器,这又是另一个故事^ 6 ] m M k ! U ,

  • 处理:真机测验正常恳求权限,所以百度了一波,发现许多模拟器没有 Call 这个权限(such as 夜神模拟器),我觉得原装的模拟器应该是能够正常运转的
  • 定论:模拟器的锅? i $ | ) $ p

3.2 上传到 JcenterFailed

  • 发作情景:执行k @ w K上传命令的时候,运转到最终发作过错
  • S j # K ( a Y错:
* What went wrong:
Execution failed for task ':utils:bintrayUpload'.
> org.apache.http.NoHttpResponseException: The targ6 n 6 S T @ ~ G qet server failed to respond
  • 过程:Google && Baidu
  • 定论:网络问题
  • 成果:测0 ( M % t s W , [验了普通网络和 Ke Xue 上网,仍是无法处理,转为运用 JitPack

假如想了解,怎样上传到 Jcenter 的话,能够看下这篇文章:^ s ~ ^AS上传Library到JCenter 教程+踩坑记载

带你封装自己的『权限管理』框架

假如文章# – ; * B L | I对您有一点协助的话,希望您能点一下赞,您的点赞,是我行进的动力

本文参p R R考链接:

  • 『Android 榜首行代码 – 第三版』
  • AS上传Library到JCenter 教程+踩坑记载
  • 怎样让你的 GitHub 项目表面上更专业
  • 快速发布开源库到jitpack