posted by By훈트 2011.07.04 18:16

지금 twitpic4j api를 이용해서 트위터에 사진을 올리는 부분을 디버깅중인데


겔러리에서 사진을 선택해서 올릴때 사진에 따라 OutOfMemoryError를 내며 죽는 현상이 나타났다.


모든 그림이 그런건 아니고 특정 그림만 올릴려고 하면 에러가 났다.


그림이 커봐야 고작 몇메가인데 그것땜에 에러나나 하고 용량을 확인한결과


에러나는 사진은 1.2메가 정도의 크기

 (한계점이 어느정도인지는 모르겠다)


그리고 인터넷을 검색한결과 안드로이드에도 메모리 누수 버그가 있다는 흥미로운 사실과

http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html


나말고도 이런일을 겪오 있는 사람이 또 있다는 사실을 알았따.

http://www.androidpub.com/8933


여튼 용량이 큰 이미지를 처리하려고 할때 에러가 발생 할 수 있다는 사실...


정확한 에러발생 위치는 아직 모르겠다. TwitPic4j 의 upload메소드에서 발생하는 에러이다.



대처법으로 클래스 맴버인 Bitmap 객체에 static을 붙여보라는 말도 있었지만 소용 없는듯...


그런데 문제는 공직 트위터 어플을 이용해서 사진을 올리면 잘올라간다는것이다 -_-


그렇다고 사진의 화질이 줄어들거나 그러지도 않는다. 아 어쩌면 좋지




-----

검색하다 얻은 글이다.

http://www.androidpub.com/31659

각 어플당 힙영역을 2.8메가 이하로 밖에 사용을 못하고 그이상을 사용하려고하면

OutOfMemoryError가 난다고한다. 결국 큰 이미지로 이런저런 처리를 하는 과정에서 힙영역을 많이 사용하게 된 탓인것같다. Bitmap을 byte배열로 변환하는작업이 그런것같다.


위 글에선 해결책으로 BitmapFactory.Option 클래스를 이용해서 그림파일을 메모리에 올리지 않고 너비와 높이를 구한뒤

너무 큰 그림이라고 판단되면 그림을 줄여서 OutOfMemoryError을 피하는 방법을 소개하고 있다.


BitmapFactory.Options options = new BitmapFactory.Options();
18.options.inJustDecodeBounds = true;
19.BitmapFactory.decodeFile(fileName, options);
20. 
21.return options.outHeight;


힙영역에서의 메모리 제한이기때문에 위에서 언급했던것처럼 Bitmap 변수를 static으로 하는 해결책도 틀리진 않는것같다. 다만 나의경우 Bitmap 도 그렇지만 Bitmap을 처리하는 byte

array가 있었고  (array 는 new을 해야해서 힙영역에 밖에 선언을 못할것같다.) TwitPic4J api에서 자체적으로 그림을 업로드하기위해 또 뭔가 사용하는게 있어서 용량을 초과한것 같다.


그리고 아래 주소는 Bitmap크기를 줄이는 방법과 관련된 내용이 잘설명된 포스팅 이다.

http://chiyo85.tistory.com/entry/Android-Bitmap-Object-Resizing-Tip


 
[출처] 카페인님의 블로그

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.05.17 11:51
이클립스 설치폴더에 eclipse.ini의 설정을 바꿔보자.

안드로이드 개발에 권장되는 eclipse.ini 파일 설정값이다.

Maximum permanent generation size at the defualt of 256MB
Minimun Java Heap size -> 128MB
Maximum Java Heap size -> 512MB

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

-startup
plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
-vm

C:/Program Files/Java/jdk1.6.0_16/bin/javaw.exe
-vmargs
-Xms128m
-Xmx512m


[출처] 인조인간 님의 블로그 
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.05.13 13:27
안드로이드 개발을 하다가 보면 많은 어려움에 힘들어할 때가 있습니다.ㅎ

저도 그러한 많은 어려움을 겪어왔고, 오늘도 어려움에 부딪혔죠.
원래 폰 화면을 끄면 Activity는 당연히 onPause()와 onStop()이 호출되어야하는데, 이상하게 onDestroy()까지 호출되더군요..;;

한참을 찾아 헤매다가 알아낸 결과입니다.

메니페스트에서 폰 화면을 한쪽으로 지정해 둘 경우(어쩌면 가로 모드일때만의 문제일 수도 있습니다. 이 부분은 테스트해보지 않았습니다.), 화면이 꺼지면 onDestroy()가 호출되고 다시 onCreate()가 호출되어 액티비티가 새로 생성됩니다.

이렇게 가로 세로 이동 때 액티비티가 재생성되지 않도록 하려면
아래 한 줄을 메니페스트에 삽입해주면 됩니다.
(물론 액티비티 속성으로요)

android:configChanges="orientation|keyboardHidden" 


[출처] 위슈의 마법세상 
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.05.13 11:51



저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.03.14 15:53

FrameLayout은 자식 뷰들을 겹쳐서 그리고자 할때 사용하는 레이아웃이다. 
여러이미지들을 같은영역에 겹쳐서 표시하고자 할때 유용하다.

 

  

 특성이름 적용대상 설명  
android:foreground 부모 뷰 내용위에 겹쳐 그릴 표시물 자원 표시물 자원 참조
android:foregroundGravity 부모 뷰 전경 표시물의 중력(정렬 방식) 다음 상수등 중 하나 또는 여러개를 '|'로 결합한것 :  
top, bottom, left, right, center_vertical, fill_vertical, fill_vertical, center_horizontal, fill_horizontal, center, fill
android:measureAllChildren 부모 뷰 레이아웃의 크기를 모든 자식을 고려해서 결정할 것인지 아니면 VISIBLE로 설정된 자식들만(INVISIBLE로 설정된 것들은 빼고) 고려할 것인지의 여부 true/ false
android:layout_gravity 자식 뷰 부모 안에서 자식 뷰의 중력(정렬방식) 다음 상수등 중 하나 또는 여러개를 '|'로 결합한것 :  
top, bottom, left, right, center_vertical, fill_vertical, fill_vertical, center_horizontal, fill_horizontal, center, fill


<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout 
android:id="@+id/FrameLayout01" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
xmlns:android="http://schemas.android.com/apk/res/android
 android:layout_gravity="center"> 
<ImageView 
  android:id="@+id/ImageView01" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:src="@drawable/green_rect" 
  android:minHeight="200px" 
  android:minWidth="200px"></ImageView> 
<ImageView 
  android:id="@+id/ImageView02" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:src="@drawable/red_oval" 
  android:minHeight="100px" 
  android:minWidth="100px" 
  android:layout_gravity="center" ></ImageView> 
</FrameLayout>
 


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.03.09 16:51

모바일웹용 mp4 동영상 스트리밍 재생 방법

1. 필요항목


1.1 스트리밍 동영상 서버

- 옴니아용 - Window Media Server ( mms 프로토콜로 동영상 스트리밍)
- 안드로이드용 - 다윈스트리밍서버(무료제품 http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=278&MAEULNo=20&no=29095&ref=29095  )
- IPhone용 - 웹서버

1.2 테스트를 위한 도구

-옴니아폰, 안드로이드폰, iPhone

1.3 hint를 처리하는 프로그램

- 안드로이드 계열은 rtsp 프로토콜로 mp4파일의 스트리밍을 지원한다. rtsp로 스트리밍을 위해서는 hint로 처리해야한다.

mp4box 라는 프로그램이 있다. (예 : mp4box -hint video.mp4  주의 : 같은파일 여러번 처리하면 파일이 깨진다. )

 

2. 인코딩


옴니아 : wmv 파일

iPhone : mp4

안드로이드 : iPhone용으로 mp4로 인코딩한 파일을 hint 처리하면 된다.



3. html 소스상


옴니아  : <a href='mms://동영상파일명'>동영상</a>
안드로이드 : <a href='rtsp://동영상파일명'>동영상</a>
iphone  : iphone의 경우는 http로 직접링크를 걸면, 해킹폰에서 다운로드받을 수 있다. 아래와 같이 object를 사용하면 다운로드는 되지 않은다.

<div id="centerbutton">
<!-- 여러가지 이벤트로 동영상을 제어할 수 있다. -->
<a href="javascript:document.movieQuick.Play();"> 강의보기</a>
</div>

