飞道的博客

Android组件化开发实战:封装权限管理请求框架

604人阅读  评论(0)

导读:

通过自己动手封装一个简单的Android权限管理请求框架,学习如何发布开源库到 Jitpack / Jcenter,从而激发自己的学习兴趣,以后自己也能多多造轮子,成为开源界的轮子哥。组件要求简单易懂易用,提供链式调用,因此开发组件需要相应的函数式编程思想,函数式编程在处理连续复杂逻辑的代码上有天然的优势,其风格以清晰著称,是我们封装工具类组件的不二选择。

没有接触过组件化开发的童鞋,可以先看下面这两篇文章:

  1. Android组件化和插件化的概念
  2. Android组件化开发简单示例

【Android权限动态请求框架】的github地址:https://github.com/respost/OmgPermission 

组件化流程:

  • 创建模块,封装自己的权限框架
  • 将开源库发布到 JitPack 仓库

 一、创建Android项目

1、打开Android Studio,创建新项目

 2、选择创建空活动 “Empty Activity” → “Next” 下一步

3、填写项目名称,包名,保存路径,Language语言选择“java” → Finish

二、创建权限组件模块

1、在项目的"APP"上右键 → New →  新建一个 Module 

2、 选择 Android Library  →  Next

3、名称填写library

 三、编写关键代码

