Android应用检查更新总结

每一个应用在进入主界面之间应该有一个界面用来显示公司或者团队的信息,介绍软件,并检查更新,及时提醒用户更新最新版本,获得更多更好的用户体验。本文将对该实现进行总结,以后用到就不要到处找自己写的项目了。

习惯上我们把实现该功能的类定义为splashActivity。

进入该界面就应该初始化一些数据,比如复制文件到系统目录,复制打包的数据库到系统目录,检查软件版本是否进行更新等。

1、复制文件到系统目录已经写成工具类,所以只要获得文件的源地址和目标地址即可完成复制。如下在android平台下 获取SD卡的文件目录代码如下:

/**
	 * 获得文件路径和状态信息
	 *
	 * @return
	 */
	private List<MyFileInfo> getFiles() {
		File path = null;
		List<MyFileInfo> infos = new ArrayList<MyFileInfo>();

		MyFileInfo info = null;
		// 判断SD卡是否存在可用
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			path = Environment.getExternalStorageDirectory();

			File[] files = path.listFiles();
			for (File file : files) {
				// 把路径如入集合中

				if (file.getPath() != null) {
					info = new MyFileInfo();
					info.setPath(file.getPath());
					infos.add(info);
					info = null;
				}

			}
		} else {

			Toast.makeText(FileSearchActivity.this, "SD卡不可用!", 300).show();
		}

		return infos;

	}

复制文件方法:

