使用okhttp和前台服务实现断点续传功能
来源:互联网 发布:全球一条线直销软件 编辑:程序博客网 时间:2024/06/05 20:12
参考资料
- 《第一行代码》
代码示例
- 清单文件配置
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.testandroid"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".service.DownloadService" android:enabled="true" android:exported="true"/> </application></manifest>
- 后台异步下载
public class DownloadTask extends AsyncTask<String,Integer,Integer> { public static final int TYPE_SUCCESS =0; public static final int TYPE_FAILED = 1; public static final int TYPE_PAUSED = 2; public static final int TYPE_CANCELED = 3; private DownloadListener listener; private boolean isCanceled = false; private boolean isPaused = false; private int lastProgress; public DownloadTask(DownloadListener listener){ this.listener = listener; } @Override protected Integer doInBackground(String... strings) { InputStream is = null; RandomAccessFile savedFile = null; File file = null; try { long downloadedLength = 0; String downloadUrl = strings[0]; String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); file = new File(directory+fileName); if (file.exists()){ downloadedLength = file.length(); } long contentLength = getContentLength(downloadUrl); if (contentLength == 0){ return TYPE_FAILED; }else if (contentLength == downloadedLength){ return TYPE_SUCCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() //断点续传 .addHeader("RANGE","bytes="+downloadedLength+"-") .url(downloadUrl) .build(); //同步下载 Response response = client.newCall(request).execute(); if (response!=null){ is = response.body().byteStream(); savedFile = new RandomAccessFile(file,"rw"); //跳过已经下载的字节 savedFile.seek(downloadedLength); byte[] b = new byte[1024]; int total = 0; int len ; while ((len=is.read(b))!=-1){ if (isCanceled){ return TYPE_CANCELED; }else if (isPaused){ return TYPE_PAUSED; }else { total +=len; savedFile.write(b,0,len); int progress = (int) ((total+downloadedLength)*100/contentLength); //发布进度 publishProgress(progress); } } response.body().close(); return TYPE_SUCCESS; } }catch (Exception e){ e.printStackTrace(); }finally { try { if (is!=null){ is.close(); } if (savedFile!=null){ savedFile.close(); } if (isCanceled && file!=null){ //如果取消了下载,就删除本地文件 file.delete(); } }catch (Exception e){ e.printStackTrace(); } } return TYPE_FAILED; } @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; if (progress>lastProgress){ listener.onProgress(progress); lastProgress = progress; } } /** * 下载完成 * @param integer */ @Override protected void onPostExecute(Integer integer) { switch (integer){ case TYPE_SUCCESS: listener.onSuccess(); break; case TYPE_FAILED: listener.onFailed(); break; case TYPE_PAUSED: listener.onPaused(); break; case TYPE_CANCELED: listener.onCanceled(); break; } } public void pauseDownload(){ isPaused = true; } public void cancelDownload(){ isCanceled = true; } private long getContentLength(String downloadUrl) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(downloadUrl) .build(); Response response = client.newCall(request).execute(); if (response!=null && response.isSuccessful()){ long contentLength = response.body().contentLength(); response.close(); return contentLength; } return 0; }}
- 接口
public interface DownloadListener { void onProgress(int progress); void onSuccess(); void onFailed(); void onPaused(); void onCanceled();}
- 后台服务
public class DownloadService extends Service{ private DownloadTask downloadTask; private String downloadUrl; private DownloadListener listener = new DownloadListener() { @Override public void onProgress(int progress) { //使用通知,显示在状态栏 getNotifcationManager().notify(1,getNotification("Downloading...",progress)); } @Override public void onSuccess() { downloadTask = null; //下载成功后,将前台服务通知关闭,并创建一个下载成功的通知 stopForeground(true); getNotifcationManager().notify(1,getNotification("Downloading Success",-1)); Toast.makeText(DownloadService.this,"Download Success",Toast.LENGTH_SHORT).show(); } @Override public void onFailed() { downloadTask = null; stopForeground(true); getNotifcationManager().notify(1,getNotification("Download Failed",-1)); Toast.makeText(DownloadService.this,"Download Fail",Toast.LENGTH_SHORT).show(); } @Override public void onPaused() { downloadTask = null; Toast.makeText(DownloadService.this,"Paused",Toast.LENGTH_SHORT).show(); } @Override public void onCanceled() { downloadTask = null; stopForeground(true); Toast.makeText(DownloadService.this,"Canceled",Toast.LENGTH_SHORT).show(); } }; public class DownloadBinder extends Binder{ //对绑定该服务的活动暴露方法 public void startDownload(String url){ if (downloadTask==null){ downloadUrl = url; downloadTask = new DownloadTask(listener); downloadTask.execute(downloadUrl); //开启前台服务 startForeground(1,getNotification("Downloading...",0)); Toast.makeText(DownloadService.this,"Download...",Toast.LENGTH_SHORT).show(); } } public void pauseDownload(){ if (downloadTask!=null){ downloadTask.pauseDownload(); } } public void CancelDownload(){ if (downloadTask!=null){ downloadTask.cancelDownload(); }else { if (downloadUrl!=null){ //取消下载,并且删除文件,关闭通知 String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); File file = new File(directory+fileName); if (file.exists()){ file.delete(); } getNotifcationManager().cancel(1); stopForeground(true); Toast.makeText(DownloadService.this,"Canceled",Toast.LENGTH_SHORT).show(); } } } } private Notification getNotification(String title, int progress) { Intent intent = new Intent(this, MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.a)); builder.setContentIntent(pi); builder.setContentTitle(title); if (progress>0){ builder.setContentText(progress+"%"); //是否使用模糊进度条 builder.setProgress(100,progress,false); } return builder.build(); } private NotificationManager getNotifcationManager() { return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); } private DownloadBinder mBinder = new DownloadBinder(); @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; }}
- Activity代码
public class MainActivity extends AppCompatActivity { private DownloadService.DownloadBinder downloadBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { downloadBinder = (DownloadService.DownloadBinder) iBinder; } @Override public void onServiceDisconnected(ComponentName componentName) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); openService(); //权限管理 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1); } } private void openService() { Intent intent = new Intent(this,DownloadService.class); startService(intent); bindService(intent,connection,BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); unbindService(connection); } public void start(View view){ if (downloadBinder==null){ return; } String url = "http://a5.pc6.com/pc6_soure/2016-1/1275710C30G3f92Q.apk"; downloadBinder.startDownload(url); } public void pause(View view){ if (downloadBinder==null){ return; } downloadBinder.pauseDownload(); } public void cancel(View view){ if (downloadBinder==null){ return; } downloadBinder.CancelDownload(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode){ case 1: if (grantResults.length>0 && grantResults[0]!=PackageManager.PERMISSION_GRANTED){ Toast.makeText(this,"拒绝权限将无法使用程序",Toast.LENGTH_SHORT).show(); } break; } }}
阅读全文
0 0
- 使用okhttp和前台服务实现断点续传功能
- 使用OkHttp实现下载的进度监听和断点续传
- 【Android】- OkHttp实现断点续传
- OkHttp实现断点续传
- OkHttp实现断点续传
- 使用.NET实现断点续传功能
- okhttp使用,支持断点续传
- Android okhttp+rxjava实现多文件下载和断点续传
- Android okhttp+rxjava实现多文件下载和断点续传
- Android okhttp+rxjava实现多文件下载和断点续传
- service+okhttp实现断点续传下载
- 断点续传功能的实现
- OKHttp实现大文件的断点续传
- OkHttp使用+文件的上传+断点续传
- iphone开发--使用ASIHTTPRequest实现下载,断点续传功能
- Android使用AsyncTask实现可以断点续传的DownloadManager功能
- Android使用AsyncTask实现可以断点续传的DownloadManager功能
- Android使用AsyncTask实现可以断点续传的DownloadManager功能
- 数值分析牛顿切线法python3实现并绘图
- 14. Longest Common Prefix
- centos7下安装docker
- ElasticSearch使用流程
- HTML和CSS适应不同终端屏幕的实现(附typecho CSS文件)
- 使用okhttp和前台服务实现断点续传功能
- Mathematica入门使用攻略
- C#分解质因数
- 第四篇:对cifar-10数据集的读取
- 设计模式(九)——代理模式(Proxy)
- 我的python学习笔记.嵌套
- Ubuntu 中安装最新版的 Node.js 和 npm
- java集合框架简介
- linux下的绝对路径和相对路径