首页 > 代码库 > 安卓APP采用观察者模式实现检测版本更新

安卓APP采用观察者模式实现检测版本更新

第一步:定义观察者

public interface CheckVersionObserver {


	/**
	 * 在MainActivity里面检测版本更新成功
	 * @param mainEntity
	 */
	public void onCheckNewVerSuccInMain(MainEntity mainEntity);
	
	/**
	 * 检测新版本失败
	 * @param errorCode
	 * @param msg
	 */
	public void onCheckNewVerFail(int errorCode,String msg);
	
	/**
	 * 检测新版本成功
	 * @param token
	 * @param msg
	 */
	public void onCheckNewVerSucc(CheckUpdataEntity newEntity);
	
	/**
	 * 检测到版本可以升级,并且能够升级(含有内存卡)
	 * @param token
	 * @param msg
	 */
	public void onCheckVerCanUpdate(String promt, String versionName);
	/**
	 * 检测到版本可以升级,但不能够升级(无内存卡)
	 */
	public void onCheckVerCanNotUpdate();
	/**
	 * 下载失败
	 * @param code
	 * @param err
	 */
	public void onUpdateError(String topic, String msg, String btnStr, final int type);
	/**
	 * 正在更新下载
	 * @param totalSize
	 * @param downSize
	 */
	public void onDataUpdating(int totalSize, int downSize);
}

第二步:检测系统版本是否升级逻辑

public class CheckNewVersionLogic extends BaseLogic<CheckVersionObserver>
		implements UpdateDownLoadResponse {

	private Context mContext;
	private Activity mActivity;

	private final static int DOWNLOAD_UPDATE = 1;
	private final static int DOWNLOAD_UPDATING = 2;
	private final static int DOWNLOAD_ERROR = 3;

	public Handler mDownloadHandler;
	private String downloadUrl;

	private ProgressDialog mDialog = null;
	private int mDownFileSize = 0;
	private int mDownSize = 0;

	public CheckNewVersionLogic() {
	}

	public CheckNewVersionLogic(Context context) {
		this.mContext = context;
		mActivity = (Activity) mContext;
		mDownloadHandler = new DownloadHandler();
	}

	/**
	 * 判断检测更新请求是否成功
	 * 
	 * @param vercode
	 */
	public void CheckNewVersion(final String vercode) {
		new BackForeTask(true) {
			CheckUpdataEntity result = null;

			@Override
			public void onFore() {
				// TODO Auto-generated method stub

				if (result == null) {
					fireCheckNewVersionFail(-1, null);
				} else if (result.getRetcode() != 0) {
					fireCheckNewVersionFail(result.getRetcode(),
							result.getMessage());
				} else {
					fireCheckNewVersionSucc(result);
				}

			}

			@Override
			public void onBack() {
				// TODO Auto-generated method stub
				result = ProtocolImpl.getInstance().checkVersion(vercode);

			}
		};

	}

	/**
	 * 主界面检查更新
	 * @param token
	 * @param firstopen
	 * @param mobiletype
	 * @param mobilesys
	 * @param vercode
	 */
	public void CheckNewVerInMain(final int firstopen,
			final String mobiletype, final String mobilesys, final String vercode) {
		new BackForeTask(true) {

			MainEntity result = null;

			@Override
			public void onFore() {
				// TODO Auto-generated method stub

				if (result == null) {
					fireCheckNewVersionFail(-1, null);
				} else if (result.getRetcode() != 0) {
					fireCheckNewVersionFail(result.getRetcode(),
							result.getMessage());
				} else {
					fireCheckNewVerSuccInMain(result);
				}
				
			}

			@Override
			public void onBack() {
				// TODO Auto-generated method stub
				result = ProtocolImpl.getInstance().checkVerInMain(firstopen, mobiletype, mobilesys, vercode);
			}
		};
	}
	
	private void fireCheckNewVerSuccInMain(MainEntity mainEntity){
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onCheckNewVerSuccInMain(mainEntity);
		}
	}
	

	/**
	 * 版本更新请求失败
	 * 
	 * @param errorCode
	 * @param msg
	 */
	private void fireCheckNewVersionFail(int errorCode, String msg) {
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onCheckNewVerFail(errorCode, msg);
		}
	}

	/**
	 * 版本更新请求成功
	 * 
	 * @param newEntity
	 */
	private void fireCheckNewVersionSucc(CheckUpdataEntity newEntity) {
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onCheckNewVerSucc(newEntity);
		}
	}

	/**
	 * 检测到版本可以升级,并且能够升级(含有内存卡)
	 * 
	 * @param promt
	 * @param versionName
	 */
	private void fireCheckVerCanUpdate(String promt, String versionName) {
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onCheckVerCanUpdate(promt, versionName);
		}
	}

	/**
	 * 检测到版本可以升级,但不能够升级(无内存卡)
	 */
	private void fireCheckVerCanNotUpdate() {
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onCheckVerCanNotUpdate();
		}
	}

	/**
	 * 下载失败
	 * 
	 * @param code
	 * @param err
	 */
	private void fireOnError(String topic, String msg, String btnStr,
			final int type) {
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onUpdateError(topic, msg, btnStr, type);
		}
	}

	/**
	 * 正在下载
	 * 
	 * @param totalSize
	 * @param downSize
	 */
	private void fireOnDataUpdating(int downFileSize, int downSize) {
		List<CheckVersionObserver> tmpList = getObservers();
		for (CheckVersionObserver observer : tmpList) {
			observer.onDataUpdating(downFileSize, downSize);
		}
	}

	/**
	 * 下载更新
	 */
	public void downloadUpdate() {
		mDownloadHandler.sendEmptyMessage(DOWNLOAD_UPDATE);
	}

	/**
	 * 正在下载更新
	 * 
	 * @param totalSize
	 * @param downSize
	 */
	public void downloadUpdating(int totalSize, int downSize) {
		mDownFileSize = totalSize;
		mDownSize = downSize;
		mDownloadHandler.sendEmptyMessage(DOWNLOAD_UPDATING);
	}

	/**
	 * 下载失败
	 */
	public void downloadError() {
		mDownloadHandler.sendEmptyMessage(DOWNLOAD_ERROR);
	}

	/***
	 * 选择是否更新版本
	 */
	public void checkVersion(int serverVerCode, String promt, String versionName, String url) {

		Log.i("ciyunupdate", serverVerCode + "");
		System.out.println("serverVerCode" + serverVerCode);

		int appVerCode = 1;
		try {
			appVerCode = mContext.getPackageManager().getPackageInfo(
					mContext.getPackageName(), 0).versionCode;

			Log.i("ciyunupdate", appVerCode + "");
			System.out.println("appVerCode" + appVerCode);

		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		if (serverVerCode > appVerCode) {
			if (!FileUtil.isSdCardExist()) {
				/*
				 * showDialog(mContext.getString(R.string.str_version_update),
				 * mContext.getResources().getString(R.string.no_sdcard),
				 * mContext.getResources().getString(R.string.sure), 0);
				 */
				fireCheckVerCanNotUpdate();
			} else {
				// popUpdateDlg(promt,versionName);
				downloadUrl = url;
				fireCheckVerCanUpdate(promt, versionName);
			}
		}

	}

	/**
	 * 
	 * @Description:下载更新处理器
	 * @author:
	 * @see:
	 * @since:
	 * @copyright © ciyun.cn
	 * @Date:2014年8月12日
	 */
	private class DownloadHandler extends Handler {
		/**
		 * {@inheritDoc}
		 * 
		 * @see android.os.Handler#handleMessage(android.os.Message)
		 */
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case DOWNLOAD_UPDATE: {
				new Thread() {
					@Override
					public void run() {
						super.run();
						if (Utils.isExternalStorageRemovable()) {
							FileUtil.createFileEx(HealthApplication.UPDATAFILENAME);
							HttpPostEngine service = new HttpPostEngine();

							service.downloadUpdateFile(
									CheckNewVersionLogic.this,
									downloadUrl,
									FileUtil.updateFile.getPath());
						}
					}
				}.start();
			}
				break;
			case DOWNLOAD_UPDATING:
				fireOnDataUpdating(mDownFileSize, mDownSize);
				break;
			case DOWNLOAD_ERROR:
				fireOnError(
						mContext.getString(R.string.str_version_update),
						mContext.getString(R.string.str_download_err),
						mContext.getResources().getString(R.string.sure), 0);
				break;
			}
		}
	}

	@Override
	public void one rror(int code, String err) {
		// TODO Auto-generated method stub
		Log.v("update", code + "/" + err);
		if (mDialog != null && mDialog.isShowing()) {
			mDialog.dismiss();
		}
		mDownloadHandler.sendEmptyMessage(DOWNLOAD_ERROR);
	}

	@Override
	public void OnDataUpdated(int totalSize, int downSize) {
		// TODO Auto-generated method stub
		mDownFileSize = totalSize;
		mDownSize = downSize;
		mDownloadHandler.sendEmptyMessage(DOWNLOAD_UPDATING);
	}

	@Override
	public void OnUpdatedFinish() {
		// TODO Auto-generated method stub
		Uri uri = Uri.fromFile(FileUtil.updateFile);
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(uri, "application/vnd.android.package-archive");
		mActivity.startActivity(intent);
	}
}

