使用AsyncTask下载+Service+通知连Notification(控制下载暂停或取消)
来源:互联网 发布:lbp算法matlab 编辑:程序博客网 时间:2024/05/17 02:34
通过阅读郭霖《第一行代码》第二版 服务最佳实践启发,写的小案例
实现通知栏显示下载进度,两个按钮:暂停下载,取消下载(删除下载文件)。
首先在创建工程之后,写一个接口inControllerDownLoad用来回调暂停,取消,ProgressBar进度,下载成功,下载失败,如下:
public interface inControllerDownLoad { public void onProgress(int progress); public void onCancle(); public void onPaused(); public void onSuccess(); public void onFailed();}
接着需要写一个线程用来实现文件下载,我们继承AsysncTask命名为DownLoadAsysncTask
代码里叙述AsysncTask使用,上代码:
package com.huida.notificationdemo;import android.content.Context;import android.content.Intent;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 Json on 2017/9/19. *//** * 继承AsyncTask发现有三个泛型参数 * 第一个String表示在执行此线程时候需要传入一个字符串参数 * 第二参数Integer表示用整型数据来作为进度显示单位 * 第三个参数Integer表示使用整型数据来反馈执行结果 */public class DownLoadAsysncTask extends AsyncTask<String, Integer, Integer> { private final inControllerDownLoad inController; public static final int SUCCESS = 0; public static final int FAILED = 1; public static final int PAUSED = 2; public static final int CANCELED = 3; private final Context context; private boolean isCancled = false; private boolean isPaused = false; private int lastProgress; private String downloadUrl; private File file; private RandomAccessFile savedFile; public DownLoadAsysncTask(inControllerDownLoad inter, Context context) { this.context = context; this.inController = inter; } /** * 线程在此方法中执行 downLoadAsysncTask.execute("http://mpge.5nd.com/2016/2016-11-15/74847/1.mp3");这里开启线程 * 参数可以为多个,这里只写了一个参数 * * @param strings * @return */ @Override protected Integer doInBackground(String... strings) { InputStream is = null; long downloadLength = 0;//记录已经下载文件长度 downloadUrl = strings[0];//通过第一个参数拿到下载链接 String fileName = Environment.getExternalStoragePublicDirectory (Environment.DIRECTORY_DOWNLOADS).getPath() + "测试下载"; file = new File(fileName); if (file != null) { downloadLength = file.length();//获取文件所下载的字节长度 } long countLength = 0; try { countLength = getContentLength(downloadUrl);//获取需要下载文件的总长度 if (downloadLength == countLength) { return SUCCESS;//如果一直 那么下载成功 } if (countLength == 0) { return FAILED;//如果总长为0 表示请求失败 } //这里用到Okhttp 需要在app下的build.gradle 添加依赖 compile 'com.squareup.okhttp3:okhttp:3.8.1' Response response = new OkHttpClient().newCall(new Request.Builder() .addHeader("RANGE", "bytes=" + file.length() + "-").url(downloadUrl).build()) .execute(); //"RANGE","bytes=" + file.length() + "-",表示从服务器请求file.length() 之后数据,注意格式bytes后有等于号 if (response.body() != null) { //获取到file.length()字节之后的流 is = response.body().byteStream(); //通过RandomAccessFile写入 savedFile = new RandomAccessFile(file, "rw"); //将指针指向file.length() savedFile.seek(file.length()); byte[] buff = new byte[1024]; int len; while ((len = is.read(buff)) != -1) { //在下载向文件中写数据时候,如果用户调用了pausedDownLoad(),和cancelDownLoad()方法会监听到此 //isCancled,isPaused会改变值 以下进行判断 if (isCancled) { return CANCELED; } else if (isPaused) { return PAUSED; } else { if (file.length() >= countLength) { break; } savedFile.write(buff, 0, len); int progress = (int) ((file.length()) * 100 / countLength); publishProgress(progress);//AsyscTask的方法表示更新Progress会调用下方onProgressUpdate()方法 } } response.body().close(); //到此表示流正常写入 返回成功 return SUCCESS; } } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } if (savedFile != null) { savedFile.close(); } if (isCancled && file != null) { file.delete(); } } catch (Exception e) { e.printStackTrace(); } } return FAILED; } 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.body() != null && response.isSuccessful()) { response.body().close(); return response.body().contentLength(); } return 0; } /** * 表示在线程执行前的准备工作 */ @Override protected void onPreExecute() { super.onPreExecute(); } /** * 这里线程执行完成之后调用,此方法中会在主线程执行 * 判断 线程执行完的返回值,AsyncTask<String, Integer, Integer>第三个参数对应, * 也是doInBackground(String... strings) 的返回值 * * @param integer */ @Override protected void onPostExecute(Integer integer) { switch (integer) { case SUCCESS: inController.onSuccess(); break; case CANCELED: inController.onCancle(); //取消之后接着删除该文件 只有在下载过程中能监听到 if (file != null) { file.delete(); } isCancled = false; break; case PAUSED: inController.onPaused(); break; case FAILED: inController.onFailed(); break; } } /** * 表示更新操作 也是在主线程中执行 * * @param values 可以为多个 我们在上方 publishProgress(progress);只传入一个 */ @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; if (progress > lastProgress) { //这里回调接口的更新操作 inController.onProgress(progress); lastProgress = progress; } } /** * 暴露次方法用来暂停或继续下载 * * @param isPaused true表示暂停,false表示继续下载 */ public void pausedDownLoad(boolean isPaused) { this.isPaused = isPaused; if (!isPaused) { Intent intent = new Intent(context, DownLoadService.class); intent.putExtra("status", "begin"); context.startService(intent); } } /** * 暴露此方法用来取消下载(会删除该下载文件) */ public void cancelDownLoad() { isCancled = true; }}
线程已经准备好了,这里我们打算在服务中开启此线程,我们写一个服务
DownLoadService 代码里都有注释ackage com.huida.notificationdemo;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.SystemClock;import android.support.annotation.Nullable;import android.support.v4.app.NotificationCompat;import android.widget.RemoteViews;import android.widget.Toast;import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;/** * Created by Json on 2017/9/19. */public class DownLoadService extends Service { private static boolean isPause = true;//用来判断暂停还是继续下载 private DownLoadAsysncTask downLoadAsysncTask; //实现该接口 实现的方法会在downLoadAsysncTask进行回调 private inControllerDownLoad inControllerDownLoad = new inControllerDownLoad() { @Override public void onProgress(int progress) { /** * getNotificationManager().notify();开启通知栏 * 两个参数 * int id:给我们的Notification 设置id 唯一标识 * Notification:需要我们写的通知栏 */ getNotificationManager().notify(1, getNotification("Downloading...", progress)); } @Override public void onCancle() { stopForeground(true);//取消 通知关闭 getNotificationManager().notify(1, getNotification("取消", -1)); getNotificationManager().cancel(1); downLoadAsysncTask=null; } @Override public void onPaused() { getNotificationManager().notify(1, getNotification("暂停", -1)); Toast.makeText(DownLoadService.this, "暂停", Toast.LENGTH_SHORT).show(); } @Override public void onSuccess() { getNotificationManager().notify(1, getNotification("下载完成", -1)); Toast.makeText(DownLoadService.this, "DownLoadSuccess", Toast.LENGTH_SHORT).show(); stopForeground(true);//下载成功 通知关闭 getNotificationManager().cancel(1); downLoadAsysncTask=null; } @Override public void onFailed() { stopForeground(false); getNotificationManager().notify(1, getNotification("下载失败", -1)); Toast.makeText(DownLoadService.this, "DownLoadFailed", Toast.LENGTH_SHORT).show(); } }; /** * * @param s 通知栏显示的数据 * @param progress 通知栏上progress的进度 * @return */ private Notification getNotification(String s, int progress) { NotificationCompat.Builder builder = new NotificationCompat.Builder(this); //使用RemoteViews进行自定义通知栏 RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.download_contllor); //暂停按钮的点击事件 Intent pauseIntent = new Intent(this, DownLoadService.class); pauseIntent.putExtra("status", "pause"); /*PendingIntent 相当于Inteng进行封装了一层 这个通过getService()得到, 也可以通过getBroadcast(),与我们需要的意图Intent第二参数类型相对应 参数1 上下文 参数2 int requestCode 该PendingIntent的唯一标识,不能重复,否则会判定为同一个PendingIntent 用户自己定义 参数3 PendingIntent.FLAG_UPDATE_CURRENT 表示 通过requestCode 判断是否有该PendingIntent 如果有进行更新 */ PendingIntent pausePendingIntent = PendingIntent.getService(this, 1, pauseIntent, PendingIntent.FLAG_UPDATE_CURRENT); //给RemoteViews设置点击事件 表示子控件的点击事件 remoteViews.setOnClickPendingIntent(R.id.bt_pause, pausePendingIntent); //取消按钮的点击事件 Intent goneIntent = new Intent(this, DownLoadService.class); goneIntent.putExtra("status", "gone"); PendingIntent canclePendingIntent = PendingIntent.getService(this, 0, goneIntent, FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.bt_cancle, canclePendingIntent); //此通知的点击事件 随意跳转了 到MainActivity中 Intent goMainActivity=new Intent(this,MainActivity.class); remoteViews.setOnClickPendingIntent(R.id.remoteView ,PendingIntent.getActivity(this, 2, goMainActivity, FLAG_UPDATE_CURRENT)); builder.setContent(remoteViews); remoteViews.setProgressBar(R.id.seek, 100, progress, false); remoteViews.setTextViewText(R.id.tv, s); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setWhen(SystemClock.currentThreadTimeMillis()); return builder.build(); } /** * 获取到系统NotificationManager * @return */ private NotificationManager getNotificationManager() { return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { String status = intent.getStringExtra("status"); switch (status) { case "begin": startDownLoad(); break; case "gone": if (downLoadAsysncTask != null) { downLoadAsysncTask.cancelDownLoad(); } break; case "pause": if (downLoadAsysncTask != null) { downLoadAsysncTask.pausedDownLoad(isPause); isPause = !isPause; } break; } return super.onStartCommand(intent, flags, startId); } /** * 开启DownLoadAsysncTask传入我们实现的接口 和上下文 */ private void startDownLoad() { downLoadAsysncTask = new DownLoadAsysncTask(inControllerDownLoad, this); downLoadAsysncTask.execute("http://mpge.5nd.com/2016/2016-11-15/74847/1.mp3"); }}
此时基本完事 别忘了去AndroidManifest.xml将服务注册,在MainActivity直接调用开启服务package com.huida.notificationdemo;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //进来我直接调用服务进行开启下载线程 findViewById(R.id.bt_start_download).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this, DownLoadService.class); intent.putExtra("status","begin"); startService(intent); } }); }}
基本一个简单的通知栏下载进度完成
思路可以学习一下,我也是自行写的demo可能还有很多不完善的地方大家见谅
阅读全文
0 0
- 使用AsyncTask下载+Service+通知连Notification(控制下载暂停或取消)
- Service + Notification(通知栏)实现断点下载
- Okhttp、AsyncTask、service下载
- Service与Notification的结合使用实现文件下载
- 使用AsyncTask下载图片
- Service结合通知下载图片
- Notification通知 模拟下载 小例子
- 使用Service下载图片并发送通知读取图片内容
- 使用service实现通知栏下载支持断点续传
- Android实现Service后台下载Notification进度条
- Android实现Service后台下载Notification进度条
- 利用service下载图片&发送进度notification
- Android实现Service后台下载Notification进度条
- Notification+BroadcastReciver+Service实现推送下载
- Android中Service+Notification断点续传下载
- Service组件+Notification断点续传下载(Android)
- 多线程下载文件(支持暂停、取消、断点续传)
- 多线程下载文件(支持暂停、取消、断点续传)
- Qt connect中的 Lambda
- 二进制中1的个数
- 微信公众号开发流程步骤-微信开发教程10
- 工作管理
- http://www.nvidia.cn/object/what-is-gpu-computing-cn.html
- 使用AsyncTask下载+Service+通知连Notification(控制下载暂停或取消)
- 【动态】IAB科技实验室为广告业成立区块链工作组
- 【观点】以太坊创始人认为区块链技术将在几年内抢走Visa的业务
- 【动态】以太坊Metropolis硬分叉首次迭代将出现
- 【资讯】三菱UFJ金融集团CEO:银行加密货币“与比特币无任何关联”
- 汉诺塔(三)
- 【解读】专家:中国监管机构关闭比特币交易所的七大原因
- 【行业】日本证券经纪公司探索如何使用区块链简化业务流程
- 【研究】剑桥大学加密货币研究重大发现