Android(安卓)版本检测更新
16lz
2021-01-26
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() { @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 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版本spice协议tls端口链接方式的bug问题
- 说明Android应用调用全屏方式
- Android中用html代码来实现界面 WebView控件
- Android开发--身高体重指数(BIM)计算--访问标识符号(android:id属性/
- Android设备的界面适配设计
- Android(安卓)Studio实现网络版音乐播放器(简单易上手)
- 【转发】Android(安卓)Metro风格的Launcher开发系列第一篇
- Android(安卓)API Levels 详解
- 探讨一下Android平台的视频类应用开发的技术研究点