Android下载apk全量更新实现
2016-09-23 16:53
435 查看
自从Umeng的更新SDK不能用了之后,公司的Android更新都是自己实现的,于是自己实现了一下,大致流程如下:
1.获取本地版本号;
2.获取服务器的版本号,进行比较,如果服务器的版本号大于本地的版本号,责提示用户进行更新;
3.如果需要更新,就开启一个Service进行版本更新。
代码如下:
1.获取本地版本号:
获取后台apk的版本号,大家自行实现;
用于版本更新的Service如下:
xml文件代码
记得把这个Service在AndroidManifest中进行注册。
首先这是一个IntentService,与普通的Service最大的区别就是,IntentService执行耗时的任务不需要新开一个线程,并且执行完任务后会自动销毁。其他的没什么好说的,都是一些非常简单的代码,相信大家都能读懂。
这里说一个小波折:就是我自己在用这个Service下载apk并进行安装的时候,都是没有问题的,但是同事用了我的Service居然老是出现apk解析失败的错误。我想要么就是apk没有下载完成,要么就是apk本身的错误。后来看了一下,原来后台给的链接是.html文件,所以我们下载的并不是apk文件,而是一个html网页,正常的链接应该是一个.apk文件,如果是html文件,我们应该调用浏览器打开这个链接来实现更新,或者用WebView把这个网页加载出来。
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 中tomcat搭建本地服务器 实现apk更新下载
- Android实现检查并下载APK更新、安装APK及获取网络信息的方法
- 使用CrossApp实现版本更新管理(iOS端给AppStore链接,android端下载apk并替换)
- Android 一步一步实现版本自动更新(第二步 下载和安装apk)
- tomcat搭建本地服务器 实现apk更新下载(Android )
- Android客户端apk自动检测更新自动下载自动安装的实现方法
- android 利用dwonLoadManager 实现apk下载更新
- android利用service实现下载apk自动更新功能
- Android 中tomcat搭建本地服务器 实现apk更新下载
- 转载 :Android apk的安装、卸载、更新升级(通过Eclipse实现静默安装)
- Android APK多线程下载自升级实现
- Android基于IIS的APK下载(二)显示更新列表
- Android开发实践经验谈:如何让各式手机浏览器可以直接下载apk安装文件且实现自动安装APP
- Android应用自动更新功能的实现!!!软件更新,自动下载,安装
- Android实现应用下载并自动安装apk包
- Android实现应用下载并自动安装apk包
- Android如何实现文件下载并自动安装apk包!!!
- (转载)Android实现应用下载并自动安装apk包
- Android实现应用下载并自动安装apk包
- Android 实现apk文件下载并自动安装