Android 检查版本更新 Server后台下载

问题来了,平时开发应用也许你会遇到这种场景:应用启动检查服务器版本,若大于当前版本,则要从网络上下载APK文件,并在Activity上展示进度条。

版本更新,无非是下载apk文件,安装apk。


//其中用到 Xutils

ublic class CheckVersionUtils {
    private static CheckVersionUtils mCheckVersionUtils;

    private CheckVersionUtils() {
    }

    public static CheckVersionUtils getInstance() {
        if (mCheckVersionUtils == null) {
            mCheckVersionUtils = new CheckVersionUtils();
        }
        return mCheckVersionUtils;
    }

    /**
     * 访问网络检查版本号码
     *
     * @param isToastNoVersion 是否弹出"当前版本已为最新版本"的Toast
     * @param activity         弹窗需要的依赖的Activity
     */
    public void checkVersionToServer(final boolean isToastNoVersion, final Activity activity) {
        x.http().get(new RequestParams(ConstantValue.CHECK_VERSION_JSON_URL), new Callback.CommonCallback() {
            @Override
            public void onSuccess(String result) {
                Log.e("CheckVersionActivity", "CheckVersionActivity onSuccess()" + result);
                processData(result, activity, isToastNoVersion);
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {

            }

            @Override
            public void onCancelled(CancelledException cex) {

            }

            @Override
            public void onFinished() {

            }
        });

    }


    /**
     * 返回版本号
     */
    private int getVersionCode() {
        return BuildConfig.VERSION_CODE;
    }


    /**
     * 解析JSON
     *
     * @param json
     * @param isToastNoVersion
     */
    private void processData(String json, Activity activity, boolean isToastNoVersion) {
        Gson gson = new Gson();
        CheckVersionBean checkVersionBean = gson.fromJson(json, CheckVersionBean.class);
        /**
         * 保存在手机的位置
         */
        String saveSDPath = EXB_SD_PATH_APK + checkVersionBean.getFileName();
        //判断是否需要更新
        if (getVersionCode() < checkVersionBean.getVersionCode()) {
            showUpdateDialog(checkVersionBean, saveSDPath, activity);
        } else {
            if (isToastNoVersion) {
                //不更新
                Toast.makeText(activity, "当前版本已为最新版本", Toast.LENGTH_SHORT).show();
            }
        }
    }


    /**
     * 显示更新对话框
     *
     * @param checkVersionBean
     */
    private void showUpdateDialog(final CheckVersionBean checkVersionBean, final String saveSDPath, final Activity activity) {

        //创建文件,判断是否存在
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        AlertDialog alertDialog = builder.create();


        //更新描述信息
        String updateLog = checkVersionBean.getUpdateLog();
        if (TextUtils.isEmpty(updateLog)) {
            updateLog = "新版本,欢迎更新";
        }
        //版本名称
        String versionName = checkVersionBean.getVersionName();
        if (TextUtils.isEmpty(versionName)) {
            versionName = "1.1";
        }

        alertDialog.setTitle("新版本" + versionName);
        alertDialog.setMessage(updateLog);


        //判断是否要强制更新
        if (checkVersionBean.getIsForceUpdate() == 1) {
            //强制更新
            //设置外部点了没有效果
            alertDialog.setCanceledOnTouchOutside(false);
            //禁用返回键
            alertDialog.setCancelable(false);

            alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "更新", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    //更新
                    downloadApk(checkVersionBean.getDownloadUrl(), saveSDPath, activity);
                }
            });

        } else {
            alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                }
            });

            alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "更新", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //更新
                    downloadApk(checkVersionBean.getDownloadUrl(), saveSDPath, activity);
                }
            });
        }

        alertDialog.show();
    }


    /**
     * 下载apk
     *
     * @param downurl
     */
    private void downloadApk(String downurl, String path, final Activity activity) {
        final ProgressDialog progressDialog = new ProgressDialog(activity);
        RequestParams requestParams = new RequestParams(downurl);
        requestParams.setSaveFilePath(path);

        x.http().get(requestParams, new Callback.ProgressCallback() {
            @Override
            public void onWaiting() {
            }
            @Override
            public void onStarted() {
            }
            @Override
            public void onLoading(long total, long current, boolean isDownloading) {
                progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressDialog.setMessage("拼命下载中...");
                progressDialog.show();
                progressDialog.setMax(100);
                double fcurrent = current;
                progressDialog.setProgress((int) ((fcurrent / total) * 100));
            }
            @Override
            public void onSuccess(File result) {
                Toast.makeText(NiceyooApplication.getNiceyooApp(), "下载完成", Toast.LENGTH_SHORT).show();
                progressDialog.dismiss();
                installApk(activity, result);
            }

            @Override
            public void onError(Throwable ex, boolean isOnCallback) {
                ex.printStackTrace();
                Toast.makeText(NiceyooApplication.getNiceyooApp(), "下载失败,请检查网络和SD卡", Toast.LENGTH_SHORT).show();
                progressDialog.dismiss();
            }

            @Override
            public void onCancelled(CancelledException cex) {
            }

            @Override
            public void onFinished() {
            }
        });
    }


    /**
     * 安装对应apk
     *
     * @param activity
     * @param file     安装文件
     */
    private void installApk(Activity activity, File file) {
        //系统应用界面,源码,安装apk入口
        Intent intent = new Intent("android.intent.action.VIEW");
        intent.addCategory("android.intent.category.DEFAULT");
        //设置安装的类型
        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
        activity.startActivityForResult(intent, ConstantValue.INSTALL_NEW_VERSION_SUCCESS);
    }
}

上边代码不是server下载

为什么要用server下载呢?因为有可能 你需要更新的这个Activity要求是可以转屏的。那么在转屏时Actvitiy会重启,如何保证下载的进度条能正确展示进度呢?当然是用server下载了…


public class UpdateService extends Service {

    public UpdateService() {
    }

    /**
     * 安卓系统下载类
     **/
    DownloadManager manager;

    /**
     * 接收下载完的广播
     **/
    DownloadCompleteReceiver receiver;
    /**
     * 初始化下载器
     **/
    private void initDownManager() {
        manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        receiver = new DownloadCompleteReceiver();
        //设置下载地址
        DownloadManager.Request down = new DownloadManager.Request(
                //     百度音乐
                Uri.parse("http://gdown.baidu.com/data/wisegame/fd84b7f6746f0b18/baiduyinyue_4802.apk"));
        //    乐视体育
        // Uri.parse("http://122.228.237.132/apk.r1.market.hiapk.com/data/upload/apkres/2016/6_12/16/com.lesports.glivesports_040405.apk"));
        // 设置允许使用的网络类型,这里是移动网络和wifi都可以
        down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
        // 下载时,通知栏显示途中
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        }
        // 显示下载界面
        down.setVisibleInDownloadsUi(true);
        // 设置下载后文件存放的位置
        down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "leshi.apk");
        // 将下载请求放入队列
        manager.enqueue(down);
        //注册下载广播
        registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        // 调用下载
        initDownManager();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    @Override
    public void onDestroy() {

        // 注销下载广播
        if (receiver != null)
            unregisterReceiver(receiver);

        super.onDestroy();
    }

    // 接受下载完成后的intent
    class DownloadCompleteReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            //判断是否下载完成的广播
            if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
                //获取下载的文件id
                long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
                //自动安装apk
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    Uri uriForDownloadedFile = manager.getUriForDownloadedFile(downId);
                    Log.d("kodulf", "uri=" + uriForDownloadedFile);
                    installApkNew(uriForDownloadedFile);
                }
                //停止服务并关闭广播
                UpdateService.this.stopSelf();
            }
        }

        //安装apk
        protected void installApkNew(Uri uri) {
            Intent intent = new Intent();
            //执行动作
            intent.setAction(Intent.ACTION_VIEW);
            //执行的数据类型
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            //不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃
            // android.os.Process.killProcess(android.os.Process.myPid());
            startActivity(intent);
        }
    }
}

参考:http://blog.csdn.net/rodulf/article/details/51706788#comments


下载demo

你可能感兴趣的:(Android,android)