/**
	 * @warning The name of file must be end with .xls
	 * @param res The resource file
	 * @param des The destination
	 * @return
	 * @throws FileNotFoundException
	 */
	public static boolean toCopy(String res,String des){
		boolean flag=false;

		//输入源文件
		File file = new File(res) ;
		FileInputStream fr=null;
		//复制目标文件
		File desFile = new File(des);
		FileOutputStream bw=null;
		try {
			fr = new FileInputStream(file);
			bw = new FileOutputStream(desFile);

			//buffer
			byte[] b = new byte[512];
			while(fr.read(b)!=-1){
				bw.write(b);
			}
			bw.flush();
			flag=true;
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if(fr != null)
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

获取android应用系统目录的方法:

File file = new File(getFilesDir(), "xxx.xls");即在android里面data/data/包名/files目录下。
通过以上方法即可完成将SD卡的文件复制到应用系统目录中。

2、复制数据库到系统目录
<p>(1)获得系统文件目录:</p><p><span style="color:rgb(127, 0, 85);">final</span> File file = <span style="color:rgb(127, 0, 85);">new</span> File(getFilesDir(), <span style="color:rgb(42, 0, 255);">"xxx.db"</span>);</p><p>(2)获得位于资产目录的文件的输入流</p><p>InputStream is = getAssets().open(<span style="color:rgb(42, 0, 255);">"xxx.db"</span>);</p><p>getResources()</p><p>*<span style="font-family:宋体;">读取文件资源:</span><span style="font-family:Times New Roman;">1.</span><span style="font-family:宋体;">读取</span><span style="font-family:Times New Roman;">res/raw</span><span style="font-family:宋体;">下的文件资源,通过以下方式获取输入流来进行写操作</span>
·        <span style="font-family:Times New Roman;">InputStream is =getResources().openRawResource(R.id.filename); </span>
2.<span style="font-family:宋体;">读取</span><span style="font-family:Times New Roman;">assets</span><span style="font-family:宋体;">下的文件资源,通过以下方式获取输入流来进行写操作</span>
·        <span style="font-family:Times New Roman;">AssetManager am = null; </span>
·        <span style="font-family:Times New Roman;">am = getAssets(); </span>
·        <span style="font-family:Times New Roman;">InputStream is = am.open("filename"); </span></p><p> </p><p> </p><p>2<span style="font-family:宋体;">、读取拷贝到系统的数据库,并获得数据库引用。然后就可以操作数据库了。</span></p><p>SQLiteDatabase db = SQLiteDatabase.openDatabase(<span style="color:rgb(0,0,192);">path</span>, <span style="color:rgb(127,0,85);">null</span>,</p><p>				SQLiteDatabase.<span style="color:rgb(0,0,192);">OPEN_READONLY</span>);</p><p> </p><p><span style="background:rgb(255,255,0);">注:拷贝到系统的数据库文件的路径为:</span><span style="color:rgb(127, 0, 85);">public</span> <span style="color:rgb(127, 0, 85);">static</span> <span style="color:rgb(127, 0, 85);">final</span> String <span style="color:rgb(0, 0, 192);">path</span> = <span style="color:rgb(42, 0, 255);">"/data/data/</span><span style="color:rgb(42, 0, 255);">应用包名</span><span style="color:rgb(42, 0, 255);">/files/</span><span style="color:rgb(42, 0, 255);">数据库文件</span><span style="color:rgb(42, 0, 255);">"</span>;</p><p>自己建立的数据库是databases<span style="font-family:宋体;">文件夹下。</span></p><p> </p>
工具类如下:
<pre name="code" class="java">public class CopyFileToSystem {

	public CopyFileToSystem() {
		// TODO Auto-generated constructor stub
	}
	/**
	 * 把文件拷贝到系统文件夹
	 * @param in
	 * @param destPath
	 */
	public static void copyFile(InputStream in,String destPath){
		//目标文件
		File file=new File(destPath);
		FileOutputStream fos=null;
		try {
			fos=new FileOutputStream(file);
			int len=0;
			byte[] buffer=new byte[1024];
			while((len=in.read(buffer))!=-1){
				fos.write(buffer,0,len);

			}
			fos.flush();
			fos.close();
			in.close();

		} catch (Exception e) {

		}

	}

}

3、检查更新
(1)首先获得应用的版本号
<pre name="code" class="java">/**
	 * 获得应用的版本信息
	 * @return 应用的版本号
	 */
	private String getAppVersion(){
		PackageManager pm=getPackageManager();
		PackageInfo info=null;
		try {
			info=pm.getPackageInfo(getPackageName(),0);
			if(info!=null){
				 return info.versionName;
			}
		} catch (NameNotFoundException e) {

			e.printStackTrace();

		}
		return "";
	}

(2)同时连接网络解析服务器的配置文件获得应用最新的版本号,如下:


<span style="white-space:pre">	</span>1)服务器端的xml文件如下
<?xml version="1.0" encoding="utf-8"?>
<info>
<version>2.0</version>
<description>空降新版本,请下载,体验更多新特性!!!</description>
<apkurl>http://192.168.253.1:8080/TouristManager.apk</apkurl>
</info>
<span style="white-space:pre">	</span>2)连接服务器获得输入流解析xml文件
<span style="white-space:pre">	</span><pre name="code" class="java">public class UpdateInfoParser {

	/**
	 * 解析服务器返回的更新信息
	 * @param is 服务器返回的流
	 * @return 如果发生异常 返回null;
	 */
	public static UpdateInfo getUpdateInfo(InputStream is) {
		try {
			XmlPullParser parser = Xml.newPullParser();
			parser.setInput(is, "utf-8");
			int type = parser.getEventType();
			UpdateInfo info = null;
			while(type!=XmlPullParser.END_DOCUMENT){
				switch (type) {
				case XmlPullParser.START_TAG:
					if("info".equals(parser.getName())){
						info = new UpdateInfo();
					}else if("version".equals(parser.getName())){
						info.setVersion(parser.nextText());
					}else if("description".equals(parser.getName())){
						info.setDescription(parser.nextText());
					}else if("apkurl".equals(parser.getName())){
						info.setApkurl(parser.nextText());
					}
					break;
				}
				type = parser.next();
			}
			return info;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

}
整个splash源代码如下:
<pre name="code" class="html">package com.example.ehrmanager;

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

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
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.content.res.Resources.NotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.animation.AlphaAnimation;
import android.widget.TextView;
import android.widget.Toast;

import com.example.ehrmanager.domain.UpdateInfo;
import com.example.ehrmanager.utils.DownLoadUtil;
import com.example.ehrmanager.utils.UpdateInfoParser;

public class SplashActivity extends Activity {
	private TextView mTVversion;//显示应用的版本
	private String mVersion;//应用的版本
	public static final int PARSE_XML_ERROR = 10;
	public static final int PARSE_XML_SUCCESS = 11;
	public static final int SERVER_ERROR = 12;
	public static final int URL_ERROR = 13;
	public static final int NETWORK_ERROR = 14;
	private static final int DOWNLOAD_SUCCESS = 15;
	private static final int DOWNLOAD_ERROR = 16;
	protected static final String TAG = "SplashActivity";
	private static final int COPYDATA_ERROR = 17;
	private UpdateInfo updateInfo;

	private ProgressDialog pd;// 下载进度的对话框

	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case PARSE_XML_ERROR:
				Toast.makeText(getApplicationContext(), "解析xml失败", 0).show();
				// 进入程序主界面
				loadMainUI();
				break;
			case SERVER_ERROR:
				Toast.makeText(getApplicationContext(), "服务器异常", 0).show();
				// 进入程序主界面
				loadMainUI();
				break;
			case URL_ERROR:
				Toast.makeText(getApplicationContext(), "服务器地址异常", 0).show();
				// 进入程序主界面
				loadMainUI();
				break;
			case NETWORK_ERROR:
				Toast.makeText(getApplicationContext(), "网络异常", 0).show();
				// 进入程序主界面
				loadMainUI();
				break;
			case PARSE_XML_SUCCESS:
				if (getAppVersion().equals(updateInfo.getVersion())) {
					// 进入程序主界面
					Log.i(TAG, "版本号相同,进入主界面");
					loadMainUI();
				} else {
					Log.i(TAG, "版本号不相同,弹出来升级提示对话框");
					showUpdateDialog();
				}
				break;
			case DOWNLOAD_ERROR:
				Toast.makeText(getApplicationContext(), "下载失败", 0).show();
				// 进入程序主界面
				loadMainUI();
				break;
			case DOWNLOAD_SUCCESS:
				File file = (File) msg.obj;
				Log.i(TAG, "安装apk" + file.getAbsolutePath());
				// 安装apk
				installApk(file);
				finish();
				break;
			case COPYDATA_ERROR:
				Toast.makeText(getApplicationContext(), "加载数据库失败", 0).show();
				break;
			}
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		intiViews();

	}

	/**
	 * 初始化组件
	 */
	private void intiViews() {
		setContentView(R.layout.activity_splash);
		mTVversion=(TextView)this.findViewById(R.id.app_version);
		mVersion=getAppVersion();//获得应用的版本
		mTVversion.setText(mVersion);
		// 连接服务器 检查版本更新.
				new Thread(new CheckVersionTask()).start();

				AlphaAnimation aa = new AlphaAnimation(0.2f, 1.0f);
				aa.setDuration(2000);
				findViewById(R.id.rl_splash).startAnimation(aa);

	}
	/**
	 * 获得应用的版本信息
	 * @return 应用的版本号
	 */
	private String getAppVersion(){
		PackageManager pm=getPackageManager();
		PackageInfo info=null;
		try {
			info=pm.getPackageInfo(getPackageName(),0);
			if(info!=null){
				 return info.versionName;
			}
		} catch (NameNotFoundException e) {

			e.printStackTrace();

		}
		return "";
	}
	/**
	 * 进入主界面
	 */
	private void  loadMainUI(){
		Intent intent=new Intent(SplashActivity.this,HomeActivity.class);
		startActivity(intent);
		this.finish();

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.splash, menu);
		return true;
	}

	/**
	 * 自动升级的提示对话框
	 */
	protected void showUpdateDialog() {

		AlertDialog.Builder builder = new Builder(this);
		builder.setTitle("升级提醒");
		builder.setMessage(updateInfo.getDescription());
		builder.setPositiveButton("确定", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				String apkurl = updateInfo.getApkurl();
				pd = new ProgressDialog(SplashActivity.this);
				pd.setTitle("升级操作");
				pd.setMessage("正在下载...");
				pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
				pd.show();
				Log.i(TAG, "下载后安装:" + apkurl);
				final File file = new File(Environment
						.getExternalStorageDirectory(), DownLoadUtil
						.getFileName(apkurl));
				// 判断sd卡是否可用,只有可用状态.
				if (Environment.getExternalStorageState().equals(
						Environment.MEDIA_MOUNTED)) {
					new Thread() {
						public void run() {
							File savedFile = DownLoadUtil.download(
									updateInfo.getApkurl(),
									file.getAbsolutePath(), pd);
							Message msg = Message.obtain();
							if (savedFile != null) {
								// 下载成功
								msg.what = DOWNLOAD_SUCCESS;
								msg.obj = savedFile;
							} else {
								// 下载失败
								msg.what = DOWNLOAD_ERROR;

							}
							handler.sendMessage(msg);
							pd.dismiss();
						};
					}.start();
				} else {
					Toast.makeText(getApplicationContext(), "sd卡不可用", 0).show();
					loadMainUI();
				}

			}
		});
		builder.setNegativeButton("取消", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				loadMainUI();
			}
		});
		builder.create().show();

		// builder.show();
	}

	private class CheckVersionTask implements Runnable {
		@Override
		public void run() {
			SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
			boolean isupdate = sp.getBoolean("update", true);
			if (!isupdate) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				loadMainUI();
				return;
			}
			long startTime = System.currentTimeMillis();
			Message msg = Message.obtain();
			try {
				URL url = new URL(getResources().getString(R.string.serverurl));
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setRequestMethod("GET");
				conn.setConnectTimeout(1500);
				int code = conn.getResponseCode();
				if (code == 200) {
					InputStream is = conn.getInputStream();
					updateInfo = UpdateInfoParser.getUpdateInfo(is);
					if (updateInfo == null) {
						// TODO:解析xml失败
						msg.what = PARSE_XML_ERROR;
					} else {
						// 解析成功
						msg.what = PARSE_XML_SUCCESS;
					}
				} else {
					// TODO:服务器内部错误.
					msg.what = SERVER_ERROR;
				}
			} catch (MalformedURLException e) {
				msg.what = URL_ERROR; // http://
				e.printStackTrace();
			} catch (NotFoundException e) {
				msg.what = URL_ERROR; //
				e.printStackTrace();
			} catch (IOException e) {
				msg.what = NETWORK_ERROR;
				e.printStackTrace();
			} finally {
				long endTime = System.currentTimeMillis();
				long dTime = endTime - startTime;
				if (dTime < 2000) {
					try {
						Thread.sleep(2000 - dTime);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				handler.sendMessage(msg);
			}

		}
	}

	/**
	 * 安装一个apk文件
	 *
	 * @param file
	 */
	protected void installApk(File file) {

		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		intent.addCategory("android.intent.category.DEFAULT");
		intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
		startActivity(intent);
	}

}

