android代码实现app升级
android 在APP需要更新的时候是如何更新的呢?
升级分为普通升级和增量升级,增量升级是差分升级,类似于把补丁,把新的特性的文件下载到客户端,在在客户端上进行组装,而不需要把整个安装包重新下载到客户端,减少流量的传输;
普通升级就是把整个apk文件下载到客户端安装,替换掉旧的app应用
1. 如何区分app版本需要升级?
谷歌建议我们使用android清单文件里面的配置区分:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test1"
android:versionCode="1"
android:versionName="1.0" >
versionCode用于我们app的版本区分,而versionName则用于显示给用户,用户查看版本
2. 区分版本需要升级后,如何下载新版本文件?
开启一个后台服务Service,使用http协议下载新版本apk,这里需要注意两点:(1)版本下载需要在service里面开启新的线程下载,防止下载任务占用时间太长造成anr(2)下载的apk要保存到sdk上,不能存在内存中占用资源,防止内存溢出
下面是具体的升级步骤:
1. 创建一个全局类,里面新建一些全局变量,主要包含以下:
local_version = getPackageManager().getPackageInfo(getPackageName() ,0).versionCode; //读取清单文件中的versionCode
service_version = 从服务器上获取版本
downloadURL = "***";
2. 在Activity中进行版本检测,local_version < service_version,则提示用户进行下载
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.ic_launcher)
.setTitle("新版本提示")
.setMessage("是否需要更新")
.setNegativeButton("确定", new android.content.DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this,UpdateService.class);
startService(intent);
}
})
.setNegativeButton("取消", null).show();
3. apk下载任务后台service执行,消息栏实时通知下载进度,开启新线程下载,并且存包于sd卡;handler用于下载任务完成后通知安装
public class UpdateService extends Service{
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public Handler hander = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch(msg.what){
case 0: //下载失败
Toast.makeText(getApplicationContext(), "下载失败...", Toast.LENGTH_LONG).show();
break;
case 1: //下载成功 提示安装
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package_archive");
startActivity(intent);
break;
}
}
};
private File file;
private String filename = "new.apk";
private NotificationManager notiManager;
private Notification notification;
private PendingIntent pIntent;
//检查是否有sd卡,并配置好存储的文件和通知
public void preDownload(){
//初始化通知
notiManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notification = new Notification();
Intent intent = new Intent(this,MainActivity.class);
pIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification.setLatestEventInfo(this, "下载中...", "0%", pIntent);
notiManager.notify(1, notification);
//sd卡是否可写
try {
if(android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())){
file = new File(Environment.getExternalStorageDirectory(),filename);
if(!file.exists()){
file.createNewFile();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//开启线程下载
new Thread(new UpdateTask(file)).start();
}
private class UpdateTask implements Runnable{
private File f;
Message msg;
public UpdateTask(File f){
this.f = f;
msg = new Message();
}
@Override
public void run() {
// TODO Auto-generated method stub
HttpURLConnection httpConnection = null;
FileOutputStream os = null;
try {
msg.what = 1; //1 == download success 0 == download failed
//网络下载
URL url = new URL("www.baidu.com");
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setConnectTimeout(5000);
if(httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
InputStream in = httpConnection.getInputStream();
os = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int currCount = 0;
int count = 0;
int totalcount = httpConnection.getContentLength();
while((count = in.read(buffer)) != -1){
int countRate = 0;
os.write(buffer, 0, count);
currCount += count;
//实时消息栏显示下载进度 每增加10%显示一次,防止显示过快占用显示资源
if((currCount*100)/totalcount > countRate || countRate == 0){
countRate += 10;
notification.setLatestEventInfo(UpdateService.this, "下载中...", countRate+"%", pIntent);
notiManager.notify(1, notification);
}
}
msg.what = 1;
}else
msg.what = 0; //失败
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
msg.what = 0;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
msg.what = 0;
}finally{
if(os != null){
try {
os = null;
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(httpConnection != null){
httpConnection = null;
httpConnection.disconnect();
}
hander.sendMessage(msg);
}
}
}
}