1.引入模块update-lib
1.file-new-import module
2.选择外部模块update-lib,finish
3.file-project struct
3.代码集成
public class MyCheckUpdate {
private UpdateURL updateURL;
private CheckUpdate checkUpdate;
private VersionParseInterface myVersionParse;
private MyCheckUpdate(Activity activity) {
//1.构造请求地址对象
updateURL = new UpdateURL("http://192.168.43.36:8080/app/getLastVersionCode?type=1",
"http://192.168.43.36:8080/app/getLastApp?type=1");
//2.重写自定义版本解析接口
myVersionParse = new VersionParseInterface() {
/**
* 解析版本信息并返回服务器上最新的版本号
* @param newVersionStr 通过调用服务器接口返回的String类型app版本信息
* @return
* @throws Exception
*/
@Override
public int getNewVersionCode(String newVersionStr) throws Exception {
Gson gson = MyGsonBuilder.getInstance().createGsonBuilder().create();
ResponseInfoObj<APPVersion> appVersion = gson.fromJson(newVersionStr, new TypeToken<ResponseInfoObj<APPVersion>>() {
}.getType());
if (appVersion.getCode() == 200) {
return appVersion.getData().getVersionCode();
} else {
throw new Exception(appVersion.getMsg());
}
}
/**
* 解析版本信息并返回服务器上版本描述信息
* @param newVersionStr 通过调用服务器接口返回的String类型app版本信息
* @return
*/
@Override
public List<String> getDesc(String newVersionStr) {
List<String> ret = new ArrayList<>();
Gson gson = MyGsonBuilder.getInstance().createGsonBuilder().create();
ResponseInfoObj<APPVersion> appVersion = gson.fromJson(newVersionStr, new TypeToken<ResponseInfoObj<APPVersion>>() {
}.getType());
String desc = appVersion.getData().getRemark();
if (null != desc && !("").equals(desc)) {
for (String item : desc.split(";")) {
ret.add(item);
}
}
return ret;
}
/**
* 升级过程中出现错误问题的回调
* @param errMsg
*/
@Override
public void checkError(String errMsg) {
Toast.makeText(activity, "更新版本时遇到问题:" + errMsg, Toast.LENGTH_LONG).show();
}
/**
* 用户取消升级回调
*/
@Override
public void checkCancel() {
Toast.makeText(activity, "请及时更新版本,否则无法使用", Toast.LENGTH_LONG).show();
}
/**
* 不需要升级回调
*/
@Override
public void checkNoUpdate() {
Toast.makeText(activity, "已是最新版本,不需要更新", Toast.LENGTH_LONG).show();
}
};
//3.构造CheckUpdate主类
checkUpdate = new CheckUpdate(activity, updateURL, myVersionParse);
}
//4.请求更新
public void check(UpdateStyle style) {
this.checkUpdate.check(style);
}
}
附录1:依赖及基础类
1.引入gson
2.MyGsonBuilder.java
```java
import com.google.gson.GsonBuilder;
public class MyGsonBuilder {
private static MyGsonBuilder instance;
private GsonBuilder builder;
private MyGsonBuilder() {
builder = new GsonBuilder();
builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
}
public static MyGsonBuilder getInstance() {
if (instance == null) {
instance = new MyGsonBuilder();
}
return instance;
}
public GsonBuilder createGsonBuilder() {
return instance.builder;
}
}
3.APPVersion.java
public class APPVersion {
/**
* id
*/
private Integer id;
/**
* 程序类型
*/
private String appType;
/**
* 版本号
*/
private Integer versionCode;
/**
* apk内容
*/
private byte[] apk;
/**
* 是否启用
*/
private String enable;
/** 备注 */
private String remark;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAppType() {
return appType;
}
public void setAppType(String appType) {
this.appType = appType;
}
public Integer getVersionCode() {
return versionCode;
}
public void setVersionCode(Integer versionCode) {
this.versionCode = versionCode;
}
public byte[] getApk() {
return apk;
}
public void setApk(byte[] apk) {
this.apk = apk;
}
public String getEnable() {
return enable;
}
public void setEnable(String enable) {
this.enable = enable;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return "APPVersion{" +
"id=" + id +
", appType='" + appType + '\'' +
", versionCode=" + versionCode +
", apk=" + Arrays.toString(apk) +
", enable='" + enable + '\'' +
", remark='" + remark + '\'' +
'}';
}
}
4.ResponseInfoObj
```java
import java.io.Serializable;
import java.util.List;
public class ResponseInfoObj<T> implements Serializable {
private Integer code;
private String msg;
private long total;
private T data;
private List<T> rows;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public List<T> getRows() {
return rows;
}
public void setRows(List<T> rows) {
this.rows = rows;
}
@Override
public String toString() {
return "ResponseInfoObj{" +
"code=" + code +
", msg='" + msg + '\'' +
", total=" + total +
", data=" + data +
", rows=" + rows +
'}';
}
}
附录2:后端服务器
@Value("${files.path}")
String filePath;
@GetMapping("/getLastVersionCode")
@ApiOperation(value = "PDA端获取最新版本号",notes="不需要登录Token")
public AjaxResult getLastVersionCode(int type) {
try {
AppVersion app=appVersionService.getLastAppVersionAndDescByType(type);
if(app!=null){
return AjaxResult.success("查询成功",app);
}else{
return AjaxResult.error("未查询到版本信息");
}
}catch (Exception e){
return AjaxResult.error("查询出错"+e.getMessage());
}
}
@GetMapping("/getLastApp")
@ApiOperation(value = "PDA端获取最新版本",notes="不需要登录Token")
public ResponseEntity<byte[]> getLastApp(int type, HttpServletRequest request) {
try {
// 获取最新版本号
AppVersion app=appVersionService.getLastAppVersionAndDescByType(type);
if(app==null){
return null;
}
//根据类型命名文件
String appName="";
List<SysDictData> dictList=dictTypeService.selectDictDataByType("app_type");
for(SysDictData temp:dictList){
if(temp.getDictValue().equals(app.getAppType())){
appName=temp.getDictLabel()+"_"+app.getVersionCode()+"_"+app.getUpdateTime().getTime();
break;
}
}
String fullFilePath = filePath + "/"+appName;
File f = new File(fullFilePath);
FileOutputStream fos=null;
BufferedOutputStream bos=null;
FileInputStream inputStream=null;
if (!f.exists()) {
//处理文件夹不存在的情况
File dir=new File(filePath);
if(!dir.exists()){
dir.mkdir();
}
app=appVersionService.getLastAppVersionByType(type);
fos = new FileOutputStream(f);
bos= new BufferedOutputStream(fos);
bos.write(app.getApk());
bos.flush();
HttpHeaders headers = new HttpHeaders();
headers.setContentLength(app.getApk().length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", URLEncoder.encode(appName, "UTF-8"));
return new ResponseEntity<>(app.getApk(), headers, HttpStatus.OK);
}else{
inputStream=new FileInputStream(f);
final int available = inputStream.available();
byte[] bytes=new byte[available];
inputStream.read(bytes);
HttpHeaders headers = new HttpHeaders();
headers.setContentLength(bytes.length);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", URLEncoder.encode(appName, "UTF-8"));
return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
}catch (Exception e){
return null;
}
}
附录3:权限
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
context = this;
initView();
app = MyApplication.newInstance();
switch (checkPermission()) {
//申请权限去了,不需要做任何事
case -1:
break;
//权限不够,退出
case 0:
Toast.makeText(context, "未申请到必要的权限,程序自动退出", Toast.LENGTH_SHORT).show();
finish();
break;
//权限够了,检查升级
case 1:
initCheckUpdate();
break;
}
}
/**
* 检查权限
*
* @return
*/
public Integer checkPermission() {
if (ContextCompat.checkSelfPermission(LoginActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(LoginActivity.this, Manifest.permission.INTERNET)
== PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(LoginActivity.this, Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED) {
return 1;
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.INTERNET
}, REQUEST_PERMISSION_CODE);
return -1;
} else {
Log.e(TAG, "sdk版本低");
Toast.makeText(context, "sdk版本低", Toast.LENGTH_LONG).show();
return 0;
}
}
}