XUpdate

A lightweight, highly available Android version update framework. Click on the instruction document to experience it!

Before asking an issue, please read the wisdom of Asking and fill in the issue template strictly to save your time.

Before use, please read the instructions carefully and say the important things three times!!

Before use, please read the instructions carefully and say the important things three times!!

Before use, please read the instructions carefully and say the important things three times!!

About me

Fast integration of X series libraries

In order to facilitate the rapid integration of the X series framework library, I provide an empty shell template for your reference: github.com/xuexiangjys…


The characteristics of

  • Supports the POST and GET version check modes, and supports user-defined network requests.

  • Support setting for version update only in wifi.

  • Support silent download (background update), automatic version update.

  • Provides a friendly version update pop-up, which can be customized theme style.

  • Support for custom version update checker, version update parser, version update reminder, version update downloader, version update installation, error handling.

  • Supports MD5 file verification, version neglect, and forced version update.

  • Supports custom file verification (MD5 verification by default).

  • Support custom request APIS.

  • Compatible with Android6.0, 7.0, 8.0 and 9.0.

  • Supports both Chinese and English language display (internationalization)

The structure

This framework draws lessons from some ideas and UI interface in API Update, and extracts each part of version update to form the following parts:

  • Version update checker IUpdateChecker: Checks to see if the latest version is available.

  • Version update parser IUpdateParser: Parses the data results returned by the server.

  • IUpdatePrompter: Displays the latest version information.

  • Version update downloader: downloads the APK installation package of the latest version.

  • Network Request Service interface IUpdateHttpService: Defines the interface for making network requests.

In addition, there are two listeners:

  • Version update failed listener OnUpdateFailureListener.

  • Version updates the apK installed listener OnInstallListener.

1. Demonstration (please star support)

  • Default version update

  • Force version updates

  • Customize the pop-up theme

  • Use the system popover

Download the Demo

2. How to use it

AndroidStudio is currently supported. You can configure build.gradle directly and add dependencies.

Add Gradle dependencies to Android Studio

1. Add repositories for Build. Gradle

