Skip to content

Commit

Permalink
Version updated to 1.2.0 and optimized chat interface
Browse files Browse the repository at this point in the history
- Updated version number to 1.2.0- Optimized chat interface, supports display of read and unread messages
- Improved processing logic of long-pressing messages
- Fixed some minor issues related to chat

版本更新至1.2.0并优化聊天界面

- 更新版本号至1.2.0- 优化聊天界面,支持消息已读未读显示
-改进长按消息的处理逻辑
- 修复一些与聊天相关的小问题

Signed-off-by: gohj99 <[email protected]>
  • Loading branch information
gohj99 committed Oct 5, 2024
1 parent 2e551d7 commit ef80bb1
Show file tree
Hide file tree
Showing 9 changed files with 592 additions and 361 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ android {
minSdk = 26
//noinspection OldTargetApi
targetSdk = 34
versionCode = 11
versionName = "1.1.6"
versionCode = 12
versionName = "1.2.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down
311 changes: 175 additions & 136 deletions app/src/main/java/com/gohj99/telewatch/ChatActivity.kt

Large diffs are not rendered by default.

188 changes: 80 additions & 108 deletions app/src/main/java/com/gohj99/telewatch/CheckUpdateActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ package com.gohj99.telewatch
import android.app.DownloadManager
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
Expand All @@ -21,6 +20,8 @@ import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -37,7 +38,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -88,23 +88,7 @@ class CheckUpdateActivity : ComponentActivity() {
private const val REQUEST_CODE_UNKNOWN_APP = 1234
}

@Deprecated("This method has been deprecated in favor of using the Activity Result API\n which brings increased type safety via an {@link ActivityResultContract} and the prebuilt\n contracts for common intents available in\n {@link androidx.activity.result.contract.ActivityResultContracts}, provides hooks for\n testing, and allow receiving results in separate, testable classes independent from your\n activity. Use\n {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}\n with the appropriate {@link ActivityResultContract} and handling the result in the\n {@link ActivityResultCallback#onActivityResult(Object) callback}.")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_UNKNOWN_APP) {
if (resultCode == RESULT_OK) {
// 用户已授予安装未知来源应用的权限,再次尝试安装 APK
installApk(fileName)
} else {
// 用户拒绝授予权限,处理拒绝情况
Toast.makeText(
this,
getString(R.string.unknown_apps_install_permission_denied),
Toast.LENGTH_SHORT
).show()
}
}
}
private lateinit var installApkLauncher: ActivityResultLauncher<Intent>

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -115,9 +99,31 @@ class CheckUpdateActivity : ComponentActivity() {
}
}

// 检查 Android 版本,如果是 Android 10 及以上,注册 ActivityResultLauncher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
registerInstallApkLauncher()
}

init()
}

private fun registerInstallApkLauncher() {
installApkLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
// 用户已授予安装未知来源应用的权限
installApk(fileName)
} else {
Toast.makeText(
this,
getString(R.string.unknown_apps_install_permission_denied),
Toast.LENGTH_SHORT
).show()
}
}
}