第三步:在主界面按钮事件里面写如下代码:
CheckNewVersionLogic checkNewVersionLogic = new CheckNewVersionLogic(AboutAppActivity.this);
checkNewVersionLogic.CheckNewVersion(verCode + "");

第四步:主界面类要实现CheckVersionObserver,并实现如下方法:

void showDialog(String topic, String msg, String btnStr, final int type) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setIcon(android.R.drawable.ic_dialog_info);
		builder.setTitle(topic);
		builder.setMessage(msg);

		builder.setNegativeButton(btnStr,
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						if (type == 1) {
							AboutAppActivity.this.finish();
						} else {
							
						}
					}
				});

		builder.setCancelable(false);
		builder.create().show();
	}
	private void popUpdatingDlg(long totalSize) {
		if (mDialog == null) {
			mDialog = new ProgressDialog(this);
			mDialog.setMax(100);
			String size = (totalSize*0.000001 + "").substring(0, 4);
			mDialog.setTitle(getResources().getString(R.string.now_loading_new_version)+size+"M)");
			mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			mDialog.setCanceledOnTouchOutside(false);
			mDialog.setOnKeyListener(new OnKeyListener() {

				@Override
				public boolean onKey(DialogInterface dialog, int keyCode,
						KeyEvent event) {
					if ((keyCode == KeyEvent.KEYCODE_SEARCH)
							|| (keyCode == KeyEvent.KEYCODE_BACK)) {
						return true;
					}
					return false;
				}
			});
			mDialog.setCancelable(false);
			mDialog.show();
		}
	}

	@Override
	public void onCheckVerCanUpdate(String promt, String versionName) {
		// TODO Auto-generated method stub
		popUpdateDlg(promt,versionName);
	}

	@Override
	public void onCheckVerCanNotUpdate() {
		// TODO Auto-generated method stub
		showDialog(getString(R.string.str_version_update),
				getResources().getString(R.string.no_sdcard), getResources().getString(R.string.sure), 0);
	}

	@Override
	public void onUpdateError(String topic, String msg, String btnStr, int type) {
		// TODO Auto-generated method stub
		showDialog(topic,msg, btnStr, type);
	}

	@Override
	public void onDataUpdating(int totalSize, int downSize) {
		// TODO Auto-generated method stub
		popUpdatingDlg(totalSize);
		if (mDialog != null && mDialog.isShowing()) {
			if (downSize < totalSize) {
				mDialog.setProgress(downSize*100/totalSize);
			} else {
				mDialog.dismiss();
			}
		}
	}

	@Override
	public void onCheckNewVerFail(int errorCode, String msg) {
		// TODO Auto-generated method stub
		
		haloToast.dismissWaitDialog();//关闭提示框
		
		if(!TextUtils.isEmpty(msg))
			Toast.makeText(this, msg, 3000).show() ;
		if(errorCode == 200){			
			Intent intent = new Intent(AboutAppActivity.this,LoginActivity.class) ;
			startActivity(intent);
		}
		
		if(TextUtils.isEmpty(msg)){
			Toast.makeText(this, R.string.str_network_error_msg, 3000).show();
		}
		
	}

	@Override
	public void onCheckNewVerSucc(CheckUpdataEntity newEntity) {
		// TODO Auto-generated method stub

		haloToast.dismissWaitDialog();
		
		if (newEntity.getRetcode() == 0) {
			HealthApplication.mUserCache.setToken(newEntity.getToken());
			
			if (newEntity.getData()!=null) {
				int serverVerCode = newEntity.getData().getVercode();
				String prompt = newEntity.getData().getMessage();
				String verName = newEntity.getData().getVername();
				checkNewVersionLogic.checkVersion(serverVerCode, prompt, verName, newEntity.getData().getAppurl());
			}
		}
	}

	@Override
	public void onCheckNewVerSuccInMain(MainEntity mainEntity) {
		// TODO Auto-generated method stub
		
	}

