sitelink1 | https://blog.naver.com/miraclehwan/220611579792 |
---|---|
sitelink2 | |
sitelink3 |
우선 제가 구현한 기능(소스)에 대한 설명을 하면,
Save 버튼 클릭 -> 외부저장소에 [AnimationCapture] 폴더 유무 확인 후 없으면 생성 -> 사진저장(Capture20160128171944.jpeg)
순서입니다. 이 과정에서 엄청난 삽질이 있었는데 그 부분 및 해결한 방법에 대해서 포스팅하려고 합니다.
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/AnimationCapture";
final FrameLayout capture = (FrameLayout) findViewById(R.id.framelayout);//캡쳐할영역(프레임레이아웃)
File file = new File(path);
if(!file.exists()){
file.mkdirs();
Toast.makeText(login.this, "폴더가 생성되었습니다.", Toast.LENGTH_SHORT).show();
}
SimpleDateFormat day = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
capture.buildDrawingCache();
Bitmap captureview = capture.getDrawingCache();
FileOutputStream fos = null;
try{
fos = new FileOutputStream(path+"/Capture"+day.format(date)+".jpeg");
captureview.compress(Bitmap.CompressFormat.JPEG, 100, fos);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path + "/Capture" + day.format(date) + ".JPEG")));
Toast.makeText(login.this, "저장완료", Toast.LENGTH_SHORT).show();
fos.flush();
fos.close();
capture.destroyDrawingCache();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
위의 소스가 제가 구현한 전체 소스입니다.
한줄한줄 제가 이해한대로 적으면....(잘못 이해했을 수도 있습니다.. 지적해주십시오~~~)
String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/AnimationCapture";
// 파일을 저장할 경로를 설정해줍니다. 내부저장소, 외부저장소가 있는데 외부저장소로 하였고
외부저장소에 파일을 쓰기위해 권한이 필요하여 아래 권한을 Manifest.xml 파일에 선언해줘야 합니다.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
final FrameLayout capture = (FrameLayout) findViewById(R.id.framelayout);
// 버튼 부분을 제외하고 이미지와 텍스트만 캡쳐하기 위해 Layout을 캡쳐영역으로 했습니다.
(원래 윗부분에 있었는데 삽질하다가 click메소드로 들어와버렸네요....)
File file = new File(path);
if(!file.exists()){
file.mkdirs();
Toast.makeText(login.this, "폴더가 생성되었습니다.", Toast.LENGTH_SHORT).show();
}
// 처음생성한 path 경로가 존재하는지 확인 후 존재하지 않을 시 경로를 생성하게 됩니다.
mkdir과 mkdirs가 존재하는데, mkdir은 상위디렉토리가 없을 경우 생성할 수 없습니다.
즉, \a\anmationcapture를 생성하는데 a라는 디렉토리가 없으면 생성불가
mkdirs는 a까지 생성하는 차이가 있습니다.
SimpleDateFormat day = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
// 파일 제목을 위해서 넣어뒀습니다. 캡쳐를 눌렀는데 중복된 이름이 나오면 안되기 때문에.
capture.buildDrawingCache();
// DrawingCache에 저장합니다.
Bitmap captureview = capture.getDrawingCache();
// DrawingCache에 저장된 이미지를 Bitmap 형태로 변환(?)합니다.
FileOutputStream fos = null;
try{
fos = new FileOutputStream(path+"/Capture"+day.format(date)+".jpeg");
captureview.compress(Bitmap.CompressFormat.JPEG, 100, fos);
//파일을 저장하는 부분입니다.
정확한 용어는 생각이 모르겠고...... 제가 겪어본 느낌으로는...
처음에 파일의 경로와 이름을 가지고 있는 fos라는 객체를 생성하고, <-- fos = new File 있는 라인
captureview에 저장된 Bitmap파일을 JPEG로 변경하여 저장합니다. <-- captureview.compress 있는 라인
정확한 용어가 알고 싶으신 분은 디벨로퍼홈페이지를 참고하시길...
이제 파일 저장은 다 끝났습니다.
이렇게 간단한걸 삽질을 했던걸 생각하면... 하.....
그런데 저장은 되었다고 나오는데 갤러리에서는 확인이 안되고 파일관리자로 보면 보이는 경우가 있습니다...(접니다..저..)
##어플 안깔아도 기본적으로 디바이스에 "파일관리자"라는 어플이 있더군요..
위와 같은 경우 PC에 연결해도 이미지가 보이지 않으실 겁니다...(이놈때메 또 삽질을... 하...)
해결방법은 초 간단합니다.
이미지스캐닝!!
저는 Save를 누른 파일에 대해서만 스캐닝이 필요해서 특정파일스캐닝을 사용하였습니다.
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + path + "/Capture" + day.format(date) + ".JPEG"))); 특정폴더 - sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory()+"/AnimationCapture"))); 전체폴더 - sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory())));
입니다~
Toast.makeText(login.this, "저장완료", Toast.LENGTH_SHORT).show(); fos.flush(); fos.close(); // 이제 저장도 다 되었고, 파일도 갤러리에 나오니 "저장완료" 메시지를 띄어주고, flush의 경우 말그대로 비워내는 것 같네요...(안찾아봄...) close도 말그대로 닫는다...?겠죠...? 이제 정말 끝난줄 알았는데... 문제가 발생했습니다.(몇번째삽질인지..) 저는 프레임레이아웃에 리니어레이아웃을 겹쳐서 보여주고 안보여주는 식으로 했는데 다음페이지를 저장해도 계속 처음 페이지만 저장이 되는 버그(?)같은 저의 실수가 발생했습니다. 이놈저놈 다 바꿔보다가 3번쨰페이지를 처음으로 저장하니 계속 3번째페이지만 저장이되고... 2번쨰를 하니 2번째페이지만 저장이 되고... 처음 저장한 이미지가 계속 저장이 되는... 삐리리같은 상황이....
제가 생각한 것은 처음에 캐시를 한 이미지가 계속 남아있어서 그 이미지로만 계속 저장되는 것이였습니다. 찾아보니 아래처음 간단합니다... capture.destroyDrawingCache(); // 말그대로 DrawingCache를 파괴하는 거겟죠... (destroy인줄도 모르고 close, flush를 찾고있던 전 바보...)