parent
cbcfc0c315
commit
9bdb30e28f
|
|
@ -43,7 +43,6 @@ import com.google.accompanist.permissions.shouldShowRationale
|
||||||
import com.img.rabbit.R
|
import com.img.rabbit.R
|
||||||
import com.img.rabbit.components.CenterToast
|
import com.img.rabbit.components.CenterToast
|
||||||
import com.img.rabbit.provider.utils.NetworkUtils.globalNetworkStatus
|
import com.img.rabbit.provider.utils.NetworkUtils.globalNetworkStatus
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
|
|
||||||
@SuppressLint("UnrememberedMutableState")
|
@SuppressLint("UnrememberedMutableState")
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
|
|
||||||
|
|
@ -1,92 +1,384 @@
|
||||||
package com.img.rabbit.utils
|
package com.img.rabbit.utils
|
||||||
|
|
||||||
import okhttp3.Call
|
import android.os.Handler
|
||||||
import okhttp3.Callback
|
import android.os.Looper
|
||||||
import okhttp3.OkHttpClient
|
import android.util.Log
|
||||||
import okhttp3.Request
|
import okhttp3.*
|
||||||
import okhttp3.Response
|
import okhttp3.Headers.Companion.toHeaders
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import okio.Buffer
|
import java.io.*
|
||||||
import okio.BufferedSource
|
import java.net.URL
|
||||||
import okio.ForwardingSource
|
import java.util.concurrent.CancellationException
|
||||||
import okio.buffer
|
import java.util.concurrent.TimeUnit
|
||||||
import okio.sink
|
|
||||||
import java.io.File
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
object FileDownloadUtil {
|
|
||||||
private val client = OkHttpClient.Builder().build()
|
|
||||||
|
|
||||||
fun download(url: String, saveFile: File, listener: DownloadListener) {
|
class DownUtils private constructor() {
|
||||||
val request = Request.Builder().url(url).build()
|
|
||||||
|
|
||||||
// 拦截器处理进度
|
companion object {
|
||||||
val progressClient = client.newBuilder()
|
private const val TAG = "DownLoadUtils"
|
||||||
.addNetworkInterceptor { chain ->
|
private val downLoadHttpUtils: DownUtils by lazy {
|
||||||
val originalResponse = chain.proceed(chain.request())
|
DownUtils()
|
||||||
originalResponse.newBuilder()
|
|
||||||
.body(ProgressResponseBody(originalResponse.body, listener))
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
.build()
|
|
||||||
|
|
||||||
progressClient.newCall(request).enqueue(object : Callback {
|
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
|
||||||
listener.onError(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
@JvmStatic
|
||||||
if (!response.isSuccessful) {
|
@Synchronized
|
||||||
listener.onError(IOException("Unexpected code $response"))
|
fun getInstance(): DownUtils {
|
||||||
|
return downLoadHttpUtils
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var downloadSizeInfo = mutableMapOf<String, Long>()
|
||||||
|
private var cancelledList = mutableListOf<String>()
|
||||||
|
|
||||||
|
private var buffSize = 4096//建议设置为2048
|
||||||
|
fun setBuffSize(size: Int): DownUtils {
|
||||||
|
this.buffSize = size
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var interceptor: Interceptor? = null
|
||||||
|
fun setInterceptor(interceptor: Interceptor?): DownUtils {
|
||||||
|
this.interceptor = interceptor
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var readTimeOut = 30L
|
||||||
|
fun setReadTImeOut(read: Long): DownUtils {
|
||||||
|
this.readTimeOut = read
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var writeTimeout = 30L
|
||||||
|
fun setWriteTimeOut(write: Long): DownUtils {
|
||||||
|
this.writeTimeout = write
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var connectTimeout = 30L
|
||||||
|
fun setConnectTimeOut(connect: Long): DownUtils {
|
||||||
|
this.connectTimeout = connect
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
var filePath = ""
|
||||||
|
fun setFilePath(path: String): DownUtils {
|
||||||
|
this.filePath = path
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var fileName = ""
|
||||||
|
fun setFileName(name: String): DownUtils {
|
||||||
|
this.fileName = name
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var deleteWhenException = true
|
||||||
|
fun setDeleteWhenException(dele: Boolean): DownUtils {
|
||||||
|
this.deleteWhenException = dele
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private val requestBuilder: Request.Builder = Request.Builder()
|
||||||
|
private var urlBuilder: HttpUrl.Builder? = null
|
||||||
|
|
||||||
|
private val okHttpClient = lazy {
|
||||||
|
OkHttpClient.Builder()
|
||||||
|
.readTimeout(readTimeOut, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
|
||||||
|
.connectTimeout(connectTimeout, TimeUnit.SECONDS)
|
||||||
|
.addInterceptor(interceptor ?: LoggingInterceptor())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
private var actionGetTotal: (total: Long) -> Unit? = { _ -> }
|
||||||
|
private var actionProgress: (position: Long) -> Unit? = { _ -> }
|
||||||
|
private var actionSuccess: (file: File) -> Unit? = { _ -> }
|
||||||
|
private var actionCancel: () -> Unit? = { }
|
||||||
|
private var actionFail: (msg: String) -> Unit? = { _ -> }
|
||||||
|
|
||||||
|
fun setActionCallBack(
|
||||||
|
actionGetTotal: (total: Long) -> Unit,
|
||||||
|
actionProgress: (position: Long) -> Unit,
|
||||||
|
actionSuccess: (file: File) -> Unit,
|
||||||
|
actionFail: (msg: String) -> Unit,
|
||||||
|
): DownUtils {
|
||||||
|
this.actionGetTotal = actionGetTotal
|
||||||
|
this.actionProgress = actionProgress
|
||||||
|
this.actionSuccess = actionSuccess
|
||||||
|
this.actionFail = actionFail
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private var downCallBack: DownCallBack? = null
|
||||||
|
fun setDownCallBack(callBack: DownCallBack): DownUtils {
|
||||||
|
this.downCallBack = callBack
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun initUrl(url: String, params: Map<String, String>?): DownUtils {
|
||||||
|
urlBuilder = url.toHttpUrlOrNull()?.newBuilder()
|
||||||
|
if (params.isNullOrEmpty()) {
|
||||||
|
return this
|
||||||
|
} else {
|
||||||
|
for ((k, v) in params) {
|
||||||
|
checkName(k)
|
||||||
|
urlBuilder?.setQueryParameter(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHeader(map: Map<String, String>): DownUtils {
|
||||||
|
requestBuilder.headers(map.toHeaders())
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkName(name: String) {
|
||||||
|
require(name.isNotEmpty()) { "name is empty" }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun down() {
|
||||||
|
if (urlBuilder == null) {
|
||||||
|
throw IllegalStateException("url not init")
|
||||||
|
} else {
|
||||||
|
doDown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doDown() {
|
||||||
|
val startTime = System.currentTimeMillis()
|
||||||
|
Log.i(TAG, "startTime=$startTime")
|
||||||
|
val url = urlBuilder?.build()
|
||||||
|
if (url == null) {
|
||||||
|
doException("url is null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (isDowning(filePath + fileName)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cancelledList.remove(fileName)
|
||||||
|
|
||||||
|
val currentLen = downloadSizeInfo[fileName] ?: 0L
|
||||||
|
if (isCanContinueDownload(url.toUrl(), currentLen)) {
|
||||||
|
requestBuilder.removeHeader("RANGE")
|
||||||
|
requestBuilder.addHeader("RANGE", "bytes=${currentLen}-")
|
||||||
|
}
|
||||||
|
val request = requestBuilder.url(url).tag(filePath + fileName).build()
|
||||||
|
|
||||||
|
var `is`: InputStream? = null
|
||||||
|
var raf: RandomAccessFile? = null
|
||||||
|
var file: File? = null
|
||||||
try {
|
try {
|
||||||
val totalSize = response.body.contentLength()
|
val response = okHttpClient.value.newCall(request).execute()
|
||||||
listener.onStart(totalSize)
|
val total = response.body.contentLength()
|
||||||
|
doGetTotal(currentLen + total)
|
||||||
|
|
||||||
response.body.source().use { source ->
|
val buf = ByteArray(buffSize)
|
||||||
saveFile.sink().buffer().use { sink ->
|
var len: Int
|
||||||
sink.writeAll(source)
|
|
||||||
|
file = if (fileName.isEmpty()) {
|
||||||
|
File(filePath)
|
||||||
|
} else {
|
||||||
|
val fileDir = File(filePath)
|
||||||
|
if (!fileDir.exists() || !fileDir.isDirectory) {
|
||||||
|
fileDir.mkdirs()
|
||||||
}
|
}
|
||||||
|
File(filePath, fileName)
|
||||||
}
|
}
|
||||||
listener.onSuccess(saveFile)
|
|
||||||
|
`is` = response.body.byteStream()
|
||||||
|
raf = RandomAccessFile(file, "rw")
|
||||||
|
raf.seek(currentLen)
|
||||||
|
|
||||||
|
var sum: Long = currentLen
|
||||||
|
while (`is`.read(buf).also { len = it } != -1) {
|
||||||
|
if (isCancelled()) throw CancellationException()
|
||||||
|
raf.write(buf, 0, len)
|
||||||
|
sum += len.toLong()
|
||||||
|
downloadSizeInfo[fileName] = sum
|
||||||
|
doProgress(sum)
|
||||||
|
}
|
||||||
|
Log.e(TAG, "download success")
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw FileNotFoundException("file create err,not exists")
|
||||||
|
} else {
|
||||||
|
doSuccess(file)
|
||||||
|
}
|
||||||
|
Log.e(TAG, "totalTime=" + (System.currentTimeMillis() - startTime))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
listener.onError(e)
|
if (deleteWhenException && file?.exists() == true) file.delete()
|
||||||
|
Log.e(TAG, "download failed : " + e.message)
|
||||||
|
doException(e.message.toString())
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
`is`?.close()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
raf?.close()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
private fun isCanContinueDownload(url: URL, start: Long): Boolean { //是否支持断点下载
|
||||||
|
val requestBuilder = Request.Builder()
|
||||||
|
requestBuilder.addHeader("RANGE", "bytes=$start-")
|
||||||
|
requestBuilder.addHeader("Connection", "close")
|
||||||
|
val request: Request = requestBuilder.url(url).head().build()
|
||||||
|
val response: Response = okHttpClient.value.newCall(request).execute()
|
||||||
|
return if (response.isSuccessful) {
|
||||||
|
if (response.code == 206) { //支持
|
||||||
|
response.close()
|
||||||
|
true
|
||||||
|
} else { //不支持
|
||||||
|
response.close()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.close()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isDowning(tag: String): Boolean {
|
||||||
|
for (call in okHttpClient.value.dispatcher.runningCalls()) {
|
||||||
|
if (call.request().tag() == tag) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isCancelled(): Boolean {
|
||||||
|
return cancelledList.contains(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancel() {
|
||||||
|
cancel(filePath + fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancel(tag: String) {
|
||||||
|
cancelledList.add(fileName)
|
||||||
|
if (okHttpClient.value.dispatcher.runningCalls().isNotEmpty()) {
|
||||||
|
for (call in okHttpClient.value.dispatcher.runningCalls()) {
|
||||||
|
if (call.request().tag() == tag) {
|
||||||
|
call.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doCancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doException(err: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
if (downCallBack == null) {
|
||||||
|
actionFail.invoke(err)
|
||||||
|
} else {
|
||||||
|
downCallBack?.fail(err)
|
||||||
|
}
|
||||||
|
mainThread = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doSuccess(file: File?) {
|
||||||
|
runOnUiThread {
|
||||||
|
if (file == null) {
|
||||||
|
doException("file not exit")
|
||||||
|
} else {
|
||||||
|
if (downCallBack == null) {
|
||||||
|
actionSuccess.invoke(file)
|
||||||
|
} else {
|
||||||
|
downCallBack?.success(file)
|
||||||
|
}
|
||||||
|
downloadSizeInfo.remove(fileName)
|
||||||
|
}
|
||||||
|
mainThread = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doGetTotal(total: Long) {
|
||||||
|
runOnUiThread {
|
||||||
|
if (downCallBack == null) {
|
||||||
|
actionGetTotal.invoke(total)
|
||||||
|
} else {
|
||||||
|
downCallBack?.total(total)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mainThread = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doProgress(progress: Long) {
|
||||||
|
runOnUiThread {
|
||||||
|
if (downCallBack == null) {
|
||||||
|
actionProgress.invoke(progress)
|
||||||
|
} else {
|
||||||
|
downCallBack?.progress(progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doCancel() {
|
||||||
|
runOnUiThread {
|
||||||
|
if (downCallBack == null) {
|
||||||
|
actionCancel.invoke()
|
||||||
|
} else {
|
||||||
|
downCallBack?.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mainThread = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mainThread: Handler? = null
|
||||||
|
private fun runOnUiThread(action: () -> Unit) {
|
||||||
|
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||||
|
if (mainThread == null) {
|
||||||
|
mainThread = Handler(Looper.getMainLooper())
|
||||||
|
}
|
||||||
|
mainThread?.post {
|
||||||
|
action.invoke()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
action.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LoggingInterceptor : Interceptor {
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val request: Request = chain.request()
|
||||||
|
val startTime = System.nanoTime()
|
||||||
|
Log.d(
|
||||||
|
TAG, String.format(
|
||||||
|
"Sending request %s on %s%n%s",
|
||||||
|
request.url, chain.connection(), request.headers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val response: Response = chain.proceed(request)
|
||||||
|
val endTime = System.nanoTime()
|
||||||
|
Log.d(
|
||||||
|
TAG, String.format(
|
||||||
|
"Received response for %s in %.1fms%n%s",
|
||||||
|
response.request.url, (endTime - startTime) / 1e6, response.headers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "LoggingInterceptor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DownCallBack {
|
||||||
|
fun success(file: File)
|
||||||
|
fun fail(str: String)
|
||||||
|
fun progress(position: Long)
|
||||||
|
fun total(total: Long)
|
||||||
|
fun cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进度回调接口
|
|
||||||
interface DownloadListener {
|
|
||||||
fun onStart(totalSize: Long) // 开始下载,返回文件总大小
|
|
||||||
fun onProgress(progress: Int, current: Long) // 进度(0-100),当前已下载字节
|
|
||||||
fun onSuccess(file: File) // 下载成功
|
|
||||||
fun onError(e: Exception) // 下载失败
|
|
||||||
}
|
|
||||||
|
|
||||||
// 自定义 ResponseBody 用于拦截进度
|
|
||||||
class ProgressResponseBody(
|
|
||||||
private val responseBody: ResponseBody,
|
|
||||||
private val listener: DownloadListener
|
|
||||||
) : ResponseBody() {
|
|
||||||
override fun contentType() = responseBody.contentType()
|
|
||||||
override fun contentLength() = responseBody.contentLength()
|
|
||||||
|
|
||||||
override fun source(): BufferedSource {
|
|
||||||
return object : ForwardingSource(responseBody.source()) {
|
|
||||||
var totalBytesRead = 0L
|
|
||||||
override fun read(sink: Buffer, byteCount: Long): Long {
|
|
||||||
val bytesRead = super.read(sink, byteCount)
|
|
||||||
totalBytesRead += if (bytesRead != -1L) bytesRead else 0
|
|
||||||
val progress = if (contentLength() > 0) (totalBytesRead * 100 / contentLength()).toInt() else 0
|
|
||||||
// 回调进度
|
|
||||||
listener.onProgress(progress, totalBytesRead)
|
|
||||||
return bytesRead
|
|
||||||
}
|
|
||||||
}.buffer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,10 +152,8 @@ object UniAppUtils {
|
||||||
private fun startUniMp(context: Context, uniVersion: UniVersionEntity, onResult:(loading: Boolean) -> Unit){
|
private fun startUniMp(context: Context, uniVersion: UniVersionEntity, onResult:(loading: Boolean) -> Unit){
|
||||||
val uniMp = _uniMpFlow.value[uniVersion.unimp_id]//uniMpPair[uniVersion.unimp_id]
|
val uniMp = _uniMpFlow.value[uniVersion.unimp_id]//uniMpPair[uniVersion.unimp_id]
|
||||||
if(uniMp?.isRuning == true){
|
if(uniMp?.isRuning == true){
|
||||||
Log.i(TAG, "startUniMp: 运行中...")
|
|
||||||
uniMp.showUniMP()
|
uniMp.showUniMP()
|
||||||
}else{
|
}else{
|
||||||
Log.i(TAG, "startUniMp: 重新加载...")
|
|
||||||
val configuration = getUniMPOpenConfiguration()
|
val configuration = getUniMPOpenConfiguration()
|
||||||
if(uniVersion.unimp_type == "wx"){
|
if(uniVersion.unimp_type == "wx"){
|
||||||
configuration.splashClass = UniMPWxSplashView::class.java
|
configuration.splashClass = UniMPWxSplashView::class.java
|
||||||
|
|
@ -278,7 +276,6 @@ object UniAppUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if(uniState == UniMpUpdate.DOWNLOAD_FAIL){
|
}else if(uniState == UniMpUpdate.DOWNLOAD_FAIL){
|
||||||
Log.i(TAG, "下载wgt失败...")
|
|
||||||
onProgress(UniMpUpdate.DOWNLOAD_FAIL, -1f)
|
onProgress(UniMpUpdate.DOWNLOAD_FAIL, -1f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -307,16 +304,13 @@ object UniAppUtils {
|
||||||
|
|
||||||
oldFile.delete()
|
oldFile.delete()
|
||||||
}
|
}
|
||||||
onProgress(UniMpUpdate.DOWNLOAD_LOADING, null, 0.001f)
|
onProgress(UniMpUpdate.DOWNLOAD_LOADING, null, 0.0f)
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val isAvailable = isFileDownloadable(uniVersion.url)
|
val isAvailable = isFileDownloadable(uniVersion.url)
|
||||||
if(!isAvailable){
|
if(!isAvailable){
|
||||||
Log.i(TAG, "下载失败,无效地址 ------>${uniVersion.url}")
|
|
||||||
onProgress(UniMpUpdate.DOWNLOAD_FAIL, null, -1f)
|
onProgress(UniMpUpdate.DOWNLOAD_FAIL, null, -1f)
|
||||||
CenterToast.show("下载失败...")
|
|
||||||
}else{
|
}else{
|
||||||
Log.i(TAG, "下载wgt---->downloadUniMp: $path/$wgtName ------>${uniVersion.url}")
|
|
||||||
UpdateUtils.download(
|
UpdateUtils.download(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
url = uniVersion.url,
|
url = uniVersion.url,
|
||||||
|
|
@ -334,10 +328,8 @@ object UniAppUtils {
|
||||||
onFinish = {isSuccess, filePath ->
|
onFinish = {isSuccess, filePath ->
|
||||||
if(isSuccess){
|
if(isSuccess){
|
||||||
PreferenceUtil.saveWgtVersion(uniMpId, uniVersion.version)
|
PreferenceUtil.saveWgtVersion(uniMpId, uniVersion.version)
|
||||||
Log.i(TAG, "下载完成---->updateUniMp: $filePath")
|
|
||||||
onProgress(UniMpUpdate.DOWNLOAD_FINISH, filePath, 1f)
|
onProgress(UniMpUpdate.DOWNLOAD_FINISH, filePath, 1f)
|
||||||
}else{
|
}else{
|
||||||
Log.i(TAG, "下载失败---->updateUniMp: $filePath")
|
|
||||||
onProgress(UniMpUpdate.DOWNLOAD_FAIL, filePath, -1f)
|
onProgress(UniMpUpdate.DOWNLOAD_FAIL, filePath, -1f)
|
||||||
|
|
||||||
CenterToast.show("下载失败...")
|
CenterToast.show("下载失败...")
|
||||||
|
|
@ -419,7 +411,7 @@ object UniAppUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.i(TAG, "异常:${e.message}")
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
return@withContext false
|
return@withContext false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ import kotlinx.coroutines.launch
|
||||||
import net.lingala.zip4j.ZipFile
|
import net.lingala.zip4j.ZipFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新管理器(本质下载器包装)
|
||||||
|
*/
|
||||||
object UpdateUtils {
|
object UpdateUtils {
|
||||||
private const val TAG = "UpdateUtils"
|
private const val TAG = "UpdateUtils"
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
|
|
@ -20,12 +23,38 @@ object UpdateUtils {
|
||||||
if(destination.exists()){
|
if(destination.exists()){
|
||||||
destination.delete()
|
destination.delete()
|
||||||
}
|
}
|
||||||
FileDownloadUtil.download(url, destination, object : DownloadListener {
|
var totalProgress = 0L
|
||||||
|
DownUtils.getInstance()
|
||||||
|
.setReadTImeOut(10L)
|
||||||
|
.setDeleteWhenException(false)
|
||||||
|
.initUrl(url, null)
|
||||||
|
.setFilePath(filePath)
|
||||||
|
.setFileName(fileName)
|
||||||
|
.setActionCallBack(
|
||||||
|
{ totalProgress = it },
|
||||||
|
{
|
||||||
|
val percent = it.toDouble() / totalProgress.toDouble() * 100
|
||||||
|
val curProgress = percent.toInt()
|
||||||
|
onProgress(curProgress)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onFinish(true, it.absolutePath)
|
||||||
|
}, {
|
||||||
|
onFinish(false, null)
|
||||||
|
}).down()
|
||||||
|
|
||||||
|
/*
|
||||||
|
applicationContext?.let {
|
||||||
|
AutoDownloadManager.startAutoDownload(it, url, destination,object: DownloadListener {
|
||||||
override fun onStart(totalSize: Long) {
|
override fun onStart(totalSize: Long) {
|
||||||
onProgress(0)
|
onProgress(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onProgress(progress: Int, current: Long) {
|
override fun onProgress(
|
||||||
|
progress: Int,
|
||||||
|
current: Long,
|
||||||
|
total: Long
|
||||||
|
) {
|
||||||
onProgress(progress)
|
onProgress(progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,6 +67,8 @@ object UpdateUtils {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun install(context: Context, apkFilePath: String) {
|
fun install(context: Context, apkFilePath: String) {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.img.rabbit.bean.local.ErrorBean
|
import com.img.rabbit.bean.local.ErrorBean
|
||||||
import com.img.rabbit.provider.api.ApiManager
|
import com.img.rabbit.provider.api.ApiManager
|
||||||
import com.img.rabbit.utils.DownloadListener
|
import com.img.rabbit.utils.DownUtils
|
||||||
import com.img.rabbit.utils.FileDownloadUtil
|
|
||||||
import com.img.rabbit.utils.FileUtils
|
import com.img.rabbit.utils.FileUtils
|
||||||
import com.img.rabbit.utils.ImageUtils
|
import com.img.rabbit.utils.ImageUtils
|
||||||
import com.img.rabbit.utils.PhotoCutter
|
import com.img.rabbit.utils.PhotoCutter
|
||||||
|
|
@ -104,25 +103,34 @@ class CutoutViewModel : BaseViewModel() {
|
||||||
targetFile.delete()
|
targetFile.delete()
|
||||||
}
|
}
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
FileDownloadUtil.download(url, targetFile, object : DownloadListener {
|
DownUtils.getInstance()
|
||||||
override fun onStart(totalSize: Long) {
|
.initUrl(url, null)
|
||||||
}
|
.setFilePath(targetPath)
|
||||||
|
.setFileName(targetFileName)
|
||||||
override fun onProgress(progress: Int, current: Long) {
|
.setDownCallBack(object : DownUtils.DownCallBack {
|
||||||
// 如果需要进度可以在这里处理
|
override fun success(file: File) {
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSuccess(file: File) {
|
|
||||||
// 3. 下载成功后,将文件解析为 Bitmap 并回调给 UI
|
// 3. 下载成功后,将文件解析为 Bitmap 并回调给 UI
|
||||||
val bitmap = android.graphics.BitmapFactory.decodeFile(file.absolutePath)
|
val bitmap = android.graphics.BitmapFactory.decodeFile(file.absolutePath)
|
||||||
onResult(true, bitmap)
|
onResult(true, bitmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Exception) {
|
override fun fail(str: String) {
|
||||||
|
onResult(false, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun progress(position: Long) {
|
||||||
|
// 如果需要进度可以在这里处理
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun total(total: Long) {
|
||||||
|
// 获取总大小
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancel() {
|
||||||
onResult(false, null)
|
onResult(false, null)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.down()
|
||||||
}
|
}
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.rememberNavController
|
|
||||||
import com.img.rabbit.bean.response.UniVersionEntity
|
|
||||||
import com.img.rabbit.config.Constants
|
import com.img.rabbit.config.Constants
|
||||||
import com.img.rabbit.provider.api.ApiManager
|
import com.img.rabbit.provider.api.ApiManager
|
||||||
import com.img.rabbit.provider.storage.PreferenceUtil
|
import com.img.rabbit.provider.storage.PreferenceUtil
|
||||||
|
|
@ -27,8 +25,6 @@ import com.tencent.mm.opensdk.constants.ConstantsAPI
|
||||||
import com.tencent.mm.opensdk.openapi.IWXAPI
|
import com.tencent.mm.opensdk.openapi.IWXAPI
|
||||||
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
import com.tencent.mm.opensdk.openapi.WXAPIFactory
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
|
||||||
|
|
||||||
@SuppressLint("ObsoleteSdkInt")
|
@SuppressLint("ObsoleteSdkInt")
|
||||||
class GeneralViewModel: BaseViewModel(){
|
class GeneralViewModel: BaseViewModel(){
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue