android版本更新功能-完整版

源码下载地址:http://download.csdn.net/download/csdn576038874/9526085

1、检测是否有新版本

<pre class="java" name="code">//访问服务器是否有新版本发布
		UpdateVersionUtil.checkVersion(MainActivity.this);
		//设置版本更新的回调接口
		UpdateVersionUtil.setUpdateListener(new UpdateListener() {
			@Override
			public void onUpdateReturned(int updateStatus,final VersionInfo versionInfo) {
				//判断回调过来的版本检测状态
				switch (updateStatus) {
				case UpdateStatus.YES:
					//弹出更新提示
					UpdateVersionUtil.showDialog(MainActivity.this,versionInfo);
					break;
				case UpdateStatus.NO:
					//没有新版本
					ToastUtils.showToast(getApplicationContext(), "已经是最新版本了!");
					break;
				case UpdateStatus.NOWIFI:
					//当前是非wifi网络
					//ToastUtils.showToast(getApplicationContext(), "只有在wifi下更新!");
					DialogUtils.showDialog(MainActivity.this, "温馨提示","当前非wifi网络,下载会消耗手机流量!", "确定", "取消",new DialogOnClickListenner() {
						@Override
						public void btnConfirmClick(Dialog dialog) {
							dialog.dismiss();
							//点击确定之后弹出更新对话框
							UpdateVersionUtil.showDialog(SystemActivity.this,versionInfo);
						}

						@Override
						public void btnCancelClick(Dialog dialog) {
							dialog.dismiss();
						}
					});
					break;
				case UpdateStatus.ERROR:
					//检测失败
		        	ToastUtils.showToast(getApplicationContext(), "检测失败,请稍后重试!");
					break;
				case UpdateStatus.TIMEOUT:
					//链接超时
		        	ToastUtils.showToast(getApplicationContext(), "链接超时,请检查网络设置!");
					break;
				}
			}
		});

2、检测版本的工具类

<pre class="java" name="code">import java.io.File;
import java.lang.reflect.Method;
import org.json.JSONArray;
import org.json.JSONObject;
import com.example.updateversion.HttpRequest.RequestCallBackListener;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

/**
 *
 * @author	wenjie
 *	版本更新的工具类
 */
public class UpdateVersionUtil{

	/**
	 * 接口回调
	 * @author wenjie
	 *
	 */
	public interface UpdateListener{
		void onUpdateReturned(int updateStatus,VersionInfo versionInfo);
	}

	public static UpdateListener updateListener;

	public static void setUpdateListener(UpdateListener updateListener) {
		UpdateVersionUtil.updateListener = updateListener;
	}

	/**
	 * 检测版本
	 * @param context 上下文
	 */
	public static void checkVersion(final Context context){
		HttpRequest.get(ServerReqAddress.UPDATA_VERSION_REQ, new RequestCallBackListener() {

			@Override
			public void onSuccess(String resultData) {
				try {
					JSONObject jsonObject = JsonUtil.stringToJson(resultData);
					JSONArray array = jsonObject.getJSONArray("data");
					VersionInfo mVersionInfo = JsonUtil.jsonToBean(array.getJSONObject(0).toString(), VersionInfo.class);
					int clientVersionCode = ApkUtils.getVersionCode(context);
					int serverVersionCode = mVersionInfo.getVersionCode();
					//有新版本
					if(clientVersionCode < serverVersionCode){
						int i = NetworkUtil.checkedNetWorkType(context);
						if(i == NetworkUtil.NOWIFI){
							updateListener.onUpdateReturned(UpdateStatus.NOWIFI,mVersionInfo);
						}else if(i == NetworkUtil.WIFI){
							updateListener.onUpdateReturned(UpdateStatus.YES,mVersionInfo);
						}
					}else{
						//无新本
						updateListener.onUpdateReturned(UpdateStatus.NO,null);
					}
				} catch (Exception e) {
					e.printStackTrace();
					updateListener.onUpdateReturned(UpdateStatus.ERROR,null);
				}
			}

			@Override
			public void onFailure(String error) {
				updateListener.onUpdateReturned(UpdateStatus.TIMEOUT,null);
			}
		});
	}

	/**
	 * 弹出新版本提示
	 * @param context 上下文
	 * @param versionInfo 更新内容
	 */
	public static void showDialog(final Context context,final VersionInfo versionInfo){
		final Dialog dialog = new AlertDialog.Builder(context).create();
		final File file = new File(SDCardUtils.getRootDirectory()+"/updateVersion/gdmsaec-app.apk");
		dialog.setCancelable(true);// 可以用“返回键”取消
		dialog.setCanceledOnTouchOutside(false);//
		dialog.show();
		View view = LayoutInflater.from(context).inflate(R.layout.version_update_dialog, null);
		dialog.setContentView(view);

		final Button btnOk = (Button) view.findViewById(R.id.btn_update_id_ok);
		Button btnCancel = (Button) view.findViewById(R.id.btn_update_id_cancel);
		TextView tvContent = (TextView) view.findViewById(R.id.tv_update_content);
		TextView tvUpdateTile = (TextView) view.findViewById(R.id.tv_update_title);
		final TextView tvUpdateMsgSize = (TextView) view.findViewById(R.id.tv_update_msg_size);

		tvContent.setText(versionInfo.getVersionDesc());
		tvUpdateTile.setText("最新版本:"+versionInfo.getVersionName());

		if(file.exists() && file.getName().equals("gdmsaec-app.apk")){
			tvUpdateMsgSize.setText("新版本已经下载,是否安装?");
		}else{
			tvUpdateMsgSize.setText("新版本大小:"+versionInfo.getVersionSize());
		}

		btnOk.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
				if(v.getId() == R.id.btn_update_id_ok){
					//新版本已经下载
					if(file.exists() && file.getName().equals("gdmsaec-app.apk")){
						Intent intent = ApkUtils.getInstallIntent(file);
						context.startActivity(intent);
					}else{
						//没有下载,则开启服务下载新版本
						Intent intent = new Intent(context,UpdateVersionService.class);
						intent.putExtra("downloadUrl", versionInfo.getDownloadUrl());
						context.startService(intent);
					}
				}
			}
		});

		btnCancel.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});
	}

	/**
	 * 收起通知栏
	 * @param context
	 */
	public static void collapseStatusBar(Context context) {
		try{
			Object statusBarManager = context.getSystemService("statusbar");
			Method collapse;
			if (Build.VERSION.SDK_INT <= 16){
				collapse = statusBarManager.getClass().getMethod("collapse");
			}else{
				collapse = statusBarManager.getClass().getMethod("collapsePanels");
			}
			collapse.invoke(statusBarManager);
		}catch (Exception localException){
			localException.printStackTrace();
		}
	}

3、版本更新的实体类

<pre class="java" name="code">import java.io.Serializable;

/**
 * @项目名: 	gdmsaec-app
 * @包名:	com.winfo.gdmsaec.app.domain
 * @类名:	VersionInfo
 * @创建者:	wenjie
 * @创建时间:	2015-10-14	上午11:06:08
 * @描述:	app版本信息封装类
 *
 * @svn版本:	$Rev: 1304 $
 * @更新人:	$Author: wenjie $
 * @更新时间:	$Date: 2016-02-27 14:58:42 +0800 (Sat, 27 Feb 2016) $
 * @更新描述:	TODO
 */
public class VersionInfo implements Serializable{
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	private String id;
	private String	versionName;//版本名
	private int		versionCode;//版本号
	private String	versionDesc;//版本描述信息内容
	private String	downloadUrl;//新版本的下载路径
	private String versionSize;//版本大小

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getVersionSize() {
		return versionSize;
	}
	public void setVersionSize(String versionSize) {
		this.versionSize = versionSize;
	}
	public String getVersionName() {
		return versionName;
	}
	public void setVersionName(String versionName) {
		this.versionName = versionName;
	}
	public int getVersionCode() {
		return versionCode;
	}
	public void setVersionCode(int versionCode) {
		this.versionCode = versionCode;
	}
	public String getVersionDesc() {
		return versionDesc;
	}
	public void setVersionDesc(String versionDesc) {
		this.versionDesc = versionDesc;
	}
	public String getDownloadUrl() {
		return downloadUrl;
	}
	public void setDownloadUrl(String downloadUrl) {
		this.downloadUrl = downloadUrl;
	}

}

4、版本更新的状态类

<pre class="java" name="code">/**
 *
 * @author wenjie
 *	检测版本的状态类
 */
public interface UpdateStatus {
	/**
	 * 没有新版本
	 */
	public static int NO = 1;

	/**
	 * 有新版本
	 */
	public static int YES = 2;

	/**
	 * 链接超时
	 */
	public static int TIMEOUT = 3;

	/**
	 * 没有wifi
	 */
	public static int NOWIFI = 4;

	/**
	 * 数据解析出错
	 */
	public static int ERROR = -1;
}

5、版本更新的服务

<pre class="java" name="code">import java.io.File;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.HttpHandler;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.RemoteViews;

/**
 *
 * @author wenjie
 *	下载新版本的服务类
 */
public class UpdateVersionService extends Service {

	private NotificationManager nm;
	private Notification notification;
	//标题标识
	private int titleId = 0;
	//安装文件
	private File updateFile;

	private static HttpHandler<File> httpHandler;
	private HttpUtils httpUtils;

	private long initTotal = 0;//文件的总长度

	@Override
	public void onCreate() {
		super.onCreate();

		httpUtils = new HttpUtils();
		updateFile = new File(SDCardUtils.getRootDirectory()+"/updateVersion/gdmsaec-app.apk");

		nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		notification = new Notification();
		notification.icon = R.drawable.ic_launcher;
		notification.tickerText = "开始下载";
		notification.when = System.currentTimeMillis();
		notification.contentView = new RemoteViews(getPackageName(), R.layout.notifycation);

	}

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

//		VersionInfo versionInfo = (VersionInfo) intent.getSerializableExtra("versionInfo");
//		String url = versionInfo.getDownloadUrl();
		Bundle bundle = intent.getExtras();
		String url = bundle.getString("downloadUrl");

		PreferenceUtils.setString(UpdateVersionService.this, "apkDownloadurl", url);

		nm.notify(titleId, notification);
		downLoadFile(url);
		return super.onStartCommand(intent, flags, startId);
	}

	public void downLoadFile(String url){

		httpHandler = httpUtils.download(url,updateFile.getAbsolutePath(), true, false, new RequestCallBack<File>() {

			@Override
			public void onSuccess(ResponseInfo<File> response) {
				// 更改文字
                notification.contentView.setTextViewText(R.id.msg, "下载完成!点击安装");
//                notification.contentView.setViewVisibility(R.id.btnStartStop, View.GONE);
//                notification.contentView.setViewVisibility(R.id.btnCancel,View.GONE);
                // 发送消息
                nm.notify(0, notification);
                stopSelf();
                //收起通知栏
                UpdateVersionUtil.collapseStatusBar(UpdateVersionService.this);
                //自动安装新版本
                Intent installIntent = ApkUtils.getInstallIntent(updateFile);
                startActivity(installIntent);

			}

			@Override
			public void onFailure(HttpException error, String msg) {
				//网络连接错误
				if(error.getExceptionCode() == 0 ){
					// 更改文字
	                notification.contentView.setTextViewText(R.id.msg, "网络异常!请检查网络设置!");
				}else if(error.getExceptionCode() == 416){//文件已经下载完毕
					// 更改文字
	                notification.contentView.setTextViewText(R.id.msg, "智慧海事");
	                // 更改文字
	                notification.contentView.setTextViewText(R.id.bartext, "检测到新版本已经下载完成,点击即安装!");
	                // 隐藏进度条
	                notification.contentView.setViewVisibility(R.id.progressBar1, View.GONE);

	                Intent intent = ApkUtils.getInstallIntent(updateFile);
	                PendingIntent pendingIntent = PendingIntent.getActivity(UpdateVersionService.this, 0, intent, 0);
	                notification.flags = Notification.FLAG_AUTO_CANCEL;//点击通知栏之后 消失
	                notification.contentIntent  = pendingIntent;//启动指定意图
				}
                // 发送消息
                nm.notify(0, notification);
			}

			@Override
			public void onLoading(long total, long current, boolean isUploading) {
				if(initTotal == 0){//说明第一次开始下载
					initTotal = total;
				}

				if(initTotal != total){//说明下载过程中暂停过,文件的总长度出现问题  就把初始的文件的长度赋值给他重新计算已经下载的比例
					total = initTotal;
				}

				long l = current*100/total;
				notification.contentView.setTextViewText(R.id.msg, "正在下载:智慧海事");
				// 更改文字
                notification.contentView.setTextViewText(R.id.bartext, l+ "%");
                // 更改进度条
                notification.contentView.setProgressBar(R.id.progressBar1, 100,(int)l, false);
                // 发送消息
                nm.notify(0, notification);

//              Intent intent = new Intent();
//				intent.setAction("cancel");
//				PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
//				notification.contentView.setOnClickPendingIntent(R.id.btnStartStop, pendingIntent);

			}

			@Override
			public void onStart() {
				notification.contentView.setTextViewText(R.id.msg, "开始下载:智慧海事");
				nm.notify(titleId, notification);
			}

		});
	}

	public static HttpHandler<File> getHandler(){
		return httpHandler;
	}

	@Override
	public void onDestroy() {
		//下载完成时,清楚该通知,自动安装
		nm.cancel(titleId);
		System.out.println("UpdateVersionService----onDestroy");
//		try {
//			GdmsaecApplication.db.deleteAll(VersionInfo.class);
//		} catch (DbException e) {
//			e.printStackTrace();
//		}
		super.onDestroy();
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

}

6、操作APK文件的工具类

<pre class="java" name="code">import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.AsyncTask;

/**
 *
 * @项目名: 	gdmsaec-app
 * @包名:	com.winfo.gdmsaec.app.utils
 * @类名:	ApkUtils
 * @创建者:	yanfeijun
 * @创建时间:	2015-10-14	上午10:57:36
 * @描述:	获取app相关信息的工具类
 *
 * @svn版本:	$Rev: 1161 $
 * @更新人:	$Author: wenjie $
 * @更新时间:	$Date: 2016-01-25 14:21:41 +0800 (Mon, 25 Jan 2016) $
 * @更新描述:	TODO
 */
public class ApkUtils {
	private static final String TAG = ApkUtils.class.getSimpleName();

	/**
	 * 获取应用程序名称
	 */
	public static String getAppName(Context context) {
		try {
			PackageManager packageManager = context.getPackageManager();
			PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
			int labelRes = packageInfo.applicationInfo.labelRes;
			return context.getResources().getString(labelRes);
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取应用程序版本名称信息
	 *
	 * @param context
	 * @return 当前应用的版本名称
	 */
	public static String getVersionName(Context context) {
		try {
			PackageManager packageManager = context.getPackageManager();
			PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
			return packageInfo.versionName;

		} catch (NameNotFoundException e) {

		}
		return null;
	}

	/**
	 * @return 当前程序的版本号
	 */
	public static int getVersionCode(Context context) {
		int version;
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
			version = packageInfo.versionCode;
		} catch (Exception e) {
			e.printStackTrace();
			version = 0;
		}
		return version;
	}

	/**
	 * 得到安装的intent
	 * @param apkFile
	 * @return
	 */
	public static Intent getInstallIntent(File apkFile) {
		Intent intent = new Intent();
		intent.setAction(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.fromFile(new File(apkFile.getAbsolutePath())),
				"application/vnd.android.package-archive");
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		return intent;
	}

}

7、网络访问的请求工具类

import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;

/**
 * http  请求工具类
 * @author winfo-wj
 *
 */
public class HttpRequest {

	private static HttpUtils http = new HttpUtils();

	/**
	 * 请求回调接口
	 * @author winfo-wj
	 *
	 */
	public interface RequestCallBackListener{
		/**
		 * 请求成功
		 * @param resultData	服务器返回的结果数据
		 */
		public void onSuccess(String resultData);

		/**
		 * 请求失败
		 * @param error	错误信息
		 */
		public void onFailure(String error);
	}

	/**
	 * get请求
	 * @param url 请求路径
	 * @param requestCallBackListener 请求回调
	 */
	public static void get(String url , final RequestCallBackListener requestCallBackListener){
		http.configTimeout(1000*10);
		http.send(HttpMethod.GET, url, new RequestCallBack<String>() {

			@Override
			public void onSuccess(ResponseInfo<String> response) {
				requestCallBackListener.onSuccess(response.result);
			}

			@Override
			public void onFailure(HttpException error, String msg) {
				requestCallBackListener.onFailure(msg);
			}
		});
	}

	/**
	 * post请求
	 * @param url	请求地址
	 * @param params	请求参数
	 * @param requestCallBackListener	请求回调
	 */
	public static void post(String url ,RequestParams params , final RequestCallBackListener requestCallBackListener){
		http.configTimeout(1000*10);
		http.send(HttpMethod.POST, url, params, new RequestCallBack<String>() {

			@Override
			public void onSuccess(ResponseInfo<String> response) {
				requestCallBackListener.onSuccess(response.result);
			}

			@Override
			public void onFailure(HttpException error, String msg) {
				requestCallBackListener.onFailure(msg);
			}
		});
	}
}

8、jaon解析工具类

<pre class="java" name="code">import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;

import com.google.gson.Gson;

/**
 * json 和 实体类之间的相互转换
 * @author 00
 *
 */
public class JsonUtil {
	/**
	 * 将一个实体对象  转换成一个json字符串  提示对象中可包含集合
	 * @param t 实体类
	 * @return
	 */
	public static <T> String beanToJson(T t){
		Gson gson = new Gson();
		String json = gson.toJson(t);
		return json;
	}

	/**
	 * 将一个json字符串 转换成一个实体类对象 可包含list
	 * @param json
	 * @param t
	 * @return
	 */
	public static <T> T jsonToBean(String json,Class<T> class1) throws InstantiationException, IllegalAccessException{
		Gson gson = new Gson();
		T t = class1.newInstance();
		t=gson.fromJson(json, class1);
		return t;
	}

	/**
	 * 将json字符串转换成一个json对象
	 * @param str
	 * @return
	 */
	public static JSONObject stringToJson(String str){
		try {
			return new JSONObject(str);
		} catch (JSONException e) {
			e.printStackTrace();
			return null;
		}
	}
	public static String getString(InputStream is){

		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();

			byte[] buffer = new byte[1024];
			int len = -1;
			while((len = is.read(buffer)) != -1){
				baos.write(buffer, 0, len);
			}

			byte[] byteArray = baos.toByteArray();
			//String str = new String(byteArray);

			return new String(byteArray,"utf-8");
		} catch (IOException e) {
			e.printStackTrace();
		}

		return "";
	}

	/**
	 * 从assert文件夹中读取json文件,然后转化为json对象
	 * @throws Exception
	 */
	public static JSONObject getJsonDataFromAssets(Context context,String jsonFileName) throws Exception{
		JSONObject mJsonObj = null;
		StringBuffer sb = new StringBuffer();
		InputStream is = context.getAssets().open(jsonFileName);
		int len = -1;
		byte[] buf = new byte[1024];
		while ((len = is.read(buf)) != -1){
			sb.append(new String(buf, 0, len, "UTF-8"));
		}
		is.close();
		mJsonObj = new JSONObject(sb.toString());
		return mJsonObj;
	}

}

9、网络状态监听的工具类

<pre class="java" name="code">import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

/**
 * 网络检查
 * @author 00
 *
 */
public class NetworkUtil {
	/**
	 * 没有网络
	 */
	public static final int NONETWORK = 0;
	/**
	 * 当前是wifi连接
	 */
	public static final int WIFI = 1;
	/**
	 * 不是wifi连接
	 */
	public static final int NOWIFI = 2;

