保存图片到本地

一个很常见的需求,图片保存到本地,矫正图片角度,通知图库更新

步骤

  1. 使用Gilde获取图片的Drawable
  2. Drawable转成Bitmap
  3. bigtmap压缩并通过流写入
  4. 通知系统图库更新

代码块

  • 保存图片,流写入,压缩
  • public static void saveImageToGallery(Context context, Bitmap bmp) {
    File appDir = new File(Environment.getExternalStorageDirectory(), "fengandev");
    if (!appDir.exists()) {
        appDir.mkdir();
    }
    String fileName = System.currentTimeMillis() + ".jpg";
    File file = new File(appDir, fileName);
    try {
        FileOutputStream fos = new FileOutputStream(file);
        bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    // 其次把文件插入到系统图库
    try {
        MediaStore.Images.Media.insertImage(context.getContentResolver(),
                file.getAbsolutePath(), fileName, null);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    // 最后通知图库更新
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(new File(file.getPath()))));
    ToastUtil.showShort("保存到" + file.getPath());
    

    }`

    通过glide回调,获取图片Drawable

  mTvSave.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        showLoadding();
        GlideUtils.loadImage(Utils.getContext(), imaUrl), mIvImg,new GlideUtils.ImageLoadListener<String, GlideDrawable>() {
            @Override
            public void onLoadingComplete(String uri, ImageView view, GlideDrawable resource) {
                FileUtils.saveImageToGallery(Utils.getContext(), BitmapUtils.drawableToBitmap(resource));
            }

            @Override
            public void onLoadingError(String source, Exception e) {
                showState("保存失败",0);
            }
        });
    }
});

分享一个Glide封装

  • Glide封装类
public abstract class GlideUtils {
/**
 * 简单图片加载回调
 *
 * @param <T> 图片url 或资源id 或 文件
 * @param <K> 返回的资源,GlideDrawable或者Bitmap或者GifDrawable,ImageView.setImageRecourse设置
 */
public interface ImageLoadListener<T, K> {

    /**
     * 图片加载成功回调
     *
     * @param uri      图片url 或资源id 或 文件
     * @param view     目标载体,不传则为空
     * @param resource 返回的资源,GlideDrawable或者Bitmap或者GifDrawable,ImageView.setImageRecourse设置
     */
    void onLoadingComplete(T uri, ImageView view, K resource);

    /**
     * 图片加载异常返回
     *
     * @param source 图片地址、File、资源id
     * @param e      异常信息
     */
    void onLoadingError(T source, Exception e);

}


/**
 * 详细加载图片加载回调
 *
 * @param <T> 图片url 或资源id 或 文件
 * @param <K> 返回的资源
 */
public interface ImageLoadDetailListener<T, K> {

    /**
     * 图片加载成功回调
     *
     * @param uri      图片url 或资源id 或 文件
     * @param view     目标载体,不传则为空
     * @param resource 返回的资源,GlideDrawable或者Bitmap或者GifDrawable,ImageView.setImageRecourse设置
     */
    void onLoadingComplete(T uri, ImageView view, K resource);

    /**
     * 图片加载异常返回
     *
     * @param source        图片地址、File、资源id
     * @param errorDrawable 加载错误占位图
     * @param e             异常信息
     */
    void onLoadingError(T source, Drawable errorDrawable, Exception e);

    /**
     * 加载开始
     *
     * @param source      图片来源
     * @param placeHolder 开始加载占位图
     */
    void onLoadingStart(T source, Drawable placeHolder);

}


/**
 * 根据上下文和 url获取 Glide的DrawableTypeRequest
 *
 * @param context 上下文
 * @param url     图片连接
 * @param <T>     Context类型
 * @param <K>     url类型
 * @return 返回DrawableTypeRequst<K> 类型
 */
private static <T, K> DrawableTypeRequest<K> getDrawableTypeRequest(T context, K url) {
    DrawableTypeRequest<K> type = null;
    try {
        if (context instanceof android.support.v4.app.Fragment) {
            type = Glide.with((android.support.v4.app.Fragment) context).load(url);
        } else if (context instanceof android.app.Fragment) {
            type = Glide.with((android.app.Fragment) context).load(url);
        } else if (context instanceof Activity) {    //包括FragmentActivity
            type = Glide.with((Activity) context).load(url);
        } else if (context instanceof Context) {
            type = Glide.with((Context) context).load(url);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return type;
}


/**
 * 图片加载监听类
 *
 * @param <T> 图片链接 的类型
 * @param <K> 图片资源返回类型
 * @param <Z> 返回的图片url
 */
private static class GlideListener<T, K, Z> implements RequestListener<T, K> {

    ImageLoadListener<Z, K> imageLoadListener = null;
    Z url;
    ImageView imageView = null;

    GlideListener(ImageLoadListener<Z, K> imageLoadListener, Z url, ImageView view) {
        this.imageLoadListener = imageLoadListener;
        this.url = url;
        this.imageView = view;
    }

    GlideListener(ImageLoadListener<Z, K> imageLoadListener, Z url) {
        this.imageLoadListener = imageLoadListener;
        this.url = url;
    }

    GlideListener(Z url) {
        this.url = url;
    }

    @Override
    public boolean onResourceReady(K resource, T model, Target<K> target, boolean isFromMemoryCache, boolean isFirstResource) {
        if (null != imageLoadListener) {
            if (imageView != null) {
                imageLoadListener.onLoadingComplete(url, imageView, resource);
            } else {
                imageLoadListener.onLoadingComplete(url, null, resource);
            }
        }

        return false;
    }

    @Override
    public boolean onException(Exception e, T model, Target<K> target, boolean isFirstResource) {

        //LogUtil.e("Glide图片加载失败:"+e + " 地址为:"+url);

        if (imageLoadListener != null) {
            imageLoadListener.onLoadingError(url, e);
        }
        return false;
    }
}


/**
 * 获取存储器上的图片,回调返回GlideDrawable
 *
 * @param context           上下文年
 * @param file              文件File
 * @param imageLoadListener 回调监听器
 */
public static <T> DrawableRequestBuilder<File> loadImage(T context, @NonNull File file, @NonNull ImageLoadListener<File, GlideDrawable> imageLoadListener) {
    DrawableTypeRequest<File> type = getDrawableTypeRequest(context, file);
    if (type != null) {
        return type.listener(new GlideListener<File, GlideDrawable, File>(imageLoadListener, file));
    } else {
        return null;
    }
}

/**
 * 获取资源中的图片,回调返回GlideDrawable
 *
 * @param context           上下文
 * @param resourceId        资源id
 * @param imageLoadListener 回调监听器
 */
public static <T> DrawableRequestBuilder<Integer> loadImage(T context, @DrawableRes int resourceId, @NonNull ImageLoadListener<Integer, GlideDrawable> imageLoadListener) {
    DrawableTypeRequest<Integer> type = getDrawableTypeRequest(context, resourceId);
    if (type != null) {
        return type.listener(new GlideListener<Integer, GlideDrawable, Integer>(imageLoadListener, resourceId));
    } else {
        return null;
    }

}

/**
 * 获取网络图片,回调返回 GlideDrawable
 *
 * @param context           上下文
 * @param url               图片url
 * @param imageLoadListener 回调监听器
 */
public static <T> DrawableRequestBuilder<String> loadImage(T context, @NonNull final String url, @NonNull ImageLoadListener<String, GlideDrawable> imageLoadListener) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(context, url);
    if (type != null) {
        return type.listener(new GlideListener<String, GlideDrawable, String>(imageLoadListener, url));
    } else {
        return null;
    }

}

/**
 * 加载存储器上的图片到目标载体
 *
 * @param file      文件File
 * @param imageView 要显示到的图片ImageView
 */
public static Target<GlideDrawable> loadImage(@NonNull final File file, @NonNull ImageView imageView, ImageLoadListener<File, GlideDrawable> imageLoadListener) {
    return getDrawableTypeRequest(imageView.getContext(), file)
            .diskCacheStrategy(DiskCacheStrategy.NONE)//禁用磁盘缓存
            .skipMemoryCache(true)//跳过内存缓存
            .dontAnimate()
            .listener(new GlideListener<File, GlideDrawable, File>(imageLoadListener, file, imageView))
            .into(imageView);
}

/**
 * 加载资源中的图片到目标载体
 *
 * @param resourceId 资源id
 * @param imageView  图片View
 */
public static Target<GlideDrawable> loadImage(@DrawableRes int resourceId, @NonNull ImageView imageView, ImageLoadListener<Integer, GlideDrawable> imageLoadListener) {
    return getDrawableTypeRequest(imageView.getContext(), resourceId)
            .listener(new GlideListener<Integer, GlideDrawable, Integer>(imageLoadListener, resourceId, imageView))
            .into(imageView);
}


/**
 * 加载成圆形头像到普通ImageView,有动画效果
 *
 * @param url               图片url
 * @param imageView         要显示到的ImageView
 * @param imageLoadListener 加载回调监听器
 * @param parms             设置占位符和加载失败图片(可变参数默认两张,第一张为占位符,第二张是默认图片)
 * @return 返回Target<GlideDrawable>
 */
public static Target<GlideDrawable> loadCircleImage(@NonNull String url, @NonNull ImageView imageView, ImageLoadListener<String, GlideDrawable> imageLoadListener, int... parms) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(imageView.getContext(), url);
    if (parms != null && parms.length > 0) {
        type.placeholder(parms[0]);   //占位符
        if (parms.length > 1) {
            type.error(parms[1]);    //图片加载失败显示图片
        }
    }
    type.transform(new CircleTransform(imageView.getContext()));
    return type.listener(new GlideListener<String, GlideDrawable, String>(imageLoadListener, url, imageView))
            .into(imageView);

}


/**
 * 加载网络图片到指定Imageview,支持CircleImageView
 *
 * @param url               图片url
 * @param imageView         要显示的Imageview
 * @param imageLoadListener 图片加载回调
 * @param parms             第一个是error的图片
 */
public static <T> Target<GlideDrawable> loadImage(T context, @NonNull String url, @NonNull ImageView imageView, ImageLoadListener<String, GlideDrawable> imageLoadListener, int... parms) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(context, url);
    if (type != null) {
        type.asBitmap();
        if (parms != null && parms.length > 0) {
            type.placeholder(parms[0]);   //占位符
            if (parms.length > 1) {
                type.error(parms[1]);    //图片加载失败显示图片
            }
        }

        //单张CircleImageView不允许动画,不然会不显示,
        if (imageView instanceof nfzr.zr.nf.nfzr.com.nongfaziran.nfzr.view.CircleImageView) {
            type.dontAnimate();
        }
        return type
                .listener(new GlideListener<String, GlideDrawable, String>(imageLoadListener, url, imageView))
                .into(imageView);
    } else {
        return null;
    }

}

/**
 * 加载一帧视频,添加圆角
 *
 * @param url       图片地址
 * @param imageView 要加载到的ImageView
 */
public static Target<GlideDrawable> loadImageFormVideo(@NonNull String url, @NonNull ImageView imageView) {
    return getDrawableTypeRequest(imageView.getContext(), url)
            .override(SizeUtil.dp2px(150), SizeUtil.dp2px(150))
            //.placeholder(android.R.drawable.picture_frame)   //占位图
            .dontAnimate()
            .into(imageView);
}


public static <T> Target<GlideDrawable> loadImageDetail(final T context, @NonNull final String url, @NonNull final ImageView imageView, final Drawable drawable, final ImageLoadDetailListener<String, GlideDrawable> imageLoadListener) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(context, url);
    if (type != null) {
        return type.into(new SimpleTarget<GlideDrawable>() {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                if (imageView != null && resource != null) {
                    imageView.setImageDrawable(resource);
                }
                if (imageLoadListener != null) {
                    imageLoadListener.onLoadingComplete(url, imageView, resource);
                }

            }

            @Override
            public void onStart() {
                super.onStart();
                if (drawable != null && imageView != null) {
                    imageView.setImageDrawable(drawable);
                }

            }

            @Override
            public void onLoadStarted(Drawable placeholder) {
                super.onLoadStarted(placeholder);
                if (imageLoadListener != null) {
                    imageLoadListener.onLoadingStart(url, placeholder);
                }

            }

            @Override
            public void onLoadFailed(Exception e, Drawable errorDrawable) {
                super.onLoadFailed(e, errorDrawable);
                if (imageLoadListener != null) {
                    imageLoadListener.onLoadingError(url, errorDrawable, e);
                }
            }
        });
    } else {
        return null;
    }

}


/**
 * 加载bitmap,回调返回 Bitmap
 *
 * @param context           上下文
 * @param url               图片url
 * @param imageLoadListener 图片加载监听器
 * @param <T>               上下文类型
 */
public static <T> BitmapRequestBuilder<String, Bitmap> loadImageBitmap(T context, @NonNull String url,@NonNull ImageLoadListener<String, Bitmap> imageLoadListener) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(context, url);
    if (type != null) {
        return type.asBitmap()
                .listener(new GlideListener<String, Bitmap, String>(imageLoadListener, url));
    }else{
        return null;
    }
}


/**
 * 加载GifDrawable,回调返回 GifDrawable
 *
 * @param context           上下文
 * @param url               图片url
 * @param imageLoadListener 图片加载监听器
 */
public static <T> GifRequestBuilder<String> loadImageGif(T context, @NonNull String url,@NonNull ImageLoadListener<String, GifDrawable> imageLoadListener) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(context, url);
    if (type != null) {
        return type.asGif()
                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .listener(new GlideListener<String, GifDrawable, String>(imageLoadListener, url));

    }else{
        return null;
    }
}


/**
 * 加载Gif的一张图片到ImageView
 *
 * @param url               图片url
 * @param imageLoadListener 图片加载监听器
 *                          @param imageView 
 *                          @param drawable 缩略图,可以为空
 */
public static Target<Bitmap> loadImageGifSingle(@NonNull String url, @NonNull ImageView imageView, ImageLoadListener<String, Bitmap> imageLoadListener, Drawable drawable) {

    DrawableTypeRequest<String> type = getDrawableTypeRequest(imageView.getContext(),url);
    return type.asBitmap()
            .placeholder(drawable)
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .listener(new GlideListener<String, Bitmap, String>(imageLoadListener, url))
            .into(imageView);
}


/**
 * 加载gif图片到指定ImageView
 *
 * @param url               图片Url
 * @param imageView         图片View
 * @param imageLoadListener 图片加载监听器
 */
public static Target<GifDrawable> loadImageGif(@NonNull String url, @NonNull ImageView imageView, ImageLoadListener<String, GifDrawable> imageLoadListener) {
    DrawableTypeRequest<String> type = getDrawableTypeRequest(imageView.getContext(),url);
    return type.asGif()
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .listener(new GlideListener<String, GifDrawable, String>(imageLoadListener, url, imageView))
            .into(imageView);
}


/**
 * 释放内存
 *
 * @param context 上下文
 */
public static void clearMemory(Context context) {
    Glide.get(context).clearMemory();
}


/**
 * 取消所有正在下载或等待下载的任务。
 *
 * @param context 上下文
 */
public static void cancelAllTasks(Context context) {
    Glide.with(context).pauseRequests();
}

/**
 * 恢复所有任务
 */
public static void resumeAllTasks(Context context) {
    Glide.with(context).resumeRequests();
}

/**
 * 清除磁盘缓存
 *
 * @param context 上下文
 */
public static void clearDiskCache(final Context context) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Glide.get(context).clearDiskCache();
        }
    }).start();
}


/**
 * 清除所有缓存
 *
 * @param context 上下文
 */
public static void cleanAll(Context context) {
    clearDiskCache(context);
    clearMemory(context);
}

public class CircleTransform extends BitmapTransformation {
public CircleTransform(Context context) {
    super(context);
}

@Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    return circleCrop(pool, toTransform);
}

private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
    if (source == null) return null;

    int size = Math.min(source.getWidth(), source.getHeight());
    int x = (source.getWidth() - size) / 2;
    int y = (source.getHeight() - size) / 2;

    Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

    Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
    if (result == null) {
        result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(result);
    Paint paint = new Paint();
    paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
    paint.setAntiAlias(true);
    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);
    return result;
}

@Override public String getId() {
    return getClass().getName();
}
}

Drawable转bigmap

public class BitmapUtils {
public static Bitmap drawableToBitmap(Drawable drawable) {
    Bitmap bitmap = Bitmap.createBitmap(
            drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(),
            drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                    : Bitmap.Config.RGB_565);
    Canvas canvas = new Canvas(bitmap);
    //canvas.setBitmap(bitmap);
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
    drawable.draw(canvas);
    return bitmap;
}
}
文章目录