博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 中 Service+Notification 断点续传下载
阅读量:6845 次
发布时间:2019-06-26

本文共 16643 字,大约阅读时间需要 55 分钟。

转载请注明出处:

本文出自


#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
() { @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.显示通知的自定义布局

复制代码

#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
() { @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.

你可能感兴趣的文章
JAVA模板方法设计模式——Java设计模式,写漂亮的代码——
查看>>
Debian 包维护者不满 Debian 开发流程,宣布退出
查看>>
Scrapy分布式爬虫打造搜索引擎-(八)elasticsearch结合django搭建搜索引擎
查看>>
朋也社区 v5.2.0 更新,新增手机号,微信登录外加主题一套
查看>>
骞云科技完成500万美元A+轮融资,清流资本领投
查看>>
PHP CORS 1.4 更新,支持框架中再填一员 - Swoft
查看>>
Python学习计划(1)
查看>>
使用宝塔linux面板管理安装WordPress个人博客
查看>>
有趣的Tensorflow游乐场以及有趣的思考
查看>>
spring源码-bean之初始化-1
查看>>
不为人知的网络编程(七):如何让不可靠的UDP变的可靠?
查看>>
Android--面试题整理(五)
查看>>
php continue break 用例
查看>>
Scrapy小解
查看>>
移动端小项目的小总结~
查看>>
【新知】 量子技术初探
查看>>
CentOS 6.9关闭NetworkManager服务
查看>>
Atom飞行手册翻译: 2.12 在Atom中写作
查看>>
JVM的大管家:自动内存管理机制
查看>>
【十年路线图】Facebook 帝国:AI、VR将成两大支柱
查看>>