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());
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。