안드로이드 Asset 사용에 있어 몇가지...
밥벌이2011. 8. 5. 18:16
안드로이드에선 패키지 내에 파일을 포함시켜서 어플리케이션에서 사용할 수 있도록 해 주는 기능이 있으며 이렇게 어플리케이션 패키지에 첨부된 파일을 Asset이라 부르고 있다. 아시는 분들은 다 아시겠지만 asset을 패키지에 포함시키는 방법은 쉽다. 일반적인 안드로이드 SDK 환경에서 개발하고 있다면, 그저 안드로이드 프로젝트 아래에 assets 폴더를 만들고 거기에 파일을 집어넣기만 하면 된다. 물론 assets 아래에 폴더를 더 만들어 집어 넣는 것도 가능하다.
이렇게 패키지에 포함시킨 파일은 안드로이드에서 제공하는 AssetManager를 통해 읽어와서 사용할 수 있다. 사용 방법도 간단하다. Context의 getAssets()를 통해 AssetManager를 가져와서 asset 경로를 지정해 주고 open() 하면 해당 asset에 대한 InputStream을 가져 올 수 있다.
안드로이드 SDK에서 apk를 묶을 때, aapt는 몇 가지 확장자를 제외하고는 압축을 시도한다. 아래와 같은 확장자를 가지지 않은 파일의 경우 거의 대부분 해당 파일을 압축 해서 패키징하게 된다. 물론 압축을 했을 경우의 사이즈가 압축하기 전 보다 더 커지는 작은 사이즈의 파일의 경우도 제외되긴 한다만.
내부적으로 압축을 하건 말건 그게 뭔 상관이냐 할 수도 있겠지만, asset으로 넣은 파일이 압축이 되면 여러가지 피곤한 상황을 맞닥뜨릴 수 있게 된다.
1. 우선적으로 파일 사이즈가 1MB 이상이 될 경우 asset의 InputStream을 가져오는 것이 불가능해 질 수 있다. 물론 단말이나 에뮬레이터 바이너리가 안드로이드 소스에서 Asset.h를 고쳐서2 사이즈를 늘였을 경우엔 크게 상관이 없으나, 구글 공식 소스에서 1MB로 제한하고 있으니3 어떤 단말에서도 실행되길 바란다면 1MB 이상의 asset 파일을 넣는게 모험수가 된다. 그래서 만약 1MB가 넘는 파일을 asset으로 넣어서 어플 구동시 사용하고자 한다면 (1)확장자를 위 목록에 있는 것으로 속여서 패키징 때 압축이 되는 것 자체를 막거나 (2)1MB 단위로 잘라서 넣고 나중에 런타임에 이를 붙어서 데이터 영역에 파일을 하나 만들어 쓰는 고육책을 써야 한다.
2. 파일 사이즈가 작다면 AssetManager.open()을 사용해서 InputStream을 성공적으로 가져올 수 있다. 다만 특별한 경우 FileDescriptor나 FileInputStream, FileOutputStream을 가져오기 위해 openFd()를 사용해야 할 필요가 있는데, 만약 압축된 asset에 이를 호출하게 되면 FileNotFoundException을 던져준다!!! 뭐 이 경우 패키징을 할 때 위 경우와 마찬가지로 (1)압축이 되지 않게 확장자를 위의 확장자 중 아무거나 하나로 바꿔서 넣어두던가, (2)혹은 open() 을 사용하여 읽어와서 어딘가에 카피본을 하나 만들어서 사용하는 수 밖에 없다.
위의 상황에서 내가 대안으로 제시한 고육지책들이 도무지 맘에 들지 않는 깔끔쟁이들이라면 http://www.xinotes.org/notes/note/1293/ 를 참조해서 위의 배열에 있는 확장자 외에 추가로 압축되지 않는 확장자를 지정할 수 있으니 참고하자. 물론 난 그 정도로 깔끔쟁이가 아니라서 마지막 방법은 해보질 않았다.... 하하
이렇게 패키지에 포함시킨 파일은 안드로이드에서 제공하는 AssetManager를 통해 읽어와서 사용할 수 있다. 사용 방법도 간단하다. Context의 getAssets()를 통해 AssetManager를 가져와서 asset 경로를 지정해 주고 open() 하면 해당 asset에 대한 InputStream을 가져 올 수 있다.
AssetManager am = context.getAssets();뭐 여기까지는 많은 책자를 통해서 소개하고 있는 부분이지만, 안드로이드 asset은 사용하기에 어느정도 까다로운 구석이 있어 주의깊게 사용할 필요가 있다. 물론 이러한 부분들은 잘 문서화되어 있지도 않아서1 실제로 사용할 때 문제가 되기도 한다.
InputStream in = am.open("assetFile.txt");
안드로이드 SDK에서 apk를 묶을 때, aapt는 몇 가지 확장자를 제외하고는 압축을 시도한다. 아래와 같은 확장자를 가지지 않은 파일의 경우 거의 대부분 해당 파일을 압축 해서 패키징하게 된다. 물론 압축을 했을 경우의 사이즈가 압축하기 전 보다 더 커지는 작은 사이즈의 파일의 경우도 제외되긴 한다만.
/* these formats are already compressed, or don't compress well */static const char* kNoCompressExt[] = {".jpg", ".jpeg", ".png", ".gif",".wav", ".mp2", ".mp3", ".ogg", ".aac",".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",".rtttl", ".imy", ".xmf", ".mp4", ".m4a",".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",".amr", ".awb", ".wma", ".wmv"};
1. 우선적으로 파일 사이즈가 1MB 이상이 될 경우 asset의 InputStream을 가져오는 것이 불가능해 질 수 있다. 물론 단말이나 에뮬레이터 바이너리가 안드로이드 소스에서 Asset.h를 고쳐서2 사이즈를 늘였을 경우엔 크게 상관이 없으나, 구글 공식 소스에서 1MB로 제한하고 있으니3 어떤 단말에서도 실행되길 바란다면 1MB 이상의 asset 파일을 넣는게 모험수가 된다. 그래서 만약 1MB가 넘는 파일을 asset으로 넣어서 어플 구동시 사용하고자 한다면 (1)확장자를 위 목록에 있는 것으로 속여서 패키징 때 압축이 되는 것 자체를 막거나 (2)1MB 단위로 잘라서 넣고 나중에 런타임에 이를 붙어서 데이터 영역에 파일을 하나 만들어 쓰는 고육책을 써야 한다.
2. 파일 사이즈가 작다면 AssetManager.open()을 사용해서 InputStream을 성공적으로 가져올 수 있다. 다만 특별한 경우 FileDescriptor나 FileInputStream, FileOutputStream을 가져오기 위해 openFd()를 사용해야 할 필요가 있는데, 만약 압축된 asset에 이를 호출하게 되면 FileNotFoundException을 던져준다!!! 뭐 이 경우 패키징을 할 때 위 경우와 마찬가지로 (1)압축이 되지 않게 확장자를 위의 확장자 중 아무거나 하나로 바꿔서 넣어두던가, (2)혹은 open() 을 사용하여 읽어와서 어딘가에 카피본을 하나 만들어서 사용하는 수 밖에 없다.
위의 상황에서 내가 대안으로 제시한 고육지책들이 도무지 맘에 들지 않는 깔끔쟁이들이라면 http://www.xinotes.org/notes/note/1293/ 를 참조해서 위의 배열에 있는 확장자 외에 추가로 압축되지 않는 확장자를 지정할 수 있으니 참고하자. 물론 난 그 정도로 깔끔쟁이가 아니라서 마지막 방법은 해보질 않았다.... 하하
'밥벌이' 카테고리의 다른 글
| 안드로이드 GDB 디버깅 ver 2 (2) | 2012.02.22 |
|---|---|
| 안드로이드의 native stack trace의 활용 (0) | 2011.08.30 |
| 안드로이드 캘린더 연동 앱 만들기 Part 2 (0) | 2011.06.02 |
| 안드로이드 캘린더 연동 앱 만들기 Part 1 (12) | 2011.03.24 |
| 리눅스에서 안드로이드 USB 디버깅 연결 설정하기 (0) | 2011.03.18 |