第三方app版本更新

1.第三方app库:

https://github.com/WVector/AppUpdate

引用:

api 'com.qianwen:update-app:3.5.2'

2.可在主页中请求接口判断是否要更新:

ApkUpdateUtils.appUpdate(mActivity);

3.ApkUpdateUtils

public class ApkUpdateUtils {
    public static AppVersionBean appVersionBean;
    public static File apkFile = null;

    public static void appUpdate(final Activity activity) {
        String path = MyApplication.getInstance().getExternalCacheDir().getAbsolutePath();
        String mUpdateUrl = "http";
        new UpdateAppManager
                .Builder()
                //必须设置,当前Activity
                .setActivity(activity)
                .setTargetPath(path)
                //必须设置,实现httpManager接口的对象
                .setHttpManager(new UpdateHttpUtil())
                //必须设置,更新地址
                .setUpdateUrl(mUpdateUrl)
                .setPost(false)
                .build().checkNewApp(new UpdateCallback() {
            /**
             * 解析json,自定义协议
             *
             * @param json 服务器返回的json
             * @return UpdateAppBean
             */
            @Override
            protected UpdateAppBean parseJson(String json) {
                appVersionBean = new Gson().fromJson(json, AppVersionBean.class);

                UpdateAppBean updateAppBean = new UpdateAppBean();
                try {
                    JSONObject jsonObject = new JSONObject(json);
                    updateAppBean
                            //(必须)是否更新Yes,No
                            .setUpdate("Yes")
                            //(必须)新版本号,
                            .setNewVersion(appVersionBean.getVersion())
                            //(必须)下载地址
                            .setApkFileUrl(appVersionBean.getLink())
                            //(必须)更新内容
                            .setUpdateLog(appVersionBean.getDescription())
                            //大小,不设置不显示大小,可以不设置
                            //.setTargetSize(jsonObject.optString("target_size"))
                            //是否强制更新,可以不设置
                            .setConstraint(true);
                    //设置md5,可以不设置
                    // .setNewMd5(jsonObject.optString("new_md5"));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return updateAppBean;
            }

            /**
             * 有新版本
             *
             * @param updateApp        新版本信息
             * @param updateAppManager app更新管理器
             */
            @Override
            public void hasNewApp(UpdateAppBean updateApp, final UpdateAppManager updateAppManager) {
                //自定义对话框
                final VersionDialog dialog = new VersionDialog(activity, appVersionBean);
                dialog.setListerner(new VersionDialog.VersionListerner() {
                    @Override
                    public void startDownload() {
                        updateAppManager.download(new DownloadService.DownloadCallback() {
                            @Override
                            public void onStart() {
                                dialog.showProgressUi();
                            }

                            /**
                             * 进度
                             *
                             * @param progress  进度 0.00 -1.00 ,总大小
                             * @param totalSize 总大小 单位B
                             */
                            @Override
                            public void onProgress(final float progress, long totalSize) {
                                activity.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        dialog.updateProgress((int) progress);
                                    }
                                });

                            }

                            /**
                             *
                             * @param total 总大小 单位B
                             */
                            @Override
                            public void setMax(long total) {

                            }


                            @Override
                            public boolean onFinish(File file) {
                                apkFile = file;
                                return true;
                            }

                            @Override
                            public void onError(String msg) {
                                activity.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        dialog.hideProgressUi();
                                    }
                                });
                            }

                            @Override
                            public boolean onInstallAppAndAppOnForeground(File file) {
                                return false;
                            }
                        });
                    }

                    @Override
                    public void install() {
                        AppUpdateUtils.installApp(activity, apkFile);
                    }
                });
                dialog.show();
            }

            /**
             * 网络请求之前
             */
            @Override
            public void onBefore() {

            }

            /**
             * 网路请求之后
             */
            @Override
            public void onAfter() {

            }

            /**
             * 没有新版本
             */
            @Override
            public void noNewApp(String error) {

            }
        });
    }
}

