用AsyncTask实现断点续传
在学习四大组件之一的service时,正好可以利用asyncTask 和OKhttp来进行断点续传,并在手机的前台显示下载进度。
尝试下载的是Oracle官网上的jdk1.7
在AS中使用OKhttp,只需要简单的在app/build.gradle里加入一句就可以了,如下代码,就最后一行加入即可
dependencies{compilefileTree(dir:'libs',include:['*.jar'])androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2',{excludegroup:'com.android.support',module:'support-annotations'})compile'com.android.support:appcompat-v7:25.3.1'compile'com.android.support.constraint:constraint-layout:1.0.2'testCompile'junit:junit:4.12'compile'com.squareup.okhttp3:okhttp:3.8.1'}
1、DownloadTask.java
在该类里主要进行了文件是否存在,存在的话是否已经下载完成等判断,还有利用OKhttp进行文件下载,最经典是是在文件写入RandomAccessFile里时,判断的当前状态,如果是isPaused是true,表示点了暂停键,那么就要暂停下载等等判断;还有使用asyncTask的方法,传递进度给前置通知显示下载进度。
packagecom.yuanlp.servicebestproject;importandroid.os.AsyncTask;importandroid.os.Environment;importjava.io.File;importjava.io.IOException;importjava.io.InputStream;importjava.io.RandomAccessFile;importokhttp3.OkHttpClient;importokhttp3.Request;importokhttp3.Response;/***Createdby原立鹏on2017/7/1.*/publicclassDownloadTaskextendsAsyncTask<String,Integer,Integer>{privatestaticfinalStringTAG="DownloadTask";publicstaticfinalintTYPE_SUCCESS=0;publicstaticfinalintTYPE_FAILED=1;publicstaticfinalintTYPE_PAUSED=2;publicstaticfinalintTYPE_CANCELD=3;privateDownLoadListenerlistener;privatebooleanisCanceld=false;privatebooleanisPaused=false;privateintlastProgress;publicDownloadTask(DownLoadListenerdownloadListener){this.listener=downloadListener;}@OverrideprotectedIntegerdoInBackground(String...params){InputStreamis=null;RandomAccessFilesavedFile=null;//RandomAccessFile用来访问指定的文件的Filefile=null;try{longdownloadLength=0;//记录已经下载的文件中长度StringdownloadUrl=params[0];StringfileName=downloadUrl.substring(downloadUrl.lastIndexOf("/"));//获取文件名Stringdirectory=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();//获取文件保存路径file=newFile(directory+fileName);//创建文件//如果文件存在if(file.exists()){downloadLength=file.length();//获取已经存在的文件大小}longcontentLength=getContentLength(downloadUrl);//获取文件总大小if(contentLength==0){returnTYPE_FAILED;//已下载的文件异常,返回失败}elseif(downloadLength==contentLength){returnTYPE_SUCCESS;//说明下载的文件和总长度一样,返回成功}OkHttpClientclient=newOkHttpClient();Requestrequest=newRequest.Builder().header("RANGE","bytes="+downloadLength+"-")//从下载之后的地方开始.url(downloadUrl).build();Responseresponse=client.newCall(request).execute();if(response!=null){is=response.body().byteStream();//获取response中的输入流savedFile=newRandomAccessFile(file,"rw");//开始访问指定的文件savedFile.seek(downloadLength);//跳过已经下载的文件长度byte[]b=newbyte[1024];longtotal=0;intlen;while((len=is.read(b))!=-1){//这个时候说明还没有读取到输入流的最后if(isCanceld){//说明取消了下载returnTYPE_FAILED;}elseif(isPaused){returnTYPE_PAUSED;}else{total+=len;savedFile.write(b,0,len);intprogress=(int)((total+downloadLength)*100/contentLength);//计算下载的百分比publishProgress(progress);//调用onProgressUpdate()更新下载进度}}response.body().close();//关闭reponsereturnTYPE_SUCCESS;//返回下载成功}}catch(Exceptione){e.printStackTrace();}finally{try{if(is!=null){is.close();//关闭输入流}if(savedFile!=null){savedFile.close();//关闭查看文件}if(isCanceld&&file!=null){file.delete();//如果点击取消下载并且已经下载的文件存在,就删除文件}}catch(Exceptione){e.printStackTrace();}}returnTYPE_FAILED;}/***在doInBackground里调用ublishProgress时调用此方法,更新UI进度*@paramvalues*/publicvoidonProgressUpdate(Integer...values){intprogress=values[0];//获取传过来的百分比值if(progress>lastProgress){listener.onProgress(progress);}}/***当doInBackground执行完成时,调用此方法*@paramstatus*/publicvoidonPostExecute(Integerstatus){switch(status){caseTYPE_SUCCESS:listener.onSuccess();break;caseTYPE_FAILED:listener.onFailed();break;caseTYPE_PAUSED:listener.onPause();break;caseTYPE_CANCELD:listener.onCancled();break;default:break;}}/***按下暂停键时调用,暂停下载*/publicvoidpausedDownload(){isPaused=true;}publicvoidcanceledDownload(){isCanceld=true;}/***根据传入的rul地址,获取文件总长度*@paramurl*@return*/publiclonggetContentLength(Stringurl)throwsIOException{OkHttpClientclient=newOkHttpClient();Requestrequest=newRequest.Builder().url(url).build();Responsereponse=client.newCall(request).execute();if(reponse!=null&&reponse.isSuccessful()){//成功返回reponselongcontentLength=reponse.body().contentLength();//获取文件中长度returncontentLength;}return0;}}
2、DownloadService.java
在这个里面,主要是根据Mainactivity里的指令,进行调用downloadTask类里的方法,以及调用前置通知,显示进度。
packagecom.yuanlp.servicebestproject;importandroid.app.Notification;importandroid.app.NotificationManager;importandroid.app.PendingIntent;importandroid.app.Service;importandroid.content.Intent;importandroid.graphics.BitmapFactory;importandroid.os.Binder;importandroid.os.Environment;importandroid.os.IBinder;importandroid.support.v4.app.NotificationCompat;importandroid.widget.Toast;importjava.io.File;publicclassDownloadServiceextendsService{privatestaticfinalStringTAG="DownloadService";privateDownloadTaskdownloadTask;privateStringdownloadUrl;publicDownloadService(){}@OverridepublicIBinderonBind(Intentintent){returnmBinder;}privateDownLoadListenerlistener=newDownLoadListener(){@OverridepublicvoidonProgress(intprogress){getNotifactionManager().notify(1,getNotification("Downloading....",progress));}@OverridepublicvoidonSuccess(){downloadTask=null;//下载成功后,将前台通知关闭,并创建一个下载成功的通告stopForeground(true);getNotifactionManager().notify(1,getNotification("DownloadSuccess",-1));Toast.makeText(DownloadService.this,"DownloadSuccess",Toast.LENGTH_SHORT).show();}@OverridepublicvoidonFailed(){downloadTask=null;stopForeground(true);getNotifactionManager().notify(1,getNotification("DownFailed",-1));Toast.makeText(DownloadService.this,"DownFailed",Toast.LENGTH_SHORT).show();}@OverridepublicvoidonPause(){downloadTask=null;Toast.makeText(DownloadService.this,"Paused",Toast.LENGTH_SHORT).show();}@OverridepublicvoidonCancled(){downloadTask=null;Toast.makeText(DownloadService.this,"Canceled",Toast.LENGTH_SHORT).show();}};privateDownloadBindermBinder=newDownloadBinder();classDownloadBinderextendsBinder{publicvoidstartDownload(Stringurl){if(downloadTask==null){downloadUrl=url;downloadTask=newDownloadTask(listener);Toast.makeText(DownloadService.this,"Downloading....",Toast.LENGTH_SHORT).show();downloadTask.execute(downloadUrl);startForeground(1,getNotification("Downloading...",0));}}publicvoidpauseDownload(){if(downloadTask==null){downloadTask.pausedDownload();}}publicvoidcancelDownload(){if(downloadTask==null){downloadTask.canceledDownload();}else{if(downloadUrl!=null){Stringfilename=downloadUrl.substring(downloadUrl.lastIndexOf("/"));Stringdirectory=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();Filefile=newFile(directory);if(file.exists()){file.delete();}getNotifactionManager().cancel(1);stopForeground(true);Toast.makeText(DownloadService.this,"Canceled",Toast.LENGTH_SHORT).show();}}}}privateNotificationManagergetNotifactionManager(){return(NotificationManager)getSystemService(NOTIFICATION_SERVICE);}privateNotificationgetNotification(Stringtitle,intprogress){Intentintent=newIntent(this,MainActivity.class);PendingIntentpi=PendingIntent.getActivity(this,0,intent,0);NotificationCompat.Builderbuilder=newNotificationCompat.Builder(this);builder.setSmallIcon(R.mipmap.ic_launcher);builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));builder.setContentIntent(pi);builder.setContentTitle(title);if(progress>=0){builder.setContentText(progress+"%");builder.setProgress(100,progress,false);}returnbuilder.build();}}
3、MainActivity.java
主要是进行了开启服务和绑定服务,对应按钮的操作,以及运行时权限申请。
packagecom.yuanlp.servicebestproject;importandroid.Manifest;importandroid.content.ComponentName;importandroid.content.Intent;importandroid.content.ServiceConnection;importandroid.content.pm.PackageManager;importandroid.os.Bundle;importandroid.os.IBinder;importandroid.support.v4.app.ActivityCompat;importandroid.support.v4.content.ContextCompat;importandroid.support.v7.app.AppCompatActivity;importandroid.view.View;importandroid.widget.Toast;publicclassMainActivityextendsAppCompatActivity{privatestaticfinalStringTAG="MainActivity";privateDownloadService.DownloadBindermDownloadBinder;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intentintent=newIntent(this,DownloadService.class);startService(intent);bindService(intent,conn,BIND_AUTO_CREATE);if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED);ActivityCompat.requestPermissions(MainActivity.this,newString[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);}privateServiceConnectionconn=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){mDownloadBinder=(DownloadService.DownloadBinder)service;}@OverridepublicvoidonServiceDisconnected(ComponentNamename){}};/***点击开始下载*@paamview*/publicvoidstartService(Viewview){Toast.makeText(this,"点击下载",Toast.LENGTH_SHORT).show();if(mDownloadBinder==null){return;}Stringurl="http://download.java.net/java/jdk9/archive/176/binaries/jdk-9+176_windows-x86_bin.exe";mDownloadBinder.startDownload(url);}publicvoidpauseService(Viewview){if(mDownloadBinder==null){return;}mDownloadBinder.pauseDownload();}publicvoidcancelSerivce(Viewview){if(mDownloadBinder==null){return;}mDownloadBinder.cancelDownload();}publicvoidonRequestPermissiosResult(intrequestCode,String[]permissions,int[]grantResult){switch(requestCode){case1:if(grantResult.length>0&&grantResult[0]!=PackageManager.PERMISSION_GRANTED){Toast.makeText(this,"拒绝授权将无法使用程序",Toast.LENGTH_SHORT).show();finish();}break;default:}}publicvoidonDestroy(){super.onDestroy();unbindService(conn);}}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。