Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Knightwood/AppUpdate2

 
 

Repository files navigation

效果图

demo中的自定义下载弹窗示例

功能介绍

  • 支持Kotlin
  • 界面定制变得极为简单
  • 支持后台下载
  • 支持强制更新
  • 支持自定义下载过程
  • 支持Android4.1及以上版本
  • 支持通知栏进度条展示(或者自定义显示进度)
  • 支持中文/繁体/英文语言(国际化)
  • 支持取消下载(如果发送了通知栏消息,则会移除)
  • 支持下载完成 打开新版本后删除旧安装包文件
  • 不需要申请存储权限
  • 使用HttpURLConnection下载,未集成其他第三方框架

使用步骤

1.添加依赖

最新版本:

groovy:

    implementation 'com.github.knightwood:appUpdate2:5.0.0'

kotlin:

    implementation("com.github.knightwood:appUpdate2:5.0.0")

settings.gradle可能需要添加:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven("https://www.jitpack.io")
    }
}

2.创建DownloadManager,显示更新界面。

更多用法请查看这里示例代码

步骤:

  1. 配置一个DownloadManager
  2. 显示更新弹窗界面

示例:

//配置一个DownloadManager
val manager = DownloadManager.config(application) {
    //这里指定使用内置的不同更新界面,如果需要自己定制界面,指定为UpdateDialogType.None      
    updateDialogType = UpdateDialogType.Colorful
    apkUrl = url
    apkName = this@MainActivity.apkName
    apkVersionCode = 2
    apkVersionName = "v4.2.1"
    apkSize = "7.7MB"
    apkDescription = getString(R.string.dialog_msg)
    forcedUpgrade = false
}

//显示更新弹窗界面
val manager = downloadApp(manager!!)

DownloadManager是个单例,每次使用DownloadManager.DownloadConfig配置DownloadManager 时,都会取消上一个下载任务。

如果要判断当前没有没下载,可以调用如下方法进行判断

    DownloadManager.isDownloading()
  • 内置界面
class UpdateDialogType {
    companion object {
        const val None = 0 //不使用界面
        const val Colorful = 1 //默认更新界面,由DialogFragment实现
        const val SimpleDialog = 2 //MaterialAlertDialog实现的更新界面
    }
}

配置下载信息得到DownloadManager详细用法

使用DownloadManager.DownloadConfig配置DownloadManager

配置项中,必需的参数有apkUrlapkNameapkDescription

  • DownloadManager
函数和变量 描述
canDownload 是否可以下载
checkThenDownload 检查并下载
directDownload 直接下载
downloadStateFlow 下载任务的状态流
downloadState 是否正在下载
config 配置项
  • AppUpgradeHolder 用于根据manager显示更新界面,一些快捷方法,如果你自定义界面,就用不到他
函数 描述
Activity.downloadApp(downloadManager: DownloadManager) 配置并显示内置下载界面
Activity.downloadApp(config: DownloadManager.DownloadConfig) 配置并显示内置下载界面
Activity.downloadApp(block: DownloadManager.DownloadConfig.() -> Unit) 配置并显示内置下载界面
DownloadManager.download(activity: Activity) 使用Builder配置并显示内置下载界面
DownloadManager.download() 使用Builder配置并显示内置下载界面
showUi(downloadManager: DownloadManager, activity: Activity) 仅显示内置下载界面

对于showUi方法:在使用内置界面时,你开始下载应用,并关闭了下载弹窗。 当你调用showUi时,弹窗会继续显示下载进度,而不会重新开始下载。

  • 也可以直接配置并显示更新界面
直接通过downloadApp方法构造downloadmanager并显示更新界面
val manager=downloadApp {
            //。。。。。
     		//跟上面一样的配置
        }

使用Builder配置DownloadManager

val downloadManager = DownloadManager.Builder(this).run {
    apkUrl(url)
    apkVersionCode(2)
    apkVersionName("v4.2.1")
    apkSize("7.7MB")
    apkName(this@MainActivity.apkName)
    apkDescription(getString(R.string.dialog_msg))
    updateDialogType(UpdateDialogType.SimpleDialog)//修改样式
    build()
}
downloadManager.download(activity)//如果不传activity参数,updateDialogType则不起作用

自定义界面

自定义界面
  • 需要做的事情极其简单,你不需要关注下载的流程,监听之类的,只需要继承并重写布局,然后显示这个自定义的DialogFragment
  • 步骤:
  1. 写一个类继承BaseUpdateDialogFragment,重写布局
  2. 跟往常一样通过DownloadManager.config(application)生成一个[DownloadManager]
  3. 显示你的自定义的DialogFragment

注意,在BaseUpdateDialogFragment中,进度条可以是任意视图,如果你的进度条不是ProgressBar,那么你需要重写

initProgressBarsetProgress方法。 比如:

/**
 * 设置进度条进度
 * @param progressValue Int
 */
override fun setProgress(progressValue: Int) {
  (progressBar() as NumberProgressBar).progress = progressValue
}

/**
 * 初始化进度条
 *
 */
override fun initProgressBar() {
  (progressBar() as NumberProgressBar).max = 100
}

自定义界面示例:

  1. 继承BaseUpdateDialogFragment
class Win8UpdateDialogFragment : BaseUpdateDialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        setStyle(STYLE_NORMAL, R1.style.M3AppTheme)
        mView = inflater.inflate(R.layout.app_update_dialog_win8, container, false)
        //全屏
        dialog?.window?.let { window ->
            //这步是必须的
            window.setBackgroundDrawableResource(R1.color.transparent)
            //必要,设置 padding,这一步也是必须的,内容不能填充全部宽度和高度
            window.decorView.setPadding(0, 0, 0, 0)
            // 关键是这句,其实跟xml里的配置长得几乎一样
            val wlp: WindowManager.LayoutParams = window.attributes
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                wlp.layoutInDisplayCutoutMode =
                    WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
            }
            wlp.gravity = Gravity.CENTER
            wlp.width = WindowManager.LayoutParams.MATCH_PARENT
            wlp.height = WindowManager.LayoutParams.WRAP_CONTENT
            window.attributes = wlp
        }
        return mView
    }


    companion object {
        const val TAG = "Win8UpdateDialogFragment"

        fun open(host: FragmentActivity) {
            host.run {
                val dialog = Win8UpdateDialogFragment()
                val ft = supportFragmentManager.beginTransaction()
                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                dialog.show(ft, TAG)
            }
        }
    }

}
  1. 展示界面
//跟往常一样构造DownloadManager
manager = DownloadManager.config(application) {
    //...一些配置项
}

//直接显示界面即可,不需要关注除了界面之外的任何内容
Win8UpdateDialogFragment.open(this)

详情查看app中的PixelUpdateDialogFragmentWin8UpdateDialogFragment

DownloadManager的一些其他配置项

 val manager = DownloadManager.config(application) {
    updateDialogType = UpdateDialogType.None //不使用内置界面
    registerDownloadListener(listenerAdapter)//自行监听下载进度
    httpManager = myHttpManager //替换默认下载功能
    notificationChannel = ... //修改通知渠道
    onButtonClickListener = {} //监听界面的按钮事件(BaseUpdateDialogFragment)
}
manager.checkThenDownload()//立即开始下载
  • 自定义下载时,需继承BaseHttpDownloadManager

混淆打包,只需保持ActivityService不混淆

-keep public class * extends android.app.Activity
- keep public class * extends android.app.Service

使用技巧

  • 框架内部支持国际化(其他语言只需要在对应的string.xml中取相同的名字即可)
  • 如果你需要修改框架内部的一些文字,你只需要在string.xml中取相同的名字即可以覆盖框架内设定的
  • 查看版本库中的Log只需要过滤AppUpdate开头的Tag
  • 支持校验安装包的MD5避免重复下载,只需要Builder设置安装包的MD5即可
  • 下载完成 打开新版本后删除旧安装包文件
  • 当设置apkVersionCode为MAX_VALUE时,将不校验版本号
  • 适配Android 13通知运行权限,且当设置showNotification(true)时,点击对话框的升级按钮会申请通知栏权限,无论是否同意都将会继续下载
  • 当设置强制更新forcedUpgrade(true)时,显示的对话框会显示下载进度条
  • 由于Android 10限制后台应用启动Activity,所以下载完成会发送一个通知至通知栏(忽略showNotification的值,需要允许发送通知)

相关文档链接

删除旧安装包

现在,下载的安装包会放入 /sdcard/Android/data/包名/cache/AppUpdateCache 下 而不会放在/sdcard/Android/data/包名/cache 下

//删除某一个文件
val result =
    ApkUtil.deleteOldApk(this, "${externalCacheDir?.path}/${Constant.cacheDirName}/$apkName")

//删除所有下载的文件
ApkUtil.deleteDefaultCacheDir(application)

About

新一代Android App update library. Android版本更新库,简单、轻量、可随意定制

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Kotlin 87.5%
  • Java 12.3%
  • Shell 0.2%