Android 版本检测更新

Posted 刘永祥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 版本检测更新相关的知识,希望对你有一定的参考价值。

android版本检测更新是每个应用升级所不可少的,以前早就做过一些,一直没有时间与大家分享,现在就跟大家来分享一下我做的版本检测更新吧。先上图
这里写图片描述
点击更新之后的
这里写图片描述
可能有人会问为啥点击更新提示框不消失啊,可以根据自己的情况而定,有的需要强制更新,也是为了方便用户看到下载的进度。我这里只是为了测试一下效果而已。真正的是点击更新以后会在通知栏里面进行显示的 效果就是这样的
这里写图片描述
也有的可能需要在桌面上面展示给用户,下面的效果
这里写图片描述
这些都是是需求而定的。不多说了上代码

package com.liuyongxiang.update.activity;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.json.JSONException;
import org.json.JSONObject;

import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.liuyongxiang.update.R;
import com.liuyongxiang.update.bean.VersionBean;
import com.liuyongxiang.update.utils.MyConstants;
import com.liuyongxiang.update.utils.SpTools;
import com.liuyongxiang.update.view.NumberProgressBar;
import com.liuyongxiang.update.view.OnProgressBarListener;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.PixelFormat;
import android.graphics.pdf.PdfDocument;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class SplashActivity extends Activity implements OnProgressBarListener {

    private static final int LOADMAIN = 1;// 加载主界面
    private static final int SHOWUPDATEDIALOG = 2;// 显示是否更新的对话框
    protected static final int ERROR = 3;// 错误统一代号
    private RelativeLayout rl_root;// 界面的根布局组件
    private int versionCode;// 版本号
    private String versionName;// 版本名
    private TextView tv_versionName;// 显示版本名的组件
    private VersionBean parseJson;// url信息封装bean
    private long startTimeMillis;// 记录开始访问网络的时间
    private NumberProgressBar pb_download;// 下载最新版本apk的进度条
    private Notification.Builder mBuilder;
    private NotificationManager mNotificationManager;
    public static final int NOTIFICATION_ID = 200; // 通知唯一id
    public static final int MUTE = 0; // 0表示静音
    public static final int VIBRATE = 1; // 1表示震动
    public static final int SOUND = 2; // 2表示响音

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化界面
        initView();
        // 初始化数据
        initData();
        //如果正常的从服务器获取应调用下面的timeInitialization(),而showUpdateDialog()只是为了测试查看一下效果
        // timeInitialization();
        showUpdateDialog();
    }

    /**
     * 耗时的功能封装,只要耗时的处理,都放到此方法
     */
    private void timeInitialization() {
        // 一开始动画,就应该干耗时的业务(网络,本地数据初始化,数据的拷贝等)
        if (SpTools.getBoolean(getApplicationContext(), MyConstants.AUTOUPDATE,
                false)) {
            // true 自动更新
            // 检测服务器的版本
            checkVerion();
        }
        // 增加自己的耗时功能处理

    }

    private void initData() {
        // 获取自己的版本信息
        PackageManager pm = getPackageManager();
        try {
            PackageInfo packageInfo = pm.getPackageInfo(getPackageName(), 0);
            // 版本号
            versionCode = packageInfo.versionCode;
            // 版本名
            versionName = packageInfo.versionName;

            // 设置textview
            tv_versionName.setText(versionName);
        } catch (NameNotFoundException e) {
            // can not reach 异常不会发生
        }
    }

    private void checkVerion() {
        // 耗时操作都要放到子线程中执行
        new Thread(new Runnable() {

            @Override
            public void run() {
                BufferedReader bfr = null;
                HttpURLConnection conn = null;
                int errorCode = -1;// 正常,没有错误
                try {
                    startTimeMillis = System.currentTimeMillis();

                    URL url = new URL("http://10.0.2.2:8080/guardversion.json");

                    conn = (HttpURLConnection) url.openConnection();
                    // 读取数据的超时时间
                    conn.setReadTimeout(5000);
                    // 网络连接超时
                    conn.setConnectTimeout(5000);
                    // 设置请求方式
                    // 获取相应结果
                    int code = conn.getResponseCode();

                    if (code == 200) {// 数据获取成功
                        // 获取读取的字节流
                        InputStream is = conn.getInputStream();
                        // 把字节流转换成字符流
                        bfr = new BufferedReader(new InputStreamReader(is));
                        // 读取一行信息
                        String line = bfr.readLine();
                        // json字符串数据的封装
                        StringBuilder json = new StringBuilder();
                        while (line != null) {
                            json.append(line);
                            line = bfr.readLine();
                        }
                        parseJson = parseJson(json);// 返回数据封装信息

                    } else {
                        errorCode = 404;
                    }
                } catch (MalformedURLException e) {// 4002
                    errorCode = 4002;
                    e.printStackTrace();
                } catch (IOException e) {// 4001
                    errorCode = 4001;
                    e.printStackTrace();
                } catch (JSONException e) {
                    errorCode = 4003;
                    e.printStackTrace();
                } finally {
                    Message msg = Message.obtain();
                    if (errorCode == -1) {
                        msg.what = isNewVersion(parseJson);// 检测是否有新版本
                    } else {
                        msg.what = ERROR;
                        msg.arg1 = errorCode;
                    }
                    long endTime = System.currentTimeMillis();
                    if (endTime - startTimeMillis < 3000) {
                        SystemClock.sleep(3000 - (endTime - startTimeMillis));// 时间不超过3秒,补足3秒
                    }
                    handler.sendMessage(msg);// 发送消息
                    try {
                        // 关闭连接资源
                        if (bfr != null) {
                            bfr.close();
                        }
                        if (conn != null) {
                            conn.disconnect();
                        }
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            }
        }).start();
    }

    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            // 处理消息
            switch (msg.what) {
            case LOADMAIN:// 加载主界面
                loadMain();
                break;
            case ERROR:// 有异常
                switch (msg.arg1) {
                case 404:// 资源找不到
                    Toast.makeText(getApplicationContext(), "404资源找不到", 0)
                            .show();
                    break;
                case 4001:// 找不到网络
                    Toast.makeText(getApplicationContext(), "4001没有网络", 0)
                            .show();
                    break;
                case 4003:// json格式错误
                    Toast.makeText(getApplicationContext(), "4003json格式错误", 0)
                            .show();
                    break;
                default:
                    break;
                }
                loadMain();// 进入主界面
                break;
            case SHOWUPDATEDIALOG:// 显示更新版本的对话框
                showUpdateDialog();
                break;
            default:
                break;
            }
        }
    };
    private AlertDialog dialog;

    private void loadMain() {
        Intent intent = new Intent(SplashActivity.this, MainActivity.class);
        startActivity(intent);// 进入主界面
        finish();// 关闭自己
    };


    protected int isNewVersion(VersionBean parseJson) {
        // 获取服务器设置的版本
        // int serverCode = parseJson.getVersionCode();
        int serverCode = 2;// 获取服务器的版本
        System.out.println("serverCode----->" + serverCode);
        if (serverCode == versionCode) {
            // 如果版本一致直接进入到主界面
            return LOADMAIN;
            /*
             * 进入主界面 Message msg = Message.obtain(); msg.what = LOADMAIN;
             */
        } else {
            // 否则会弹出提示更新的提示框
            return SHOWUPDATEDIALOG;
        }
    }

    /**
     * 显示是否更新新版本的对话框
     */
    public void showUpdateDialog() {
        dialog = new AlertDialog.Builder(this).create();
        dialog.setCancelable(false);
        dialog.show();
        Window window = dialog.getWindow();
        window.setContentView(R.layout.prompt_alertdialog);
        LinearLayout ll_title = (LinearLayout) window
                .findViewById(R.id.ll_title);
        ll_title.setVisibility(View.VISIBLE);
        TextView tv_title = (TextView) window.findViewById(R.id.tv_title);
        pb_download = (NumberProgressBar) window
                .findViewById(R.id.pb_splash_download);
        pb_download.setVisibility(View.GONE);// 隐藏进度条
        pb_download.setOnProgressBarListener(this);
        tv_title.setText("版本更新");
        TextView tv_content = (TextView) window.findViewById(R.id.tv_content);
        tv_content.setMovementMethod(new ScrollingMovementMethod());
        tv_content
                .setText("是否更新新版本?新版本的具有如下特性:1.是否更新新版本?新版本的具有如下特性 2.是否更新新版本?新版本的具有如下特性 3.是否更新新版本?新版本的具有如下特性 4.是否更新新版本?新版本的具有如下特性 5.是否更新新版本?新版本的具有如下特性 6.是否更新新版本?新版本的具有如下特性 7.是否更新新版本?新版本的具有如下特性 8.是否更新新版本?新版本的具有如下特性");
        final TextView tv_sure = (TextView) window.findViewById(R.id.tv_sure);
        final TextView tv_cancle = (TextView) window
                .findViewById(R.id.tv_cancle);
        tv_cancle.setText("取消");
        tv_cancle.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                loadMain();
                dialog.cancel();
            }
        });
        tv_sure.setText("更新");
        tv_sure.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                downLoadNewApk();// 下载新版本
                createFloatView();
                tv_cancle.setEnabled(false);
                tv_sure.setEnabled(false);
                dialog.cancel();
                loadMain();
                pb_download.setVisibility(View.VISIBLE);
            }
        });

    }

    /**
     * 新版本的下载安装
     */
    protected void downLoadNewApk() {
        HttpUtils utils = new HttpUtils();
        // parseJson.getUrl() 下载的url
        // target 本地路径
        // System.out.println(parseJson.getUrl());
        File file = new File("/mnt/sdcard/测试.apk");
        //如果此文件已存在先删除
        file.delete();// 删除文件

        utils.download(
                "http://www.gamept.cn/d/file/game/qipai/20140627/HappyLordZZ_1.0.19_20140325_300002877528_2200139763.apk",
                "/mnt/sdcard/测试.apk", new RequestCallBack<File>() {

                    @Override
                    public void onLoading(final long total, final long current,
                            boolean isUploading) {
                        pb_download.setVisibility(View.VISIBLE);// 设置进度的显示
                        int max = (int) total;
                        int progress = (int) current;
                        pb_download.setMax(max);// 设置进度条的最大值
                        pb_download.setProgress(progress);// 设置当前进度
                        pb_download2.setMax(max);
                        pb_download2.setProgress(progress);
                        // showNotification(max,progree);

                        showNotifi(max, progress);
                        super.onLoading(total, current, isUploading);
                    }

                    @Override
                    public void onSuccess(ResponseInfo<File> arg0) {
                        // 下载成功
                        // 在主线程中执行
                        Toast.makeText(getApplicationContext(), "下载新版本成功", 1)
                                .show();
                        // 安装apk
                        installApk();// 安装apk
                        pb_download.setVisibility(View.GONE);// 隐藏进度条
                        rl_notification.setVisibility(View.GONE);
                    }

                    @Override
                    public void onFailure(HttpException arg0, String arg1) {
                        // 下载失败
                        Toast.makeText(getApplicationContext(), "下载新版本失败", 1)
                                .show();
                        pb_download.setVisibility(View.GONE);// 隐藏进度条
                    }
                });
    }

    private NumberProgressBar pb_download2;
    private RelativeLayout rl_notification;

    /**
     * 安装下载的新版本
     */
    protected void installApk() {
        Intent intent = new Intent("android.intent.action.VIEW");
        intent.addCategory("android.intent.category.DEFAULT");
        String type = "application/vnd.android.package-archive";
        Uri data = Uri.fromFile(new File("/mnt/sdcard/测试.apk"));
        intent.setDataAndType(data, type);
        startActivityForResult(intent, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // 如果用户取消更新apk,那么直接进入主界面
        loadMain();
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * @param jsonString
     *            url的json数据
     * @return url信息封装对象
     * @throws JSONException
     */
    protected VersionBean parseJson(StringBuilder jsonString)
            throws JSONException {
        VersionBean bean = new VersionBean();
        JSONObject jsonObj;
        jsonObj = new JSONObject(jsonString + "");
        int versionCode = jsonObj.getInt("version");
        String url = jsonObj.getString("url");
        String desc = jsonObj.getString("desc");
        // 封装结果数据
        bean.setDesc(desc);
        bean.setUrl(url);
        bean.setVersionCode(versionCode);
        return bean;
    }

    /**
     * 初始化界面
     */
    private void initView() {
        setContentView(R.layout.activity_main);
        rl_root = (RelativeLayout) findViewById(R.id.rl_splash_root);
        tv_versionName = (TextView) findViewById(R.id.tv_splash_version_name);
    }

    @Override
    public void onProgressChange(int current, int max) {
        pb_download.setProgress(current);
        pb_download2.setProgress(current);
    }

    private void createFloatView() {
        final WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
        getApplication();
        final WindowManager mWindowManager = (WindowManager) getApplication()
                .getSystemService(Context.WINDOW_SERVICE);
        wmParams.type = LayoutParams.TYPE_PHONE;
        wmParams.format = PixelFormat.RGBA_8888;
        wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
        wmParams.gravity = Gravity.LEFT | Gravity.TOP;
        wmParams.x = 0;
        wmParams.y = 0;
        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        LayoutInflater inflater = LayoutInflater.from(getApplication());
        final View mFloatLayout = inflater.inflate(
                R.layout.activity_notification, null);
        mWindowManager.addView(mFloatLayout, wmParams);
        rl_notification = (RelativeLayout) mFloatLayout
                .findViewById(R.id.rl_notification);
        pb_download2 = (NumberProgressBar) mFloatLayout
                .findViewById(R.id.pb_download);
        // TextView tv_name = (TextView)
        // mFloatLayout.findViewById(R.id.tv_name);
        // TextView tv_time = (TextView)
        // mFloatLayout.findViewById(R.id.tv_time);
        // ImageView iv_icon = (ImageView)
        // mFloatLayout.findViewById(R.id.iv_icon);// 系统显示的通知图片
        mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
                .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

        rl_notification.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                wmParams.x = (int) event.getRawX()
                        - rl_notification.getMeasuredWidth() / 2;
                wmParams.y = (int) event.getRawY()
                        - rl_notification.getMeasuredHeight() / 2 - 25;
                mWindowManager.updateViewLayout(mFloatLayout, wmParams);
                return false;
            }
        });
    }

    private void showNotification(final int total, final int current) {
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mBuilder = new Notification.Builder(SplashActivity.this);
        LayoutInflater inflater = LayoutInflater.from(getApplication());
        View view = inflater.inflate(R.layout.activity_notification, null);
        mBuilder.setContentTitle("这是测试").setContentText("下载中...")
                .setSmallIcon(R.drawable.app_icon);
        new Thread(new Runnable() {

            @SuppressLint("NewApi")
            @Override
            public void run() {
                mBuilder.setProgress(total, current, false);
                mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
                if (current / total == 1) {
                    mNotificationManager.cancel(0);
                }
            }
        }).start();
    }

    private void showNotifi(final int total, final int current) {
        NotificationManager notiManage;
        Notification note;
        mBuilder = new Notification.Builder(SplashActivity.this);
        notiManage = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        note = new Notification();
        note.flags = Notification.FLAG_AUTO_CANCEL;
        RemoteViews contentView = new RemoteViews(getPackageName(),
                R.layout.activity_notifi);

        contentView.setTextViewText(R.id.notificationTitle, "这是测试");
        String str_progress =current*100/total+"%"; 
        contentView.setTextViewText(R.id.notificationPercent, str_progress);

        contentView.setProgressBar(R.id.notificationProgress, total, current,
                false);
        note.contentView = contentView;
        note.tickerText = "正在下载";
        note.icon = R.drawable.app_icon;

        PendingIntent p = PendingIntent.getActivity(SplashActivity.this, 0,
                new Intent(Intent.ACTION_VIEW), 0);// 这个非要不可。
        note.contentIntent = p;
        notiManage.notify(NOTIFICATION_ID, note);
        if (current / total == 1) {
            notiManage.cancelAll();
        }
    }
}

这只是一些简单的代码,如果想测试一下具体效果
点击免费下载源码
如果有问题请加Android交流群 470707794或留言

以上是关于Android 版本检测更新的主要内容,如果未能解决你的问题,请参考以下文章

Android 版本检测更新

android 实现检测版本,下载apk更新(附源码)

[android] 手机卫士欢迎页检测更新

Android应用更新-自动检测版本及自动升级

Android Studio 无法检测到更新

Android Place自动填充片段:无法设置文字