我用玩AndroidApi写了一个sdk

 前言

相信很多同学都知道鸿神的WanAndroidapi,也写过很多酷炫的App,flutter、compose、kotlin、Java、小程序等各种版本,但是写过sdk的很少,sdk开发很常见,比如直播sdk、美颜sdk、统计sdk等等,本系列博客会有4-6篇,从sdk初始化、sdk开发、sdk合并、sdk文档编写等一步步慢慢讲解,看完之后,我相信各位同学都会开发属于自己的sdk.本篇是第一篇利用第三方库实现自己的sdk开发。

其实之前有写个2篇关于sdk开发的文章,有兴趣的同学可以去看看,博客地址如下:

Android SDK开发1将完整项目或Module打包成aar_u012556114的博客-CSDN博客

AndroidSDK开发2SDK初始化问题_u012556114的博客-CSDN博客_android sdk 初始化

思路:

1.封装一个初始化管理工具类便于交互.

2.根据需求封装相应的接口和请求,以接口形式给出请求参数和返回结果.

3.本篇采用依赖第三方库请求的方式来写sdk.

实现

一、sdk初始化:对内方便管理,对外提供一个接口或者方法

1.在Application中写一个设置值和返回的方法

public class App extends Application {

    private static Application mInstance;

    @Override

    public void onCreate() {

        super.onCreate();

        mInstance = this;

    }

    public static void setApp(Application app){

        mInstance =  app;

    }

    public static Application getInstance() {

        return  mInstance;

    }

}

2.封装一个初始化管理类:

/**

*@author: njb

*@date:  2021/2/23 17:11

*@desc:  交互工具类

*/

public class WanAndroidManager {

    var mContext: Context? = null

    fun init(application: Application){

        mContext =application.applicationContext

    }

}

二、网络请求: 

包含WanAndroidHttpUtil、api、BaseApi、APIService、WanAndroidHttpResult五个类.

1.封装一个网络请求工具类:WanAndroidHttpUtil,

可以看到这里的网络请求都是以接口形式回调出来.

/**

* @author: njb

* @date: 2021/2/23 17:55

* @desc: 网络请求工具类

*/

public class WanAndroidHttpUtil {

    public static void getBanner(final BannerCallBack callBack) {

        (Api.getDefault().banner()).enqueue(new Callback>>() {

            @Override

            public void onResponse(@NotNull Call>> call, @NotNull Response>> response) {

                WanAndroidHttpResult> result = response.body();

                if (result != null && result.isBizSucceed(true) && result.getData() != null) {

                    callBack.onResponse(result);

                }

            }

            @Override

            public void onFailure(@NotNull Call>> call, @NotNull Throwable t) {

                callBack.onFailure(t.getMessage());

            }

        });

    }

    public static void getArticle(int page, final ArticleCallBack callBack) {

        Api.getDefault().articleList(page).enqueue(new Callback>() {

            @Override

            public void onResponse(Call> call, Response> response) {

                WanAndroidHttpResult result = response.body();

                if (result != null && result.isBizSucceed(true) && result.getData() != null) {

                    callBack.onResponse(result);

                }

            }

            @Override

            public void onFailure(Call> call, Throwable t) {

                callBack.onFailure(t.getMessage());

            }

        });

    }

    public static void getHotKey(final HotKeyCallBack callBack){

        Api.getDefault().getHotKey().enqueue(new Callback>>() {

            @Override

            public void onResponse(@NotNull Call>> call, @NotNull Response>> response) {

                WanAndroidHttpResult> result  =response.body();

                if (result != null && result.isBizSucceed(true) && result.getData() != null) {

                    callBack.onResponse(result);

                }

            }

            @Override

            public void onFailure(@NotNull Call>> call, @NotNull Throwable t) {

                callBack.onFailure(t.getMessage());

            }

        });

    }

    public static void getKnwLedge(final KnowLedgeCallBack callBack){

        Api.getDefault().getKnowLedge().enqueue(new Callback>>() {

            @Override

            public void onResponse(@NotNull Call>> call, @NotNull Response>> response) {

                WanAndroidHttpResult> result  = response.body();

                if (result != null && result.isBizSucceed(true) && result.getData() != null) {

                    callBack.onResponse(result);

                }

            }

            @Override

            public void onFailure(@NotNull Call>> call, @NotNull Throwable t) {

                      callBack.onFailure(t.getMessage());

            }

        });

    }

    public interface BannerCallBack {

        BannerBean onResponse(WanAndroidHttpResult> beanEduHttpResult);

        BannerBean onFailure(String message);

    }

    public interface ArticleCallBack {

        ArticleListBean onResponse(WanAndroidHttpResult androidHttpResult);

        ArticleListBean onFailure(String message);

    }

    public interface HotKeyCallBack{

      HotKeyBean onResponse(WanAndroidHttpResult> androidHttpResult);

      HotKeyBean onFailure(String message);

    }

    public interface KnowLedgeCallBack{

        KnowledgeBean.DataBean onResponse(WanAndroidHttpResult> wanAndroidHttpResult);

        String onFailure(String message);

    }

}

2.Api:

public class Api extends BaseApi {

