在主线程创建一个线程 判断是否更新
Runnable runnable = new Runnable() { @Override public void run() { //从资源文件获取服务器 地址 String path = getResources().getString(R.string.serverurl); info = SmallTools.getUpdateInfo(path); int verCode = SmallTools.getVerCode(); if(info.getVersionCode()>verCode) { //更新 Message msg = new Message(); msg.what = UPDATE_TRUE; mHandler.sendMessage(msg); } } }; new Thread(runnable).start();
/** * 获取版本号 * * @return */ public static int getVerCode() { int verCode = -1; try { verCode = SellerApplication.getOverAllContext().getPackageManager().getPackageInfo("包名", 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return verCode; }
/** * 获取更新对象 * @param path 服务器xml地址 * @return */ public static UpdateInfo getUpdateInfo(String path){ try { URL url=new URL(path); //创建连接对象 HttpURLConnection conn= (HttpURLConnection) url.openConnection(); //设置超时时间 conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); //如果连接成功,获取输入流 if(conn.getResponseCode()==200){ return getUpdateInfo(conn.getInputStream()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (XmlPullParserException e) { e.printStackTrace(); } return null; }
根据xml流 获取对象 (可根据自己情况设置对应数据)
public static UpdateInfo getUpdateInfo(InputStream is) throws XmlPullParserException, IOException { XmlPullParser parser= Xml.newPullParser(); parser.setInput(is,"utf-8"); int type=parser.getEventType(); UpdateInfo info=new UpdateInfo(); while (type!=XmlPullParser.END_DOCUMENT){ switch (type){ case XmlPullParser.START_TAG: if(parser.nextText().equals("version")){ info.setVersionCode(Integer.parseInt(parser.nextText())); }else if(parser.nextText().equals("url")){ info.setUrl(parser.nextText()); }else if(parser.nextText().equals("message")){ info.setMessage(parser.nextText()); } break; } type=parser.next(); } return info; }
更新消息实体类
public class UpdateInfo { private int versionCode; //版本号 private String url;//apk下载地址 private String message;//更新消息 public int getVersionCode() { return versionCode; } public void setVersionCode(int versionCode) { this.versionCode = versionCode; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
如果当前版本号低于服务器版本号 就行更新 (弹窗提示)
Handler mHandler = new android.os.Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case UPDATE_TRUE: showUpdataDialog(); break; } super.handleMessage(msg); } };
/** * 展示弹窗 */ private void showUpdataDialog() { AlertDialog.Builder builer = new AlertDialog.Builder(this); builer.setTitle("版本升级"); builer.setMessage(info.getMessage()); //当点确定按钮时从服务器上下载 新的apk 然后安装 builer.setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //下载 downApk(); } }); //当点取消按钮时进行登录 builer.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub dialog.dismiss(); } }); AlertDialog dialog = builer.create(); dialog.show(); }
点击更新 启动后台服务下载apk
/** * 后台下载apk */ private void downApk() { Intent it = new Intent(MainActivity.this, DownloadService.class); startService(it); bindService(it, conn, Context.BIND_AUTO_CREATE); }
ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub isBinded = false; } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub binder = (DownloadService.DownloadBinder) service; System.out.println("服务启动!!!"); Log.e("服务启动", "服务启动----------------------------"); // 开始下载 isBinded = true; binder.addCallback(callback); binder.start(); } };
回调方法
private DownloadService.ICallbackResult callback = new DownloadService.ICallbackResult() { @Override public void OnBackResult(Object result) { // TODO Auto-generated method stub if ("finish".equals(result)) { finish(); return; } int i = (Integer) result; // mProgressBar.setProgress(i); // tv_progress.setText("当前进度 => "+i+"%"); // tv_progress.postInvalidate(); // mHandler.sendEmptyMessage(i); } };
//服务类
public class DownloadService extends Service { private static final int NOTIFY_ID = 0; private int progress; private NotificationManager mNotificationManager; private boolean canceled; // 返回的安装包url private String apkUrl = "http://softfile.3g.qq.com:8080/msoft/179/24659/43549/qq_hd_mini_1.4.apk"; // private String apkUrl = MyApp.downloadApkUrl; /* 下载包安装路径 */ private static final String savePath = "/sdcard/updateApkDemo/"; private static final String saveFileName = savePath + "3GQQ_AppUpdate.apk"; private ICallbackResult callback; private DownloadBinder binder; private SellerApplication app; private boolean serviceIsDestroy = false; private Context mContext = this; private Handler mHandler = new Handler() { @SuppressLint("NewApi") @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch (msg.what) { case 0: app.setDownload(false); // 下载完毕 // 取消通知 mNotificationManager.cancel(NOTIFY_ID); installApk(); break; case 2: app.setDownload(false); // 这里是用户界面手动取消,所以会经过activity的onDestroy();方法 // 取消通知 mNotificationManager.cancel(NOTIFY_ID); break; case 1: int rate = msg.arg1; app.setDownload(true); if (rate < 100) { RemoteViews contentview = mNotification.contentView; contentview.setTextViewText(R.id.tv_progress, rate + "%"); contentview.setProgressBar(R.id.progressbar, 100, rate, false); } else { System.out.println("下载完毕!!!!!!!!!!!"); // 下载完毕后变换通知形式 mNotification.flags = Notification.FLAG_AUTO_CANCEL; mNotification.contentView = null; Intent intent = new Intent(mContext, MainActivity.class); // 告知已完成 intent.putExtra("completed", "yes"); // 更新参数,注意flags要使用FLAG_UPDATE_CURRENT PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", contentIntent); mNotification=new Notification.Builder(mContext).setContentTitle("下载完成") .setContentText("文件已下载完毕").setContentIntent(contentIntent).build(); serviceIsDestroy = true; stopSelf();// 停掉服务自身 } mNotificationManager.notify(NOTIFY_ID, mNotification); break; } } }; // // @Override // public int onStartCommand(Intent intent, int flags, int startId) { // // TODO Auto-generated method stub // return START_STICKY; // } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub System.out.println("是否执行了 onBind"); return binder; } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); System.out.println("downloadservice ondestroy"); // 假如被销毁了,无论如何都默认取消了。 app.setDownload(false); } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub System.out.println("downloadservice onUnbind"); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { // TODO Auto-generated method stub super.onRebind(intent); System.out.println("downloadservice onRebind"); } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); binder = new DownloadBinder(); mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE); //setForeground(true);// 这个不确定是否有作用 app = (SellerApplication) getApplication(); } public class DownloadBinder extends Binder { public void start() { if (downLoadThread == null || !downLoadThread.isAlive()) { progress = 0; setUpNotification(); new Thread() { public void run() { // 下载 startDownload(); }; }.start(); } } public void cancel() { canceled = true; } public int getProgress() { return progress; } public boolean isCanceled() { return canceled; } public boolean serviceIsDestroy() { return serviceIsDestroy; } public void cancelNotification() { mHandler.sendEmptyMessage(2); } public void addCallback(ICallbackResult callback) { DownloadService.this.callback = callback; } } private void startDownload() { // TODO Auto-generated method stub canceled = false; downloadApk(); } // Notification mNotification; // 通知栏 /** * 创建通知 */ private void setUpNotification() { int icon = R.drawable.ic_launcher; CharSequence tickerText = "开始下载"; long when = System.currentTimeMillis(); mNotification = new Notification(icon, tickerText, when); // 放置在"正在运行"栏目中 mNotification.flags = Notification.FLAG_ONGOING_EVENT; RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.download_notification_layout); contentView.setTextViewText(R.id.name, "我的菜.apk 正在下载..."); // 指定个性化视图 mNotification.contentView = contentView; Intent intent = new Intent(this, MainActivity.class); // 下面两句是 在按home后,点击通知栏,返回之前activity 状态; // 有下面两句的话,假如service还在后台下载, 在点击程序图片重新进入程序时,直接到下载界面,相当于把程序MAIN 入口改了 - - // 是这么理解么。。。 // intent.setAction(Intent.ACTION_MAIN); // intent.addCategory(Intent.CATEGORY_LAUNCHER); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 指定内容意图 mNotification.contentIntent = contentIntent; mNotificationManager.notify(NOTIFY_ID, mNotification); } // /** * 下载apk * * @param url */ private Thread downLoadThread; private void downloadApk() { downLoadThread = new Thread(mdownApkRunnable); downLoadThread.start(); } /** * 安装apk */ private void installApk() { File apkfile = new File(saveFileName); if (!apkfile.exists()) { return; } Intent i = new Intent(Intent.ACTION_VIEW); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); mContext.startActivity(i); callback.OnBackResult("finish"); } private int lastRate = 0; private Runnable mdownApkRunnable = new Runnable() { @Override public void run() { try { URL url = new URL(apkUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.connect(); int length = conn.getContentLength(); InputStream is = conn.getInputStream(); File file = new File(savePath); if (!file.exists()) { file.mkdirs(); } String apkFile = saveFileName; File ApkFile = new File(apkFile); 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); // 更新进度 Message msg = mHandler.obtainMessage(); msg.what = 1; msg.arg1 = progress; if (progress >= lastRate + 1) { mHandler.sendMessage(msg); lastRate = progress; if (callback != null) callback.OnBackResult(progress); } if (numread <= 0) { // 下载完成通知安装 mHandler.sendEmptyMessage(0); // 下载完了,cancelled也要设置 canceled = true; break; } fos.write(buf, 0, numread); } while (!canceled);// 点击取消就停止下载. fos.close(); is.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; public interface ICallbackResult { public void OnBackResult(Object result); } }
通知栏布局文件