3月18日研究-App自动更新通知通知栏下载

一、首先看下项目Demo的包结构图:



主要有以下这几个文件:


1、MainActivity.java:项目的入口文件,一进这个Activity就会检查版本更新方法,如果本地版本小于服务器端的版本,就会跳出提示框提示是否下载,若点击更新下载就会启动UpdateService.java更新服务类进行更新操作。


2、MyApplication.java:继承Application类,进行一些初始化操作,比如获取本地版本号以及服务器版本号等操作。


3、Global.java:主要定义一些项目常量。


4、UpdateService.java:更新服务Service类,具体的更新操作都在这个类之中进行操作。


================================================================

1、MainActivity.java类:

package com.sutian.appupdatedemo;

import java.io.File;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;

import com.sutian.appupdatedemo.config.Global;
import com.sutian.appupdatedemo.service.UpdateService;

/**
 * 第一个启动页面中调用checkVersion方法进行版本更新检查
 * 
 * @author Jerry
 *
 */
public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 调用检查版本方法
		checkVersion();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	/**
	 * 检查版本更新
	 */
	public void checkVersion() {
		// 判断本地版本是否小于服务器端的版本号
		if (Global.localVersion < Global.serverVersion) {
			// 发现新版本,提示用户更新
			AlertDialog.Builder alert = new AlertDialog.Builder(this);
			alert.setTitle("软件升级")
					.setMessage("发现新版本,建议您立即更新使用.")
					.setPositiveButton("更新",
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// 开启更新服务UpdateService
									// 这里为了把update更好模块化,可以传一些updateService依赖的值
									// 如布局ID,资源ID,动态获取的标题,这里以app_name为例
									Intent updateIntent = new Intent(
											MainActivity.this,
											UpdateService.class);
									updateIntent.putExtra("titleId",
											R.string.app_name);
									startService(updateIntent);
								}
							})
					.setNegativeButton("取消",
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
								}
							});
			alert.create().show();
		} else {
			// 清理工作,略去
			cheanUpdateFile();
		}
	}

	/**
	 * 清理缓存的下载文件
	 */
	private void cheanUpdateFile() {
		File updateFile = new File(Global.downloadDir, getResources()
				.getString(R.string.app_name) + ".apk");
		if (updateFile.exists()) {
			// 当不需要的时候,清除之前的下载文件,避免浪费用户空间
			updateFile.delete();
		}
	}
}


2、MyApplication.java类:

package com.sutian.appupdatedemo;

import com.sutian.appupdatedemo.config.Global;

import android.app.Application;
import android.content.pm.PackageManager.NameNotFoundException;

/**
 * 自定义Application类
 * 
 * @author Jerry
 *
 */
public class MyApplication extends Application {
	@Override
	public void onCreate() {
		super.onCreate();
		//初始化全局变量
		initGlobal();
	}

