Android Asset目錄下的Apk文件的複製安裝

1.項目結構

其中
target.apk爲目標apk,包名爲 com.zian.target
PermissionManager爲權限工具類
(權限以及安裝可以參考我另一篇博客 : https://blog.csdn.net/qq_30837235/article/details/83383230)

2.代碼

//權限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>
import android.Manifest
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import kotlinx.android.synthetic.main.activity_main.*
import java.io.*


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.w("device", android.os.Build.BRAND)
        btn_to_app.setOnClickListener {
            toApp()
        }
    }

    fun toApp() {
        //如果已安裝 跳轉
        if (checkAppInstalled(this, "com.zian.target")) {
            val intent = packageManager.getLaunchIntentForPackage("com.zian.target")
            if (intent != null) {
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                startActivity(intent)
            }
        } else {
            showInstallDialog()
        }
    }

    /**
     * 通過包名判斷是否已安裝該應用
     * (可能有更好的解決方案)
     */
    fun checkAppInstalled(context: Context, pkgName: String): Boolean {
        val pm = context.packageManager
        val infoList = pm.getInstalledPackages(0)
        if (infoList == null) {
            return false
        } else {
            for (packageBean in infoList) {
                if (pkgName == packageBean.packageName) {
                    return true
                }
            }
        }
        return false
    }

    fun showInstallDialog() {
        val builder = AlertDialog.Builder(this)
        builder
            .setMessage("安裝Target.Apk,是否繼續")
            .setPositiveButton("安裝") { dialogInterface, i ->
                dialogInterface.dismiss()

                requestPermission()
            }
            .setNegativeButton("取消") { dialogInterface, i -> dialogInterface.dismiss() }
        builder.setCancelable(false)
        builder.show()
    }

    //文件寫入權限請求
    fun requestPermission() {
        PermissionManager.newBuilder(this)
            .setPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .callBack(object : PermissionManager.PermissionRequestCallBack {
                override fun successCallBack() {
                    prepareInstall(this@MainActivity)
                }

                override fun failureCallBack() {
                    showGetPermissionDialog(this@MainActivity)
                }
            })

    }


    fun showGetPermissionDialog(context: Context) {
        val builder = AlertDialog.Builder(context)
        builder.setTitle("權限管理")
            .setMessage("請開啓相應權限")
            .setPositiveButton("前往") { dialogInterface, i ->
                dialogInterface.dismiss()
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                intent.data = Uri.parse("package:" + context.packageName)
                context.startActivity(intent)
            }
            .setNegativeButton("取消") { dialogInterface, i -> dialogInterface.dismiss() }
        builder.setCancelable(false)
        builder.show()
    }

    //複製asset目錄下的apk文件並安裝
    fun prepareInstall(context: Context) {

        val assets = context.assets
        try {
            val stream = assets.open("target.apk")
            if (stream == null) {
                Log.e("error", "no file")
                return
            }
            val folder = Environment.getExternalStorageDirectory()
                .absolutePath + "/apk/"
            val f = File(folder)
            if (!f.exists()) {
                f.mkdir()
            }
            val apkPath = Environment.getExternalStorageDirectory()
                .absolutePath + "/apk/" + "target.apk"
            val file = File(apkPath)
            file.createNewFile()
            writeStreamToFile(stream, file)
            installApp(context, "com.zian.apptest", apkPath)
        } catch (e: IOException) {

            e.printStackTrace()
        }

    }

    private fun writeStreamToFile(stream: InputStream, file: File) {
        try {
            var output: OutputStream? = null
            try {
                output = FileOutputStream(file)
            } catch (e1: FileNotFoundException) {
                e1.printStackTrace()
            }

            try {
                try {
                    val buffer = ByteArray(1024)
                    var read = 0
                    while (true) {
                        output!!.write(buffer, 0, read)
                        read = stream.read(buffer)
                        if (read <= 0) {
                            break
                        }
                    }
                    output!!.flush()
                } finally {
                    output!!.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

        } finally {
            try {
                stream.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }

        }
    }

    fun installApp(context: Context, packageName: String, filePath: String) {
        val appFile = File(filePath)
        if (!appFile.parentFile.exists()) {
            appFile.parentFile.mkdir()
        }
        //判斷版本是否在7.0以上
        //跳轉到新版本應用安裝頁面
        if (Build.VERSION.SDK_INT >= 24) {
            //yourname 是定義在xxxx.xml中的值
            val apkUri = FileProvider.getUriForFile(
                context,
                "$packageName.fileprovider",
                appFile
            )//在AndroidManifest中的android:authorities值
            val install = Intent(Intent.ACTION_VIEW)
            install.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            install.setDataAndType(apkUri, "application/vnd.android.package-archive")
            context.startActivity(install)
        } else {
            val install = Intent(Intent.ACTION_VIEW)
            install.setDataAndType(Uri.fromFile(appFile), "application/vnd.android.package-archive")
            install.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            context.startActivity(install)
        }
        System.exit(0)
    }

}

3.我真無聊...居然寫這個...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章