您的位置:首页 > 移动开发 > Android开发

Android下载apk全量更新实现

2016-09-23 16:53 435 查看
自从Umeng的更新SDK不能用了之后,公司的Android更新都是自己实现的,于是自己实现了一下,大致流程如下:

1.获取本地版本号;

2.获取服务器的版本号,进行比较,如果服务器的版本号大于本地的版本号,责提示用户进行更新;

3.如果需要更新,就开启一个Service进行版本更新。

代码如下:

1.获取本地版本号:

private String getLocalVersion() {
try {
PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
String version = info.versionName;
return version;
} catch (Exception e) {
e.printStackTrace();
return "找不到版本号";
}
}


获取后台apk的版本号,大家自行实现;

用于版本更新的Service如下:

package com.ccclubs.pa.service;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.ccclubs.pa.R;
import com.ccclubs.pa.rxapp.App;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownloadApkService extends IntentService {

private static final String APP_NAME = "demo";

public static final String APP_FILE_PATH = File.separator + APP_NAME + File.separator;

// 文件存储
private File saveDir;
private File saveFile;
private String mUrl;

// 通知栏
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 RemoteViews contentView;
private Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case DOWNLOAD_COMPLETE:
// 当下载完毕,自动安装APK
installApk(App.getInstance(), saveFile);
notifyNotification(100, 100);
break;
case DOWNLOAD_FAIL:
notifyNotification(101,100);
break;
default:
break;
}
}
};

public DownloadApkService() {
super("com.demo.service.DownloadApkService");
}

@Override public int onStartCommand(Intent intent, int flags, int startId) {
mUrl = intent.getStringExtra("url");
createNotification();
return super.onStartCommand(intent, flags, startId);
}

@Override protected void onHandleIntent(Intent intent) {
Log.e("JP", "begin onHandleIntent() in " + this);
Message message = mHandler.obtainMessage();
message.what = DOWNLOAD_COMPLETE;
if (saveDir != null && !saveDir.exists()) {
saveDir.mkdirs();
}
if (saveFile != null && !saveFile.exists()) {
try {
saveFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
long downloadSize = downloadFile(mUrl, saveFile);
if (downloadSize > 0) {// 下载成功
mHandler.sendMessage(message);
}
} catch (Except
4000
ion ex) {
message.what = DOWNLOAD_FAIL;
mHandler.sendMessage(message);// 下载失败
}
}

private void createNotification() {
String downloadDir = APP_FILE_PATH;
apkUrl = mUrl;
// 如果有SD卡,则创建APK文件
if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment
.getExternalStorageState())) {

saveDir = new File(Environment.getExternalStorageDirectory(),
downloadDir);
saveFile = new File(saveDir.getPath(), "demo.apk");
}
this.updateNotificationManager = (NotificationManager) App.getInstance()
.getSystemService(App.getInstance().NOTIFICATION_SERVICE);
updateNotification = new Notification(
R.mipmap.ic_launcher,//应用的图标
"正在下载...",
System.currentTimeMillis());
updateNotification.flags = Notification.FLAG_AUTO_CANCEL;
// 设置下载过程中,点击通知栏,回到主界面
updateIntent = new Intent();
updatePendingIntent = PendingIntent.getActivity(App.getInstance(), 0,
updateIntent, 0);
updateNotification.contentIntent = updatePendingIntent;
/**自定义  Notification 的显示*/
contentView = new RemoteViews(getPackageName(), R.layout.layout_notification_update);
contentView.setProgressBar(R.id.progress, 100, 0, false);
contentView.setTextViewText(R.id.tv_progress, "0%");
updateNotification.contentView = contentView;
updateNotificationManager.notify(R.layout.layout_notification_update, updateNotification);
}

private void notifyNotification(long percent, long length) {
if(percent == length) {
contentView.setTextViewText(R.id.tv_txt, "下载完成");
} else if(percent > length) {
contentView.setTextViewText(R.id.tv_txt, "下载失败,请检查网络连接");
} else {
contentView.setTextViewText(R.id.tv_txt, "正在下载...");
}
contentView.setTextViewText(R.id.tv_progress, (percent * 100 / length) + "%");
contentView.setProgressBar(R.id.progress, (int) length, (int) percent, false);
updateNotification.contentView = contentView;
updateNotificationManager.notify(R.layout.layout_notification_update, updateNotification);
}

public long downloadFile(String downloadUrl, File saveFile) throws Exception {
int downloadCount = 0;
int currentSize = 0;
long totalSize = 0;
int updateTotalSize = 0;
int rate = 0;// 下载完成比例

HttpURLConnection httpConnection = null;
InputStream is = null;
FileOutputStream fos = null;

try {
URL url = new URL("http://" + downloadUrl);
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("User-Agent",
"PacificHttpClient");
if (currentSize > 0) {
httpConnection.setRequestProperty("RANGE", "bytes="
+ currentSize + "-");
}
httpConnection.setConnectTimeout(200000);
httpConnection.setReadTimeout(200000);
updateTotalSize = httpConnection.getContentLength();// 获取文件大小
if (httpConnection.getResponseCode() == 404) {
throw new Exception("fail!");
}
is = httpConnection.getInputStream();
fos = new FileOutputStream(saveFile, false);
byte buffer[] = new byte[1024 * 1024 * 3];
int readsize = 0;
while ((readsize = is.read(buffer)) != -1) {
fos.write(buffer, 0, readsize);

totalSize += readsize;// 已经下载的字节数
rate = (int) (totalSize * 100 / updateTotalSize);// 当前下载进度
// 为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次
if ((downloadCount == 0) || rate - 0 > downloadCount) {
downloadCount += 1;
notifyNotification(totalSize, httpConnection.getContentLength());
}
}
} finally {
if (httpConnection != null) {
httpConnection.disconnect();
}
if (is != null) {
is.close();
}
if (fos != null) {
fos.close();
}
}
return totalSize;
}

public static void installApk(Context context, File file) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
context.startActivity(intent);
}
}


xml文件代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:padding="5dp"
android:orientation="horizontal">

<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@mipmap/ic_launcher"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/tv_txt"
android:layout_centerVertical="true"
android:padding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在下载..."
/>
<TextView
android:id="@+id/tv_progress"
android:layout_alignParentRight="true"
android:padding="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0%"
/>
</RelativeLayout>

<ProgressBar
android:padding="5dp"
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

</LinearLayout>


记得把这个Service在AndroidManifest中进行注册。

首先这是一个IntentService,与普通的Service最大的区别就是,IntentService执行耗时的任务不需要新开一个线程,并且执行完任务后会自动销毁。其他的没什么好说的,都是一些非常简单的代码,相信大家都能读懂。

这里说一个小波折:就是我自己在用这个Service下载apk并进行安装的时候,都是没有问题的,但是同事用了我的Service居然老是出现apk解析失败的错误。我想要么就是apk没有下载完成,要么就是apk本身的错误。后来看了一下,原来后台给的链接是.html文件,所以我们下载的并不是apk文件,而是一个html网页,正常的链接应该是一个.apk文件,如果是html文件,我们应该调用浏览器打开这个链接来实现更新,或者用WebView把这个网页加载出来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 版本更新 Umeng