Android图片上传队列Service

来源:互联网 发布:降维算法 编辑:程序博客网 时间:2024/04/29 02:46

需求描述

  1. 没有网络的时候,将操作产生的本地图片(拍照,也可能是其他文件),存储起来。有网络的时候传输到文件服务器。
  2. 文件服务器只支持一个文件一个文件的传输。

分析

  1. 因为文件上传的过程不依赖与界面,所以不考虑Activity开启子线程的方式,使用Service,并且App一开启就开启这个服务。
  2. 创建一个上传队列,每次队列有新的元素加入的时候就去通知Service上传队列改变
  3. 创建一个任务队列,每次一个上传任务执行完成后,改变任务状态然后通知Service任务状态改变
  4. Service负责维护这个需求主要逻辑。负责通维护通知栏状态变化,接收任务个数改变,任务状态改变的监听
    流程逻辑图如下:
    这里写图片描述

实现

demo

这里写图片描述

上传事件和事件队列

/** 上传任务 */public class PhotoUpload {    // 任务状态    public static final int STATE_UPLOAD_COMPLETED = 5;    public static final int STATE_UPLOAD_ERROR = 4;    public static final int STATE_UPLOAD_IN_PROGRESS = 3;    public static final int STATE_UPLOAD_WAITING = 2;    public static final int STATE_SELECTED = 1;    public static final int STATE_NONE = 0;    private int mState;    private String name;    public int getUploadState() {        return mState;    }    public void reset() {        mState = STATE_NONE;    }    public void setUploadState(final int state) {        if (mState != state) {            mState = state;            switch (state) {            case STATE_UPLOAD_ERROR:            case STATE_UPLOAD_COMPLETED:                EventBus.getDefault().post(new UploadsModifiedEvent());                break;            case STATE_SELECTED:            case STATE_UPLOAD_WAITING:                break;            }            notifyUploadStateListener();        }    }    private void notifyUploadStateListener() {        EventBus.getDefault().post(new UploadStateChangedEvent(this));    }}
/** 上传事件队列 */public class PhotoUploadController {    public static PhotoUploadController getFromContext(Context context) {        return MyApp.getApplication(context).getPhotoUploadController();    }    private final Context mContext;    private final ArrayList<PhotoUpload> mSelectedPhotoList;    private final ArrayList<PhotoUpload> mUploadingList;    public PhotoUploadController(Context context) {        mContext = context;        mSelectedPhotoList = new ArrayList<PhotoUpload>();        mUploadingList = new ArrayList<PhotoUpload>();    }    // 添加任务方法    public boolean addUpload(PhotoUpload selection) {        if (null != selection) {            synchronized (this) {                if (!mUploadingList.contains(selection)) {                    selection.setUploadState(PhotoUpload.STATE_UPLOAD_WAITING);                    mUploadingList.add(selection);                    mSelectedPhotoList.remove(selection);                    postEvent(new UploadsModifiedEvent());                    return true;                }            }        }        return false;    }    public synchronized int getActiveUploadsCount() {        int count = 0;        for (PhotoUpload upload : mUploadingList) {            if (upload.getUploadState() != PhotoUpload.STATE_UPLOAD_COMPLETED) {                count++;            }        }        return count;    }    /* 获取下一个任务 */    public synchronized PhotoUpload getNextUpload() {        for (PhotoUpload selection : mUploadingList) {            if (selection.getUploadState() == PhotoUpload.STATE_UPLOAD_WAITING) {                return selection;            }        }        return null;    }    public synchronized List<PhotoUpload> getUploadingUploads() {        return new ArrayList<PhotoUpload>(mUploadingList);    }    public synchronized int getUploadsCount() {        return mUploadingList.size();    }}

EventBus 通讯

主要包括两种类型的通讯

  1. 任务暂停事件
  2. 上传状态改变;上传失败、上传成功、上传错误、暂停
/** 上传任务状态改变 */public class UploadStateChangedEvent {    private final PhotoUpload mUpload;    public UploadStateChangedEvent(PhotoUpload upload) {        mUpload = upload;    }    public PhotoUpload getUpload() {        return mUpload;    }}
public class UploadingPausedStateChangedEvent {    // 空实现 直接开始下一个任务即可}

想到但是还没实现的通讯:移除一个上传任务
所以在Service中存在两个EventBus监听方法

// 监听任务状态    public void onEventMainThread(UploadStateChangedEvent event) {        PhotoUpload upload = event.getUpload();        switch (upload.getUploadState()) {        case PhotoUpload.STATE_UPLOAD_IN_PROGRESS:            updateNotification(upload);            break;        case PhotoUpload.STATE_UPLOAD_COMPLETED:            mNumberUploaded++;        case PhotoUpload.STATE_UPLOAD_ERROR:            startNextUploadOrFinish();        case PhotoUpload.STATE_UPLOAD_WAITING:            break;        }    }    // 监听手动改变任务public void onEvent(UploadingPausedStateChangedEvent event) {        if (isUploadingPaused(this)) {            stopUploading();        } else {            startNextUploadOrFinish();        }    }

具体单个上传任务执行

具体使用

    private boolean mCurrentlyUploading;    private ExecutorService mExecutor = Executors.newSingleThreadExecutor();    private Future<?> mCurrentUploadRunnable;

申明任务

public abstract class PhotupThreadRunnable implements Runnable {    public final void run() {        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);        runImpl();    }    public abstract void runImpl();    protected boolean isInterrupted() {        return Thread.currentThread().isInterrupted();    }}

具体实现

private class UpdateRunnable extends PhotupThreadRunnable {        private final PhotoUpload mSelection;        public UpdateRunnable(PhotoUpload selection) {            mSelection = selection;        }        public void runImpl() {            try {                if (mSelection.getUploadState() == PhotoUpload.STATE_UPLOAD_WAITING) {                    mSelection                            .setUploadState(PhotoUpload.STATE_UPLOAD_IN_PROGRESS);                    // 暂停1秒 模拟上传                    Thread.sleep(1000);                    // TODO 在这里配置文件服务器地址和参数,需要上传的文件 使用公司文件服务器测试通过                    RequestParams params = new RequestParams(                            "https://www.baidu.com/");                    params.addBodyParameter("f", new File("文件路径"));                    x.http().post(params, new CommonCallback<String>() {                        @Override                        public void onSuccess(String result) {                            mSelection                                    .setUploadState(PhotoUpload.STATE_UPLOAD_COMPLETED);                        }                        @Override                        public void onError(Throwable ex, boolean isOnCallback) {                            mSelection                                    .setUploadState(PhotoUpload.STATE_UPLOAD_ERROR);                        }                        @Override                        public void onCancelled(CancelledException cex) {                            mSelection                                    .setUploadState(PhotoUpload.STATE_UPLOAD_WAITING);                        }                        @Override                        public void onFinished() {                            // 通知service                            bus.post(new UploadingPausedStateChangedEvent());                        }                    });                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }

维护通知栏

private void startForeground() {        if (null == mNotificationBuilder) {            mNotificationBuilder = new android.support.v4.app.NotificationCompat.Builder(                    this);            mNotificationBuilder.setSmallIcon(R.drawable.ic_launcher);            mNotificationBuilder.setContentTitle(getString(R.string.app_name));            mNotificationBuilder.setOngoing(true);            mNotificationBuilder.setWhen(System.currentTimeMillis());            PendingIntent intent = PendingIntent.getActivity(this, 0,                    new Intent(this, MainActivity.class), 0);            mNotificationBuilder.setContentIntent(intent);        }        startForeground(12, mNotificationBuilder.build());    }    void updateNotification(final PhotoUpload upload) {        String text;        switch (upload.getUploadState()) {        case PhotoUpload.STATE_UPLOAD_WAITING:            text = "上传: " + upload.getName();            mNotificationBuilder.setContentTitle(text);            mNotificationBuilder.setTicker(text);            mNotificationBuilder.setProgress(0, 0, true);            mNotificationBuilder.setWhen(System.currentTimeMillis());            break;        case PhotoUpload.STATE_UPLOAD_IN_PROGRESS:            text = "上传: " + upload.getName();            mNotificationBuilder.setContentTitle(text);            mNotificationBuilder.setTicker(text);            mNotificationBuilder.setProgress(0, 0, true);            mNotificationBuilder.setWhen(System.currentTimeMillis());            break;        }        mNotificationMgr.notify(12, mNotificationBuilder.build());    }

Demo

下载地址

0 0
原创粉丝点击