Android下载进度监听和通知的处理详解
本文实例为大家分享了Android下载进度监听和通知的具体代码,供大家参考,具体内容如下
下载管理器
关于下载进度的监听,这个比较简单,以apk文件下载为例,需要处理3个回调函数,分别是:
1.下载中
2.下载成功
3.下载失败
因此对应的回调接口就有了:
publicinterfaceDownloadCallback{ /** *下载成功 *@paramfile目标文件 */ voidonComplete(Filefile); /** *下载失败 *@parame */ voidonError(Exceptione); /** *下载中 *@paramcount总大小 *@paramcurrent当前下载的进度 */ voidonLoading(longcount,longcurrent); }
接下来就是线程池的管理了,当然你也可以直接使用Executors工具类中提供的几个静态方法来创建线程池,这里我是手动创建线程池的,代码如下:
publicclassThreadManager{ privatestaticThreadPoolmThreadPool; /** *获取线程池 * *@return */ publicstaticThreadPoolgetThreadPool(){ if(null==mThreadPool){ synchronized(ThreadManager.class){ if(null==mThreadPool){ //cpu个数 intcpuNum=Runtime.getRuntime().availableProcessors(); //线程个数 intcount=cpuNum*2+1; mThreadPool=newThreadPool(count,count,0); } } } returnmThreadPool; } publicstaticclassThreadPool{ intcorePoolSize;//核心线程数 intmaximumPoolSize;//最大线程数 longkeepAliveTime;//保持活跃时间(休息时间) privateThreadPoolExecutorexecutor; /** *构造方法初始化 * *@paramcorePoolSize *@parammaximumPoolSize *@paramkeepAliveTime */ privateThreadPool(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime){ this.corePoolSize=corePoolSize; this.maximumPoolSize=maximumPoolSize; this.keepAliveTime=keepAliveTime; } privatestaticfinalThreadFactorysThreadFactory=newThreadFactory(){ privatefinalAtomicIntegermCount=newAtomicInteger(1); publicThreadnewThread(Runnabler){ returnnewThread(r,"ThreadManager#"+mCount.getAndIncrement()); } }; /** *执行线程任务 * *@paramr */ publicvoidexecute(Runnabler){ //参1:核心线程数;参2:最大线程数;参3:保持活跃时间(休息时间);参4:活跃时间单位;参5:线程队列;参6:线程工厂;参7:异常处理策略 if(null==executor){ executor=newThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, newLinkedBlockingQueue(), sThreadFactory/*Executors.defaultThreadFactory()*/, newThreadPoolExecutor.AbortPolicy()); } //将当前Runnable对象放在线程池中执行 executor.execute(r); } /** *从线程池的任务队列中移除一个任务 *如果当前任务已经是运行状态了,那么就表示不在任务队列中了,也就移除失败. */ publicvoidcancle(Runnabler){ if(null!=executor&&null!=r){ executor.getQueue().remove(r); } } /** *是否关闭了线程池 *@return */ publicbooleanisShutdown(){ returnexecutor.isShutdown(); } /** *关闭线程池 */ publicvoidshutdown(){ executor.shutdown(); } } }
接下来就是一个下载管理器的封装了.
publicclassDownloadManager{ privateDownloadCallbackcallback; privateContextcontext; privateStringurl; privateStringfileName; /** *初始化 *@paramcontext上下文 *@paramurl目标文件url *@paramfileName下载保存的文件名 *@paramcallback下载回调函数 */ publicDownloadManager(finalContextcontext,finalStringurl,finalStringfileName,DownloadCallbackcallback){ this.context=context; this.url=url; this.fileName=fileName; this.callback=callback; } /** *开始下载 */ publicvoidstartDownload(){ if(null==callback)return; ThreadManager.getThreadPool().execute(newRunnable(){ @Override publicvoidrun(){ HttpURLConnectionconn=null; try{ conn=(HttpURLConnection)newURL(url).openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(5000); conn.setConnectTimeout(10000); longtotal=conn.getContentLength(); longcurr=0; Filefile=newFile(PathUtils.getDirectory(context,"apk"),fileName); if(!file.exists()){ file.createNewFile(); }else{ file.delete(); } FileOutputStreamfos=newFileOutputStream(file); if(200==conn.getResponseCode()){ InputStreamin=conn.getInputStream(); byte[]buff=newbyte[1024]; intlen=0; while((len=in.read(buff))!=-1){ fos.write(buff,0,len); curr+=len; callback.onLoading(total,curr); } in.close(); fos.close(); if(curr==total){ callback.onComplete(file); }else{ thrownewException("curr!=total"); } }else{ thrownewException(""+conn.getResponseCode()); } }catch(Exceptione){ e.printStackTrace(); callback.onError(e); }finally{ if(null!=conn){ conn.disconnect(); } } } }); } }
涉及的工具类如下:
PathUtils
publicclassPathUtils{ /** *获取cache目录下的rootDir目录 * *@paramcontext *@paramrootDir *@return */ publicstaticFilegetDirectory(Contextcontext,StringrootDir){ StringcachePath=context.getApplicationContext().getCacheDir().getAbsolutePath(); if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) ||!Environment.isExternalStorageRemovable()){ if(Build.VERSION.SDK_INT<=8){ cachePath=Environment.getExternalStorageDirectory().getAbsolutePath(); }elseif(context.getApplicationContext().getExternalCacheDir()!=null){ cachePath=context.getApplicationContext().getExternalCacheDir().getAbsolutePath(); } } FilerootF=newFile(cachePath+File.separator+rootDir); if(!rootF.exists()){ rootF.mkdirs(); } //修改目录权限可读可写可执行 Stringcmd="chmod777-R"+rootF.getPath(); CmdUtils.execCmd(cmd); returnrootF; } }
CmdUtils
publicclassCmdUtils{ publicstaticvoidexecCmd(Stringcmd){ try{ Runtime.getRuntime().exec(cmd); }catch(IOExceptione){ e.printStackTrace(); } } }
下载通知服务
同样以apk下载为例,要实现下载通知服务的话,就用到了Notification和Service,Notification用来通知下载进度并显示给用户看,Service用于后台默默的下载文件,这里我用到了IntentService,它的好处在于任务执行完毕后会自动关闭服务.同时程序用如果其他地方还想监听到下载的进度,那么可以在IntentService下载服务中通过发送广播告知进度.
ok,下面的代码可以直接用户实现apk的升级更新的操作.
publicclassUpdateServiceextendsIntentService{ privateFileapkFile; privateStringurl; privateStringfileName; privateNotificationCompat.BuilderbuilderNotification; privateNotificationManagerupdateNotificationManager; privateintappNameID; privateinticonID; privatePendingIntentupdatePendingIntent; privatebooleanisUpdating; publicstaticfinalStringACTION_UPDATE_PROGRESS="blog.csdn.net.mchenys.mobilesafe.ACTION_UPDATE_PROGRESS"; privateHandlerupdateHandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ switch(msg.what){ case0: UpdateService.this.onFailNotification(); break; case1: UpdateService.this.downComplete(); break; } super.handleMessage(msg); } }; publicUpdateService(){ super("UpdateService"); } /** *开始更新 * *@paramcontext *@paramurl更新的url *@paramfileName下载保存apk的文件名称 */ publicstaticvoidstartUpdate(Contextcontext,Stringurl,StringfileName){ Intentintent=newIntent(context,UpdateService.class); intent.putExtra("url",url); intent.putExtra("fileName",fileName); context.startService(intent); } @Override protectedvoidonHandleIntent(Intentintent){ //WorkerThread if(!this.isUpdating&&intent!=null){ initData(intent); initNotification(); downloadFile(true); } } /** *初始数据 * *@paramintent */ privatevoidinitData(Intentintent){ this.isUpdating=true; this.url=intent.getStringExtra("url"); this.fileName=intent.getStringExtra("fileName"); this.apkFile=newFile(PathUtils.getDirectory(getApplicationContext(),"mobilesafe"),fileName); if(!this.apkFile.exists()){ try{ this.apkFile.createNewFile(); }catch(IOExceptione){ e.printStackTrace(); } }else{ this.apkFile.delete(); } this.appNameID=R.string.app_name; this.iconID=R.mipmap.ic_logo; } /** *初始化通知 */ privatevoidinitNotification(){ IntentupdateCompletingIntent=newIntent(); updateCompletingIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); updateCompletingIntent.setClass(this.getApplication().getApplicationContext(),UpdateService.class); this.updatePendingIntent=PendingIntent.getActivity(this,this.appNameID,updateCompletingIntent,PendingIntent.FLAG_CANCEL_CURRENT); this.updateNotificationManager=(NotificationManager)this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); this.builderNotification=newNotificationCompat.Builder(this.getApplicationContext()); this.builderNotification.setSmallIcon(this.iconID). setContentTitle(this.getResources().getString(this.appNameID)). setContentIntent(updatePendingIntent). setAutoCancel(true). setTicker("开始更新"). setDefaults(1). setProgress(100,0,false). setContentText("下载进度"). build(); this.updateNotificationManager.notify(this.iconID,this.builderNotification.build()); } /** *开始下载apk * *@paramappend是否支持断点续传 */ privatevoiddownloadFile(finalbooleanappend){ finalMessagemessage=updateHandler.obtainMessage(); intcurrentSize=0;//上次下载的大小 longreadSize=0L;//已下载的总大小 longcontentLength=0;//服务器返回的数据长度 if(append){ FileInputStreamfis=null; try{ fis=newFileInputStream(UpdateService.this.apkFile); currentSize=fis.available();//获取上次下载的大小,断点续传可用 }catch(IOExceptione){ e.printStackTrace(); }finally{ if(fis!=null){ try{ fis.close(); }catch(IOExceptione){ e.printStackTrace(); } } } } HttpURLConnectionconn=null; InputStreamis=null; FileOutputStreamfos=null; try{ conn=(HttpURLConnection)newURL(UpdateService.this.url).openConnection(); conn.setRequestProperty("User-Agent","Android"); if(currentSize>0){ conn.setRequestProperty("RANGE","bytes="+currentSize+"-"); } conn.setConnectTimeout(10000); conn.setReadTimeout(20000); contentLength=conn.getContentLength(); if(conn.getResponseCode()==404){ thrownewException("Cannotfindremotefile:"+UpdateService.this.url); } is=conn.getInputStream(); fos=newFileOutputStream(UpdateService.this.apkFile,append); //实时更新通知 UpdateService.this.builderNotification.setSmallIcon(iconID). setContentTitle(UpdateService.this.getResources().getString(UpdateService.this.appNameID)). setContentIntent(updatePendingIntent). setAutoCancel(true). setTicker("正在更新"). setDefaults(0). setContentText("下载进度"). build(); byte[]buffer=newbyte[8*1024]; intlen=0; while((len=is.read(buffer))!=-1){ fos.write(buffer,0,len); readSize+=len;//累加已下载的大小 intprogress=(int)(readSize*100/contentLength); Log.d("UpdateService",(readSize*100/contentLength)+""); if(progress%8==0){ UpdateService.this.builderNotification.setProgress(100,progress,false); UpdateService.this.updateNotificationManager.notify(iconID,UpdateService.this.builderNotification.build()); //发送广播,通知外界下载进度 sendUpdateProgress(progress); } } if(readSize==0L){ message.what=0; }elseif(readSize==contentLength){ message.what=1; sendUpdateProgress(100); } }catch(Exceptione){ e.printStackTrace(); message.what=0; }finally{ if(conn!=null){ conn.disconnect(); } IOUtils.close(is); IOUtils.close(fos); updateHandler.sendMessage(message); } } /** *发送更新进度 * *@paramprogress */ privatevoidsendUpdateProgress(intprogress){ Intentintent=newIntent(ACTION_UPDATE_PROGRESS); intent.putExtra("progress",progress); sendBroadcast(intent); } /** *下载失败通知用户重新下载 */ privatevoidonFailNotification(){ this.builderNotification.setSmallIcon(iconID). setContentTitle("更新失败,请重新下载"). setContentIntent(updatePendingIntent). setAutoCancel(true). setTicker("更新失败"). setDefaults(1). setProgress(100,0,false). setContentText("下载进度"). build(); this.updateNotificationManager.notify(iconID,this.builderNotification.build()); } /** *下载完毕,后通知用户点击安装 */ privatevoiddownComplete(){ UpdateService.this.isUpdating=false; Stringcmd="chmod777"+this.apkFile.getPath(); CmdUtils.execCmd(cmd); Uriuri=Uri.fromFile(this.apkFile); IntentupdateCompleteIntent=newIntent("android.intent.action.VIEW"); updateCompleteIntent.addCategory("android.intent.category.DEFAULT"); updateCompleteIntent.setDataAndType(uri,"application/vnd.android.package-archive"); this.updatePendingIntent=PendingIntent.getActivity(this,this.appNameID,updateCompleteIntent,PendingIntent.FLAG_UPDATE_CURRENT); this.builderNotification.setSmallIcon(this.iconID). setContentTitle(this.getResources().getString(this.appNameID)). setContentIntent(this.updatePendingIntent). setAutoCancel(true). setTicker("更新完成"). setDefaults(1). setProgress(0,0,false). setContentText("更新完成,点击安装"). build(); this.updateNotificationManager.notify(this.iconID,this.builderNotification.build()); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。