	/**
	 * 检测当前网络的类型 是否是wifi
	 * @param context
	 * @return
	 */
	public static int checkedNetWorkType(Context context){
		if(!checkedNetWork(context)){
			return NONETWORK;
		}
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		if(cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting() ){
			return WIFI;
		}else{
			return NOWIFI;
		}
	}

	/**
	 * 检查是否连接网络
	 * @param context
	 * @return
	 */
	public static boolean  checkedNetWork(Context context){
		// 1.获得连接设备管理器
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		if(cm == null) return false;
		/**
		 * 获取网络连接对象
		 */
		NetworkInfo networkInfo = cm.getActiveNetworkInfo();

		if(networkInfo == null || !networkInfo.isAvailable()){
			return false;
		}
		return true;
	}
}

10、临时文件保存

<pre class="java" name="code">import com.lidroid.xutils.DbUtils;
import com.lidroid.xutils.exception.DbException;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
/**
 *
 * @项目名: 	WinfoSeaMap
 * @包名:	com.winfo.seamap.utils
 * @类名:	PreferenceUtils
 * @创建者:	yanfeijun
 * @创建时间:	2015-9-15	上午10:55:24
 * @描述:	SharedPreferences工具类
 *
 * @svn版本:	$Rev: 93 $
 * @更新人:	$Author: wenjie $
 * @更新时间:	$Date: 2015-09-24 15:48:12 +0800 (Thu, 24 Sep 2015) $
 * @更新描述:	TODO
 */
public class PreferenceUtils
{
	private static SharedPreferences	mSp;
	private final static String			SP_NAME	= "config";

	/**
	 * 获得sharePreference内存对象
	 *
	 * @param context
	 * @return
	 */
	private static SharedPreferences getSp(Context context)
	{
		if (mSp == null)
		{
			mSp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
		}
		return mSp;
	}

	/**
	 * 获取boolean类型的值
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @param defValue
	 *            如果没有对应的值,
	 * @return
	 */
	public static boolean getBoolean(Context context, String key, boolean defValue)
	{
		SharedPreferences sp = getSp(context);
		return sp.getBoolean(key, defValue);
	}

	/**
	 * 获取boolean类型的值,如果没有对应的值,默认值返回false
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @return
	 */
	public static boolean getBoolean(Context context, String key)
	{
		return getBoolean(context, key, false);
	}

	/**
	 * 设置int类型的值
	 *
	 * @param context
	 * @param key
	 * @param value
	 */
	public static void setInt(Context context, String key, int value)
	{
		SharedPreferences sp = getSp(context);
		Editor editor = sp.edit();
		editor.putInt(key, value);
		editor.commit();
	}

	/**
	 * 设置boolean类型的值
	 *
	 * @param context
	 * @param key
	 * @param value
	 */
	public static void setBoolean(Context context, String key, boolean value)
	{
		SharedPreferences sp = getSp(context);
		Editor editor = sp.edit();
		editor.putBoolean(key, value);
		editor.commit();
	}

	/**
	 * 获取String类型的值
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @param defValue
	 *            如果没有对应的值,
	 * @return
	 */
	public static String getString(Context context, String key, String defValue)
	{
		SharedPreferences sp = getSp(context);
		return sp.getString(key, defValue);
	}

	/**
	 * 获取int类型的值
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @param defValue
	 *            如果没有对应的值,
	 * @return
	 */
	public static int getInt(Context context, String key, int defValue)
	{
		SharedPreferences sp = getSp(context);
		return sp.getInt(key, defValue);
	}

	/**
	 * 获取String类型的值,如果没有对应的值,默认值返回null
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @return
	 */
	public static String getString(Context context, String key)
	{
		return getString(context, key, null);
	}

	/**
	 * 设置String类型的值
	 *
	 * @param context
	 * @param key
	 * @param value
	 */
	public static void setString(Context context, String key, String value)
	{
		SharedPreferences sp = getSp(context);
		Editor editor = sp.edit();
		editor.putString(key, value);
		editor.commit();
	}

	/**
	 * 获取long类型的值
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @param defValue
	 *            如果没有对应的值,
	 * @return
	 */
	public static long getLong(Context context, String key, long defValue)
	{
		SharedPreferences sp = getSp(context);
		return sp.getLong(key, defValue);
	}

	/**
	 * 获取long类型的值,如果没有对应的值,默认值返回0
	 *
	 * @param context
	 *            上下文
	 * @param key
	 *            对应的键
	 * @return
	 */
	public static Long getLong(Context context, String key)
	{
		return getLong(context, key, 0);
	}

	/**
	 * 设置Long类型的值
	 *
	 * @param context
	 * @param key
	 * @param value
	 */
	public static void setLong(Context context, String key, long value)
	{
		SharedPreferences sp = getSp(context);
		Editor editor = sp.edit();
		editor.putLong(key, value);
		editor.commit();
	}

	/**
	 * 根据key值删除指定的数据
	 * @param context
	 * @param key
	 */
	public static void remove(Context context , String key){
		SharedPreferences sp = getSp(context);
		Editor editor = sp.edit();
		editor.remove(key);
		editor.commit();
	}
}

11、sdcard操作工具类

<pre class="java" name="code">import java.io.File;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;

/**
 *
 * @项目名: 	gdmsaec-app
 * @包名:	com.winfo.gdmsaec.app.utils
 * @类名:	SDCardUtils
 * @创建者:	yanfeijun
 * @创建时间:	2015-10-20	下午3:38:10
 * @描述:	SD卡工具类
 *
 * @svn版本:	$Rev$
 * @更新人:	$Author$
 * @更新时间:	$Date$
 * @更新描述:	TODO
 */
public class SDCardUtils {

	public static String getPath(){
		return Environment.getExternalStorageDirectory().getAbsolutePath();
	}
	/**
	 * 获取SD卡的状态
	 * @return
	 */
	public static String getState(){
		return Environment.getExternalStorageState();
	}

	/**
	 * SD卡是否可用
	 * @return 只有当SD卡已经安装并且准备好了才返回true
	 */
	public static boolean isAvailable(){
		return getState().equals(Environment.MEDIA_MOUNTED);
	}

	/**
	 * 获取SD卡的根目录
	 * @return null:不存在SD卡
	 */
	public static File getRootDirectory(){
		return isAvailable()?Environment.getExternalStorageDirectory():null;
	}

	/**
	 * 获取SD卡的根路径
	 * @return null:不存在SD卡
	 */
	public static String getRootPath(){
		File rootDirectory = getRootDirectory();
		return rootDirectory != null ?rootDirectory.getPath():null;
	}

	/**
	 * 获取SD卡总的容量
	 * @return 总容量;-1:SD卡不可用
	 */
	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	public static long getTotalSize(){
		if(isAvailable()){
			StatFs statFs = new StatFs(getRootDirectory().getPath());
			if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1){
				return statFs.getBlockCount() * statFs.getBlockSize();
			}else{
				return statFs.getBlockCount() * statFs.getBlockSize();
			}
		}else{
			return -1;
		}
	}

	/**
	 * 获取SD卡中可用的容量
	 * @return 可用的容量;-1:SD卡不可用
	 */
	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	public static long getAvailableSize(){
		if(isAvailable()){
			StatFs statFs = new StatFs(getRootDirectory().getPath());
			if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1){
				return statFs.getAvailableBlocks() * statFs.getBlockSize();
			}else{
				return statFs.getAvailableBlocks() * statFs.getBlockSize();
			}
		}else{
			return -1;
		}
	}
}

12、吐司工具类

<pre class="java" name="code">import android.content.Context;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Toast工具箱  可防止用户多次点击之后 显示消息的时长太长  利用handler消息机制
 */
public class ToastUtils {

	private static String oldMsg;
    protected static Toast toast   = null;
    private static long oneTime=0;
    private static long twoTime=0;
    private static Handler handler = new Handler();
    private static Runnable runnable = new Runnable() {
		@Override
		public void run() {
			toast.cancel();
			toast = null;
		}
	};
    /**
     * 吐出一个显示时间较短的提示
     * @param context 上下文
     * @param s  文本内容
     */
    public static void showToast(Context context, String s){
        if(toast==null){
            toast =Toast.makeText(context, s, Toast.LENGTH_SHORT);
            toast.show();
            oneTime=System.currentTimeMillis();
        }else{
            twoTime=System.currentTimeMillis();
            if(s.equals(oldMsg)){
                if(twoTime-oneTime>Toast.LENGTH_SHORT){
                    toast.show();
                }
            }else{
                oldMsg = s;
                toast.setText(s);
                toast.show();
            }
        }
        oneTime=twoTime;
    }

	/**
	 * 吐出一个显示时间较短的提示
	 * @param context 上下文对象
	 * @param resId 显示内容资源ID
	 */
	public static final void showToast(Context context, int resId){
		showToast(context, context.getString(resId));
	}

	/**
	 * 吐出一个显示时间较长的提示
	 * @param context 上下文对象
	 * @param formatResId 被格式化的字符串资源的ID
	 * @param args 参数数组
	 */
	public static final void toastL(Context context, int formatResId, Object... args){
		Toast.makeText(context, String.format(context.getString(formatResId), args), Toast.LENGTH_LONG).show();
	}

	/**
	 * 吐出一个显示时间较短的提示
	 * @param context 上下文对象
	 * @param formatResId 被格式化的字符串资源的ID
	 * @param args 参数数组
	 */
	public static final void toastS(Context context, int formatResId, Object... args){
		Toast.makeText(context, String.format(context.getString(formatResId), args), Toast.LENGTH_SHORT).show();
	}

	/**
	 * 吐出一个显示时间较长的提示
	 * @param context 上下文对象
	 * @param format 被格式化的字符串
	 * @param args 参数数组
	 */
	public static final void toastL(Context context, String format, Object... args){
		Toast.makeText(context, String.format(format, args), Toast.LENGTH_LONG).show();
	}

	/**
	 * 吐出一个显示时间较短的提示
	 * @param context 上下文对象
	 * @param format 被格式化的字符串
	 * @param args 参数数组
	 */
	public static final void toastS(Context context, String format, Object... args){
		Toast.makeText(context, String.format(format, args), Toast.LENGTH_SHORT).show();
	}

}

