Android Service后台多线程压缩并提交图片及数据
来源:互联网 发布:qq飞车奇迹数据 编辑:程序博客网 时间:2024/05/13 04:01
手机端发帖,多张图片上传是个问题.最近重构项目代码,正好碰到这个,这里把解决的方案整理,以备后用.
方案原理:
- 创建上传任务表, 帖子内容发布的时候将数据存放到任务表中,并传递数据到service中.
- 启动服务,遍历任务表中内容,创建上传任务.如果接收到上传任务,创建任务,加入上传任务队列中.(上传任务顺序可以自定义)
- 包含图片的上传任务.开启多线程压缩(使用线程池管理压缩线程),压缩完毕后返回压缩后临时图片位置
- 上传成功后,根据返回值处理临时目录, 删除任务表中上传成功任务
Activity 和 Service 之间的数据通信使用的是 EventBus
数据上传使用的的是retrofit + okHttp
不多说,直接上代买
上传服务:
public class UploadService extends Service { private static final String TAG = UploadService.class.getSimpleName(); private ExecutorService executorService = Executors.newFixedThreadPool(3); private ExecutorService singleTaskService = Executors.newSingleThreadExecutor();// 按顺序处理任务 @Override public void onCreate() { super.onCreate(); EventBus.getDefault().register(this); LogUtils.e(TAG, "UploadService is onCreate"); } /** * 通过EventBus接受传递过来的数据 * * @param submitPostBena */ @Subscribe public void receiveUploadData(SubmitPostBena submitPostBena) { createSubmitTask(submitPostBena); } /** * 查询任务表中是否有数据 (未实现任务表) */ private void queryTaskTable() { //mTaskCount = queryFromTable().size();//查询数据库 //List<SubmitPostBena> postsBeen = new ArrayList<>(); //for (int i = 0; i < postsBeen.size(); i++) { //循环创建提交帖子任务 // createSubmitTask(postsBeen.get(i)); //} } /** * 创建提交帖子数据任务 * * @param bean 要提交的提子数据 */ private void createSubmitTask(SubmitPostBena bean) { singleTaskService.execute(new TaskRunnable(bean)); } /** * 任务 */ private class TaskRunnable implements Runnable { private CountDownLatch countDownLatch; private List<String> newPath = Collections.synchronizedList(new ArrayList<String>());//返回值 private List<String> faile = Collections.synchronizedList(new ArrayList<String>());//提交失败返回值 private SubmitPostBena bean; TaskRunnable(SubmitPostBena bean) { this.bean = bean; countDownLatch = new CountDownLatch(bean.getImagePaths().size());//这地方有个小坑,countDown 的数量一定要和压缩图片的数量一致 } @Override public void run() { synchronized (UploadService.class) { try { if (bean.isImagePost()) { LogUtils.e(TAG, "开始任务处理图片压缩"); CompressTask(countDownLatch, newPath, bean.getImagePaths()); //处理压缩问题 countDownLatch.await(); bean.setImagePaths(newPath); LogUtils.e(TAG, "压缩完成"); } submitData(bean, faile); //提交 } catch (Exception e) { e.printStackTrace(); } } } } /** * 创建处理压缩任务 * * @param countDownLatch 线程同步辅助工具,用于记录图片压缩线程全部执行完毕后通知提交线程提交 * @param newPath 处理过后的图片的地址 * @param imagePath 原始图片地址 */ private void CompressTask(CountDownLatch countDownLatch, List<String> newPath, List<String> imagePath) { for (int i = 0; i < imagePath.size(); i++) { String path = imagePath.get(i); executorService.execute(new CompressRunnable(countDownLatch, path, newPath)); } } /** * 压缩任务 */ private class CompressRunnable implements Runnable { private String filePath; private List<String> newPath; private CountDownLatch countDownLatch; /** * 压缩图片处理 * * @param countDownLatch 线程同步辅助类,用于基数当前线程是否完成,如果完成,线程数量减少1 * @param imagePath 要处理图片的路径 * @param newPath 处理后图片的新路径 */ CompressRunnable(CountDownLatch countDownLatch, String imagePath, List<String> newPath) { this.newPath = newPath; this.filePath = imagePath; this.countDownLatch = countDownLatch; } @Override public void run() { Bitmap smallBitmap = BitmapUtils.getSmallBitmap(filePath); String tempPath = BitmapUtils.compressImage(smallBitmap); if (!TextUtils.isEmpty(tempPath)) { newPath.add(tempPath); countDownLatch.countDown(); } } } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); LogUtils.e(TAG, "UploadService is onDestroy"); executorService.shutdownNow(); singleTaskService.shutdownNow(); } private void submitData(SubmitPostBena mBean, List<String> faile) { if (SystemUtils.checkNet(this)) { //上传方法 } }}
图片压缩:
public class BitmapUtils { /** * 根据路径获得图片并压缩,返回bitmap用于显示 * * @param filePath 图片路径 * @return */ public static Bitmap getSmallBitmap(String filePath) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); options.inSampleSize = calculateInSampleSize(options, 480, 800);// Calculate inSampleSize options.inJustDecodeBounds = false;// Decode bitmap with inSampleSize set Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); return bitmap; } /** * 计算图片的缩放值 * * @param options * @param reqWidth * @param reqHeight * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } public static String compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 90; while (baos.toByteArray().length / 1024 > 100) {//循环判断如果压缩后图片是否大于100kb,大于继续压缩 baos.reset();//重置baos即清空baos options -= 10; image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 if (options < 0) options = 0; } String tempName = UUID.randomUUID().toString().replace("-", "") + ".jpg"; File fileDir = new File(Commons.PHOTOCACHE_TEMP); if (!fileDir.exists()) { fileDir.mkdirs(); } File file = new File(fileDir, tempName); try { if (file.exists()) file.delete(); FileOutputStream fos = new FileOutputStream(file); image.compress(Bitmap.CompressFormat.JPEG, 50, fos); fos.flush(); fos.close(); if (!image.isRecycled()) { image.recycle(); } } catch (IOException e) { e.printStackTrace(); } LogUtils.e("压缩后图片大小 >>>> ", file.length() + ""); return file.getPath(); }}
0 0
- Android Service后台多线程压缩并提交图片及数据
- WebUploader 上传图片并提交表单(一)
- javascript将base64编码的图片数据转换为file并提交
- javascript将base64编码的图片数据转换为file并提交
- js 动态创建forn 并提交数据
- oracle恢复删除并提交的数据
- Android中处理崩溃异常,并提交
- PHP CURL模拟登陆并提交数据,及PHP CURL文件上传(仅作调试,待完善)
- java实现登陆WEB站点,并提交数据
- android service 后台处理一些数据
- java后台压缩图片
- js多图片压缩上传及后台处理
- Android图片压缩及内存缓存
- Android图片压缩及各种图处理
- JavaScript验证表单数据,并提交给Java后台
- javascript创建并提交表单
- Hive 编译并提交Patch
- RTEMS创造并提交patch
- java中的三元运算符没那么肤浅
- JVM原理和优化
- tcpdump抓包方法
- SAP中查找业务应用使用的数据表
- 【网络安全】SSL协议(HTTPS) 握手、工作流程详解(双向HTTPS流程)
- Android Service后台多线程压缩并提交图片及数据
- iOS 集成ijkplayer视频直播框架
- @Controller("HomeAction") @Scope("prototype") 啥意思呢
- 一个简单的小程序演示Unity的三种依赖注入方式
- 数据库悲观锁和乐观锁
- 自定义控件三部曲之绘图篇(十五)——QQ红点拖动删除效果实现(基本原理篇)
- caffe例子mnist
- 解决css中input输入框点击时去掉外边框方法【outline:medium;】
- PSR规范