第五步:用到的一些网络方法:

/**
	 * 检测系统版本升级
	 * @param vercode
	 * @return
	 */
	public CheckUpdataEntity checkVersion(String vercode){
		
		JSONObject j = HttpJsonRequesProxy.getInstance().getCheckVerReques(vercode);
		String jsonData=http://www.mamicode.com/null;>
/**
	 * 版本更新
	 * 
	 * @param token
	 * @param vercode
	 * @return
	 */
	public JSONObject getCheckVerReques(String vercode) {
		JSONObject title = getContextJsonObj("CheckUp");
		try {
			// 另外一个Json对象需要新建
			JSONObject mQrInfo = new JSONObject();
			mQrInfo.put("vercode", vercode);
			// 将用户和码值添加到整个Json中
			title.put("data", mQrInfo);

		} catch (JSONException e) {
			// 键为null或使用json不支持的数字格式(NaN, infinities)
			throw new RuntimeException(e);
		}

		return title;
	}

/**
	 * 主页
	 * 
	 * @param token
	 * @param firstopen
	 * @param mobiletype
	 * @param mobilesys
	 * @param vercode
	 * @return
	 */
	public JSONObject getHomePageReques(int firstopen,
			String mobiletype, String mobilesys, String vercode) {
		JSONObject title = getContextJsonObj("HomePage");
		try {
			// 另外一个Json对象需要新建
			JSONObject mQrInfo = new JSONObject();
			mQrInfo.put("firstopen", firstopen);
			mQrInfo.put("mobiletype", mobiletype);
			mQrInfo.put("mobilesys", mobilesys);
			mQrInfo.put("vercode", vercode);
			// 将用户和码值添加到整个Json中
			title.put("data", mQrInfo);

		} catch (JSONException e) {
			// 键为null或使用json不支持的数字格式(NaN, infinities)
			throw new RuntimeException(e);
		}

		return title;
	}

public String sendDataToServer(String url, String body) throws Exception {

		HttpPost httpPost = new HttpPost(url);
		ByteArrayEntity postdata = http://www.mamicode.com/new ByteArrayEntity(body.getBytes());>





安卓APP采用观察者模式实现检测版本更新