Skip to content

Commit

Permalink
v2.0.1 新增文件MD5校验功能
Browse files Browse the repository at this point in the history
  • Loading branch information
muxiannian committed Oct 22, 2019
1 parent 394bb50 commit fd91fed
Show file tree
Hide file tree
Showing 26 changed files with 652 additions and 73 deletions.
Binary file modified .idea/caches/build_file_checksums.ser
Binary file not shown.
Binary file modified .idea/caches/gradle_models.ser
Binary file not shown.
82 changes: 51 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
+ **已适配Android 6.0,Android 7.0,Android 8.0,Android 9.0。**
+ **提供强制更新,不更新则无法使用APP,同时可以根据后台返回受影响的版本号,可控制多个版本同时被强制更新。**
+ **通知栏图片自定义**
+ **新增文件MD5校验,防止安装文件被恶意替换(2019-10-22 18:48:39添加)**

### 新版本说明
+ 2019-10-22 18:53:42更新新版,版本号为:v2.0.1
+ 新版新增文件的MD5校验
+ 新版新增对文件下载进度的监听
+ 新版新增对文件MD5校验结果的回调
+ DEMO中提供了获取文件MD5检验码的工具页面,也提供了加密工具类Md5Utils

### 博客地址

Expand Down Expand Up @@ -51,42 +59,54 @@ dependencies { implementation 'com.github.MZCretin:AutoUpdateProject:latest_vers
**Step 3.** Init it in BaseApplication or MainActivity before using it.And then register BaseApplication in AndroidManifest(Don't forget it).

```java
//更新库配置
UpdateConfig updateConfig = new UpdateConfig()
.setDebug(true)//是否是Debug模式
.setBaseUrl("http://www.cretinzp.com/system/versioninfo")//当dataSourceType为DATA_SOURCE_TYPE_URL时,配置此接口用于获取更新信息
.setMethodType(TypeConfig.METHOD_GET)//当dataSourceType为DATA_SOURCE_TYPE_URL时,设置请求的方法
.setDataSourceType(TypeConfig.DATA_SOURCE_TYPE_URL)//设置获取更新信息的方式
.setShowNotification(true)//配置更新的过程中是否在通知栏显示进度
.setNotificationIconRes(R.mipmap.download_icon)//配置通知栏显示的图标
.setUiThemeType(TypeConfig.UI_THEME_AUTO)//配置UI的样式,一种有12种样式可供选择
.setRequestHeaders(null)//当dataSourceType为DATA_SOURCE_TYPE_URL时,设置请求的请求头
.setRequestParams(null)//当dataSourceType为DATA_SOURCE_TYPE_URL时,设置请求的请求参数
.setCustomActivityClass(CustomActivity.class)//如果你选择的UI样式为TypeConfig.UI_THEME_CUSTOM,那么你需要自定义一个Activity继承自RootActivity,并参照demo实现功能,在此处填写自定义Activity的class
.setModelClass(new UpdateModel());
AppUpdateUtils.init(this, updateConfig);
//更新库配置
UpdateConfig updateConfig = new UpdateConfig()
.setDebug(true)//是否是Debug模式
.setBaseUrl("http://www.cretinzp.com/system/versioninfo")//当dataSourceType为DATA_SOURCE_TYPE_URL时,配置此接口用于获取更新信息
.setMethodType(TypeConfig.METHOD_GET)//当dataSourceType为DATA_SOURCE_TYPE_URL时,设置请求的方法
.setDataSourceType(TypeConfig.DATA_SOURCE_TYPE_URL)//设置获取更新信息的方式
.setShowNotification(true)//配置更新的过程中是否在通知栏显示进度
.setNotificationIconRes(R.mipmap.download_icon)//配置通知栏显示的图标
.setUiThemeType(TypeConfig.UI_THEME_AUTO)//配置UI的样式,一种有12种样式可供选择
.setRequestHeaders(null)//当dataSourceType为DATA_SOURCE_TYPE_URL时,设置请求的请求头
.setRequestParams(null)//当dataSourceType为DATA_SOURCE_TYPE_URL时,设置请求的请求参数
.setCustomActivityClass(CustomActivity.class)//如果你选择的UI样式为TypeConfig.UI_THEME_CUSTOM,那么你需要自定义一个Activity继承自RootActivity,并参照demo实现功能,在此处填写自定义Activity的class
.setNeedFileMD5Check(false)//是否需要进行文件的MD5检验,如果开启需要提供文件本身正确的MD5校验码,DEMO中提供了获取文件MD5检验码的工具页面,也提供了加密工具类Md5Utils
.setModelClass(new UpdateModel());
AppUpdateUtils.init(this, updateConfig);
```

**Step 4.** Start using it wherever you want as below with 3 ways.

```java
//有三种方式实现app更新,您可选其中一种方式来进行,推荐使用第三种方式!

//第一种方式,使用JSON字符串,让sdk自主解析并实现功能
String jsonData = "{\"versionCode\": 25,\"isForceUpdate\": 1,\"preBaselineCode\": 24,\"versionName\": \"v2.3.1\",\"downurl\": \"http://jokesimg.cretinzp.com/apk/app-release_231_jiagu_sign.apk\",\"updateLog\": \"1、优化细节和体验,更加稳定\n2、引入大量优质用户\r\n3、修复已知bug\n4、风格修改\",\"size\": \"31338250\",\"hasAffectCodes\": \"1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24\"}";
AppUpdateUtils.getInstance().checkUpdate(jsonData);

//第二种方式,使用MODEL方式,组装好对应的MODEL,传入sdk中
DownloadInfo info = new DownloadInfo().setApkUrl("http://jokesimg.cretinzp.com/apk/app-release_231_jiagu_sign.apk")
.setFileSize(31338250)
.setProdVersionCode(25)
.setProdVersionName("2.3.1")
.setForceUpdateFlag(listModel.isForceUpdate() ? 1 : 0)
.setUpdateLog("1、优化细节和体验,更加稳定\n2、引入大量优质用户\r\n3、修复已知bug\n4、风格修改");
AppUpdateUtils.getInstance().checkUpdate(info);

//第三种方式,在初始化的时候配置接口地址,sdk自主请求+解析实现功能(推荐)
AppUpdateUtils.getInstance().checkUpdate();
//有三种方式实现app更新,您可选其中一种方式来进行,推荐使用第三种方式!
//新增下载进度和MD5检测结果的回调监听 2019-10-22 18:51:19

//第一种方式,使用JSON字符串,让sdk自主解析并实现功能
String jsonData = "{\"versionCode\": 25,\"isForceUpdate\": 1,\"preBaselineCode\": 24,\"versionName\": \"v2.3.1\",\"downurl\": \"http://jokesimg.cretinzp.com/apk/app-release_231_jiagu_sign.apk\",\"updateLog\": \"1、优化细节和体验,更加稳定\n2、引入大量优质用户\r\n3、修复已知bug\n4、风格修改\",\"size\": \"31338250\",\"hasAffectCodes\": \"1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24\"}";
AppUpdateUtils.getInstance()
.addMd5CheckListener(...)
.addAppDownloadListener(...)
.checkUpdate(jsonData);

//第二种方式,使用MODEL方式,组装好对应的MODEL,传入sdk中
DownloadInfo info = new DownloadInfo().setApkUrl("http://jokesimg.cretinzp.com/apk/app-release_231_jiagu_sign.apk")
.setFileSize(31338250)
.setProdVersionCode(25)
.setProdVersionName("2.3.1")
.setMd5Check("68919BF998C29DA3F5BD2C0346281AC0")
.setForceUpdateFlag(listModel.isForceUpdate() ? 1 : 0)
.setUpdateLog("1、优化细节和体验,更加稳定\n2、引入大量优质用户\r\n3、修复已知bug\n4、风格修改");
AppUpdateUtils.getInstance()
.addMd5CheckListener(...)
.addAppDownloadListener(...)
.checkUpdate(info);

//第三种方式,在初始化的时候配置接口地址,sdk自主请求+解析实现功能(推荐)
AppUpdateUtils.getInstance()
.addMd5CheckListener(...)
.addAppDownloadListener(...)
.checkUpdate();

```

Expand Down
18 changes: 3 additions & 15 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,8 @@ dependencies {
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.blankj:utilcode:1.25.9'

//使用jirpack
implementation 'com.github.MZCretin:AutoUpdateProject:v2.0.0'
//使用jitpack
// implementation 'com.github.MZCretin:AutoUpdateProject:v2.0.0'
//使用本地库依赖
// implementation project(':cretinautoupdatelibrary')












implementation project(':cretinautoupdatelibrary')
}
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MD5HelperActivity"
android:label="文件MD5校验码"></activity>
<activity
android:name=".CustomActivity"
android:theme="@style/DialogActivityTheme"></activity>
android:theme="@style/DialogActivityTheme" />
<activity
android:name=".InfoActivity"
android:label="相关介绍" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@
import com.cretin.www.cretinautoupdatelibrary.activity.RootActivity;
import com.cretin.www.cretinautoupdatelibrary.activity.UpdateType2Activity;
import com.cretin.www.cretinautoupdatelibrary.interfaces.AppDownloadListener;
import com.cretin.www.cretinautoupdatelibrary.interfaces.MD5CheckListener;
import com.cretin.www.cretinautoupdatelibrary.utils.ResUtils;

/**
* 自定义UI类型
* 你需要注意:
* 1、Activity需要继承RootActivity才有效,并实现需要实现的方法
* 2、你需要在你的AndroidManifest.xml中为这个自定义的Activity设置
* @style/DialogActivityTheme 这个对话框的主题;
* 当然这只是建议,你只要撸出来的页面好看,咋地都行
*
* @style/DialogActivityTheme 这个对话框的主题;
* 当然这只是建议,你只要撸出来的页面好看,咋地都行
*/
public class CustomActivity extends RootActivity {
private TextView tvInfo;
Expand Down Expand Up @@ -105,4 +107,24 @@ public void pause() {
}
};
}

/**
* 如果需要知道文件MD5校验结果就重写此方法
*
* @return
*/
@Override
public MD5CheckListener obtainMD5CheckListener() {
return new MD5CheckListener() {
@Override
public void fileMd5CheckFail(String originMD5, String localMD5) {

}

@Override
public void fileMd5CheckSuccess() {

}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.cretin.www.autoupdateproject;

import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.cretin.www.autoupdateproject.utils.Md5Utils;
import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadListener;
import com.liulishuo.filedownloader.FileDownloader;

import java.io.File;

import static com.cretin.www.cretinautoupdatelibrary.activity.RootActivity.permission;
import static com.cretin.www.cretinautoupdatelibrary.utils.AppUtils.getAppLocalPath;

public class MD5HelperActivity extends AppCompatActivity {
private TextView tvDownload;
private EditText edContent;
private TextView tvDetails;
private boolean isDownloading;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_md5_helper);

tvDownload = findViewById(R.id.tv_download);
tvDetails = findViewById(R.id.tv_details);
edContent = findViewById(R.id.ed_content);

tvDownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isDownloading) {
return;
}
if (TextUtils.isEmpty(edContent.getText().toString().trim())) {
Toast.makeText(MD5HelperActivity.this, "请输入文件下载地址", Toast.LENGTH_SHORT).show();
return;
}
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M)) {
downloadFile(edContent.getText().toString().trim());
} else {
//下载权限
int writePermission = ContextCompat.checkSelfPermission(MD5HelperActivity.this, permission);
if (writePermission == PackageManager.PERMISSION_GRANTED) {
//拥有权限则直接下载
downloadFile(edContent.getText().toString().trim());
} else {
// 申请权限
ActivityCompat.requestPermissions(MD5HelperActivity.this, new String[]{permission}, 1000);
}
}
}
});
}

//下载文件
private void downloadFile(String appUrl) {
FileDownloader.setup(this);

final String downloadUpdateApkFilePath = getAppLocalPath("test");

BaseDownloadTask downloadTask = FileDownloader.getImpl().create(appUrl)
.setPath(downloadUpdateApkFilePath);
downloadTask
.addHeader("Accept-Encoding", "identity")
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36")
.setListener(new FileDownloadListener() {
@Override
protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
isDownloading = true;
}

@Override
protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
tvDownload.setText("已下载:" + (soFarBytes * 100l / totalBytes) + "%");
}

@Override
protected void completed(BaseDownloadTask task) {
isDownloading = false;
tvDownload.setText("下载完成(点击可重新下载)");
//获取校验码
try {
String fileMD5String = Md5Utils.getFileMD5(new File(downloadUpdateApkFilePath));
tvDetails.setText(fileMD5String);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
isDownloading = false;
tvDownload.setText("下载出错(点击可重新下载)");
}

@Override
protected void error(BaseDownloadTask task, Throwable e) {
isDownloading = false;
tvDownload.setText("下载出错(点击可重新下载)");
}

@Override
protected void warn(BaseDownloadTask task) {

}
})
.setAutoRetryTimes(3)
.start();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ private void obtainData() {
ListModel listModel = new ListModel();
listModel.setForceUpdate(false);
listModel.setUiTypeValue(300 + i);
listModel.setCheckFileMD5(true);
listModel.setSourceTypeVaule(TypeConfig.DATA_SOURCE_TYPE_MODEL);
list.add(listModel);
}
Expand Down Expand Up @@ -87,6 +88,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
AppUpdateUtils.getInstance().checkUpdate(recyclerviewAdapter.jsonDataUnForce);
Toast.makeText(this, "为了展示是真的可以自定义UI的,我写了个很丑的页面", Toast.LENGTH_SHORT).show();
break;
case R.id.action_04:
//获取文件MD5检验码工具
startActivity(new Intent(this, MD5HelperActivity.class));
break;
}
return super.onOptionsItemSelected(item);
}
Expand Down
Loading

0 comments on commit fd91fed

Please sign in to comment.