GithubHelp home page GithubHelp logo

updateapputils's Introduction

UpdateAppUtils2.0

Download

一行代码,快速实现app在线下载更新 A simple library for Android update app

UpdateAppUtils2.0 特点

  • Kotlin First,Kotlin开发
  • 支持AndroidX
  • 支持Md5签名验证
  • 支持自定义任意UI
  • 适配中英文
  • 适配至Android 10
  • 通知栏图片自定义
  • 支持修改是否每次显示弹窗(非强更)
  • 支持安装完成后自动删除安装包

UpdateAppUtils2.0功能结构变化巨大,建议使用2.0以上版本;2.0以前版本文档

效果图

集成

repositories {
   jcenter()
}

Support

implementation 'com.teprinciple:updateapputils:2.3.0'

AndroidX项目

注意,由于操作失误bintray 中updateapputilsX被我删掉,
所以2.3.0以后使用updateapputilsx。之前的仍使用updateapputilsX
//implementation 'com.teprinciple:updateapputilsX:2.2.1'
implementation 'com.teprinciple:updateapputilsx:2.3.0'

使用

下面为kotlin使用示例,Java示例请参考JavaDemo

1、快速使用

注意:部分手机SDK内部初始化不了context,造成context空指针,建议在application或者使用SDK前先初始化
 UpdateAppUtils.init(context)
 UpdateAppUtils
        .getInstance()
        .apkUrl(apkUrl)
        .updateTitle(updateTitle)
        .updateContent(updateContent)
        .update()

2、多配置使用

    // ui配置
    val uiConfig = UiConfig().apply {
        uiType = UiType.PLENTIFUL
        cancelBtnText = "下次再说"
        updateLogoImgRes = R.drawable.ic_update
        updateBtnBgRes = R.drawable.bg_btn
        titleTextColor = Color.BLACK
        titleTextSize = 18f
        contentTextColor = Color.parseColor("#88e16531")
    }

    // 更新配置
    val updateConfig = UpdateConfig().apply {
        force = true
        checkWifi = true
        needCheckMd5 = true
        isShowNotification = true
        notifyImgRes = R.drawable.ic_logo
        apkSavePath = Environment.getExternalStorageDirectory().absolutePath +"/teprinciple"
        apkSaveName = "teprinciple"
    }

    UpdateAppUtils
        .getInstance()
        .apkUrl(apkUrl)
        .updateTitle(updateTitle)
        .updateContent(updateContent)
        .updateConfig(updateConfig)
        .uiConfig(uiConfig)
        .setUpdateDownloadListener(object : UpdateDownloadListener{
            // do something
        })
        .update()

3、md5校验说明

为了保证app的安全性,避免apk被二次打包的风险。UpdateAppUtils内部提供了对签名文件md5值校验的接口; 首先你需要保证当前应用和服务器apk使用同一个签名文件进行了签名(一定要保管好自己的签名文件,否则检验就失去了意义), 然后你需要将UpdateConfig 的 needCheckMd5 设置为true,并在Md5CheckResultListener监听中,监听校验返回结果。具体使用可参考 CheckMd5DemoActivity

UpdateAppUtils
       .getInstance()
       .apkUrl(apkUrl)
       .updateTitle(updateTitle)
       .updateContent(updateContent)
       .updateConfig(updateConfig) // needCheckMd5设置为true
       .setMd5CheckResultListener(object : Md5CheckResultListener{
           override fun onResult(result: Boolean) {
               // true:检验通过,false:检验失败
           }
       })

4、自定义UI

UpdateAppUtils内置了两套UI,你可以通过修改UiConfig进行UI内容的自定义; 当然当内部UI模板与你期望UI差别很大时,你可以采用完全自定义UI

Api说明

1、UpdateAppUtils Api

api 说明 默认值 必须设置
fun apkUrl(apkUrl: String) 更新包服务器url null true
fun update() UpdateAppUtils入口 - true
fun updateTitle(title: String) 更新标题 版本更新啦! false
fun updateContent(content: String) 更新内容 发现新版本,立即更新 false
fun updateConfig(config: UpdateConfig) 更新配置 查看源码 false
fun uiConfig(uiConfig: UiConfig) 更新弹窗UI配置 查看源码 false
fun setUpdateDownloadListener() 下载过程监听 null false
fun setMd5CheckResultListener() md5校验结果回调 null false
fun setOnInitUiListener() 初始化更新弹窗UI回调 null false
fun deleteInstalledApk() 删除已安装的apk - false
fun setCancelBtnClickListener() 暂不更新按钮点击监听 - false
fun setUpdateBtnClickListener() 立即更新按钮点击监听 - false

2、UpdateConfig:更新配置说明

属性 说明 默认值
isDebug 是否输出【UpdateAppUtils】为Tag的日志 true
force 是否强制更新,强制时无取消按钮 false
apkSavePath apk下载存放位置 包名目录
apkSaveName apk保存文件名 项目名
downloadBy 下载方式 DownLoadBy.APP
needCheckMd5 是否需要校验apk签名md5 false
checkWifi 检查是否wifi false
isShowNotification 是否显示通知栏进度 true
notifyImgRes 通知栏图标 项目icon
serverVersionName 服务器上apk版本名
serverVersionCode 服务器上apk版本号
alwaysShow 是否每次显示更新弹窗(非强更) true
thisTimeShow 本次是否显示更新弹窗(非强更) false
alwaysShowDownLoadDialog 是否需要显示更新下载进度弹窗(非强更) false
showDownloadingToast 开始下载时是否显示Toast true

3、UiConfig:更新弹窗Ui配置说明

属性 说明 默认值
uiType ui模板 UiType.SIMPLE
customLayoutId 自定义布局id false
updateLogoImgRes 更新弹窗logo图片资源id -
titleTextSize 标题字体大小 16sp
titleTextColor 标题字体颜色 -
contentTextSize 内容字体大小 14sp
contentTextColor 内容字体颜色 -
updateBtnBgColor 更新按钮背景颜色 -
updateBtnBgRes 更新按钮背景资源id -
updateBtnTextColor 更新按钮字体颜色 -
updateBtnTextSize 更新按钮文字大小 14sp
updateBtnText 更新按钮文案 立即更新
cancelBtnBgColor 取消按钮背景颜色 -
cancelBtnBgRes 取消按钮背景资源id -
cancelBtnTextColor 取消按钮文字颜色 -
cancelBtnTextSize 取消按钮文字大小 14sp
cancelBtnText 取消按钮文案 暂不更新
downloadingToastText 开始下载时的Toast提示文字 更新下载中...
downloadingBtnText 下载中 下载按钮以及通知栏标题前缀,进度自动拼接在后面 下载中
downloadFailText 下载出错时,下载按钮及通知栏标题 下载出错,点击重试

Demo体验

更新日志

2.3.0

  • 修复部分手机context空指针异常

updateapputils's People

Contributors

teprinciple avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

updateapputils's Issues

安卓4.4下载异常

com.liulishuo.filedownloader.exception.FileDownloadHttpException: response code error: 404,
request headers: {Range=[bytes=0-]}
response headers: {null=[HTTP/1.1 404 Not Found], Access-Control-Allow-Origin=[*], Access-Control-Expose-Headers=[X-Log, X-Reqid], Access-Control-Max-Age=[2592000], Connection=[keep-alive], Content-Length=[30], Content-Type=[application/json], Date=[Wed, 17 Jan 2018 06:05:43 GMT], Last-Modified=[Wed, 17 Jan 2018 06:00:00 GMT], Server=[openresty], X-Android-Received-Millis=[1516169142938], X-Android-Response-Source=[NETWORK 404], X-Android-Selected-Transport=[http/1.1], X-Android-Sent-Millis=[1516169142682], X-Cache-Lookup=[Hit From Upstream, Hit From Inner Cluster, Hit From Upstream, Hit From Upstream, Hit From Inner Cluster, Hit From Upstream], X-Daa-Tunnel=[hop_count=6], X-Log=[mc.g/404;rs4_3.sel:2/not found;rdb.g/no such key;DBD/404;v4.get/Document not found;rwro.get:2/Document not found;RS.dbs:2/Document not found;RS:2/404;mc.g/404;rs4_3.sel:1/not found;rdb.g/no such key;DBD/404;v4.get/Document not found;rwro.get:2/Document not found;RS.dbs:2/Document not found;RS:3/404;IO:7/404], X-M-Log=[QNM:fs219;SRCPROXY:fs176;SRCPROXY:11/404;QNM3:27/404], X-M-Reqid=[gAQAAP507o_NgwoV], X-NWS-LOG-UUID=[6cd9fd91-ea4b-4413-9d2b-dd3805f16d7c a453a0cb48e09ab4f18aef9bc8e7c732], X-Qnm-Cache=[Validate,Proxy,Cache], X-Reqid=[Z3EAAOCF8JDNgwoV], X-Svr=[IO]}

直接返回404,这个下载链接肯定是没有问题的,在7.0上能够下载,并且在4.4使用浏览器也能下载,但是选择app内下载方式就直接返回上述异常

崩溃惹

kotlin.KotlinNullPointerException

Caused by: kotlin.KotlinNullPointerException at util.GlobalContextProvider$Companion.getGlobalContext(GlobalContextProvider.kt:24) at update.UpdateAppUtils.<clinit>(UpdateAppUtils.kt:25) at update.UpdateAppUtils.getInstance(UpdateAppUtils.kt:159) 

我在application调用了删除的方法
复现步骤:点两次立即更新

app下载出错 6.0 7.0 8.0 测试的是模拟器 log是InstantRun支持错误

06-19 04:47:22.484 7284-7284/com.ulabcare.saas.clinic:filedownloader E/ClassUtils: InstantRun support error, com.android.tools.fd.runtime.Paths
06-19 04:47:22.705 7284-7284/com.ulabcare.saas.clinic:filedownloader E/ClassUtils: No files were found, check your configuration please!
06-19 04:47:22.732 7284-7284/com.ulabcare.saas.clinic:filedownloader E/ARouter::: InstantRun support error, com.android.tools.fd.runtime.Paths

建议 update 函数返回一个值

如果服务器端版本号大需要升级返回 true ,如果版本号相同或者小则返回 false ,这样 app 的检测更新功能只需要添加如下代码就可以提示是否需要更新了,省去了自己再去比对版本的代码。

if ( !....update() ){
//提示用户已经是最新版本!
}

强制更新有问题(没有屏蔽返回键,岂不是直接点下返回就可以取消更新了?) 数据网络下载也有问题(弹出WiFi连接dialog同时执行了finish()导致无法下载)。。

private void download() {

    startService(new Intent(this, UpdateAppService.class));

    if (updateBean.getDownloadBy() == UpdateAppUtils.DOWNLOAD_BY_APP) {
        if (isWifiConnected(this)) {

            DownloadAppUtils.download(this, updateBean.getApkPath(), updateBean.getServerVersionName());
        } else {
            new ConfirmDialog(this, new ConfirmDialog.Callback() {
                @Override
                public void callback(int position) {
                    if (position == 1) {
                        DownloadAppUtils.download(UpdateAppActivity.this, updateBean.getApkPath(), updateBean.getServerVersionName());
                    } else {
                        if (updateBean.getForce()) {
                            System.exit(0);
                        } else {
                            finish();
                        }
                    }
                }
            }).setContent("目前手机不是WiFi状态\n确认是否继续下载更新?").show();
        }
    } else if (updateBean.getDownloadBy() == UpdateAppUtils.DOWNLOAD_BY_BROWSER) {
        DownloadAppUtils.downloadForWebView(this, updateBean.getApkPath());
    }

    finish();
}

报错

这个集成之后运行报错
image

通知的进度和activity的进度都不正确

通知的进度和activity的进度都不正确,我设置了
updateConfig.setAlwaysShowDownLoadDialog(true);
显示的是字节的大小,需要在另行传递什么参数吗?我看demo上没有传啊
P1R_S3116U @E{ODBN$A8C3

我试了试demo中的地址是没问题的,但是不知道为什么我这个地址不行

适配奥利奥

大哥,你有适配android8.0吗?可否更新一下。

弹窗问题

如何不使用的弹窗,直接调用下载可以吗?

android7.0下载时闪退

android7.0下载时闪退
11-01 17:25:37.767 13907-13907/com.domain.app02 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.domain.app02, PID: 13907
java.lang.RuntimeException: Unable to start receiver util.UpdateAppReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3194)
at android.app.ActivityThread.-wrap18(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6595)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:584)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:558)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
at util.UpdateAppReceiver.onReceive(UpdateAppReceiver.java:49)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3184)
at android.app.ActivityThread.-wrap18(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656) 
at android.os.Handler.dispatchMessage(Handler.java:105) 
at android.os.Looper.loop(Looper.java:156) 
at android.app.ActivityThread.main(ActivityThread.java:6595) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832) 

强制更新问题

1.5.1版本,强制更新,点击返回键会关闭弹窗,正常使用APP,而不是退出

progress

by mistak:

DownloadAppUtils --> download --> send(context, (int)(soFarBytes/totalBytes),serverVersionName);

correction:
send(context, (int)(soFarBytes*100/totalBytes),serverVersionName);

android7.0下载时闪退

android7.0下载时闪退
11-01 17:25:37.767 13907-13907/com.domain.app02 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.domain.app02, PID: 13907
java.lang.RuntimeException: Unable to start receiver util.UpdateAppReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3194)
at android.app.ActivityThread.-wrap18(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6595)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:584)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:558)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
at util.UpdateAppReceiver.onReceive(UpdateAppReceiver.java:49)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3184)
at android.app.ActivityThread.-wrap18(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1656) 
at android.os.Handler.dispatchMessage(Handler.java:105) 
at android.os.Looper.loop(Looper.java:156) 
at android.app.ActivityThread.main(ActivityThread.java:6595) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832) 

下载更新问题

你好,请问我下载安装了apk后,之后再提示更新 会提示安装上次的下载的apk吗(因为安装后没有删除本地安装包) ,这样就不会下载最新的apk,应该如何解决

Android 7.0 以下也需要使用FileProvider

FileProvider也兼容Android 7.0以下的,可以将私有文件转换成 content uri用于apk 安装,不然将apk保存为私有文件时,在Android 7.0以下只能转换成 file uri。安装器无法访问私有file uri,导致无法安装。

// Utils
    /**
     * 跳转安装
     */
    fun installApk(context: Context, apkPath: String) {

        val i = Intent(Intent.ACTION_VIEW)
        val apkFile = File(apkPath)

        // android 7.0 fileprovider 适配
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            i.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
            val contentUri = FileProvider.getUriForFile(
                context, context.packageName + ".fileprovider", apkFile)
            i.setDataAndType(contentUri, "application/vnd.android.package-archive")
        } else {
            i.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive")
        }

        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(i)
    }

建议修改成

    /**
     * 跳转安装
     */
    fun installApk(context: Context, apkPath: String) {

        val i = Intent(Intent.ACTION_VIEW)
        val apkFile = File(apkPath)

        i.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        val contentUri = FileProvider.getUriForFile(
            context, context.packageName + ".fileprovider", apkFile)
        i.setDataAndType(contentUri, "application/vnd.android.package-archive")
        
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(i)
    }

下载路径问题

下载路径更改两次,只会显示第二次路劲,就算是在代码里更改了路劲

报错:cannot Resolve CallBack

在Demo程序的 onRequestPermissionsResult 中
new ConfirmDialog(this, new Callback() {
@OverRide
public void callback(int position) {
...
}
}).setContent("There is no permission for SD card.\nDo you want to get it?").show();

CallBack下划红线
显示 cannot resolve CallBack
已同步dependency

因为我的SDK是较新版的 不知道是不是这个原因 Dialog类貌似在新版里deprecated了

求解

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.