4.UpdateHttpUtil (自定义网络下载)

public class UpdateHttpUtil implements HttpManager {
    @Override
    public void asyncGet(@NonNull String url, @NonNull Map<String, String> params, @NonNull final
    Callback callBack) {
        final int versionCode = DeviceUtils.getVersionCode(MyApplication.getInstance());
        RetrofitCreateHelper.createApi(CommonLibraryApi.class)
                .getAppVersions(versionCode, "android").compose(RxHelper.<List<AppVersionBean>>rxSchedulerHelper())
                .subscribe(new Consumer<List<AppVersionBean>>() {
                    @Override
                    public void accept(List<AppVersionBean> appVersionBean) throws Exception {
//可以在判断版本之后在设置是否强制更新或者VersionParams
                        if (appVersionBean != null && !appVersionBean.isEmpty()
                                && versionCode < appVersionBean.get(0).getVersion_code()) {
                            callBack.onResponse(new Gson().toJson(appVersionBean.get(0)));
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Log.d("version", "accept: " + throwable.getMessage());
                    }
                });
    }

    @Override
    public void asyncPost(@NonNull String url, @NonNull Map<String, String> params, @NonNull
            Callback callBack) {

    }

    @Override
    public void download(@NonNull String url, @NonNull final String path, @NonNull final String fileName,
                         @NonNull final FileCallback callback) {
        OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
        OkHttpClient client = okHttpClient
                .retryOnConnectionFailure(true)
                .sslSocketFactory(DownloadFileUrlConnectionImpl.createSSLSocketFactory())
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS).build();

        Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("pdf", "onFailure: " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    File dir = new File(path);
                    IoUtils.createFolder(dir);
                    File file = new File(dir, fileName);
                    IoUtils.delFileOrFolder(file);

                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total*100);
                        // 下载中
                        Log.e("apk", "onLoad: " + progress);
                        callback.onProgress(progress, total);
                    }
                    fos.flush();
                    // 下载完成
                    callback.onResponse(file);
                } catch (Exception e) {
                    callback.onError("异常");
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }

            }
        });
    }
}

5.自定义VersionDialog (含有非强制更新,强制更新一些列操作,后台返回的是markdown格式,结合需求自己定义)

public class VersionDialog extends Dialog {

    AppVersionBean appVersionBean;
    private LinearLayout ll_progress;
    private TextView tv_progress;
    private ProgressBar pb;
    private TextView tvInstall;
    private boolean isForceUpdate;  //true 强制更新,

