okhttp实现app更新

okhttp实现app更新

使用 OkHttp 的 Interceptor 来监听下载进度并更新进度条

1.创建一个自定义的 OkHttp Interceptor 来监听下载进度

import okhttp3.Interceptor
import okhttp3.Response
import okhttp3.ResponseBody

class ProgressInterceptor(private val listener: ProgressListener) : Interceptor {

    interface ProgressListener {
        fun onProgress(bytesRead: Long, contentLength: Long, done: Boolean)
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val originalResponse = chain.proceed(chain.request())
        return originalResponse.newBuilder()
            .body(ProgressResponseBody(originalResponse.body!!, listener))
            .build()
    }
}

2.创建一个自定义的 ResponseBody,其中会回调进度监听器以更新进度条

import okhttp3.MediaType
import okhttp3.ResponseBody
import okio.*
import java.io.IOException

class ProgressResponseBody(
    private val responseBody: ResponseBody,
    private val listener: ProgressInterceptor.ProgressListener
) : ResponseBody() {

    private var bufferedSource: BufferedSource? = null

    override fun contentLength(): Long {
        return responseBody.contentLength()
    }

    override fun contentType(): MediaType? {
        return responseBody.contentType()
    }

    override fun source(): BufferedSource {
        if (bufferedSource == null) {
            bufferedSource = source(responseBody.source()).buffer()
        }
        return bufferedSource!!
    }

    private fun source(source: Source): Source {
        return object : ForwardingSource(source) {
            private var totalBytesRead = 0L

            @Throws(IOException::class)
            override fun read(sink: Buffer, byteCount: Long): Long {
                val bytesRead = super.read(sink, byteCount)
                totalBytesRead += if (bytesRead != -1L) bytesRead else 0
                listener.onProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1L)
                return bytesRead
            }
        }
    }
}

3.创建一个实现进度监听器的回调函数

class DownloadCallback(private val progressBar: ProgressBar) : ProgressInterceptor.ProgressListener {
    override fun onProgress(bytesRead: Long, contentLength: Long, done: Boolean) {
        val percentage = (bytesRead * 100 / contentLength).toInt()
        // 更新进度条
        progressBar.progress = percentage
    }
}

4.使用这些组件来下载文件并更新进度条

fun downloadFileWithProgress(
    url: String,
    destPath: String,
    progressBar: ProgressBar,
    onComplete: (success: Boolean) -> Unit
) {
    val client = OkHttpClient.Builder()
        .addNetworkInterceptor(ProgressInterceptor(DownloadCallback(progressBar)))
        .build()

    val request = Request.Builder().url(url).build()

    client.newCall(request).enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            // 处理下载失败的情况
            e.printStackTrace()
            onComplete(false) // 标记下载失败
        }

        override fun onResponse(call: Call, response: Response) {
            if (!response.isSuccessful) {
                // 处理响应不成功的情况
                onComplete(false) // 标记下载失败
                return
            }

            val responseBody = response.body
            if (responseBody != null) {
                // 下载和保存文件的逻辑与之前相同
                val inputStream = responseBody.byteStream()
                val outputStream = FileOutputStream(destPath)
                val buffer = ByteArray(4096)
                var bytesRead: Int

                while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                    outputStream.write(buffer, 0, bytesRead)
                }

                outputStream.flush()
                outputStream.close()
                inputStream.close()

                onComplete(true) // 标记下载成功
            }
        }
    })
}

安装app

1.安装

fun startApkInstallation(apkFilePath: String) {
    val apkFile = File(apkFilePath)
    if (apkFile.exists()) {
        val intent = Intent(Intent.ACTION_VIEW)
        val apkUri = FileProvider.getUriForFile(
            applicationContext,
            BuildConfig.APPLICATION_ID + ".provider",
            apkFile
        )
        intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        startActivity(intent)
    }
}

2.在AndroidManifest.xml 文件中配置FileProvider

<application>
    ...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>
    ...
</application>

3.在 res/xml 目录下创建一个 provider_paths.xml 文件,用于配置 FileProvider

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="external_files"
        path="." />
</paths>

4.AndroidManifest.xml 文件中配置权限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值