工具类源代码:
下载新版APK
<pre name="code" class="java">package com.example.ehrmanager.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.ProgressDialog;

public class DownLoadUtil {

	/**
	 * 下载文件操作
	 *
	 * @param serverPath
	 *            服务器文件的路径
	 * @param savedPath
	 *            本地保存的路径
	 * @param pd 进度条对话框
	 * @return 下载成功 返回文件对象 下载失败 返回null
	 */
	public static File download(String serverPath, String savedPath, ProgressDialog pd) {
		try {
			URL url = new URL(serverPath);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setRequestMethod("GET");
			int code = conn.getResponseCode();
			if (code == 200) {
				pd.setMax(conn.getContentLength());
				InputStream is = conn.getInputStream();
				File file = new File(savedPath);
				FileOutputStream fos = new FileOutputStream(file);
				byte[] buffer = new byte[1024];
				int len = 0;
				int total = 0;
				while ((len = is.read(buffer)) != -1) {
					fos.write(buffer, 0, len);
					total +=len;
					pd.setProgress(total);
					Thread.sleep(20);
				}
				fos.flush();
				fos.close();
				is.close();
				return file;
			} else {
				return null;
			}

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 获取服务器文件的名称
	 * @param serverPath
	 * @return
	 */
	public static String getFileName(String serverPath){
		return serverPath.substring(serverPath.lastIndexOf("/")+1);
	}
}







				
时间: 2024-10-10 21:46:11

Android应用检查更新总结的相关文章

Android 应用检查更新并下载

1.在Android应用当中都有应用检查更新的要求,往往都是在打开应用的时候去更新下载. 实现的方法是:服务器端提供接口,接口中可以包含在最新APK下载的URL,最新APK的VersionCode,等附带信息. 将最新APK的Versioncode与当前的APP的VersionCode做大小比较就可以知道是否是最新版本,如果是最新版本就下载安装. 2.效果图:                   4.上代码: 借用别人的接口:http://jcodecraeer.com/update.php A

Android设置选项开发及自定义Preference样式

一个完整的Android应用程序都应该提供选项(或者叫偏好设置等等)让用户对APP的表现形式能够进行设置,比如说是否加入用户体验计划,或者是否自动升级.定时提醒.开启自启动.后台运行等等.提供一个好的设置项,会大大提升APP的用户体验.为了完成这样的功能,你不必从头开始写Activity或者Fragment,因为Android已经提供了实现这个功能的API,并且会自动将用户设置以键值对的形式存入SharedPreference(Android的四大存储方式之一)中.在3.0以前的系统,使用Pre

Android应用开发-小巫CSDN博客客户端UI篇

Android应用开发-小巫CSDN博客客户端UI篇 上一篇是给童鞋们介绍整个项目的概况,从这篇博文开始,后续也会详细介绍整个客户端的开发,但不会贴很多代码,我会贴核心代码然后提供实现思路,想看里面更详细的代码的可以到我的资源页下载源码进行查看,之前上传到github的少了些jar包,所以我在csdn下载频道也上传了一份,地址:http://download.csdn.net/detail/wwj_748/7912513. 整个客户端的开始,自然是需要搭建一个承载我们数据的框架,我这里所说的是U

仿百度壁纸client(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化

仿百度壁纸client(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸client(一)--主框架搭建,自己定义Tab + ViewPager + Fragment 仿百度壁纸client(二)--主页自己定义ViewPager广告定时轮播图 仿百度壁纸client(三)--首页单向,双向事件冲突处理,壁纸列表的实现 仿百度壁纸client(四)--自己定义上拉载入实现精选壁纸墙 仿百度壁纸client(五)--实现搜索动画GestureDetector

仿百度壁纸客户端(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化

仿百度壁纸客户端(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 仿百度壁纸客户端(三)--首页单向,双向事件冲突处理,壁纸列表的实现 仿百度壁纸客户端(四)--自定义上拉加载实现精选壁纸墙 仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 仿百度壁纸客

Android启动页面实现版本检查更新

1.引入模块 CheckUpdateLibrary的github地址如下: https://github.com/qiangxi/CheckUpdateLibrary 打包下载,复制该文件下的两个文件夹到项目的extras文件夹下, 项目setting.gradle里面加入这两个模块. include ':app', ':extras:okhttputils', ':extras:FlycoTabLayout_Lib', ':extras:ViewPagerIndicator_library',

android使用友盟实现第三方登录、分享以及微信回调无反应问题解决办法

        Leaning_wk每一次的进步都会拉近与成功的距离! 帐号设置退出   关闭 qq_15855289的博客 目录视图 摘要视图 订阅 异步赠书:Kotlin领衔10本好书      免费直播:AI时代,机器学习如何入门?      程序员8月书讯      每周荐书:Java Web.Python极客编程(评论送书) android使用友盟实现第三方登录.分享以及微信回调无反应问题解决办法 标签: android友盟第三方登录分享微信登录回调问题 2017-02-10 16:2

Android实现App版本自动更新

现在很多的App中都会有一个检查版本的功能.例如斗鱼TV App的设置界面下: 当我们点击检查更新的时候,就会向服务器发起版本检测的请求.一般的处理方式是:服务器返回的App版本与当前手机安装的版本号进行对比. (1)如果服务器所返回的版本号大于当前App版本号那么此时手机所安装的App不是最新版.可以提示用户升级. (2)如果不大于当前版本号,可以提示用户为最新版本: 版本升级,也分为两种处理方式: (1)跳转到App某市场(例如:360手机助手),然后根据包名在市场定位到该App,通过市场下

优秀的 Android 开源项目

摘要  转载http://www.trinea.cn/android/android-open-source-projects-view/,方便大家找到自己合适的资料 目录[-] 一.ListView 二.ActionBar 三.Menu 四.ViewPager .Gallery 五.GridView 六.ImageView 七.ProgressBar 八.其他 GitHub上优秀Android开源项目 3. Android开发神器 1.Xabber客户端 2.oschina客户端 3.手机安全