1、创建Permission.java类,这个类主要是将权限进行分组的,代码如下:


  
  1. package net.zy13.library;
  2. import android.Manifest;
  3. import android.os.Build;
  4. /**
  5. * 权限类
  6. * 将权限共分为11组,每组只要有一个权限申请成功,就默认整组权限都可以使用了。
  7. *
  8. * @author 安阳 QQ:15577969
  9. * @version 1.0
  10. * @team 美奇软件开发工作室
  11. * @date 2020/11/23 12:54
  12. */
  13. public final class Permission {
  14. public static final String[] CALENDAR;
  15. public static final String[] CAMERA;
  16. public static final String[] CONTACTS;
  17. public static final String[] LOCATION;
  18. public static final String[] MICROPHONE;
  19. public static final String[] PHONE;
  20. public static final String[] SENSORS;
  21. public static final String[] SMS;
  22. public static final String[] STORAGE;
  23. //安装应用权限
  24. public static final String[] PACKAGES;
  25. //通知栏权限
  26. public static final String[] NOTIFICATION;
  27. //悬浮窗权限
  28. public static final String[] ALERTWINDOW;
  29. //系统设置权限
  30. public static final String[] SETTINGS;
  31. static {
  32. /**
  33. * Android系统从6.0开始将权限分为一般权限和危险权限:
  34. * 1、一般权限指不涉及用户隐私的一些权限,比如Internet权限。
  35. * 2、危险权限指涉及获取用户隐私的一些操作所需要的权限,比如读取用户地理位置的权限。
  36. * Android在对权限进行分类的同时,还将危险类型的权限进行了分组划分,因此我们在申请权限的时候要一组一组的申请。
  37. */
  38. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
  39. CALENDAR = new String[]{};
  40. CAMERA = new String[]{};
  41. CONTACTS = new String[]{};
  42. LOCATION = new String[]{};
  43. MICROPHONE = new String[]{};
  44. PHONE = new String[]{};
  45. SENSORS = new String[]{};
  46. SMS = new String[]{};
  47. STORAGE = new String[]{};
  48. PACKAGES= new String[]{};
  49. NOTIFICATION= new String[]{};
  50. ALERTWINDOW= new String[]{};
  51. SETTINGS= new String[]{};
  52. } else {
  53. CALENDAR = new String[]{
  54. Manifest.permission.READ_CALENDAR,
  55. Manifest.permission.WRITE_CALENDAR};
  56. CAMERA = new String[]{
  57. Manifest.permission.CAMERA};
  58. CONTACTS = new String[]{
  59. Manifest.permission.READ_CONTACTS,
  60. Manifest.permission.WRITE_CONTACTS,
  61. Manifest.permission.GET_ACCOUNTS};
  62. //Android10及以上版本,新增2种权限
  63. if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  64. LOCATION = new String[]{
  65. Manifest.permission.ACCESS_FINE_LOCATION,
  66. Manifest.permission.ACCESS_COARSE_LOCATION,
  67. Manifest.permission.ACCESS_BACKGROUND_LOCATION, //在后台获取位置(Android 10.0及以上)
  68. Manifest.permission.ACCESS_MEDIA_LOCATION //读取照片中的地理位置(Android 10.0及以上)
  69. };
  70. } else{
  71. LOCATION = new String[]{
  72. Manifest.permission.ACCESS_FINE_LOCATION,
  73. Manifest.permission.ACCESS_COARSE_LOCATION};
  74. }
  75. MICROPHONE = new String[]{
  76. Manifest.permission.RECORD_AUDIO};
  77. //Android8以上版本PROCESS_OUTGOING_CALLS换成了ANSWER_PHONE_CALLS。
  78. if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
  79. PHONE = new String[]{
  80. Manifest.permission.READ_PHONE_STATE,
  81. Manifest.permission.CALL_PHONE,
  82. Manifest.permission.READ_CALL_LOG,
  83. Manifest.permission.WRITE_CALL_LOG,
  84. Manifest.permission.USE_SIP,
  85. Manifest.permission.ADD_VOICEMAIL,
  86. Manifest.permission.ANSWER_PHONE_CALLS, //接听电话(Android8.0及以上)
  87. Manifest.permission.READ_PHONE_NUMBERS //读取手机号码(Android8.0及以上)
  88. };
  89. } else {
  90. PHONE = new String[]{
  91. Manifest.permission.READ_PHONE_STATE,
  92. Manifest.permission.CALL_PHONE,
  93. Manifest.permission.READ_CALL_LOG,
  94. Manifest.permission.WRITE_CALL_LOG,
  95. Manifest.permission.USE_SIP,
  96. Manifest.permission.ADD_VOICEMAIL,
  97. Manifest.permission.PROCESS_OUTGOING_CALLS};
  98. }
  99. SENSORS = new String[]{
  100. Manifest.permission.BODY_SENSORS,
  101. Manifest.permission.ACTIVITY_RECOGNITION};
  102. SMS = new String[]{
  103. Manifest.permission.SEND_SMS,
  104. Manifest.permission.RECEIVE_SMS,
  105. Manifest.permission.READ_SMS,
  106. Manifest.permission.RECEIVE_WAP_PUSH,
  107. Manifest.permission.RECEIVE_MMS};
  108. /**
  109. * 外部存储权限
  110. * Android11以上版本,存储权限统一用MANAGE_EXTERNAL_STORAGE
  111. */
  112. if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
  113. STORAGE = new String[]{
  114. Manifest.permission.MANAGE_EXTERNAL_STORAGE};
  115. } else {
  116. STORAGE = new String[]{
  117. Manifest.permission.READ_EXTERNAL_STORAGE,
  118. Manifest.permission.WRITE_EXTERNAL_STORAGE};
  119. }
  120. //安装应用权限(Android8.0及以上)
  121. if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
  122. PACKAGES= new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES};
  123. } else{
  124. PACKAGES = new String[]{};
  125. }
  126. //通知栏权限
  127. NOTIFICATION= new String[]{Manifest.permission.ACCESS_NOTIFICATION_POLICY};
  128. //悬浮窗权限
  129. ALERTWINDOW= new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW};
  130. //系统设置权限
  131. SETTINGS= new String[]{Manifest.permission.WRITE_SETTINGS};
  132. }
  133. }
  134. }

