Android中的应用更新
来源:互联网 发布:优化人才培养方案 编辑:程序博客网 时间:2024/05/17 22:43
实现思路:通过启动service,新建一个线程进行下载,handler通知到notification。
1、下载接口
public interface UpdateDownloadListener { /** * 下载请求开始回调 */ public void onStarted(); /** * 请求成功,下载前的准备回调 * * @param contentLength * 文件长度 * @param downloadUrl * 下载地址 */ public void onPrepared(long contentLength, String downloadUrl); /** * 进度更新回调 * * @param progress * @param downloadUrl */ public void onProgressChanged(int progress, String downloadUrl); /** * 下载过程中暂停的回调 * * @param completeSize * @param downloadUrl */ public void onPaused(int progress, int completeSize, String downloadUrl); /** * 下载完成回调 * * @param completeSize * @param downloadUrl */ public void onFinished(int completeSize, String downloadUrl); /** * 下载失败回调 */ public void onFailure();}
2、下载请求
public class UpdateDownloadRequest implements Runnable { private int startPos = 0; //下载路径 private String downloadUrl; //文件保存路径 private String localFilePath; //事件回调 private UpdateDownloadListener downloadListener; private DownloadResponseHandler downloadHandler; //下载的标志位 private boolean isDownloading = false; //文件长度 private long contentLength; public UpdateDownloadRequest(String downloadUrl, String localFilePath, UpdateDownloadListener downloadListener) { this.downloadUrl = downloadUrl; this.localFilePath = localFilePath; this.downloadListener = downloadListener; downloadHandler = new DownloadResponseHandler(); isDownloading = true; } //真正建立连接的方法 private void makeRequest() throws IOException, InterruptedException { if (!Thread.currentThread().isInterrupted()) { try { URL url = new URL(downloadUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(5000); connection.setRequestMethod("GET"); connection.setRequestProperty("Range", "bytes=" + startPos + "-"); connection.setRequestProperty("Connection", "Keep-Alive"); connection.connect(); contentLength = connection.getContentLength(); if (!Thread.currentThread().isInterrupted()) { if (downloadHandler != null) { downloadHandler.sendResponseMessage(connection.getInputStream());//取得与远程文件的流 } } } catch (IOException e) { if (!Thread.currentThread().isInterrupted()) { throw e; } } } } @Override public void run() { try { makeRequest(); } catch (IOException e) { if (downloadHandler != null) { downloadHandler.sendFailureMessage(FailureCode.IO); } } catch (InterruptedException e) { if (downloadHandler != null) { downloadHandler.sendFailureMessage(FailureCode.Interrupted); } } } public boolean isDownloading() { return isDownloading; } public void stopDownloading() { isDownloading = false; } /** * 用来真正的去下载文件,并发送消息和回调接口 */ public class DownloadResponseHandler { protected static final int SUCCESS_MESSAGE = 0; protected static final int FAILURE_MESSAGE = 1; protected static final int START_MESSAGE = 2; protected static final int FINISH_MESSAGE = 3; protected static final int NETWORK_OFF = 4; private Handler handler; public DownloadResponseHandler() { if (Looper.myLooper() != null) { handler = new Handler() { @Override public void handleMessage(Message msg) { handleSelfMessage(msg); } }; } } public void onFinish() { downloadListener.onFinished(mCompleteSize, ""); } public void onFailure(FailureCode failureCode) { downloadListener.onFailure(); } private void sendPausedMessage() { sendMessage(obtainMessage(PAUSED_MESSAGE, null)); } private void sendProgressChangedMessage(int progress) { sendMessage(obtainMessage(PROGRESS_CHANGED, new Object[] { progress })); } protected void sendFailureMessage(FailureCode failureCode) { sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[] { failureCode })); } // // Pre-processing of messages (in original calling thread, typically the // UI thread) // protected void handlePausedMessage() { downloadListener.onPaused(progress, mCompleteSize, ""); } protected void handleProgressChangedMessage(int progress) { downloadListener.onProgressChanged(progress, ""); } protected void handleFailureMessage(FailureCode failureCode) { onFailure(failureCode); } protected void sendFinishMessage() { sendMessage(obtainMessage(FINISH_MESSAGE, null)); } // Methods which emulate android's Handler and Message methods protected void handleSelfMessage(Message msg) { Object[] response; switch (msg.what) { case FAILURE_MESSAGE: response = (Object[]) msg.obj; handleFailureMessage((FailureCode) response[0]); break; case PROGRESS_CHANGED: response = (Object[]) msg.obj; handleProgressChangedMessage(((Integer) response[0]).intValue()); break; case PAUSED_MESSAGE: handlePausedMessage(); break; case FINISH_MESSAGE: onFinish(); break; } } protected void sendMessage(Message msg) { if (handler != null) { handler.sendMessage(msg); } else { handleSelfMessage(msg); } } protected Message obtainMessage(int responseMessage, Object response) { Message msg = null; if (handler != null) { msg = this.handler.obtainMessage(responseMessage, response); } else { msg = Message.obtain(); msg.what = responseMessage; msg.obj = response; } return msg; } private String getTwoPointFloatStr(float value) { DecimalFormat fnum = new DecimalFormat("0.00"); return fnum.format(value); } private int mCompleteSize = 0; private int progress = 0; private static final int PROGRESS_CHANGED = 5; private static final int PAUSED_MESSAGE = 7; //文件 下载方法,会发送各种类型的事件 void sendResponseMessage(InputStream is) { RandomAccessFile randomAccessFile = null; mCompleteSize = 0; try { byte[] buffer = new byte[1024]; int length = -1; int limit = 0; randomAccessFile = new RandomAccessFile(localFilePath, "rwd"); randomAccessFile.seek(startPos); boolean isPaused = false; while ((length = is.read(buffer)) != -1) { if (isDownloading) { randomAccessFile.write(buffer, 0, length); mCompleteSize += length; if ((startPos + mCompleteSize) < (contentLength + startPos)) { progress = (int) (Float.parseFloat(getTwoPointFloatStr( (float) (startPos + mCompleteSize) / (contentLength + startPos))) * 100); if (limit % 30 == 0 &&progress <= 100) { //为了显示我们notification的更新频率 sendProgressChangedMessage(progress); //在子线程中读取流数据,后转发到主线程中去。 } } limit++; } else { isPaused = true; sendPausedMessage(); break; } } stopDownloading(); if (!isPaused) { sendFinishMessage(); } } catch (IOException e) { sendPausedMessage(); stopDownloading(); e.printStackTrace(); } finally { try { if (is != null) { is.close(); } if (randomAccessFile != null) { randomAccessFile.close(); } } catch (IOException e) { stopDownloading(); e.printStackTrace(); } } } } /** * 失败码 */ public enum FailureCode { UnknownHost, Socket, SocketTimeout, ConnectTimeout, IO, HttpResponse, JSON, Interrupted }}
3、下载调度管理器
public class UpdateManager { private static UpdateManager manager; private ThreadPoolExecutor threadPool; private UpdateDownloadRequest downloadRequest; private UpdateManager() { threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool(); } static { manager = new UpdateManager(); } public static UpdateManager getInstance() { return manager; } public void startDownload(String downloadUrl, String localFilePath, UpdateDownloadListener downloadListener) { if (downloadRequest != null && downloadRequest.isDownloading()) { return; } checkLocalFilePath(localFilePath); downloadRequest = new UpdateDownloadRequest(downloadUrl, localFilePath, downloadListener); Future<?> request = threadPool.submit(downloadRequest); new WeakReference<Future<?>>(request); } //检查路径是否合法 private void checkLocalFilePath(String localFilePath) { File path = new File(localFilePath.substring(0, localFilePath.lastIndexOf("/") + 1)); File file = new File(localFilePath); if (!path.exists()) { path.mkdirs(); } if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } }}
4、下载的service
public class UpdateService extends Service { /** * 服务器固定地址 */ private static final String APK_URL_TITLE = "http://www.imooc.com/mobile/mukewang.apk"; /** * 文件存放路经 */ private String filePath; /** * 文件下载地址 */ private String apkUrl; private NotificationManager notificationManager; private Notification mNotification; @Override public void onCreate() { notificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE); filePath = Environment.getExternalStorageDirectory() + "/imooc/imooc.apk"; } @Override public int onStartCommand(Intent intent, int flags, int startId) { apkUrl = APK_URL_TITLE; notifyUser(getString(R.string.update_download_start), getString(R.string.update_download_start), 0); startDownload(); return super.onStartCommand(intent, flags, startId); } private void startDownload() { UpdateManager.getInstance().startDownload(apkUrl, filePath, new UpdateDownloadListener() { @Override public void onStarted() { } @Override public void onProgressChanged(int progress, String downloadUrl) { notifyUser(getString(R.string.update_download_processing), getString(R.string.update_download_processing), progress); } @Override public void onPrepared(long contentLength, String downloadUrl) { } @Override public void onPaused(int progress, int completeSize, String downloadUrl) { notifyUser(getString(R.string.update_download_failed), getString(R.string.update_download_failed_msg), 0); deleteApkFile(); stopSelf();// 停掉服务自身 } @Override public void onFinished(int completeSize, String downloadUrl) { notifyUser(getString(R.string.update_download_finish), getString(R.string.update_download_finish), 100); stopSelf();// 停掉服务自身 startActivity(getInstallApkIntent()); } @Override public void onFailure() { notifyUser(getString(R.string.update_download_failed), getString(R.string.update_download_failed_msg), 0); deleteApkFile(); stopSelf();// 停掉服务自身 } }); } @Override public IBinder onBind(Intent intent) { return null; } public void notifyUser(String tickerMsg, String message, int progress) { notifyThatExceedLv21(tickerMsg, message, progress); } private void notifyThatExceedLv21(String tickerMsg, String message, int progress) { NotificationCompat.Builder notification = new NotificationCompat.Builder(this); notification.setSmallIcon(R.drawable.bg_message_imooc); notification.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bg_message_imooc)); notification.setContentTitle(getString(R.string.app_name)); if (progress > 0 && progress < 100) { notification.setProgress(100, progress, false); } else { /** * 0,0,false,可以将进度条影藏 */ notification.setProgress(0, 0, false); notification.setContentText(message); } notification.setAutoCancel(true); notification.setWhen(System.currentTimeMillis()); notification.setTicker(tickerMsg); notification.setContentIntent(progress >= 100 ? getContentIntent() : PendingIntent.getActivity(this, 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT)); mNotification = notification.build(); notificationManager.notify(0, mNotification); } private PendingIntent getContentIntent() { PendingIntent contentIntent = PendingIntent.getActivity(this, 0, getInstallApkIntent(), PendingIntent.FLAG_UPDATE_CURRENT); return contentIntent; } /** * 下载完成,安装 */ private Intent getInstallApkIntent() { File apkfile = new File(filePath); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); return intent; } /** * 删除无用apk文件 */ private boolean deleteApkFile() { File apkFile = new File(filePath); if (apkFile.exists() && apkFile.isFile()) { return apkFile.delete(); } return false; }}
0 0
- Android中的应用更新
- android 增量更新应用
- Android应用更新
- Android应用检测更新
- Android应用版本更新
- android应用检测更新
- Android应用更新apk
- Android应用增量更新
- Android应用增量更新
- Android应用更新库
- Android应用更新
- Android 应用更新总结
- Android中的UI更新
- Android -- 应用自动检测更新代码
- Android应用更新自动检测下载
- android检测应用版本更新
- Android应用的定时更新
- Android应用检查更新总结
- MySql Host is blocked because of many connection errors;
- java日志组件(4):logback
- iOS coretext框架第三章 CTParagraphStyle类介绍
- leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal
- TCP三次握手和四次挥手的全过程
- Android中的应用更新
- spring集成httpclient配置
- Atitit 图像处理类库安装与安装模式的前世今生与未来大趋势attilax总结.docx
- 测试2
- header中Content-Disposition的作用
- 手工使用Protobuf-net工具来序列化对象
- 2017~不再碎碎念
- Extjs中用url动态传参到后台的汉字为乱码
- OSI,TCP/IP,五层协议的体系结构,以及各层协议