	/**
	 * 初始化全局变量 实际工作中这个方法中serverVersion从服务器端获取,最好在启动画面的activity中执行
	 */
	public void initGlobal() {
		try {
			// 获取本地版本号
			Global.localVersion = getPackageManager().getPackageInfo(
					getPackageName(), 0).versionCode;
			// 假设服务端版本号为2,这个应该是要获取服务器端的版本号的,这里只是假设服务端版本号2
			Global.serverVersion = 2;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	
}

3、Global.java类:

package com.sutian.appupdatedemo.config;
/**
 * 常量類
 * @author Jerry
 *
 */
public class Global {
	//本地版本信息
    public static int localVersion = 0;
    //服務器版本信息
    public static int serverVersion = 0;
    //下載地址
    public static String downloadDir = "app/download/";
}

4、UpdateService.java类:

package com.sutian.appupdatedemo.service;

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

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import com.sutian.appupdatedemo.MainActivity;
import com.sutian.appupdatedemo.R;
import com.sutian.appupdatedemo.config.Global;

/**
 * 更新服务Service类
 * 
 * @author Jerry
 *
 */
public class UpdateService extends Service {
	// 标题
	private int titleId = 0;

	// 文件存储
	private File updateFile = null;
	// 下载文件的存放路径
	File updateDir;

	// 通知栏
	private NotificationManager updateNotificationManager = null;
	private Notification updateNotification = null;

	// 通知栏跳转Intent
	private Intent updateIntent = null;
	private PendingIntent updatePendingIntent = null;

	// 下载完成标记常量
	private final static int DOWNLOAD_COMPLETE = 0;
	private final static int DOWNLOAD_FAIL = 1;
	
	private Thread downThread;
	

	private Handler updateHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			// 下载成功
			case DOWNLOAD_COMPLETE:
				// 点击安装
				Uri uri = Uri.fromFile(updateFile);
				Intent installIntent = new Intent(Intent.ACTION_VIEW);
				installIntent.setDataAndType(uri,
						"application/vnd.android.package-archive");
				updatePendingIntent = PendingIntent.getActivity(
						UpdateService.this, 0, installIntent, 0);
				updateNotification.defaults = Notification.DEFAULT_SOUND;
				updateNotification.setLatestEventInfo(UpdateService.this,
						"腾讯QQ", "下载完成,点击安装", updatePendingIntent);
				updateNotificationManager.notify(0, updateNotification);
                
				//停止服务
				stopSelf();
				break;
			// 下载失败
			case DOWNLOAD_FAIL:
				 //下载失败,这里是看要提示重新下载还是另外做其他操作
//                updateNotification.setLatestEventInfo(UpdateService.this, "腾讯QQ", "下载失败,sorry", updatePendingIntent);
//                updateNotificationManager.notify(0, updateNotification);
                break;
			default:
				stopSelf();
			}
		}
	};

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

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// 获取传值
		titleId = intent.getIntExtra("titleId", 0);
		// 创建文件
		if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment
				.getExternalStorageState())) {
			// 组合下载地址
			updateDir = new File(Environment.getExternalStorageDirectory(),
					Global.downloadDir);			
		}else{
			//files目录
		    updateDir = getFilesDir();
		}
		// 拼凑下载文件文件名称
					updateFile = new File(updateDir.getPath(), getResources()
							.getString(titleId) + ".apk");
					
		this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		this.updateNotification = new Notification();

		// 设置下载过程中,点击通知栏,回到主界面
		updateIntent = new Intent(this, MainActivity.class);
		updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent,
				0);
		// 设置通知栏显示内容
		updateNotification.icon = R.drawable.ic_launcher;
		updateNotification.tickerText = "开始下载";
		updateNotification.setLatestEventInfo(this, "腾讯QQ", "0%",
				updatePendingIntent);
		// 发出通知
		updateNotificationManager.notify(0, updateNotification);

		// 开启一个新的线程下载,如果使用Service同步下载,会导致ANR问题,Service本身也会阻塞
		//new Thread(new updateRunnable()).start();// 这个是下载的重点,是下载的过程
		downThread=new Thread(new updateRunnable());
		downThread.start();
		return super.onStartCommand(intent, flags, startId);
	}

	/**
	 * 下载线程类
	 * 
	 * @author Jerry
	 *
	 */
	class updateRunnable implements Runnable {

		Message message = updateHandler.obtainMessage();

		@Override
		public void run() {
			message.what = DOWNLOAD_COMPLETE;
			try {
				// 文件目录是否存在
				if (!updateDir.exists()) {
					updateDir.mkdirs();
				}
				// 文件是否存在
				if (!updateFile.exists()) {
					updateFile.createNewFile();
				}
				// 下载函数
				// 增加权限
				long downloadSize = downloadUpdateFile(
						"http://apk.hiapk.com/appdown/com.tencent.qqpimsecure/54",
						updateFile);
				if (downloadSize > 0) {
					// 下载成功,发送消息
					updateHandler.sendMessage(message);
				}
			} catch (Exception e) {
				e.printStackTrace();
				// 设置失败标识
				message.what = DOWNLOAD_FAIL;
				// 下载失败,发送消息
				updateHandler.sendMessage(message);
			}
		}

		/**
		 * 下载文件
		 * 
		 * @param downloadUrl
		 *            下载路径
		 * @param saveFile
		 *            文件名称
		 * @return
		 * @throws Exception
		 */
		private long downloadUpdateFile(String downloadUrl, File saveFile)
				throws Exception {
			int downloadCount = 0;
			int currentSize = 0;
			long totalSize = 0;
			int updateTotalSize = 0;

			HttpURLConnection httpConnection = null;
			//输入流
			InputStream is = null;
			//文件输出流
			FileOutputStream fos = null;
			try {
				URL url = new URL(downloadUrl);
				httpConnection = (HttpURLConnection) url.openConnection();
				httpConnection.setRequestProperty("User-Agent",
						"PacificHttpClient");
				if (currentSize > 0) {
					httpConnection.setRequestProperty("RANGE", "bytes="
							+ currentSize + "-");
				}
				httpConnection.setConnectTimeout(10000);
				httpConnection.setReadTimeout(20000);
				updateTotalSize = httpConnection.getContentLength();
				if (httpConnection.getResponseCode() == 404) {
					throw new Exception("fail!");
				}
				is = httpConnection.getInputStream();
				fos = new FileOutputStream(saveFile, false);
				byte buffer[] = new byte[4096];
				int readsize = 0;
				while ((readsize = is.read(buffer)) > 0) {
					fos.write(buffer, 0, readsize);
					totalSize += readsize;
					// 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次
					if ((downloadCount == 0)
							|| (int) (totalSize * 100 / updateTotalSize) - 10 > downloadCount) {
						downloadCount += 10;
						updateNotification.setLatestEventInfo(
								UpdateService.this, "正在下载", (int) totalSize
										* 100 / updateTotalSize + "%",
								updatePendingIntent);
						updateNotificationManager.notify(0, updateNotification);
					}
				}
			} finally {
				if (httpConnection != null) {
					httpConnection.disconnect();
				}
				if (is != null) {
					is.close();
				}
				if (fos != null) {
					fos.close();
				}
			}
			return totalSize;
		}
	}

	@Override
	public void onDestroy() {
		downThread.destroy();
		downThread=null;
		super.onDestroy();
	}
}


源代码下载地址:http://download.csdn.net/detail/su_tianbiao/8512441


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值