加载网络图片并点击保存图片到系统相册
1.首先在清单文件上加入相关权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2.定义一个ImageUtils工具类
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class ImageUtils {
private static File mPhotoFile = null;
public static void setPhotoFile(File photoFile){
mPhotoFile = photoFile;
}
public static File getPhotoFile(){
return mPhotoFile;
}
/**
* 保存图片到图库
* @param bmp
*/
public static void saveImageToGallery(Bitmap bmp, String bitName ) {
// 首先保存图片
File appDir = new File(Environment.getExternalStorageDirectory(),
"picture");
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = bitName + ".png";
File file = new File(appDir, fileName);
Log.v("Photo",fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
setPhotoFile(file);
}
/**
* @param bmp 获取的bitmap数据
* @param picName 自定义的图片名
*/
public static void saveBmp2Gallery(Context context, Bitmap bmp, String picName) {
saveImageToGallery(bmp,picName);
String fileName = null;
//系统相册目录
String galleryPath = Environment.getExternalStorageDirectory()
+ File.separator + Environment.DIRECTORY_DCIM
+ File.separator + "Camera" + File.separator;
// 声明文件对象
File file = null;
// 声明输出流
FileOutputStream outStream = null;
try {
// 如果有目标文件,直接获得文件对象,否则创建一个以filename为名称的文件
file = new File(galleryPath, picName + ".png");
// 获得文件相对路径
fileName = file.toString();
// 获得输出流,如果文件中有内容,追加内容
outStream = new FileOutputStream(fileName);
if (outStream!=null) {
bmp.compress(Bitmap.CompressFormat.PNG, 90, outStream);
}
}catch (Exception e) {
e.getStackTrace();
} finally {
try {
if (outStream != null) {
//关闭输出流
outStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//添加图片到系统相册并更新通知
MediaStore.Images.Media.insertImage(context.getContentResolver(),bmp,fileName,null);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
context.sendBroadcast(intent);
}
/**
* 将URL转化成bitmap形式
* @param url
* @return bitmap type
*/
public final static Bitmap returnBitMap(String url) {
URL myFileUrl;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
HttpURLConnection conn;
conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
}
Notes:这里Bitmap.compress(Bitmap.CompressFormat.PNG, 90, outStream);解压缩是PNG格式的图片
推荐阅读:BitmapFactory.decodeResource为null的处理方法之一
3.使用Glide加载图片
//glide加载图片
implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'
3.2加载图片
String imgUrl;//设置全局变量
imgURl=mData.get(0).url;//通过下标获得第一张图片
GlideApp.with(BaseApplication.getContext()).load(imgURl).apply(options).into(mImage);
4.开启子线程获取网络图片,更新UI
//保存图片必须在子线程中操作,是耗时操作
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bp = ImageUtils.returnBitMap(imgURl);
if (EmptyUtils.isNotEmpty(bp))
ImageUtils.saveBmp2Gallery(BaseApplication.getContext(), bp, "picName");
}
}).start();
Notes:保存图片之前先一层判断,判断Bitmap对象是否为空,否则程序容易出现空指针异常错误。一旦出现空指针异常的错误,一定要去找哪一个引用没有指向实际存在的对象,导致为null
Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
5.用到的EmptyUtils工具类
import android.os.Build;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
public final class EmptyUtils {
private EmptyUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* 判断对象是否为空
*
* @param obj 对象
* @return {@code true}: 为空
{@code false}: 不为空
*/
public static boolean isEmpty(Object obj) {
if (obj == null) {
return true;
}
if (obj instanceof String && obj.toString().length() == 0) {
return true;
}
if (obj.getClass().isArray() && Array.getLength(obj) == 0) {
return true;
}
if (obj instanceof Collection && ((Collection) obj).isEmpty()) {
return true;
}
if (obj instanceof Map && ((Map) obj).isEmpty()) {
return true;
}
if (obj instanceof SparseArray && ((SparseArray) obj).size() == 0) {
return true;
}
if (obj instanceof SparseBooleanArray && ((SparseBooleanArray) obj).size() == 0) {
return true;
}
if (obj instanceof SparseIntArray && ((SparseIntArray) obj).size() == 0) {
return true;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (obj instanceof SparseLongArray && ((SparseLongArray) obj).size() == 0) {
return true;
}
}
return false;
}
/**
* 判断对象是否非空
*
* @param obj 对象
* @return {@code true}: 非空
{@code false}: 空
*/
public static boolean isNotEmpty(Object obj) {
return !isEmpty(obj);
}
}
感谢查看!