From 8a3720049fa180737111d1289b0d36b8d80ae45d Mon Sep 17 00:00:00 2001 From: Li ZongYing Date: Mon, 19 Feb 2024 17:31:00 +0800 Subject: [PATCH 1/3] update mannager --- .../java/com/lizongying/mytv/CardPresenter.kt | 5 + .../mytv/ConfirmationDialogFragment.kt | 36 ++++ .../java/com/lizongying/mytv/Encryptor.kt | 2 + .../java/com/lizongying/mytv/MainActivity.kt | 30 ++- .../java/com/lizongying/mytv/MainFragment.kt | 15 +- .../com/lizongying/mytv/PlayerFragment.kt | 3 + .../com/lizongying/mytv/SettingFragment.kt | 33 +++- .../main/java/com/lizongying/mytv/TVList.kt | 26 ++- .../java/com/lizongying/mytv/UpdateManager.kt | 186 +++++++++++++++++- .../java/com/lizongying/mytv/api/ApiClient.kt | 9 + .../main/java/com/lizongying/mytv/api/Auth.kt | 37 ++++ .../main/java/com/lizongying/mytv/api/Info.kt | 23 ++- .../com/lizongying/mytv/api/ReleaseService.kt | 11 ++ .../main/java/com/lizongying/mytv/api/YSP.kt | 23 +++ .../com/lizongying/mytv/api/YSPApiService.kt | 12 ++ .../com/lizongying/mytv/requests/MyRequest.kt | 44 +++++ app/src/main/res/layout/dialog.xml | 26 ++- app/src/main/res/values/strings.xml | 1 + 18 files changed, 486 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/com/lizongying/mytv/ConfirmationDialogFragment.kt create mode 100644 app/src/main/java/com/lizongying/mytv/api/Auth.kt create mode 100644 app/src/main/java/com/lizongying/mytv/api/ReleaseService.kt create mode 100644 app/src/main/java/com/lizongying/mytv/requests/MyRequest.kt diff --git a/app/src/main/java/com/lizongying/mytv/CardPresenter.kt b/app/src/main/java/com/lizongying/mytv/CardPresenter.kt index 099a918..cd6dbf4 100644 --- a/app/src/main/java/com/lizongying/mytv/CardPresenter.kt +++ b/app/src/main/java/com/lizongying/mytv/CardPresenter.kt @@ -47,6 +47,11 @@ class CardPresenter( .centerInside() .into(cardView.mainImageView) + "兵团卫视" -> Glide.with(viewHolder.view.context) + .load(R.drawable.bingtuan) + .centerInside() + .into(cardView.mainImageView) + else -> Glide.with(viewHolder.view.context) .load(tvViewModel.logo.value) .centerInside() diff --git a/app/src/main/java/com/lizongying/mytv/ConfirmationDialogFragment.kt b/app/src/main/java/com/lizongying/mytv/ConfirmationDialogFragment.kt new file mode 100644 index 0000000..2100510 --- /dev/null +++ b/app/src/main/java/com/lizongying/mytv/ConfirmationDialogFragment.kt @@ -0,0 +1,36 @@ +package com.lizongying.mytv + +import android.app.AlertDialog +import android.app.Dialog +import android.os.Bundle +import androidx.fragment.app.DialogFragment + +class ConfirmationDialogFragment(private val listener: ConfirmationDialogListener) : + DialogFragment() { + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + return activity?.let { + val builder = AlertDialog.Builder(it) + builder.setTitle("确认") + .setMessage("确认更新吗?") + .setPositiveButton( + "确定" + ) { _, _ -> + listener.onConfirm() + } + .setNegativeButton( + "取消" + ) { _, _ -> + listener.onCancel() + } + // 创建并返回 AlertDialog 对象 + builder.create() + } ?: throw IllegalStateException("Activity cannot be null") + } + + interface ConfirmationDialogListener { + fun onConfirm() + fun onCancel() + } +} + diff --git a/app/src/main/java/com/lizongying/mytv/Encryptor.kt b/app/src/main/java/com/lizongying/mytv/Encryptor.kt index 525a651..3d3fe99 100644 --- a/app/src/main/java/com/lizongying/mytv/Encryptor.kt +++ b/app/src/main/java/com/lizongying/mytv/Encryptor.kt @@ -9,6 +9,8 @@ class Encryptor { external fun hash(data: ByteArray): ByteArray? + external fun hash2(data: ByteArray): ByteArray? + companion object { init { System.loadLibrary("native") diff --git a/app/src/main/java/com/lizongying/mytv/MainActivity.kt b/app/src/main/java/com/lizongying/mytv/MainActivity.kt index e766306..2064f37 100644 --- a/app/src/main/java/com/lizongying/mytv/MainActivity.kt +++ b/app/src/main/java/com/lizongying/mytv/MainActivity.kt @@ -29,10 +29,11 @@ import java.security.MessageDigest class MainActivity : FragmentActivity() { - var playerFragment = PlayerFragment() - private val mainFragment = MainFragment() - private val infoFragment = InfoFragment() - private val channelFragment = ChannelFragment() + private var ready = 0 + private var playerFragment = PlayerFragment() + private var mainFragment = MainFragment() + private var infoFragment = InfoFragment() + private var channelFragment = ChannelFragment() private lateinit var settingFragment: SettingFragment private var doubleBackToExitPressedOnce = false @@ -85,8 +86,15 @@ class MainActivity : FragmentActivity() { channelNum = sharedPref.getBoolean(CHANNEL_NUM, channelNum) bootStartup = sharedPref.getBoolean(BOOT_STARTUP, bootStartup) - versionName = getPackageInfo().versionName - settingFragment = SettingFragment(versionName, channelReversal, channelNum, bootStartup) + val packageInfo = getPackageInfo() + versionName = packageInfo.versionName + val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + packageInfo.longVersionCode + } else { + packageInfo.versionCode.toLong() + } + settingFragment = + SettingFragment(versionName, versionCode, channelReversal, channelNum, bootStartup) } fun showInfoFragment(tvViewModel: TVViewModel) { @@ -172,7 +180,11 @@ class MainActivity : FragmentActivity() { } fun fragmentReady() { - mainFragment.fragmentReady() + ready++ + Log.i(TAG, "ready $ready") + if (ready == 4) { + mainFragment.fragmentReady() + } } override fun onTouchEvent(event: MotionEvent?): Boolean { @@ -520,7 +532,7 @@ class MainActivity : FragmentActivity() { override fun onResume() { Log.i(TAG, "onResume") super.onResume() - if (!mainFragment.isHidden){ + if (!mainFragment.isHidden) { handler.postDelayed(hideMain, delayHideMain) } } @@ -537,4 +549,4 @@ class MainActivity : FragmentActivity() { private const val CHANNEL_NUM = "channel_num" const val BOOT_STARTUP = "boot_startup" } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/MainFragment.kt b/app/src/main/java/com/lizongying/mytv/MainFragment.kt index b537dcb..f23e4a1 100644 --- a/app/src/main/java/com/lizongying/mytv/MainFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/MainFragment.kt @@ -41,8 +41,6 @@ class MainFragment : BrowseSupportFragment() { private val handler = Handler(Looper.getMainLooper()) private lateinit var mUpdateProgramRunnable: UpdateProgramRunnable - private var ready = 0 - override fun onCreate(savedInstanceState: Bundle?) { Log.i(TAG, "onCreate") super.onCreate(savedInstanceState) @@ -89,6 +87,7 @@ class MainFragment : BrowseSupportFragment() { tvViewModel.change.observe(viewLifecycleOwner) { _ -> if (tvViewModel.change.value != null) { val title = tvViewModel.title.value + Log.i(TAG, "switch $title") if (tvViewModel.pid.value != "") { Log.i(TAG, "request $title") lifecycleScope.launch(Dispatchers.IO) { @@ -113,7 +112,7 @@ class MainFragment : BrowseSupportFragment() { } } - fragmentReady() + (activity as MainActivity).fragmentReady() } fun toLastPosition() { @@ -245,12 +244,8 @@ class MainFragment : BrowseSupportFragment() { } fun fragmentReady() { - ready++ - Log.i(TAG, "ready $ready") - if (ready == 4) { // request.fetchPage() - tvListViewModel.getTVViewModel(itemPosition)?.changed() - } + tvListViewModel.getTVViewModel(itemPosition)?.changed() } fun play(itemPosition: Int) { @@ -332,7 +327,9 @@ class MainFragment : BrowseSupportFragment() { override fun onDestroy() { Log.i(TAG, "onDestroy") super.onDestroy() - handler.removeCallbacks(mUpdateProgramRunnable) + if (::mUpdateProgramRunnable.isInitialized) { + handler.removeCallbacks(mUpdateProgramRunnable) + } } companion object { diff --git a/app/src/main/java/com/lizongying/mytv/PlayerFragment.kt b/app/src/main/java/com/lizongying/mytv/PlayerFragment.kt index b7b987b..81f7ccc 100644 --- a/app/src/main/java/com/lizongying/mytv/PlayerFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/PlayerFragment.kt @@ -80,6 +80,7 @@ class PlayerFragment : Fragment(), SurfaceHolder.Callback { super.onPlayerError(error) Log.e(TAG, "PlaybackException $error") + tvViewModel?.changed() } }) } @@ -107,10 +108,12 @@ class PlayerFragment : Fragment(), SurfaceHolder.Callback { if (playerView != null && playerView!!.player?.isPlaying == false) { Log.i(TAG, "replay") playerView!!.player?.prepare() + playerView!!.player?.play() } if (exoPlayer?.isPlaying == false) { Log.i(TAG, "replay") exoPlayer?.prepare() + exoPlayer?.play() } } diff --git a/app/src/main/java/com/lizongying/mytv/SettingFragment.kt b/app/src/main/java/com/lizongying/mytv/SettingFragment.kt index 8a55c50..87889ae 100644 --- a/app/src/main/java/com/lizongying/mytv/SettingFragment.kt +++ b/app/src/main/java/com/lizongying/mytv/SettingFragment.kt @@ -8,16 +8,20 @@ import androidx.fragment.app.DialogFragment import com.lizongying.mytv.databinding.DialogBinding -class SettingFragment(private val versionName: String, - private val channelReversal: Boolean, - private val channelNum: Boolean, - private val bootStartup: Boolean, - ) : +class SettingFragment( + private val versionName: String, + private val versionCode: Long, + private val channelReversal: Boolean, + private val channelNum: Boolean, + private val bootStartup: Boolean, +) : DialogFragment() { private var _binding: DialogBinding? = null private val binding get() = _binding!! + private lateinit var updateManager: UpdateManager + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, 0) @@ -50,14 +54,33 @@ class SettingFragment(private val versionName: String, (activity as MainActivity).saveBootStartup(isChecked) } + updateManager = UpdateManager(context, this, versionCode) + _binding?.checkVersion?.setOnClickListener(OnClickListenerCheckVersion(updateManager)) + return binding.root } + fun setVersionName(versionName: String) { + binding.versionName.text = versionName + } + + internal class OnClickListenerCheckVersion(private val updateManager: UpdateManager) : + View.OnClickListener { + override fun onClick(view: View?) { + updateManager.checkAndUpdate() + } + } + override fun onDestroyView() { super.onDestroyView() _binding = null } + override fun onDestroy() { + super.onDestroy() +// updateManager.destroy() + } + companion object { const val TAG = "SettingFragment" } diff --git a/app/src/main/java/com/lizongying/mytv/TVList.kt b/app/src/main/java/com/lizongying/mytv/TVList.kt index 6eeb17a..26a083b 100644 --- a/app/src/main/java/com/lizongying/mytv/TVList.kt +++ b/app/src/main/java/com/lizongying/mytv/TVList.kt @@ -859,10 +859,24 @@ object TVList { true, mustToken = false ), + TV( + 56, + "兵团卫视", + "兵团卫视", + listOf(), + 0, + "地方频道", + "", + "600170344", + "2022606701", + "", + true, + mustToken = false + ), ), "国际频道" to listOf( TV( - 56, + 57, "CGTN", "CGTN", listOf("http://live.cgtn.com/1000/prog_index.m3u8"), @@ -876,7 +890,7 @@ object TVList { mustToken = false ), TV( - 57, + 58, "CGTN 法语频道", "CGTN法语频道", listOf("https://livefr.cgtn.com/1000f/prog_index.m3u8"), @@ -890,7 +904,7 @@ object TVList { mustToken = false ), TV( - 58, + 59, "CGTN 俄语频道", "CGTN俄语频道", listOf("http://liveru.cgtn.com/1000r/prog_index.m3u8"), @@ -904,7 +918,7 @@ object TVList { mustToken = false ), TV( - 59, + 60, "CGTN 阿拉伯语频道", "CGTN阿拉伯语频道", listOf("http://livear.cgtn.com/1000a/prog_index.m3u8"), @@ -918,7 +932,7 @@ object TVList { mustToken = false ), TV( - 60, + 61, "CGTN 西班牙语频道", "CGTN西班牙语频道", listOf( @@ -935,7 +949,7 @@ object TVList { mustToken = false ), TV( - 61, + 62, "CGTN 纪录频道", "CGTN外语纪录频道", listOf("https://livedoc.cgtn.com/500d/prog_index.m3u8"), diff --git a/app/src/main/java/com/lizongying/mytv/UpdateManager.kt b/app/src/main/java/com/lizongying/mytv/UpdateManager.kt index 02b054a..ac1b852 100644 --- a/app/src/main/java/com/lizongying/mytv/UpdateManager.kt +++ b/app/src/main/java/com/lizongying/mytv/UpdateManager.kt @@ -1,5 +1,189 @@ package com.lizongying.mytv -class UpdateManager { +import android.app.DownloadManager +import android.app.DownloadManager.Request +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.database.Cursor +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.os.Handler +import android.os.Looper +import android.util.Log +import android.widget.Toast +import com.lizongying.mytv.api.Release +import com.lizongying.mytv.requests.MyRequest +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.io.File + +class UpdateManager( + private var context: Context?, + private var settingFragment: SettingFragment, + private var versionCode: Long +) : + ConfirmationDialogFragment.ConfirmationDialogListener { + + private var myRequest = MyRequest() + private var release: Release? = null + + private var downloadReceiver: DownloadReceiver? = null + + fun checkAndUpdate() { + CoroutineScope(Dispatchers.Main).launch { + try { + release = myRequest.getRelease() + updateUI(release) + Log.i(TAG, "versionCode $versionCode ${release?.data?.versionCode}") + if (release != null) { + if (release?.data?.versionCode!! >= versionCode) { + val dialog = ConfirmationDialogFragment(this@UpdateManager) + dialog.show(settingFragment.fragmentManager, "ConfirmationDialogFragment") + } else { + Toast.makeText(context, "不需要更新", Toast.LENGTH_LONG) + .show() + } + } + } catch (e: Exception) { + Log.e(TAG, "Error occurred: ${e.message}", e) + } + } + } + + private fun updateUI(release: Release?) { + if (release?.data?.versionName.isNullOrEmpty()) { + settingFragment.setVersionName("版本获取失败") + } else { + settingFragment.setVersionName("最新版本:${release?.data?.versionName!!}") + } + } + + private fun startDownload(release: Release) { + val apkFileName = "my-tv-${release.data.versionName}.apk" + Log.i(TAG, "apkFileName $apkFileName") + val downloadManager = + context!!.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + val request = Request(Uri.parse(release.data.downloadUrl)) + Log.i(TAG, "url ${Uri.parse(release.data.downloadUrl)}") + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkFileName) + request.setTitle("New Version Download") + request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) + + // 获取下载任务的引用 + val downloadReference = downloadManager.enqueue(request) + + downloadReceiver = DownloadReceiver(context!!, apkFileName, downloadReference) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context!!.registerReceiver( + downloadReceiver, + IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), + Context.RECEIVER_NOT_EXPORTED, + ) + } else { + context!!.registerReceiver( + downloadReceiver, + IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) + ) + } + + getDownloadProgress(context!!, downloadReference) { progress -> + println("Download progress: $progress%") + } + } + + private fun getDownloadProgress(context: Context, downloadId: Long, progressListener: (Int) -> Unit) { + val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + val handler = Handler(Looper.getMainLooper()) + val intervalMillis: Long = 1000 + + handler.post(object : Runnable { + override fun run() { + Log.i(TAG, "search") + val query = DownloadManager.Query().setFilterById(downloadId) + val cursor: Cursor = downloadManager.query(query) + cursor.use { + if (it.moveToFirst()) { + val bytesDownloadedIndex = + it.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR) + val bytesTotalIndex = + it.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES) + + // 检查列名是否存在 + if (bytesDownloadedIndex != -1 && bytesTotalIndex != -1) { + val bytesDownloaded = it.getInt(bytesDownloadedIndex) + val bytesTotal = it.getInt(bytesTotalIndex) + + if (bytesTotal != -1) { + val progress = (bytesDownloaded * 100L / bytesTotal).toInt() + progressListener(progress) + if (progress == 100) { + return + } + } + } + } + } + +// handler.postDelayed(this, intervalMillis) + } + }) + } + + private class DownloadReceiver( + private val context: Context, + private val apkFileName: String, + private val downloadReference: Long + ) : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) + Log.i(TAG, "reference $reference") + val progress = intent.getIntExtra("progress", 0) + Log.i(TAG, "progress $progress") + + // 检查是否是我们发起的下载 + if (reference == downloadReference) { + // 下载完成,触发安装 + installNewVersion() + } + } + + private fun installNewVersion() { + val installIntent = Intent(Intent.ACTION_VIEW) + val apkUri = Uri.fromFile( + File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + apkFileName + ) + ) + installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive") + installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(installIntent) + } + } + + companion object { + private const val TAG = "UpdateManager" + } + + override fun onConfirm() { + Log.i(TAG, "onConfirm $release") + release?.let { startDownload(it) } + } + + override fun onCancel() { + } + + + fun destroy() { + if (downloadReceiver != null) { + context!!.unregisterReceiver(downloadReceiver) + Log.i(TAG, "destroy downloadReceiver") + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/api/ApiClient.kt b/app/src/main/java/com/lizongying/mytv/api/ApiClient.kt index 076e6aa..6ff511a 100644 --- a/app/src/main/java/com/lizongying/mytv/api/ApiClient.kt +++ b/app/src/main/java/com/lizongying/mytv/api/ApiClient.kt @@ -13,6 +13,7 @@ import javax.net.ssl.X509TrustManager class ApiClient { private val yspUrl = "https://player-api.yangshipin.cn/" private val myUrl = "https://lyrics.run/" + private val devUrl = "http://10.0.2.2:8081/" private val protoUrl = "https://capi.yangshipin.cn/" private val traceUrl = "https://btrace.yangshipin.cn/" @@ -34,6 +35,14 @@ class ApiClient { .build().create(YSPTokenService::class.java) } + val releaseService: ReleaseService by lazy { + Retrofit.Builder() + .baseUrl(myUrl) + .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) + .build().create(ReleaseService::class.java) + } + val yspProtoService: YSPProtoService by lazy { Retrofit.Builder() .baseUrl(protoUrl) diff --git a/app/src/main/java/com/lizongying/mytv/api/Auth.kt b/app/src/main/java/com/lizongying/mytv/api/Auth.kt new file mode 100644 index 0000000..095516c --- /dev/null +++ b/app/src/main/java/com/lizongying/mytv/api/Auth.kt @@ -0,0 +1,37 @@ +package com.lizongying.mytv.api + +import android.util.Log +import okhttp3.MediaType +import okhttp3.RequestBody +import okio.BufferedSink +import java.io.IOException + +data class Auth( + val code: Int, + val msg: String, + val data: AuthData, +) + +data class AuthData( + val token: String, +) + +data class AuthRequest( + var data: String, +) : RequestBody() { + override fun contentType(): MediaType? { + return MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8") + } + + override fun writeTo(sink: BufferedSink) { + try { + sink.writeUtf8(data) + } catch (e: IOException) { + Log.e(TAG, "$e") + } + } + + companion object { + private const val TAG = "AuthRequest" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/api/Info.kt b/app/src/main/java/com/lizongying/mytv/api/Info.kt index c4a3eeb..0f46b18 100644 --- a/app/src/main/java/com/lizongying/mytv/api/Info.kt +++ b/app/src/main/java/com/lizongying/mytv/api/Info.kt @@ -3,12 +3,25 @@ package com.lizongying.mytv.api data class Info( val code: Int?, val msg: String?, - val data: InfoData, -) + val data: Data, +) { + data class Data( + val token: String, + ) +} -data class InfoData( - val token: String, -) +data class Release( + val code: Int?, + val msg: String?, + val data: Data, +) { + data class Data( + val versionName: String, + val versionCode: Int, + val downloadUrl: String, + val updateTime: Int, + ) +} data class TimeResponse( val data: Time diff --git a/app/src/main/java/com/lizongying/mytv/api/ReleaseService.kt b/app/src/main/java/com/lizongying/mytv/api/ReleaseService.kt new file mode 100644 index 0000000..d06eea1 --- /dev/null +++ b/app/src/main/java/com/lizongying/mytv/api/ReleaseService.kt @@ -0,0 +1,11 @@ +package com.lizongying.mytv.api + +import retrofit2.Call +import retrofit2.http.GET + + +interface ReleaseService { + @GET("my-tv/v1/release") + fun getRelease( + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/api/YSP.kt b/app/src/main/java/com/lizongying/mytv/api/YSP.kt index 413db75..23349cc 100644 --- a/app/src/main/java/com/lizongying/mytv/api/YSP.kt +++ b/app/src/main/java/com/lizongying/mytv/api/YSP.kt @@ -50,6 +50,9 @@ class YSP(var context: Context) { private var signature = "" + private var appid = "ysp_pc" + var token = "" + private var encryptor: Encryptor? = null private lateinit var sharedPref: SharedPreferences @@ -83,6 +86,19 @@ class YSP(var context: Context) { return """{"cnlid":"$cnlid","livepid":"$livepid","stream":"$stream","guid":"$guid","cKey":"$cKey","adjust":$adjust,"sphttps":"$sphttps","platform":"$platform","cmd":"$cmd","encryptVer":"$encryptVer","dtype":"$dtype","devid":"$devid","otype":"$otype","appVer":"$appVer","app_version":"$appVersion","rand_str":"$randStr","channel":"$channel","defn":"$defn","signature":"$signature"}""" } + fun getAuthData(tvModel: TVViewModel): String { + livepid = tvModel.pid.value!! + + randStr = getRand() + + if (tvModel.retryTimes > 0) { + guid = newGuid() + } + + signature = getAuthSignature() + return """pid=$livepid&guid=$guid&appid=$appid&rand_str=$randStr&signature=$signature""" + } + private fun getTimeStr(): String { return getDateTimestamp().toString() } @@ -131,6 +147,13 @@ class YSP(var context: Context) { return hashedData.let { it -> it.joinToString("") { "%02x".format(it) } } } + private fun getAuthSignature(): String { + val e = + "appid=${appid}&guid=${guid}&pid=${livepid}&rand_str=${randStr}".toByteArray() + val hashedData = encryptor?.hash2(e) ?: return "" + return hashedData.let { it -> it.joinToString("") { "%02x".format(it) } } + } + companion object { private const val TAG = "YSP" } diff --git a/app/src/main/java/com/lizongying/mytv/api/YSPApiService.kt b/app/src/main/java/com/lizongying/mytv/api/YSPApiService.kt index b121d07..563a17b 100644 --- a/app/src/main/java/com/lizongying/mytv/api/YSPApiService.kt +++ b/app/src/main/java/com/lizongying/mytv/api/YSPApiService.kt @@ -18,4 +18,16 @@ interface YSPApiService { @Header("cookie") cookie: String, @Body request: LiveInfoRequest, ): Call + + @POST("v1/player/auth") + @Headers( + "content-type: application/x-www-form-urlencoded;charset=UTF-8", + "referer: https://www.yangshipin.cn/", + "yspappid: 519748109", + "user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" + ) + fun getAuth( + @Header("cookie") cookie: String, + @Body request: AuthRequest, + ): Call } \ No newline at end of file diff --git a/app/src/main/java/com/lizongying/mytv/requests/MyRequest.kt b/app/src/main/java/com/lizongying/mytv/requests/MyRequest.kt new file mode 100644 index 0000000..412c504 --- /dev/null +++ b/app/src/main/java/com/lizongying/mytv/requests/MyRequest.kt @@ -0,0 +1,44 @@ +package com.lizongying.mytv.requests + +import com.lizongying.mytv.api.ApiClient +import com.lizongying.mytv.api.Release +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +class MyRequest { + private var releaseService = ApiClient().releaseService + + suspend fun getRelease(): Release? { + return withContext(Dispatchers.IO) { + fetchRelease() + } + } + + private suspend fun fetchRelease(): Release? { + return suspendCoroutine { continuation -> + releaseService.getRelease() + .enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + continuation.resume(response.body()) + } else { + continuation.resume(null) + } + } + + override fun onFailure(call: Call, t: Throwable) { + continuation.resume(null) + } + }) + } + } + + companion object { + private const val TAG = "MyRequest" + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/dialog.xml b/app/src/main/res/layout/dialog.xml index 819e99d..bb69502 100644 --- a/app/src/main/res/layout/dialog.xml +++ b/app/src/main/res/layout/dialog.xml @@ -27,7 +27,31 @@ android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="当前版本: $versionName\n获取最新: https://github.com/lizongying/my-tv/releases/" - > + /> + +