AppUpdate Android Library

repository·master·Indexed 25 days ago

https://github.com/wvector/appupdate

An Android library for managing application updates with support for Java and Kotlin. It features forced updates, silent background downloads (e.g., Wi-Fi only), progress visualization in dialogs and notification bars, and custom protocol integration via the HttpManager interface. The library provides a default JSON protocol for update checks and allows for custom UI dialogs and custom server response parsing using UpdateCallback.

Tokens
5K
Snippets
13
Records
18
Agent score
86%

What's inside AppUpdate

  1. Add AppUpdate dependency to Gradle

    master

    Depending on your preferred language, add the corresponding dependency to your build.gradle file.

    For Java projects, use update-app. For Kotlin projects, use update-app-kotlin for a more concise syntax.

    // Java
    dependencies {
        compile 'com.qianwen:update-app:3.5.2'
    }
    
    // Kotlin
    dependencies {
        compile 'com.qianwen:update-app-kotlin:1.2.3'
    }
  2. Configure the default AppKey in AndroidManifest

    master

    To use the default interface protocol, you can configure a unique appKey for your application in the AndroidManifest.xml file using a <meta-data> tag. This key is used by the tool to identify your app on the server.

    <meta-data
        android:name="UPDATE_APP_KEY"
        android:value="ab55ce55Ac4bcP408cPb8c1Aaeac179c5f6f"/>
  3. Implement a custom interface protocol

    master

    For projects with custom API requirements, use the updateApp builder to configure request methods, custom parameters, download paths, and UI styling. You must implement the parseJson block to map your server's JSON response to an UpdateAppBean object.

    // Download path
    val path = Environment.getExternalStorageDirectory().absolutePath
    // Custom parameters
    val params = HashMap<String, String>()
    params.put("appKey", "ab55ce55Ac4bcP408cPb8c1Aaeac179c5f6f")
    params.put("appVersion", AppUpdateUtils.getVersionName(this))
    params.put("key1", "value2")
    params.put("key2", "value3")
    
    updateApp(mUpdateUrl, UpdateAppHttpUtil())
    {
        isPost = false
        setParams(params)
        hideDialogOnDownloading(true)
        topPic = R.mipmap.top_8
        targetPath = path
    }
    .check {
        onBefore { showProgressDialog() }
        parseJson {
            val jsonObject = JSONObject(it)
            UpdateAppBean()
                .setUpdate(jsonObject.optString("update"))
                .setNewVersion(jsonObject.optString("new_version"))
                .setApkFileUrl(jsonObject.optString("apk_file_url"))
                .setUpdateLog(jsonObject.optString("update_log"))
                .setTargetSize(jsonObject.optString("target_size"))
                .setConstraint(false)
                .setNewMd5(jsonObject.optString("new_md5"))
        }
        noNewApp { toast("没有新版本") }
        onAfter { cancelProgressDialog() }
    }
  4. Use Custom Dialogs with Updates

    master

    To use your own UI for the update prompt, override the hasNewApp method in UpdateCallback. You can then use the provided UpdateAppBean to populate your dialog and use updateAppManager.download() to trigger the download process.

    To monitor download progress within your custom dialog, pass a DownloadService.DownloadCallback to the download() method.

    // 1. Override hasNewApp to show your own dialog
    @Override
    public void hasNewApp(UpdateAppBean updateApp, UpdateAppManager updateAppManager) {
        showDiyDialog(updateApp, updateAppManager);
    }
    
    // 2. Inside your dialog, trigger download with a progress callback
    private void showDiyDialog(final UpdateAppBean updateApp, final UpdateAppManager updateAppManager) {
        // ... setup your AlertDialog ...
        .setPositiveButton("升级", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                updateAppManager.download(new DownloadService.DownloadCallback() {
                    @Override
                    public void onStart() { /* Show progress UI */ }
    
                    @Override
                    public void onProgress(float progress, long totalSize) {
                        // progress is 0.00 - 1.00
                    }
    
                    @Override
                    public boolean onFinish(File file) {
                        // Return true to auto-install, false to just finish download
                        return true;
                    }
    
                    @Override
                    public void onError(String msg) { /* Handle error */ }
                });
                dialog.dismiss();
            }
        })
    }
  5. Perform Silent Updates

    master

    Silent updates download the APK in the background (e.g., only on WiFi) and only prompt the user once the download is complete.

    Default Protocol Silent Update: Use .silenceUpdate() on the builder.

    Custom Protocol Silent Update: Use .checkNewApp() with a SilenceUpdateCallback. The showDialog method in the callback is triggered after the download finishes, providing the File object for installation.

    // Default protocol silent update
    new UpdateAppManager.Builder()
            .setActivity(this)
            .setUpdateUrl(mUpdateUrl)
            .setHttpManager(new UpdateAppHttpUtil())
            .setOnlyWifi()
            .build()
            .silenceUpdate();
    
    // Custom protocol silent update
    new UpdateAppManager.Builder()
            .setActivity(this)
            .setUpdateUrl(mUpdateUrl)
            .setHttpManager(new OkGoUpdateHttpUtil())
            .build()
            .checkNewApp(new SilenceUpdateCallback() {
                @Override
                protected void showDialog(UpdateAppBean updateApp, UpdateAppManager updateAppManager, File appFile) {
                    // Show your dialog and call AppUpdateUtils.installApp(context, appFile) on click
                }
            });
  6. Monitor download progress with a custom dialog

    master

    When using a custom dialog, you can pass a callback to updateAppManager.download to listen to the download lifecycle. Use onStart, onProgress, onFinish, and onError to update your UI. Returning true in onFinish will automatically trigger the installation interface.

    updateAppManager.download {
        onStart { HProgressDialogUtils.showHorizontalProgressDialog(this@KotlinActivity, "下载进度", false) }
        onProgress { progress, _ -> HProgressDialogUtils.setProgress(Math.round(progress * 100)) }
        onFinish {
            HProgressDialogUtils.cancel()
            true // Return true to trigger auto-install
        }
        onError { error ->
            toast(error)
            HProgressDialogUtils.cancel()
        }
    }
  7. Implement Custom Interface Protocol

    master

    If your server uses a different API structure, use the checkNewApp method with a custom UpdateCallback. You must implement parseJson to map your server's response to an UpdateAppBean object.

    Customizable Options via Builder:

    • setPost(boolean): Set request method (default is GET).
    • setParams(Map<String, String>): Add custom request parameters.
    • hideDialogOnDownloading(boolean): If true, the dialog disappears once downloading starts.
    • setTopPic(int resId): Set a header image; the library automatically extracts the theme color for buttons and progress bars.
    • setTargetPath(String path): Specify where to save the APK.
    • dismissNotificationProgress(): Hides the notification bar progress indicator.
    • showIgnoreVersion(): Allows the user to ignore the update version.
    new UpdateAppManager
            .Builder()
            .setActivity(this)
            .setHttpManager(new OkGoUpdateHttpUtil())
            .setUpdateUrl(mUpdateUrl)
            .setPost(false)
            .setParams(params)
            .hideDialogOnDownloading(false)
            .setTopPic(R.mipmap.top_8)
            .setTargetPath(path)
            .dismissNotificationProgress()
            .build()
            .checkNewApp(new UpdateCallback() {
                @Override
                protected UpdateAppBean parseJson(String json) {
                    UpdateAppBean updateAppBean = new UpdateAppBean();
                    try {
                        JSONObject jsonObject = new JSONObject(json);
                        updateAppBean
                                .setUpdate(jsonObject.optString("update"))
                                .setNewVersion(jsonObject.optString("new_version"))
                                .setApkFileUrl(jsonObject.optString("apk_file_url"))
                                .setUpdateLog(jsonObject.optString("update_log"))
                                .setTargetSize(jsonObject.optString("target_size"))
                                .setConstraint(false)
                                .setNewMd5(jsonObject.optString("new_md51"));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    return updateAppBean;
                }
    
                @Override
                public void onBefore() { /* Show loading dialog */ }
    
                @Override
                public void onAfter() { /* Hide loading dialog */ }
    
                @Override
                public void noNewApp() { /* Handle no update case */ }
            });
  8. Use custom dialogs for update notifications

    master

    To use your own UI instead of the library's default dialog, override the hasNewApp method within the updateApp check block. You can access the UpdateAppBean (containing version info) and UpdateAppManager (to control the download) to drive your custom dialog.

    hasNewApp {\n    showDiyDialog(updateApp, updateAppManager)\n}
    
    // Inside your custom dialog logic:
    dialog("是否升级到${updateApp.newVersion}版本?", "新版本大小:${updateApp.targetSize}\n\n${updateApp.updateLog}")
    {
        positiveButton("升级") {
            updateAppManager.download()
            dismiss()
        }
        negativeButton("暂不升级") {
            dismiss()
        }
        show()
    }
  9. Use the Default Interface Protocol

    master

    The default protocol uses a GET request to check for updates. The client automatically sends appKey (configured in AndroidManifest.xml) and version (the current app version) as query parameters.

    1. Configure App Key Add the UPDATE_APP_KEY meta-data to your AndroidManifest.xml:

    2. Server Response Format If an update is available, the server must return a JSON object with these keys:

    • update: "Yes" or "No"
    • new_version: The new version string
    • apk_file_url: URL to the APK
    • update_log: Text describing changes
    • target_size: Size of the APK (e.g., "5M")
    • new_md5: MD5 hash of the APK
    • constraint: Boolean (true for forced update)

    If no update is available, return:

    {
      "update": "No"
    }
    <meta-data
        android:name="UPDATE_APP_KEY"
        android:value="ab55ce55Ac4bcP408cPb8c1Aaeac179c5f6f"/>
  10. Use the default interface protocol for updates

    master
    If your server follows the default JSON protocol, you can trigger an update check using updateApp. The tool automatically handles the version parameter and parses the response. You only need to provide the update URL and an implementation of UpdateAppHttpUtil.
  11. Implement app updates in Kotlin

    master

    For Kotlin projects, the library provides a simplified extension function updateApp to trigger the update process. Pass the update URL and an instance of UpdateAppHttpUtil directly.

    updateApp(mUpdateUrl, UpdateAppHttpUtil()).update()
  12. Implement app updates in Java

    master

    To trigger an update in a Java-based Android application, use the UpdateAppManager.Builder to configure the update process. You must provide the current Activity, the update URL, and an implementation of the HttpManager interface (e.g., UpdateAppHttpUtil).

    new UpdateAppManager
                    .Builder()
                    //当前Activity
                    .setActivity(this)
                    //更新地址
                    .setUpdateUrl(mUpdateUrl)
                    //实现httpManager接口的对象
                    .setHttpManager(new UpdateAppHttpUtil())
                    .build()
                    .update();