android文件缓存及SD卡创建文件夹失败解决和bitmap内存溢出解决

时间:2021-10-10 12:30:44
 1.相关代码:

    添加权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
/** 获取SD卡路径 **/
private static String getSDPath() {
String sdcardPath = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在
if (sdCardExist) {
sdcardPath = Environment.getExternalStorageDirectory();//获取根目录
}
if (sdcardPath != null) {
return sdcardPath;
} else {
return "";
}
}

  解决方法:获取根目录的代码改为:
  sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();

这样就可以了。

----------------------------------------------------------------------------------------------------------------------------------

附文件缓存类:

package com.etnet.utilities;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Comparator;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;

/**
* 图片文件保存、读写类
* @author Barry
*/
public class FileOperationUtil {
private static final String TAG = "FileOperationUtil";
private static final String CACHE_DIRECTORY = "TqProCache";

private static final int MB = 1024*1024;
private static final int MAX_CACHE_SIZE = 10 * MB;
private static final int LEAST_SIZE_OF_SDCARD = 10 * MB;

/** 从缓存中获取图片 **/
public static Bitmap getImage(final String imageUrl) {
final String path = getCacheDirectory() + "/" + convertUrlToFileName(imageUrl);
// Log.i(TAG, "getImage filepath:" + path);
// Log.i(TAG, "getImage url:" + url);
File file = new File(path);
if (file.exists()) {
// Log.i(TAG, "getImage file exists");
Bitmap bmp = null;
try {
//宽变为原图的1/3,高也变为原图的1/3。这样是为了降低内存的消耗,防止内存溢出
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 3;
bmp = BitmapFactory.decodeFile(path,options);
LogUtil.d(TAG, "bmp size="+bmp.getByteCount());
} catch (Exception e) {
e.printStackTrace();
}
if (bmp == null) {
file.delete();
} else {
updateFileTime(path);
return bmp;
}
}
return null;
}

/** 将图片存入文件缓存 **/
public static void saveBitmap(String imageUrl, Bitmap bm ) {
if (bm == null) {
return;
}
//判断sdcard上的空间
if (getFreeSpaceOfSdcard() < LEAST_SIZE_OF_SDCARD) {
//SD空间不足
return;
}
String filename = convertUrlToFileName(imageUrl);
String dir = getCacheDirectory();
File dirFile = new File(dir);
if (!dirFile.exists()){
if(!dirFile.mkdirs()){
Log.w(TAG, "create cache file directorys failed");
}
}
File file = new File(dir +"/" + filename);
try {
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.w(TAG, "FileNotFoundException");
} catch (IOException e) {
Log.w(TAG, "IOException");
}
}

/**
* 计算存储目录下的文件大小,
* 当文件总大小大于指定的MAX_CACHE_SIZE或者sdcard剩余空间小于指定的LEAST_SIZE_OF_SDCARD
* 那么删除40%最近没有被使用的文件
*/
public static boolean removeExtraCache() {
File dir = new File(getCacheDirectory());
File[] files = dir.listFiles();
if (files == null) {
return true;
}
if (!android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
return false;
}

int dirSize = 0;
for (int i = 0; i < files.length; i++) {
dirSize += files[i].length();
}
// LogUtil.d("Barry", "dirSize="+dirSize);

if (dirSize > MAX_CACHE_SIZE || getFreeSpaceOfSdcard() < LEAST_SIZE_OF_SDCARD) {
int removeNum = (int) ((0.4 * files.length) + 1);
/* 根据文件的最后修改时间进行升序排序 */
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File file1, File file2) {
if (file1.lastModified() > file2.lastModified()) {
return 1;
} else if (file1.lastModified() == file2.lastModified()) {
return 0;
} else {
return -1;
}
}
});
/* for (int i = 0; i < files.length; i++) {
LogUtil.d("Barry", "file.modifiedTime="+files[i].lastModified());
}*/
for (int i = 0; i < removeNum; i++) {
files[i].delete();
}
return true;
}else{
return false;
}
}

/** 修改文件的最后修改时间 **/
public static void updateFileTime(String path) {
File file = new File(path);
long newModifiedTime = System.currentTimeMillis();
file.setLastModified(newModifiedTime);
}

/** 计算sdcard上的剩余空间 **/
private static int getFreeSpaceOfSdcard() {
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
double sdFreeSize = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize());
return (int) sdFreeSize;
}

private static String convertUrlToFileName(String url) {
String[] strs = url.split("/");
String savedImageName = strs[strs.length - 1];
return savedImageName;
}

/** 获得缓存目录 **/
private static String getCacheDirectory() {
String dir = getSDPath() + "/" + CACHE_DIRECTORY;
return dir;
}

/** 获取SD卡路径 **/
private static String getSDPath() {
String sdcardPath = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED); //判断sd卡是否存在
if (sdCardExist) {
sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath(); //获取根目录
}
if (sdcardPath != null) {
return sdcardPath;
} else {
return "";
}
}
}