13、通知栏的布局

<pre class="html" name="code"><pre class="html" name="code"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:orientation="vertical"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >
	    <LinearLayout
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:orientation="horizontal"
	        android:layout_gravity="center_vertical"
	        >
	        <ImageView
	            android:layout_width="40dp"
	            android:layout_height="40dp"
	            android:layout_gravity="center"
	            android:src="@drawable/ic_launcher"
	            />
	    </LinearLayout>

	    <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="wrap_content"
	        android:orientation="vertical"
	        android:weightSum="3"
	        android:paddingLeft="10dp"
	        android:paddingRight="10dp"
	        android:layout_gravity="center_vertical"
	        >
	        <TextView
	            android:id="@+id/msg"
	            android:text="正在下载:智慧海事"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:textColor="#ffffff"
	            android:textSize="14sp"
	            />
	        <TextView
	            android:id="@+id/bartext"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:text="0%"
	            android:textColor="#ffffff"
	            android:textSize="12sp"
	            />
	        <ProgressBar
	        	android:id="@+id/progressBar1"
	        	style="?android:attr/progressBarStyleHorizontal"
	        	android:layout_width="match_parent"
	        	android:layout_height="5dp" />

	        <!--
	        <LinearLayout
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content"
		        android:orientation="horizontal"
		        >
		        <Button
		            android:id="@+id/btnStartStop"
		            android:layout_width="0dp"
		            android:layout_weight="1"
		            android:layout_height="25dp"
		            android:text="暂停"
		            android:textSize="12sp"
		            android:textColor="#ffffff"
		            />
		        <Button
		            android:id="@+id/btnCancel"
		            android:layout_width="0dp"
		            android:layout_weight="1"
		            android:layout_height="25dp"
		            android:text="取消"
		            android:textSize="12sp"
		            android:textColor="#ffffff"
		            />
	    	</LinearLayout>
	         -->
	    </LinearLayout>

    </LinearLayout>

</LinearLayout>


14、按本更新提示的对话框布局文件

<pre class="html" name="code"><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="60dp"
         android:layout_centerInParent="true"
        android:layout_marginRight="60dp"
        android:background="@drawable/dialog_bg"
        android:orientation="vertical" >

        <!-- Title -->

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="45dp" >
            <ImageView
                android:id="@+id/umeng_wifi_indicator"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:src="@drawable/ic_launcher" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="发现新版本"
                android:textSize="@dimen/normal_text_size"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:textColor="@color/black" />

        </RelativeLayout>

        <!-- split -->

        <View
            android:layout_width="fill_parent"
           	android:layout_height="0.5dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="#d8d8d8" />
        <!-- Content -->

        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:padding="10dp"
            android:layout_weight="1" >

            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/tv_update_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="最新版本:智慧海事v2.2.1"
                    android:textColor="@color/black"
                    android:textSize="@dimen/medium_text_size"
                    />

                <TextView
                    android:id="@+id/tv_update_msg_size"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="新版本大小:19.07M"
                    android:textSize="@dimen/medium_text_size"
                    android:layout_marginTop="10dp"
                    android:textColor="@color/black"
                    />

                <TextView
                    android:id="@+id/tv_update_content"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:minHeight="60dp"
                    android:textSize="@dimen/medium_text_size"
                    android:text="\n更新内容:\n1、处理了海图上长按定点查询附近通航要素和船舶的bug\n2、新增点击消息列表查看消息类容\n3、调整经纬度变化距离获取消息通知,以及优化消息列表的显示样式\n4、海图切换窗口里面新增 显示当前屏幕范围内的AIS数据\n"
                    android:lineSpacingExtra="3dp"
                    android:textColor="@color/black"
                    />
            </LinearLayout>
        </ScrollView>

        <!-- Ignore CheckBox -->

        <!-- OK&Cancel Button -->

        <LinearLayout
            android:layout_width="fill_parent"
            android:orientation="horizontal"
            android:layout_height="wrap_content" >

            <Button
                android:id="@+id/btn_update_id_cancel"
                android:layout_width="0dp"
                android:layout_height="40dp"
                android:layout_weight="1"
                android:background="@drawable/dialog_cancel_btn_bg"
                android:text="以后再说"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="5dp"
                android:layout_marginBottom="10dp"
                android:textSize="@dimen/normal_text_size"
                android:textColor="@color/black" />

            <Button
                android:id="@+id/btn_update_id_ok"
                android:layout_width="0dp"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="10dp"
                android:layout_marginBottom="10dp"
                android:layout_height="40dp"
                android:layout_weight="1"
                android:textSize="@dimen/normal_text_size"
                android:background="@drawable/dialog_ok_btn_bg"
                android:text="立即更新"
                android:textColor="@color/white" />
        </LinearLayout>
    </LinearLayout>

</RelativeLayout>

15、对话框按钮的.9图

16、字体颜色

<!-- 黑色 -->

<color name="black">#333333</color>

17、字体大小文件

