前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 更新实现

Android 更新实现

作者头像
用户4458175
发布2020-02-12 17:01:33
6720
发布2020-02-12 17:01:33
举报
文章被收录于专栏:andy的小窝

Gradle 引入

代码语言:javascript
复制
    compile 'com.qiangxi.checkupdatelibrary:checkupdatelibrary:1.1.3@aar'

自定义一个ForceUpdateDialog

代码语言:javascript
复制
public class ForceUpdateDialog extends Dialog {
    private Context context;
    private View view;
    private TextView forceUpdateTitle;//标题
    private TextView forceUpdateTime; //发布时间
    private TextView forceUpdateVersion;//版本名
    private TextView forceUpdateSize;//软件大小
    private TextView forceUpdateDesc;//更新日志
    private LinearLayout forceUpdateDescLayout;//更新日志根布局
    private TextView forceUpdateNetworkState;//网络状况
    private NumberProgressBar forceUpdateProgress;//下载进度
    private Button forceUpdate;//开始更新
    private Button exitApp;//退出应用

    private String mDownloadUrl;//软件下载地址
    private String mTitle;//标题
    private String mAppTime;//发布时间
    private String mVersionName;//版本名
    private float mAppSize;//软件大小
    private String mAppDesc;//更新日志
    private String mFilePath;//文件存储路径
    private String mFileName;//自定义的文件名
    private long timeRange;//时间间隔

    private Fragment mCompatFragmentCallback;//兼容v4版本fragment
    private android.app.Fragment mFragmentCallback;//兼容3.0的fragment
    public boolean isForce=false;

    public boolean isForce() {
        return isForce;
    }

    public void setForce(boolean force) {
        isForce = force;
    }

    public static final int FORCE_UPDATE_DIALOG_PERMISSION_REQUEST_CODE = 1;//权限请求码

    /**
     * 在activity中动态请求权限使用这个构造方法
     */
    public ForceUpdateDialog(Context context) {
        super(context);
        setDialogTheme();
        setCanceledOnTouchOutside(false);
        this.context = context;
    }

    /**
     * 在v4包的Fragment中动态请求权限使用这个构造方法
     */
    public ForceUpdateDialog(Context context, @NonNull Fragment fragment) {
        this(context);
        mCompatFragmentCallback = fragment;
    }

    /**
     * 在app包的Fragment中动态请求权限使用这个构造方法
     */
    public ForceUpdateDialog(Context context, @NonNull android.app.Fragment fragment) {
        this(context);
        mFragmentCallback = fragment;
    }

