Android元件化開發實戰:封裝許可權管理請求框架

安陽發表於2020-11-23

導讀:

通過自己動手封裝一個簡單的Android許可權管理請求框架,學習如何釋出開源庫到 Jitpack / Jcenter,從而激發自己的學習興趣,以後自己也能多多造輪子,成為開源界的輪子哥。元件要求簡單易懂易用,提供鏈式呼叫,因此開發元件需要相應的函數語言程式設計思想,函數語言程式設計在處理連續複雜邏輯的程式碼上有天然的優勢,其風格以清晰著稱,是我們封裝工具類元件的不二選擇。

沒有接觸過元件化開發的童鞋,可以先看下面這兩篇文章:

1、Android元件化和外掛化的概念:https://blog.csdn.net/qq15577969/article/details/109594307

2、Android元件化開發簡單示例:https://blog.csdn.net/qq15577969/article/details/109596071

【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類,這個類主要是將許可權進行分組的,程式碼如下:

import android.Manifest;
import android.os.Build;

/**
 * 許可權類
 * @author 安陽 QQ:15577969
 * @version 1.0
 * @team 美奇軟體開發工作室
 * @date 2020/11/23 12:54
 */
public final class Permission {
    //將許可權共分為9組,每組只要有一個許可權申請成功,就預設整組許可權都可以使用了。
    public static final String[] CALENDAR;
    public static final String[] CAMERA;
    public static final String[] CONTACTS;
    public static final String[] LOCATION;
    public static final String[] MICROPHONE;
    public static final String[] PHONE;
    public static final String[] SENSORS;
    public static final String[] SMS;
    public static final String[] STORAGE;

    static {
        /**
         * Android系統從6.0開始將許可權分為一般許可權和危險許可權:
         * 1、一般許可權指不涉及使用者隱私的一些許可權,比如Internet許可權。
         * 2、危險許可權指涉及獲取使用者隱私的一些操作所需要的許可權,比如讀取使用者地理位置的許可權。
         * Android在對許可權進行分類的同時,還將危險型別的許可權進行了分組劃分,因此我們在申請許可權的時候要一組一組的申請。
         */
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            CALENDAR = new String[]{};
            CAMERA = new String[]{};
            CONTACTS = new String[]{};
            LOCATION = new String[]{};
            MICROPHONE = new String[]{};
            PHONE = new String[]{};
            SENSORS = new String[]{};
            SMS = new String[]{};
            STORAGE = new String[]{};
        } else {
            CALENDAR = new String[]{
                    Manifest.permission.READ_CALENDAR,
                    Manifest.permission.WRITE_CALENDAR};

            CAMERA = new String[]{
                    Manifest.permission.CAMERA};

            CONTACTS = new String[]{
                    Manifest.permission.READ_CONTACTS,
                    Manifest.permission.WRITE_CONTACTS,
                    Manifest.permission.GET_ACCOUNTS};

            LOCATION = new String[]{
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION};

            MICROPHONE = new String[]{
                    Manifest.permission.RECORD_AUDIO};

            PHONE = new String[]{
                    Manifest.permission.READ_PHONE_STATE,
                    Manifest.permission.CALL_PHONE,
                    Manifest.permission.READ_CALL_LOG,
                    Manifest.permission.WRITE_CALL_LOG,
                    Manifest.permission.USE_SIP,
                    Manifest.permission.PROCESS_OUTGOING_CALLS};

            SENSORS = new String[]{
                    Manifest.permission.BODY_SENSORS};

            SMS = new String[]{
                    Manifest.permission.SEND_SMS,
                    Manifest.permission.RECEIVE_SMS,
                    Manifest.permission.READ_SMS,
                    Manifest.permission.RECEIVE_WAP_PUSH,
                    Manifest.permission.RECEIVE_MMS};

            STORAGE = new String[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE};
        }
    }

}

2、建立PermissionUtils.java工具類,這個類主要是封裝一些許可權的通用方法,程式碼如下:

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;

import androidx.fragment.app.Fragment;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 許可權的工具類
 *
 * @author 安陽 QQ:15577969
 * @version 1.0
 * @team 美奇軟體開發工作室
 * @date 2020/11/23 13:09
 */
public class PermissionUtils {
    /**
     * 判斷Android系統版本是否大於6.0
     *
     * @return
     */
    public static boolean judgeVersion() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
    }

    /**
     * 從申請的許可權中找出未授予的許可權
     *
     * @param activity
     * @param permission
     * @return
     */
    @TargetApi(value = Build.VERSION_CODES.M)
    public static List<String> findDeniedPermissions(Activity activity, String... permission) {
        List<String> denyPermissions = new ArrayList<>();
        for (String value : permission) {
            if (activity.checkSelfPermission(value) != PackageManager.PERMISSION_GRANTED) {
                denyPermissions.add(value);
            }
        }
        return denyPermissions;
    }

    /**
     * 尋找相應的註解方法
     *
     * @param c1 要尋找的那個類
     * @param c2 響應的註解標記
     * @return
     */
    public static List<Method> findAnnotationMethods(Class c1, Class<? extends Annotation> c2) {
        List<Method> methods = new ArrayList<>();
        for (Method method : c1.getDeclaredMethods()) {
            if (method.isAnnotationPresent(c2)) {
                methods.add(method);
            }
        }
        return methods;
    }

    public static <A extends Annotation> Method findMethodPermissionFailWithRequestCode(Class clazz, Class<A> permissionFailClass, int requestCode) {
        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(permissionFailClass)) {
                if (requestCode == method.getAnnotation(PermissionFail.class).requestCode()) {
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * 找到相應的註解方法(requestCode請求碼與需要的一樣)
     *
     * @param m
     * @param c
     * @param requestCode
     * @return
     */
    public static boolean isEqualRequestCodeFromAnntation(Method m, Class c, int requestCode) {
        if (c.equals(PermissionFail.class)) {
            return requestCode == m.getAnnotation(PermissionFail.class).requestCode();
        } else if (c.equals(PermissionSuccess.class)) {
            return requestCode == m.getAnnotation(PermissionSuccess.class).requestCode();
        } else {
            return false;
        }
    }

    public static <A extends Annotation> Method findMethodWithRequestCode(Class c, Class<A> annotation, int requestCode) {
        for (Method method : c.getDeclaredMethods()) {
            if (method.isAnnotationPresent(annotation)) {
                if (isEqualRequestCodeFromAnntation(method, annotation, requestCode)) {
                    return method;
                }
            }
        }
        return null;
    }

    public static <A extends Annotation> Method findMethodPermissionSuccessWithRequestCode(Class c, Class<A> permissionFailClass, int requestCode) {
        for (Method method : c.getDeclaredMethods()) {
            if (method.isAnnotationPresent(permissionFailClass)) {
                if (requestCode == method.getAnnotation(PermissionSuccess.class).requestCode()) {
                    return method;
                }
            }
        }
        return null;
    }

    public static Activity getActivity(Object object) {
        if (object instanceof Fragment) {
            return ((Fragment) object).getActivity();
        } else if (object instanceof Activity) {
            return (Activity) object;
        }
        return null;
    }
}

3、建立成功和失敗的回撥介面類,程式碼如下:

PermissionSuccess.java
/**
 * @author 安陽 QQ:15577969
 * @version 1.0
 * @team 美奇軟體開發工作室
 * @date 2020/11/23 13:12
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PermissionSuccess {
    int requestCode();
}
PermissionFail.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 安陽 QQ:15577969
 * @version 1.0
 * @team 美奇軟體開發工作室
 * @date 2020/11/23 13:12
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionFail {
    int requestCode();
}

4、建立OmgPermission.java物件類,這個類就是我們封裝的許可權框架主體,程式碼如下:

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.fragment.app.Fragment;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 動態許可權的物件
 * @author 安陽 QQ:15577969
 * @version 1.0
 * @team 美奇軟體開發工作室
 * @date 2020/11/23 12:56
 */
public class OmgPermission {
    //許可權集合
    private String[] mPermissions;
    //請求碼
    private int mRequestCode;
    //物件
    private Object object;
    //許可權回撥方法
    private static PermissionCallback permissionCallback;

    /**
     * 構造方法
     */
    private OmgPermission(Object object) {
        this.object = object;
    }

    /**
     *  with函式是將某物件作為函式的引數,在函式塊內可以通過 this 指代該物件。
     *  返回值為函式塊的最後一行或指定return表示式。
     */
    public static OmgPermission with(Activity activity){
        return new OmgPermission(activity);
    }
    public static OmgPermission with(Fragment fragment){
        return new OmgPermission(fragment);
    }

    /**
     * 獲取許可權組集合
   * @param permissions
     * @return
     */
    public OmgPermission permissions(String... permissions){
        this.mPermissions = permissions;
        return this;
    }

    /**
     * 新增請求碼
     * @param requestCode
     * @return
     */
    public OmgPermission addRequestCode(int requestCode){
        this.mRequestCode = requestCode;
        return this;
    }

    @TargetApi(value = Build.VERSION_CODES.M)
    public void request(){
        permissionCallback = null;
        requestPermissions(object, mRequestCode, mPermissions);
    }

    @TargetApi(value = Build.VERSION_CODES.M)
    public void request(PermissionCallback callback){
        if(callback!=null) {
            permissionCallback = callback;
        }
        requestPermissions(object, mRequestCode, mPermissions);
    }

    /**
     * 活動請求許可權
     * @param activity
     * @param requestCode
     * @param permissions
     */
    public static void needPermission(Activity activity, int requestCode, String[] permissions){
        permissionCallback = null;
        requestPermissions(activity, requestCode, permissions);
    }

    public static void needPermission(Activity activity, int requestCode, String permission){
        permissionCallback = null;
        needPermission(activity, requestCode, new String[] { permission });
    }

    /**
     * 活動請求許可權,帶回撥方法
     * @param activity
     * @param requestCode
     * @param permissions
     * @param callback
     */
    public static void needPermission(Activity activity, int requestCode, String[] permissions
            ,OmgPermission.PermissionCallback callback) {
        if (callback != null) {
            permissionCallback = callback;
        }
        requestPermissions(activity, requestCode, permissions);
    }

    public static void needPermission(Activity activity, int requestCode, String permission,PermissionCallback callback){
        if (callback != null) {
            permissionCallback = callback;
        }
        needPermission(activity, requestCode, new String[] { permission });
    }

    /**
     * 碎片請求許可權
     * @param fragment
     * @param requestCode
     * @param permissions
     */
    public static void needPermission(Fragment fragment, int requestCode, String[] permissions){
        permissionCallback = null;
        requestPermissions(fragment, requestCode, permissions);
    }

    public static void needPermission(Fragment fragment, int requestCode, String permission){
        permissionCallback = null;
        needPermission(fragment, requestCode, new String[] { permission });
    }

    /**
     * 碎片請求許可權,帶回撥方法
     * @param fragment
     * @param requestCode
     * @param permissions
     * @param callback
     */
    public static void needPermission(Fragment fragment, int requestCode, String[] permissions
            ,OmgPermission.PermissionCallback callback) {
        if (callback != null) {
            permissionCallback = callback;
        }
        requestPermissions(fragment, requestCode, permissions);
    }

    public static void needPermission(Fragment fragment, int requestCode, String permission,PermissionCallback callback){
        if (callback != null) {
            permissionCallback = callback;
        }
        needPermission(fragment, requestCode, new String[] { permission });
    }

    /**
     * 請求許可權
     * @param object
     * @param requestCode
     * @param permissions
     */
    @TargetApi(value = Build.VERSION_CODES.M)
    private static void requestPermissions(Object object, int requestCode, String[] permissions){
        //判斷系統版本是否大於6.0
        if(!PermissionUtils.judgeVersion()) {
            if (permissionCallback != null) {
                permissionCallback.permissionSuccess(requestCode);
            }else {
                doExecuteSuccess(object, requestCode);
            }
            return;
        }
        List<String> deniedPermissions = PermissionUtils.findDeniedPermissions(PermissionUtils.getActivity(object), permissions);

        /**
         * 先檢查是否有沒有授予的許可權,有的話請求,沒有的話就直接執行許可權授予成功的介面/註解方法
         */
        if(deniedPermissions.size() > 0){
            if(object instanceof Activity){
                ((Activity)object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode);
            } else if(object instanceof Fragment){
                ((Fragment)object).requestPermissions(deniedPermissions.toArray(new String[deniedPermissions.size()]), requestCode);
            } else {
                throw new IllegalArgumentException(object.getClass().getName() + " is not supported");
            }

        } else {
            if (permissionCallback != null) {
                permissionCallback.permissionSuccess(requestCode);
            }else {
                doExecuteSuccess(object, requestCode);
            }
        }
    }

    private static void doExecuteSuccess(Object activity, int requestCode) {
        Method executeMethod = PermissionUtils.findMethodWithRequestCode(activity.getClass(),
                PermissionSuccess.class, requestCode);

        executeMethod(activity, executeMethod);
    }

    private static void doExecuteFail(Object activity, int requestCode) {
        Method executeMethod = PermissionUtils.findMethodWithRequestCode(activity.getClass(),
                PermissionFail.class, requestCode);

        executeMethod(activity, executeMethod);
    }

    private static void executeMethod(Object activity, Method executeMethod) {
        if(executeMethod != null){
            try {
                if(!executeMethod.isAccessible()) executeMethod.setAccessible(true);
                executeMethod.invoke(activity, new  Object[]{});
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions,
                                                  int[] grantResults) {
        requestResult(activity, requestCode, permissions, grantResults);
    }

    public static void onRequestPermissionsResult(Fragment fragment, int requestCode, String[] permissions,
                                                  int[] grantResults) {
        requestResult(fragment, requestCode, permissions, grantResults);
    }

    /**
     * 回撥介面不為空的話,先執行回撥介面的方法,若為空,則尋找響應的註解方法。
     * @param obj
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    private static void requestResult(Object obj, int requestCode, String[] permissions,
                                      int[] grantResults){
        List<String> deniedPermissions = new ArrayList<>();
        for(int i=0; i<grantResults.length; i++){
            if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
                deniedPermissions.add(permissions[i]);
            }
        }

        if(deniedPermissions.size() > 0){
            if(permissionCallback!=null){
                permissionCallback.permissionFail(requestCode);
            }else {
                doExecuteFail(obj, requestCode);
            }
        } else {
            if(permissionCallback!=null){
                permissionCallback.permissionSuccess(requestCode);
            }else {
                doExecuteSuccess(obj, requestCode);
            }
        }
    }

    public interface PermissionCallback{
        //請求許可權成功
        void permissionSuccess(int requsetCode);

        //請求許可權失敗
        void permissionFail(int requestCode);
    }
}

四、本地呼叫許可權框架

1、新增依賴,在主專案的build.gradle檔案的dependencies{}配置裡,新增如下語句:

dependencies {
    //整合許可權請求框架
    implementation project(':library')
}

2、簡單示例用法:

public class MainActivity extends AppCompatActivity {
    //聯絡人請求碼
    private final int REQUEST_CONTACT = 100;
    //儲存請求碼
    private final int REQUEST_STORAGE = 200;
    //相機請求碼
    private final int REQUEST_CAMERA = 300;

    private Button storageButton;
    private Button cameraButton;
    @Override
    protected void onCreate(Bundle savedInstanceState)  {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**
         * 請求許可權
         * request()方法的引數可以有也可以沒有,有且不為空,就會回撥PermissionCallback的響應的回撥方法,沒有或為空,則回撥響應的註解方法。
         */
        OmgPermission.with(MainActivity.this)
                //新增請求碼
                .addRequestCode(REQUEST_CAMERA)
                //單獨申請一個許可權
                //.permissions(Manifest.permission.CAMERA)
                //同時申請多個許可權
                .permissions(Manifest.permission.READ_CONTACTS, Manifest.permission.RECEIVE_SMS, Manifest.permission.WRITE_CONTACTS)
                .request(new OmgPermission.PermissionCallback(){
            @Override
            public void permissionSuccess(int requestCode) {
                Toast.makeText(MainActivity.this, "成功授予聯絡人許可權,請求碼: " + requestCode, Toast.LENGTH_SHORT).show();
            }
            @Override
            public void permissionFail(int requestCode) {
                Toast.makeText(MainActivity.this, "授予聯絡人許可權失敗,請求碼: " + requestCode, Toast.LENGTH_SHORT).show();
            }
        });
    }
    /**
     * 回撥註解方法
     * 當request()沒有引數的時候,就會在當前類裡面尋找相應的註解方法
     */
    @PermissionSuccess(requestCode = REQUEST_STORAGE)
    public void permissionSuccess() {
        Toast.makeText(MainActivity.this, "回撥註解方法:成功授予讀寫許可權" , Toast.LENGTH_SHORT).show();
    }

    @PermissionFail(requestCode = REQUEST_STORAGE)
    public void permissionFail() {
        Toast.makeText(MainActivity.this, "回撥註解方法:授予讀寫許可權失敗" , Toast.LENGTH_SHORT).show();
    }

    @PermissionSuccess(requestCode = REQUEST_CONTACT)
    public void permissionSuccessContact() {
        Toast.makeText(MainActivity.this, "回撥註解方法:成功授予聯絡人許可權" , Toast.LENGTH_SHORT).show();
    }

    @PermissionFail(requestCode = REQUEST_CONTACT)
    public void permissionFailContact() {
        Toast.makeText(MainActivity.this, "回撥註解方法:授予聯絡人許可權失敗" , Toast.LENGTH_SHORT).show();
    }

    @PermissionSuccess(requestCode = REQUEST_CAMERA)
    public void permissionSuccessCamera() {
        Toast.makeText(MainActivity.this, "回撥註解方法:成功授予相機許可權" , Toast.LENGTH_SHORT).show();
    }

    @PermissionFail(requestCode = REQUEST_CAMERA)
    public void permissionFailCamera() {
        Toast.makeText(MainActivity.this, "回撥註解方法:授予相機許可權失敗" , Toast.LENGTH_SHORT).show();
    }
    /**
     * 申請許可權的系統回撥方法
     * @param requestCode
     * @param permissions
     * @param grantResults
    */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        OmgPermission.onRequestPermissionsResult(MainActivity.this, requestCode, permissions, grantResults);
    }
}

3、點選按鈕時,使用needPermission()方法動態申請許可權:


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    //聯絡人請求碼
    private final int REQUEST_CONTACT = 100;
    //儲存請求碼
    private final int REQUEST_STORAGE = 200;
    //相機請求碼
    private final int REQUEST_CAMERA = 300;

    private Button storageButton;
    private Button cameraButton;
    @Override
    protected void onCreate(Bundle savedInstanceState)  {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		//獲取控制元件
        storageButton=(Button) findViewById(R.id.storageButton);
        cameraButton=(Button) findViewById(R.id.cameraButton);
        //設定監聽
        storageButton.setOnClickListener(this);
        cameraButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            //申請儲存許可權按鈕
            case R.id.storageButton:
                /**
                 * 請求許可權
                 * 如果沒有callback作為引數,就會去呼叫響應的註解方法
                 */
                OmgPermission.needPermission(MainActivity.this, REQUEST_STORAGE, Permission.STORAGE);
                break;
            //申請相機許可權按鈕
            case R.id.cameraButton:
                /**
                 * 請求許可權
                 */
                OmgPermission.needPermission(MainActivity.this, REQUEST_CAMERA, Permission.CAMERA,new OmgPermission.PermissionCallback(){
                @Override
                public void permissionSuccess(int requestCode) {
                    Toast.makeText(MainActivity.this, "成功授予相機許可權", Toast.LENGTH_SHORT).show();
                }
                @Override
                public void permissionFail(int requestCode) {
                    Toast.makeText(MainActivity.this, "授予相機許可權失敗", Toast.LENGTH_SHORT).show();
                }
            });
                break;
        }
    }
}

