Files
assistant-android/app/src/main/java/com/gh/common/util/PackageInstaller.kt

156 lines
5.8 KiB
Kotlin

package com.gh.common.util
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import com.gh.common.constant.Constants
import com.gh.common.dialog.InstallPermissionDialogFragment
import com.gh.common.xapk.XapkInstaller
import com.gh.gamecenter.BuildConfig
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.AppManager
import com.lightgame.utils.Utils
import java.io.File
object PackageInstaller {
/**
* 为了兼容java代码
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity?) {
downloadEntity?.let { install(context, downloadEntity, true) }
}
/**
* 启动安装应用程序并取消通知栏安装消息
*
* 兼容所有包安装(apk,xapk),后续可加上apks
*
* 主动点击安装如果是xapk则需要toast提示
*/
@JvmStatic
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
val pkgPath = downloadEntity.path
val isXapk = XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()
val currentActivity = AppManager.getInstance().currentActivity() ?: return
// TODO 此处可能遇到 activity 是 WXEntryActivity
// TODO 当 activity 全部出栈,但是应用还在下载游戏,下载完会唤不起安装!
if (currentActivity is AppCompatActivity) {
InstallPermissionDialogFragment.show(currentActivity, downloadEntity) {
// 取消状态栏下载完成的通知,若存在
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
if (isXapk) {
XapkInstaller.install(context, downloadEntity, showUnzipToast)
} else {
install(context, downloadEntity.path)
}
}
}
}
/**
* 启动安装应用程序
*
* 除非特殊情况,请勿使用此方法进行应用安装操作
* 除非你已经确定该文件一定是Apk
*/
@JvmStatic
fun install(context: Context, pkgPath: String) {
try {
if (PackageUtils.isCanLaunchSetup(context, pkgPath)) {
val installIntent = getInstallIntent(context, pkgPath)
context.startActivity(installIntent)
} else {
DialogUtils.showPluginDialog(context) {
uninstall(context, pkgPath)
}
}
} catch (e: Exception) {
Utils.toast(context, e.message)
}
}
/**
* 获取启动安装意图
*
* 除非特殊情况,请勿使用此方法进行应用安装操作
* 除非你已经确定该文件一定是Apk且该次安装无需检查签名情况
*/
@JvmStatic
fun getInstallIntent(context: Context, path: String): Intent {
var uri = Uri.fromFile(File(path))
val installIntent = Intent(Intent.ACTION_VIEW)
if ("smartisan" == Build.MANUFACTURER) {
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(path))
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} else {
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
// Application 上下文就更不用说了
val pkgName = PackageUtils.getPackageNameByPath(context, path)
if (pkgName == context.packageName || context is Application) {
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
}
InstallUtils.getInstance(context).addInstall(PackageUtils.getPackageNameByPath(context, path))
return installIntent
}
/**
* 卸载应用
*/
@JvmStatic
fun uninstall(context: Context, path: String) {
val packageName = PackageUtils.getPackageNameByPath(context, path)
uninstallForPackageName(context, packageName)
}
/**
* 根据包名卸载应用
*/
@JvmStatic
fun uninstallForPackageName(context: Context, pkn: String) {
if (pkn.isBlank()) return
val uninstallIntent = Intent()
uninstallIntent.action = Intent.ACTION_DELETE
uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
if (context !is Activity) {
uninstallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
uninstallIntent.data = Uri.parse("package:$pkn")
InstallUtils.getInstance(context).addUninstall(pkn)
context.startActivity(uninstallIntent)
}
@JvmStatic
fun getDownloadPath(gameName: String?, format: String?): String {
return FileUtils.getDownloadPath(HaloApp.getInstance().application, getDownloadFileName(gameName, format))
}
private fun getDownloadFileName(gameName: String?, format: String?): String {
var fileExtension = "apk"
if (format == XapkInstaller.XAPK_EXTENSION_NAME) {
fileExtension = XapkInstaller.XAPK_EXTENSION_NAME
}
return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis()) + "." + fileExtension
}
}