    /**
     * set dialog theme(设置对话框主题)
     */
    private void setDialogTheme() {
        requestWindowFeature(Window.FEATURE_NO_TITLE);// android:windowNoTitle
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);// android:backgroundDimEnabled默认是true的
        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));// android:windowBackground
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        view = LayoutInflater.from(context).inflate(R.layout.checkupdatelibrary_force_update_dialog_layout, null);
        setContentView(view);
        initView();
        initData();
        initEvent();
    }

    private void initData() {
        //标题
        if (TextUtils.isEmpty(mTitle)) {
            forceUpdateTitle.setVisibility(View.GONE);
        } else {
            forceUpdateTitle.setText(mTitle);
        }
        //发布时间
        if (TextUtils.isEmpty(mAppTime)) {
            forceUpdateTime.setVisibility(View.GONE);
        } else {
            forceUpdateTime.setText("发布时间:" + mAppTime);
        }
        //新版版本名,eg:2.2.1
        if (TextUtils.isEmpty(mVersionName)) {
            forceUpdateVersion.setVisibility(View.GONE);
        } else {
            forceUpdateVersion.setText("版本:" + mVersionName);
        }
        //新版本app大小
        if (mAppSize == 0) {
            forceUpdateSize.setVisibility(View.GONE);
        } else {
            forceUpdateSize.setText("大小:" + mAppSize + "M");
        }
        //更新日志
        if (TextUtils.isEmpty(mAppDesc)) {
            forceUpdateDescLayout.setVisibility(View.GONE);
        } else {
            forceUpdateDesc.setText(mAppDesc);
            forceUpdateDesc.setMovementMethod(ScrollingMovementMethod.getInstance());
        }
        setNetWorkState();
    }

    /**
     * 设置网络状态
     */
    private void setNetWorkState() {
        if (NetWorkUtil.isWifiConnection(context)) {
            forceUpdateNetworkState.setText("当前为WiFi网络环境,可放心下载.");
            forceUpdateNetworkState.setTextColor(Color.parseColor("#629755"));
        } else if (NetWorkUtil.isMobileConnection(context)) {
            forceUpdateNetworkState.setText("当前为移动网络环境,下载将会消耗流量!");
            forceUpdateNetworkState.setTextColor(Color.parseColor("#BAA029"));
        } else if (!NetWorkUtil.hasNetConnection(context)) {
            forceUpdateNetworkState.setText("当前无网络连接,请打开网络后重试!");
            forceUpdateNetworkState.setTextColor(Color.RED);
        } else {
            forceUpdateNetworkState.setVisibility(View.GONE);
        }
    }

    private void initEvent() {
        exitApp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(isForce){
                    ((Activity) context).finish();
                    System.exit(0);
                }else {
                    dismiss();
                }

            }
        });
        forceUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int permissionStatus = ContextCompat.checkSelfPermission(context, Manifest.permission_group.STORAGE);
                if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.M
                        || Build.VERSION.SDK_INT < Build.VERSION_CODES.M
                        || permissionStatus == PackageManager.PERMISSION_GRANTED) {
                    download();
                } else {
                    if (mCompatFragmentCallback != null) {
                        mCompatFragmentCallback.requestPermissions(new String[]{Manifest.permission.
                                WRITE_EXTERNAL_STORAGE}, UPDATE_DIALOG_PERMISSION_REQUEST_CODE);
                    } else if (mFragmentCallback != null) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            mFragmentCallback.requestPermissions(new String[]{Manifest.permission.
                                    WRITE_EXTERNAL_STORAGE}, UPDATE_DIALOG_PERMISSION_REQUEST_CODE);
                        }
                    } else {
                        ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.
                                WRITE_EXTERNAL_STORAGE}, UPDATE_DIALOG_PERMISSION_REQUEST_CODE);
                    }
                }
            }
        });
    }

    public void download() {
        //防抖动,两次点击间隔小于500ms都return;
        if (System.currentTimeMillis() - timeRange < 500) {
            return;
        }
        timeRange = System.currentTimeMillis();
        setNetWorkState();
        if (!NetWorkUtil.hasNetConnection(context)) {
            Toast.makeText(context, "当前无网络连接", Toast.LENGTH_SHORT).show();
            return;
        }
        if ("点击安装".equals(forceUpdate.getText().toString().trim())) {
            File file = new File(mFilePath, mFileName);
            if (file.exists()) {
                ApplicationUtil.installApk(context, file);
            } else {
                download();
            }
            return;
        }
        forceUpdateProgress.setVisibility(View.VISIBLE);


        HttpRequest.download(mDownloadUrl, mFilePath, mFileName, new DownloadCallback() {
            @Override
            public void onDownloadSuccess(File file) {
                forceUpdate.setEnabled(true);
                exitApp.setEnabled(true);
                forceUpdate.setText("点击安装");
                ApplicationUtil.installApk(context, file);
            }

            @Override
            public void onProgress(long currentProgress, long totalProgress) {
                exitApp.setEnabled(false);
                forceUpdate.setEnabled(false);
                forceUpdate.setText("正在下载");
                forceUpdateProgress.setProgress((int) (currentProgress));
                forceUpdateProgress.setMax((int) (totalProgress));
            }

            @Override
            public void onDownloadFailure(String failureMessage) {
                forceUpdate.setEnabled(true);
                exitApp.setEnabled(true);
                forceUpdate.setText("重新下载");
            }
        });
    }

    private void initView() {
        forceUpdateTitle = (TextView) view.findViewById(R.id.forceUpdateTitle);
        forceUpdateTime = (TextView) view.findViewById(R.id.forceUpdateTime);
        forceUpdateVersion = (TextView) view.findViewById(R.id.forceUpdateVersion);
        forceUpdateSize = (TextView) view.findViewById(R.id.forceUpdateSize);
        forceUpdateDesc = (TextView) view.findViewById(R.id.forceUpdateDesc);
        forceUpdateDescLayout = (LinearLayout) view.findViewById(R.id.forceUpdateDescLayout);
        forceUpdateNetworkState = (TextView) view.findViewById(R.id.forceUpdateNetworkState);
        forceUpdateProgress = (NumberProgressBar) view.findViewById(R.id.forceUpdateProgress);
        exitApp = (Button) view.findViewById(R.id.exitApp);
        forceUpdate = (Button) view.findViewById(R.id.forceUpdate);
    }

    @Override
    public void onBackPressed() {
        //强制更新时,按返回键不隐藏dialog,方法体置空即可
    }

    /**
     * 设置文件下载地址
     */
    public ForceUpdateDialog setDownloadUrl(String downloadUrl) {
        this.mDownloadUrl = downloadUrl;
        return this;
    }

    /**
     * 设置dialog显示标题
     */
    public ForceUpdateDialog setTitle(String title) {
        this.mTitle = title;
        return this;
    }

    /**
     * 设置发布时间
     */
    public ForceUpdateDialog setReleaseTime(String releaseTime) {
        this.mAppTime = releaseTime;
        return this;
    }

    /**
     * 设置版本名,如2.2.1
     */
    public ForceUpdateDialog setVersionName(String versionName) {
        this.mVersionName = versionName;
        return this;
    }

    /**
     * 设置更新日志,需要自己分好段落
     */
    public ForceUpdateDialog setUpdateDesc(String updateDesc) {
        this.mAppDesc = updateDesc;
        return this;
    }

    /**
     * 设置软件大小
     */
    public ForceUpdateDialog setAppSize(float appSize) {
        this.mAppSize = appSize;
        return this;
    }

    /**
     * 设置文件存储路径
     */
    public ForceUpdateDialog setFilePath(String filePath) {
        this.mFilePath = filePath;
        return this;
    }

    /**
     * 设置下载文件名
     */
    public ForceUpdateDialog setFileName(String fileName) {
        this.mFileName = fileName;
        return this;
    }
}

1使用Rxjava2与retrofit2获取更新信息,调用loadUpdate()即可。

代码语言:javascript
复制
 private void loadUpdate(){
        ApiUtils.getTqgApi(ApiUrls.tqgApiUrl)
                .getUpdateInfo()
                .unsubscribeOn(Schedulers.io())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<UpdateBean>() {
                    Disposable d;
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {
                        this.d =d;
                    }

                    @Override
                    public void onNext(@NonNull UpdateBean updateBean) {
                        if (getVersionCode(getApplicationContext())<updateBean.getUpdate_ver_code()) {
                            if(update_switch) {
                                mCheckUpdateInfo = new CheckUpdateInfo();
                                mCheckUpdateInfo.setAppName(updateBean.getUpdate_app_name())
                                        // .setIsForceUpdate(1)//设置是否强制更新,该方法的参数只要和服务端商定好什么数字代表强制更新即可
                                        .setNewAppReleaseTime(updateBean.getUpdate_Time())//软件发布时间
                                        // .setNewAppSize(12.3f)//单位为M
                                        .setNewAppSize(Float.parseFloat(updateBean.getUpdate_app_size()))
                                        .setNewAppUrl(updateBean.getUpdate_url())
                                        .setNewAppVersionCode(updateBean.getUpdate_ver_code())//新app的VersionCode
                                        .setNewAppVersionName(updateBean.getUpdate_ver_name())
                                        .setNewAppUpdateDesc(updateBean.getUpdate_content());
                                forceUpdateDialogClick(updateBean.isIgnore_able());
                            }
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        onComplete();
                    }

                    @Override
                    public void onComplete() {
                        d.dispose();
                    }
                });
    }
代码语言:javascript
复制
    /**
     * setForce(true);
     * 强制更新,checkupdatelibrary中提供的默认强制更新Dialog,您完全可以自定义自己的Dialog,
     */
    public void forceUpdateDialogClick(boolean isForce ) {
        mForceUpdateDialog = new ForceUpdateDialog(MainActivity.this);
        mForceUpdateDialog.setForce(isForce);
        mForceUpdateDialog.setAppSize(mCheckUpdateInfo.getNewAppSize())
                .setDownloadUrl(mCheckUpdateInfo.getNewAppUrl())
                .setTitle(mCheckUpdateInfo.getAppName() + "有更新啦")
                .setReleaseTime(mCheckUpdateInfo.getNewAppReleaseTime())
                .setVersionName(mCheckUpdateInfo.getNewAppVersionName())
                .setUpdateDesc(mCheckUpdateInfo.getNewAppUpdateDesc())
                .setFileName("taoxiang.apk")
                .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/checkupdatelib").show();
    }
代码语言:javascript
复制
    public int getVersionCode(Context context){
        PackageManager packageManager=context.getPackageManager();
        PackageInfo packageInfo;
        int versionCode = 0;
        try {
            packageInfo=packageManager.getPackageInfo(context.getPackageName(),0);
            versionCode=packageInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return versionCode;
    }

服务端Json文件如下

代码语言:javascript
复制
{
    "update_url": "http://taoxiang.hwwwwh.cn/taoxiang.apk",
	"share_text":"\u6dd8\u4eab\u4e0b\u8f7d\u5730\u5740\uff1ahttp://taoxiang.hwwwwh.cn/taoxiang.apk\uff0c\u590d\u5236\u6d4f\u89c8\u5668\u6253\u5f00",
    "update_content": "1,\u65b0\u589e\u5e94\u7528\u8bbe\u7f6e\u754c\u9762\n2,\u5e94\u7528\u5916\u89c2\u7f8e\u5316\n3,\u5e94\u7528\u64cd\u4f5c\u529f\u80fd\u6539\u8fdb\n4,\u4fee\u590d\u82e5\u5e72Bug,\u96c6\u6210\u5e94\u7528\u70ed\u66f4\u65b0",
    "update_ver_code": 2,
    "update_ver_name": "1.0.0",
    "update_Time": "2017-10-01 00: 00",
    "update_app_name": "\u6dd8\u4eab",
    "ignore_able": false,
    "update_app_size": "6.96"
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档