- 浏览: 816091 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
wa19912002:
感谢 tomcat8改成7就好了
jstl的错误总结与解决方法 -
呵呵6666:
不错,谢谢分享!推荐个参考视频内容:http://www.ro ...
浅谈mysql主从复制的高可用解决方案 -
masuweng:
tabindex的微妙使用 -
syxfqw7:
完全正确,补充一下<beans:bean id=&quo ...
SpringSecurity3.1.2控制一个账户同时只能登录一次 -
fireinjava:
longToip直接用ipToLong反过来就好了 publi ...
IP地址与长整数之间的转换详解
1、之前写过一篇说版本升级的,用到广播。感觉乱用,搞的有点复杂,且混乱。现在又用到了版本升级功能,然后梳理下思路,使用回调接口重新写了个。
2、需求同http://aokunsang.iteye.com/blog/1487429,部分源码已上传。
3、增加了点小功能:
1>、可以手动检查升级;
2>、显示升级日志;
3>、修改上篇博客潜在问题:
问题:后台查询到更新,提示更新的AlertDialog只能在启动更新的页面弹出;如果离开此页面,抛异常。
解决:在app的所有页面顶层弹出,参考代码:
//设置dialog dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); //加入权限 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
4、截图如下:
5、上代码(代码才能说明一切):
(1)、DownloadCallback.java
/** * 下载数据接口 * @author: aokunsang * @date: 2012-12-17 */ public interface DownloadCallback { /** * 下载前准备 */ public void onDownloadPreare(); /** * 下载进度更新 * @param progress 进度值 */ public void onChangeProgress(int progress); /** * 下载完成 * @param success 下载成功标示 * @param errorMsg 下载失败显示内容 */ public void onCompleted(boolean success,String errorMsg); /** * 取消下载 */ public boolean onCancel(); }
(2)、DownloadInstall.java
/** * @author: aokunsang * @date: 2012-12-18 */ public class DownloadInstall implements DownloadCallback { private Context mContext; private String apkPath,apkVersion; private int apkCode; private LayoutInflater inflater; private TextView textView; private ProgressBar progressView; private AlertDialog downloadDialog; //下载弹出框 private boolean interceptFlag = false; //是否取消下载 public DownloadInstall(Context mContext,String apkPath,String apkVersion,int apkCode) { this.mContext = mContext; this.apkCode = apkCode; this.apkPath = apkPath; this.apkVersion = apkVersion; inflater = LayoutInflater.from(mContext); } @Override public boolean onCancel() { return interceptFlag; } @Override public void onChangeProgress(int progress) { progressView.setProgress(progress); //设置下载进度 textView.setText("进度:"+progress+"%"); } @Override public void onCompleted(boolean success, String errorMsg) { if(downloadDialog!=null){ downloadDialog.dismiss(); } if(success){ //更新成功 alearyUpdateSuccess(); installApk(); }else{ Toast.makeText(mContext, errorMsg, Toast.LENGTH_SHORT).show(); } } @Override public void onDownloadPreare() { if(IntentUtil.checkSoftStage(mContext)){ File file = new File(Const.apkSavepath); if(!file.exists()){ file.mkdir(); } Builder builder = new AlertDialog.Builder(mContext); builder.setIcon(R.drawable.upgrade).setTitle("正在更新版本"); //---------------------------- 设置在对话框中显示进度条 -------------------- View view = inflater.inflate(R.layout.upgrade_apk, null); textView = (TextView)view.findViewById(R.id.progressCount_text); textView.setText("进度:0"); progressView = (ProgressBar)view.findViewById(R.id.progressbar); builder.setView(view); builder.setNegativeButton("取消", new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); interceptFlag = true; } }); downloadDialog = builder.create(); downloadDialog.show(); } } /** * 升级成功,更新升级日期和版本号,和版本code */ private void alearyUpdateSuccess(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0); sharedPreference.edit().putString(UpdateShared.UPDATE_DATE, sdf.format(new Date())) .putString(UpdateShared.APK_VERSION, apkVersion).putInt(UpdateShared.APK_VERCODE, apkCode).commit(); } /** * 安装apk */ private void installApk(){ File file = new File(apkPath); if(!file.exists()){ return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); mContext.startActivity(intent); } }
(3)、DownloadAsyncTask.java
/** * 异步下载数据 * @author: aokunsang * @date: 2012-12-17 */ public class DownloadAsyncTask extends AsyncTask<String, Integer, String> { private DownloadCallback downCallBack; private HttpURLConnection urlConn; public DownloadAsyncTask(DownloadCallback downloadCallback){ this.downCallBack = downloadCallback; } @Override protected void onPreExecute() { downCallBack.onDownloadPreare(); super.onPreExecute(); } @Override protected String doInBackground(String... args) { String apkDownloadUrl = args[0]; //apk下载地址 String apkPath = args[1]; //apk在sd卡中的安装位置 String result = ""; if(!IntentUtil.checkURL(apkDownloadUrl)){ result = "netfail"; }else{ InputStream is = null; FileOutputStream fos = null; try { URL url = new URL(apkDownloadUrl); urlConn = (HttpURLConnection)url.openConnection(); is = urlConn.getInputStream(); int length = urlConn.getContentLength(); //文件大小 fos = new FileOutputStream(apkPath); int count = 0,numread = 0; byte buf[] = new byte[1024]; while(!downCallBack.onCancel()&& (numread = is.read(buf))!=-1){ count+=numread; int progressCount =(int)(((float)count / length) * 100); publishProgress(progressCount); fos.write(buf, 0, numread); } fos.flush(); result = "success"; } catch (Exception e) { e.printStackTrace(); result = "fail"; }finally{ try { if(fos!=null) fos.close(); if(is!=null) is.close(); } catch (IOException e) { e.printStackTrace(); result = "fail"; } } } return result; } @Override protected void onProgressUpdate(Integer... values) { downCallBack.onChangeProgress(values[0]); super.onProgressUpdate(values); } @Override protected void onPostExecute(String result) { if(downCallBack.onCancel()){ downCallBack.onCompleted(false, "版本更新下载已取消。"); }else if("success".equals(result)){ downCallBack.onCompleted(true, null); }else if("netfail".equals(result)){ downCallBack.onCompleted(false, "连接服务器失败,请稍后重试。"); }else{ downCallBack.onCompleted(false, "版本更新失败,请稍后重试。"); } super.onPostExecute(result); } @Override protected void onCancelled() { if(urlConn!=null){ urlConn.disconnect(); } super.onCancelled(); } }
(4)、DownloadManager.java
/** * 下载管理 * @author: aokunsang * @date: 2012-12-18 */ public class DownloadManager{ private Context mContext; final static int CHECK_FAIL = 0; final static int CHECK_SUCCESS = 1; final static int CHECK_NOUPGRADE = 2; final static int CHECK_NETFAIL = 3; private ApkInfo apkinfo; private AlertDialog noticeDialog; //提示弹出框 private ProgressDialog progressDialog; private boolean isAccord; //是否主动检查软件升级 private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); public DownloadManager(Context mContext,boolean isAccord){ this.mContext = mContext; this.isAccord = isAccord; } Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { if(progressDialog!=null){ progressDialog.dismiss(); } switch(msg.what){ case CHECK_SUCCESS:{ showNoticeDialog(); break; } case CHECK_NOUPGRADE:{ //不需要更新 if(isAccord) Toast.makeText(mContext, "当前版本是最新版。", Toast.LENGTH_SHORT).show(); break; } case CHECK_NETFAIL:{ if(isAccord) Toast.makeText(mContext, "网络连接不正常。", Toast.LENGTH_SHORT).show(); break; } case CHECK_FAIL:{ if(isAccord) Toast.makeText(mContext, "从服务器获取更新数据失败。", Toast.LENGTH_SHORT).show(); break; } } }; }; /* 检查下载更新 [apk下载入口] */ public void checkDownload(){ if(isAccord) progressDialog = ProgressDialog.show(mContext, "", "请稍后,正在检查更新..."); new Thread() { @Override public void run() { if(!IntentUtil.isConnect(mContext)){ //检查网络连接是否正常 handler.sendEmptyMessage(CHECK_NETFAIL); }else if(checkTodayUpdate() || isAccord){//判断今天是否已自动检查过更新 ;如果手动检查更新,直接进入 String result = HttpRequestUtil.getSourceResult(Const.apkCheckUpdateUrl, null, mContext); try { //从服务器下载数据有中文,所以服务器对数据进行了编码;在这里需要解码 result = Escape.unescape(result); JSONObject obj = new JSONObject(result); String apkVersion = obj.getString("apkVersion"); int apkCode = obj.getInt("apkVerCode"); String apkSize = obj.getString("apkSize"); String apkName = obj.getString("apkName"); String downloadUrl = obj.getString("apkDownloadUrl"); String apkLog = obj.getString("apklog"); apkinfo = new ApkInfo(downloadUrl, apkVersion, apkSize, apkCode, apkName, apkLog); if(apkinfo!=null && checkApkVercode()){ //检查版本号 alreayCheckTodayUpdate(); //设置今天已经检查过更新 handler.sendEmptyMessage(CHECK_SUCCESS); }else{ handler.sendEmptyMessage(CHECK_NOUPGRADE); } } catch (Exception e) { e.printStackTrace(); handler.sendEmptyMessage(CHECK_FAIL); } } } }.start(); } /* 弹出软件更新提示对话框*/ private void showNoticeDialog(){ StringBuffer sb = new StringBuffer(); sb.append("版本号:"+apkinfo.getApkVersion()+"\n") .append("文件大小:"+apkinfo.getApkSize()+"\n") .append("更新日志:\n"+apkinfo.getApkLog()); Builder builder = new AlertDialog.Builder(mContext); builder.setIcon(R.drawable.upgrade).setTitle("版本更新").setMessage(sb.toString()); builder.setPositiveButton("下载", new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { String apkPath = Const.apkSavepath + apkinfo.getApkName(); DownloadCallback downCallback = new DownloadInstall(mContext, apkPath, apkinfo.getApkVersion(), apkinfo.getApkCode()); DownloadAsyncTask request = new DownloadAsyncTask(downCallback); request.execute(apkinfo.getDownloadUrl(),apkPath); dialog.dismiss(); } }); builder.setNegativeButton("以后再说", new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); noticeDialog = builder.create(); noticeDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); //设置最顶层Alertdialog noticeDialog.show(); } /** * 根据日期检查是否需要进行软件升级 * @throws Exception */ private boolean checkTodayUpdate() { SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0); String checkDate = sharedPreference.getString(UpdateShared.CHECK_DATE, ""); String updateDate = sharedPreference.getString(UpdateShared.UPDATE_DATE, ""); if("".equals(checkDate) && "".equals(updateDate)){ //刚安装的新版本,设置详细信息 int verCode = IntentUtil.getCurrentVersionCode(mContext); String versionName = IntentUtil.getCurrentVersionName(mContext); String dateStr = sdf.format(new Date()); sharedPreference.edit().putString(UpdateShared.CHECK_DATE, dateStr) .putString(UpdateShared.UPDATE_DATE, dateStr) .putString(UpdateShared.APK_VERSION, versionName) .putInt(UpdateShared.APK_VERCODE, verCode).commit(); return true; } try { //判断defaultMinUpdateDay天内不检查升级 if((new Date().getTime()-sdf.parse(updateDate).getTime())/1000/3600/24<Const.defaultMinUpdateDay){ return false; }else if(checkDate.equalsIgnoreCase(sdf.format(new Date()))){//判断今天是否检查过升级 return false; } } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 设置今天已经检查过升级 * @return */ private void alreayCheckTodayUpdate(){ String date = sdf.format(new Date()); SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0); sharedPreference.edit().putString(UpdateShared.CHECK_DATE, date).commit(); } /** * 检查版本是否需要更新 * @return */ private boolean checkApkVercode(){ SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0); int verCode = sharedPreference.getInt(UpdateShared.APK_VERCODE, 0); if(apkinfo.getApkCode()>verCode){ return true; }else{ return false; } } static interface UpdateShared{ String SETTING_UPDATE_APK_INFO = "cbt_upgrade_setting"; String UPDATE_DATE = "updatedate"; String APK_VERSION = "apkversion"; String APK_VERCODE = "apkvercode"; String CHECK_DATE = "checkdate"; } }
代码内容我不讲解,使用的是回调接口。里面的各种检查是否升级,参考上一篇软件更新博客http://aokunsang.iteye.com/blog/1487429。
(5)、其他操作类:
a、Const.java是一个常量存储类,保存检查更新地址等;
b、Escape.java是个URL解码编码类;
c、HttpRequestUtil.java获取远程数据类;
d、IntentUtil.java工具类,如:检查网络连接状态等。
(以上类参考附件源码)
/** * apk更新信息 * @author: aokunsang * @date: 2012-12-18 */ public class ApkInfo implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String downloadUrl; //下载地址 private String apkVersion; //apk版本 private String apkSize; //apk文件大小 private int apkCode; //apk版本号(更新必备) private String apkName; //apk名字 private String apkLog; //apk更新日志 setter and getter... }
(6)、服务器代码(这里的apklog可以是个txt文档,在UI上下载展示,我做的比较简单):
/** * 获取apk更新信息 * {apkVersion:'1.10',apkSize:'36K',apkVerCode:2,apkName:'1.1.apk',apkDownloadUrl:'http://localhost:8080/myapp/1.1.apk',apklog:'1、修改页面;\n2、修改字体'} */ @Action(value="checkUpdateApk") public String updateApk(){ ResourceLoader loader = new DefaultResourceLoader(); Properties pp = null; try { InputStream is = loader.getResource("classpath:config/sysconf.properties").getInputStream(); pp = new Properties(); pp.load(new InputStreamReader(is, "utf-8")); } catch (Exception e) { e.printStackTrace(); } if(pp!=null){ String apkVersion = pp.getProperty("apkVersion"); String apkDownloadUrl = pp.getProperty("apkDownloadUrl"); String apkName = pp.getProperty("apkName"); int apkVerCode = NumberUtils.toInt(pp.getProperty("apkVerCode"),0); String apklog = pp.getProperty("apkLog"); String apkSize = pp.getProperty("apkSize"); Httptear.ResponseResultByEscape("{apkVersion:'"+apkVersion+"',apkSize:'"+apkSize+"',apkVerCode:"+apkVerCode+",apkName:'"+apkName+"',apkDownloadUrl:'"+apkDownloadUrl+"',apklog:'"+apklog+"'}"); }else{ Httptear.ResponseResultByEscape("{}"); } return NONE; }
6、upgrade_apk.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/progressCount_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="@color/white" android:textSize="14dip" /> <ProgressBar android:id="@+id/progressbar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
7、需要加入以下权限:
<!-- 在SD卡中创建和删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 向SD卡中写入东西权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
8、启动更新检查代码:
/* 升级程序[主动] (因为会弹出一个ProgressDialog窗口,不能使用getApplicationContext())*/ DownloadManager downManger = new DownloadManager(this,true); downManger.checkDownload();
/* 升级程序启动[被动](使用this引用会导致:如在1页面启动升级,当前页面为2页面,此时弹出Dialog抛异常)*/ DownloadManager downManger = new DownloadManager(getApplicationContext(),false); downManger.checkDownload();
评论
这个不科学,重新下载试试。
这是很久以前做android项目时候的blog,现在已不做android很多年。
哦 谢谢
这是很久以前做android项目时候的blog,现在已不做android很多年。
项目工程没法公开,只能根据该文章结合理解实现。如有问题,可发出来共同解决。
亲,你下载下来放项目中不能使用么。 这就好比一个可插拔的控件,放项目中都能用的啊。
发表评论
-
gridview图片展示,长按进入编辑模式
2012-08-31 14:53 14035看到小米手机和其他一些图片显示软件,gridview显示 ... -
Android-ExifInterface如何正确存取Double类型坐标
2012-08-10 15:08 48041、向图片中存储一些属性,可以使用ExifInter ... -
Android软件的自动更新
2012-04-16 12:47 13983今天重新写了一篇 ... -
Android拍照,上传,预览综合【修改】
2011-12-07 14:21 33004最近需要做手机 ... -
百度地图的手动定位和自动定位
2011-07-07 18:45 52514最近由于项目需要,研究了下百度地图定位, ... -
android资源文件详细介绍
2011-07-01 13:45 3599摘自:http://blog.csdn.net/sayyanf ... -
谈Activity的生命周期
2011-07-01 13:42 1820摘自:http://blog.csdn.net/wyh0802 ... -
Android开发调试时logcat不显示问题
2011-07-01 13:40 2251摘自:http://dev.10086.cn/cmdn/wik ... -
AndroidManifest.xml详细介绍
2011-07-01 13:30 1841以下摘自网上,只为记录学习。 一、关于Andro ...
相关推荐
Android API 26,也称为Android Oreo(奥利奥),是Android操作系统的一个重大更新,于2017年发布。这个版本带来了许多新的特性和改进,旨在提升设备性能、电池寿命以及用户体验。在本文中,我们将详细探讨API 26的...
2. **课程教学方法改革**:针对《Android应用程序开发》课程,由于其对实践能力的要求高且技术更新迅速,传统教学方式往往难以满足需求。论文提出改革教学方法,强调培养学生的编程能力、新技术应用能力、解决问题...
5. **通知系统升级**:Android 5.0的通知系统进行了彻底改革,现在可以在锁屏上直接显示,用户可以不用解锁设备就能查看并处理通知。同时,通知还可以根据其重要程度进行优先级排序。 6. **设备加密**:5.0版本默认...
在Android系统的发展历程中,Android 6.0 Marshmallow是一个重要的里程碑,因为它引入了一系列关键的权限管理系统改革。这个更新使得应用程序权限的管理更加细致和灵活,增强了用户对隐私的控制,同时也对开发者提出...
《制造业要素、分类与转型升级策略选择》探讨了制造企业如何通过技术创新实现产业升级,主要围绕自动化、信息化、数字化和智能化这四个关键领域展开。这四个关键词是制造业升级过程中的核心概念,但并非所有企业都...
10. **Android Studio更新**:随着新平台的发布,Android Studio IDE也得到了升级,提供了更好的代码编辑器、性能分析工具以及对Marshmallow特性的支持,帮助开发者更高效地构建和调试应用。 11. **Type-C接口**:...
【基于Android平台的智能用电管理系统的设计】 随着电力体制改革的不断深入和互联网技术的快速发展,智能用电管理系统已经成为电力营销领域的重要趋势。本文主要探讨了如何基于Android平台设计一款智能用电管理系统...
智慧教室系统设计包括硬件系统、应用软件系统和资源平台的整合,遵循统一性、先进性、实用性和稳定性的原则,确保系统的兼容性和扩展性。系统架构以互联网技术为核心,支持多种操作系统终端,如Windows、Android和...
此外,系统还支持iOS和Android版本的同步或异步管理,确保版本升级的平滑进行,并具备二维码共享功能,使得不同平台用户都能方便地下载和使用。 在技术支撑方面,文章提到了原生APP开发的优势,如调用硬件设备(如...
数字迎新系统的设计需要一个核心的技术架构,该架构应支持移动设备访问和操作,兼容各类移动操作系统,如iOS和Android,保证新生可以使用智能手机或平板电脑完成迎新流程。系统应包含多个模块,比如用户注册、资料...