ApkInstallTool.kt 6.9 KB
Newer Older
1
package com.ydl.ydlcommon.utils
konghaorui committed
2 3 4 5 6 7 8 9 10 11 12

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.support.v4.content.FileProvider
import com.tbruyelle.rxpermissions2.RxPermissions
import com.yidianling.common.tools.ToastUtil
13
import com.ydl.ydlcommon.bean.VersionData
konghaorui committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.net.HttpURLConnection
import java.net.MalformedURLException
import java.net.URL

/**
 * apk安装工具类
 */
class ApkInstallTool {

    private var activity : Activity? = null

    private var listener: UpdateProgressListener? = null

31
    private var updateData: VersionData? = null
konghaorui committed
32 33 34

    private var isDownload = true

35
    fun start(activity : Activity?, version: VersionData?, listener: UpdateProgressListener?){
konghaorui committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
        this.activity = activity
        this.listener = listener
        this.updateData = version

        checkIsAndroidO(activity)
    }

    interface UpdateProgressListener {
        fun progress(progress: Int)

        fun startLoad()
    }

    /**
     * 判断是否是8.0,8.0需要处理未知应用来源权限问题,否则直接安装
     */
     private fun checkIsAndroidO(context: Activity?) {
        if (context==null)return
        if (Build.VERSION.SDK_INT >= 26) {
            val b = context.packageManager.canRequestPackageInstalls()
            if (b) {
                startDownload()//安装应用的逻辑
            } else {
                //请求安装未知应用来源的权限
                context.runOnUiThread{
                    RxPermissions(context)
                            .requestEach(Manifest.permission.REQUEST_INSTALL_PACKAGES)
                            .subscribe { permission ->
                                if (permission.granted) {
                                    startDownload()
                                } else if (permission.shouldShowRequestPermissionRationale) {
                                    checkIsAndroidO(context)
                                } else {
                                    ToastUtil.toastLong(context, "在线更新,请允许开启系统未知来源安装")
                                    val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
                                    context.startActivity(intent)
                                }
                            }
                }
            }
        } else {
            startDownload()
        }

    }

    /**
     * 开始下载
     */
    fun startDownload(){
        DownloadApkThread().start()
        listener?.startLoad()
    }

    companion object{
        /**
         * 通过隐式意图调用系统安装程序安装APK
         * 兼容7.0
         */
        fun installApk(filePath : String,context: Context?) {

            setPermission(filePath)
            val file = File(filePath)
            val intent = Intent(Intent.ACTION_VIEW)
            // 由于没有在Activity环境下启动Activity,设置下面的标签
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            if (Build.VERSION.SDK_INT >= 24) { //判读版本是否在7.0以上
                //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
                val apkUri = FileProvider.getUriForFile(context, "com.cxzapp.yidianling.fileprovider", file)
                //添加这一句表示对目标应用临时授权该Uri所代表的文件
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
            } else {
                intent.setDataAndType(Uri.fromFile(file),
                        "application/vnd.android.package-archive")
            }
            context?.startActivity(intent)
        }

        /**
         * 提升读写权限
         * @param filePath 文件路径
         * @return
         * @throws IOException
         */
        private fun setPermission(filePath: String) {
            val command = "chmod 777 $filePath"
            val runtime = Runtime.getRuntime()
            try {
                runtime.exec(command)
            } catch (e: IOException) {
                e.printStackTrace()
            }

        }
    }

    fun cancleDown(){
        isDownload = false
        listener = null
    }

    /**
     * 下载文件线程
     */
    inner class DownloadApkThread : Thread() {
        override fun run() {
            try {
                // 判断SD卡是否存在
145
                if (FileUtil2.ExistSDCard()) {
konghaorui committed
146
                    // 获得存储卡的路径
147
                    var downloadPath = FileUtil2.getLocalStorePath("download")
konghaorui committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
                    val url = URL(updateData?.installLink)
                    //URL url = new URL("http://d2.eoemarket.com/app0/16/16371/apk/1353803.apk");
                    // 创建连接
                    val conn = url.openConnection() as HttpURLConnection
                    conn.connect()
                    // 获取文件大小
                    val length = conn.contentLength
                    // 创建输入流
                    val `is` = conn.inputStream

                    val file = File(downloadPath)
                    // 判断文件目录是否存在
                    if (!file.exists()) {
                        file.mkdir()
                    }

                    var apkName = "ydl-user-" + updateData?.ver + ".apk"
                    val apkFile = File(downloadPath, apkName)
                    val fos = FileOutputStream(apkFile)
                    var count = 0
                    // 缓存
                    val buf = ByteArray(1024)
                    // 写入到文件中
                    do {
                        val numread = `is`.read(buf)
                        count += numread
                        // 计算进度条位置
                        val progress = (count.toFloat() / length * 100).toInt()
                        // 更新进度
                        listener?.progress(progress)
                        if (numread <= 0 && listener!=null) {
                            // 下载完成
                            installApk(
                                apkFile.absolutePath,
                                activity
                            )
                            listener?.progress(100)
                            break
                        }
                        // 写入文件
                        fos.write(buf, 0, numread)
                    } while (isDownload)// 点击取消就停止下载.
                    fos.close()
                    `is`.close()
                }
            } catch (e: MalformedURLException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

}