Android中Service+Notification断点续传下载
来源:互联网 发布:免费股票交易软件 编辑:程序博客网 时间:2024/06/13 05:21
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53874148
本文出自【DylanAndroid的博客】
Android中Service+Notification断点续传下载
在Android开发中,我们经常会用到例如版本更新这种的文件下载,那么如何用service+notification去做一个支持断点续传的
文件下载呢?效果图如下
一.在启动Activity中启动Service
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(this, TaskService.class); startService(intent); }}
2.在Service的启动命令中注册按钮点击广播
@Override public int onStartCommand(Intent intent, int flags, int startId) { registerBroadCast(); download(); return super.onStartCommand(intent, flags, startId); }/** * 注册按钮点击广播* */ private void registerBroadCast() { myBroadcastReceiver = new MyBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(BROADCAST_ACTION_CLICK); registerReceiver(myBroadcastReceiver, filter); } /** * 更新通知界面的按钮的广播 */ private class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!intent.getAction().equals(BROADCAST_ACTION_CLICK)) { return; } Logger.d("status=" + status); switch (status) { case DOWNLOADING: /**当在下载中点击暂停按钮**/ cancelable.cancel(); mRemoteViews.setTextViewText(R.id.bt, "下载"); mRemoteViews.setTextViewText(R.id.tv_message, "暂停中..."); status = Status.PAUSE; notificationManager.notify(NOTIFICATION_ID, notification); break; case SUCCESS: /**当下载完成点击完成按钮时关闭通知栏**/ notificationManager.cancel(NOTIFICATION_ID); break; case FAIL: case PAUSE: /**当在暂停时点击下载按钮**/ download(); mRemoteViews.setTextViewText(R.id.bt, "暂停"); mRemoteViews.setTextViewText(R.id.tv_message, "下载中..."); status = Status.DOWNLOADING; notificationManager.notify(NOTIFICATION_ID, notification); break; } } }
3.开始下载用xutils3
/** * 下载文件 */ private void download() { final String url = "https://github.com/linglongxin24/DylanStepCount/raw/master/app-debug.apk"; RequestParams requestParams = new RequestParams(url); String fileName = url.substring(url.lastIndexOf("/") + 1); file = new File(filePath, fileName); showNotificationProgress(TaskService.this); showFileName(fileName); requestParams.setSaveFilePath(file.getPath()); /**自动为文件命名**/ requestParams.setAutoRename(true); /**自动为文件断点续传**/ requestParams.setAutoResume(true); cancelable = x.http().get(requestParams, new Callback.ProgressCallback<File>() { @Override public void onSuccess(File result) { Logger.d("下载完成"); Logger.d("result=" + result.getPath()); downloadSuccess(); } @Override public void onError(Throwable ex, boolean isOnCallback) { Logger.d("下载异常"); downloadFail(); } @Override public void onCancelled(CancelledException cex) { Logger.d("下载已取消"); } @Override public void onFinished() { } @Override public void onWaiting() { } @Override public void onStarted() { } @Override public void onLoading(long total, long current, boolean isDownloading) { Logger.d("total=" + total + "--" + "current=" + current); updateNotification(total, current); } }); }
4.显示通知
/** * 显示一个下载带进度条的通知 * * @param context 上下文 */ public void showNotificationProgress(Context context) { /**进度条通知构建**/ NotificationCompat.Builder builderProgress = new NotificationCompat.Builder(context); /**设置为一个正在进行的通知**/ builderProgress.setOngoing(true); /**设置小图标**/ builderProgress.setSmallIcon(R.mipmap.ic_launcher); /**新建通知自定义布局**/ mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.notification); /**进度条ProgressBar**/ mRemoteViews.setProgressBar(R.id.pb, 100, 0, false); /**提示信息的TextView**/ mRemoteViews.setTextViewText(R.id.tv_message, "下载中..."); /**操作按钮的Button**/ mRemoteViews.setTextViewText(R.id.bt, "暂停"); /**设置左侧小图标*/ mRemoteViews.setImageViewResource(R.id.iv, R.mipmap.ic_launcher); /**设置通过广播形式的PendingIntent**/ Intent intent = new Intent(BROADCAST_ACTION_CLICK); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_BROADCAST, intent, 0); mRemoteViews.setOnClickPendingIntent(R.id.bt, pendingIntent); /**设置自定义布局**/ builderProgress.setContent(mRemoteViews); /**设置滚动提示**/ builderProgress.setTicker("开始下载..."); notification = builderProgress.build(); /**设置不可手动清除**/ notification.flags = Notification.FLAG_NO_CLEAR; /**获取通知管理器**/ notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE); /**发送一个通知**/ notificationManager.notify(NOTIFICATION_ID, notification); }
5.显示通知的自定义布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" android:orientation="horizontal"> <ImageView android:id="@+id/iv" android:layout_width="40dp" android:layout_height="40dp" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_weight="1" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="随时随地" android:textColor="@color/colorAccent" android:textSize="12sp" /> </LinearLayout> <ProgressBar android:id="@+id/pb" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="20dp" android:max="100" android:progressBackgroundTint="@color/colorPrimaryDark" android:progress="50" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tv_message" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="正在下载中..." android:textColor="@color/colorAccent" android:textSize="12sp" /> <TextView android:id="@+id/tv_progress" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center_vertical" android:gravity="center" android:textColor="@color/colorAccent" android:textSize="12sp" /> <TextView android:id="@+id/tv_size" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/colorAccent" android:textSize="12sp" /> </LinearLayout> </LinearLayout> <Button android:id="@+id/bt" android:layout_width="50dp" android:layout_height="30dp" android:layout_gravity="center_vertical" android:gravity="center" android:text="下载" android:textColor="@color/colorAccent" android:textSize="12sp" /></LinearLayout>
6.更新通知栏状态
/** * 在通知栏显示文件名 * * @param url 下载地址 */ private void showFileName(String url) { mRemoteViews.setTextViewText(R.id.tv_name, url.substring(url.lastIndexOf("/") + 1)); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 下载更改进度 * * @param total 总大小 * @param current 当前已下载大小 */ private void updateNotification(long total, long current) { mRemoteViews.setTextViewText(R.id.tv_size, formatSize(current) + "/" + formatSize(total)); int result = Math.round((float) current / (float) total * 100); mRemoteViews.setTextViewText(R.id.tv_progress, result + "%"); mRemoteViews.setProgressBar(R.id.pb, 100, result, false); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 下载失败 */ private void downloadFail() { status = Status.FAIL; if (!cancelable.isCancelled()) { cancelable.cancel(); } mRemoteViews.setTextViewText(R.id.bt, "重试"); mRemoteViews.setTextViewText(R.id.tv_message, "下载失败"); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 下载成功 */ private void downloadSuccess() { status = Status.SUCCESS; mRemoteViews.setTextViewText(R.id.bt, "完成"); mRemoteViews.setTextViewText(R.id.tv_message, "下载完成"); notificationManager.notify(NOTIFICATION_ID, notification); }
7.TaskService完整代码
package cn.bluemobi.dylan.servicetask;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Environment;import android.os.IBinder;import android.support.annotation.Nullable;import android.support.v7.app.NotificationCompat;import android.widget.RemoteViews;import com.orhanobut.logger.Logger;import org.xutils.common.Callback;import org.xutils.http.RequestParams;import org.xutils.x;import java.io.File;/** * Created by yuandl on 2016-12-19. */public class TaskService extends Service { /**** * 发送广播的请求码 */ private final int REQUEST_CODE_BROADCAST = 0X0001; /**** * 发送广播的action */ private final String BROADCAST_ACTION_CLICK = "servicetask"; /** * 通知 */ private Notification notification; /** * 通知的Id */ private final int NOTIFICATION_ID = 1; /** * 通知管理器 */ private NotificationManager notificationManager; /** * 通知栏的远程View */ private RemoteViews mRemoteViews; /** * 下载是否可取消 */ private Callback.Cancelable cancelable; /** * 自定义保存路径,Environment.getExternalStorageDirectory():SD卡的根目录 */ private String filePath = Environment.getExternalStorageDirectory() + "/ServiceTask/"; private File file; /** * 通知栏操作的四种状态 */ private enum Status { DOWNLOADING, PAUSE, FAIL, SUCCESS } /** * 当前在状态 默认正在下载中 */ private Status status = Status.DOWNLOADING; private MyBroadcastReceiver myBroadcastReceiver; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { registerBroadCast(); download(); return super.onStartCommand(intent, flags, startId); } /** * 注册按钮点击广播* */ private void registerBroadCast() { myBroadcastReceiver = new MyBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(BROADCAST_ACTION_CLICK); registerReceiver(myBroadcastReceiver, filter); } /** * 更新通知界面的按钮的广播 */ private class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!intent.getAction().equals(BROADCAST_ACTION_CLICK)) { return; } Logger.d("status=" + status); switch (status) { case DOWNLOADING: /**当在下载中点击暂停按钮**/ cancelable.cancel(); mRemoteViews.setTextViewText(R.id.bt, "下载"); mRemoteViews.setTextViewText(R.id.tv_message, "暂停中..."); status = Status.PAUSE; notificationManager.notify(NOTIFICATION_ID, notification); break; case SUCCESS: /**当下载完成点击完成按钮时关闭通知栏**/ notificationManager.cancel(NOTIFICATION_ID); break; case FAIL: case PAUSE: /**当在暂停时点击下载按钮**/ download(); mRemoteViews.setTextViewText(R.id.bt, "暂停"); mRemoteViews.setTextViewText(R.id.tv_message, "下载中..."); status = Status.DOWNLOADING; notificationManager.notify(NOTIFICATION_ID, notification); break; } } } /** * 下载文件 */ private void download() { final String url = "https://github.com/linglongxin24/DylanStepCount/raw/master/app-debug.apk"; RequestParams requestParams = new RequestParams(url); String fileName = url.substring(url.lastIndexOf("/") + 1); file = new File(filePath, fileName); showNotificationProgress(TaskService.this); showFileName(fileName); requestParams.setSaveFilePath(file.getPath()); /**自动为文件命名**/ requestParams.setAutoRename(true); /**自动为文件断点续传**/ requestParams.setAutoResume(true); cancelable = x.http().get(requestParams, new Callback.ProgressCallback<File>() { @Override public void onSuccess(File result) { Logger.d("下载完成"); Logger.d("result=" + result.getPath()); downloadSuccess(); } @Override public void onError(Throwable ex, boolean isOnCallback) { Logger.d("下载异常"); downloadFail(); } @Override public void onCancelled(CancelledException cex) { Logger.d("下载已取消"); } @Override public void onFinished() { } @Override public void onWaiting() { } @Override public void onStarted() { } @Override public void onLoading(long total, long current, boolean isDownloading) { Logger.d("total=" + total + "--" + "current=" + current); updateNotification(total, current); } }); } /** * 显示一个下载带进度条的通知 * * @param context 上下文 */ public void showNotificationProgress(Context context) { /**进度条通知构建**/ NotificationCompat.Builder builderProgress = new NotificationCompat.Builder(context); /**设置为一个正在进行的通知**/ builderProgress.setOngoing(true); /**设置小图标**/ builderProgress.setSmallIcon(R.mipmap.ic_launcher); /**新建通知自定义布局**/ mRemoteViews = new RemoteViews(context.getPackageName(), R.layout.notification); /**进度条ProgressBar**/ mRemoteViews.setProgressBar(R.id.pb, 100, 0, false); /**提示信息的TextView**/ mRemoteViews.setTextViewText(R.id.tv_message, "下载中..."); /**操作按钮的Button**/ mRemoteViews.setTextViewText(R.id.bt, "暂停"); /**设置左侧小图标*/ mRemoteViews.setImageViewResource(R.id.iv, R.mipmap.ic_launcher); /**设置通过广播形式的PendingIntent**/ Intent intent = new Intent(BROADCAST_ACTION_CLICK); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_BROADCAST, intent, 0); mRemoteViews.setOnClickPendingIntent(R.id.bt, pendingIntent); /**设置自定义布局**/ builderProgress.setContent(mRemoteViews); /**设置滚动提示**/ builderProgress.setTicker("开始下载..."); notification = builderProgress.build(); /**设置不可手动清除**/ notification.flags = Notification.FLAG_NO_CLEAR; /**获取通知管理器**/ notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE); /**发送一个通知**/ notificationManager.notify(NOTIFICATION_ID, notification); } /** * 在通知栏显示文件名 * * @param url 下载地址 */ private void showFileName(String url) { mRemoteViews.setTextViewText(R.id.tv_name, url.substring(url.lastIndexOf("/") + 1)); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 下载更改进度 * * @param total 总大小 * @param current 当前已下载大小 */ private void updateNotification(long total, long current) { mRemoteViews.setTextViewText(R.id.tv_size, formatSize(current) + "/" + formatSize(total)); int result = Math.round((float) current / (float) total * 100); mRemoteViews.setTextViewText(R.id.tv_progress, result + "%"); mRemoteViews.setProgressBar(R.id.pb, 100, result, false); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 下载失败 */ private void downloadFail() { status = Status.FAIL; if (!cancelable.isCancelled()) { cancelable.cancel(); } mRemoteViews.setTextViewText(R.id.bt, "重试"); mRemoteViews.setTextViewText(R.id.tv_message, "下载失败"); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 下载成功 */ private void downloadSuccess() { status = Status.SUCCESS; mRemoteViews.setTextViewText(R.id.bt, "完成"); mRemoteViews.setTextViewText(R.id.tv_message, "下载完成"); notificationManager.notify(NOTIFICATION_ID, notification); } /** * 格式化文件大小 * * @param size * @return */ private String formatSize(long size) { String format; if (size >= 1024 * 1024) { format = byteToMB(size) + "M"; } else if (size >= 1024) { format = byteToKB(size) + "k"; } else { format = size + "b"; } return format; } /** * byte转换为MB * * @param bt 大小 * @return MB */ private float byteToMB(long bt) { int mb = 1024 * 1024; float f = (float) bt / (float) mb; float temp = (float) Math.round(f * 100.0F); return temp / 100.0F; } /** * byte转换为KB * * @param bt 大小 * @return K */ private int byteToKB(long bt) { return Math.round((bt / 1024)); } /** * 销毁时取消下载,并取消注册广播,防止内存溢出 */ @Override public void onDestroy() { if (cancelable != null && !cancelable.isCancelled()) { cancelable.cancel(); } if (myBroadcastReceiver != null) { unregisterReceiver(myBroadcastReceiver); } super.onDestroy(); }}
8.GitHub
1 0
- Android中Service+Notification断点续传下载
- Service组件+Notification断点续传下载(Android)
- Android-Service系列之断点续传下载
- android-service系列之断点续传下载
- Android-Service系列之断点续传下载
- Android 使用service实现多线程断点续传下载
- Android实现Service后台下载Notification进度条
- Android实现Service后台下载Notification进度条
- Android实现Service后台下载Notification进度条
- Android实现Service下载文件,Notification显示下载进度
- 12、Android中多线程断点续传下载
- Service之断点续传(下载)
- service+okhttp实现断点续传下载
- Android 实现service后台多任务下载notification进度条更新
- android service broadcast notification
- 68 Android service Notification
- Android--Service之Notification
- Android-Service&Notification
- TCP/IP工作流的开始 socket创建4
- 欢迎使用CSDN-markdown编辑器
- Android学习笔记--初见AsyncQueryHandler
- js中append字符串包含onclick无效传递参数失败问题解决方案
- 【Codeforces Round #389】Codeforces 752E Santa Claus and Tangerines【解法一】
- Android中Service+Notification断点续传下载
- python 画二维图
- Python Simple Programs 简单小程序
- 屏幕适配
- 知识点:float、position与display关系
- css实现导航条
- JS中||或 、 && 与的执行顺序测试
- MachineLearning_note:Logistic Regression(Classification)
- 【codeforces 752E】Santa Claus and Tangerines