From 47fb44ea251460a07ea20849c590c6d081b68358 Mon Sep 17 00:00:00 2001 From: lwy <9011532@qq.com> Date: Mon, 24 Jun 2019 16:42:58 +0800 Subject: [PATCH 1/2] add support for custom dialogs --- README.md | 114 +++++++++++++++++- .../com/lwy/appsmartupdate/MainActivity.java | 68 +++++++++-- .../com/lwy/appsmartupdate/MyApplication.java | 1 + .../main/java/com/lwy/smartupdate/Config.java | 14 +++ .../com/lwy/smartupdate/UpdateManager.java | 65 +++++++--- .../com/lwy/smartupdate/UpdateService.java | 2 +- .../lwy/smartupdate/api/IUpdateCallback.java | 11 ++ .../lwy/smartupdate/data/AppUpdateModel.java | 34 +++++- 8 files changed, 276 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 57efd09..4687f75 100755 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ - [x] 支持外部注入网络框架(库默认使用okhttp) - [x] 支持前台或后台自动更新 - [x] 支持基于版本的强制更新 -- [ ] 支持对外定制提示界面 -- [ ] 支持暂停、多线程断点下载 +- [x] 支持对外定制更新提示和更新进度界面 +- [ ] 记忆下载 - [x] 含发布功能后台服务端[github](https://github.com/itlwy/App-Update-Server) (Node.js实现) ## 流程图 @@ -58,7 +58,7 @@ Add the dependency ``` dependencies { - implementation 'com.github.itlwy:AppSmartUpdate:v1.0.5' + implementation 'com.github.itlwy:AppSmartUpdate:v1.0.6' } ``` @@ -227,6 +227,114 @@ public interface IHttpManager { } ``` +### 定制更新交互界面 + +每个应用的风格都可能是不一样的,因此这里也支持自定义弹出的提示框和进度框,详细见如下代码示例: + +1. 初始化config时需要将内部默认的弹框屏蔽掉 + + ```java + public class MyApplication extends Application { + + @Override + public void onCreate() { + super.onCreate(); + Config config = new Config.Builder() + .isShowInternalDialog(false) + .build(this); + UpdateManager.getInstance().init(config); + } + } + ``` + +2. 自定义对话框,如下(详细代码在MainActivity.java里): + +```java + public void registerUpdateCallbak() { + mCallback = new IUpdateCallback() { + @Override + public void noNewApp() { + Toast.makeText(MainActivity.this, "当前已是最新版本!", Toast.LENGTH_LONG).show(); + } + + @Override + public void hasNewApp(AppUpdateModel appUpdateModel, UpdateManager updateManager, final int updateMethod) { + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + mDialog = builder.setTitle("自动更新提示") + .setMessage(appUpdateModel.getTip()) + .setPositiveButton("更新", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + UpdateManager.getInstance().startUpdate(updateMethod); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).create(); + mDialog.show(); + } + + @Override + public void beforeUpdate() { + // 更新开始 + mProgressDialog = new ProgressDialog(MainActivity.this); + mProgressDialog.setTitle("更新中..."); + mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + mProgressDialog.setMessage("正在玩命更新中..."); + mProgressDialog.setMax(100); + mProgressDialog.setProgress(0); + mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + // 退到后台自动更新,进度由通知栏显示 + if (UpdateManager.getInstance().isRunning()) { + UpdateManager.getInstance().onBackgroundTrigger(); + } + } + }); + mProgressDialog.show(); + } + + @Override + public void onProgress(int percent, long totalLength, int patchIndex, int patchCount) { + String tip; + if (patchCount > 0) { + tip = String.format("正在下载补丁%d/%d", patchIndex, patchCount); + } else { + tip = "正在下载更新中..."; + } + mProgressDialog.setProgress(percent); + mProgressDialog.setMessage(tip); + } + + @Override + public void onCompleted() { + mProgressDialog.dismiss(); + } + + @Override + public void onError(String error) { + Toast.makeText(MainActivity.this, error, Toast.LENGTH_LONG).show(); + mProgressDialog.dismiss(); + } + + @Override + public void onCancelUpdate() { + + } + + @Override + public void onBackgroundTrigger() { + Toast.makeText(MainActivity.this, "转为后台更新,进度由通知栏提示!", Toast.LENGTH_LONG).show(); + } + }; + UpdateManager.getInstance().register(mCallback); + } +``` + ### 差分包合成(jni) diff --git a/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java b/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java index b67264d..06620b3 100755 --- a/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java +++ b/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java @@ -1,19 +1,27 @@ package com.lwy.appsmartupdate; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; +import android.widget.Toast; import com.lwy.smartupdate.UpdateManager; import com.lwy.smartupdate.api.IUpdateCallback; +import com.lwy.smartupdate.data.AppUpdateModel; public class MainActivity extends AppCompatActivity { - private String manifestJsonUrl = "https://raw.githubusercontent.com/itlwy/AppSmartUpdate/master/resources/app/UpdateManifest.json"; + private String manifestJsonUrl = "https://raw.githubusercontent.com/itlwy/AppSmartUpdate/master/resources/app/UpdateManifest.json"; // private String manifestJsonUrl = "http://192.168.2.107:8000/app/UpdateManifest.json"; private IUpdateCallback mCallback; private TextView mVersionTV; + private ProgressDialog mProgressDialog; + private AlertDialog mDialog; @Override protected void onCreate(Bundle savedInstanceState) { @@ -21,11 +29,13 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); mVersionTV = (TextView) findViewById(R.id.version_tv); mVersionTV.setText(BuildConfig.VERSION_CODE + ""); + registerUpdateCallbak(); checkUpdate(); + } private void checkUpdate() { - UpdateManager.getInstance().update(this, manifestJsonUrl, null); + UpdateManager.getInstance().update(this, manifestJsonUrl); } @@ -33,27 +43,71 @@ public void registerUpdateCallbak() { mCallback = new IUpdateCallback() { @Override public void noNewApp() { + Toast.makeText(MainActivity.this, "当前已是最新版本!", Toast.LENGTH_LONG).show(); + } + @Override + public void hasNewApp(AppUpdateModel appUpdateModel, UpdateManager updateManager, final int updateMethod) { + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + mDialog = builder.setTitle("自动更新提示") + .setMessage(appUpdateModel.getTip()) + .setPositiveButton("更新", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + UpdateManager.getInstance().startUpdate(updateMethod); + } + }) + .setNegativeButton("取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).create(); + mDialog.show(); } @Override public void beforeUpdate() { - + // 更新开始 + mProgressDialog = new ProgressDialog(MainActivity.this); + mProgressDialog.setTitle("更新中..."); + mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + mProgressDialog.setMessage("正在玩命更新中..."); + mProgressDialog.setMax(100); + mProgressDialog.setProgress(0); + mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + // 退到后台自动更新,进度由通知栏显示 + if (UpdateManager.getInstance().isRunning()) { + UpdateManager.getInstance().onBackgroundTrigger(); + } + } + }); + mProgressDialog.show(); } @Override public void onProgress(int percent, long totalLength, int patchIndex, int patchCount) { - + String tip; + if (patchCount > 0) { + tip = String.format("正在下载补丁%d/%d", patchIndex, patchCount); + } else { + tip = "正在下载更新中..."; + } + mProgressDialog.setProgress(percent); + mProgressDialog.setMessage(tip); } @Override public void onCompleted() { - + mProgressDialog.dismiss(); } @Override public void onError(String error) { - + Toast.makeText(MainActivity.this, error, Toast.LENGTH_LONG).show(); + mProgressDialog.dismiss(); } @Override @@ -63,7 +117,7 @@ public void onCancelUpdate() { @Override public void onBackgroundTrigger() { - + Toast.makeText(MainActivity.this, "转为后台更新,进度由通知栏提示!", Toast.LENGTH_LONG).show(); } }; UpdateManager.getInstance().register(mCallback); diff --git a/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java b/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java index a9cc6e0..fb4b9e9 100755 --- a/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java +++ b/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java @@ -19,6 +19,7 @@ public void onCreate() { super.onCreate(); Config config = new Config.Builder() .isDebug(true) + .isShowInternalDialog(false) .httpManager(new OkhttpManager()) .build(this); UpdateManager.getInstance().init(config); diff --git a/smartupdate/src/main/java/com/lwy/smartupdate/Config.java b/smartupdate/src/main/java/com/lwy/smartupdate/Config.java index fb10d48..7644977 100755 --- a/smartupdate/src/main/java/com/lwy/smartupdate/Config.java +++ b/smartupdate/src/main/java/com/lwy/smartupdate/Config.java @@ -17,12 +17,14 @@ public class Config { private boolean isDebug; private String updateDirPath; private boolean isOnlyWifi; + private boolean isShowDialog; private IHttpManager httpManager; private Config(Builder builder) { isDebug = builder.isDebug; updateDirPath = builder.updateDirPath; isOnlyWifi = builder.isOnlyWifi; + isShowDialog = builder.isShowDialog; httpManager = builder.httpManager; if (httpManager == null) httpManager = new OkhttpManager(); @@ -40,6 +42,10 @@ public boolean isOnlyWifi() { return isOnlyWifi; } + public boolean isShowDialog() { + return isShowDialog; + } + public IHttpManager getHttpManager() { return httpManager; } @@ -48,6 +54,7 @@ public static class Builder { private boolean isDebug; private String updateDirPath; private boolean isOnlyWifi; + private boolean isShowDialog = true; private IHttpManager httpManager; public Builder() { @@ -67,10 +74,17 @@ public Builder isOnlyWifi(boolean flag) { isOnlyWifi = flag; return this; } + + public Builder isShowInternalDialog(boolean flag) { + isShowDialog = flag; + return this; + } + public Builder httpManager(IHttpManager httpManager) { this.httpManager = httpManager; return this; } + public Config build(Context context) { if (TextUtils.isEmpty(updateDirPath)) updateDirPath = context.getExternalFilesDir("update").getAbsolutePath() + "/"; diff --git a/smartupdate/src/main/java/com/lwy/smartupdate/UpdateManager.java b/smartupdate/src/main/java/com/lwy/smartupdate/UpdateManager.java index f3eb29d..e24c88c 100755 --- a/smartupdate/src/main/java/com/lwy/smartupdate/UpdateManager.java +++ b/smartupdate/src/main/java/com/lwy/smartupdate/UpdateManager.java @@ -36,7 +36,6 @@ import static com.lwy.smartupdate.UpdateService.FLAG_UPDATE_PATCH; import static com.lwy.smartupdate.UpdateService.INTENT_ACTION; import static com.lwy.smartupdate.UpdateService.PARAM_ICONRES; -import static com.lwy.smartupdate.UpdateService.PARAM_SHOWFLAG; import static com.lwy.smartupdate.UpdateService.PARAM_UPDATEMETHODFLAG; /** @@ -63,6 +62,10 @@ public class UpdateManager { private int mAppVersionCode; + public boolean isRunning() { + return isRunning; + } + public int getNotifyFlag() { return notifyFlag; } @@ -124,7 +127,7 @@ public UpdateManager init(Config config) { if (config == null) throw new IllegalArgumentException("Config can not be initialized with null"); if (mConfig != null) { - TraceUtil.w("have already initialized,you should call clear method first!!"); + TraceUtil.w("have already initialized,you should call destroy method first!!"); } else { mConfig = config; } @@ -149,7 +152,8 @@ public void destroy(Context context) { mListener.clear(); clear(null); mConfig = null; - sendCancel2Service(context); + if (isRunning) + sendCancel2Service(context); } public void register(IUpdateCallback callback) { @@ -160,6 +164,11 @@ public void register(IUpdateCallback callback) { /************ 分割线 ************/ + public void update(Activity activity, String updateInfoUrl) { + update(activity, updateInfoUrl, null); + } + + /** * 发起更新 * @@ -249,8 +258,8 @@ private void checkUpdate(AppUpdateModel appUpdateModel) { // 使用全量更新 updateMethod = FLAG_UPDATE_ALL; } - beforeUpdate(); - if (mActivityTarget.get() != null) + hasNewApp(updateMethod); + if (mConfig.isShowDialog() && mActivityTarget.get() != null) showUpdateDialog(isForceUpdate, updateMethod, tip); } @@ -260,7 +269,6 @@ private void showUpdateDialog(final boolean isForceUpdate, final int method, Str @Override public void onIgnored(View view) { - // TODO: 2018/8/31 忽略此版本更新,不再提示此版本更新 } @Override @@ -268,16 +276,13 @@ public void onOK(View view) { mUpdateDialogTarget.get().setOKBtnEnable(false); mUpdateDialogTarget.get().showProgressBar(true); mUpdateDialogTarget.get().showIgnoreTextView(false); - startUpdate(0, method); - isRunning = true; + startUpdate(method); mUpdateDialogTarget.get().setUpdating(true); -// showUpdatingDialog(); } @Override public void onClosed(View view) { if (mUpdateDialogTarget.get().isUpdating()) { - notifyFlag = FLAG_NOTIFY_BACKGROUND; onBackgroundTrigger(); } } @@ -290,7 +295,6 @@ public void onClosed(View view) { @Override public void onCancel(DialogInterface dialog) { if (mUpdateDialogTarget.get().isUpdating()) { - notifyFlag = FLAG_NOTIFY_BACKGROUND; onBackgroundTrigger(); } } @@ -311,17 +315,18 @@ private void sendCancel2Service(Context context) { } /** - * @param showFlag 0:前台通知下载,1:后台下载 - * @param method 0:全量更新,1:增量更新 + * @param method 0:全量更新,1:增量更新 */ - private void startUpdate(int showFlag, int method) { + public void startUpdate(int method) { + beforeUpdate(); Intent intent = new Intent(mActivityTarget.get(), UpdateService.class); intent.putExtra(INTENT_ACTION, ACTION_UPDATE); - intent.putExtra(PARAM_SHOWFLAG, showFlag); +// intent.putExtra(PARAM_SHOWFLAG, showFlag); intent.putExtra(PARAM_UPDATEMETHODFLAG, method); intent.putExtra(PARAM_ICONRES, android.R.drawable.btn_star); // intent.putExtra(UPDATE_PARAM_MODEL, mAppUpdateModel); mActivityTarget.get().startService(intent); + isRunning = true; } /************ 分割线 ************/ @@ -339,7 +344,21 @@ public void run() { }); } - void cancelUpdate() { + void hasNewApp(final int updateMethod) { + final AppUpdateModel copyModel = (AppUpdateModel) mAppUpdateModel.clone(); + mDispatcher.dispatch(new Runnable() { + @Override + public void run() { + for (IUpdateCallback iUpdateCallback : UpdateManager.getInstance().mListener) { + iUpdateCallback.hasNewApp(copyModel, UpdateManager.this, updateMethod); + } + } + }); + } + + public void cancelUpdate() { + if (isRunning && mActivityTarget.get() != null) + sendCancel2Service(mActivityTarget.get()); mDispatcher.dispatch(new Runnable() { @Override public void run() { @@ -356,7 +375,11 @@ public void run() { }); } - void onBackgroundTrigger() { + /** + * 触发后台更新模式,由通知栏显示进度 + */ + public void onBackgroundTrigger() { + notifyFlag = FLAG_NOTIFY_BACKGROUND; if (UpdateManager.getInstance().mListener.size() == 0 && mActivityTarget.get() != null) { ToastUtil.toast(mActivityTarget.get(), "更新程序后台进行,可在通知栏查看进度"); @@ -389,7 +412,9 @@ public void run() { } else { tip = "正在下载更新中..."; } - if (mActivityTarget.get() != null) { + if (mActivityTarget.get() != null + && mUpdateDialogTarget != null + && mUpdateDialogTarget.get() != null) { mUpdateDialogTarget.get().setProgress(percent); mUpdateDialogTarget.get().setText(tip); } @@ -404,7 +429,7 @@ void onCompleted() { mDispatcher.dispatch(new Runnable() { @Override public void run() { - if (mUpdateDialogTarget.get() != null) + if (mUpdateDialogTarget != null && mUpdateDialogTarget.get() != null) mUpdateDialogTarget.get().dismiss(); mUpdateDialogTarget = null; for (IUpdateCallback iUpdateCallback : UpdateManager.getInstance().mListener) { @@ -419,7 +444,7 @@ void onError(final String error) { mDispatcher.dispatch(new Runnable() { @Override public void run() { - if (mUpdateDialogTarget.get() != null) + if (mUpdateDialogTarget != null && mUpdateDialogTarget.get() != null) mUpdateDialogTarget.get().dismiss(); mUpdateDialogTarget = null; if (UpdateManager.getInstance().mListener.size() == 0 diff --git a/smartupdate/src/main/java/com/lwy/smartupdate/UpdateService.java b/smartupdate/src/main/java/com/lwy/smartupdate/UpdateService.java index 35770b0..94e9f1b 100755 --- a/smartupdate/src/main/java/com/lwy/smartupdate/UpdateService.java +++ b/smartupdate/src/main/java/com/lwy/smartupdate/UpdateService.java @@ -42,7 +42,7 @@ public class UpdateService extends Service implements IAppUploadTask.CallBack { public static final int ACTION_UPDATE = 100; // 发起更新 public static final int ACTION_CACEL = 101; // 发起取消 - public static final String PARAM_SHOWFLAG = "showFlag"; +// public static final String PARAM_SHOWFLAG = "showFlag"; public static final String PARAM_UPDATEMETHODFLAG = "updateMethod"; public static final String PARAM_ICONRES = "mIconRes"; // public static final String PARAM_UPDATE_PARAM_MODEL = "update_param_model"; diff --git a/smartupdate/src/main/java/com/lwy/smartupdate/api/IUpdateCallback.java b/smartupdate/src/main/java/com/lwy/smartupdate/api/IUpdateCallback.java index 33faf25..b74dbf4 100755 --- a/smartupdate/src/main/java/com/lwy/smartupdate/api/IUpdateCallback.java +++ b/smartupdate/src/main/java/com/lwy/smartupdate/api/IUpdateCallback.java @@ -1,5 +1,8 @@ package com.lwy.smartupdate.api; +import com.lwy.smartupdate.UpdateManager; +import com.lwy.smartupdate.data.AppUpdateModel; + /** * @author lwy 2018/8/30 * @version v1.0.0 @@ -13,6 +16,14 @@ public interface IUpdateCallback { */ void noNewApp(); + /** + * 检测到有新版本更新,运行在主线程,可用来自定义提示框 + * @param appUpdateModel 更新清单的model类 + * @param updateManager 单例的UpdateManager 同UpdateManager.getInstance() + * @param updateMethod 更新的方式,增量 or 全量 + */ + void hasNewApp(AppUpdateModel appUpdateModel, UpdateManager updateManager,int updateMethod); + /** * 检测到有更新,自动更新准备开始时回调,运行在主线程,可做一些提示等 */ diff --git a/smartupdate/src/main/java/com/lwy/smartupdate/data/AppUpdateModel.java b/smartupdate/src/main/java/com/lwy/smartupdate/data/AppUpdateModel.java index c48bc22..8f39c51 100755 --- a/smartupdate/src/main/java/com/lwy/smartupdate/data/AppUpdateModel.java +++ b/smartupdate/src/main/java/com/lwy/smartupdate/data/AppUpdateModel.java @@ -3,12 +3,14 @@ import android.os.Parcel; import java.util.HashMap; +import java.util.Map; +import java.util.Set; /** * Created by lwy on 2018/8/29. */ -public class AppUpdateModel { +public class AppUpdateModel implements Cloneable { /* { "minVersion": "100", "minAllowPatchVersion": "101", @@ -100,6 +102,24 @@ public void setHash(String hash) { this.hash = hash; } + @Override + public Object clone() { + AppUpdateModel cloneModel = null; + try { + cloneModel = (AppUpdateModel) super.clone(); + cloneModel.patchInfoMap = new HashMap(); + Set> entrys = patchInfoMap.entrySet(); + for (Map.Entry entry : entrys) { + String key = entry.getKey(); + PatchInfoModel clonePatchInfoModel = (PatchInfoModel) entry.getValue().clone(); + cloneModel.patchInfoMap.put(key, clonePatchInfoModel); + } + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return cloneModel; + } + public HashMap getPatchInfoMap() { return patchInfoMap; } @@ -108,7 +128,7 @@ public void setPatchInfoMap(HashMap patchInfoMap) { this.patchInfoMap = patchInfoMap; } - public static class PatchInfoModel { + public static class PatchInfoModel implements Cloneable { private String patchURL; private String tip; private int size; @@ -154,6 +174,16 @@ protected PatchInfoModel(Parcel in) { this.hash = in.readString(); } + @Override + public Object clone() { + PatchInfoModel cloneModel = null; + try { + cloneModel = (PatchInfoModel) super.clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return cloneModel; + } } } From 36be822844642e1fe517310a7e1ac71f46c8a4ad Mon Sep 17 00:00:00 2001 From: lwy <9011532@qq.com> Date: Mon, 24 Jun 2019 17:01:23 +0800 Subject: [PATCH 2/2] something changed --- app/src/main/java/com/lwy/appsmartupdate/MainActivity.java | 2 +- app/src/main/java/com/lwy/appsmartupdate/MyApplication.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java b/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java index 06620b3..73a72f6 100755 --- a/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java +++ b/app/src/main/java/com/lwy/appsmartupdate/MainActivity.java @@ -29,7 +29,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); mVersionTV = (TextView) findViewById(R.id.version_tv); mVersionTV.setText(BuildConfig.VERSION_CODE + ""); - registerUpdateCallbak(); +// registerUpdateCallbak(); // 需要自定义弹框时打开注释 checkUpdate(); } diff --git a/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java b/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java index fb4b9e9..b5728d0 100755 --- a/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java +++ b/app/src/main/java/com/lwy/appsmartupdate/MyApplication.java @@ -19,7 +19,7 @@ public void onCreate() { super.onCreate(); Config config = new Config.Builder() .isDebug(true) - .isShowInternalDialog(false) +// .isShowInternalDialog(false) // 需要自定义弹框时打开注释 .httpManager(new OkhttpManager()) .build(this); UpdateManager.getInstance().init(config);