一款安装包升级管理工具库ApkUpdater

简介

1.基于DownLoadManager实现,支持断点续传。
2.安装包自动缓存、删除。如果下载完成后用户没有安装,那么下次则直接自动跳过下载。安装成功后会自动删除之前的安装包。
3.支持安装包完整性校验,目前支持MD5和SHA1校验,用与解决网络环境不好时导致下载丢包,从而导致一直提示安装包无效的问题。
4.支持自定义弹窗(提供了默认的弹窗),如果你不喜欢默认提供的弹窗,那么你可以自定义。
5.从3.0.0版本开始改为纯Kotlin实现并基于Androidx库。

演示

按照惯例还是先上图吧。


默认弹窗样式

更新

3.1.0 优化升级逻辑,增加弱更新功能。

  1. UpdateInfo接口移除了isForceUpdate的属性,改为updateType属性,其类型为UpdateTypeUpdateType为枚举类型,共有以下3个类型:
    • UpdateType.UPDATE_WEAK 弱更新,当更新类型为该类型时将会在默认的弹窗中出现忽略此版本的按钮,点击后默认会调用ApkUpdater.skipThisVersion()方法,
      即表示直到下一个版本出现前不会再次自动提示。如果用户还想更新则可以通过手动更新的方式更新应用。设置手动更新的方式可参考ApkUpdater.check()方法。
    • UpdateType.UPDATE_NORMAL普通更新。
    • UpdateType.UPDATE_FORCE强制更新。
  2. DefaultUpdateDialog中的onUpdateButtonClick()方法名变更为onUpgradingInTheBackground()
  3. 判断是否是强制更新的逻辑发生了变化,只要应用当前的版本号包含在UpdateInfo中的forceUpdateVersionCodes字段中就会认为是强制更新,及updateType为UpdateType.UPDATE_FORCE,而忽略updateType原来的值。

3.0.4 修复Manifest merger时可能会出现label冲突的问题。

3.0.3 修复FragmentDialog在dismiss时可以引发崩溃的Bug。

3.0.2 修复在OPPO手机上总是提示安装包已损坏的问题。

在安装更新时OPPO手机总是提示包已损坏(其实并没有损坏),主要是因为在startActivity之后调用了Process.killProcess(Process.myPid())这行代码所导致的。现已将这行代码删除。

3.0.1 将DefaultUpdateDialog改为open(可以被继承)。

将DefaultUpdateDialog改为open(可以被继承),这将使得自定义弹窗更加容易,你可以直接继承DefaultUpdateDialog来自定义你的弹窗。

3.0.0 基于Kotlin和Androidx重构

  1. 基于Kotlin语言进行重构并迁移至Androidx。没有迁移至Androidx的小伙伴请使用之前的版本。
  2. 优化升级弹窗的逻辑,使得自定义弹窗更加容易。

2.2.3及以前

基于Java、Support库开发,可自定义弹窗、支持完整性校验、自动缓存。

下载

第一步:添加 JitPack 仓库到你项目根目录的 gradle 文件中。

allprojects {
    repositories {
        //省略部分代码...
        maven { url 'https://jitpack.io' }
    }
}

第二步:添加这个依赖。

dependencies {
    implementation 'com.github.kelinZhou:ApkUpdater:${Last version here!}'
}

使用

第一步:添加权限

你需要在你的清单文件中添加以下权限:

    <!--网络访问权限-->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!--不弹出通知栏权限-->
    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
    <!--DownloadManager-->
    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
    <!--获取网络状态权限-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--APK安装权限-->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

第二步:清单文件配置

你需要在你清单文件中的Application节点下添加如下配置:

<!--Android7.0一上安装Apk所需要的文件提供者-->
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileProvider" 
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/apk_updater_file_paths" />
</provider>

<!--版本更新服务-->
<service android:name="com.kelin.apkUpdater.DownloadService" />

provider标签中android:authorities的值可以自定义,需要在初始化ApkUpdater.init(context,fileProvider)方法中传入该值。

在Android7.0以上的设备如果不能正常下载你可能还需要在清单文件的Application节点下增加networkSecurityConfig配置。例如:

<application
        android:name=".App"
        android:networkSecurityConfig="@xml/network_security_config">

        <!--此处省略了你的Activity、Service等四大组件-->
        
</application>

其中 network_security_config 文件需要定义在res的xml文件夹下,它的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

第三步:初始化

你需要在Application的onCreate方法中调用ApkUpdater.init(context, fileProvider)初始化ApkUpdater。例如:

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        ApkUpdater.init(this, "$packageName.fileProvider")
    }
}

注意: 别忘记在清单文件中使用你的Application:

<application
        android:name=".App"  //这里是你自定义的Application。
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <!--此处省略了你的Activity、Service等四大组件-->
        
</application>

第五步:检测更新

首先利用你项目的网络访问能力从服务器端获取更新信息并转换为javaBean对象,然后让这个对象实现UpdateInfo接口。下面是这个接口中所有方法:

ApkUpdater.Builder().create().check(
    UpdateInfoImpl(
            "http://test-cloud-yxholding-com.oss-cn-shanghai.aliyuncs.com/yx-logistics/file/file/20200703/1593709201374.apk", //安装包下载地址
            131, //网络上的版本号,用于判断是否可以更新(是否大于本地版本号)。
            "v1.3.1", //版本名称,用于显示在弹窗中,以告知用户将要更到哪个版本。
            false,  //是否是强制更新,如果干参数为true则用户没有进行更新就不能继续使用App。(当旧版本存在严重的Bug时或新功能不与旧版兼容时使用)
            "更新内容如下:",  //升级弹窗的标题。
            "1.修复了极端情况下可能导致下单失败的bug。\n2.增加了许多新的玩法,并且增加了app的稳定性。 \n3.这是测试内容,其实什么都没有更新。", //升级弹窗的消息内容,用于告知用户本次更新的内容。
            SignatureType.MD5, //安装包完整性校验开启,并使用MD5进行校验,如果不想开启,传null。(目前只支持MD5和SHA1)
            ""  //完成性校验的具体值,返回空或null则不会进行校验。
    )
)

其他

构建Updater对象

方法名 说明
setCallback(callback: IUpdateCallback?) 设置监听对象。
setDialogGenerator(generator: (updater: ApkUpdater) -> ApkUpdateDialog) 使用自定义弹窗。
create() 完成Updater对象的构建。

自定义Dialog

ApkUpdater.Builder()
        .setDialogGenerator {
            MyUpdateDialog(it)
        }.create()

MyUpdateDialog 是ApkUpdateDialog接口的实现类,也可以直接继承DefaultUpdateDialog。ApkUpdateDialog接口中都有注释,写的应该还算比较详细的,这里就不在讲了。

检查更新

检查更新的代码如下:

apkUpdater.check(updateInfo)

安装APK

安装是不许要你关心的,下载完成后会自动进入安装页面。除非你禁用了自动安装,或是想安装一个现有的Apk。如果是这样的话你可以使用UpdateHelperfun installApk(context: Context, apkFile: File?): Boolean方法。

其他

该项目中提供了两个工具类:UpdateHelper 和 NetWorkStateUtil。


如果需要源码请点击这里,如果你觉得有用就给个免费的Star支持一下。你的支持将是我继续创作的动力。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354