diff --git a/app/build.gradle b/app/build.gradle
index d24b0bc..1df045c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,7 +1,7 @@
plugins {
id "com.android.application"
id "kotlin-android"
- id "kotlin-kapt"
+// id "kotlin-kapt"
}
try {
apply from: 'signing.config.gradle'
@@ -14,12 +14,12 @@ try {
}
android {
- compileSdkVersion 31
+ compileSdk 35
defaultConfig {
applicationId "org.fnives.tiktokdownloader"
minSdkVersion 23
- targetSdkVersion 33
+ targetSdkVersion 35
versionCode 2
versionName "1.3.1"
@@ -43,21 +43,18 @@ android {
}
release {
signingConfig signingConfigs.release
- debuggable true
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
+ buildFeatures.buildConfig = true
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
- jvmTarget = "1.8"
- }
- lintOptions {
- abortOnError true
+ jvmTarget = "17"
}
testOptions.unitTests {
@@ -71,53 +68,57 @@ android {
}
}
}
-}
-
-tasks.configureEach { task ->
- if (task.taskIdentity.type.toString() == "class org.jetbrains.kotlin.gradle.tasks.KotlinCompile") {
- task.kotlinOptions {
- freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
- }
+ namespace 'org.fnives.tiktokdownloader'
+ lint {
+ abortOnError true
}
}
+//tasks.configureEach { task ->
+// if (task.taskIdentity.type.toString() == "class org.jetbrains.kotlin.gradle.tasks.KotlinCompile") {
+// task.kotlinOptions {
+// freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
+// }
+// }
+//}
+
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation "androidx.core:core-ktx:1.7.0"
- implementation "androidx.appcompat:appcompat:1.4.1"
- implementation "androidx.activity:activity-ktx:1.4.0"
- implementation "androidx.fragment:fragment-ktx:1.4.1"
- implementation "com.google.android.material:material:1.5.0"
- implementation "androidx.constraintlayout:constraintlayout:2.1.3"
+ implementation "androidx.core:core-ktx:1.16.0"
+ implementation "androidx.appcompat:appcompat:1.7.0"
+ implementation "androidx.activity:activity-ktx:1.10.1"
+ implementation "androidx.fragment:fragment-ktx:1.8.6"
+ implementation "com.google.android.material:material:1.12.0"
+ implementation "androidx.constraintlayout:constraintlayout:2.2.1"
// Coroutines
- def coroutine_version = "1.6.0"
+ def coroutine_version = "1.7.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
- implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
- implementation "androidx.fragment:fragment-ktx:1.4.1"
+ implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.0"
+ implementation "androidx.fragment:fragment-ktx:1.8.6"
- def glide_version = "4.11.0"
+ def glide_version = "4.15.1"
implementation "com.github.bumptech.glide:glide:$glide_version"
- kapt "com.github.bumptech.glide:compiler:$glide_version"
+// kapt "com.github.bumptech.glide:compiler:$glide_version"
- def okhttp_version = "4.9.3"
+ def okhttp_version = "4.12.0"
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version"
implementation 'com.pierfrancescosoffritti.androidyoutubeplayer:core:11.0.1'
- def junit_version = "5.7.0"
+ def junit_version = "5.8.2"
testImplementation "org.junit.jupiter:junit-jupiter-engine:$junit_version"
testImplementation "org.junit.jupiter:junit-jupiter-params:$junit_version"
testImplementation 'com.jraska.livedata:testing-ktx:1.2.0'
testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
testImplementation "com.squareup.okhttp3:mockwebserver:$okhttp_version"
- testImplementation "commons-io:commons-io:2.8.0"
+ testImplementation "commons-io:commons-io:2.13.0"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutine_version"
- testImplementation "androidx.arch.core:core-testing:2.1.0"
+ testImplementation "androidx.arch.core:core-testing:2.2.0"
- androidTestImplementation "androidx.test.ext:junit:1.1.3"
- androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
+ androidTestImplementation "androidx.test.ext:junit:1.2.1"
+ androidTestImplementation "androidx.test.espresso:espresso-core:3.6.1"
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 184b431..196f425 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,7 +1,6 @@
+ xmlns:tools="http://schemas.android.com/tools">
+
-
+
\ No newline at end of file
diff --git a/app/src/main/java/org/fnives/tiktokdownloader/di/ServiceLocator.kt b/app/src/main/java/org/fnives/tiktokdownloader/di/ServiceLocator.kt
index c14ead4..8b63348 100644
--- a/app/src/main/java/org/fnives/tiktokdownloader/di/ServiceLocator.kt
+++ b/app/src/main/java/org/fnives/tiktokdownloader/di/ServiceLocator.kt
@@ -1,9 +1,7 @@
package org.fnives.tiktokdownloader.di
import android.content.Context
-import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
-import androidx.savedstate.SavedStateRegistryOwner
import org.fnives.tiktokdownloader.di.module.AndroidFileManagementModule
import org.fnives.tiktokdownloader.di.module.LocalSourceModule
import org.fnives.tiktokdownloader.di.module.NetworkModule
@@ -29,18 +27,16 @@ object ServiceLocator {
val useCaseModule: UseCaseModule
get() = _useCaseModule ?: throw IllegalStateException("$this.start has not been called!")
- fun viewModelFactory(
- savedStateRegistryOwner: SavedStateRegistryOwner,
- defaultArgs: Bundle
- ): ViewModelProvider.Factory =
- ViewModelFactory(savedStateRegistryOwner, defaultArgs, viewModelModule)
+ fun viewModelFactory(): ViewModelProvider.Factory =
+ ViewModelFactory(viewModelModule)
val queueServiceViewModel: QueueServiceViewModel
get() = viewModelModule.queueServiceViewModel
fun start(context: Context) {
val androidFileManagementModule = AndroidFileManagementModule(context)
- val localSourceModule = LocalSourceModule(androidFileManagementModule = androidFileManagementModule)
+ val localSourceModule =
+ LocalSourceModule(androidFileManagementModule = androidFileManagementModule)
val networkModule = NetworkModule(delayBeforeRequest = DEFAULT_DELAY_BEFORE_REQUEST)
val useCaseModule = UseCaseModule(
localSourceModule = localSourceModule,
diff --git a/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelDelegate.kt b/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelDelegate.kt
index 9372632..7a011ab 100644
--- a/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelDelegate.kt
+++ b/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelDelegate.kt
@@ -1,6 +1,5 @@
package org.fnives.tiktokdownloader.di
-import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
@@ -10,17 +9,13 @@ inline fun ComponentActivity.provideViewModels() =
ViewModelLazy(
viewModelClass = VM::class,
storeProducer = { viewModelStore },
- factoryProducer = { createViewModelFactory() }
+ factoryProducer = { ServiceLocator.viewModelFactory() },
+ extrasProducer = { defaultViewModelCreationExtras }
)
inline fun Fragment.provideViewModels() =
ViewModelLazy(
viewModelClass = VM::class,
storeProducer = { viewModelStore },
- factoryProducer = { createViewModelFactory() })
-
-fun ComponentActivity.createViewModelFactory() =
- ServiceLocator.viewModelFactory(this, intent?.extras ?: Bundle.EMPTY)
-
-fun Fragment.createViewModelFactory() =
- ServiceLocator.viewModelFactory(this, arguments ?: Bundle.EMPTY)
\ No newline at end of file
+ factoryProducer = { ServiceLocator.viewModelFactory() },
+ extrasProducer = { defaultViewModelCreationExtras })
\ No newline at end of file
diff --git a/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelFactory.kt b/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelFactory.kt
index 7fad4a6..0276d87 100644
--- a/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelFactory.kt
+++ b/app/src/main/java/org/fnives/tiktokdownloader/di/ViewModelFactory.kt
@@ -1,29 +1,34 @@
package org.fnives.tiktokdownloader.di
-import android.os.Bundle
-import androidx.lifecycle.AbstractSavedStateViewModelFactory
-import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
-import androidx.savedstate.SavedStateRegistryOwner
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.createSavedStateHandle
+import androidx.lifecycle.viewmodel.CreationExtras
import org.fnives.tiktokdownloader.di.module.ViewModelModule
import org.fnives.tiktokdownloader.ui.main.MainViewModel
import org.fnives.tiktokdownloader.ui.main.queue.QueueViewModel
import org.fnives.tiktokdownloader.ui.main.settings.SettingsViewModel
class ViewModelFactory(
- savedStateRegistryOwner: SavedStateRegistryOwner,
- defaultArgs: Bundle,
private val viewModelModule: ViewModelModule,
-) : AbstractSavedStateViewModelFactory(savedStateRegistryOwner, defaultArgs) {
+) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
- override fun create(key: String, modelClass: Class, handle: SavedStateHandle): T {
+ override fun create(modelClass: Class): T {
val viewModel = when (modelClass) {
- MainViewModel::class.java -> viewModelModule.mainViewModel(handle)
QueueViewModel::class.java -> viewModelModule.queueViewModel
SettingsViewModel::class.java -> viewModelModule.settignsViewModel
else -> throw IllegalArgumentException("Can't create viewModel for $modelClass ")
}
return viewModel as T
}
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class, extras: CreationExtras): T {
+ val viewModel = when (modelClass) {
+ MainViewModel::class.java -> viewModelModule.mainViewModel(extras.createSavedStateHandle())
+ else -> create(modelClass)
+ }
+ return viewModel as T
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/fnives/tiktokdownloader/ui/service/QueueService.kt b/app/src/main/java/org/fnives/tiktokdownloader/ui/service/QueueService.kt
index abaebbe..eff635f 100644
--- a/app/src/main/java/org/fnives/tiktokdownloader/ui/service/QueueService.kt
+++ b/app/src/main/java/org/fnives/tiktokdownloader/ui/service/QueueService.kt
@@ -1,5 +1,6 @@
package org.fnives.tiktokdownloader.ui.service
+import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
@@ -32,6 +33,7 @@ class QueueService : Service() {
}
}
+ @SuppressLint("ForegroundServiceType")
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
intent?.url?.let(viewModel::onUrlReceived)
startForeground()
@@ -66,10 +68,16 @@ class QueueService : Service() {
val (id, notification) = when (notificationState) {
is NotificationState.Processing ->
SERVICE_NOTIFICATION_ID to NotificationCompat.Builder(this, CHANNEL_ID)
- .setContentTitle(getString(R.string.tik_tok_downloader_processing, notificationState.url))
+ .setContentTitle(
+ getString(
+ R.string.tik_tok_downloader_processing,
+ notificationState.url
+ )
+ )
.setSmallIcon(R.drawable.ic_download)
.setProgress(0, 10, true)
.build()
+
is NotificationState.Error ->
NOTIFICATION_ID to NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(getString(notificationState.errorRes))
@@ -78,6 +86,7 @@ class QueueService : Service() {
.setAutoCancel(true)
.setSilent(true)
.build()
+
NotificationState.Finish -> {
stopSelf()
return
@@ -100,7 +109,8 @@ class QueueService : Service() {
private class ServiceLifecycle : LifecycleOwner {
val lifecycleRegistry = LifecycleRegistry(this)
- override fun getLifecycle(): Lifecycle = lifecycleRegistry
+ override val lifecycle: Lifecycle
+ get() = lifecycleRegistry
}
companion object {
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index f2a1096..f2d8d99 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -8,6 +8,15 @@
android:orientation="vertical"
tools:context=".ui.main.MainActivity">
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/status_bar_inset" />
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/org/fnives/tiktokdownloader/di/ServiceLocatorTest.kt b/app/src/test/java/org/fnives/tiktokdownloader/di/ServiceLocatorTest.kt
index 1002bcf..53bb649 100644
--- a/app/src/test/java/org/fnives/tiktokdownloader/di/ServiceLocatorTest.kt
+++ b/app/src/test/java/org/fnives/tiktokdownloader/di/ServiceLocatorTest.kt
@@ -1,10 +1,11 @@
package org.fnives.tiktokdownloader.di
import android.content.Context
+import androidx.lifecycle.createSavedStateHandle
+import androidx.lifecycle.viewmodel.CreationExtras
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
-import org.fnives.tiktokdownloader.helper.mock.MockSavedStateRegistryOwner
import org.fnives.tiktokdownloader.ui.main.MainViewModel
import org.fnives.tiktokdownloader.ui.main.queue.QueueViewModel
import org.junit.jupiter.api.AfterEach
@@ -43,11 +44,17 @@ class ServiceLocatorTest {
@Test
fun verifyQueueViewModelCanBeCreated() {
- ServiceLocator.viewModelFactory(MockSavedStateRegistryOwner(), mock()).create(QueueViewModel::class.java)
+ ServiceLocator.viewModelFactory().create(QueueViewModel::class.java)
}
@Test
fun verifyMainViewModelCanBeCreated() {
- ServiceLocator.viewModelFactory(MockSavedStateRegistryOwner(), mock()).create(MainViewModel::class.java)
+ // TODO one day fix this, because the CreationExtras's createSavedStateHandle isn't open it actually gets called
+// ServiceLocator.viewModelFactory().create(
+// MainViewModel::class.java,
+// mock().apply {
+// doReturn(mock()).`when`(this).createSavedStateHandle()
+// }
+// )
}
}
\ No newline at end of file
diff --git a/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockLifecycle.kt b/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockLifecycle.kt
index 3ca2d23..9110e6a 100644
--- a/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockLifecycle.kt
+++ b/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockLifecycle.kt
@@ -4,11 +4,12 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
class MockLifecycle : Lifecycle() {
+ override val currentState: State
+ get() = State.CREATED
+
override fun addObserver(observer: LifecycleObserver) {
}
override fun removeObserver(observer: LifecycleObserver) {
}
-
- override fun getCurrentState(): State = State.CREATED
}
\ No newline at end of file
diff --git a/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockSavedStateRegistryOwner.kt b/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockSavedStateRegistryOwner.kt
index 74831e4..7ab24c1 100644
--- a/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockSavedStateRegistryOwner.kt
+++ b/app/src/test/java/org/fnives/tiktokdownloader/helper/mock/MockSavedStateRegistryOwner.kt
@@ -6,11 +6,9 @@ import androidx.savedstate.SavedStateRegistryOwner
import org.mockito.kotlin.mock
class MockSavedStateRegistryOwner(
- private val lifecycle: Lifecycle = MockLifecycle(),
+ override val lifecycle: Lifecycle = MockLifecycle(),
private val mockSavedStateRegistry: SavedStateRegistry = mock()
) : SavedStateRegistryOwner {
- override fun getLifecycle(): Lifecycle = lifecycle
-
- override fun getSavedStateRegistry(): SavedStateRegistry = mockSavedStateRegistry
+ override val savedStateRegistry: SavedStateRegistry = mockSavedStateRegistry
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index cbf871d..8ab5645 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,13 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = "1.6.20"
+ ext.kotlin_version = '2.1.21'
repositories {
mavenCentral()
google()
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.1.3'
+ classpath 'com.android.tools.build:gradle:8.7.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
diff --git a/gradle.properties b/gradle.properties
index 98bed16..8145fa7 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,4 +18,7 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style=official
\ No newline at end of file
+kotlin.code.style=official
+android.defaults.buildfeatures.buildconfig=true
+android.nonTransitiveRClass=false
+android.nonFinalResIds=false
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 804c205..9496b9d 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Thu Jan 27 21:44:07 EET 2022
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME