2.3.5 release
parent
2da7de0a60
commit
a8b9647c62
@ -0,0 +1,179 @@
|
|||||||
|
package com.rehome.zhdcoa.utils
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.azhon.appupdate.base.BaseHttpDownloadManager
|
||||||
|
import com.azhon.appupdate.base.bean.DownloadStatus
|
||||||
|
import com.azhon.appupdate.config.Constant
|
||||||
|
import com.azhon.appupdate.util.LogUtil
|
||||||
|
import com.rehome.zhdcoa.R
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.net.HttpURLConnection
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
|
import java.net.URL
|
||||||
|
import java.security.KeyStore
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.net.ssl.HostnameVerifier
|
||||||
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.SSLSocketFactory
|
||||||
|
import javax.net.ssl.TrustManager
|
||||||
|
import javax.net.ssl.TrustManagerFactory
|
||||||
|
import javax.net.ssl.X509TrustManager
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProjectName: AppUpdate
|
||||||
|
* PackageName: com.azhon.appupdate.manager
|
||||||
|
* FileName: HttpDownloadManager
|
||||||
|
* CreateDate: 2022/4/7 on 14:29
|
||||||
|
* Desc:
|
||||||
|
*
|
||||||
|
* @author azhon
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
|
class AppUpdateHttpDownloadManager(private val path: String,private val context: Context) : BaseHttpDownloadManager() {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "HttpDownloadManager"
|
||||||
|
}
|
||||||
|
|
||||||
|
private var shutdown: Boolean = false
|
||||||
|
|
||||||
|
override fun download(apkUrl: String, apkName: String): Flow<DownloadStatus> {
|
||||||
|
LogUtil.i("app","-------------apkUrl----------")
|
||||||
|
LogUtil.i("app",apkUrl)
|
||||||
|
trustAllHosts(apkUrl)
|
||||||
|
shutdown = false
|
||||||
|
File(path, apkName).let {
|
||||||
|
if (it.exists()) it.delete()
|
||||||
|
}
|
||||||
|
return flow {
|
||||||
|
emit(DownloadStatus.Start)
|
||||||
|
connectToDownload(apkUrl, apkName, this)
|
||||||
|
}.catch {
|
||||||
|
emit(DownloadStatus.Error(it))
|
||||||
|
}.flowOn(Dispatchers.IO)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun connectToDownload(
|
||||||
|
apkUrl: String, apkName: String, flow: FlowCollector<DownloadStatus>
|
||||||
|
) {
|
||||||
|
val con = URL(apkUrl).openConnection() as HttpURLConnection
|
||||||
|
con.apply {
|
||||||
|
requestMethod = "GET"
|
||||||
|
readTimeout = Constant.HTTP_TIME_OUT
|
||||||
|
connectTimeout = Constant.HTTP_TIME_OUT
|
||||||
|
setRequestProperty("Accept-Encoding", "identity")
|
||||||
|
}
|
||||||
|
if (con.responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
val inStream = con.inputStream
|
||||||
|
val length = con.contentLength
|
||||||
|
var len: Int
|
||||||
|
var progress = 0
|
||||||
|
val buffer = ByteArray(1024 * 2)
|
||||||
|
val file = File(path, apkName)
|
||||||
|
FileOutputStream(file).use { out ->
|
||||||
|
while (inStream.read(buffer).also { len = it } != -1 && !shutdown) {
|
||||||
|
out.write(buffer, 0, len)
|
||||||
|
progress += len
|
||||||
|
flow.emit(DownloadStatus.Downloading(length, progress))
|
||||||
|
}
|
||||||
|
out.flush()
|
||||||
|
}
|
||||||
|
inStream.close()
|
||||||
|
if (shutdown) {
|
||||||
|
flow.emit(DownloadStatus.Cancel)
|
||||||
|
} else {
|
||||||
|
flow.emit(DownloadStatus.Done(file))
|
||||||
|
}
|
||||||
|
} else if (con.responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
||||||
|
|| con.responseCode == HttpURLConnection.HTTP_MOVED_TEMP
|
||||||
|
) {
|
||||||
|
con.disconnect()
|
||||||
|
val locationUrl = con.getHeaderField("Location")
|
||||||
|
LogUtil.d(
|
||||||
|
TAG,
|
||||||
|
"The current url is the redirect Url, the redirected url is $locationUrl"
|
||||||
|
)
|
||||||
|
connectToDownload(locationUrl, apkName, flow)
|
||||||
|
} else {
|
||||||
|
val e = SocketTimeoutException("Error: Http response code = ${con.responseCode}")
|
||||||
|
flow.emit(DownloadStatus.Error(e))
|
||||||
|
}
|
||||||
|
con.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fix https url (SSLHandshakeException) exception
|
||||||
|
*/
|
||||||
|
private fun trustAllHosts(url:String) {
|
||||||
|
if (url.startsWith("https://219.131.195.3:7100") || url.startsWith("https://219.131.195.3:7011") || url.startsWith(
|
||||||
|
"https://219.131.195.3:7081"
|
||||||
|
) || url.startsWith("https://219.131.195.3:7082")
|
||||||
|
) {
|
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(getSSLSocketFactory(context))
|
||||||
|
HttpsURLConnection.setDefaultHostnameVerifier { _, _ -> true }
|
||||||
|
}else{
|
||||||
|
val manager: TrustManager = object : X509TrustManager {
|
||||||
|
override fun getAcceptedIssuers(): Array<X509Certificate> {
|
||||||
|
return arrayOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
|
||||||
|
LogUtil.d(TAG, "checkClientTrusted")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
|
||||||
|
LogUtil.d(TAG, "checkServerTrusted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
|
sslContext.init(null, arrayOf(manager), SecureRandom())
|
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LogUtil.e(TAG, "trustAllHosts error: $e")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancel() {
|
||||||
|
shutdown = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun release() {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSSLSocketFactory(context: Context): SSLSocketFactory? {
|
||||||
|
try {
|
||||||
|
val certificateFactory = CertificateFactory.getInstance("X.509")
|
||||||
|
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
|
||||||
|
keyStore.load(null)
|
||||||
|
val certificateAlias = 0.toString()
|
||||||
|
keyStore.setCertificateEntry(
|
||||||
|
certificateAlias, certificateFactory.generateCertificate
|
||||||
|
(context.resources.openRawResource(R.raw.domain))
|
||||||
|
)
|
||||||
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
|
val trustManagerFactory =
|
||||||
|
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
|
||||||
|
trustManagerFactory.init(keyStore)
|
||||||
|
sslContext.init(
|
||||||
|
null,
|
||||||
|
trustManagerFactory.trustManagers,
|
||||||
|
SecureRandom()
|
||||||
|
)
|
||||||
|
return sslContext.socketFactory
|
||||||
|
} catch (ex: java.lang.Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue