├── .gitignore ├── CHANGELOG.md ├── README.md ├── build.gradle ├── demo ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── bingoogolapple │ │ └── update │ │ └── demo │ │ ├── DownloadingDialog.java │ │ └── MainActivity.java │ └── res │ ├── layout │ ├── activity_main.xml │ └── dialog_downloading.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── build.gradle ├── consumer-proguard-rules.pro ├── gradle.properties └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── bingoogolapple │ │ └── update │ │ ├── AppUtil.java │ │ ├── BGADownloadProgressEvent.java │ │ ├── BGAUpgradeUtil.java │ │ ├── DownloadResponseBody.java │ │ ├── Engine.java │ │ ├── RxUtil.java │ │ └── StorageUtil.java │ └── res │ └── xml │ └── bga_upgrade_file_paths.xml ├── sample ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── bingoogolapple │ │ └── update │ │ └── sample │ │ ├── DownloadingDialog.java │ │ └── MainActivity.java │ └── res │ ├── layout │ ├── activity_main.xml │ └── dialog_downloading.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | /*/build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Eclipse project files 30 | .classpath 31 | .project 32 | .settings/ 33 | 34 | # Intellij project files 35 | *.iml 36 | *.ipr 37 | *.iws 38 | .idea/ 39 | 40 | # Mac system files 41 | .DS_Store 42 | 43 | *.keystore 44 | 45 | captures -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | ========== 3 | 4 | Version 1.0.2 *(2017-11-06)* 5 | ---------------------------- 6 | 7 | - 适配 Android 8.0 系统 8 | 9 | Version 1.0.1 *(2016-12-18)* 10 | ---------------------------- 11 | 12 | - 适配 Android 7.0 系统 13 | - 增加混淆配置 14 | 15 | Version 1.0.0 *(2016-12-16)* 16 | ---------------------------- 17 | 18 | Initial release. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :running:BGAUpdate-Android:running: 2 | ============ 3 | 4 | ## 功能介绍 5 | 6 | - [x] 适配 Android 8.+ 系统 7 | - [x] 检测新版 apk 文件是否已经下载过 8 | - [x] RxJava1.x + Retrofit2.x 下载新版 apk 文件 9 | - [x] RxBus 监听下载进度 10 | - [x] 安装 apk 文件 11 | - [x] 删除之前升级时下载的老的 apk 文件 12 | 13 | ## TODO 14 | 15 | - [x] 支持 RxJava2.x 16 | - [x] MD5 校验 17 | 18 | ## 效果图与示例 apk 19 | 20 | ![BGAUpdateDemo](https://cloud.githubusercontent.com/assets/8949716/21256759/256dce3e-c3af-11e6-98b3-373afcfa4cce.gif) 21 | 22 | [点击下载 BGAUpdateDemo.apk](http://fir.im/BGAUpdateDemo) 或扫描下面的二维码安装 23 | 24 | ![BGABannerDemo apk文件二维](https://cloud.githubusercontent.com/assets/8949716/21256883/db23d4b2-c3af-11e6-9793-7ac5c6624e25.png) 25 | 26 | ## 使用 27 | 28 | ### 1.添加 Gradle 依赖 29 | [![Download](https://api.bintray.com/packages/bingoogolapple/maven/bga-update/images/download.svg)](https://bintray.com/bingoogolapple/maven/bga-update/_latestVersion) bga-update 后面的「latestVersion」指的是左边这个 Download 徽章后面的「数字」,请自行替换。 30 | ```groovy 31 | dependencies { 32 | compile 'cn.bingoogolapple:bga-update:latestVersion@aar' 33 | 34 | // 换成己工程里依赖的 rxjava 和 retrofit 版本 35 | compile 'io.reactivex:rxjava:1.3.2' 36 | compile 'io.reactivex:rxandroid:1.2.1' 37 | compile 'com.squareup.retrofit2:retrofit:2.3.0' 38 | compile 'com.squareup.retrofit2:converter-gson:2.3.0' 39 | compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' 40 | } 41 | ``` 42 | 43 | ### 2.在 Activity 的 onCreate 方法中监听下载进度。demo 里引用了 rxlifecycle 这个库来防止 Activity 内存泄漏 44 | 45 | ```java 46 | BGAUpgradeUtil.getDownloadProgressEventObservable() 47 | .compose(this.bindToLifecycle()) 48 | .subscribe(new Action1() { 49 | @Override 50 | public void call(BGADownloadProgressEvent downloadProgressEvent) { 51 | if (mDownloadingDialog != null && mDownloadingDialog.isShowing() && downloadProgressEvent.isNotDownloadFinished()) { 52 | mDownloadingDialog.setProgress(downloadProgressEvent.getProgress(), downloadProgressEvent.getTotal()); 53 | } 54 | } 55 | }); 56 | ``` 57 | 58 | ### 3.下载新版 apk 文件。注意先申请 WRITE_EXTERNAL_STORAGE 权限 59 | 60 | ```java 61 | @AfterPermissionGranted(RC_PERMISSION_DOWNLOAD) 62 | public void downloadApkFile() { 63 | String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; 64 | if (EasyPermissions.hasPermissions(this, perms)) { 65 | // 如果新版 apk 文件已经下载过了,直接 return,此时不需要开发者调用安装 apk 文件的方法,在 isApkFileDownloaded 里已经调用了安装」 66 | if (BGAUpgradeUtil.isApkFileDownloaded(mNewVersion)) { 67 | return; 68 | } 69 | 70 | // 下载新版 apk 文件 71 | BGAUpgradeUtil.downloadApkFile(mApkUrl, mNewVersion) 72 | .subscribe(new Subscriber() { 73 | @Override 74 | public void onStart() { 75 | showDownloadingDialog(); 76 | } 77 | 78 | @Override 79 | public void onCompleted() { 80 | dismissDownloadingDialog(); 81 | } 82 | 83 | @Override 84 | public void onError(Throwable e) { 85 | dismissDownloadingDialog(); 86 | } 87 | 88 | @Override 89 | public void onNext(File apkFile) { 90 | if (apkFile != null) { 91 | BGAUpgradeUtil.installApk(apkFile); 92 | } 93 | } 94 | }); 95 | } else { 96 | EasyPermissions.requestPermissions(this, "使用 BGAUpdateDemo 需要授权读写外部存储权限!", RC_PERMISSION_DOWNLOAD, perms); 97 | } 98 | } 99 | ``` 100 | 101 | ### 4.下次进入应用时删除之前升级时下载的老的 apk 文件 102 | 103 | ``` 104 | BGAUpgradeUtil.deleteOldApk(); 105 | ``` 106 | 107 | ## 代码是最好的老师,更多详细用法请查看 [demo](https://github.com/bingoogolapple/BGAUpdate-Android/tree/master/demo):feet: 108 | 109 | ## 贡献者 110 | 111 | * [bingoogolapple](https://github.com/bingoogolapple) 112 | * [chenfei0928](https://github.com/chenfei0928) 113 | * [HYVincent](https://github.com/HYVincent) 114 | 115 | ## 作者联系方式 116 | 117 | | 个人主页 | 邮箱 | 118 | | ------------- | ------------ | 119 | | bingoogolapple.cn | bingoogolapple@gmail.com | 120 | 121 | | 个人微信号 | 微信群 | 公众号 | 122 | | ------------ | ------------ | ------------ | 123 | | 个人微信号 | 微信群 | 公众号 | 124 | 125 | | 个人 QQ 号 | QQ 群 | 126 | | ------------ | ------------ | 127 | | 个人 QQ 号 | QQ 群 | 128 | 129 | ## 打赏支持作者 130 | 131 | 如果您觉得 BGA 系列开源库或工具软件帮您节省了大量的开发时间,可以扫描下方的二维码打赏支持。您的支持将鼓励我继续创作,打赏后还可以加我微信免费开通一年 [上帝小助手浏览器扩展/插件开发平台](https://github.com/bingoogolapple/bga-god-assistant-config) 的会员服务 132 | 133 | | 微信 | QQ | 支付宝 | 134 | | ------------- | ------------- | ------------- | 135 | | 微信 | QQ | 支付宝 | 136 | 137 | ## 作者项目推荐 138 | 139 | * 欢迎您使用我开发的第一个独立开发软件产品 [上帝小助手浏览器扩展/插件开发平台](https://github.com/bingoogolapple/bga-god-assistant-config) 140 | 141 | ## License 142 | 143 | Copyright 2015 bingoogolapple 144 | 145 | Licensed under the Apache License, Version 2.0 (the "License"); 146 | you may not use this file except in compliance with the License. 147 | You may obtain a copy of the License at 148 | 149 | http://www.apache.org/licenses/LICENSE-2.0 150 | 151 | Unless required by applicable law or agreed to in writing, software 152 | distributed under the License is distributed on an "AS IS" BASIS, 153 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 154 | See the License for the specific language governing permissions and 155 | limitations under the License. 156 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | google() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.0.0' 10 | 11 | // classpath 'com.novoda:bintray-release:0.7.0' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | jcenter() 21 | google() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion ANDROID_BUILD_SDK_VERSION as int 5 | buildToolsVersion ANDROID_BUILD_TOOLS_VERSION 6 | 7 | defaultConfig { 8 | minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION as int 9 | targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION as int 10 | versionCode VERSION_CODE as int 11 | versionName VERSION_NAME 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled true 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | // 下面几个库非必须,只是为了写 demo 24 | compile 'com.android.support:appcompat-v7:27.0.0' 25 | compile 'pub.devrel:easypermissions:1.0.1' 26 | compile 'cn.bingoogolapple:bga-progressbar:1.0.0@aar' 27 | compile "com.android.support:cardview-v7:27.0.0" 28 | 29 | compile 'com.trello:rxlifecycle:1.0' 30 | compile 'com.trello:rxlifecycle-android:1.0' 31 | compile 'com.trello:rxlifecycle-components:1.0' 32 | // 上面几个库非必须,只是为了写 demo 33 | 34 | 35 | // 下面几个库必须依赖,请自行将 RxJava 和 Retrofit 换成你自己项目里对应的版本号 36 | compile 'io.reactivex:rxjava:1.3.2' 37 | compile 'io.reactivex:rxandroid:1.2.1' 38 | compile 'com.squareup.retrofit2:retrofit:2.3.0' 39 | compile 'com.squareup.retrofit2:converter-gson:2.3.0' 40 | compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' 41 | compile 'cn.bingoogolapple:bga-update:1.0.2@aar' 42 | // 上面几个库必须依赖 43 | 44 | // compile project(':library') 45 | } 46 | -------------------------------------------------------------------------------- /demo/proguard-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingoogolapple/BGAUpdate-Android/3f4727e60794416a3fa9d5c35f7f629f0d933999/demo/proguard-rules.pro -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /demo/src/main/java/cn/bingoogolapple/update/demo/DownloadingDialog.java: -------------------------------------------------------------------------------- 1 | package cn.bingoogolapple.update.demo; 2 | 3 | import android.content.Context; 4 | import android.support.v7.app.AppCompatDialog; 5 | 6 | import cn.bingoogolapple.progressbar.BGAProgressBar; 7 | 8 | /** 9 | * 作者:王浩 邮件:bingoogolapple@gmail.com 10 | * 创建时间:16/12/16 下午3:34 11 | * 描述:下载进度对话框,进度条使用的是 https://github.com/bingoogolapple/BGAProgressBar-Android 12 | */ 13 | public class DownloadingDialog extends AppCompatDialog { 14 | private BGAProgressBar mProgressBar; 15 | 16 | public DownloadingDialog(Context context) { 17 | super(context, R.style.AppDialogTheme); 18 | setContentView(R.layout.dialog_downloading); 19 | mProgressBar = (BGAProgressBar) findViewById(R.id.pb_downloading_content); 20 | setCancelable(false); 21 | } 22 | 23 | public void setProgress(long progress, long maxProgress) { 24 | mProgressBar.setMax((int) maxProgress); 25 | mProgressBar.setProgress((int) progress); 26 | } 27 | 28 | @Override 29 | public void show() { 30 | super.show(); 31 | mProgressBar.setMax(100); 32 | mProgressBar.setProgress(0); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /demo/src/main/java/cn/bingoogolapple/update/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.bingoogolapple.update.demo; 2 | 3 | import android.Manifest; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import com.trello.rxlifecycle.components.support.RxAppCompatActivity; 8 | 9 | import java.io.File; 10 | import java.util.List; 11 | 12 | import cn.bingoogolapple.update.BGADownloadProgressEvent; 13 | import cn.bingoogolapple.update.BGAUpgradeUtil; 14 | import pub.devrel.easypermissions.AfterPermissionGranted; 15 | import pub.devrel.easypermissions.EasyPermissions; 16 | import rx.Subscriber; 17 | import rx.functions.Action1; 18 | 19 | public class MainActivity extends RxAppCompatActivity implements EasyPermissions.PermissionCallbacks { 20 | /** 21 | * 下载文件权限请求码 22 | */ 23 | private static final int RC_PERMISSION_DOWNLOAD = 1; 24 | /** 25 | * 删除文件权限请求码 26 | */ 27 | private static final int RC_PERMISSION_DELETE = 2; 28 | 29 | private DownloadingDialog mDownloadingDialog; 30 | 31 | private String mNewVersion = "1.0.3"; 32 | private String mApkUrl = "http://7xk9dj.com1.z0.glb.clouddn.com/BGAUpdateDemo_v1.0.3_debug.apk"; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_main); 38 | 39 | // 监听下载进度 40 | BGAUpgradeUtil.getDownloadProgressEventObservable() 41 | .compose(this.bindToLifecycle()) 42 | .subscribe(new Action1() { 43 | @Override 44 | public void call(BGADownloadProgressEvent downloadProgressEvent) { 45 | if (mDownloadingDialog != null && mDownloadingDialog.isShowing() && downloadProgressEvent.isNotDownloadFinished()) { 46 | mDownloadingDialog.setProgress(downloadProgressEvent.getProgress(), downloadProgressEvent.getTotal()); 47 | } 48 | } 49 | }); 50 | } 51 | 52 | @Override 53 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 54 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 55 | EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); 56 | } 57 | 58 | @Override 59 | public void onPermissionsGranted(int requestCode, List perms) { 60 | } 61 | 62 | @Override 63 | public void onPermissionsDenied(int requestCode, List perms) { 64 | finish(); 65 | } 66 | 67 | public void onClick(View v) { 68 | if (v.getId() == R.id.btn_main_delete) { 69 | deleteApkFile(); 70 | } else if (v.getId() == R.id.btn_main_download) { 71 | downloadApkFile(); 72 | } 73 | } 74 | 75 | /** 76 | * 删除之前升级时下载的老的 apk 文件 77 | */ 78 | @AfterPermissionGranted(RC_PERMISSION_DELETE) 79 | public void deleteApkFile() { 80 | String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; 81 | if (EasyPermissions.hasPermissions(this, perms)) { 82 | // 删除之前升级时下载的老的 apk 文件 83 | BGAUpgradeUtil.deleteOldApk(); 84 | } else { 85 | EasyPermissions.requestPermissions(this, "使用 BGAUpdateDemo 需要授权读写外部存储权限!", RC_PERMISSION_DELETE, perms); 86 | } 87 | } 88 | 89 | /** 90 | * 下载新版 apk 文件 91 | */ 92 | @AfterPermissionGranted(RC_PERMISSION_DOWNLOAD) 93 | public void downloadApkFile() { 94 | String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; 95 | if (EasyPermissions.hasPermissions(this, perms)) { 96 | // 如果新版 apk 文件已经下载过了,直接 return,此时不需要开发者调用安装 apk 文件的方法,在 isApkFileDownloaded 里已经调用了安装」 97 | if (BGAUpgradeUtil.isApkFileDownloaded(mNewVersion)) { 98 | return; 99 | } 100 | 101 | // 下载新版 apk 文件 102 | BGAUpgradeUtil.downloadApkFile(mApkUrl, mNewVersion) 103 | .subscribe(new Subscriber() { 104 | @Override 105 | public void onStart() { 106 | showDownloadingDialog(); 107 | } 108 | 109 | @Override 110 | public void onCompleted() { 111 | dismissDownloadingDialog(); 112 | } 113 | 114 | @Override 115 | public void onError(Throwable e) { 116 | dismissDownloadingDialog(); 117 | } 118 | 119 | @Override 120 | public void onNext(File apkFile) { 121 | if (apkFile != null) { 122 | BGAUpgradeUtil.installApk(apkFile); 123 | } 124 | } 125 | }); 126 | } else { 127 | EasyPermissions.requestPermissions(this, "使用 BGAUpdateDemo 需要授权读写外部存储权限!", RC_PERMISSION_DOWNLOAD, perms); 128 | } 129 | } 130 | 131 | /** 132 | * 显示下载对话框 133 | */ 134 | private void showDownloadingDialog() { 135 | if (mDownloadingDialog == null) { 136 | mDownloadingDialog = new DownloadingDialog(this); 137 | } 138 | mDownloadingDialog.show(); 139 | } 140 | 141 | /** 142 | * 隐藏下载对话框 143 | */ 144 | private void dismissDownloadingDialog() { 145 | if (mDownloadingDialog != null) { 146 | mDownloadingDialog.dismiss(); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |