Android App自动更新之通知栏下载

本文实例为大家分享了Android App自动更新通知栏下载的具体代码,供大家参考,具体内容如下

版本更新说明

这里有调用UpdateService启动服务检查下载安装包等

1. 文件下载,下完后写入到sdcard

2. 如何在通知栏上显示下载进度

3. 下载完毕自动安装

4. 如何判断是否有新版本

版本更新的主类

package com.wei.update; 

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory; 

import com.wei.util.MyApplication; 

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Handler; 

/**
 * 版本更新主类,这里有调用UpdateService启动服务检查下载安装包等 1. 文件下载,下完后写入到sdcard 2. 如何在通知栏上显示下载进度
 * 3. 下载完毕自动安装 4. 如何判断是否有新版本
 *
 * @author david
 */
public class UpdateManager {
 private static String packageName;// = "com.yipinzhe"; // 应用的包名
 private static String jsonUrl = "version.txt"; // JSON版本文件URL
 private static String xmlUrl = "version.xml"; // XML版本文件URL
 private static final String DOWNLOAD_DIR = "/"; // 应用下载后保存的子目录 

 private Context mContext;
 HashMap<String, String> mHashMap;// 保存解析的XML信息
 int versionCode, isNew; 

 public UpdateManager(Context context) {
 this.mContext = context;
 packageName = context.getPackageName();
 jsonUrl = MyApplication.site + jsonUrl;
 xmlUrl = MyApplication.site + xmlUrl;
 checkVersion();
 } 

 Handler checkHandler = new Handler() {
 @Override
 public void handleMessage(android.os.Message msg) {
 if (msg.what == 1) {
 // 发现新版本,提示用户更新
 StringBuffer message = new StringBuffer();
 message.append(mHashMap.get("note").replace("|", "\n"));
 AlertDialog.Builder alert = new AlertDialog.Builder(mContext);
 alert.setTitle("软件升级")
  .setMessage(message.toString())
  .setPositiveButton("更新",
  new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog,
   int which) {
   // 开启更新服务UpdateService
   System.out.println("你点击了更新");
   Intent updateIntent = new Intent(
   mContext, UpdateService.class);
   /**
   * updateIntent.putExtra("downloadDir",
   * DOWNLOAD_DIR);
   * updateIntent.putExtra("apkUrl",
   * mHashMap.get("url"));
   */
   mContext.startService(updateIntent);
   }
  })
  .setNegativeButton("取消",
  new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog,
   int which) {
   dialog.dismiss();
   }
  });
 alert.create().show();
 }
 };
 }; 

 /**
 *检查是否有新版本
 */
 public void checkVersion() {
 try {
 // 获取软件版本号,对应AndroidManifest.xml下android:versionCode
 versionCode = mContext.getPackageManager().getPackageInfo(
  packageName, 0).versionCode;
 } catch (NameNotFoundException e) {
 e.printStackTrace();
 } 

 new Thread() {
 @Override
 public void run() {
 String result = null;
 /**
  * try { //如果服务器端是JSON文本文件 result =
  * MyApplication.handleGet(jsonUrl); if (result != null) {
  * mHashMap = parseJSON(result); } } catch (Exception e1) {
  * e1.printStackTrace(); }
  */ 

 InputStream inStream = null;
 try {
  // 本机XML文件
  inStream = UpdateManager.class.getClassLoader().getResourceAsStream("version.xml");
  // 如果服务器端是XML文件
  inStream = new URL(xmlUrl).openConnection().getInputStream();
  if (inStream != null)
  mHashMap = parseXml(inStream);
 } catch (Exception e1) {
  e1.printStackTrace();
 }
 if (mHashMap != null) {
  int serviceCode = Integer.valueOf(mHashMap.get("version"));
  if (serviceCode > versionCode) {// 版本判断,返回true则有新版本
  isNew = 1;
  }
 }
 checkHandler.sendEmptyMessage(isNew);
 };
 }.start();
 } 

 /**
 *解析服务器端的JSON版本文件
 */
 public HashMap<String, String> parseJSON(String str) {
 HashMap<String, String> hashMap = new HashMap<String, String>();
 try {
 JSONObject obj = new JSONObject(str);
 hashMap.put("version", obj.getString("version"));
 hashMap.put("name", obj.getString("name"));
 hashMap.put("url", obj.getString("url"));
 hashMap.put("note", obj.getString("note"));
 } catch (JSONException e) {
 e.printStackTrace();
 }
 return hashMap;
 } 

 /**
 *解析服务器端的XML版本文件
 */
 public HashMap<String, String> parseXml(InputStream inputStream) {
 HashMap<String, String> hashMap = new HashMap<String, String>();
 try {
 XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
 parser.setInput(inputStream, "GBK");//设置数据源编码
 int eventCode = parser.getEventType();//获取事件类型
 while(eventCode != XmlPullParser.END_DOCUMENT) {
 System.out.println("循环开始");
 switch (eventCode){
  case XmlPullParser.START_DOCUMENT: //开始读取XML文档
  System.out.println("START_DOCUMENT");
  break;
  case XmlPullParser.START_TAG://开始读取某个标签
  if("version".equals(parser.getName())) {
  hashMap.put(parser.getName(), parser.nextText());
  } else if("name".equals(parser.getName())) {
  hashMap.put(parser.getName(), parser.nextText());
  } else if("url".equals(parser.getName())) {
  hashMap.put(parser.getName(), parser.nextText());
  } else if("note".equals(parser.getName())) {
  hashMap.put(parser.getName(), parser.nextText());
  }
  break;
  case XmlPullParser.END_TAG:
  break;
 }
 eventCode = parser.next();//继续读取下一个元素节点,并获取事件码 

 }
 System.out.println(hashMap.get("version"));
 } catch(Exception e) { 

 }
 return hashMap; 

 /**
 *try {
 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 DocumentBuilder builder = factory.newDocumentBuilder();
 Document document = builder.parse(inStream);
 Element root = document.getDocumentElement();//获取根节点
 NodeList childNodes = root.getChildNodes();//获得所有子节点,然后遍历
 for (int j = 0; j < childNodes.getLength(); j++) {
 Node childNode = childNodes.item(j);
 if (childNode.getNodeType() == Node.ELEMENT_NODE) {
  Element childElement = (Element) childNode;
  if ("version".equals(childElement.getNodeName())) {
  hashMap.put("version", childElement.getFirstChild()
  .getNodeValue());
  }
  else if (("name".equals(childElement.getNodeName()))) {
  hashMap.put("name", childElement.getFirstChild()
  .getNodeValue());
  }
  else if (("url".equals(childElement.getNodeName()))) {
  hashMap.put("url", childElement.getFirstChild()
  .getNodeValue());
  } else if (("note".equals(childElement.getNodeName()))) {
  hashMap.put("note", childElement.getFirstChild()
  .getNodeValue());
  }
 }
 }
 } catch (Exception e) {
 e.printStackTrace();
 }*/ 

 }
} 

