diff --git a/app/build.gradle b/app/build.gradle index 9fbfb0a..667fb79 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,17 +1,19 @@ plugins { id 'com.android.application' + id 'kotlin-android' + id 'kotlin-android-extensions' + id 'kotlin-kapt' } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" + compileSdkVersion rootProject.ext.android.compileSdkVersion + buildToolsVersion rootProject.ext.android.buildToolsVersion defaultConfig { - applicationId "com.yinuo.commonlibtest" - minSdkVersion 23 - targetSdkVersion 30 - versionCode 1 - versionName "1.0" + minSdkVersion rootProject.ext.android.minSdkVersion + targetSdkVersion rootProject.ext.android.targetSdkVersion + versionCode rootProject.ext.android.versionCode + versionName rootProject.ext.android.versionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -26,6 +28,14 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + dataBinding { + enabled = true + } + + viewBinding { + enabled = true + } } dependencies { @@ -34,7 +44,4 @@ dependencies { implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.1' implementation project(path: ':commonLib') - testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } \ No newline at end of file diff --git a/app/src/androidTest/java/com/yinuo/commonlibtest/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/yinuo/commonlibtest/ExampleInstrumentedTest.java deleted file mode 100644 index 82e98bd..0000000 --- a/app/src/androidTest/java/com/yinuo/commonlibtest/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.yinuo.commonlibtest; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - assertEquals("com.yinuo.commonlibtest", appContext.getPackageName()); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java b/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java index f3ade52..f8320a4 100644 --- a/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java +++ b/app/src/main/java/com/yinuo/commonlibtest/MainActivity.java @@ -4,11 +4,14 @@ import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; +import com.yinuo.commonlibtest.databinding.ActivityMainBinding; + public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); + ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); } } \ No newline at end of file diff --git a/app/src/test/java/com/yinuo/commonlibtest/ExampleUnitTest.java b/app/src/test/java/com/yinuo/commonlibtest/ExampleUnitTest.java deleted file mode 100644 index cf66f31..0000000 --- a/app/src/test/java/com/yinuo/commonlibtest/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.yinuo.commonlibtest; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/commonLib/build.gradle b/commonLib/build.gradle index 07004a9..060c04b 100644 --- a/commonLib/build.gradle +++ b/commonLib/build.gradle @@ -23,16 +23,23 @@ android { debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + buildConfigField 'String', 'BASE_URL_CONFIG_PATH', '"baseUrl.properties"' } release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + buildConfigField 'String', 'BASE_URL_CONFIG_PATH', '"baseUrl.properties"' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + androidExtensions { + // kotlin序列化 + experimental = true + } } dependencies { @@ -47,6 +54,18 @@ dependencies { // 添加kotlin依赖 implementation rootProject.ext.dependencies.kotlin implementation rootProject.ext.dependencies.kotlin_android + // 添加okhttp依赖 + implementation rootProject.ext.dependencies.okhttp + // 添加retrofit依赖 + implementation rootProject.ext.dependencies.retrofit + // 添加retrofit转化gson能力依赖 + implementation rootProject.ext.dependencies.converter_gson + // 添加rxjava依赖 + implementation rootProject.ext.dependencies.rxjava + // 添加rxAndroid依赖 + implementation rootProject.ext.dependencies.rxandroid + // 添加retrofit和rxjava适配器 + implementation rootProject.ext.dependencies.retrofit_rxjava //luban图片压缩 implementation rootProject.ext.dependencies.luban diff --git a/commonLib/src/main/assets/baseUrl.properties b/commonLib/src/main/assets/baseUrl.properties new file mode 100644 index 0000000..8f9b83a --- /dev/null +++ b/commonLib/src/main/assets/baseUrl.properties @@ -0,0 +1,2 @@ +debug1 = https://www.wanandroid.com +debug2 = https://www.baidu.com diff --git a/commonLib/src/main/java/com/yinuo/commonlib/CommonApplication.kt b/commonLib/src/main/java/com/yinuo/commonlib/CommonApplication.kt new file mode 100644 index 0000000..7fc9f2e --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/CommonApplication.kt @@ -0,0 +1,17 @@ +package com.yinuo.commonlib + +import android.annotation.SuppressLint +import android.content.Context + +@SuppressLint("StaticFieldLeak") +object CommonApplication { + private var commonContext: Context? = null + + fun intLibs(context: Context) { + commonContext = context + } + + fun getContext(): Context? { + return commonContext + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/BaseObserve.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/BaseObserve.kt new file mode 100644 index 0000000..1eda43a --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/BaseObserve.kt @@ -0,0 +1,98 @@ +package com.common.commonlib.net + +import android.net.ParseException +import android.util.Log +import com.google.gson.JsonParseException +import io.reactivex.Observable +import io.reactivex.Observer +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.Disposable +import io.reactivex.schedulers.Schedulers +import org.json.JSONException +import retrofit2.HttpException +import java.net.ConnectException +import java.net.SocketTimeoutException +import java.net.UnknownHostException +import javax.net.ssl.SSLHandshakeException + +/** + * 请求基类 + */ +open class BaseObserve { + /** + * 初始化服务类 + */ + fun initService(clazz: Class): T { + return RequestManager.INSTANCE.create(clazz) + } + + /** + * 调用接口 + * @param observable 可订阅 + * @param callBack 请求回调 + */ + fun observe(observable: Observable, callBack: RequestCallBack?) { + observable + .subscribeOn(Schedulers.io()) + .unsubscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Observer { + override fun onSubscribe(d: Disposable) { + } + + override fun onNext(t: R) { + callBack?.onResult(t) + } + + override fun onError(e: Throwable) { + e.message?.let { Log.e(TAG, it) } + callBack?.onError(dealError(e)) + } + + override fun onComplete() { + callBack?.onComplete() + } + }) + } + + /** + * 处理错误 + * @param e 异常 + */ + private fun dealError(e: Throwable): String? { + if (e is HttpException) { + return when (e.code()) { + UNAUTHORIZED -> "登录验证过期" + INTERNAL_SERVER_ERROR -> "服务器错误" + FORBIDDEN, NOT_FOUND -> "无效的请求" + REQUEST_TIMEOUT, GATEWAY_TIMEOUT, BAD_GATEWAY, SERVICE_UNAVAILABLE -> e.message() + else -> e.message() + } + } else if (e is ConnectException) { + return "网络连接异常,请检查您的网络状态" + } else if (e is SocketTimeoutException) { + return "网络连接超时,请检查您的网络状态,稍后重试" + } else if (e is UnknownHostException) { + return "网络异常,请检查您的网络状态" + } else if (e is JsonParseException || e is JSONException || e is ParseException) { + return "数据解析错误" + } else if (e is SSLHandshakeException) { + return "网络异常,请检查您的网络状态" + } else if (e is RuntimeException) { + return "运行时异常" + } + return e.message + } + + companion object { + const val TAG: String = "BaseLoader" + const val UNAUTHORIZED = 401 + const val FORBIDDEN = 403 + const val NOT_FOUND = 404 + const val REQUEST_TIMEOUT = 408 + const val INTERNAL_SERVER_ERROR = 500 + const val BAD_GATEWAY = 502 + const val SERVICE_UNAVAILABLE = 503 + const val GATEWAY_TIMEOUT = 504 + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/RequestCallBack.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/RequestCallBack.kt new file mode 100644 index 0000000..4f290af --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/RequestCallBack.kt @@ -0,0 +1,10 @@ +package com.common.commonlib.net + +/** + * 请求回调 + */ +interface RequestCallBack { + fun onResult(result: T) + fun onError(error: String?) + fun onComplete() +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/RequestManager.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/RequestManager.kt new file mode 100644 index 0000000..a4ea8a0 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/RequestManager.kt @@ -0,0 +1,51 @@ +package com.common.commonlib.net + +import com.yinuo.commonlib.net.interceptor.BaseUrlInterceptor +import com.yinuo.commonlib.net.interceptor.HttpCommonInterceptor +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit + +/** + * 网络请求管理器 + */ +enum class RequestManager { + INSTANCE; + + /** + * 默认超时时间 + */ + private val defaultTimeOut: Long = 5 + + /** + * 默认读取超时时间 + */ + private val defaultReadTimeOut: Long = 10 + + private var mRetrofit: Retrofit? = null + + init { + val builder: OkHttpClient.Builder = OkHttpClient.Builder() + builder.connectTimeout(defaultTimeOut, TimeUnit.SECONDS) + builder.readTimeout(defaultReadTimeOut, TimeUnit.SECONDS) + val commonInterceptor: HttpCommonInterceptor = HttpCommonInterceptor.Builder().build() + builder.addInterceptor(commonInterceptor) + builder.addInterceptor(BaseUrlInterceptor()) + + mRetrofit = Retrofit.Builder() + .client(builder.build()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl("https://www.wanandroid.com") + .build() + } + + /** + * 创建service + */ + fun create(service: Class): T { + return mRetrofit!!.create(service) + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/bean/BaseResponse.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/bean/BaseResponse.kt new file mode 100644 index 0000000..f5d894d --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/bean/BaseResponse.kt @@ -0,0 +1,21 @@ +package com.yinuo.commonlib.net.bean + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize + +/** + * 基础响应类 + */ +@Parcelize +open class BaseResponse : Parcelable { + var errorCode: Int = 0 + var errorMessage: String = "" + + fun getMErrorCode(): Int { + return errorCode + } + + fun getMErrorMessage(): String { + return errorMessage + } +} diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/bean/RequestParam.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/bean/RequestParam.kt new file mode 100644 index 0000000..b81cf00 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/bean/RequestParam.kt @@ -0,0 +1,9 @@ +package com.yinuo.commonlib.net.bean + +/** + * 请求参数 + */ +data class RequestParam(var baseUrl: String) { + var params: Map? = null +} + diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/interceptor/BaseUrlInterceptor.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/interceptor/BaseUrlInterceptor.kt new file mode 100644 index 0000000..95d1640 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/interceptor/BaseUrlInterceptor.kt @@ -0,0 +1,83 @@ +package com.yinuo.commonlib.net.interceptor + +import android.text.TextUtils +import android.util.Log +import com.yinuo.commonlib.BuildConfig +import com.yinuo.commonlib.CommonApplication +import okhttp3.HttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.Interceptor +import okhttp3.Request +import okhttp3.Response +import java.io.BufferedInputStream +import java.util.* + +/** + * BaseUrl链接拦截器 + */ +class BaseUrlInterceptor : Interceptor { + /** + * 拦截替换BaseUrl + */ + override fun intercept(chain: Interceptor.Chain): Response { + val oldRequest: Request = chain.request() + val requestBuilder: Request.Builder = oldRequest.newBuilder() + val headKey = BASE_URL_KEY + val headValue: String? = oldRequest.header(headKey) + // 判断是否需要替换BaseUrl,不需要则直接跳转 + if (TextUtils.isEmpty(headValue)) { + return chain.proceed(chain.request()) + } + // 该HEAD只用于替换BaseUrl,将对应的自定义HEAD去除 + requestBuilder.removeHeader(headKey) + // 尝试获取新BaseUrl + val newUrlValue = getValueFromProperties(headValue) + val newBaseUrl: HttpUrl? = newUrlValue.toHttpUrlOrNull() + // 获取到新BaseUrl进行替换 + return if (newBaseUrl != null) { + val oldHttpUrl: HttpUrl = oldRequest.url + val newUrl = oldHttpUrl.newBuilder() + .scheme(newBaseUrl.scheme) + .host(newBaseUrl.host) + .port(newBaseUrl.port) + .build() + chain.proceed(requestBuilder.url(newUrl).build()) + } else { + chain.proceed(chain.request()) + } + } + + /** + * 通过KEY从配置文件中获取值 + */ + private fun getValueFromProperties(key: String?): String { + val prop = Properties() + var value = "" + try { + val context = CommonApplication.getContext() + if (context == null) { + Log.e(TAG, "got context null, please init context!") + return value + } + val mAssets = context.assets + if (mAssets == null) { + Log.e(TAG, "got assets null, please check the assets folder") + } + // 通过输入缓冲流进行读取配置文件 + val inputStream = + BufferedInputStream(mAssets.open((BuildConfig.BASE_URL_CONFIG_PATH))) + // 加载输入流 + prop.load(inputStream) + // 根据关键字获取value值 + value = prop.getProperty(key); + } catch (e: Exception) { + Log.e(TAG, e.toString()) + } + return value + } + + companion object { + const val TAG = "BaseUrlInterceptor" + const val BASE_URL_KEY = "baseurl" + } +} \ No newline at end of file diff --git a/commonLib/src/main/java/com/yinuo/commonlib/net/interceptor/HttpCommonInterceptor.kt b/commonLib/src/main/java/com/yinuo/commonlib/net/interceptor/HttpCommonInterceptor.kt new file mode 100644 index 0000000..b4d40a0 --- /dev/null +++ b/commonLib/src/main/java/com/yinuo/commonlib/net/interceptor/HttpCommonInterceptor.kt @@ -0,0 +1,70 @@ +package com.yinuo.commonlib.net.interceptor + +import okhttp3.Interceptor +import okhttp3.Request +import okhttp3.Response + +/** + * 公共请求拦截器 + */ +class HttpCommonInterceptor : Interceptor { + /** + * 请求头部参数 + */ + var mHeaderHashMap: HashMap? = null + + /** + * 拦截请求并添加参数 + */ + override fun intercept(chain: Interceptor.Chain): Response { + val oldRequest: Request = chain.request() + val requestBuilder: Request.Builder = oldRequest.newBuilder() + requestBuilder.method(oldRequest.method, oldRequest.body) + if (mHeaderHashMap != null && mHeaderHashMap!!.size > 0) { + for (item: Map.Entry in mHeaderHashMap!!.entries) { + requestBuilder.addHeader(item.key, item.value) + } + } + return chain.proceed(requestBuilder.build()) + } + + /** + * builder构造函数 + */ + class Builder { + private var mHttpCommonInterceptor: HttpCommonInterceptor? = null + + init { + mHttpCommonInterceptor = HttpCommonInterceptor() + } + + fun addHeadParams(key: String, value: String): Builder { + mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value) + return this + } + + fun addHeadParams(key: String, value: Int): Builder { + mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString()) + return this + } + + fun addHeadParams(key: String, value: Long): Builder { + mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString()) + return this + } + + fun addHeadParams(key: String, value: Float): Builder { + mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString()) + return this + } + + fun addHeadParams(key: String, value: Double): Builder { + mHttpCommonInterceptor?.mHeaderHashMap?.set(key, value.toString()) + return this + } + + fun build(): HttpCommonInterceptor { + return mHttpCommonInterceptor!! + } + } +} \ No newline at end of file diff --git a/yinuoapp.jks b/yinuoapp.jks new file mode 100644 index 0000000..3ddd979 Binary files /dev/null and b/yinuoapp.jks differ