    private static ApiService SERVICE;

    public static ApiService getDefault() {

        if (SERVICE == null) {

            //获取请求客户端

            OkHttpClient.Builder httpClientBuilder = getHttpClient(Api.class.getSimpleName());

            SERVICE = new Retrofit.Builder()

                    .client(httpClientBuilder.build())

                    .addConverterFactory(ScalarsConverterFactory.create())

                    .addConverterFactory(GsonConverterFactory.create())

                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

                    .baseUrl(Constants.EasyPlayHostDefault)

                    .build().create(ApiService.class);

        }

        return SERVICE;

    }

}

3.BaseApi:

public class BaseApi {

    public static final int DEFAULT_TIMEOUT = 20000;//10秒

    protected static OkHttpClient.Builder getHttpClient(final String tagName) {

        OkHttpClient.Builder httpClientBuilder;

        //设置缓存路径,系统默认缓存路径,并且限制缓存大小500m

        Cache cache = new Cache(new File(Objects.requireNonNull(App.getInstance()).getCacheDir(), "HttpCache"), 500);

        httpClientBuilder = new OkHttpClient.Builder().cache(cache);

        try {

            httpClientBuilder.addNetworkInterceptor(new HeaderInterceptor());

            httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);

            httpClientBuilder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);

            httpClientBuilder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);

            httpClientBuilder.retryOnConnectionFailure(true);

            //根据当前调试状态,是否显示请求日志

            if (BuildConfig.DEBUG) {

                HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {

                    @Override

                    public void log(String message) {

                        LogUtils.e(tagName + "", message);

                    }

                });

                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

                httpClientBuilder.addInterceptor(interceptor);

                httpClientBuilder.addInterceptor(new CustomLoggingInterceptor());

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        return httpClientBuilder;

    }

    static class CustomLoggingInterceptor implements Interceptor {

        private String TAG = BaseApi.class.getSimpleName();

        @Override

        public Response intercept(Chain chain) throws IOException {

            Request request = chain.request();

            return chain.proceed(request);

        }

    }

}

4.ApiService:

/**

* @author: njb

* @date: 2021/2/24 18:04

* @desc:

*/

public interface ApiService {

    /**

    * 获取首页banner

    */

    @GET(Constants.BANNER_LIST)

    Call>> banner();

    /**

    * 获取文章列表

    * @param page

    * @return

    */

    @GET(Constants.ARTICLE_LIST)

    Call> articleList(@Path("page") int page);

    /**

    *获取搜索热词

    *

    *

    *

    */

    @GET(Constants.HOT_KEY)

    Call>> getHotKey();

    /**

    * 获取知识

    * @return

    */

    @GET(Constants.TREE)

    Call>> getKnowLedge();

}

5.WanAndroidHttpResult:请求结果类

/**

* @author: njb

* @date: 2021/2/23 17:32

* @desc:

*/

public class WanAndroidHttpResult {

    /**

    * 记录请求回来的状态描述

    */

    private String errorMsg;

    /**

    * 记录请求回来的错误状态描述

    */

    private String code = "";

    /**

    * 记录请求回来的错误状态描述

    */

    private Integer errorCode = 0;

    /**

    * 记录返回的数据

    */

    private T data;

    /**

    * 业务是否成功

    */

    public boolean isBizSucceed(boolean defaultValue) {

        return null == errorCode ? defaultValue : errorCode == 0;

    }

    public void setMessage(String message) {

        this.errorMsg = message;

    }

    public T getData() {

        return data;

    }

    public void setData(T data) {

        this.data = data;

    }

}

三、导入的第三方库:

//rxjava

implementation 'io.reactivex.rxjava2:rxjava:2.2.12'

implementation 'com.squareup.retrofit2:retrofit:2.6.2'

implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'

implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'

implementation 'com.squareup.retrofit2:converter-gson:2.6.2'

implementation 'com.squareup.okhttp3:okhttp:4.2.0'

implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'

implementation  'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2'

四:build.gradle和Manifest配置:

1.build,gradle配置:

//apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

apply plugin: 'com.android.library'

2.Manifest配置:

    android:allowBackup="true">

五、打包成aar,截图依次如下5-1、5-2、5-3:

第1步把build,gradle的

apply plugin: 'com.android.application改为apply plugin: 'com.android.library'

第2步把applicationId注释

第3步把Manifest里面application的theme、图标全部去掉,只保留

android:allowBackup="true"

第4步点开Studio右边的Gradle按钮,可以看到如下图的选项,选择assemable

第5步点开项目App的-----build------outputs----aar目录,看到生成的aar文件,有debug和release两个.

                                                                                            图5-1

                                                                                                            图5-2

                                                                                                               图5-3

如果有不会的或者看不明白的同学可以看我之前的博客,里面有详细步骤,这里就不展开讲解,把项目或者module打包成aar的博客地址如下:

Android SDK开发1将完整项目或Module打包成aar_u012556114的博客-CSDN博客

六、在新项目中的使用,这里新建一个项目WanAndroidSdkTest:

引入项目步骤如下:

1.把打包好的aar放到项目的libs目录下,这里命名为:wanandroidsdk_v1.0.0

 2.build.gradle配置如下:

完整配置代码:

plugins {

    id 'com.android.application'

    id 'kotlin-android'

}

android {

    compileSdkVersion 28

    buildToolsVersion "28.0.3"

    defaultConfig {

        applicationId "com.example.wanandroidsdktest"

        minSdkVersion 19

        targetSdkVersion 28

        versionCode 1

        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

    }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

        }

    }

    compileOptions {

        sourceCompatibility JavaVersion.VERSION_1_8

        targetCompatibility JavaVersion.VERSION_1_8

    }

    kotlinOptions {

        jvmTarget = '1.8'

    }

    repositories {

        //libs 目录

        flatDir {

            dirs "libs"

        }

    }

}

dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

    implementation 'androidx.core:core-ktx:1.6.0'

    implementation 'androidx.appcompat:appcompat:1.3.1'

    implementation 'com.google.android.material:material:1.4.0'

    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'

    testImplementation 'junit:junit:4.+'

    androidTestImplementation 'androidx.test.ext:junit:1.1.3'

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    //rxjava

    implementation 'io.reactivex.rxjava2:rxjava:2.2.12'

    implementation 'com.squareup.retrofit2:retrofit:2.6.2'

    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.0'

    implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'

    implementation 'com.squareup.retrofit2:converter-gson:2.6.2'

    implementation 'com.squareup.okhttp3:okhttp:4.2.0'

    implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'

    implementation  'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2'

    implementation(name: 'wanandroidsdk_v1.0.0', ext: 'aar')

}

3.sdk初始化:

private void initWanSdk() {

    App.setApp(MyApplication.getInstance());

}

4.调用首页banner、文章列表、搜索热词、知识列表接口:

private void initData() {

    //获取首页Banner

    getBanner();

    //获取文章列表

    initArticle();

    //获取热门关键字

    initHotKey();

    //获取知识列表

    initKnowledge();

}

private void getBanner() {

    WanAndroidHttpUtil.getBanner(new WanAndroidHttpUtil.BannerCallBack() {

        @Override

        public BannerBean onResponse(WanAndroidHttpResult> wanAndroidHttpResult) {

            LogUtils.d("--BannerData--", wanAndroidHttpResult.getData().toString());

            return null;

        }

        @Override

        public BannerBean onFailure(String message) {

            LogUtils.d("message", message);

            return null;

        }

    });

}

private void initArticle() {

    WanAndroidHttpUtil.getArticle(1, new WanAndroidHttpUtil.ArticleCallBack() {

        @Override

        public ArticleListBean onResponse(WanAndroidHttpResult wanAndroidHttpResult) {

            LogUtils.d("--ArticleData--", wanAndroidHttpResult.getData().toString());

            return null;

        }

        @Override

        public ArticleListBean onFailure(String message) {

            LogUtils.d("message", message);

            return null;

        }

    });

}

private void initHotKey() {

    WanAndroidHttpUtil.getHotKey(new WanAndroidHttpUtil.HotKeyCallBack() {

        @Override

        public HotKeyBean onResponse(WanAndroidHttpResult> wanAndroidHttpResult) {

            LogUtils.d("--hotData--", wanAndroidHttpResult.getData().toString());

            return null;

        }

        @Override

        public HotKeyBean onFailure(String message) {

            LogUtils.d("message", message);

            return null;

        }

    });

}

private void initKnowledge() {

    WanAndroidHttpUtil.getKnwLedge(new WanAndroidHttpUtil.KnowLedgeCallBack() {

        @Override

        public KnowledgeBean.DataBean onResponse(WanAndroidHttpResult> wanAndroidHttpResult) {

            LogUtils.d("--KnowData--", wanAndroidHttpResult.getData().toString());

            return null;

        }

        @Override

        public String onFailure(String message) {

            LogUtils.d("message", message);

            return null;

        }

    });

}

 测试结果如下,可以看到结果正常返回,打印出想要的数据:

七、总结一下:

本篇文章其实去年就写好了,只是不知道以啥样的形式展现出来,再加上工作原因,而我本人又变懒惰了,文章的构思和排版不是很好,所以最近才发布,花费了近3个多小时终于是完成了。

这里sdk开发首先是初始化,然后是接口设计,打包成aar,当然还有文档编写,sdk加密,sdk中aar的合并,本文是这系列的第一篇,小伙伴可以直接尝试一下,里面的代码不重要,这里都是写的很粗糙,由于是演示demo,大家可以根据自己的习惯来写,主要学习一下思想和怎么写成一个sdk的过程,这里也没有把aar放到远程仓库,直接本地引用的,有兴趣的同学可以放到自己的远程仓库,本文肯定有很多不足之处,希望大家谅解,有问题提出来我及时更正,一起学习进步.

wanandroidsdkdemo的源码地址如下:

WanAndroidSdk: 利用鸿神的wanAndroid开源APi封装的wanAndroidsdk,可以快速调用

我的csdn地址:

https://blog.csdn.net/u012556114

原创不易,如需转载请说明出处!!

你可能感兴趣的:(我用玩AndroidApi写了一个sdk)