流程是这样,在远程服务器上存储了一个和android客户端类似的androidManifest.xml文件,对比客户端和服务器两个文件中的versionName,如果不一样,说明有新版本;
xml文件
:
<update> <version>90</version> <versionName>3.0.20</versionName> <name>fy.apk</name> <url>/res/a/fy.apk</url> </update>
public class UpdateService extends Service { private NotificationManager nm; private Notification notification; private RemoteViews views; private int notificationId = R.drawable.logo; UpdateManager um; private MyHandler myHandler; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); um = new UpdateManager(getApplicationContext()); notificationId = getResources().getIdentifier("updateId", "id", getPackageName());//应用下指定应用资源id myHandler = new MyHandler(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("tcp", "UpdateService-onStartCommand"); update(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } private void update() { String checkUpdateTime = PublicUtil.getSharedValue(this, PublicUtil.SYSTEM_SETTINGS, PublicUtil.CHECKUPDATAETIME, ""); String currentTime = PublicUtil.getDateTime().split(" ")[0]; if(checkUpdateTime.equals(currentTime))return; int type = um.getUpdateType(); if(type>=1) PublicUtil.putSharedValue(this, PublicUtil.SYSTEM_SETTINGS, PublicUtil.CHECKUPDATAETIME, currentTime); Log.i("tcp","type=====" + type); if (type >= 2) { updateId = type - 2; creatNotification(); } } void creatNotification() { nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notification = new Notification(); notification.icon = R.drawable.logo; try { notification.number = Integer.valueOf(mHashMap.get("number")); } catch (Exception e) { // TODO: handle exception } notification.flags = Notification.FLAG_AUTO_CANCEL; // notification.icon=android.R.drawable.stat_sys_download_done; notification.tickerText = getString(R.string.app_name) + "软件更新"; notification.when = System.currentTimeMillis(); notification.defaults = Notification.DEFAULT_LIGHTS; // 设置任务栏中下载进程显示的views views = new RemoteViews(getPackageName(), R.layout.update); Intent intent = new Intent(getApplicationContext(), UpdateActivity.class); System.out.println("==============" + updateId); intent.putExtra("updateId", updateId); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0); notification.setLatestEventInfo(this, "饭友", "饭友有新版本啦", contentIntent); // 将下载任务添加到任务栏中 notification.contentView = views; nm.notify(notificationId, notification); // nm. // 初始化下载任务内容views // Message message = myHandler.obtainMessage(2, 0); // myHandler.sendMessage(message); } class MyHandler extends Handler { // private Context context; // public MyHandler(Looper looper, Context c) { // super(looper); // this.context = c; // } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg != null) { switch (msg.what) { case 0: creatNotification(); break; case 1: break; case 2: notification.contentView = views; nm.notify(notificationId, notification); break; } } } } }
class UpdateManager{ private HashMap<String, String> mHashMap; /** * 检查软件是否有更新版本 * * @return */ public int getUpdateType() { // 获取当前软件版本 int versionCode = getVersionCode(mContext); String versionName = getVersionName(mContext); System.out.println("versionCode==" + versionCode); // 把version.xml放到网络上,然后获取文件信息 InputStream inStream = null; try { URL url = new URL(PublicUtil.getWebRoot()+"/res/a/fy-update.xml"); HttpURLConnection urlCon = (HttpURLConnection)url.openConnection(); urlCon.setConnectTimeout(3000); urlCon.setReadTimeout(3000); inStream = urlCon.getInputStream(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); return -1; } // // 获取当前软件版本 // int versionCode = getVersionCode(mContext); // // 把version.xml放到网络上,然后获取文件信息 // InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml"); // // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlService service = new ParseXmlService(); try { mHashMap = service.parseXml(inStream); } catch (Exception e) { e.printStackTrace(); } if (null != mHashMap) { int serviceCode = Integer.valueOf(mHashMap.get("version")); // 版本判断 if (serviceCode > versionCode) { try{ String updateType = mHashMap.get("versionName"); PublicVariable.serverVersion = updateType; String[] code_s = updateType.split("\\."); String[] code_c = versionName.split("\\."); int type = 0; if(Integer.valueOf(code_c[0])<Integer.valueOf(code_s[0])){ type = 3; }else if(Integer.valueOf(code_c[1])<Integer.valueOf(code_s[1])){ type = 2; }else if(Integer.valueOf(code_c[2])<Integer.valueOf(code_s[2])){ type = 1; } PublicUtil.putSharedValue(mContext, PublicUtil.SYSTEM_SETTINGS, PublicUtil.UPDATECODE, type>0?type+"-"+updateType:""); return type; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } return 0; } }
点击下拉更新跳转到具体activity
public class UpdateActivity extends Activity implements OnClickListener { Button btn_update, btn_cancel, btn_exit; TextView tv_title; ProgressBar pb; int updateType; String updateVersion; private String mSavePath; private HashMap<String, String> mHashMap; private int progress; private boolean cancelUpdate; Handler mHandler; /* 下载中 */ private static final int DOWNLOAD = 1; /* 下载结束 */ private static final int DOWNLOAD_FINISH = 2; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.update_layout); findViews(); prepareData(); initViews(); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.cancel(R.id.updateId); } void findViews() { btn_update = (Button) findViewById(R.id.btn_update); btn_cancel = (Button) findViewById(R.id.btn_cancel); btn_exit = (Button) findViewById(R.id.btn_exit); tv_title = (TextView) findViewById(R.id.tv_title); pb = (ProgressBar) findViewById(R.id.update_progress); } void prepareData() { String[] updateCode = PublicUtil.getSharedValue(this, PublicUtil.SYSTEM_SETTINGS, PublicUtil.UPDATECODE, "").split( "-"); updateType = updateCode[0].equals("3")?1:0; updateVersion = updateCode[1]; mHashMap = UpdateManager.mHashMap; mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { // 正在下载 case DOWNLOAD: // 设置进度条位置 pb.setProgress(progress); break; case DOWNLOAD_FINISH: // 安装文件 installApk(); pb.setVisibility(View.GONE); if (updateType == 0) finish(); break; default: break; } }; }; } void initViews() { btn_cancel.setVisibility(updateType == 0 ? View.VISIBLE : View.GONE); btn_exit.setVisibility(updateType == 1 ? View.VISIBLE : View.GONE); tv_title.setText("饭友更新至" + updateVersion + "正式版"); btn_cancel.setOnClickListener(this); btn_update.setOnClickListener(this); btn_exit.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn_cancel: cancelUpdate = true; finish(); break; case R.id.btn_update: pb.setVisibility(View.VISIBLE); v.setEnabled(false); btn_cancel.setText("取消更新"); new downloadApkThread().start(); break; case R.id.btn_exit: cancelUpdate = true; finish(); if (MoreActivity.activity != null) MoreActivity.activity.finish(); if (HomeTabActivity.activity != null) HomeTabActivity.activity.finish(); break; default: break; } } private class downloadApkThread extends Thread { @Override public void run() { try { // 判断SD卡是否存在,并且是否具有读写权限 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 获得存储卡的路径 String sdpath = Environment.getExternalStorageDirectory() + "/"; mSavePath = sdpath + "download"; URL url = new URL(PublicUtil.getWebRoot() + mHashMap.get("url")); // 创建连接 HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.connect(); // 获取文件大小 int length = conn.getContentLength(); // 创建输入流 InputStream is = conn.getInputStream(); File file = new File(mSavePath); // 判断文件目录是否存在 if (!file.exists()) { file.mkdir(); } File apkFile = new File(mSavePath, mHashMap.get("name")); FileOutputStream fos = new FileOutputStream(apkFile); int count = 0; // 缓存 byte buf[] = new byte[1024]; // 写入到文件中 do { int numread = is.read(buf); count += numread; // 计算进度条位置 progress = (int) (((float) count / length) * 100); // 更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if (numread <= 0) { // 下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } // 写入文件 fos.write(buf, 0, numread); } while (!cancelUpdate);// 点击取消就停止下载. fos.close(); is.close(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; /** * 安装APK文件 */ private void installApk() { File apkfile = new File(mSavePath, mHashMap.get("name")); if (!apkfile.exists()) { return; } // 通过Intent安装APK文件 Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); startActivity(i); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == event.KEYCODE_BACK) { return true; } return super.onKeyDown(keyCode, event); } }