mirror of
https://github.com/lizongying/my-tv.git
synced 2026-10-27 06:36:29 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d4353249f | ||
|
|
a8944e75b1 | ||
|
|
d1eae8947e | ||
|
|
fccd64c07b | ||
|
|
eac355a1c1 | ||
|
|
6c6736fd0a | ||
|
|
f4c1db33b3 |
@@ -1,5 +1,13 @@
|
||||
## 更新日誌
|
||||
|
||||
### v2.1.7
|
||||
|
||||
*
|
||||
|
||||
### v2.1.4
|
||||
|
||||
* 解決切換頻道時黑屏問題
|
||||
|
||||
### v2.1.1
|
||||
|
||||
* 平衡聲音
|
||||
|
||||
+18
-66
@@ -98,71 +98,23 @@ static def VersionName() {
|
||||
}
|
||||
}
|
||||
|
||||
def gson_version = "2.10.1"
|
||||
def failureaccess_version = "1.0.2"
|
||||
def guava_version = "33.2.1-android"
|
||||
|
||||
dependencies {
|
||||
|
||||
// minSdk17
|
||||
def media3_version = "1.2.1"
|
||||
|
||||
implementation "androidx.media3:media3-ui:$media3_version"
|
||||
|
||||
// For media playback using ExoPlayer
|
||||
implementation("com.google.guava:failureaccess:$failureaccess_version")
|
||||
implementation("com.google.guava:guava:$guava_version")
|
||||
implementation("androidx.media3:media3-common:$media3_version") {
|
||||
exclude group: 'com.google.guava', module: 'guava'
|
||||
exclude group: 'com.google.guava', module: 'failureaccess'
|
||||
}
|
||||
implementation("androidx.media3:media3-exoplayer:$media3_version")
|
||||
|
||||
// For HLS playback support with ExoPlayer
|
||||
implementation "androidx.media3:media3-exoplayer-hls:$media3_version"
|
||||
|
||||
// 21:2.9.0 17:2.6.4
|
||||
def retrofit2_version = "2.6.4"
|
||||
|
||||
implementation 'com.google.protobuf:protobuf-kotlin:3.25.1'
|
||||
// Gson 2.10.1 and older: API level 19
|
||||
implementation("com.google.code.gson:gson:$gson_version")
|
||||
implementation("com.squareup.retrofit2:converter-gson:$retrofit2_version") {
|
||||
exclude group: 'com.google.code.gson', module: 'gson'
|
||||
}
|
||||
implementation "com.squareup.retrofit2:converter-protobuf:$retrofit2_version"
|
||||
implementation "com.squareup.retrofit2:retrofit:$retrofit2_version"
|
||||
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
|
||||
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||
implementation 'androidx.core:core-ktx:1.11.0-beta02'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.leanback:leanback:1.2.0-alpha02'
|
||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2"
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0-RC")
|
||||
|
||||
implementation 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
}
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy {
|
||||
force("com.google.code.gson:gson:$gson_version")
|
||||
force "com.google.guava:failureaccess:$failureaccess_version"
|
||||
force "com.google.guava:guava:$guava_version"
|
||||
eachDependency { details ->
|
||||
if (details.requested.group == 'com.google.code.gson') {
|
||||
details.useVersion "$gson_version"
|
||||
}
|
||||
if (details.requested.group == 'com.google.guava' && details.requested.name == 'failureaccess') {
|
||||
details.useVersion "$failureaccess_version"
|
||||
}
|
||||
if (details.requested.group == 'com.google.guava' && details.requested.name == 'guava') {
|
||||
details.useVersion "$guava_version"
|
||||
}
|
||||
}
|
||||
}
|
||||
implementation(libs.media3.ui)
|
||||
implementation(libs.media3.exoplayer)
|
||||
implementation(libs.media3.exoplayer.hls)
|
||||
implementation(libs.protobuf.kotlin)
|
||||
implementation(libs.gson)
|
||||
implementation(libs.converter.gson)
|
||||
implementation(libs.converter.protobuf)
|
||||
implementation(libs.retrofit)
|
||||
implementation(libs.glide)
|
||||
implementation(libs.work.runtime.ktx)
|
||||
implementation(libs.core.ktx)
|
||||
implementation(libs.multidex)
|
||||
implementation(libs.leanback)
|
||||
implementation(libs.lifecycle.runtime.ktx)
|
||||
implementation(libs.constraintlayout)
|
||||
implementation(libs.serialization.json)
|
||||
implementation(libs.coroutines.android)
|
||||
implementation(libs.javax.annotation.api)
|
||||
}
|
||||
Vendored
+1
-7
@@ -18,10 +18,4 @@
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
-keep class com.google.gson.** { *; }
|
||||
-dontwarn com.google.gson.**
|
||||
|
||||
-keep class com.google.guava.** { *; }
|
||||
-dontwarn com.google.guava.**
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -11,6 +11,7 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -3,13 +3,37 @@ package com.lizongying.mytv
|
||||
import android.app.AlertDialog
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.lizongying.mytv.databinding.ConfirmationBinding
|
||||
|
||||
class ConfirmationFragment(
|
||||
private val listener: ConfirmationListener,
|
||||
private val message: String,
|
||||
private val update: Boolean
|
||||
) : DialogFragment() {
|
||||
//
|
||||
// private var _binding: ConfirmationBinding? = null
|
||||
// private val binding get() = _binding!!
|
||||
//
|
||||
// override fun onCreateView(
|
||||
// inflater: LayoutInflater, container: ViewGroup?,
|
||||
// savedInstanceState: Bundle?
|
||||
// ): View {
|
||||
// _binding = ConfirmationBinding.inflate(inflater, container, false)
|
||||
// return binding.root
|
||||
// }
|
||||
//
|
||||
// fun updateProgress(progress: Int) {
|
||||
// binding.progressBar.progress = progress
|
||||
// }
|
||||
//
|
||||
// override fun onDestroyView() {
|
||||
// super.onDestroyView()
|
||||
// _binding = null
|
||||
// }
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
return activity?.let {
|
||||
|
||||
@@ -5,7 +5,10 @@ import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.WindowManager
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelStore
|
||||
import androidx.multidex.MultiDex
|
||||
import com.lizongying.mytv.models.MyViewModel
|
||||
|
||||
|
||||
class MyTVApplication : Application() {
|
||||
@@ -23,6 +26,8 @@ class MyTVApplication : Application() {
|
||||
private var density = 2.0f
|
||||
private var scale = 1.0f
|
||||
|
||||
lateinit var myViewModel: MyViewModel
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
@@ -60,6 +65,11 @@ class MyTVApplication : Application() {
|
||||
|
||||
deviation = width - Resources.getSystem().displayMetrics.widthPixels
|
||||
scale = Resources.getSystem().displayMetrics.scaledDensity
|
||||
|
||||
myViewModel = ViewModelProvider(
|
||||
ViewModelStore(),
|
||||
ViewModelProvider.NewInstanceFactory()
|
||||
)[MyViewModel::class.java]
|
||||
}
|
||||
|
||||
fun getDisplayMetrics(): DisplayMetrics {
|
||||
|
||||
@@ -6,11 +6,14 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginEnd
|
||||
import androidx.core.view.marginTop
|
||||
import androidx.fragment.app.DialogFragment
|
||||
@@ -159,6 +162,21 @@ class SettingFragment : DialogFragment() {
|
||||
requireActivity().finishAffinity()
|
||||
}
|
||||
|
||||
// val myViewModel = application.myViewModel
|
||||
// application.myViewModel.downloadProgress.observe(viewLifecycleOwner) { _ ->
|
||||
// val downloadProgress = myViewModel.downloadProgress.value
|
||||
// if (downloadProgress != null) {
|
||||
// if (downloadProgress == 100) {
|
||||
// binding.progressBar.visibility = GONE
|
||||
// } else {
|
||||
// if (!binding.progressBar.isVisible) {
|
||||
// binding.progressBar.visibility = VISIBLE
|
||||
// }
|
||||
// binding.progressBar.progress = downloadProgress
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
updateManager = UpdateManager(context, context.appVersionCode)
|
||||
|
||||
return binding.root
|
||||
|
||||
@@ -31,7 +31,7 @@ class UpdateManager(
|
||||
release = releaseRequest.getRelease()
|
||||
val code = release?.version_code
|
||||
if (code != null) {
|
||||
if (code.toLong() > versionCode) {
|
||||
if (code.toLong() >= versionCode) {
|
||||
text = "最新版本:${release?.version_name}"
|
||||
update = true
|
||||
} else {
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.lizongying.mytv.models.MyViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
@@ -22,6 +23,8 @@ class UpdateWorker(context: Context, params: WorkerParameters) : CoroutineWorker
|
||||
private lateinit var notificationManager: NotificationManager
|
||||
private lateinit var notificationBuilder: NotificationCompat.Builder
|
||||
|
||||
private lateinit var myViewModel: MyViewModel
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val downloadUrl = inputData.getString("DOWNLOAD_URL") ?: return Result.failure()
|
||||
val apkFileName = inputData.getString("APK_FILENAME") ?: return Result.failure()
|
||||
@@ -29,6 +32,9 @@ class UpdateWorker(context: Context, params: WorkerParameters) : CoroutineWorker
|
||||
|
||||
showNotification(applicationContext)
|
||||
|
||||
val app = applicationContext as MyTVApplication
|
||||
myViewModel = app.myViewModel
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
downloadAndInstall(applicationContext, downloadUrl, apkFileName, versionName)
|
||||
@@ -96,6 +102,8 @@ class UpdateWorker(context: Context, params: WorkerParameters) : CoroutineWorker
|
||||
|
||||
if (bytesTotal > 0) {
|
||||
val progress = (bytesDownloaded * 100L / bytesTotal).toInt()
|
||||
Log.i(TAG, "progress $progress")
|
||||
// myViewModel.setDownloadProgress(progress)
|
||||
notificationBuilder.setProgress(100, progress, false)
|
||||
notificationManager.notify(1, notificationBuilder.build())
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.lizongying.mytv
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import com.google.gson.Gson
|
||||
import com.lizongying.mytv.api.TimeResponse
|
||||
@@ -18,6 +19,10 @@ import java.util.Locale
|
||||
object Utils {
|
||||
private var between: Long = 0
|
||||
|
||||
private var a: String = ""
|
||||
var b: String = ""
|
||||
private var c: String = ""
|
||||
|
||||
private var listener: Request.RequestListener? = null
|
||||
|
||||
fun getDateFormat(format: String): String {
|
||||
@@ -45,6 +50,31 @@ object Utils {
|
||||
println("Failed to retrieve timestamp from server: ${e.message}")
|
||||
}
|
||||
|
||||
var x = ""
|
||||
try {
|
||||
x = getNothing()
|
||||
} catch (e: Exception) {
|
||||
x = ""
|
||||
println("a ${e.message}")
|
||||
}
|
||||
|
||||
if (x != "") {
|
||||
try {
|
||||
x = getNothing2(x)
|
||||
} catch (e: Exception) {
|
||||
x = ""
|
||||
println("b ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
// if (x != "") {
|
||||
// try {
|
||||
// getNothing3(x)
|
||||
// } catch (e: Exception) {
|
||||
// println("b ${e.message}")
|
||||
// }
|
||||
// }
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
listener?.onRequestFinished(null)
|
||||
}
|
||||
@@ -88,6 +118,115 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
private val regex = Regex("""chunk-vendors\.([^.]+)\.js""")
|
||||
|
||||
private suspend fun getNothing(): String {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val client = okhttp3.OkHttpClient.Builder()
|
||||
.addInterceptor(RetryInterceptor(3))
|
||||
.build()
|
||||
val request = okhttp3.Request.Builder()
|
||||
.url("https://www.yangshipin.cn")
|
||||
.build()
|
||||
try {
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||
val string = response.body()?.string()
|
||||
|
||||
val matchResult = string?.let { regex.find(it) }
|
||||
var x = ""
|
||||
if (matchResult != null) {
|
||||
x = matchResult.groupValues[1]
|
||||
}
|
||||
x
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw IOException("Error during network request", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val regex2 = Regex(""""ysp_tx"[^:]+:"([^"]+)[^:]+:"([^"]+)""")
|
||||
|
||||
private val regex3 = Regex(""""(https[^"]+wasm([^"]+))""")
|
||||
|
||||
private suspend fun getNothing2(x: String): String {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val client = okhttp3.OkHttpClient.Builder()
|
||||
.addInterceptor(RetryInterceptor(3))
|
||||
.build()
|
||||
|
||||
val request = okhttp3.Request.Builder()
|
||||
.url("https://www.yangshipin.cn/js/chunk-vendors.$x.js")
|
||||
.build()
|
||||
try {
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||
val string = response.body()?.string()
|
||||
|
||||
val matches = string?.let { regex2.findAll(it) }
|
||||
|
||||
var matchResult = matches?.lastOrNull()
|
||||
|
||||
if (matchResult != null) {
|
||||
val (aa, bb) = matchResult.destructured
|
||||
a = aa
|
||||
b = bb
|
||||
}
|
||||
|
||||
matchResult = string?.let { regex3.find(it) }
|
||||
|
||||
if (matchResult != null) {
|
||||
val (cc) = matchResult.destructured
|
||||
c = cc
|
||||
Log.i("", "ccccc $c")
|
||||
}
|
||||
c
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw IOException("Error during network request", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getNothing3(x: String): String {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val client = okhttp3.OkHttpClient.Builder()
|
||||
.addInterceptor(RetryInterceptor(3))
|
||||
.build()
|
||||
|
||||
val request = okhttp3.Request.Builder()
|
||||
.url("https://www.yangshipin.cn/js/chunk-vendors.$x.js")
|
||||
.build()
|
||||
try {
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||
val string = response.body()?.string()
|
||||
|
||||
val matches = string?.let { regex2.findAll(it) }
|
||||
|
||||
var matchResult = matches?.lastOrNull()
|
||||
|
||||
if (matchResult != null) {
|
||||
val (aa, bb) = matchResult.destructured
|
||||
a = aa
|
||||
b = bb
|
||||
}
|
||||
|
||||
matchResult = string?.let { regex3.find(it) }
|
||||
|
||||
if (matchResult != null) {
|
||||
val (cc) = matchResult.destructured
|
||||
c = cc
|
||||
}
|
||||
c
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw IOException("Error during network request", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun dpToPx(dp: Float): Int {
|
||||
return TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().displayMetrics
|
||||
|
||||
@@ -12,6 +12,8 @@ import okhttp3.TlsVersion
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.converter.protobuf.ProtoConverterFactory
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Proxy
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
@@ -166,7 +168,7 @@ class ApiClient {
|
||||
val sslContext = SSLContext.getInstance("SSL")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
|
||||
// val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("10.0.2.2", 8888))
|
||||
val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("10.0.2.2", 8888))
|
||||
|
||||
val builder = OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
|
||||
@@ -13,6 +13,8 @@ class Encryptor {
|
||||
|
||||
external fun hash2(data: ByteArray): ByteArray?
|
||||
|
||||
external fun hash3(data: ByteArray): ByteArray?
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("native")
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.lizongying.mytv.api
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.lizongying.mytv.SP
|
||||
import com.lizongying.mytv.Utils
|
||||
import com.lizongying.mytv.Utils.getDateTimestamp
|
||||
import com.lizongying.mytv.models.TVViewModel
|
||||
import java.security.MessageDigest
|
||||
@@ -182,13 +183,13 @@ object YSP {
|
||||
|
||||
private fun getAuthSignature(): String {
|
||||
val e =
|
||||
"appid=${appid}&guid=${guid}&pid=${livepid}&rand_str=${randStr}".toByteArray()
|
||||
val hashedData = encryptor.hash2(e) ?: return ""
|
||||
"appid=${appid}&guid=${guid}&pid=${livepid}&rand_str=${randStr}${Utils.b}".toByteArray()
|
||||
val hashedData = encryptor.hash3(e) ?: return ""
|
||||
return hashedData.let { it -> it.joinToString("") { "%02x".format(it) } }
|
||||
}
|
||||
|
||||
fun getAuthSignature(e: String): String {
|
||||
val hashedData = encryptor.hash2(e.toByteArray()) ?: return ""
|
||||
val hashedData = encryptor.hash3("$e${Utils.b}".toByteArray()) ?: return ""
|
||||
return hashedData.let { it -> it.joinToString("") { "%02x".format(it) } }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lizongying.mytv.models
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class MyViewModel : ViewModel() {
|
||||
private var _downloadProgress = MutableLiveData<Int>()
|
||||
val downloadProgress: LiveData<Int>
|
||||
get() = _downloadProgress
|
||||
|
||||
fun setDownloadProgress(progress: Int) {
|
||||
_downloadProgress.value = progress
|
||||
}
|
||||
|
||||
init {
|
||||
_downloadProgress.value = 0
|
||||
}
|
||||
}
|
||||
@@ -334,21 +334,8 @@ object Request {
|
||||
val liveInfo = response.body()
|
||||
|
||||
if (liveInfo?.data?.playurl != null) {
|
||||
val chanll = liveInfo.data.chanll
|
||||
val decodedBytes = Base64.decode(
|
||||
chanll.substring(9, chanll.length - 3),
|
||||
Base64.DEFAULT
|
||||
)
|
||||
val decodedString = String(decodedBytes)
|
||||
val matchResult = regex.find(decodedString)
|
||||
if (matchResult != null) {
|
||||
val (key, iv) = matchResult.destructured
|
||||
val keyBytes = Base64.decode(key, Base64.DEFAULT)
|
||||
val ivBytes = Base64.decode(iv, Base64.DEFAULT)
|
||||
val url = liveInfo.data.playurl + "&revoi=" + encryptTripleDES(
|
||||
keyBytes + byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
ivBytes
|
||||
).uppercase() + liveInfo.data.extended_param
|
||||
if (liveInfo.data.extended_param != null) {
|
||||
val url = liveInfo.data.playurl + "&revoi=" + liveInfo.data.extended_param
|
||||
Log.d(TAG, "$title url $url")
|
||||
tvModel.addVideoUrl(url)
|
||||
tvModel.allReady()
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<!-- res/layout/fragment_progress_dialog.xml -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/start_update"
|
||||
tools:text="开始更新">
|
||||
</Button>
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
android:progressDrawable="@android:drawable/progress_horizontal" />
|
||||
</LinearLayout>
|
||||
@@ -11,6 +11,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:shutter_background_color="@android:color/transparent"
|
||||
app:resize_mode="fill"
|
||||
app:use_controller="false" />
|
||||
</FrameLayout>
|
||||
@@ -59,6 +59,15 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
<!-- <androidx.core.widget.ContentLoadingProgressBar-->
|
||||
<!-- android:id="@+id/progressBar"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:indeterminate="false"-->
|
||||
<!-- android:max="100"-->
|
||||
<!-- android:progress="0"-->
|
||||
<!-- android:visibility="gone"-->
|
||||
<!-- android:progressDrawable="@android:drawable/progress_horizontal" />-->
|
||||
<Button
|
||||
android:id="@+id/clear"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -8,4 +8,5 @@
|
||||
<string name="title_time">显示时间</string>
|
||||
<string name="clear">恢复默认</string>
|
||||
<string name="exit">退出应用</string>
|
||||
<string name="start_update">开始更新</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,40 @@
|
||||
[versions]
|
||||
media3 = "1.2.1" # minSdk17
|
||||
gson = "2.10.1" # 2.10.1 and older: API level 19
|
||||
failureaccess = "1.0.2"
|
||||
guava = "33.2.1-android"
|
||||
retrofit = "2.6.4" # 21:2.9.0 17:2.6.4
|
||||
protobuf = "3.25.1"
|
||||
glide = "4.11.0"
|
||||
work = "2.9.0"
|
||||
core_ktx = "1.11.0-beta02"
|
||||
multidex = "2.0.1"
|
||||
leanback = "1.2.0-alpha02"
|
||||
lifecycle = "2.6.2"
|
||||
constraintlayout = "2.1.4"
|
||||
serialization = "1.6.2"
|
||||
coroutines = "1.8.0-RC"
|
||||
javax_annotation = "1.3.2"
|
||||
|
||||
[libraries]
|
||||
media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3" }
|
||||
media3-common = { module = "androidx.media3:media3-common", version.ref = "media3" }
|
||||
media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "media3" }
|
||||
media3-exoplayer-hls = { module = "androidx.media3:media3-exoplayer-hls", version.ref = "media3" }
|
||||
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
|
||||
failureaccess = { module = "com.google.guava:failureaccess", version.ref = "failureaccess" }
|
||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
|
||||
converter-protobuf = { module = "com.squareup.retrofit2:converter-protobuf", version.ref = "retrofit" }
|
||||
protobuf-kotlin = { module = "com.google.protobuf:protobuf-kotlin", version.ref = "protobuf" }
|
||||
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||
work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "work" }
|
||||
core-ktx = { module = "androidx.core:core-ktx", version.ref = "core_ktx" }
|
||||
multidex = { module = "androidx.multidex:multidex", version.ref = "multidex" }
|
||||
leanback = { module = "androidx.leanback:leanback", version.ref = "leanback" }
|
||||
lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" }
|
||||
constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
|
||||
serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
||||
coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
|
||||
javax-annotation-api = { module = "javax.annotation:javax.annotation-api", version.ref = "javax_annotation" }
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#Fri Dec 01 13:53:24 HKT 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-rc-1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version_code": 33620224, "version_name": "v2.1.1"}
|
||||
{"version_code": 33621760, "version_name": "v2.1.7"}
|
||||
|
||||
Reference in New Issue
Block a user