관리 메뉴

정상에서 IT를 외치다

[Android, Cache, Bitmap] 내부저장소에 비트맵 저장하기 본문

안드로이드

[Android, Cache, Bitmap] 내부저장소에 비트맵 저장하기

Black-Jin 2019. 4. 3. 17:45
728x90
반응형

안녕하세요. 블랙진입니다.


Bitmap을 내부저장소(Cache)에 저장하고 불러올 수 있는 예제를 준비해보았습니다.



1. 저장소?


안드로이드는 크게 두가지 저장소를 가지고 있습니다.


1-1 내부저장소


해당 어플리케이션만 읽고 쓸 수 있으며 어플리케이션이 삭제되면 같이 지워집니다.


여기에는 임시 파일을 저장하는 캐시데이터베이스를 저장하는 파일 그리고 기타 파일을 저장할 수 있는 영역으로 나뉩니다.



1-2 외부저장소


외부저장소는 다른 어플리케이션이 접근할 수 있는 영역입니다. 이는 고유영역공용영역으로 나뉘게 되는데 고유영역은 어플리케이션이 삭제되면 함께 지워지지만 공용영역은 어플리케이션이 삭제되어도 데이터는 남아 있습니다. (공용역역은 일반적으로 단말기의 외장 SD 카드를 지칭하지만, 단말기에 따라서는 이 영역이 외장 SD카드가 아닌 단말기 내부에 탑재되어 있는 경우도 있습니다)



2. 캐시 파일에 저장하기


비트맵을 캐시에 저장하는 함수입니다.

private void saveBitmapToJpeg(Bitmap bitmap, String name) {

//내부저장소 캐시 경로를 받아옵니다.
File storage = getCacheDir();

//저장할 파일 이름
String fileName = name + ".jpg";

//storage 에 파일 인스턴스를 생성합니다.
File tempFile = new File(storage, fileName);

try {

// 자동으로 빈 파일을 생성합니다.
tempFile.createNewFile();

// 파일을 쓸 수 있는 스트림을 준비합니다.
FileOutputStream out = new FileOutputStream(tempFile);

// compress 함수를 사용해 스트림에 비트맵을 저장합니다.
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);

// 스트림 사용후 닫아줍니다.
out.close();

} catch (FileNotFoundException e) {
Log.e("MyTag","FileNotFoundException : " + e.getMessage());
} catch (IOException e) {
Log.e("MyTag","IOException : " + e.getMessage());
}
}

구글 문서와 함께 하나하나 다시 살펴보겠습니다.


File(File parent, String child)

Creates a new File instance from a parent abstract pathname and a child pathname string.

File tempFile = new File(storage, fileName);

첫 번째 파라미터 경로에 파일 인스턴스를 생성해 줍니다.



createNewFile()

Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist.

tempFile.createNewFile();

createNewFile 함수를 사용해 해당 경로에 빈 파일을 생성해 주며 만약 파일이 있는 경우 생성하지 않습니다.


public FileOutputStream (FileDescriptor fdObj)
FileOutputStream out = new FileOutputStream(tempFile);

파라미터로 보낸 파일을 쓰기 위한 스트림을 생성합니다.



compress(Bitmap.CompressFormat format, int quality, OutputStream stream)

Write a compressed version of the bitmap to the specified outputstream.

bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);

compress 함수를 사용해 스트림에 비트맵을 저장합니다.



3. 캐시 파일 불러오기

File file = new File(getCacheDir().toString());
File[] files = file.listFiles();

for(File tempFile : files) {

Log.d("MyTag",tempFile.getName());

}

File 함수를 사용해 캐시에 저장되어 있는 파일을 불러올 수 있습니다.



4. 예제


사용할 예제 이미지 입니다.

 출처 : 구글


서버로 부터 받아온 이미지를 Glide 를 사용해 Bitmap 으로 변환한 후 캐시에 저장하겠습니다..

SimpleTarget<Bitmap> target = new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {

String fileName = "blackJin";

//서버로부터 받아온 bitmap 을 blackJin 이름의 jpg 로 변환해 캐시에 저장합니다.
saveBitmapToJpeg(bitmap, fileName);
}
};

Glide.with(this.getApplicationContext())
.load("https://i.ytimg.com/vi/WCXM4DnwT1g/maxresdefault.jpg")
.asBitmap()
.into(target);

saveBItmapToJpeg()는 위에서 언급했듯이 비트맵을 파일로 변환 후 캐시에 저장하는 함수입니다.

이렇게 블랙펜서 이미지를 blackJin이라는 이름의 파일로 저장했습니다.


