一扫腺、背景
AOP (面向切面編程),Aspect Oriented Programming的縮寫,意為:面向切面編程句柠,通過預編譯方式和運行期間動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)咸包。AOP是OOP的延續(xù)桃序,是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容烂瘫,是函數(shù)式編程的一種衍生范型媒熊。利用AOP可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低坟比,提高程序的可重用性芦鳍,同時提高了開發(fā)的效率。(百度百科)
Android權(quán)限葛账,做Android開發(fā)的都知道柠衅,申請權(quán)限雖然簡單,但是每次使用都寫一次繁瑣的申請流程籍琳。當然茄茁,github上面也有很多比較優(yōu)秀的開源權(quán)限申請框架。
所謂“不想當將軍的士兵不是好士兵”巩割,“不想‘偷懶’的程序員不是好程序員”裙顽。因此,我本著偷懶偷到極致的想法宣谈,利用aspectjrt aop編程方式開發(fā)一個權(quán)限申請工具愈犹,做到在實際使用當中一行代碼完成申請權(quán)限。(牛吹得有點過了)
項目github地址:https://github.com/wushaohongly/AopPermission
運行效果:
二、依賴配置
項目 build.gradle
dependencies {
...
classpath 'org.aspectj:aspectjtools:1.9.5'
}
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
app build.gradle
dependencies {
...
implementation 'org.aspectj:aspectjrt:1.9.5'
implementation 'com.github.wushaohongly:AopPermission:1.0.0'
}
// 最后增加
/**
* aspectjrt 編譯相關(guān)
*/
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
final def log = project.logger
final def variants = project.android.applicationVariants
// 在構(gòu)建工程時漩怎,執(zhí)行編輯
variants.all { variant ->
// if (!variant.buildType.isDebuggable()) {
// log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
// return;
// }
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = ["-showWeaveInfo",
"-1.8",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
log.debug "ajc args: " + Arrays.toString(args)
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
log.warn message.message, message.thrown
break;
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
三勋颖、使用
以申請撥打電話與讀外置存儲權(quán)限為例,click是一個需要擁有權(quán)限才能執(zhí)行的方法勋锤,在click方法加入@PermissionsCheck(權(quán)限名稱字符串數(shù)組)注解饭玲,執(zhí)行click方法前就會申請注解生命的權(quán)限。
如果申請成功叁执,則會執(zhí)行click方法體茄厘,否則將不執(zhí)行click方法體。
@PermissionsCheck({Manifest.permission.CALL_PHONE, Manifest.permission.READ_EXTERNAL_STORAGE})
public void click(View view) {
Toast.makeText(this, "權(quán)限申請成功", Toast.LENGTH_LONG).show();
}
四谈宛、支持配置拒絕權(quán)限彈框
在三次哈,當用戶拒絕權(quán)限后,因為不執(zhí)行click方法體吆录,沒有其他友好性提示窑滞,顯然是不合理的。為了增加擴展性恢筝,類庫支持拒絕權(quán)限后彈出自定義Dialog哀卫。
自定義的Dialog須繼承與類庫的PermissionRefuseDialog。
public class MyRefuseDialog extends PermissionRefuseDialog {
...
public MyRefuseDialog(@NonNull Context context) {
super(context);
setContentView(R.layout.布局);
}
@Override
public void setPermissions(String[] permissions) {
// 父類賦值 permissions
super.setPermissions(permissions);
// 這里拿到拒絕的權(quán)限數(shù)組
}
}
在BaseActivity / BaseFragment當中設(shè)置撬槽,此處為什么呢聊训?因為Dialog是需要依賴Window,所以需要在具體的某個Activity / Fragment當中創(chuàng)建恢氯。(或者還有更好的方式實現(xiàn))
// 將自定義的Dialog,設(shè)置到 library中
AopPermissionsConfig.setRefuseDialog(new MyRefuseDialog(this));
五鼓寺、混淆配置
-keep class com.wushaohong.library.permissions.**{*;}
六勋拟、結(jié)語
1、實測是運行在Android10系統(tǒng)妈候,編譯環(huán)境jdk1.8敢靡,據(jù)了解,aspectjrt1.9.5最低支持Android7.0
2苦银、不支持Kotlin語言(kotlin版已實現(xiàn)啸胧,有時間再整理上傳)
3、如有不合理之處幔虏,歡迎各位指點纺念,本人感激不盡。