概述
实现App常见下载公共 支持通知栏显示 支持 暂停、取消功能,使用Service、AsyncTask实现异步下载。特点简单、实用、方便源码扩展修改
详细
代码下载:http://www.demodashi.com/demo/11216.html
一、准备工作
1、项目运行环境AndroidStudio
3、通过Service、AsyncTask实现异步下载,并通过通知栏显示下载进度。
二、程序实现
1、工程目录
2、在AsyncTask中实现下载操作
public DownloadTask(DownloadListener listener) {
this.listener = listener;
}
/**
* 执行具体下载逻辑
* @param strings
* @return 下载状态
*/
@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);//将文件指定下载到SD卡的Download目录下
if (file.exists()) {//判断是否已存在文件,是:取出文件大小(字节数)
downloadedLength = file.length();
}
long contentLength = getContentLength(downloadUrl);//获取待下载文件大小(字节数)
if (contentLength == 0) {//长度为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[] bytes = new byte[1024];
int total = 0;
int len;
while ((len = is.read(bytes)) != -1) {
if (isCanceled) {//判断是否有取消操作
return TYPE_CANCELED;
} else if (isPaused) {//判断是否有暂停操作
return TYPE_PAUSED;
} else {
total += len;
savedFile.write(bytes, 0, len);
//计算已下载百分比
int progress = (int) ((total + downloadedLength) * 100 / contentLength);
publishProgress(progress);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
return TYPE_FAILED;
}
/**
* 更新下载进度
* @param values
*/
@Override
protected void onProgressUpdate(Integer... values) {
int progress = values[0];
if (progress > lastProgress) {
listener.onProgress(progress);
lastProgress = progress;
}
}
/**
* 通知下载结果
* @param type
*/
@Override
protected void onPostExecute(Integer type) {
switch (type) {
case TYPE_SUCCESS:
listener.onSuccess();
break;
case TYPE_FAILED:
listener.onFailed();
break;
case TYPE_PAUSED:
listener.onPaused();
break;
case TYPE_CANCELED:
listener.onCanceled();
break;
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.body().close();
return contentLength;
}
return 0;
}
3、使用interface观察者模式监听下载动作
public interface DownloadListener {
//当前下载进度
void onProgress(int progress);
//下载成功
void onSuccess();
//下载失败
void onFailed();
//下载暂停
void onPaused();
//下载取消
void onCanceled();
}
4、在Service中初始化AsyncTask并实例化监听
private DownloadTask downloadTask;
private String downloadUrl;
private DownloadListener downloadListener = new DownloadListener() {//创建Download实例
@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,"Download Paused",Toast.LENGTH_SHORT).show();
}
@Override
public void onCanceled() {
downloadTask = null;
stopForeground(true);
Toast.makeText(DownloadService.this,"Download Canceled",Toast.LENGTH_SHORT).show();
}
};
5、创建下载进度通知栏
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_round);
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();
}
6.创见DownloadBinder类,与外部建立连接
private DownloadBinder mBinder = new DownloadBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
class DownloadBinder extends Binder{
public void startDownload(String url){
if (downloadTask == null){
downloadUrl = url;
downloadTask = new DownloadTask(downloadListener);
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();
}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();
}
}
}
public void cancelDownload(){
if (downloadTask != null){
downloadTask.cancelDownload();
}
}
}
7、绑定Service
private DownloadService.DownloadBinder downloadBinder;
private ServiceConnection serviceConnection = 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);
Intent intent = new Intent(this,DownloadService.class);
startService(intent);//启动服务
bindService(intent,serviceConnection,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);
}
}
三、运行效果
1、调用方法
public void startDownload(View view) {
if (downloadBinder == null){
return;
}
String url = "your URL (你的下载路径)";
downloadBinder.startDownload(url);
}
public void pauseDownload(View view) {
if (downloadBinder == null){
return;
}
downloadBinder.pauseDownload();
}
public void cancelDownload(View view) {
if (downloadBinder == null){
return;
}
downloadBinder.cancelDownload();
}
3、运行时的截图
四、其他补充
1、如何修改通知栏样式?
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher_round);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentIntent(pi);
builder.setContentTitle(title);
2、不了解Service、AsyncTask?
Android Service(服务)详解·(一)相关知识点引入
Android Service(服务)详解·(二)Service基本用法
3、还有疑问?
请联系我 留言 或者 E-mail : duyangs1994@gmail.com
一起学习,一起进步
代码下载:http://www.demodashi.com/demo/11216.html
注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权
原文链接:https://blog.csdn.net/findhappy117/article/details/79358179
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。
还没有人抢沙发呢~