android断点续传多线程下载
来源:互联网 发布:网络教育专科多少费用 编辑:程序博客网 时间:2024/06/06 17:40
活动
public class MainActivity extends AppCompatActivity implements View.OnClickListener{private DownloadService.DownloadBinder downloadBinder;private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { } @Override public void onServiceConnected(ComponentName name, IBinder service) { downloadBinder = (DownloadService.DownloadBinder) service; }};@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button startDownload = (Button) findViewById(R.id.start_download); Button pauseDownload = (Button) findViewById(R.id.pause_download); Button cancelDownload = (Button) findViewById(R.id.cancel_download); startDownload.setOnClickListener(this); pauseDownload.setOnClickListener(this); cancelDownload.setOnClickListener(this); Intent intent = new Intent(this, DownloadService.class); startService(intent); // 启动服务,保证DownloadService在后台运行 bindService(intent, connection, BIND_AUTO_CREATE); // 绑定服务,活动和服务交互 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission. WRITE_EXTERNAL_STORAGE }, 1); }//获取SD卡权限}@Overridepublic void onClick(View v) { if (downloadBinder == null) { return; } switch (v.getId()) { case R.id.start_download: String url = "http://192.168.37.23:8080/axis2/xml/get_data.xml"; downloadBinder.startDownload(url); break; case R.id.pause_download: downloadBinder.pauseDownload(); break; case R.id.cancel_download: downloadBinder.cancelDownload(); break; default: break; }}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 1: if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show(); finish(); } break; default: }}@Overrideprotected void onDestroy() { super.onDestroy(); unbindService(connection);}}
异步任务
这里我们用到了OkHttp所以要在gradle中添加依赖库:
compile ‘com.squareup.okhttp3:okhttp:3.8.1’
/*第一个参数String表示在执行AsyncTask任务时传入一个字符串参数第二个参数Integer表示使用整型数据来显示下载进度第三个参数Integer表示使用整型数据来执行反馈结果*/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;//将下载的状态通过DownloadListener进行回调public DownloadTask(DownloadListener listener) { this.listener = listener;}@Override//后台执行下载的具体逻辑protected Integer doInBackground(String... params) { InputStream is = null; RandomAccessFile savedFile = null;//随机读取和写入文件 File file = null; try { long downloadedLength = 0; // 记录已下载的文件长度 String downloadUrl = params[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");//创建一个随机访问文件流从File参数指定的文件中读取,并可选地写入文件 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; }}@Override//通知下载结果protected void onPostExecute(Integer status) { switch (status) { case TYPE_SUCCESS: listener.onSuccess(); break; case TYPE_FAILED: listener.onFailed(); break; case TYPE_PAUSED: listener.onPaused(); break; case TYPE_CANCELED: listener.onCanceled(); default: 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 class DownloadService extends Service {private DownloadTask downloadTask;private String downloadUrl;private DownloadListener listener = new DownloadListener() { @Override public void onProgress(int progress) { getNotificationManager().notify(1, getNotification("Downloading...", progress)); } @Override public void onSuccess() { downloadTask = null; // 下载成功时将前台服务通知关闭,并创建一个下载成功的通知 stopForeground(true); getNotificationManager().notify(1, getNotification("Download Success", -1)); Toast.makeText(DownloadService.this, "Download Success", Toast.LENGTH_SHORT).show(); } @Override public void onFailed() { downloadTask = null; // 下载失败时将前台服务通知关闭,并创建一个下载失败的通知 stopForeground(true); getNotificationManager().notify(1, getNotification("Download Failed", -1)); Toast.makeText(DownloadService.this, "Download Failed", 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(); }};private DownloadBinder mBinder = new DownloadBinder();@Overridepublic IBinder onBind(Intent intent) { return mBinder;}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, "Downloading...", 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(); } getNotificationManager().cancel(1); stopForeground(true); Toast.makeText(DownloadService.this, "Canceled", Toast.LENGTH_SHORT).show(); } } }}private NotificationManager getNotificationManager() { return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);}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.mipmap.ic_launcher)); builder.setContentIntent(pi); builder.setContentTitle(title); if (progress >= 0) { // 当progress大于或等于0时才需显示下载进度 builder.setContentText(progress + "%"); builder.setProgress(100, progress, false); } return builder.build();}}
阅读全文
0 0
- android 多线程断点续传下载
- Android多线程.断点续传下载
- android 多线程断点续传下载
- Android 多线程下载断点续传
- Android多线程断点续传下载
- Android多线程断点续传下载
- android多线程断点续传下载
- android 多线程下载断点续传
- android多线程断点续传下载
- Android多线程断点续传下载
- Android多线程下载断点续传
- Android多线程断点续传下载
- Android多线程断点续传下载
- Android多线程断点续传下载
- android断点续传多线程下载
- android 多线程断点续传下载
- android 多线程断点续传下载
- Android--多线程断点续传下载器
- 剑指offer_栈和队列---栈的压入,弹出序列
- PHP知识细节
- ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1'
- ajax动态赋值highcharts柱形图
- Android进阶#(6/12)让程序更优的技术——性能优化_内存泄漏
- android断点续传多线程下载
- 网络栈主要结构介绍(socket、sock、sk_buff,etc)
- 赢在面试之Java集合框架篇
- 一位资深程序员大牛给予Java初学者的学习路线建议
- 《华为机试在线训练》之数据分类处理
- 【转载】$("body").animate({"scrollTop":top})不被Firefox支持问题的解决
- NYOJ 325 zb的生日
- kubernetes学习记录(0)——学习记录阅读顺序
- 常见的TCP定时器