一般app在进入主界面时会与后台服务器进行一次版本比较,后台服务器存放最新版本的app,如果用户当前的版本号与之不对应,则要提示用户进行更新。
在弹出的dialog的确定键代码里写入:
Intent it = new Intent(MainActivity.this, UpdateService.class);
startService(it);
bindService(it, conn, Context.BIND_AUTO_CREATE);
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
}
};
//在此处要对service进行停止操作
@Override
protected void onDestroy()
{
Intent it = new Intent(this, UpdateService.class);
stopService(it);
super.onDestroy();
}
下面是UpdateService,继承Service类,复写相关方法,注意要在application里配置该service.
private NotificationManager nm;
private Notification notification;
private File tempFile = null;
private boolean cancelUpdate = false;
private MyHandler myHandler;
private int download_precent = 0;
private RemoteViews views;
private int notificationId = 0;
重写onStartCommand方法。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
setUpNotification();//创建通知
myHandler = new MyHandler(Looper.myLooper(), this);
// 初始化下载任务内容views
Message message = myHandler.obtainMessage(3, 0);
myHandler.sendMessage(message);
// 启动线程开始执行下载任务
downFile("服务器存放最新apk的URL");
return super.onStartCommand(intent, flags, startId);
}
创建通知,布局可以自己定义,一般包含有图标,app名称和一个progressbar。这段代码的布局后面再贴出。
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notification = new Notification();
notification.icon = android.R.drawable.stat_sys_download;
// notification.icon=android.R.drawable.stat_sys_download_done;
// 放置在"正在运行"栏目中
notification.flags = Notification.FLAG_ONGOING_EVENT;
notification.tickerText = getString(R.string.app_name) + "更新";
notification.when = System.currentTimeMillis();
notification.defaults = Notification.DEFAULT_LIGHTS;
// 设置任务栏中下载进程显示的views
views = new RemoteViews(getPackageName(), R.layout.update_service);
notification.contentView = views;
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
notification.contentIntent = contentIntent;
// 将下载任务添加到任务栏中
nm.notify(notificationId, notification);
下载更新文件
注意,更新进度条的频率不能太高,不然容易造成卡顿。
private void downFile(final String url) {
new Thread() {
public void run() {
try {
HttpClient client = new DefaultHttpClient();
// params[0]代表连接的url
HttpGet get = new HttpGet(url);
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
InputStream is = entity.getContent();
if (is != null) {
File rootFile = new File(
Environment.getExternalStorageDirectory(),
"/QiLoo");
if (!rootFile.exists() && !rootFile.isDirectory())
rootFile.mkdir();
tempFile = new File(
Environment.getExternalStorageDirectory(),
"/QiLoo/"+ url.substring(url.lastIndexOf("/") + 1));
if (tempFile.exists())
tempFile.delete();
tempFile.createNewFile();
// 已读出流作为参数创建一个带有缓冲的输出流
BufferedInputStream bis = new BufferedInputStream(is);
// 创建一个新的写入流,讲读取到的图像数据写入到文件中
FileOutputStream fos = new FileOutputStream(tempFile);
// 已写入流作为参数创建一个带有缓冲的写入流
BufferedOutputStream bos = new BufferedOutputStream(fos);
int read;
long count = 0;
int precent = 0;
byte[] buffer = new byte[1024];
while ((read = bis.read(buffer)) != -1 && !cancelUpdate) {
bos.write(buffer, 0, read);
count += read;
precent = (int) (((double) count / length) * 100);
// 每下载完成5%就通知任务栏进行修改下载进度
if (precent - download_precent >= 5) {
download_precent = precent;
Message message = myHandler.obtainMessage(3,
precent);
myHandler.sendMessage(message);
}
}
bos.flush();
bos.close();
fos.flush();
fos.close();
is.close();
bis.close();
}
if (!cancelUpdate) {
Message message = myHandler.obtainMessage(2, tempFile);
myHandler.sendMessage(message);
} else {
tempFile.delete();
}
} catch (ClientProtocolException e) {
Message message = myHandler.obtainMessage(4, "下载更新文件失败");
myHandler.sendMessage(message);
} catch (IOException e) {
Message message = myHandler.obtainMessage(4, "下载更新文件失败");
myHandler.sendMessage(message);
} catch (Exception e) {
Message message = myHandler.obtainMessage(4, "下载更新文件失败");
myHandler.sendMessage(message);
}
}
}.start();
}
安装下载后的apk文件,这是固定写法
private void Instanll(File file, Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
context.startActivity(intent);
}
消息处理
class MyHandler extends Handler {
private Context context;
public MyHandler(Looper looper, Context c) {
super(looper);
this.context = c;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg != null) {
switch (msg.what) {
case 0:
Toast.makeText(context, msg.obj.toString(),
Toast.LENGTH_SHORT).show();
break;
case 1:
break;
case 2:
// 下载完成后清除所有下载信息,执行安装提示
download_precent = 0;
nm.cancel(notificationId);
Instanll((File) msg.obj, context);
// 停止掉当前的服务
stopSelf();
break;
case 3:
// 更新状态栏上的下载进度信息
views.setTextViewText(R.id.tvProcess, "已下载"
+ download_precent + "%");
views.setProgressBar(R.id.pbDownload, 100,
download_precent, false);
notification.contentView = views;
nm.notify(notificationId, notification);
break;
case 4:
nm.cancel(notificationId);
break;
}
}
}
}
最后贴出update的布局文件