Skip to content

Commit

Permalink
Merge pull request #249 from GuoXiCheng/dev-c
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
GuoXiCheng authored Sep 24, 2024
2 parents 0efb28d + fbb9a3a commit 19f5597
Show file tree
Hide file tree
Showing 19 changed files with 384 additions and 79 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.android.skip.data.download

import com.android.skip.data.network.MyApiNetwork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ApkDownloadRepository @Inject constructor(
private val myApiNetwork: MyApiNetwork
) {
suspend fun downloadAPK(latestVersion: String, onDownloadProcess: (process: Int) -> Unit) =
withContext(Dispatchers.IO) {
myApiNetwork.fetchAPK(latestVersion, onDownloadProcess)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.android.skip.data.download

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
class ApkDownloadViewModel @Inject constructor(
private val apkDownloadRepository: ApkDownloadRepository
) : ViewModel() {
private val _isShowDialog = MutableLiveData(false)
val isShowDialog: LiveData<Boolean> = _isShowDialog

private val _apkDownloadProcess = MutableLiveData(0)
val apkDownloadProcess: LiveData<Int> = _apkDownloadProcess

fun changeDialogState(showDialog: Boolean) {
_isShowDialog.postValue(showDialog)
}

private fun changeApkDownloadProcess(process: Int) {
_apkDownloadProcess.postValue(process)
}

fun downloadAPK(latestVersion: String) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
apkDownloadRepository.downloadAPK(latestVersion) {
changeApkDownloadProcess(it)
}
}
}
}
}
54 changes: 54 additions & 0 deletions app/src/main/java/com/android/skip/data/network/MyApiNetwork.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package com.android.skip.data.network

import com.android.skip.MyApp
import com.android.skip.data.network.api.MyApiService
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.LogUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.io.FileOutputStream
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.floor

@Singleton
class MyApiNetwork @Inject constructor() {
Expand All @@ -26,4 +34,50 @@ class MyApiNetwork @Inject constructor() {
AppUtils.getAppVersionName()
}
}

suspend fun fetchAPK(latestVersion: String, onDownloadProcess: (process: Int)->Unit) {
try {
val response = myApiService.downloadAPK(latestVersion)

if (response.isSuccessful) {
response.body()?.let { body->
val contentLength = body.contentLength()
val inputStream = body.byteStream()

val path = "${MyApp.context.filesDir}/apk"
val fileDir = File(path)
if (!fileDir.exists()) {
fileDir.mkdir()
} else {
FileUtils.deleteFilesInDir(fileDir)
}

val file = File(path, "SKIP-v$latestVersion.apk")
val outputStream = FileOutputStream(file)

val buffer = ByteArray(2048)
var downloaded = 0L
var read: Int

withContext(Dispatchers.IO) {
while (inputStream.read(buffer).also { read = it } != -1) {
outputStream.write(buffer, 0, read)
downloaded += read
val progress = (downloaded.toFloat() / contentLength.toFloat()) * 100
withContext(Dispatchers.Main) {
onDownloadProcess(floor(progress).toInt())
}
}
outputStream.flush()
outputStream.close()
inputStream.close()
}
}
} else {
throw Exception("Failed to download file: ${response.errorBody()?.string()}")
}
} catch (e: Exception) {
LogUtils.e(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.android.skip.data.network.api

import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Streaming
import retrofit2.http.Url

interface MyApiService {
Expand All @@ -10,4 +13,8 @@ interface MyApiService {

@GET("/latest_version.txt")
suspend fun getLatestVersion(): Response<String>

@GET("/SKIP-v{version}.apk")
@Streaming
suspend fun downloadAPK(@Path("version") latestVersion: String): Response<ResponseBody>
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,27 @@ class ApkVersionRepository @Inject constructor(
_versionPostState.postValue(versionPostState)
val version = myApiNetwork.fetchLatestVersion()
if (version == AppUtils.getAppVersionName()) {
_versionPostState.postValue(VersionPostSchema(VersionState.CURRENT_LATEST, version))
_versionPostState.postValue(
VersionPostSchema(
VersionState.CURRENT_LATEST,
version,
version
)
)
} else {
_versionPostState.postValue(
VersionPostSchema(
VersionState.DISCOVER_LATEST,
getString(R.string.about_discover_latest)
getString(R.string.about_discover_latest),
version
)
)
}
}

suspend fun checkVersion() {
changeVersionState(
VersionPostSchema(VersionState.PENDING, getString(R.string.checking))
VersionPostSchema(VersionState.PENDING, getString(R.string.checking), String())
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ enum class VersionState {

data class VersionPostSchema(
val status: VersionState,
val value: String
val value: String,
val latestVersion: String
)
12 changes: 12 additions & 0 deletions app/src/main/java/com/android/skip/ui/about/AboutActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import com.android.skip.MyApp
import com.android.skip.R
import com.android.skip.data.config.ConfigViewModel
import com.android.skip.data.version.ApkVersionViewModel
import com.android.skip.dataclass.VersionState
import com.android.skip.ui.about.config.ConfigVersionButton
import com.android.skip.ui.about.download.ApkDownloadDialog
import com.android.skip.data.download.ApkDownloadViewModel
import com.android.skip.ui.about.version.ApkVersionButton
import com.android.skip.ui.components.FlatButton
import com.android.skip.ui.components.ResourceIcon
Expand All @@ -32,6 +35,8 @@ class AboutActivity : AppCompatActivity() {

private val apkVersionViewModel by viewModels<ApkVersionViewModel>()

private val apkDownloadViewModel by viewModels<ApkDownloadViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Expand All @@ -52,6 +57,7 @@ class AboutActivity : AppCompatActivity() {
}
ApkVersionButton(apkVersionViewModel)
ConfigVersionButton(configViewModel)
ApkDownloadDialog(apkDownloadViewModel, apkVersionViewModel)
}, {
DropdownMenuItem(
leadingIcon = { ResourceIcon(iconResource = R.drawable.help) },
Expand All @@ -65,6 +71,12 @@ class AboutActivity : AppCompatActivity() {
})
}
}

apkVersionViewModel.versionPostState.observe(this) {
if (it.status == VersionState.DISCOVER_LATEST) {
apkDownloadViewModel.changeDialogState(true)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.android.skip.ui.about.download

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.android.skip.R
import com.android.skip.data.download.ApkDownloadViewModel
import com.android.skip.data.version.ApkVersionViewModel
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.StringUtils.getString

@Composable
fun ApkDownloadDialog(
apkDownloadViewModel: ApkDownloadViewModel,
apkVersionViewModel: ApkVersionViewModel
) {
val showDialog = apkDownloadViewModel.isShowDialog.observeAsState()

val versionPostState = apkVersionViewModel.versionPostState.observeAsState()

val apkDownloadProcess = apkDownloadViewModel.apkDownloadProcess.observeAsState()

if (showDialog.value == true) {
AlertDialog(
modifier = Modifier.fillMaxWidth(),
containerColor = MaterialTheme.colorScheme.background,
title = {
Text(text = stringResource(id = R.string.dialog_new_version_released))
},
text = {
Column {
Text(
text = getString(
R.string.dialog_update_version,
AppUtils.getAppVersionName(),
versionPostState.value?.latestVersion
)
)
apkDownloadProcess.value?.let { process ->
if (process > 0) {
Text(
text = getString(
R.string.dialog_downloading,
apkDownloadProcess.value
)
)
}
}
}

},
onDismissRequest = {
apkDownloadViewModel.changeDialogState(false)
},
confirmButton = {
Button(onClick = {
versionPostState.value?.latestVersion?.let {
apkDownloadViewModel.downloadAPK(
it
)
}
}) {
Text(text = stringResource(id = R.string.dialog_update_now))
}
},
dismissButton = {
TextButton(onClick = { apkDownloadViewModel.changeDialogState(false) }) {
Text(text = stringResource(id = R.string.dialog_not_update))
}
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,5 @@ class NotificationBarRepository @Inject constructor() {

fun changeEnable(enable: Boolean) {
_enable.postValue(enable)
DataStoreUtils.putSyncData(getString(R.string.store_resident_notification_bar), enable)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package com.android.skip.ui.alive.notificationbar

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.android.skip.R
import com.android.skip.util.DataStoreUtils
import com.blankj.utilcode.util.StringUtils.getString
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
Expand All @@ -10,5 +17,13 @@ class NotificationBarViewModel @Inject constructor(
) : ViewModel() {
val enable = notificationBarRepository.enable

fun changeEnable(enable: Boolean) = notificationBarRepository.changeEnable(enable)
fun changeEnable(enable: Boolean) {
notificationBarRepository.changeEnable(enable)

viewModelScope.launch {
withContext(Dispatchers.IO) {
DataStoreUtils.putSyncData(getString(R.string.store_resident_notification_bar), enable)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.android.skip.ui.components.notification
import android.content.Intent
import android.provider.Settings
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
Expand Down Expand Up @@ -31,7 +32,7 @@ fun NotificationDialog(
},
onDismissRequest = onDismiss,
confirmButton = {
TextButton(
Button(
onClick = {
val intent = Intent().apply {
action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import com.android.skip.R
import com.android.skip.util.DataStoreUtils
import com.blankj.utilcode.util.StringUtils.getString
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
Expand All @@ -25,7 +27,9 @@ class RecentViewModel @Inject constructor() : ViewModel() {
_excludeFromRecent.postValue(excludeFromRecent)

viewModelScope.launch {
DataStoreUtils.putData(getString(R.string.store_exclude_from_recent), excludeFromRecent)
withContext(Dispatchers.IO) {
DataStoreUtils.putData(getString(R.string.store_exclude_from_recent), excludeFromRecent)
}
}
}
}
Loading

0 comments on commit 19f5597

Please sign in to comment.