allprojects {
     repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
Copy the code

2. In Dependencies, add:

dependencies { ... Implementation 'com. Making. Xuexiangjys: XUpdate: 1.1.1'}Copy the code

Initialize XUpdate

Initial configuration in Application:

Xupdate.get ().debug(true).isWifionly (true) // Default to check version updates.isget (true) // Default to check version with get request.isautomode (false) // The default mode is not automatic, Can be used depending on the configuration. The param (" versionCode ", UpdateUtils getVersionCode (this)) / / set the default public request parameters. The param (" appKey ", GetPackageName ()). SetOnUpdateFailureListener (new OnUpdateFailureListener () {/ / set the version update error listening in @ Override public void onFailure(UpdateError error) { if (error.getCode() ! = CHECK_NO_NEW_VERSION) {// handle different errors toastutils.toast (error-tostring ()); SetIUpdateHttpService (new OKHttpUpdateHttpService()) // This must be set! Implement network request function. .init(this); // This must be initializedCopy the code

[Note] : If there is any problem, enable debug mode to trace the problem. If you also need to log to disk, you can implement the following interface

XUpdate.get().setILogger(new ILogger() { @Override public void log(int priority, String tag, String message, Throwable t) {// implement logging function}});Copy the code

2.3. Update entity information

(1) UpdateEntity field attribute

The field name type The default value note
mHasUpdate boolean false Whether there is a new version
mIsForce boolean false Mandatory installation or not: The APP cannot be used without installation
mIsIgnorable boolean false Whether the version can be ignored
mVersionCode int 0 Latest version code
mVersionName String unknown_version Name of latest version
mUpdateContent String “” Update the content
mDownloadEntity DownloadEntity / Download information entities
mIsSilent boolean false Silent download or not: Download a new version without prompting
mIsAutoInstall boolean true Whether to install the software automatically after the download is complete

(2) The DownloadEntity field property

The field name type The default value note
mDownloadUrl String “” Download address
mCacheDir String “” Directory where the file is downloaded
mMd5 String “” Encryption verification value of the downloaded file (md5 encryption is used by default). It is used for verification to prevent the downloaded APK file from being replaced. (The latest demo contains a tool to calculate the verification value.)
mSize long 0 Size of the downloaded file [in KB]
mIsShowNotification boolean false Whether to display the download progress in the notification bar

2.4 File encryption verification mode

If you do not want to use MD5 encryption, you can also customize IFileEncryptor. The following is the implementation of the MD5 file encryptor.

** @author xuexiang * @since 2019-09-06 14:21 */ public class DefaultFileEncryptor implements. /** * The default file encryption computation uses MD5 encryption ** @author xuexiang * @since 2019-09-06 14:21 */ IFileEncryptor {/** * encryptFile ** @param file * @return */ @override public String encryptFile(file file) {return Md5Utils.getFileMD5(file); } /** * Verify that the file is valid (the encryption is consistent) ** @param encrypt encrypts the value, if encrypt is empty, * @override public Boolean isFileValid(String encrypt, encrypt) File file) { return TextUtils.isEmpty(encrypt) || encrypt.equalsIgnoreCase(encryptFile(file)); }}Copy the code

Finally, the setting takes effect by calling the xupdate.get ().setiFileEncryptor method.

3. Version update

3.1. Update the default version

To complete the version update operation, call the following code directly:

XUpdate.newBuild(getActivity())
        .updateUrl(mUpdateUrl)
        .update();
Copy the code

Note that with the default version update, the json format returned by the request server should include the following:

{"Code": 0, "Msg": "", "UpdateStatus": 1, "VersionCode": 3, "VersionName": "1.0.2", "ModifyContent": "1, optimized API interface. \r\n2, add use demo. \r\n3. Added custom update service API. \r\n4. Optimize the update prompt interface. , "DownloadUrl" : "https://raw.githubusercontent.com/xuexiangjys/XUpdate/master/apk/xupdate_demo_1.0.2.apk", "ApkSize" : 2048 "ApkMd5": "..." // If the md5 value is not included, the apK is not guaranteed to be complete and will be re-downloaded every time. }Copy the code

3.2. Automatic version updates

Automatic version update: automatic version check + automatic download APK + automatic installation APK (silent installation). You only need to set isAutoMode(true), but full automatic updates are not possible if the device does not have root permission (because silent installation requires root permission).

Xupdate.newbuild (getActivity()).updateurl (mUpdateUrl).isautomode (true);Copy the code

3.3. Force version update

That is, if the user does not update, the program will not work properly. The server only needs to return the UpdateStatus field as 2.

Set the mIsForce field of UpdateEntity to true if you want to customize the request return API.

3.4. Customize the theme of the version update prompt popup

You can set the popover title background and button color.

  • ThemeColor: set the themeColor (the background color of the upgrade/install button)
  • TopResId: Resource image for popover title background
XUpdate.newBuild(getActivity())
        .updateUrl(mUpdateUrl)
        .themeColor(ResUtils.getColor(R.color.update_theme_color))
        .topResId(R.mipmap.bg_update_top)
        .update();
Copy the code

Update the parser with a custom version

You can customize the parser by implementing the IUpdateParser interface.

Xupdate.newbuild (getActivity()).updateurl (mUpdateUrl3).updateparser (new CustomUpdateParser()) // set a custom version of the updateParser .update(); public class CustomUpdateParser implements IUpdateParser { @Override public UpdateEntity parseJson(String json) throws Exception { CustomResult result = JsonUtil.fromJson(json, CustomResult.class); if (result ! = null) { return new UpdateEntity() .setHasUpdate(result.hasUpdate) .setIsIgnorable(result.isIgnorable) .setVersionCode(result.versionCode) .setVersionName(result.versionName) .setUpdateContent(result.updateLog) .setDownloadUrl(result.apkUrl) .setSize(result.apkSize); } return null; }}Copy the code

3.6. Custom version Update checker + Version update parser + Version update cue

  • You can customize the inspector by implementing the IUpdateChecker interface.

  • You can customize the parser by implementing the IUpdateParser interface.

  • You can implement the IUpdatePrompter interface to customize the prompter.

XUpdate.newBuild(getActivity()) .updateUrl(mUpdateUrl3) .updateChecker(new DefaultUpdateChecker() { @Override public void onBeforeCheck() { super.onBeforeCheck(); CProgressDialogUtils. ShowProgressDialog (getActivity (), "in the query..." ); } @Override public void onAfterCheck() { super.onAfterCheck(); CProgressDialogUtils.cancelProgressDialog(getActivity()); } }) .updateParser(new CustomUpdateParser()) .updatePrompter(new CustomUpdatePrompter(getActivity())) .update(); public class CustomUpdatePrompter implements IUpdatePrompter { private Context mContext; public CustomUpdatePrompter(Context context) { mContext = context; } @Override public void showPrompt(@NonNull UpdateEntity updateEntity, @NonNull IUpdateProxy updateProxy) { showUpdatePrompt(updateEntity, updateProxy); } /** * Display a custom prompt ** @param updateEntity * @param updateProxy */ private void showUpdatePrompt(final @nonNULL UpdateEntity updateEntity, final @NonNull IUpdateProxy updateProxy) { String updateInfo = UpdateUtils.getDisplayUpdateInfo(updateEntity); New alertDialog.Builder (mContext).setTitle(String. Format (" Upgrade to %s version? ") , updateEntity getVersionName ())). SetMessage (updateInfo). SetPositiveButton (" upgrade ", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { updateProxy.startDownload(updateEntity, new OnFileDownloadListener() { @Override public void onStart() { HProgressDialogUtils. ShowHorizontalProgressDialog (mContext, "progress", false); } @Override public void onProgress(float progress, long total) { HProgressDialogUtils.setProgress(Math.round(progress * 100)); } @Override public boolean onCompleted(File file) { HProgressDialogUtils.cancel(); return true; } @Override public void onError(Throwable throwable) { HProgressDialogUtils.cancel(); }}); }}).setnegativeButton (" not yet upgrade ", null).setCancelable(false).create().show(); }Copy the code

3.7 use only the XUpdate downloader function to download APK

XUpdate. NewBuild (getActivity ()). ApkCacheDir (PathUtils. GetExtDownloadsPath ()) / / set the root directory of the download cache. The build () .download(mDownloadUrl, New OnFileDownloadListener() {// set the address and listener to download @override public void onStart() { HProgressDialogUtils. ShowHorizontalProgressDialog (getContext (), "progress", false); } @Override public void onProgress(float progress, long total) { HProgressDialogUtils.setProgress(Math.round(progress * 100)); } @Override public boolean onCompleted(File file) { HProgressDialogUtils.cancel(); Toastutils.toast ("apk downloaded, file path: "+ file.getPath())); return false; } @Override public void onError(Throwable throwable) { HProgressDialogUtils.cancel(); }});Copy the code

3.8. Use only the APK installation of XUpdate

_XUpdate.startInstallApk(getContext(), FileUtils.getFileByPath(PathUtils.getFilePathByUri(getContext(), data.getData()))); // Enter the path where the file is locatedCopy the code

If your APK installation is different, you can implement your own APK installer. You only need to implement OnInstallListener interfaces, and through the XUpdate. SetOnInstallListener set to take effect.

Confuse configuration

-keep class com.xuexiang.xupdate.entity.** { *; }
Copy the code

Special thanks to

Github.com/WVector/App…

Wechat official account

For more information, welcome to wechat search official account: [My Android Open Source Journey]