이렇게 blackJin 이라는 파일명을 가진 경로를 캐시에서 가져오겠습니다.

private void getBitmapFromCacheDir() {

//blackJin 이 들어간 파일들을 저장할 배열 입니다.
ArrayList<String> blackJins = new ArrayList<>();

File file = new File(getCacheDir().toString());

File[] files = file.listFiles();

for(File tempFile : files) {

Log.d("MyTag",tempFile.getName());

//blackJin 이 들어가 있는 파일명을 찾습니다.
if(tempFile.getName().contains("blackJin")) {

blackJins.add(tempFile.getName());

}

}

Log.e("MyTag","blackJins size : " + blackJins.size());
if(blackJins.size() > 0) {
int randomPosition = new Random().nextInt(blackJins.size());

//blackJins 배열에 있는 파일 경로 중 하나를 랜덤으로 불러옵니다.
String path = getCacheDir() + "/" + blackJins.get(randomPosition);

//파일경로로부터 비트맵을 생성합니다.
Bitmap bitmap = BitmapFactory.decodeFile(path);
}
}


getCacheDir/{파일명}


을 통해 캐시에 저장되어 있는 파일 경로를 불러올 있습니다.


public static Bitmap decodeFile (String pathName)

Decode a file path into a bitmap. If the specified file name is null, or cannot be decoded into a bitmap, the function returns null.


BitmapFactory.decodeFile(path)


불러온 경로를 BitmapFactory 의 decodeFile 함수를 사용해 비트맵으로 반환해줍니다.



정리


비트맵을 캐시에 저장하는 포스팅을 쓸려고 준비하다가 오히려 안드로이드 기기에서 저장소에 관해 더 공부하게되었습니다. 파일 입출력 및 저장소에 관해 따로 포스팅을 쓸 정도로 꼭 필요한 내용인것 같아 다음에는 저장소에 관해 정리해보겠습니다. 감사합니다.



구글문서 - 저장소 옵션


안드로이드 저장소 경로 얻는 메소드


파일 입출력에 필요한 경로 총정리




반응형
6 Comments
  • 프로필사진 ㅁㅇㄴㄹ 2020.12.09 02:01 좋은 정보 감사합니다.
    실례가 되지 않는다면 해당 코드들로 간단한 예제를 보여주실 수 있을까요? 이해가 안 가는 부분이 아직 많아 부탁드립니다.
  • 프로필사진 Black-Jin 2021.12.16 10:57 신고 전체코드는 따로 없습니다. 혹시 이해가 안가시는 부분을 구체적으로 적어주시면 최대한! 자세히 답변하도록 하겠습니다. 감사합니다.
  • 프로필사진 ㅇㅇㅇㅇ 2020.12.19 03:36 제 생각에는 blackJin 이름으로 계속 파일을 만드니 앱을 열때마다 blackJin이라는 이름을 가진 중복되는 파일들이 생길거라고 생각했는데 실제로는 그렇지 않은 이유는 뭔가요?
  • 프로필사진 Black-Jin 2021.12.16 10:55 신고 오래전에 한 테스트라 파일이 덮어씌어 지거나 아니면 자동으로 파일명에 추가 이름이 부여되었던것 같습니다 @_@

    Device File Explorer 를 통해 저장되어 있는 파일을 직접 보시면 좋을 듯 합니다 :)
  • 프로필사진 ㅇㅇ 2021.12.16 10:38 제일 큰 문제가 cashdir이 어딘지 파일탐색기에서 못찾겠어요
    그냥 간단하게 바탕화면같은 메인폴더나 download같은데 저장하면 안되나요? 왜 굳이 cashdir을 쓰는지..
  • 프로필사진 Black-Jin 2021.12.16 10:51 신고 앱에서는 여러 저장소가 있습니다. 말씀하신 메인 폴더나 downlooad 는 공용 공간이므로 사용하기 위해서는 따로 앱에서 권한을 부여 받아야만 합니다. 또한 이 경우 앱이 제거되어도 파일은 공용공간에 남아있는 특징이 있습니다. 반대로 cashdir로 받아온 경로는 실행되고 있는 앱만의 고유 캐시 공간으로 앱이 제거되면 같이 제거되고 따로 권한을 요청하지 않아도 됩니다. 저장소는 보안 문제로 여러 이슈를 고려해야 되는 점이 있습니다. :)

    저장소에 관한 자세한 설명은 아래 링크를 통해 확인 부탁드립니다.
    https://black-jin0427.tistory.com/236
댓글쓰기 폼