Android save multiple images to local

Contents Introduction

  • 01. Save the picture the actual development of the problems encountered
  • 02. http request directly with the picture and save it locally
  • 03. save a local download pictures with glide
  • 04. How to save multiple images to achieve continuous
  • 05. For other presentation

good news

  • Large blog notes summary [16 March] to date, including Java basic and in-depth knowledge, Android technology blog, Python study notes, etc., also includes bug summary usually encountered in the development, of course, also collected his spare time a large number of interview questions, long-term maintenance and updating correction, continuous improvement ...... open source file format is markdown! As well as open source live blog, from 12 years and has accumulated a total of N articles [nearly 100 million words, gradually move to the Internet], please indicate the source, thank you!
  • Link Address: https://github.com/yangchong211/YCBlogs
  • If you feel good, you can star, thank you! Of course, also welcome suggestions, everything is suddenly starting to micro, quantitative cause a qualitative change!

01. Save the picture the actual development of the problems encountered

  • Business needs
    • Jiugongge material in the material list of the page, showing the network requests load pictures. If the user clicks the Save button, the number of images stored locally. In practice, use glide Load picture, and then set the listener listens, after an image request is successful onResourceReady, resource resources save the picture to the collection. This time, if you click save controls, then loop through the picture collection of resources saved to a local folder.
  • Specifically code shows
    • This time the request directly to the network pictures into bitmap, and then stored in the collection. Then click the Save button when the time will be saved in the group set multiple pictures to a local folder.
    //bitmap图片集合
    private ArrayList<Bitmap> bitmapArrayList = new ArrayList<>();
    
    
    RequestOptions requestOptions = new RequestOptions() .transform(new GlideRoundTransform(mContext, radius, cornerType)); GlideApp.with(mIvImg.getContext()) .asBitmap() .load(url) .listener(new RequestListener<Bitmap>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) { return true; } @Override public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) { bitmapArrayList.add(resource); return false; } }) .apply(requestOptions) .placeholder(ImageUtils.getDefaultImage()) .into(mIvImg); //循环遍历图片资源集合,然后开始保存图片到本地文件夹 mBitmap = bitmapArrayList.get(i); savePath = FileSaveUtils.getLocalImgSavePath(); FileOutputStream fos = null; try { File filePic = new File(savePath); if (!filePic.exists()) { filePic.getParentFile().mkdirs(); filePic.createNewFile(); } fos = new FileOutputStream(filePic); // 100 图片品质为满 mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); } catch (IOException e) { e.printStackTrace(); return null; } finally { if (fos != null) { try { fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } //刷新相册 if (isScanner) { scanner(context, savePath); } } 
  • Problems encountered
    • After you save the picture to the local, the picture is not found in the original picture, but the show on view controls are cropped picture, which is the size of the ImageView picture.
  • Why you would encounter this problem
    • If you pass a ImageView as a parameter .into () is, Glide will use the size of the ImageView to limit the size of the picture. For example, if you want to load images is 1000x1000 pixels, but ImageView size is only 250x250 pixels, Glide will reduce picture size to small, to save processing time and memory.
    • After setting into control, that is, the return process in onResourceReady picture resources resource, essentially not you load the original picture, but ImageView set the size of the picture. So after you save, you will find pictures smaller.
  • So how do you solve the problem?
    • The first approach: when squared picture control display will load the network resource, and then load the picture is successful, it will save resources to the collection, then click Save collection cycle storage resources. This will only request a network. Since the beginning
    • The second approach: when squared picture control display will load the network resource, click Save squared pictures when pictures are cyclically requested network resource and then save the image to a local, this approach would request the network twice.

02. http request directly with the picture and save it locally

  • http request Pictures
    /**
     * 请求网络图片
     * @param url                       url
     * @return                          将url图片转化成bitmap对象 */ private static long time = 0; public static InputStream HttpImage(String url) { long l1 = System.currentTimeMillis(); URL myFileUrl = null; Bitmap bitmap = null; HttpURLConnection conn = null; InputStream is = null; try { myFileUrl = new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); } try { conn = (HttpURLConnection) myFileUrl.openConnection(); conn.setConnectTimeout(10000); conn.setReadTimeout(5000); conn.setDoInput(true); conn.connect(); is = conn.getInputStream(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); conn.disconnect(); } } catch (IOException e) { e.printStackTrace(); } long l2 = System.currentTimeMillis(); time = (l2-l1) + time; LogUtils.e("毫秒值"+time); //保存 } return is; } 
  • Saved locally
    InputStream inputStream = HttpImage(
            "https://img1.haowmc.com/hwmc/material/2019061079934131.jpg");
    String localImgSavePath = FileSaveUtils.getLocalImgSavePath();
    File imageFile = new File(localImgSavePath); if (!imageFile.exists()) { imageFile.getParentFile().mkdirs(); try { imageFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } FileOutputStream fos = null; BufferedInputStream bis = null; try { fos = new FileOutputStream(imageFile); bis = new BufferedInputStream(inputStream); byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); } if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } } 