五、釋出開源庫到 JitPack

JitPack的簡介:

JitPack實際上是一個自定義的Maven倉庫,不過它的流程極度簡化,只需要輸入Github專案地址就可釋出專案,大大方便了像我這種懶得配置環境的人。JitPack允許你把git 託管的專案(支援github和碼雲),輕鬆釋出到 jitpack的 maven 倉庫上,它所有內容都通過內容分發網路(CDN)使用加密 https 連線獲取!

1、在專案的build.gradle(project級別)檔案配置裡,新增 maven的地址和github外掛依賴:

buildscript {
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        //新增maven的github外掛
        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
    }
}
allprojects {
    repositories {
        google()
        jcenter()
        //maven地址
        maven { url "https://jitpack.io" }
    }
}

我這裡用的JitPack版本是2.0,因為的Gradle版本是3.5.2,對應的JitPack是2.0,如果你的Gradle版本比較高或者比較低,需要自己查詢JitPack對應的版本號

2、在 library模組的 build.gradle下 apply 外掛和新增 group分組:

apply plugin: 'com.android.library'
//----------------------maven外掛 start---------------------//
//apply maven外掛
apply plugin: 'com.github.dcendents.android-maven'
//定義github分組,這裡的respost改為你github的賬號名
group='com.github.respost'
//----------------------maven外掛 end ---------------------//
android {
}

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

不會使用github管理專案的小白,建議把我部落格裡的Git欄目的文章都學習一遍!

直達地址:https://blog.csdn.net/qq15577969/category_10239294.html

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

相關文章