使用service实现通知栏下载支持断点续传
来源:互联网 发布:电脑壁纸软件哪个好 编辑:程序博客网 时间:2024/05/18 00:03
先看一下效果
首先写一个监听器用来处理返回结果
public interface DownloadListener { void onProgress(int progreess); void onPuase(); void onCancel(); void onFailed(); void onSuccess();}
然后写一个异步任务来下载,在异步任务中传入DownloadListener 来处理下载的情况。使用异步任务的目的是为了能根据返回值方便的处理监听。
package down;import android.os.AsyncTask;import android.os.Environment;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;/** * Created by yuanteng on 2017/6/30. */public class DownLoadTask extends AsyncTask<String,Integer,Integer> { public static final int TYPE_SUCESS = 0; public static final int TYPE_FAILED = 1; public static final int TYPE_PAUSE = 2; public static final int TYPE_CANCEL = 3; private boolean isCancel = false; private boolean isPause = false; private DownloadListener listener; private int lastProgress; public DownLoadTask(DownloadListener listener){ this.listener = listener; } @Override protected Integer doInBackground(String... strings) { InputStream inputStream = null; //随机读取文件类可以指定文件从哪个地方开始写入,所以不用OutputStream RandomAccessFile saveFile = null; long downLoadLength = 0;//记录已经下载下的长度 File file = null; try { String downUrl = strings[0]; String fileName = downUrl.substring(downUrl.lastIndexOf("/")); String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); file = new File(dir + fileName); if (file.exists()){ downLoadLength = file.length(); } long contentLength = getContentLength(downUrl); if (contentLength == 0){ return TYPE_FAILED; } if (contentLength == downLoadLength){ return TYPE_SUCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() //断点下载 .addHeader("RANGE","bytes="+downLoadLength+"-") .url(downUrl) .build(); Response response = client.newCall(request).execute(); if (response != null && response.isSuccessful()){ inputStream = response.body().byteStream(); saveFile = new RandomAccessFile(file,"rw"); //断点续传 saveFile.seek(downLoadLength); byte[] b = new byte[4096]; int total = 0; int len ; while ((len = inputStream.read(b)) != -1){ if (isCancel){ return TYPE_CANCEL; } else if (isPause){ return TYPE_PAUSE; } else { total += len; saveFile.write(b,0,len); int progress = (int)((total + downLoadLength)*100/contentLength); publishProgress(progress); } } response.body().close(); return TYPE_SUCESS; } } catch (Exception e){ e.printStackTrace(); } finally { try { if (inputStream != null){ inputStream.close(); } if (saveFile != null){ saveFile.close(); } if (isCancel && file != null){ file.delete(); } } catch (IOException e){ e.printStackTrace(); } } return TYPE_FAILED; } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); int progress = values[0]; if (progress > lastProgress){ listener.onProgress(progress); lastProgress = progress; } } /*根据不同的返回值进行处理*/ @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); switch (integer){ case TYPE_SUCESS: listener.onSuccess(); break; case TYPE_CANCEL: listener.onCancel(); break; case TYPE_PAUSE: listener.onPuase(); break; case TYPE_FAILED: listener.onFailed(); break; default: break; } } /*改变暂停或者取消的状态*/ public void pauseDownLoad(){ isPause = true; } public void cancelDownLoad(){ isCancel = true; } /* * 获取文件的长度*/ private long getContentLength(String downUrl){ OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(downUrl).build(); try { Response response = okHttpClient.newCall(request).execute(); if (response != null && response.isSuccessful()){ long length = response.body().contentLength(); response.close(); return length; } } catch (IOException e) { e.printStackTrace(); } return 0; }}
现在是关键部分写一个service
package down;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.graphics.BitmapFactory;import android.os.Binder;import android.os.Environment;import android.os.IBinder;import android.support.v7.app.NotificationCompat;import com.petecc.potevio.testvitmionew.MainActivity;import com.petecc.potevio.testvitmionew.R;import com.petecc.potevio.testvitmionew.TestDownLoadActivity;import java.io.File;public class DownLoadService extends Service { private DownLoadTask downLoadTask; private String downloadUrl; private DownloadListener listener = new DownloadListener() { @Override public void onProgress(int progreess) { getNotificationManager().notify(1,getNotification("下载中...",progreess)); } @Override public void onPuase() { downLoadTask = null; } @Override public void onCancel() { downLoadTask = null; //将前台服务通知关闭 stopForeground(true); } @Override public void onFailed() { downLoadTask = null; //将前台服务通知关闭,并创建一个下载失败通知 stopForeground(true); getNotificationManager().notify(1,getNotification("下载失败!",-1)); } @Override public void onSuccess() { downLoadTask = null; //将前台服务通知关闭,并创建一个下载成功通知 stopForeground(true); getNotificationManager().notify(1,getNotification("下载成功!",-1)); } }; public DownLoadService() { } private DownLoadBinder downLoadBinder = new DownLoadBinder(); @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return downLoadBinder; } public class DownLoadBinder extends Binder{ public void startDownLoad(String url){ if (downLoadTask == null){ downloadUrl = url; downLoadTask = new DownLoadTask(listener); downLoadTask.execute(url); //开启前台服务,保证在内存低的情况下服务不会被杀死。同时系统会创建一个notification startForeground(1,getNotification("下载中...",0)); } } public void pauseDownload(){ if (downLoadTask != null){ downLoadTask.pauseDownLoad(); } } public void cancelDownload(){ if (downLoadTask != null){ downLoadTask.cancelDownLoad(); } else{ //如果downloadUrl不等于null删除已经下载的文件,并关闭通知 if (downloadUrl != null){ String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/")); String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); File file = new File(dir+fileName); if (file.exists()){ file.delete(); } getNotificationManager().cancel(1); //取消前台服务 stopForeground(true); } } } } /*获取Notification*/ private Notification getNotification(String title,int progress){ //intent 需要根据自己的需要来制定 Intent intent = new Intent(DownLoadService.this, TestDownLoadActivity.class); PendingIntent penIntent = PendingIntent.getActivity(DownLoadService.this,0,intent,PendingIntent.FLAG_ONE_SHOT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setContentTitle(title); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)); builder.setAutoCancel(true); builder.setWhen(System.currentTimeMillis()); builder.setContentIntent(penIntent); if (progress >= 0){ builder.setContentText(progress+" %"); builder.setProgress(100,progress,false); } return builder.build(); } /*获取NotificationManager*/ private NotificationManager getNotificationManager(){ return ((NotificationManager) getSystemService(NOTIFICATION_SERVICE)); }}
测试使用
import android.Manifest;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.content.pm.PackageManager;import android.os.Bundle;import android.os.IBinder;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.Toast;import butterknife.BindView;import butterknife.ButterKnife;import butterknife.OnClick;import down.DownLoadService;public class TestDownLoadActivity extends AppCompatActivity { @BindView(R.id.start) Button start; @BindView(R.id.pause) Button pause; @BindView(R.id.cancel) Button cancel; @BindView(R.id.agin) Button agin; private DownLoadService.DownLoadBinder binder; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (DownLoadService.DownLoadBinder) iBinder; } @Override public void onServiceDisconnected(ComponentName componentName) { } }; private String path = "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_down_load); ButterKnife.bind(this); Intent intent = new Intent(this, DownLoadService.class); startService(intent); bindService(intent, serviceConnection, BIND_AUTO_CREATE); //检查权限是否授权 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } @OnClick({R.id.start, R.id.pause, R.id.cancel,R.id.agin}) public void onViewClicked(View view) { if (binder == null) { return; } switch (view.getId()) { case R.id.start: binder.startDownLoad(path); break; case R.id.pause: binder.pauseDownload(); break; case R.id.cancel: binder.cancelDownload(); break; case R.id.agin: binder.startDownLoad("http://imgsrc.baidu.com/image/c0%3Dshijue%2C0%2C0%2C245%2C40/sign=2f6a98db3cd3d539d530078052ee8325/8c1001e93901213f5e8ef6f95ee736d12f2e9552.jpg"); break; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case 1: if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "无法使用", Toast.LENGTH_SHORT).show(); finish(); } } } @Override protected void onDestroy() { super.onDestroy(); unbindService(serviceConnection); } @OnClick(R.id.agin) public void onViewClicked() { }}
记得在清单文件注册service
android:name="down.DownLoadService" android:enabled="true" android:exported="true" />
所有代码就这么多,除布局文件都已经贴出!
欢迎点赞!
阅读全文
0 0
- 使用service实现通知栏下载支持断点续传
- Android 使用service实现多线程断点续传下载
- service+okhttp实现断点续传下载
- Service + Notification(通知栏)实现断点下载
- C#: 实现支持断点续传多线程下载的
- C#: 实现支持断点续传多线程下载
- C#实现文件下载,支持断点续传
- C#实现文件下载,支持断点续传
- Android Service 实现下载,实现前台、通知栏同步更新
- Android 使用Service、Thread实现断点续传思路
- Python 使用urllib2模块实现断点续传下载
- iOS开发 使用NSURLConnection实现断点续传下载
- 使用OKHttp3实现下载(断点续传、显示进度)
- Net/C#: 实现支持断点续传多线程下载2
- Delphi实现Ftp客户端下载(支持断点续传,多线程传输)
- vc++ socket实现的支持断点续传的下载器
- vc++ socket实现的支持断点续传的下载器
- Delphi实现Ftp客户端下载(支持断点续传,多线程传输)
- Struts2的类型转换
- 几乎有序数组排序
- gradlew编译时出现Unsupported major.minor version 52.0
- k数和-LintCode
- 存储过程
- 使用service实现通知栏下载支持断点续传
- 通过bcc 使用ebpf
- Linux笔记 命令行
- MFC让对话框窗口始终在最前&MFC弹出非模态对话框
- 一行代码解决各种IE兼容问题
- 深入理解Java:注解(Annotation)--注解处理器
- 某年某月有几天?(代码)
- python中列表,元组,字符串如何互相转换
- 源码解读腾讯 GT 的性能测试方案