    public VersionDialog(@NonNull Context context, AppVersionBean appVersionBean) {
        super(context);
        this.appVersionBean = appVersionBean;
        isForceUpdate = appVersionBean.getIs_forced() > 0;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Window window = getWindow();
        window.setGravity(Gravity.CENTER);
        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.custom_dialog_two_layout);
        TextView tvTitle = (TextView) findViewById(com.ls.commonlibrary.R.id.tv_title);
        final MarkdownView mdMsg = (MarkdownView) findViewById(com.ls.commonlibrary.R.id.md_msg);
        TextView tvAbord = (TextView) findViewById(com.ls.commonlibrary.R.id.tv_abord);
        tvInstall = (TextView) findViewById(com.ls.commonlibrary.R.id.versionchecklib_version_dialog_commit);
        View line = findViewById(com.ls.commonlibrary.R.id.view_line);
        ImageView close = (ImageView) findViewById(com.ls.commonlibrary.R.id.img_close);
        ll_progress = (LinearLayout) findViewById(R.id.ll_progress);
        tv_progress = (TextView) findViewById(R.id.tv_progress);
        pb = (ProgressBar) findViewById(R.id.pb);
        //可以使用之前从service传过来的一些参数比如:title。msg,downloadurl,parambundle
        tvTitle.setText("V" + appVersionBean.getVersion() + "版本更新");
        InternalStyleSheet css = new Github();
        css.addRule(".container", "padding-right:0", ";padding-left:0", "text-align:justify",
                "text-align-last:left", "letter-spacing: 0.3px");
        css.addRule("body", "line-height: 1.59", "padding: 0px", "font-size: 17px", "color: " +
                "#333333");
        css.addRule("h1", "color: #333333", "size: 25px", "margin-top: 30px", "magin-bottom: " +
                "30px", "text-align: left");
        css.addRule("h2", "color: #333333", "size: 23px", "margin-top: 30px", "magin-bottom: " +
                "30px", "text-align: left");
        css.addRule("h3", "color: #333333", "size: 21px", "margin-top: 30px", "magin-bottom: " +
                "30px", "text-align: left");
        css.addRule("h4", "color: #333333", "size: 19px", "margin-top: 30px", "magin-bottom: " +
                "30px", "text-align: left");
        css.addRule("img", "margin-top: 20px", "margin-bottom: 20px", "align:center", "margin: 0 " +
                "auto", "max-width: 100%", "display: block");
        /*设置 a 标签文字颜色,不知道为什么,要这样混合才能有效*/
        css.addMedia("color: #59b6d7; a:link {color: #59b6d7}");
        css.endMedia();
        css.addRule("a", "font-weight: bold");
        mdMsg.addStyleSheet(css);
        mdMsg.loadMarkdown(appVersionBean.getDescription());
        WebViewClient mWebViewClient = new WebViewClient() {
            /**
             * 多页面在同一个 WebView 中打开,就是不新建 activity 或者调用系统浏览器打开
             */
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }

            /**
             * 网页开始加载
             * @param view
             * @param url
             * @param favicon
             */
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            /**
             *   网页加载结束
             */
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                mdMsg.scrollTo(0, 0);
            }

            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String
                    failingUrl) {
                System.out.println("errorCode = " + errorCode);
                super.onReceivedError(view, errorCode, description, failingUrl);
            }
        };
        mdMsg.setWebViewClient(mWebViewClient);

        tvInstall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvInstall.setVisibility(View.GONE);
                ll_progress.setVisibility(View.VISIBLE);
                if (listerner != null) {
                    listerner.startDownload();
                }
            }
        });
        if (!isForceUpdate) {
            line.setVisibility(View.VISIBLE);
            close.setVisibility(View.VISIBLE);
            close.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dismiss();
                }
            });
        }
        setCanceledOnTouchOutside(!isForceUpdate);
        setCancelable(!isForceUpdate);
        if (isForceUpdate) {
            setOnKeyListener(new DialogInterface.OnKeyListener() {
                @Override
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        return true;
                    } else {
                        return false; //默认返回 false
                    }
                }
            });
        }
    }

    public void updateProgress(int progress) {
        tv_progress.setText(progress + "%");
        pb.setProgress(progress);

        if (progress == 100) {
            hideProgressUi();
            tvInstall.setText("安装");
            tvInstall.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listerner != null) {
                        listerner.install();
                    }
                }
            });
        }
    }

    VersionListerner listerner;

    public void setListerner(VersionListerner listerner) {
        this.listerner = listerner;
    }

    public interface VersionListerner {
        void startDownload();

        void install();
    }

    public void showProgressUi() {
        tvInstall.setVisibility(View.GONE);
        ll_progress.setVisibility(View.VISIBLE);
    }

    public void hideProgressUi() {
        tvInstall.setText("重新下载");
        tvInstall.setVisibility(View.VISIBLE);
        ll_progress.setVisibility(View.GONE);
    }
}



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
框架内部支持中/英文(其他语言只需要在对应的string.xml中取相同的名字即可)内部对话框背景图片、按钮支持自定义了查看版本中的Log只需要过滤AppUpdate开头的Tag重点: 如果没有设置downloadPath则默认为getExternalCacheDir()目录,同时不会申请[存储]权限!目录编译问题效果图功能介绍DownloadManagerUpdateConfiguration使用步骤Demo下载体验版本更新记录结语编译问题因为适配了Android O的通知栏,所以依赖的v7包版本比较高appcompat-v7:26.1.0使用的gradle版本为gradle-4.1-all,所以建议使用Android Studio 3.0及以上的版本打开此项目效果图     功能介绍 支持断点下载 支持后台下载 支持自定义下载过程 支持 设备 >= Android M 动态权限的申请 支持通知栏进度条展示(或者自定义显示进度) 支持Android N 支持Android O 支持中/英文双语 支持自定内置对话框的样式 使用HttpURLConnection下载,未集成其他第三方框架更加详细的文档参阅此处《AppUpdate API文档》DownloadManager:配置文档初始化使用DownloadManager.getInstance(this)属性描述默认值是否必须设置context上下文nulltrueapkUrlapk的下载地址nulltrueapkNameapk下载好的名字nulltruedownloadPathapk下载的位置getExternalCacheDir()falseshowNewerToast是否提示用户 "当前已是最新版本"falsefalsesmallIcon通知栏的图标(资源id)-1trueconfiguration这个库的额外配置nullfalseapkVersionCode更新apk的versionCode (如果设置了那么库中将会进行版本判断下面的属性也就需要设置了)1falseapkVersionName更新apk的versionNamenullfalseapkDescription更新描述nullfalseapkSize新版本的安装包大小(单位M)nullfalseauthorities兼容Android N uri授权应用包名falseUpdateConfiguration:配置文档属性描述默认值notifyId通知栏消息id1011notificationChannel适配Android O的渠道通知详情查阅源码httpManager设置自己的下载过程nullbreakpointDownload是否需要支持断点下载trueenableLog是否需要日志输出trueonDownloadListener下载过程的回调nulljumpInstallPage下载完成是否自动弹出安装页面trueshowNotification是否显示通知栏进度(后台下载提示)trueforcedUpgrade是否强制升级falseonButtonClickListener按钮点击事件回调nulldialogImage对话框背景图片资源(图片规范参考demo)-1dialogButtonColor对话框按钮的颜色-1dialogButtonTextColor对话框按钮的文字颜色-1所有版本:点击查看使用步骤第一步: app/build.gradle进行依赖implementation 'com.azhon:appupdate:1.7.3'第二步:创建DownloadManager,更多用法请查看这里示例代码DownloadManager manager = DownloadManager.getInstance(this); manager.setApkName("appupdate.apk")         .setApkUrl("https://raw.githubusercontent.com/azhon/AppUpdate/master/apk/appupdate.apk")         .setSmallIcon(R.mipmap.ic_launcher)         //可设置,可不设置         .setConfiguration(configuration)         .download();第三步:兼容Android N 及以上版本,在你应用的Manifest.xml添加如下代码<--! android:authorities="${applicationId}"  这个值必须与DownloadManager中的authorities一致(不设置则为应用包名)--> <provider     android:name="android.support.v4.content.FileProvider"     android:authorities="${applicationId}"     android:exported="false"     android:grantUriPermissions="true">     <meta-data         android:name="android.support.FILE_PROVIDER_PATHS"         android:resource="@xml/file_paths_public" /> </provider>第四步:资源文件res/xml/file_paths_public.xml内容<?xml version="1.0" encoding="utf-8"?> <paths>     <external-path         name="app_update_external"         path="/" />     <external-cache-path         name="app_update_cache"         path="/" /> </paths>兼容Android O及以上版本,需要设置NotificationChannel(通知渠道);库中已经写好可以前往查阅NotificationUtil.java温馨提示:升级对话框中的内容是可以上下滑动的哦!如果需要实现自己一套下载过程,只需要继承BaseHttpDownloadManager 并使用listener更新进度public class MyDownload extends BaseHttpDownloadManager {}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值