private fun init() {
lifecycleScope.launch(Dispatchers.IO) {
try {
Expand All @@ -143,68 +149,34 @@ class CheckUpdateActivity : ComponentActivity() {
val releaseInfo =
Gson().fromJson(responseData, ReleaseInfo::class.java)

val releaseType =
if (releaseInfo.prerelease) getString(R.string.pre_release) else getString(
R.string.release
)
val tagName = releaseInfo.tagName
val version = tagName.substring(1, 6)

val pInfo = packageManager.getPackageInfo(packageName, 0)
val localVersion = pInfo.versionName
val needsUpdate = compareVersions(version, localVersion)

val publishedAt = releaseInfo.publishedAt
val zonedDateTime = ZonedDateTime.parse(publishedAt)
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val formattedPublishedAt = zonedDateTime.format(formatter)

val armAsset =
releaseInfo.assets.find { it.name.contains("arm.apk") }
val armDownloadUrl = armAsset?.browserDownloadUrl ?: ""

fileName = armDownloadUrl.substringAfterLast('/')

val updateInfo = """
${getString(R.string.version)}: $version
${getString(R.string.Release_type)}: $releaseType
${getString(R.string.Release_time)}: $formattedPublishedAt
""".trimIndent()
val needsUpdate = compareVersions(
releaseInfo.tagName.substring(1, 6),
packageManager.getPackageInfo(packageName, 0).versionName
)

if (needsUpdate) {
setContent {
TelewatchTheme {
var downloadProgress by remember { mutableStateOf(0f) }
var isDownloadComplete by remember {
mutableStateOf(
false
)
}

SplashUpdateView(
contentText = updateInfo,
onDownloadClick = {
startDownload(armDownloadUrl, { progress ->
downloadProgress = progress
}, {
isDownloadComplete = true
})
},
downloadProgress = downloadProgress,
onInstallClick = {
installApk(fileName)
},
isDownloadComplete = isDownloadComplete
contentText = generateUpdateInfo(releaseInfo),
onDownloadClick = { startDownload(armDownloadUrl) },
downloadProgress = 0f,
onInstallClick = { installApk(fileName) },
isDownloadComplete = false
)
}
}
} else {
setContent {
TelewatchTheme {
Box(
modifier = Modifier
.fillMaxSize()
.fillMaxWidth(),
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
Expand Down Expand Up @@ -233,11 +205,7 @@ class CheckUpdateActivity : ComponentActivity() {
}
}

private fun startDownload(
url: String,
onProgress: (Float) -> Unit,
onDownloadComplete: () -> Unit
) {
private fun startDownload(url: String) {
val request = DownloadManager.Request(Uri.parse(url))
.setTitle("Downloading update")
.setDescription("Downloading the latest version of the app")
Expand All @@ -248,52 +216,24 @@ class CheckUpdateActivity : ComponentActivity() {

val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadId = downloadManager.enqueue(request)

val query = DownloadManager.Query().setFilterById(downloadId)

lifecycleScope.launch(Dispatchers.IO) {
var downloading = true
while (downloading) {
val cursor: Cursor = downloadManager.query(query)
if (cursor.moveToFirst()) {
val statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
if (statusIndex >= 0) {
val status = cursor.getInt(statusIndex)
if (status == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false
onProgress(1f)
launch(Dispatchers.Main) {
onDownloadComplete()
}
} else if (status == DownloadManager.STATUS_RUNNING) {
val totalIndex =
cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
val downloadedIndex =
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
if (totalIndex >= 0 && downloadedIndex >= 0) {
val total = cursor.getLong(totalIndex)
if (total > 0) {
val downloaded = cursor.getLong(downloadedIndex)
val progress = downloaded.toFloat() / total.toFloat()
onProgress(progress)
}
}
}
}
}
cursor.close()
}
}
}

private fun installApk(fileName: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!packageManager.canRequestPackageInstalls()) {
// 请求用户授予安装未知来源应用的权限
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = Uri.parse("package:$packageName")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = Uri.parse("package:$packageName")
}
installApkLauncher.launch(intent)
} else {
// Android 7.1 及以下版本使用 onActivityResult
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = Uri.parse("package:$packageName")
}
startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP)
}
startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP)
return
}
}
Expand All @@ -315,10 +255,25 @@ class CheckUpdateActivity : ComponentActivity() {
startActivity(intent)
}

@Deprecated("Deprecated in Android 14", ReplaceWith("ActivityResult API"))
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_UNKNOWN_APP) {
if (resultCode == RESULT_OK) {
installApk(fileName)
} else {
Toast.makeText(
this,
getString(R.string.unknown_apps_install_permission_denied),
Toast.LENGTH_SHORT
).show()
}
}
}

private fun compareVersions(version1: String, version2: String): Boolean {
val parts1 = version1.split(".")
val parts2 = version2.split(".")

for (i in 0..2) {
val num1 = parts1.getOrNull(i)?.toIntOrNull() ?: 0
val num2 = parts2.getOrNull(i)?.toIntOrNull() ?: 0
Expand All @@ -327,6 +282,23 @@ class CheckUpdateActivity : ComponentActivity() {
}
return false
}

private fun generateUpdateInfo(releaseInfo: ReleaseInfo): String {
val releaseType =
if (releaseInfo.prerelease) getString(R.string.pre_release) else getString(R.string.release)
val tagName = releaseInfo.tagName
val version = tagName.substring(1, 6)
val publishedAt = releaseInfo.publishedAt
val zonedDateTime = ZonedDateTime.parse(publishedAt)
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
val formattedPublishedAt = zonedDateTime.format(formatter)

return """
${getString(R.string.version)}: $version
${getString(R.string.Release_type)}: $releaseType
${getString(R.string.Release_time)}: $formattedPublishedAt
""".trimIndent()
}
}

@Composable
Expand Down
Loading

0 comments on commit ef80bb1

Please sign in to comment.