2、创建PermissionUtils.java工具类,这个类主要是封装一些权限的通用方法,代码如下:


  
  1. import android.annotation.TargetApi;
  2. import android.app.Activity;
  3. import android.content.pm.PackageManager;
  4. import android.os.Build;
  5. import androidx.fragment.app.Fragment;
  6. import java.lang.annotation.Annotation;
  7. import java.lang.reflect.Method;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /**
  11. * 权限的工具类
  12. *
  13. * @author 安阳 QQ:15577969
  14. * @version 1.0
  15. * @team 美奇软件开发工作室
  16. * @date 2020/11/23 13:09
  17. */
  18. public class PermissionUtils {
  19. /**
  20. * 判断Android系统版本是否大于6.0
  21. *
  22. * @return
  23. */
  24. public static boolean judgeVersion() {
  25. return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
  26. }
  27. /**
  28. * 从申请的权限中找出未授予的权限
  29. *
  30. * @param activity
  31. * @param permission
  32. * @return
  33. */
  34. @TargetApi(value = Build.VERSION_CODES.M)
  35. public static List<String> findDeniedPermissions(Activity activity, String... permission) {
  36. List<String> denyPermissions = new ArrayList<>();
  37. for (String value : permission) {
  38. if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED) {
  39. denyPermissions.add(value);
  40. }
  41. }
  42. return denyPermissions;
  43. }
  44. /**
  45. * 寻找相应的注解方法
  46. *
  47. * @param c1 要寻找的那个类
  48. * @param c2 响应的注解标记
  49. * @return
  50. */
  51. public static List<Method> findAnnotationMethods(Class c1, Class<? extends Annotation> c2) {
  52. List<Method> methods = new ArrayList<>();
  53. for (Method method : c1.getDeclaredMethods()) {
  54. if (method.isAnnotationPresent(c2)) {
  55. methods.add(method);
  56. }
  57. }
  58. return methods;
  59. }
  60. public static <A extends Annotation> Method findMethodPermissionFailWithRequestCode(Class clazz, Class<A> permissionFailClass, int requestCode) {
  61. for (Method method : clazz.getDeclaredMethods()) {
  62. if (method.isAnnotationPresent(permissionFailClass)) {
  63. if (requestCode == method.getAnnotation(PermissionFail.class).requestCode()) {
  64. return method;
  65. }
  66. }
  67. }
  68. return null;
  69. }
  70. /**
  71. * 找到相应的注解方法(requestCode请求码与需要的一样)
  72. *
  73. * @param m
  74. * @param c
  75. * @param requestCode
  76. * @return
  77. */
  78. public static boolean isEqualRequestCodeFromAnntation(Method m, Class c, int requestCode) {
  79. if (c.equals(PermissionFail.class)) {
  80. return requestCode == m.getAnnotation(PermissionFail.class).requestCode();
  81. } else if (c.equals(PermissionSuccess.class)) {
  82. return requestCode == m.getAnnotation(PermissionSuccess.class).requestCode();
  83. } else {
  84. return false;
  85. }
  86. }
  87. public static <A extends Annotation> Method findMethodWithRequestCode(Class c, Class<A> annotation, int requestCode) {
  88. for (Method method : c.getDeclaredMethods()) {
  89. if (method.isAnnotationPresent(annotation)) {
  90. if (isEqualRequestCodeFromAnntation(method, annotation, requestCode)) {
  91. return method;
  92. }
  93. }
  94. }
  95. return null;
  96. }
  97. public static <A extends Annotation> Method findMethodPermissionSuccessWithRequestCode(Class c, Class<A> permissionFailClass, int requestCode) {
  98. for (Method method : c.getDeclaredMethods()) {
  99. if (method.isAnnotationPresent(permissionFailClass)) {
  100. if (requestCode == method.getAnnotation(PermissionSuccess.class).requestCode()) {
  101. return method;
  102. }
  103. }
  104. }
  105. return null;
  106. }
  107. public static Activity getActivity(Object object) {
  108. if (object instanceof Fragment) {
  109. return ((Fragment) object).getActivity();
  110. } else if (object instanceof Activity) {
  111. return (Activity) object;
  112. }
  113. return null;
  114. }
  115. }

3、创建成功和失败的回调接口类,代码如下:

PermissionSuccess.java

  
  1. /**
  2. * @author 安阳 QQ:15577969
  3. * @version 1.0
  4. * @team 美奇软件开发工作室
  5. * @date 2020/11/23 13:12
  6. */
  7. import java.lang.annotation.ElementType;
  8. import java.lang.annotation.Retention;
  9. import java.lang.annotation.RetentionPolicy;
  10. import java.lang.annotation.Target;
  11. @Retention(RetentionPolicy.RUNTIME)
  12. @Target(ElementType.METHOD)
  13. public @interface PermissionSuccess {
  14. int requestCode();
  15. }
PermissionFail.java

  
  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. /**
  6. * @author 安阳 QQ:15577969
  7. * @version 1.0
  8. * @team 美奇软件开发工作室
  9. * @date 2020/11/23 13:12
  10. */
  11. @Target(ElementType.METHOD)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface PermissionFail {
  14. int requestCode();
  15. }

4、创建OmgPermission.java对象类,这个类就是我们封装的权限框架主体,代码如下:


  
  1. import android.annotation.TargetApi;
  2. import android.app.Activity;
  3. import android.content.pm.PackageManager;
  4. import android.os.Build;
  5. import androidx.fragment.app.Fragment;
  6. import java.lang.reflect.InvocationTargetException;
  7. import java.lang.reflect.Method;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. /**
  11. * 动态权限的对象
  12. * @author 安阳 QQ:15577969
  13. * @version 1.0
  14. * @team 美奇软件开发工作室
  15. * @date 2020/11/23 12:56
  16. */
  17. public class OmgPermission {
  18. //权限集合
  19. private String[] mPermissions;
  20. //请求码
  21. private int mRequestCode;
  22. //对象
  23. private Object object;
  24. //权限回调方法
  25. private static PermissionCallback permissionCallback;
  26. /**
  27. * 构造方法
  28. */
  29. private OmgPermission(Object object) {
  30. this.object = object;
  31. }
  32. /**
  33. * with函数是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。
  34. * 返回值为函数块的最后一行或指定return表达式。
  35. */
  36. public static OmgPermission with(Activity activity){
  37. return new OmgPermission(activity);
  38. }
  39. public static OmgPermission with(Fragment fragment){
  40. return new OmgPermission(fragment);
  41. }
  42. /**
  43. * 获取权限组集合
  44. * @param permissions
  45. * @return
  46. */
  47. public OmgPermission permissions(String... permissions){
  48. this.mPermissions = permissions;
  49. return this;
  50. }
  51. /**
  52. * 添加请求码
  53. * @param requestCode
  54. * @return
  55. */
  56. public OmgPermission addRequestCode(int requestCode){
  57. this.mRequestCode = requestCode;
  58. return this;
  59. }
  60. @TargetApi(value = Build.VERSION_CODES.M)
  61. public void request(){
  62. permissionCallback = null;
  63. requestPermissions(object, mRequestCode, mPermissions);
  64. }
  65. @TargetApi(value = Build.VERSION_CODES.M)
  66. public void request(PermissionCallback callback){
  67. if(callback!= null) {
  68. permissionCallback = callback;
  69. }
  70. requestPermissions(object, mRequestCode, mPermissions);
  71. }
  72. /**
  73. * 活动请求权限
  74. * @param activity
  75. * @param requestCode
  76. * @param permissions
  77. */
  78. public static void needPermission(Activity activity, int requestCode, String[] permissions){
  79. permissionCallback = null;
  80. requestPermissions(activity, requestCode, permissions);
  81. }
  82. public static void needPermission(Activity activity, int requestCode, String permission){
  83. permissionCallback = null;
  84. needPermission(activity, requestCode, new String[] { permission });
  85. }
  86. /**
  87. * 活动请求权限,带回调方法
  88. * @param activity
  89. * @param requestCode
  90. * @param permissions
  91. * @param callback
  92. */
  93. public static void needPermission(Activity activity, int requestCode, String[] permissions
  94. ,OmgPermission.PermissionCallback callback) {
  95. if (callback != null) {
  96. permissionCallback = callback;
  97. }
  98. requestPermissions(activity, requestCode, permissions);
  99. }
  100. public static void needPermission(Activity activity, int requestCode, String permission,PermissionCallback callback){
  101. if (callback != null) {
  102. permissionCallback = callback;
  103. }
  104. needPermission(activity, requestCode, new String[] { permission });
  105. }
  106. /**
  107. * 碎片请求权限
  108. * @param fragment
  109. * @param requestCode
  110. * @param permissions
  111. */
  112. public static void needPermission(Fragment fragment, int requestCode, String[] permissions){
  113. permissionCallback = null;
  114. requestPermissions(fragment, requestCode, permissions);
  115. }
  116. public static void needPermission(Fragment fragment, int requestCode, String permission){
  117. permissionCallback = null;
  118. needPermission(fragment, requestCode, new String[] { permission });
  119. }
  120. /**
  121. * 碎片请求权限,带回调方法
  122. * @param fragment
  123. * @param requestCode
  124. * @param permissions
  125. * @param callback
  126. */
  127. public static void needPermission(Fragment fragment, int requestCode, String[] permissions
  128. ,OmgPermission.PermissionCallback callback) {
  129. if (callback != null) {
  130. permissionCallback = callback;
  131. }
  132. requestPermissions(fragment, requestCode, permissions);
  133. }
  134. public static void needPermission(Fragment fragment, int requestCode, String permission,PermissionCallback callback){
  135. if (callback != null) {
  136. permissionCallback = callback;
  137. }
  138. needPermission(fragment, requestCode, new String[] { permission });
  139. }
  140. /**
  141. * 请求权限
  142. * @param object
  143. * @param requestCode
  144. * @param permissions
  145. */
  146. @TargetApi(value = Build.VERSION_CODES.M)
  147. private static void requestPermissions(Object object, int requestCode, String[] permissions){
  148. //判断系统版本是否大于6.0
  149. if(!PermissionUtils.judgeVersion()) {
  150. if (permissionCallback != null) {
  151. permissionCallback.permissionSuccess(requestCode);
  152. } else {
  153. doExecuteSuccess(object, requestCode);
  154. }
  155. return;
  156. }
  157. List<String> deniedPermissions = PermissionUtils.findDeniedPermissions(PermissionUtils.getActivity(object), permissions);
  158. /**
  159. * 先检查是否有没有授予的权限,有的话请求,没有的话就直接执行权限授予成功的接口/注解方法
  160. */
  161. if(deniedPermissions.size() > 0){
  162. if(object instanceof Activity){
  163. ((Activity)object).requestPermissions(deniedPermissions.toArray( new String[deniedPermissions.size()]), requestCode);
  164. } else if(object instanceof Fragment){
  165. ((Fragment)object).requestPermissions(deniedPermissions.toArray( new String[deniedPermissions.size()]), requestCode);
  166. } else {
  167. throw new IllegalArgumentException(object.getClass().getName() + " is not supported");
  168. }
  169. } else {
  170. if (permissionCallback != null) {
  171. permissionCallback.permissionSuccess(requestCode);
  172. } else {
  173. doExecuteSuccess(object, requestCode);
  174. }
  175. }
  176. }
  177. private static void doExecuteSuccess(Object activity, int requestCode) {
  178. Method executeMethod = PermissionUtils.findMethodWithRequestCode(activity.getClass(),
  179. PermissionSuccess.class, requestCode);
  180. executeMethod(activity, executeMethod);
  181. }
  182. private static void doExecuteFail(Object activity, int requestCode) {
  183. Method executeMethod = PermissionUtils.findMethodWithRequestCode(activity.getClass(),
  184. PermissionFail.class, requestCode);
  185. executeMethod(activity, executeMethod);
  186. }
  187. private static void executeMethod(Object activity, Method executeMethod) {
  188. if(executeMethod != null){
  189. try {
  190. if(!executeMethod.isAccessible()) executeMethod.setAccessible( true);
  191. executeMethod.invoke(activity, new Object[]{});
  192. } catch (IllegalAccessException e) {
  193. e.printStackTrace();
  194. } catch (InvocationTargetException e) {
  195. e.printStackTrace();
  196. }
  197. }
  198. }
  199. public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions,
  200. int[] grantResults) {
  201. requestResult(activity, requestCode, permissions, grantResults);
  202. }
  203. public static void onRequestPermissionsResult(Fragment fragment, int requestCode, String[] permissions,
  204. int[] grantResults) {
  205. requestResult(fragment, requestCode, permissions, grantResults);
  206. }
  207. /**
  208. * 回调接口不为空的话,先执行回调接口的方法,若为空,则寻找响应的注解方法。
  209. * @param obj
  210. * @param requestCode
  211. * @param permissions
  212. * @param grantResults
  213. */
  214. private static void requestResult(Object obj, int requestCode, String[] permissions,
  215. int[] grantResults){
  216. List<String> deniedPermissions = new ArrayList<>();
  217. for( int i= 0; i<grantResults.length; i++){
  218. if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
  219. deniedPermissions.add(permissions[i]);
  220. }
  221. }
  222. if(deniedPermissions.size() > 0){
  223. if(permissionCallback!= null){
  224. permissionCallback.permissionFail(requestCode);
  225. } else {
  226. doExecuteFail(obj, requestCode);
  227. }
  228. } else {
  229. if(permissionCallback!= null){
  230. permissionCallback.permissionSuccess(requestCode);
  231. } else {
  232. doExecuteSuccess(obj, requestCode);
  233. }
  234. }
  235. }
  236. public interface PermissionCallback{
  237. //请求权限成功
  238. void permissionSuccess(int requsetCode);
  239. //请求权限失败
  240. void permissionFail(int requestCode);
  241. }
  242. }

