diff --git a/app/build.gradle b/app/build.gradle index 2b8760ac..d9aef303 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -52,6 +52,11 @@ android { viewBinding true } + packagingOptions { + exclude 'META-INF/DEPENDENCIES' + exclude "META-INF/*.kotlin_module" + } + // To inline the bytecode built with JVM target 1.8 into // bytecode that is being built with JVM target 1.6. (e.g. navArgs) @@ -101,6 +106,7 @@ dependencies { implementation project(':core-presentation') implementation project(":core-ui") + implementation project(':library-network') // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" diff --git a/library-network/.gitignore b/library-network/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/library-network/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/library-network/build.gradle b/library-network/build.gradle new file mode 100644 index 00000000..a2113814 --- /dev/null +++ b/library-network/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'com.android.library' + id 'kotlin-android' +} + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.2" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + 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' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'androidx.core:core-ktx:1.3.2' + + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation "com.squareup.retrofit2:converter-moshi:2.9.0" + + implementation "com.squareup.moshi:moshi-kotlin:1.11.0" + implementation "com.squareup.moshi:moshi-kotlin-codegen:1.11.0" + implementation "com.squareup.moshi:moshi-adapters:1.11.0" + + + + implementation "com.squareup.okhttp3:logging-interceptor:4.9.0" + + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1" + + implementation "org.koin:koin-android:2.2.1" + implementation "org.koin:koin-android-viewmodel:2.2.1" + implementation "org.koin:koin-android-ext:2.2.1" +} \ No newline at end of file diff --git a/library-network/src/main/AndroidManifest.xml b/library-network/src/main/AndroidManifest.xml new file mode 100644 index 00000000..492aa7ff --- /dev/null +++ b/library-network/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt b/library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt new file mode 100644 index 00000000..c3d177c9 --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt @@ -0,0 +1,48 @@ +package com.vanced.manager.library.network.di + +import com.vanced.manager.library.network.okhttp.interceptors.LOG_INTERCEPTOR +import com.vanced.manager.library.network.okhttp.interceptors.NO_CONNECT_INTERCEPTOR +import com.vanced.manager.library.network.okhttp.interceptors.loggingInterceptor +import com.vanced.manager.library.network.okhttp.interceptors.noConnectionInterceptor +import com.vanced.manager.library.network.providers.provideMoshi +import com.vanced.manager.library.network.providers.provideOkHttpClient +import com.vanced.manager.library.network.providers.provideRetrofit +import org.koin.android.BuildConfig +import org.koin.android.ext.koin.androidContext +import org.koin.core.qualifier.named +import org.koin.dsl.module + + +const val ORIGINAL = "ORIGINAL" + +val NetworkModule = module { + factory(named(LOG_INTERCEPTOR)) { loggingInterceptor() } + factory(named(NO_CONNECT_INTERCEPTOR)) { noConnectionInterceptor(androidContext()) } + + factory(named(ORIGINAL)) { + if (BuildConfig.DEBUG) { + provideOkHttpClient( + interceptors = listOf( + get(named(LOG_INTERCEPTOR)), + get(named(NO_CONNECT_INTERCEPTOR)) + ) + ) + } else { + provideOkHttpClient( + interceptors = listOf( + get(named(NO_CONNECT_INTERCEPTOR)) + ) + ) + } + } + + factory { provideMoshi() } + + factory(named(ORIGINAL)) { + provideRetrofit( + moshi = get(), + okHttpClient = get(named(ORIGINAL)), + url = "https://www.haliksar.fun" + ) + } +} \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt b/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt new file mode 100644 index 00000000..adb21f39 --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt @@ -0,0 +1,10 @@ +package com.vanced.manager.library.network.okhttp.interceptors + +import okhttp3.Interceptor +import okhttp3.logging.HttpLoggingInterceptor +import okhttp3.logging.HttpLoggingInterceptor.Level + +const val LOG_INTERCEPTOR = "LOG_INTERCEPTOR" + +internal fun loggingInterceptor(): Interceptor = + HttpLoggingInterceptor().setLevel(Level.BODY) \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt b/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt new file mode 100644 index 00000000..125a4457 --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt @@ -0,0 +1,42 @@ +package com.vanced.manager.library.network.okhttp.interceptors + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import android.os.Build +import okhttp3.Interceptor + +class NoConnectException : Exception() + +const val NO_CONNECT_INTERCEPTOR = "NO_CONNECT_INTERCEPTOR" + +internal fun noConnectionInterceptor(context: Context) = Interceptor { chain -> + if (!isInternetAvailable(context)) { + throw NoConnectException() + } else { + chain.proceed(chain.request()) + } +} + +@Suppress("DEPRECATION") +private fun isInternetAvailable(context: Context): Boolean { + with(context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager) { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val networkCapabilities = activeNetwork ?: return false + val actNw = getNetworkCapabilities(networkCapabilities) ?: return false + when { + actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true + actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true + actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true + else -> false + } + } else { + when (activeNetworkInfo?.type) { + ConnectivityManager.TYPE_WIFI -> true + ConnectivityManager.TYPE_MOBILE -> true + ConnectivityManager.TYPE_ETHERNET -> true + else -> false + } + } + } +} \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt new file mode 100644 index 00000000..291b2d25 --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.library.network.providers + +import com.squareup.moshi.Moshi +import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory +import java.util.* + +internal fun provideMoshi(): Moshi = Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .add(Date::class.java, Rfc3339DateJsonAdapter().nullSafe()) + .build() \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt new file mode 100644 index 00000000..80e0b7ce --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt @@ -0,0 +1,24 @@ +package com.vanced.manager.library.network.providers + +import okhttp3.Authenticator +import okhttp3.Interceptor +import okhttp3.OkHttpClient +import java.util.concurrent.TimeUnit + +private const val WaitTime = 0L +private const val ConnTime = 0L + +fun provideOkHttpClient( + interceptors: List = emptyList(), + authenticators: List = emptyList() +): OkHttpClient = + OkHttpClient.Builder() + .callTimeout(WaitTime, TimeUnit.SECONDS) + .readTimeout(WaitTime, TimeUnit.MILLISECONDS) + .connectTimeout(ConnTime, TimeUnit.MILLISECONDS) + .writeTimeout(WaitTime, TimeUnit.MILLISECONDS) + .apply { + interceptors.forEach { addInterceptor(it) } + authenticators.forEach { authenticator(it) } + } + .build() \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt new file mode 100644 index 00000000..6ecccda4 --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.library.network.providers + +import com.squareup.moshi.Moshi +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.moshi.MoshiConverterFactory + +fun provideRetrofit( + okHttpClient: OkHttpClient, + moshi: Moshi, + url: String +): Retrofit = Retrofit.Builder() + .addConverterFactory(MoshiConverterFactory.create(moshi)) + .client(okHttpClient) + .baseUrl(url) + .build() \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt b/library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt new file mode 100644 index 00000000..1dcb43ba --- /dev/null +++ b/library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.library.network.service + +import retrofit2.Retrofit + +inline fun createRetrofitService(retrofit: Retrofit): T = + retrofit.create(T::class.java) \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 4a0a39a7..fb3a2764 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,8 @@ rootProject.name='Vanced Manager' include ':app' -include ':core-presentation' -include ':core-ui' +include ':core-presentation', ':core-ui' -include ':feature-home' \ No newline at end of file +include ':feature-home' + +include ':library-network'