<object id="qt_event_source" classid="clsid:CB927D12-4FF7-4a9e-A169-56E4B8A75598" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=7,2,1,0" ></object>
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=7,2,1,0" width="0" height="0" type="video/quicktime" id="movieQuick" style="behavior:url(#qt_event_source);">
<param name="src" value="video.mp4" />
<param name="qtsrc" value="video.mp4" />
<param name="postdomevents" value="true" />
<param name="AUTOPLAY" value="False" />
<embed src="video.mp4" qtsrc="video.mp4" width="0" height="0" id="movieQuick" name="movieQuick" postdomevents="true" AUTOPLAY="False" /></object>



4.hint 처리하는 mp4box 프로그램


다운로드 : http://kurtnoise.free.fr/mp4tools/

hint 처리 후 모토로이/ 갤럭시등 안드로이드 폰에서 오디오가 나오지 않을때 처리 옵션(코덱의 문제로 보인다)

MP4Box0.4.5.exe -hint -latm  ./2.MP4    <--오디오를  Advanced Audio Coding(latm )으로 강제로 사용하도록 처리


도움말 : http://gpac.sourceforge.net/doc_mp4box.php




### 추가 ###

실시간 동영상 스트리밍 서버를 만들어서 테스트를 하는데 어찌된 일인지 셈플 동영상은 잘 플레이가 되는데 새로 인코딩해서 테스트를 해보면 동작을 하지 않아서 오랜 삽질 끝에 인코딩 된 동영상에 hint를 추가해 주어야 한다는 것을 알았다.
hint를 추가하는 것은 보통 mp4box를 많이 사용하는데 사용 방법은 간단하다.


프롬프트창을 열어서 mp4box.exe가 있는 곳으로 이동하여 아래와 같이 입력하면 된다.
mp4box -hint video.mp4
* 여기서 video.mp4는 해당 동영상을 의미함.


[출처] 안개속 님의 블로그
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.03.08 14:34
메모리 부족 관련 질문들이 있어서 정리 합니다. (기억을 더듬어 작성하는거라 잘못된 부분이 있으면 댓글로 말씀주세요)

안드로이드에서 OutOfMemoryError라 발생하는 가장 많은 경우는 바로 비트맵 로딩때문에 발생합니다. 
그 경우 Logcat에서 다음과 같은 메시지를 보실 수 있습니다.

"java.lang.OutOfMemoryError: bitmap size exceeds VM budget"

안드로이드는 애플리케이션 프로세스별로 메모리가 제한되어있다는 것은 다 아실텐데 (16M, 24M, 32M등)  
문제는 위의 메모리 에러가 DDMS에서 가장 쉽게 확인할 수 있는 메모리 값인 VM Heap 사이즈와는 크게 상관없이 발생합니다.
Bitmap을 로딩할 경우 VM 내의 힙메모리를 사용하는게 아니라 VM밖의 Native 힙메모리 영역을 사용하기때문입니다.

0. 가용 메모리의 확인 

아래의 API들을 활용해서 Native Heap 값을 확인할수 있습니다.
Debug.getNativeHeapSize(), Debug.getNativeHeapFreeSize(), Debug.getNativeHeapAllocatedSize()
위 사이즈들은 단말별, 버전별로 조금씩 달라질수 있으니 레퍼런스 폰을 기준으로 약간 여유를 두는 것이 좋을겁니다.

해결 방법은 이미 많은 분들이 작성한 글들이 있는데 정리해보면

1. 아주 큰 이미지 파일을 불러오는 경우 BitmapFactory.Options.inSampleSize 설정을 통해 축소해서 메모리에 로드해야합니다.


2. 이미지의 경우 시스템이 알아서 판단해서 적합한 형식으로 로딩하는데 디폴트인 RGB8888(픽셀당 4바이트)로 로딩하는 경우가 
   많습니다. 이미지를 많이 사용하는 게임등의 경우 투명 이미지는 RGB4444, 불투명 이미지는 RGB565로 충분한 경우가 많으니 
   BitmapFactory.Options.inPreferredConfig 설정값을 어떻게 주고 있는지 확인해보시기 바랍니다. 

3. 더이상 쓰지않는 Bitmap의 경우 Recycle 을 호출해서 바로 가용 메모리를 늘려줍니다.

   bitmap.recycle(); bitmap = null;

  ((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();


4. 메모리 릭이 발생하지는 않는지 확인하는것은 기본이겠죠.




메모리 관련해서는 저도 확실하게 모르는 부분이 있으니 댓글로 추가 정보 주시면 감사하겠습니다.


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.03.07 18:48
비트맵 관련 앱에서 많이 발생하는 힙메모리 관련 오류 해결하기
개발 환경 - 안드로이드 2.1

1. 액티비티
    - onCreate에서 dalvik 버추얼 머신에게 힙메모리 임계값 지정하기 (70%)
       dalvik.system.VMRuntime.getRuntime().setTargetHeapUtilization(0.7f); --> 메인 액티비티에서 한번만 지정

    - onDestroy 이벤트에서 모든 지역변수 null 처리히기, 모든 비트맵 인스턴스 변수 recycle 시키기,
      메인앱에서 System.gc() 한번 호출하기
      
    - dalvik 버추얼 머신에게 dalvik.system.VMRuntime.getRuntime().runFinalizationSync()를
      호출하여 강제로 클래스들의 finalization 호출하기

2. 뷰를 상속한 차일드뷰
    - destroyDrawingCache 메소드를 상속 받아서 이부분에서 비트맵 인스턴스들 recycle 및 null 처리하기

제가 그래픽 관련 앱을짜면서 가장 애먹은 부분이 힙메모리 부분이었습니다.

힙모메리가 한계값까지 계속 늘어나기만 하고 줄어들지 않아서 결국에는 앱이 강제 종료 되는 현상이
계속 발생하더군요.. 구글링으로 여기저기 뒤지다가 안드로이드 플랫폼에서는 앱을 사용자가 종료를
시켜도 실제로는 메모리에 상주해 있어서 메모리가 계속 늘어나는 현상이 있다고 합니다.

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.03.03 17:02
BitmapFactory Class에서 Stream을 읽어오는 기능을 하는데, Stream을 다 읽어 오기전에 연결을 다 끊어 NULL을 반환할 경우가 있다. 아래 처럼 하면 해결 될 듯..

HttpGet httpRequest = null;

URL url = new URL(CommunicationManager.getUrlEncode(url));
httpRequest = new HttpGet(url.toURL());
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse)httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
Bitmap bm = BitmapFactory.decodeStream(instream);

출처: http://cafe.naver.com/busanandroid.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=96
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
posted by By훈트 2011.02.18 11:22

이번에는 Bitmap 데이터 형을 byte Array로 변환하거나 혹은 그 역으로 변환하는 예제를 다루어 보도록 하겠습니다.

해결책

ByteArrayOutputStream 인스턴스를 생성한 후, Bitmap의 compress 메서드를 통해 비트맵을 압축하여 stream에 담습니다.

BitmapFactory의 decodeByteArray 메서드를 통해 byte Array를 Bitmap으로 변환합니다.

토의

안드로이드의 Bitmap은 비트맵 데이터를 stream에 넣어주는 compress 메서드를 제공하고 있습니다.

  1. public byte[] bitmapToByteArray( Bitmap $bitmap ) {  
  2.         ByteArrayOutputStream stream = new ByteArrayOutputStream() ;  
  3.         $bitmap.compress( CompressFormat.JPEG, 100, stream) ;  
  4.         byte[] byteArray = stream.toByteArray() ;  
  5.         return byteArray ;  
  6.     }  

compress 인자 값에는 압축 옵션( JPEG, PNG ) 와 품질 설정 ( 0 - 100까지의 int형 ), 그리고 압축된 바이트배열을 담을 stream을 넘겨줍니다.

byteArray는 stream의 toByteArray() 메서드를 통해 반환받을 수 있습니다.

다음은 역으로, 바이트 배열로부터 비트맵을 생성하는 코드 입니다.

  1. public Bitmap byteArrayToBitmap( byte[] $byteArray ) {  
  2.     Bitmap bitmap = BitmapFactory.decodeByteArray( $byteArray, 0, $byteArray.length ) ;  
  3.     return bitmap ;  
  4. }  

바이트 배열로부터 비트맵 생성은 BitmapFactory의 decodeByteArray의 메서드를 통해 간단히 생성할 수 있습니다. decodeByteArray의 메서드 인자값으로 바이트 배열과 offset(배열의 시작점), length(decode할 바이트 배열의 길이)를 넘겨줍니다.

결과

관련예제

안드로이드 카메라 캡쳐해서 bitmap 얻어오기



[출처] 시스님의 블로그

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

티스토리 툴바