<dimen name="title_text_size">18sp</dimen><!-- 标题字体大小 -->

<dimen name="normal_text_size">16sp</dimen><!-- 通常字体大小 -->

<dimen name="medium_text_size">14sp</dimen><!-- 中等字体大小 -->

<dimen name="small_text_size">12sp</dimen><!-- 小号字体大小 -->

时间: 2024-10-11 16:11:58

android版本更新功能-完整版的相关文章

弱智儿童欢乐多游戏android源码完整版

1.弱智儿童欢乐多游戏源码完整版2  项目概要:弱智儿童欢乐多,这就是一款弱智的游戏……回归正题,这是一款仿IOS上TripTrap的关卡解锁模式的益智休闲游戏,代码中实际只有一关游戏,但是可以体验解锁,第一关和第二关都是一样的游戏场景.3  项目问题:虽然上传了文档,但不是参考,而是因为存在很多问题,欢迎大家指导:代码也很渣,欢迎吐槽:没有做适屏,所以打包的APK如果安装在大家的机子里maybe会混乱,我的机子是魅族MX3:微博分享功能是直接用的网上下载的例子,自己原理也没有弄清楚,所以这块有

OKHttp和NumberProgressbar组建强大的Android版本更新功能

你们看过韩国电影<奇怪的她>不?女主角是不是超级漂亮的.......好啦,扯正事吧,先看看女神照片. 公司新项目用到了OKHttp网络框架,在下载文件这块都蒙圈啦,再查查资料就一个Resopnse方法返回数据,而且是在下载文件结束之后才会走这个方法,整个项目和服务器打交道那块用得都是OKHttp,如果我再整个原生的HttpClient在里边实现版本更新总觉得我这代码脏了,心里不舒服,但是那我怎么获取下载的进度啊,所幸在网上找到了相应的案例,写的非常好,大家可以参考参考,可以获取下载的进度啦,那

android 混淆 不完整版

1.不混淆容易定位问题 (易破解) 2.proguard混淆  需要一个一个的添加麻烦(不容易破解) 3.加固 不错(非常不容易破解) 不完整混淆 # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/weidingqiang/Downloads/adt-bundle-mac-x86_64-201407

Android掌中游斗地主游戏源码完整版

源码大放送-掌中游斗地主(完整版),集合了单机斗地主.网络斗地主.癞子斗地主等,有史以来最有参考价值的源码,虽然运行慢了一点但是功能正常,用的是纯java写的. 项目详细说明:http://android.662p.com <ignore_js_op> [/td][td] <ignore_js_op> [/td][td] <ignore_js_op> [/td][td] <ignore_js_op> [/td][td] <ignore_js_op>

【电子书下载】《Android应用程序开发与典型案例》完整版!!

图书简介: <android应用程序开发与典型案例>共23章,内容包含两大部分.第一部分是android程序设计基础,在介绍android环境搭建以及android系统基本控件和组件后,详细介绍了android系统应用编程中典型的技术,比如,android中的图形图像.多媒体编程.gps定位与地图编程等:第二部分是android程序ui设计,从手机软件的交互设计谈起,介绍了android用户界面设计原则和方法.android用户界面设计哲学等,并给出了具体建议. <android应用程序

完整版linux下android源码下载、编译、模拟器启动运行

一.环境说明: 1.VMware版本:8.0.3 build-703057 2.liunx系统:Ubuntu10.10 3.jdk:sun-java6-jdk 二.Ubuntu 10.10更新源列表 由于??Ubuntu 10.10版本的源已经过期了,所以,需要对其进行更新,Ubuntu 10.10 已经发布了,下面提供更新源方法与更新源列表地址: 1.sudo gedit /etc/apt/sources.list     编辑你的源列表,将原来的内容全部删除,添加下面的源,复制到你的列表中,

对于同一套应用程序如何发布一个体验版(有部分功能)完整版(有完整功能)

最近项目中,先做一个版本给用户(普通用户作为体验使用).之后再有一个完整功能版. #define OFFLINE using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 完整版_精简版 { class Program { static void Mai

Android照片墙完整版,完美结合LruCache和DiskLruCache

转载地址:http://blog.csdn.net/guolin_blog/article/details/34093441#comments 在上一篇文章当中,我们学习了DiskLruCache的概念和基本用法,但仅仅是掌握理论知识显然是不够的,那么本篇文章我们就来继续进阶一下,看一看在实战当中应该怎样合理使用DiskLruCache.还不熟悉DiskLruCache用法的朋友可以先去参考我的上一篇文章 Android DiskLruCache完全解析,硬盘缓存的最佳方案 . 其实,在真正的项

转 Android Activity之间动画完整版详解

标签:Android Activity动画详解 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://mzh3344258.blog.51cto.com/1823534/807337 大家可能遇到过跟小马一样的问题,就是在项目中不给Activity添加动画感觉好烂,特此,小马找个时间学习下Activity跳转时添加动画,网上资料一堆,但有些讲的是错的,而且只有文字没有效果,不如自己来,顺带试下什么效果,这个工程里面小马收集了一些常用