四、本地调用权限框架

1、添加依赖,在主项目的build.gradle文件的dependencies{}配置里,添加如下语句:


  
  1. dependencies {
  2. //集成权限请求框架
  3. implementation project(':library')
  4. }

2、简单示例用法:


  
  1. public class MainActivity extends AppCompatActivity {
  2. //联系人请求码
  3. private final int REQUEST_CONTACT = 100;
  4. //存储请求码
  5. private final int REQUEST_STORAGE = 200;
  6. //相机请求码
  7. private final int REQUEST_CAMERA = 300;
  8. private Button storageButton;
  9. private Button cameraButton;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. /**
  15. * 请求权限
  16. * request()方法的参数可以有也可以没有,有且不为空,就会回调PermissionCallback的响应的回调方法,没有或为空,则回调响应的注解方法。
  17. */
  18. OmgPermission.with(MainActivity. this)
  19. //添加请求码
  20. .addRequestCode(REQUEST_CAMERA)
  21. //单独申请一个权限
  22. //.permissions(Manifest.permission.CAMERA)
  23. //同时申请多个权限
  24. .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.WRITE_CONTACTS)
  25. .request( new OmgPermission.PermissionCallback(){
  26. @Override
  27. public void permissionSuccess(int requestCode) {
  28. Toast.makeText(MainActivity. this, "成功授予联系人权限,请求码: " + requestCode, Toast.LENGTH_SHORT).show();
  29. }
  30. @Override
  31. public void permissionFail(int requestCode) {
  32. Toast.makeText(MainActivity. this, "授予联系人权限失败,请求码: " + requestCode, Toast.LENGTH_SHORT).show();
  33. }
  34. });
  35. }
  36. /**
  37. * 回调注解方法
  38. * 当request()没有参数的时候,就会在当前类里面寻找相应的注解方法
  39. */
  40. @PermissionSuccess(requestCode = REQUEST_STORAGE)
  41. public void permissionSuccess() {
  42. Toast.makeText(MainActivity. this, "回调注解方法:成功授予读写权限" , Toast.LENGTH_SHORT).show();
  43. }
  44. @PermissionFail(requestCode = REQUEST_STORAGE)
  45. public void permissionFail() {
  46. Toast.makeText(MainActivity. this, "回调注解方法:授予读写权限失败" , Toast.LENGTH_SHORT).show();
  47. }
  48. @PermissionSuccess(requestCode = REQUEST_CONTACT)
  49. public void permissionSuccessContact() {
  50. Toast.makeText(MainActivity. this, "回调注解方法:成功授予联系人权限" , Toast.LENGTH_SHORT).show();
  51. }
  52. @PermissionFail(requestCode = REQUEST_CONTACT)
  53. public void permissionFailContact() {
  54. Toast.makeText(MainActivity. this, "回调注解方法:授予联系人权限失败" , Toast.LENGTH_SHORT).show();
  55. }
  56. @PermissionSuccess(requestCode = REQUEST_CAMERA)
  57. public void permissionSuccessCamera() {
  58. Toast.makeText(MainActivity. this, "回调注解方法:成功授予相机权限" , Toast.LENGTH_SHORT).show();
  59. }
  60. @PermissionFail(requestCode = REQUEST_CAMERA)
  61. public void permissionFailCamera() {
  62. Toast.makeText(MainActivity. this, "回调注解方法:授予相机权限失败" , Toast.LENGTH_SHORT).show();
  63. }
  64. /**
  65. * 申请权限的系统回调方法
  66. * @param requestCode
  67. * @param permissions
  68. * @param grantResults
  69. */
  70. @Override
  71. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  72. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  73. OmgPermission.onRequestPermissionsResult(MainActivity. this, requestCode, permissions, grantResults);
  74. }
  75. }