03. save a local download pictures with glide

  • glide Photo
    File file = Glide.with(ReflexActivity.this)
            .load(url.get(0))
            .downloadOnly(500, 500) .get(); 
  • Saved locally
    String localImgSavePath = FileSaveUtils.getLocalImgSavePath();
    File imageFile = new File(localImgSavePath);
    if (!imageFile.exists()) {
        imageFile.getParentFile().mkdirs();
        imageFile.createNewFile();
    }
    copy(file,imageFile); /** * 复制文件 * * @param source 输入文件 * @param target 输出文件 */ public static void copy(File source, File target) { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(source); fileOutputStream = new FileOutputStream(target); byte[] buffer = new byte[1024]; while (fileInputStream.read(buffer) > 0) { fileOutputStream.write(buffer); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (fileInputStream != null) { fileInputStream.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } 

04. How to save multiple images to achieve continuous

  • Ideas: circulation child thread
    • Possible (not recommended), if I want to download the nine images will be added to the child thread for loop, and final presentation.
    • Seriously flawed, thread delay, order of the pictures can not be guaranteed. If the thread is set one thread, then thread the end of the first child, the child thread nested within the loop or sub-thread f is not over, so that the main thread to obtain images in less than a sub-thread acquired.
    • There is how to determine all threads finished, such as after all the pictures downloaded, toast the download is complete.
  • The program is not recommended
    • Create a thread pool to manage threads, thread pool package on library, you can see the thread pool simple package
    • This scheme does not know whether the image requested all threads completed, and can not guarantee the order.
    ArrayList<String> images = new ArrayList<>();
    for (String image : images){ //使用该线程池,及时run方法中执行异常也不会崩溃 PoolThread executor = BaseApplication.getApplication().getExecutor(); executor.setName("getImage"); executor.execute(new Runnable() { @Override public void run() { //请求网络图片并保存到本地操作 } }); } 
  • Recommended Solution
    ArrayList<String> images = new ArrayList<>();
    ApiService apiService = RetrofitService.getInstance().getApiService();
    //注意:此处是保存多张图片,可以采用异步线程
    ArrayList<Observable<Boolean>> observables = new ArrayList<>(); final AtomicInteger count = new AtomicInteger(); for (String image : images){ observables.add(apiService.downloadImage(image) .subscribeOn(Schedulers.io()) .map(new Function<ResponseBody, Boolean>() { @Override public Boolean apply(ResponseBody responseBody) throws Exception { saveIo(responseBody.byteStream()); return true; } })); } // observable的merge 将所有的observable合成一个Observable,所有的observable同时发射数据 Disposable subscribe = Observable.merge(observables).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean b) throws Exception { if (b) { count.addAndGet(1); Log.e("yc", "download is succcess"); } } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { Log.e("yc", "download error"); } }, new Action() { @Override public void run() throws Exception { Log.e("yc", "download complete"); // 下载成功的数量 图片集合的数量一致,说明全部下载成功了 if (images.size() == count.get()) { ToastUtils.showRoundRectToast("保存成功"); } else { if (count.get() == 0) { ToastUtils.showRoundRectToast("保存失败"); } else { ToastUtils.showRoundRectToast("因网络问题 保存成功" + count + ",保存失败" + (images.size() - count.get())); } } } }, new Consumer<Disposable>() { @Override public void accept(Disposable disposable) throws Exception { Log.e("yc","disposable"); } }); private void saveIo(InputStream inputStream){ String localImgSavePath = FileSaveUtils.getLocalImgSavePath(); File imageFile = new File(localImgSavePath); if (!imageFile.exists()) { imageFile.getParentFile().mkdirs(); try { imageFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } FileOutputStream fos = null; BufferedInputStream bis = null; try { fos = new FileOutputStream(imageFile); bis = new BufferedInputStream(inputStream); byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); } if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } //刷新相册代码省略…… } } 

Other Introduction

01. Summary link on blog

02. About my blog

Projects: https://github.com/yangchong211/YCVideoPlayer

Guess you like

Origin www.cnblogs.com/yc211/p/11015795.html