package com.zytk.net.update;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;
/**
* @author sgz
* @date 2014-05-17实现软件更新的管理类:手动联网检测,通知栏显示下载进度
*/
public class UpdateManager {
private static final int CHECK_UPDATE_ERR = 0x00;// 检查更新时联网错误
private static final int CHECK_UPDATE_TIMEOUT = 0x02;// 检查更新时联网超时
private static final int CHECK_UPDATE_OK = 0x01;// 检查更新读取远程版本号码成功
private static final int DOWNLOAD_ING = 0x11;// 下载中...
private static final int DOWNLOAD_FINISH = 0x12;// 下载完成
private static final int DOWNLOAD_ERR = 0x13;// 有错误发生
private final static int NOTIFICATION_ID = 0x10000;//用于下载进度显示的通知栏通知ID
HashMap<String, String> mHashMap;// 保存解析的XML信息
private String mSavePath;// 下载保存路径
private int progressCnt=0;// 记录进度条数量
private boolean cancelDownload = false;//是否取消下载
private NotificationManager manager;
private Notification notif;
private Context mContext;// 上下文对象
private Handler mHandler;
private File file=null;
/**构造函数*/
public UpdateManager(Context context) {
this.mContext = context;
mHandler = new DownloadHandler();
}
/** 下载用的自定义handler */
private class DownloadHandler extends Handler {
public void handleMessage(Message msg)
{
switch (msg.what) {
case CHECK_UPDATE_ERR:
Toast.makeText(mContext, "联网发生错误", Toast.LENGTH_LONG).show();
break;
case CHECK_UPDATE_TIMEOUT:
Toast.makeText(mContext, "联网超时,请保证网络畅通情况下重试", Toast.LENGTH_LONG).show();
break;
case CHECK_UPDATE_OK:
Log.d("handler","开始对比版本号");
int versionCode = ApkRunEnvParams.getAppVersionCode(mContext);// 获取本地软件版本
int serviceCode = Integer.valueOf(mHashMap.get("version").trim());// 服务器版本号
if (serviceCode > versionCode)// 版本判断// 若有软件更新信息
showNoticeDialog();// 显示提示对话框
else
Toast.makeText(mContext, "无软件更新信息", Toast.LENGTH_SHORT).show();
break;
case DOWNLOAD_ING:
notif.contentView.setTextViewText(R.id.content_view_text1, ApkRunEnvParams.downLoadAppName+"下载进度"+progressCnt+"%");
notif.contentView.setProgressBar(R.id.content_view_progress, 100, progressCnt, false);
manager.notify(NOTIFICATION_ID, notif);
//System.out.println(progressCnt);// 更新进度条
break;
case DOWNLOAD_FINISH:// 下载完成
Toast.makeText(mContext, "下载完成", Toast.LENGTH_SHORT).show();
addIconToNoticeBar(android.R.drawable.stat_sys_download_done,true);
showInstallDialog();// 询问是否安装文件
break;
case DOWNLOAD_ERR:// 发生错误
Toast.makeText(mContext, "下载时发生错误或取消", Toast.LENGTH_SHORT).show();
deleteIconToNoticeBar();
if(file!=null)file.delete();// 删除已经下载文件
break;
default:
break;
}
};
}
/**检测软件更新:启动联网线程读取服务器文件版本信息所在url*/
public void checkUpdate() {
cancelDownload = false;//是否取消下载
new Thread(new HttpCheckUpdate()).start();
}
/**若上述检测方法联网读取服务器端版本号码成功,则弹出对话框是否执行下载更新操作;联网失败直接Toast出联网失败信息*/
private void showNoticeDialog() {
// 构造对话框
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("系统提示");
builder.setMessage("检测到有新的版本,是否立即更新?\n" + mHashMap.get("desc").trim().replace("#n", "\n").replace("#N", "\n"));
// 更新
builder.setPositiveButton("立即更新", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
addIconToNoticeBar(android.R.drawable.stat_sys_download,false);
//开启线程下载文件
new DownloadFileThread().start();
}
});
// 稍后更新
builder.setNegativeButton("暂不更新", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
Dialog noticeDialog = builder.create();
noticeDialog.show();
}
/**0.联网线程:联网检测是否有新版本软件*/
private class HttpCheckUpdate implements Runnable {
public synchronized void HttpPost() {
Message msg = new Message();
try {
String xmlString = "";
String httpVersionXmlPath = ApkRunEnvParams.apkVersionUrl;// 远程版本信息文件url
HttpUriRequest request = new HttpGet(httpVersionXmlPath);
HttpResponse response = new DefaultHttpClient().execute(request);
HttpEntity ent = response.getEntity();
int status = response.getStatusLine().getStatusCode();
if (status == HttpStatus.SC_OK) {
String result = EntityUtils.toString(ent);
result = new String(result.getBytes(), "UTF-8");
// result = new String(result.getBytes("ISO-8859-1"), "UTF-8");//某些服务器需要此配置转码
xmlString = result;
xmlString = xmlString.replaceAll("\n|\t|\r", "");
Log.d("检测下载xml字符串:", xmlString);
mHashMap = ParseXmlService.getFindNodeValue(xmlString);
if (null != mHashMap) {
msg.what = CHECK_UPDATE_OK;//分析远程服务器版本文件url成功
Log.d("分析远程服务器版本文件url成功:", xmlString);
}
else
msg.what = CHECK_UPDATE_ERR;
}
else
msg.what = CHECK_UPDATE_ERR;
} catch (IOException e) {
msg.what = CHECK_UPDATE_TIMEOUT;
e.printStackTrace();
}
mHandler.sendMessage(msg);
}
@Override
public void run() {
HttpPost();
}
}
/**1.下载文件线程:开始联网下载指定文件*/
private class DownloadFileThread extends Thread {
@Override
public void run() {
try {
// 判断SD卡是否存在,并且是否具有读写权限
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File SDCardRoot = Environment.getExternalStorageDirectory();// 获取SDCard的路径
mSavePath = SDCardRoot + "/download";
File fileDir = new File(mSavePath);
if (!fileDir.exists())// 如果文件夹不存在,则新建之
{
fileDir.mkdir();
}
URL url = new URL(mHashMap.get("url"));
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
if (ApkRunEnvParams.getSDKVersionNumber() < 14)
urlConnection.setDoOutput(true);
urlConnection.connect();
file = new File(mSavePath, mHashMap.get("name"));//保存文件名
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream inputStream = urlConnection.getInputStream();
int totalSize = urlConnection.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[1024*8];
int bufferLength = 0; //缓存大小定义
int tmpProgressCnt=0;
while (((bufferLength = inputStream.read(buffer)) > 0) && !cancelDownload) {
fileOutput.write(buffer, 0, bufferLength);
downloadedSize += bufferLength;
progressCnt = (int) (100 * ((float) downloadedSize / (float) totalSize));
if(progressCnt>tmpProgressCnt)//防止频繁通知系统资源紧张而卡住
mHandler.sendEmptyMessage(DOWNLOAD_ING);
tmpProgressCnt=progressCnt;
}
fileOutput.close();
inputStream.close();
if (!cancelDownload) {
Log.d("DOWNLOAD_FINISH","发送完成消息");
mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
}
else
// 若为取消按钮,则清除没有下载完成的文件
{
mHandler.sendEmptyMessage(DOWNLOAD_ERR);
}
}
} catch (MalformedURLException e) {
Log.e("MalformedURLException发生异常",e.toString());
Message msg1 = mHandler.obtainMessage();
msg1.what = DOWNLOAD_ERR;
mHandler.sendMessage(msg1);
} catch (IOException e) {
Log.e("IOException发生异常",e.toString());
Message msg1 = mHandler.obtainMessage();
msg1.what = DOWNLOAD_ERR;
mHandler.sendMessage(msg1);
}
}
}
/**
* 是否进行安装
*/
private void showInstallDialog() {
if(ApkRunEnvParams.ifInstall){
deleteIconToNoticeBar();
installApk();//直接安装
}
else {//询问是否安装
AlertDialog.Builder builder = new Builder(mContext);
builder.setTitle("安装提示");
builder.setMessage("下载完成,是否立即安装?");
builder.setPositiveButton("立即安装", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
deleteIconToNoticeBar();
installApk();
}
});
builder.setNegativeButton("暂不安装", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
Dialog noticeDialog = builder.create();
noticeDialog.show();
}
}
/**安装apk文件*/
private void installApk(){
//--------------------------------------------- 执行安装
File apkfile = new File(mSavePath, mHashMap.get("name"));
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
mContext.startActivity(i);
}
/**
* 如果没有从状态栏中删除ICON,且继续调用addIconToStatusbar,
* 则不会有任何变化。如果,将notification中的resId设置不同的图标,则会显示不同
* 的图标:showInstall参数用于指定是否提示下载完成二修改下载通知栏界面显示
*/
private void addIconToNoticeBar(int resId,boolean showInstall){
Log.w("", "执行通知栏显示");
manager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notif = new Notification();
notif.icon =resId;
notif.tickerText = "开始下载...";
//通知栏显示所用的布局文件
notif.contentView = new RemoteViews(mContext.getPackageName(), R.layout.content_view);
if(showInstall){
notif.contentView.setViewVisibility(R.id.content_view_text2,View.VISIBLE);
notif.contentView.setViewVisibility(R.id.content_view_progress,View.GONE);
notif.defaults = Notification.DEFAULT_SOUND;//铃声提醒
}
manager.notify(NOTIFICATION_ID, notif);
}
/**删除下载通知栏图标*/
private void deleteIconToNoticeBar(){
//manager.cancelAll();
manager.cancel(NOTIFICATION_ID);//删除通知栏图标
}
}
本网原创,转载请注明出处。http://www.dbmng.com/Article_695.html