3、点击按钮时,使用needPermission()方法动态申请权限:


  
  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  2. //联系人请求码
  3. private final int REQUEST_CONTACT = 100;
  4. //存储请求码
  5. private final int REQUEST_STORAGE = 200;
  6. //相机请求码
  7. private final int REQUEST_CAMERA = 300;
  8. private Button storageButton;
  9. private Button cameraButton;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. //获取控件
  15. storageButton=(Button) findViewById(R.id.storageButton);
  16. cameraButton=(Button) findViewById(R.id.cameraButton);
  17. //设置监听
  18. storageButton.setOnClickListener( this);
  19. cameraButton.setOnClickListener( this);
  20. }
  21. @Override
  22. public void onClick(View view) {
  23. switch (view.getId()){
  24. //申请存储权限按钮
  25. case R.id.storageButton:
  26. /**
  27. * 请求权限
  28. * 如果没有callback作为参数,就会去调用响应的注解方法
  29. */
  30. OmgPermission.needPermission(MainActivity. this, REQUEST_STORAGE, Permission.STORAGE);
  31. break;
  32. //申请相机权限按钮
  33. case R.id.cameraButton:
  34. /**
  35. * 请求权限
  36. */
  37. OmgPermission.needPermission(MainActivity. this, REQUEST_CAMERA, Permission.CAMERA, new OmgPermission.PermissionCallback(){
  38. @Override
  39. public void permissionSuccess(int requestCode) {
  40. Toast.makeText(MainActivity. this, "成功授予相机权限", Toast.LENGTH_SHORT).show();
  41. }
  42. @Override
  43. public void permissionFail(int requestCode) {
  44. Toast.makeText(MainActivity. this, "授予相机权限失败", Toast.LENGTH_SHORT).show();
  45. }
  46. });
  47. break;
  48. }
  49. }
  50. }

