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

作者:袖梨 2022-06-25

本文实例为大家分享了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 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 parseJSON(String str) { 
 HashMap hashMap = new HashMap(); 
 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 parseXml(InputStream inputStream) { 
 HashMap hashMap = new HashMap(); 
 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; 
 } 
 } 
 }; 
} 

相关文章

精彩推荐