trust all certs
This commit is contained in:
parent
7821e8fa58
commit
b075a7db81
|
@ -5,6 +5,7 @@ import android.content.pm.PackageInfo
|
|||
import android.content.pm.PackageManager
|
||||
import android.content.pm.Signature
|
||||
import android.content.pm.SigningInfo
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
|
@ -36,7 +37,7 @@ class MainActivity : FragmentActivity() {
|
|||
private lateinit var gestureDetector: GestureDetector
|
||||
|
||||
private val handler = Handler()
|
||||
private val delay: Long = 3000
|
||||
private val delay: Long = 4000
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -170,6 +171,40 @@ class MainActivity : FragmentActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun showHelp() {
|
||||
val versionName = getPackageInfo().versionName
|
||||
|
||||
val textView = TextView(this)
|
||||
textView.text =
|
||||
"当前版本: $versionName\n获取最新: https://github.com/lizongying/my-tv/releases/"
|
||||
textView.setBackgroundColor(0xFF263238.toInt())
|
||||
textView.setPadding(20, 50, 20, 20)
|
||||
|
||||
val imageView = ImageView(this)
|
||||
val drawable = ContextCompat.getDrawable(this, R.drawable.appreciate)
|
||||
imageView.setImageDrawable(drawable)
|
||||
imageView.setBackgroundColor(Color.WHITE)
|
||||
|
||||
val linearLayout = LinearLayout(this)
|
||||
linearLayout.orientation = LinearLayout.VERTICAL
|
||||
linearLayout.addView(textView)
|
||||
linearLayout.addView(imageView)
|
||||
|
||||
val layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
imageView.layoutParams = layoutParams
|
||||
textView.layoutParams = layoutParams
|
||||
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
|
||||
builder
|
||||
.setView(linearLayout)
|
||||
|
||||
val dialog: AlertDialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_BACK -> {
|
||||
|
@ -192,35 +227,13 @@ class MainActivity : FragmentActivity() {
|
|||
return true
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_SETTINGS -> {
|
||||
showHelp()
|
||||
return true
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_MENU -> {
|
||||
val versionName = getPackageInfo().versionName
|
||||
|
||||
val textView = TextView(this)
|
||||
textView.text =
|
||||
"当前版本: $versionName\n获取最新: https://github.com/lizongying/my-tv/releases/"
|
||||
|
||||
val imageView = ImageView(this)
|
||||
val drawable = ContextCompat.getDrawable(this, R.drawable.appreciate)
|
||||
imageView.setImageDrawable(drawable)
|
||||
|
||||
val linearLayout = LinearLayout(this)
|
||||
linearLayout.orientation = LinearLayout.VERTICAL
|
||||
linearLayout.addView(textView)
|
||||
linearLayout.addView(imageView)
|
||||
|
||||
val layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
imageView.layoutParams = layoutParams
|
||||
textView.layoutParams = layoutParams
|
||||
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
|
||||
builder
|
||||
.setView(linearLayout)
|
||||
|
||||
val dialog: AlertDialog = builder.create()
|
||||
dialog.show()
|
||||
showHelp()
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,10 @@ class Request {
|
|||
ysp = YSP(context)
|
||||
}
|
||||
|
||||
var call: Call<LiveInfo>? = null
|
||||
|
||||
fun fetchVideo(tvModel: TVViewModel, cookie: String) {
|
||||
call?.cancel()
|
||||
if (::myRunnable.isInitialized) {
|
||||
handler.removeCallbacks(myRunnable)
|
||||
}
|
||||
|
@ -97,71 +100,71 @@ class Request {
|
|||
tvModel.seq = 0
|
||||
val data = ysp?.switch(tvModel)
|
||||
val request = data?.let { LiveInfoRequest(it) }
|
||||
call = request?.let { yspApiService.getLiveInfo("guid=${ysp?.getGuid()}; $cookie", it) }
|
||||
|
||||
request?.let { yspApiService.getLiveInfo(cookie, it) }
|
||||
?.enqueue(object : Callback<LiveInfo> {
|
||||
override fun onResponse(call: Call<LiveInfo>, response: Response<LiveInfo>) {
|
||||
if (response.isSuccessful) {
|
||||
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 regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""")
|
||||
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()
|
||||
Log.i(TAG, "$title url $url")
|
||||
tvModel.addVideoUrl(url)
|
||||
tvModel.allReady()
|
||||
tvModel.retryTimes = 0
|
||||
myRunnable = MyRunnable(tvModel)
|
||||
handler.post(myRunnable)
|
||||
} else {
|
||||
Log.e(TAG, "$title key error")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
}
|
||||
call?.enqueue(object : Callback<LiveInfo> {
|
||||
override fun onResponse(call: Call<LiveInfo>, response: Response<LiveInfo>) {
|
||||
if (response.isSuccessful) {
|
||||
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 regex = Regex("""des_key = "([^"]+).+var des_iv = "([^"]+)""")
|
||||
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()
|
||||
Log.i(TAG, "$title url $url")
|
||||
tvModel.addVideoUrl(url)
|
||||
tvModel.allReady()
|
||||
tvModel.retryTimes = 0
|
||||
myRunnable = MyRunnable(tvModel)
|
||||
handler.post(myRunnable)
|
||||
} else {
|
||||
if (liveInfo?.data?.errinfo != null && liveInfo.data.errinfo == "应版权方要求,暂停提供直播信号,请点击观看其他精彩节目") {
|
||||
Log.e(TAG, "$title error ${liveInfo.data.errinfo}")
|
||||
tvModel.setErrInfo(liveInfo.data.errinfo)
|
||||
} else {
|
||||
Log.e(TAG, "$title url error $request $liveInfo")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
Log.e(TAG, "$title key error")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "$title status error")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
if (liveInfo?.data?.errinfo != null && liveInfo.data.errinfo == "应版权方要求,暂停提供直播信号,请点击观看其他精彩节目") {
|
||||
Log.e(TAG, "$title error ${liveInfo.data.errinfo}")
|
||||
tvModel.setErrInfo(liveInfo.data.errinfo)
|
||||
} else {
|
||||
Log.e(TAG, "$title url error $request $liveInfo")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
|
||||
Log.e(TAG, "$title request error")
|
||||
} else {
|
||||
Log.e(TAG, "$title status error")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<LiveInfo>, t: Throwable) {
|
||||
Log.e(TAG, "$title request error")
|
||||
if (tvModel.retryTimes < tvModel.retryMaxTimes) {
|
||||
tvModel.retryTimes++
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun fetchVideo(tvModel: TVViewModel) {
|
||||
|
@ -172,7 +175,7 @@ class Request {
|
|||
val token = response.body()?.data?.token
|
||||
Log.i(TAG, "info success $token")
|
||||
val cookie =
|
||||
"guid=1; vplatform=109; yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
|
||||
"vplatform=109; yspopenid=vu0-8lgGV2LW9QjDeuBFsX8yMnzs37Q3_HZF6XyVDpGR_I; vusession=$token"
|
||||
fetchVideo(tvModel, cookie)
|
||||
} else {
|
||||
Log.e(TAG, "info status error")
|
||||
|
@ -197,7 +200,7 @@ class Request {
|
|||
if (tvModel.needToken) {
|
||||
fetchVideo(tvModel)
|
||||
} else {
|
||||
val cookie = "guid=1; vplatform=109"
|
||||
val cookie = "vplatform=109"
|
||||
fetchVideo(tvModel, cookie)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import okhttp3.OkHttpClient
|
|||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import retrofit2.converter.protobuf.ProtoConverterFactory
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
|
||||
class ApiClient {
|
||||
|
@ -13,9 +16,7 @@ class ApiClient {
|
|||
private val protoUrl = "https://capi.yangshipin.cn/"
|
||||
private val traceUrl = "https://btrace.yangshipin.cn/"
|
||||
|
||||
private var okHttpClient = OkHttpClient.Builder()
|
||||
.dns(DnsCache())
|
||||
.build()
|
||||
private var okHttpClient = getUnsafeOkHttpClient()
|
||||
|
||||
val yspApiService: YSPApiService by lazy {
|
||||
Retrofit.Builder()
|
||||
|
@ -48,4 +49,40 @@ class ApiClient {
|
|||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build().create(YSPBtraceService::class.java)
|
||||
}
|
||||
|
||||
private fun getUnsafeOkHttpClient(): OkHttpClient {
|
||||
try {
|
||||
val trustAllCerts: Array<TrustManager> = arrayOf(
|
||||
object : X509TrustManager {
|
||||
override fun checkClientTrusted(
|
||||
chain: Array<out java.security.cert.X509Certificate>?,
|
||||
authType: String?
|
||||
) {
|
||||
}
|
||||
|
||||
override fun checkServerTrusted(
|
||||
chain: Array<out java.security.cert.X509Certificate>?,
|
||||
authType: String?
|
||||
) {
|
||||
}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
|
||||
return emptyArray()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val sslContext = SSLContext.getInstance("SSL")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
|
||||
return OkHttpClient.Builder()
|
||||
.sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager)
|
||||
.hostnameVerifier { _, _ -> true }
|
||||
.dns(DnsCache())
|
||||
.build()
|
||||
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -71,7 +71,10 @@ class YSP(var context: Context) {
|
|||
|
||||
randStr = getRand()
|
||||
|
||||
guid = newGuid()
|
||||
if (tvModel.retryTimes > 0) {
|
||||
guid = newGuid()
|
||||
}
|
||||
|
||||
timeStr = getTimeStr()
|
||||
|
||||
// guid = "lq3oqitm_1e15dnzgjnb"
|
||||
|
@ -107,7 +110,7 @@ class YSP(var context: Context) {
|
|||
return guid
|
||||
}
|
||||
|
||||
fun newGuid(): String {
|
||||
private fun newGuid(): String {
|
||||
guid = generateGuid()
|
||||
with(sharedPref!!.edit()) {
|
||||
putString("guid", guid)
|
||||
|
|
Loading…
Reference in New Issue