版本更新的服务类

package com.wei.update; 

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

import com.wei.util.MyApplication;
import com.wei.wotao.R; 

//import android.annotation.SuppressLint;
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 android.view.View;
import android.widget.RemoteViews; 

/**
 * 下载安装包的服务类
 * @author david
 */ 

public class UpdateService extends Service { 

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

 // 通知栏
 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; 

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
 System.out.println("onStartCommand");
 contentView = new RemoteViews(getPackageName(), R.layout.activity_app_update);
 // 获取传值
 String downloadDir = intent.getStringExtra("downloadDir");
 apkUrl = MyApplication.site+intent.getStringExtra("apkUrl");
 // 如果有SD卡,则创建APK文件
 if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment
 .getExternalStorageState())) { 

 saveDir = new File(Environment.getExternalStorageDirectory(),
  downloadDir);
 saveFile = new File(saveDir.getPath(), getResources()
  .getString(R.string.app_name) + ".apk");
 } 

 this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 this.updateNotification = new Notification(); 

 // 设置下载过程中,点击通知栏,回到主界面
 updateIntent = new Intent();
 updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent, 0);
 // 设置通知栏显示内容
 updateNotification.icon = R.drawable.icon_info;
 updateNotification.tickerText = "开始下载";
 updateNotification.contentView.setProgressBar(R.id.progressBar1, 100, 0, true);
 updateNotification.setLatestEventInfo(this,
 getResources().getString(R.string.app_name), "0%",
 updatePendingIntent);
 // 发出通知
 updateNotificationManager.notify(0, updateNotification);
 new Thread(new DownloadThread()).start();
 return super.onStartCommand(intent, flags, startId);
 } 

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

 /**
 *下载的线程
 */
 private class DownloadThread implements Runnable {
 Message message = updateHandler.obtainMessage(); 

 public void run() {
 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(apkUrl, saveFile);
 if (downloadSize > 0) {// 下载成功
  updateHandler.sendMessage(message);
 }
 } catch (Exception ex) {
 ex.printStackTrace();
 message.what = DOWNLOAD_FAIL;
 updateHandler.sendMessage(message);// 下载失败
 }
 } 

 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(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;
  updateNotification.setLatestEventInfo(
  UpdateService.this, "正在下载", rate + "%",
  updatePendingIntent);//设置通知的内容、标题等
  updateNotification.contentView.setProgressBar(R.id.progressBar1, 100, rate, true);
  updateNotificationManager.notify(0, updateNotification);//把通知发布出去
  } 

 }
 } finally {
 if (httpConnection != null) {
  httpConnection.disconnect();
 }
 if (is != null) {
  is.close();
 }
 if (fos != null) {
  fos.close();
 }
 }
 return totalSize;
 }
 } 

 private Handler updateHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
 switch (msg.what) {
 case DOWNLOAD_COMPLETE:
 //当下载完毕,自动安装APK(ps,打电话 发短信的启动界面工作)
 Uri uri = Uri.fromFile(saveFile);//根据File获得安装包的资源定位符
 Intent installIntent = new Intent(Intent.ACTION_VIEW);//设置Action
 installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//新的Activity会在一个新任务打开,而不是在原先的任务栈
 installIntent.setDataAndType(uri, "application/vnd.android.package-archive");//设置URI的数据类型
 startActivity(installIntent);//把打包的Intent传递给startActivity 

 //当下载完毕,更新通知栏,且当点击通知栏时,安装APK
 updatePendingIntent = PendingIntent.getActivity(UpdateService.this, 0, installIntent, 0);
 updateNotification.defaults = Notification.DEFAULT_SOUND;// 铃声提醒
 updateNotification.setLatestEventInfo(UpdateService.this, getResources().getString(R.string.app_name),
  "下载完成,点击安装", updatePendingIntent);
 updateNotificationManager.notify(0, updateNotification); 

 // 停止服务
 stopService(updateIntent);
 break;
 case DOWNLOAD_FAIL:
 // 下载失败
 updateNotification.setLatestEventInfo(UpdateService.this,
  getResources().getString(R.string.app_name),
  "下载失败,网络连接超时", updatePendingIntent);
 updateNotificationManager.notify(0, updateNotification);
 break;
 default:
 stopService(updateIntent);
 break;
 }
 }
 };
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android如何实现APP自动更新

    先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP到各大应用市场的工作量就已经很大了,好不容易我们把APP都上传完了,突然发现一个会导致应用闪退的小Bug,这时那个崩溃啊,明明不是很大的改动,难道我们还要再去重新去把各大应用市场的版本再上传更新一次?相信我,运营人员肯定会弄死你的!! 有问题,自然就会有解决问题的方案,因此我们就会想到如果在APP里

  • Android软件自动更新实现代码

    如何实现软件自动更新,下面是具体实例: 效果图: 具体步骤: 1.在服务器上部署更新所用的xml文件:version.xml <update> <version>2</version> <name>baiduxinwen.apk</name> <url>http://gdown.baidu.com/data/wisegame/e5f5c3b8e59401c8/baiduxinwen.apk</url> </updat

  • Android应用自动更新功能实现的方法

    本文给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出版本到最后精品,这个过程需要版本不停的更新,那么如何让用户第一时间获取最新的应用安装包呢?那么就要求我们从第一个版本就要实现升级模块这一功能. 自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语:最新版本的url等).然后我们给出提示框,用户点击开始下载,下载完成开始覆盖安装程序,这样用户的应

  • Android程序自动更新功能模块的实现方法【附完整demo源码下载】

    本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更新模块检测服务器上存放的版本号跟当前程序的版本号如果大于当前版本号,弹出更新对话框,如果用户选择更新,则显示当前更新状态,然后替换当前程序. 程序调用版本更新检测: private UpdateManager updateMan; private ProgressDialog updateProgr

  • Android App实现应用内部自动更新的最基本方法示例

    这只是初步的实现,并没有加入自动编译等功能.需要手动更改更新的xml文件和最新的apk.    共涉及到四个文件! 一.客户端 AndroidUpdateTestActivity:程序首页 main.xml:首页布局 Update:更新类 softupdate_progress:更新等待界面 Updage package majier.test; import java.io.File; import java.io.FileOutputStream; import java.io.IOExce

  • Android7.0自动更新适配 包解析异常

    在Android7.0的手机上,自动更新的时候出现包解析异常,在其他的手机上没有这个问题. 原因: Android7.0引入私有目录被限制访问和StrictMode API .私有目录被限制访问是指在Android7.0中为了提高应用的安全性,在7.0上应用私有目录将被限制访问.StrictMode API是指禁止向你的应用外公开 file:// URI. 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,则会报出异常. 解决办法: 第一步:在AndroidManif

  • Android应用APP自动更新功能的代码实现

    由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必要给我们的Android应用增加自动更新的功能. 既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息: <update> <version>2</version> <name>baidu

  • 浅析Android手机卫士关闭自动更新

    推荐阅读: 浅析Android手机卫士自定义控件的属性 保存数据的四种方式,网络,广播提供者,SharedPreferences,数据库 获取SharedPreferences对象,通过getSharedPreferences()方法,参数:名称,模式 例如config,MODE_PRIVATE 调用SharedPreferences对象的edit()方法,得到Editor对象 调用Editor对象的putBoolean()方法,放入布尔数据,参数:键值对,"update" false

  • Android实现APP自动更新功能

    现在一般的android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.该小程序实现的就是这个功能. 该小程序的特点是,当有更新时,会弹出一个提示框,点击确定,则在通知来创建一个进度条进行下载,点击取消,则取消更新. 以下是详细代码: 1.创建布局文件notification_item.xml,用于在通知栏生成一个进度条和下载图标. <?xml version="1.0" encoding="utf-8"?>

  • Android编程实现应用自动更新、下载、安装的方法

    本文实例讲述了Android编程实现应用自动更新.下载.安装的方法.分享给大家供大家参考,具体如下: 我们看到很多Android应用都具有自动更新功能,用户一键就可以完成软件的升级更新.得益于Android系统的软件包管理和安装机制,这一功能实现起来相当简单,下面我们就来实践一下. 1. 准备知识 在AndroidManifest.xml里定义了每个Android apk的版本标识: <manifest xmlns:android="http://schemas.android.com/a

随机推荐