五、发布开源库到 JitPack

JitPack的简介:

JitPack实际上是一个自定义的Maven仓库,不过它的流程极度简化,只需要输入Github项目地址就可发布项目,大大方便了像我这种懒得配置环境的人。JitPack允许你把git 托管的项目(支持github和码云),轻松发布到 jitpack的 maven 仓库上,它所有内容都通过内容分发网络(CDN)使用加密 https 连接获取!

1、在项目的build.gradle(project级别)文件配置里,添加 maven的地址和github插件依赖:


  
  1. buildscript {
  2. repositories {
  3. google()
  4. jcenter()
  5. }
  6. dependencies {
  7. classpath 'com.android.tools.build:gradle:3.5.2'
  8. //添加maven的github插件
  9. classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
  10. }
  11. }
  12. allprojects {
  13. repositories {
  14. google()
  15. jcenter()
  16. //maven地址
  17. maven { url "https://jitpack.io" }
  18. }
  19. }

我这里用的JitPack插件版本是2.0,因为我的Gradle版本是3.5.2,对应的JitPack是2.0,如果你的Gradle版本比较高或者比较低,需要自己查询JitPack对应的版本号

2、在 library模块的 build.gradle下 apply 插件和添加 group分组:


  
  1. apply plugin: 'com.android.library'
  2. //----------------------maven插件 start---------------------//
  3. //apply maven插件
  4. apply plugin: 'com.github.dcendents.android-maven'
  5. //定义github分组,这里的respost改为你github的账号名
  6. group= 'com.github.respost'
  7. //----------------------maven插件 end ---------------------//
  8. android {
  9. }

3、添加好后保存设置,然后点击提示信息里的“Sync Now”进行项目同步。

4、在命令行中输入 gradlew install ,从而构建你的 library 到你的本地 maven 仓库

等待出现 BUILD SUCCESSFUL 就表示构建成功了。若 出现 BUILD FAIL,说明构建失败,这时候你就要按照失败提示去排错,排错完后在执行一遍 gradlew install 命令,直到出现 BUILD SUCCESSFUL

5、上传项目到github上,如果不会的,可以参考这篇文章:https://blog.csdn.net/qq15577969/article/details/107607507

不会使用git管理项目的小白,建议把我博客里的Git栏目的文章都学习一遍!

6、项目上传到github后,在github项目界面的右侧栏点击“Create a new release” :

7、填写release的信息,如下:

8、浏览器访问Jitpack官网 ​​​​​​,在搜索栏里输入你项目的github网址,然后点击“Look up”

9、点击“Get it”进行编译,图标变成如下的绿色,表示编译成功

10、再次点击绿色的“Get it”按钮,就可以查看到开源库的依赖地址了

六、在项目中,使用我们自己的开源库

关于第三方框架(开源库)的使用方法,直接参考这篇文章,https://blog.csdn.net/qq15577969/article/details/109515808


转载:https://blog.csdn.net/qq15577969/article/details/109578824
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场