| |
|
|
|
|
|
안드로이드를 탑제하는 디바이스 제조사는.. 안드로이드 운영체제의 외형(Theme)을 원하는대로 커스터마이징할 수 있습니다. 내부 핵심 코어는 동일하나.. 외형을 다르게 함으로써 안드로이드는 다양한 모습으로 사용자에게 전달됩니다.. 이러한 안드로이드의 특징은 분명 장점입니다만.. 제조사와 개발자에게 이러한 다양성은 골치 아픈 "선택"입니다..
갤럭시 노트에 맞도록 UI를 구성한 앱을 그대로 갤럭시탭 10.1에서 실행해보니.. UI가 싸그리 깨져버려.. 다시 갤럭시탭 10.1에 맞도록 UI를 재구성하게 되었는데요. 갤럭시 노트의 해상도와 탭 10.1의 해상도는 동일하나.. DPI가 다르므로 나타나는 것으로.. 만약 해상도가 달라졌다면 더욱 골치 아팠겠지요..
여튼.... UI를 맞추는 도중.. Dialog의 크기를 조정해야할 필요가 있었습니다.. 갤럭시 노트에서는 별 문제가 없었으나.. 탭에서는 폰트가 커지는 바램에 아래의 화면처럼 컨텐츠가 Dialog 크기보다 넘치는 문제가 발생했습니다..
뭐... Dialog의 너비를 늘리면 해결될일.. 해서 다음과 같은 코드로 Dialog의 크기를 확장했습니다. 일반적으로 대화창을 화면에 표시하는 코드에 대해서 대화창의 크기를 늘려주는 코드로 추가된 것은 11번 ~ 14번 그리고 17번 ~ 18번 코드입니다. 13번 코드에서 800 픽셀 크기로 늘렸습니다. 그리고 실행해보니 원하는대로 크기가 늘어났습니다.
근데... 가만히 보면.. 이상한게 있습니다.. 대화창의 가장자리의 반투명 효과가 제대로 먹히질 않습니다. 이는 기본적으로 탭10.0에서 제공하는 테마(Theme)에서 대화상자의 크기는 딱! 정해져 있습니다. 즉, 크기 자체도 테마 값으로 생각할 수 있습니다. 대화상자의 크기를 키우면? 기존의 테마값들 중 몇가지가 초기화되는 모양입니다. 초기화된 녀석이 무엇인지 찾아보면 해결할 수 있겠지요..
대화상자의 크기값을 지정함으로써 초기화된 속성은 대화상자의 배경으로 사용될 Drawable 객체입니다. 이 녀석이 기본값인 검정색 Drawable로 초기화된 것으로 예상되고..... 그렇다면 이 녀석을 완전 투명으로 처리한다면 해결될듯합니다.. 이에 대한 코드를 앞서 언급한 코드에 덧붙이면 다음과 같습니다. 새롭게 추가된 코드는 오직 19번 코드입니다. 함수명 자체가 앞서 설명드린 것을 그대로 나타내고 있습니다. 실행해보면... 아래의 화면처럼 완벽하게 원하는 결과를 얻을 수 있습니다.
|
김형준(Dip2K)
2012/05/02 16:35
2012/05/02 16:35
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/827 |
|
|
|
|
|
|
|
작디 작은 화면을 가지는 모바일 디바이스.. 요즘은 작다고 하면 한대 맞은 시대이긴 하지만 말입니다. 여튼 모바일 디바이스에서 이미지를 참 많이 가져다 사용합니다. 아래의 코드는 파일명으로 해서 코드단에서 쉽게 사용할 수 있는 Bitmap을 하나 만드는 코드입니다. 와우.. 참 쉽죠? 사실 1번과 2번 코드는 옵션입니다. 이 코드가 필요없을때는 BitmapFactory의 decodeFile 함수의 두번째 인자를 null로 주면 됩니다. 생성한 비트맵을 잘썼다면 7번 코드를 호출해 줍니다.
이 글의 요지는 이렇게 비트맵을 생성하는게 아니고.. 생성된 비트맵을 회전하고 Mirror시키는 방법이니다. 먼저 회전입니다. 2번 코드에서 postRotate 함수의 첫번째 인자가 바로 회전하고자 하는 각도입니다. 다음은 Mirror 시키는 코드입니다. 회전처럼 행렬을 이동하기는 하는데.. Mirror의 경우 직접 행렬요소를 직접 지정하고 있습니다. 행렬(Matrix)는 개발자에게 매우 유용한 수학적 도구중에 하나가 분명합니다.
안드로이드에서 비트맵에 대한 이야기가 나온 차에 하나 더...! 비트맵을 파일로 저장하는 방법입니다. 안드로이드는 PNG와 JPG 포맷을 지원합니다. 아래의 코드는 비트맵을 PNG 포맷에 대한 파일로 저장하는 코드입니다.
|
김형준(Dip2K)
2012/04/27 16:09
2012/04/27 16:09
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/823 |
|
|
|
|
|
|
|
안드로이드를 처음 학습할때... 첨으로 별나다.. 싶었던 기억이 이었습니다만.. 지금은 제법 잘만들어진 프레임워크라는 생각이 듭니다. 버전업이 많이 되어져.. 안정화가 되었다는 것이 가장 큰 이유인듯 하지만 말입니다. 아래의 코드는 디바이스에 저장된 이미지 파일(PNG, JPG)들 전체를 얻는 코드입니다.
|
김형준(Dip2K)
2012/04/27 15:51
2012/04/27 15:51
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/821 |
|
|
|
|
|
|
|
| 맨날 까먹어 책 찾아 보고.. 인터넷 뒤져보고.. 해서 이 기회에 버튼에 대한 클릭 이벤트 핸들러 코드를 작성하는 것에 대해 정리를 해 놔야겠습니다. 머리가 나쁘니.. 손이 좀 고생을 해야겠지요..
레이아웃에 두개의 버튼이 있다고 가정하겠습니다. id는 각각 viewMode, editMode라고 하면.. 클릭 이벤트에 대한 핸들러 코드를 작성하는 방법에는 2가지가 있습니다. 물론 따져보면 둘다 동일한 방식이기는 하지만 코드 모냥새가 다르므로 다르다고 치겠습니다.
첫번째 방식입니다. 다수의 버튼들에 대한 이벤트 코드를 한자리에 가족같은 분위기로 다스리는 치국평천하 방식이라고 할 수 있겠습니다.. 두번째 방식입니다. 이 방식은 각 버튼마다 이벤트 처리 코드를 따라 분리해 두는 방식입니다.
앞서도 말씀드렸지만.. 첫번째나 두번째나 결국 똑 같은 방식입니다..
|
김형준(Dip2K)
2011/10/26 13:19
2011/10/26 13:19
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/753 |
|
|
|
|
|
|
|
모바일이 이미 충분히 대중화되었음으로 해서.. GIS 분야 중 하나인 LBS(Location Based System; 위치 기반 시스템)을 활용할 수 다양한 앱이 꽃을 피울 기회를 맞이 한지 이미 꽤 오래되었습니다.
이에 안드로이드가 탑재된 모바일 기기의 GPS를 통해 현재 자신의 위치를 얻을 수 있는 안드로이드 API를 활용하는 샘플 코드를 공유해 봅니다. 아래는 샘플 코드에 대한 스크린 샷입니다.
위치(WGS84 타원체에 대한 경위도)는 물론이고 현재 이동 속도과 위치 정확도(휴대용 GPS의 경우 최고의 정확도 오차는 10m로 제한됨) 등을 얻어와 화면에 표시하고 있습니다. 또한 GPS의 원체 데이터 형식인 NMEA0183을 표시하고 있습니다.
GPS에게 위치데이터 힌트를 제공하는 인공위성의 수 역시 제공하고 있는데요. 이 인공위성의 수는 NMEA0183 데이터로부터 얻어올 수 있습니다. 긴 설명보다는 실제 실행 가능한 예제 코드 샘플을 공유합니다.
인터넷 상에서 공유되고 있는 다양한 소스를 취합하여 이 하나의 예제 샘플을 제작했습니다. 안드로이드에서 GPS로부터 위치 데이터 등을 취득하고자 하시는 개발자 분들에게 조금이라도 도움이 되시길 바랍니다.
GPS로부터 수신받은 좌표(WGS84 타원체의 경위도 좌표)를 다른 좌표계로 변환하기 위한 방법은 다음 URL을 통해 살펴보시기 바랍니다.
|
김형준(Dip2K)
2011/09/18 15:20
2011/09/18 15:20
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/742 |
|
|
|
|
|
|
|
몇일전.. 안드로이드에서 OpenGL ES의 텍스쳐 맵핑을 살펴보고 실습을 해보면서.. 아무리 해도 텍스쳐가 맵핑되지 않았습니다.. 일단 OpenGL에서 텍스쳐맵핑을 위한 OpenGL의 API의 사용순서에 문제가 있겠거니.. 하며 문제를 파악해 나갔지만.. 도통 모르겠다 싶었구요.. 그러던중.. 문제를 해결.. ㅜㅜ
텍스쳐 맵핑을 하기위한 준비 과정으로 먼저 Bitmap 객체를 하나 생성해야 하는데.. 아래의 코드를 통해 Bitmap 객체를 생성했었습니다.
이 한줄로 비트맵을 포맷에 상관없이 읽을 수 있는 안드로이드의 API에 감탄을 했던것같은데.. 바로 문제는 여기에 있었습니다.. 이 코드를 아래 코드로 변경해야 텍스쳐가 맵핑됩니다.
감탄했던 단 한줄의 코드 대신.. 원시 데이터로써 비트맵을 읽어 스트림을 만들고 이 스트림을 통해 비트맵을 만드는 제법 복잡다단한 방법이 바로 옳바른 방법이였습니다.. 아래는 그토록 보고 싶어라 했던 텍스쳐가 맵핑된 화면 결과...
흠.... 답답했던 때가 언제었냐는듯.. 눈이 맑아집니다.. ㅎㅎ 만약 첫번째 방식으로 하여 텍스쳐맵핑이 않되시는 분이 계시다면 두번째 방법으로 접근해 보시기 바랍니다.
|
김형준(Dip2K)
2011/08/30 09:43
2011/08/30 09:43
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/737 |
|
|
|
|
|
|
|
| 자바에서 사용자 정의 이벤트를 추가하는 방법에 대한 글(http://www.gisdeveloper.co.kr/734)을 남긴 적이 있습니다. 그 글에서 소개한 사용자 정의 이벤트 추가 방식은 안드로이드에서는 추천하지 않는다는 글로 정리를 했습니다.
안드로이드에서는 어떤 식으로 사용자 정의 이벤트를 남기면 좋을까에 대한 것이 이 글의 주제입니다. 일반적인 자바에서 사용자 정의 이벤트는 이벤트 리스트에 여러개의 이벤트를 등록하게 됩니다. 예를 들어서 특정한 뷰에 대한 마우스 클릭에 대한 이벤트라면.. 여러개의 이벤트를 등록하게 하는 방식입니다. 하지만 안드로이드라는 환경은 한정된 리소스를 가지고 있음으로 해서.. 예로 든 특정 뷰에 대한 마우스 클릭에 대한 이벤트에 대해 '하나'만을 등록하는 방식이 더 적당하다고 할 수 있습니다. 물론... 필요하다면 자바에서 일반적인 사용자 정의 이벤트를 추가하는 방식을 안드로이드에서 사용해도 됩니다. 그럼.. 안드로이드에서 적합한 사용자 정의 이벤트를 추가하는 방식에 대해 정리해 보겠습니다.
먼저 새롭게 추가할 이벤트가 무엇인지 확인해 봅니다. 예를 들어 맵엔진 개발에 있어서 맵의 축척이 변경되었을때 발생하는 이벤트를 추가하는 예를 통해 살펴보겠습니다. 1개의 클래스와 또 다른 한개의 인터페이스를 추가해야 하는데.. 새롭게 추가할 클래스는 이벤트 객체에 대한 클래스이며 새롭게 추가할 인터페이스는 이벤트 리스너입니다. 이 둘은 일반적인 자바에서의 사용자 정의 이벤트에 대해서 동일한 내용입니다. 다른게 없습니다.
아래는 축척 변경 이벤트에 대한 이벤트 객체 클래스 소스입니다. 이벤트 객체는 이벤트를 발생시킨 주체(getSource 매서드를 통해 반환됨)를 기본적인 내용으로 하며 그외 더 필요한 정보를 담을 수 있습니다. 다음으로 이벤트 리스너에 대한 인터페이스입니다.
이벤트 리스너 인터페이스에는 여러개의 이벤트를 넣을 수 있는데.. 이 경우 맵축척 변경에 대한 이벤트만이 있습니다. 이제 축척 변경에 대한 이벤트에 필요한 클래스와 인터페이스가 준비되었습니다.
그럼 맵엔진 단에서 맵 축척이 변경되었을때 이벤트를 발생시키는 것에 대해 코드를 통해 살펴보겠습니다.
보시는 것처럼.. 이벤트 리스너에 대한 변수와 이 이벤트 리스너를 할당시키기 위한 매서드 끝으로 실제 이벤트가 발생될때 이벤트 리스너를 실행해 주는 코드로 구성되어 있습니다. 여기까지가 일반적으로 안드로이드에서 사용자 정의 이벤트를 만들어 주는 방식입니다. 그럼.. 이 맵축척이 변경되었을때 발생하는 이벤트에서 원하는 코드를 작성해보는 샘플 코드는 어떻게 될까.. 아래 코드를 통해 살펴보시기 바랍니다.
map은 앞서 XrMap 클래스에 대한 변수입니다. 축척이 변경될때마다 화면에 SCALE CHANGED라는 메세지를 토스트를 통해 띠웁니다.. 끝으로 안드로이드에서 버튼을 클릭했을 때 이벤트를 할당하는 코드를 살펴보고.. 위의 맵축척 변경 이벤트 할당 코드와 비교해 보시기 바랍니다.
보시는 것처럼.. 이벤트를 할당하는 두개의 구조가 모두 동일함을 알 수 있습니다. 이상으로 안드로이드에서 사용자 정의 이벤트를 할당하는 방법에 대한 정리를 마치도록 하겠습니다.
|
김형준(Dip2K)
2011/08/17 16:09
2011/08/17 16:09
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/735 |
|
|
|
|
|
|
|
| 이전 글을 통해 안드로이드에서 OpenGL ES에 대한 초기화에 대해 살펴보았습니다. 이 글은 간단한 폴리곤을 화면상에 렌더링해 보는 API에 대해 살펴보겠습니다. 간단한 폴리곤에 대한 렌더링을 위해 먼저 폴리곤을 구성하는 데이터에 대한 개념을 살펴보도록 하겠습니다. (OpenGL ES를 보시기 전에 먼저 OpenGL을 선행 학습하시면 훨씬 쉽게 이글을 이해할 수 있습니다.)
정점(Vertex) : 정점은 3D 모델을 구성하는 최소 단위입니다. 정점은 2개 이상의 모서리(Edge)가 만나는 점입니다. 3D 모델에서 정점은 모든 연결된 모서리나 면(Face) 그리고 폴리곤 사이에 공유됩니다. 또한 정점은 카메라나 광원의 위치를 나타내는데도 사용됩니다.
모서리(Edge) : 모서리는 두개의 정점을 잇는 선분입니다. 모서리는 면이나 폴리곤의 외곽선입니다. 3D 모델에서 모서리는 2개의 인접한 면이나 폴리곤 사이에 공유됩니다. OpenGL ES에서는 선분을 정의한다라는 개념보다는 정점을 이용해 면을 정의한다고 합니다. 면은 최소 3개의 모서리로 구성됩니다.
면(Face) : 면은 삼각형입니다. 면은 3개의 정점으로 구성되며 3개의 모서리로 둘러 싸여졌습니다. 면의 구성을 변환하면 모든 연결된 정점과 모서리 그리고 폴리곤에 영향을 받습니다. 면을 구성하는 정점의 지정 순서에 따라 면의 앞면과 뒷면에 대한 정의가 달라집니다. 앞면과 뒷면이 중요한 이유는 퍼포먼스에 있습니다. 뒷면은 눈에 들어나지 않으므로 렌더링에서 제외될 수 있기 때문입니다. 정점의 지정 순서에 대해 앞면이냐 뒷면이냐를 정의할 수 있는데 glFrontFace 매서드를 통해 가능합니다. 정점의 지정순서는 삼각형에 대해 반시계 방향 순서(CCW)냐 시계 방향 순서(CW)냐입니다. OpenGL ES는 기본적으로 반시계 방향이 앞면을 의미합니다.
폴리곤(Polygon) : 폴리곤은 하나의 3D 모델이라고 생각하면 됩니다. 폴리곤을 구성하기 위해서는 정점들의 데이터와 이 정점들 중 3개를 이용해 면을 구성하기 위한 정점 인덱스 정보를 통해 이뤄집니다. 폴리곤을 화면에 렌더링하는 매서드는 glDrawArrays와 glDrawElements입니다. 이 두 함수의 첫번째 인자는 정점과 인덱스를 통해 구성할 모델의 형태입니다. 다음과 같이 총 7가지 모드가 존재합니다.
1. GL_POINTS : 정점을 개별적인 포인트로 렌더링한다.  2. GL_LINE_STRIP : 정점을 지정된 순서대로 이어 라인을 구성해 렌더링한다. 3. GL_LINE_LOOP : GL_LINE_STRIP와 동일하고 첫번째와 마지막 정점을 잇는다. 4. GL_LINES : 정점 2개씩 연속적으로 묶어 개별적인 선분 하나씩 구성해 렌더링한다. 5. GL_TRIANGLES : 정점 3개씩 연속적으로 묶어 개별적인 삼각형을 구성해 렌더링한다. 6. GL_TRIANGLE_STRIP : 처음은 제공되는 3개의 정점으로 삼각형을 구성하고 다음 정점 하나를 통해 또 다른 삼각형을 구성한다. 구성되는 삼각형들은 모두 동일한 면 방향을 갖도록 구성하게 된다. 7. GL_TRIANGLE_FAN : GL_TRIANGLES_STRIP와 비슷하지만 처음 제공되는 정점을 중심으로 팬(Fan) 형태로 삼각형을 구성해 렌더링한다. 이제 이러한 기본 지식을 토대로 OpenGL ES를 통해 안드로이드에서 간단한 사각형 폴리곤 모델을 렌더링 해보는 코드를 작성해 보겠습니다. 기반이 되는 코드는 이전 글의 초기화에서 작성했던 프로젝트를 기반으로 합니다. 변경될 부분은 MyRenderer 클래스와 Square라는 새로운 클래스 추가입니다. 먼저 Square이라는 새로운 클래스를 추가합니다.
이 클래스는 앞에서 언급했던 사각형 폴리곤 모델에 대한 정점과 정점 인덱스 정보를 담고 있으며 렌더링하는 코드가 존재합니다. 구성할 사각형 폴리곤의 정점 좌표와 인덱스 정보는 다음과 같습니다.
즉.. 총 4개의 정점으로 존재하며 총 2개의 삼각형 면으로 구성되어 있습니다. 2개의 삼각형면을 구성하기 위해 사용할 정점에 대한 인덱스가 필요할텐데.. 이에 대한 정보를 클래스에 코드로 추가합니다.
vertices가 정점에 대한 정보를 담고 있으며 indices가 삼각형 면을 구성할 정점에 대한 인덱스 정보를 담고 있습니다. 이제 Square의 생성자에서 이 정보를 OpenGL ES에서 사용할 수 있도록 Buffer로 저장하는 코드를 작성합니다.
자바의 NIO를 이용해 배열을 ByteBuffer에 담아 정점에 대한 버퍼는 FloatBuffer 타입의 vertexBuffer로 정점 인덱스에 대한 버퍼는 ShortBuffer 타입의 indexBuffer에 담아 놓습니다. 이제 3D 모델에 대한 정의는 끝났고.. 이 모델을 렌더링해주는 코드를 Square에 추가해 보면 다음과 같습니다.
먼저 2번 코드는 앞면은 정점 지정 순서가 반시계 방향으로 지정한 것이고 3번 코드와 4번 코드를 통해 뒷면은 렌더링되지 않도록 합니다. 6번 코드는 정점 배열을 통해 모델을 렌더링하겠다고 지정한 코드이며 7번 코드는 모델의 정점 배열을 지정해 주는 코드입니다. 8번은 실제로 렌더링 시키라는 코드로 이 함수에 정점 인덱스 배열이 인자로 들어갑니다. 9번 코드는 정점 배열과 정점 인덱스 배열의 지정이 끝났음을 알립니다. 이제 이렇게 만들어진 Square 클래스를 사용하는 일이 남았습니다.
MyRenderer 클래스에 Square 클래스에 대한 필드 변수를 추가하고 onSurfaceCreated 매서드에서 생성합니다.
onSurfaceCreated 매서드를 보면 Square 변수를 생성하는 코드 이외에도 OpenGL ES의 다양한 값들을 지정해 주는 코드가 존재합니다. 다음으로 MyRenderer 클래스의 onDrawFrame 매서드에서 square를 그리는 코드를 작성합니다.
화면상에 사각형 모델이 보이도록 5번 코드에서 Z축으로 -10만큼 이동하였습니다. 이에 앞서 투영 행렬과 모델뷰 행렬을 지정해 줘야 하는데.. 이 코드는 MyRenderer의 onSurfaceChanged 매서드에서 실행됩니다.
이제 실행해 보면 다음과 같은 결과를 얻을 수 있습니다.
|
김형준(Dip2K)
2011/08/02 18:47
2011/08/02 18:47
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/731 |
|
|
|
|
|
|
|
안드로이는 2D Drawing API가 상당히 뛰어납니다. 일반 PC에서 제공하는 API 수준.. 그 이상인데요. 안드로이에서 제공하는 2D Drawing API 중에서 텍스트에 외곽선 효과를 주는 코드에 대해 간단히 소개해 드리겠습니다. 결과를 먼저 보여드리면 다음과 같습니다.
위의 시스템은 지오서비스에서 현재 개발중인 지적도 현장 검색 시스템으로.. 항공사진과 지적도를 표현하고 있습니다. 지적도의 특성상 라벨로.. 지번을 텍스트로 표현해야 합니다. 텍스트를 그냥 표현하게 되면 지도와 텍스트가 섞여 라벨이 눈에 잘 들어오지 않게 됩니다. 해서.. 라벨에 외곽선을 그려주게 되면 라벨의 가독성이 향상됩니다. 위의 그림에서처럼 글자는 하얀색으로 하고 외곽선은 검정색으로 하는 코드는 다음과 같습니다.
위의 코드에서 보시는 것처럼.. 하얀색의 글자와 외곽선의 검정색에 대한 Paint 객체를 2개 만듭니다. 즉 글자 자체의 하얀색에 대한 textPaint와 검정색 외곽선에 대한 strokePaint 변수가 바로 그 것입니다. 이렇게 만들어진 Paint 객체를 다음의 텍스트 그리기 함수에서 사용합니다.
텍스트 그리기 한번 그리고 외곽선 그리기 한번.. 이렇게 총 2번을 그려서 텍스트의 외곽선을 표현해 줄 수 있습니다. 외곽선의 굵기를 원하는 만큼 지정할 수 있는데요. 방법은 strokePaint의 setStrokeWidth 매서드에 원하는 굵기만큼 값을 주면 쉽게 원하는 바를 얻을 수 있습니다.
|
김형준(Dip2K)
2011/07/30 21:34
2011/07/30 21:34
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/732 |
|
|
|
|
|
|
|
| 안드로이드에서 3차원 그래픽을 위한 API는 OpenGL ES입니다. 꽤 오래전부터 3차원 그래픽 API인 OpenGL에 대해 관심이 많은 저로써는 모바일에서 3D API인 OpenGL ES에 대해서도 관심이 많았습니다. 해서 모바일 OS 중의 하나이면서.. 모바일 OS 중에서 가장 관심이 많은 안드로이드에서 3D API인 OpenGL ES에 대한 글을 체계적으로 남겨 보려고 합니다. 그중 가장 먼저 초기화입니다.
이 글의 대상은 안드로이드에 대한 기본적인 내용(Activity, View의 개념)에 대해 알고 있는 개발자 분입니다. 이클립스에서 새로운 안드로이드 프로젝트를 생성할 수 있으며 애뮬레이터이든.. 가지고 계시는 디바이스에서든.. 실행해 그 결과를 살펴보실수 있는 분에 한합니다. 아울러 OpenGL ES가 토대로 하고 있는 OpenGL API를 알고 있다면 매우 쉽게 이 글을 이해하실 수 있을 것입니다. OpenGL ES를 보시기 전에 먼저 OpenGL을 선행 학습하시면 이글을 훨씬 쉽게 이해할 수 있습니다.
먼저 Android Project를 생성합니다. 나타나는 대화상자에서 입력해야할 곳에 아래 그림을 참조해 입력하시기 바랍니다.
위와 같이 입력한 뒤에 Finish 버튼을 클릭하면 OpenGLES_Tutorial1Activity 라는 클래스가 생성됩니다. 여기서 다음과 같이 필드 변수 하나와 onCreate 매서드의 코드를 수정합니다.
MyView라는 View 파생 클래스를 하나 생성할 것인데.. 생성했다고 가정하고 일단 필드로써 정의해 onCreate에서 생성하고 setContentView로 지정했습니다. 여기까지는 안드로이드에서 일반적인 프로젝트를 생성하고 코딩하는 내용입니다. OpenGL ES의 내용은 아직 언급되지 않았구요. 이제 MyView 클래스 작성에서부터 OpenGL ES가 시작됩니다. MyView라는 새로운 클래스를 생성합니다.
상속받을 Superclass는 android.opengl 패키지의 GLSurfaceView라는 점이 중요합니다. 이 클래스는 View라는 클래스를 상속받는 클래스로 다음과 같은 책임을 가지는 클래스입니다.- OpenGL ES와 View 시스템을 연결
- 서페이스에 OpenGL이 렌더링 될 수 있도록 EGLS Display를 관리함
- Activity의 라이프 사이클과 함께 OpenGL ES가 작동하도록 함
- 적당한 프레임버퍼의 픽셀 포맷 선택을 쉽게 해줌
- 렌더링에 대한 별도의 스레드를 만들어 줌
- OpenGL ES API 호출과 에러에 대한 검사를 위한 디버깅 도구 지원
MyView 클래스에 하나의 필드 변수를 추가하고 생성자를 다음과 같이 코딩합니다.
MyRenderer라는 앞으로 추가할 또 다른 새로운 클래스에 대한 내부 필드를 선언했고 생성자에서 이 필드를 생성한 후 setRenderer로 렌더러로써 지정했습니다. 새롭게 추가할 MyRenderer라는 클래스를 생성합니다.
구현할 Interface를 지정해야 하는데.. android.opengl.GLServiceView 클래스의 Inner Interface인 Renderer 인터페이스를 추가합니다. Finish를 클릭합니다. 이 Renderer 인터페이스에서 구현해 줘야 하는 매서드는 총 3가지입니다.- onSufaceCreated - 초기화 코드 부분으로 렌더링 될때 변경되지 않는 것에 대한 설정 코드가 실행되면 적합하다. 화면을 지울 배경 색이나 z-buffer에 대한 활성화 여부 등등
- onSurfaceChanged - 화면이 가로로 회전될때 등과 같이 화면의 크기가 변경될때 이와 관련된 코드가 실행되면 적합하다. 예를 들어서 Viewport의 크기 지정이라든지 카메라의 재설정 코드 등등
- onDrawFrame - 프레임을 그리는 코드가 오면 적합하다.
구현해야할 매서드에 대해 내용을 파악했으니.. 이제 MyRenderer에 대한 코드를 작성해 보겠습니다. 색상에 대한 RGB값을 위해 3개의 float 변수를 추가하고 앞의 3개의 메서드를 구현해 보면 다음과 같습니다.
일단.. 이해를 쉽게 하기 위해 단순히 화면을 red, green, blue 필드값으로 지정된 색상으로 지우는 것이 그리는 것의 전부입니다. 즉 onDrawFrame에서는 배경을 Clear할 색상을 지정하기 위해 glClearColor 매서드를 사용했고 실제 지우는 함수는 glClear 입니다. 그리고 onSurfaceChanged에서는 뷰포트의 크기를 지정하는 glViewport를 호출하고 있습니다. onSurfaceCreated에서는 특별하 무엇가를 그리는 것이 없기 때문에 별다른 코드는 존재하지 않습니다. 하지만 무언가 3D 오브젝트를 그릴때 이 부분에 코드가 필요할 것입니다. 실행해 보면 다음과 같은 결과가 나타나게 됩니다.
여기에 잠시 응용을 해보겠습니다.. 사용자가 화면에 손을 대고 스크롤하면 색상이 스크롤한 내용에 따라 변경되게 말입니다. 색상에 대한 값이 MyRenderer에 정의되어 있고.. 사용자의 스크롤에 대한 이벤트는 MyView에서 발생하니.. MyRenderer의 색상값을 변경할 수 있는 매서드를 MyRenderer에 추가해해 줘야 합니다.
이제 MyView에 터치 이벤트를 작성합니다.
네.. 화면에 손을 터치하면 터치된 좌표값을 통해 색상값을 재설정합니다. OpenGL에서 색상값은 0~1.0까지이므로 이 값의 범위에 맞춰주고 있습니다. 실행해서 손을 터치하거나 스크롤해보면 색상값이 그에 따라 변하는 것을 살펴볼 수 있습니다.
|
김형준(Dip2K)
2011/07/27 14:58
2011/07/27 14:58
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/730 |
|
|
|
|
|
|
|
안드로이드는 보안상의 이유로 모바일 디바이스의 내장 메모리를 통한 파일을 여러개의 어플리케이션에서 공유하는 것이 여러모로 불편하게 되어 있습니다. 하지만 외장 메모리인 SD 카드의 경우는 이러한 제약이 존재하지 않습니다. 이 글은 안드로이드에서 SD 카드에 파일을 생성하는 것에 대한 정리입니다.
먼저 안드로이드에 SD 카드의 사용 가능 여부를 판단하기 위한 코드는 아래와 같습니다.
showMsg는 안드로이드의 Toast 기능을 좀더 쉽게 사용하기 위한 사용자 정의 매서드로써 아래와 같습니다.
Toast는 디바이스 화면에 일정 시간 동안 메세지를 띠워주는 기능입니다. 다시 본론으로 돌아가서.. 정적 클래스인 Environment의 getExternalStorageState 매서드의 반환값이 Environment.MEDIA_MOUNTED 인 경우가 SD 카드를 사용할 수 있다는 의미이고 사용 가능하다면 SD 카드가 마운트된 디렉토리 명을 얻기 위해 다시 Environment의 getExternalStorageDirectory 매서드를 사용합니다. 이렇게 얻은 디렉토리에는 보안상의 제약 없이 자유롭게 파일을 읽고 쓸 수 있습니다. 여기서는 파일을 쓰는 코드에 대해 살펴보겠습니다.
안드로이드는 자바 언어를 통해 플랫폼의 API를 사용할 수 있습니다. 이런 맥락으로 SD 카드에 파일을 생성하고 읽고, 쓰기는 자바의 API를 그대로 사용할 수 있습니다.
끝으로 SD 카드를 사용하기 위해서는 매니페스트 파일에 다음과 같은 설정값을 추가해줘야 합니다.
이 설정값이 없다고 해도 SD 카드를 사용할 수 있다고 나오지만 실제로 파일을 쓰거나 읽을 수 없으니.. 반드시 이 설정값을 추가하기 바랍니다.
|
김형준(Dip2K)
2010/09/07 16:13
2010/09/07 16:13
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/625 |
|
|
|
|
|
|
|
| Adapter는 데이터 테이블을 목록 형태로 보여주기 위해 사용되는 것으로 데이터를 다양한 형식의 리스트 형식으로 보여주기 위해서 데이터와 리스트 뷰 사이에 존재하는 객체입니다. 즉, 간단히 말해 데이터와 리스트 뷰 사이의 통신을 위한 다리 역활을 합니다.
안드로이드를 살펴보면서.. 데이터를 사용자 정의 리스트뷰 형식으로 표현하는데 있어서 매우 유연한 방식을 제공한다는 것을 알게 되었고... 이런 유연함을 위해 다소 복잡한 구조에 익숙해져 볼 생각으로 이 글을 작성하게 되었습니다.
안드로이드를 처음 접하시는 분들에게 상당히 불친절한 내용이라고 생각됩니다. 제 개인적으로는 정리 차원의 글이라는 점을 다시금 언급해 드립니다.
먼저 아래와 같은 결과를 목표로 해서 사용자 정의 Adapter 만들기에 대한 핵심 내용을 정리해 보겠습니다.
인물에 대한 사진과 이름 그리고 생일 정보를 리스트 형식으로 보여주고 있는 화면입니다. 위의 화면에 대한 레이아웃은 다음과 같습니다.
즉.. Activity의 View Content가 profilelistview.xml에 해당되며 리스트뷰를 채우는 각 항목은 profileview.xml로 정의된다는 내용입니다. 먼저 큰 레이아웃인 profilelistview.xml에 대한 코드는 다음과 같습니다.
단순히 레이아웃 안에 list라는 id의 ListView 위젯만을 가지고 있습니다. 그리고 다음 코드는 이 ListView 위젯 안에 담을 항목에 대한 뷰에 해당하는 profileview.xml입니다.
위의 코드를 도식화 하면 아래와 같습니다.
수평 정렬로 지정된 레이아웃 안에 ImageView 위젯과 TextView 위젯 2개를 가지고 있는 수직 정렬로 지정된 레이아웃에 대한 내용입니다. 이제 이렇게 UI가 정해졌으니 코드에 대해서 정리해 보겠습니다.
먼저 리스트 뷰를 채울 데이터를 나타낼 클래스인 Profile에 대한 코드입니다.
사진에 대한 리소스 ID값과 이름 그리고 전화번호에 대한 값을 저장하고 얻기 위한 단순한 클래스입니다.
다음으로 뷰를 화면에 표시하기 위한 Activity 클래스를 상속받은 ProfileList 클래스 입니다.
2번 코드의 _profiles는 데이터 목록을 담고 있는 컨테이너입니다. 이 컨테이너에 데이터를 추가하는 코드가 8~22번입니다. 이 컨테이너의 데이터가 바로 리스트 뷰에 표시될 정보입니다. 이 데이터와 리스트 뷰를 연결해주기 위한 것이 바로... 24번 코드, 즉.. 이 글의 주제인 사용자 정의 Adapter인 ProfileListAdapter 입니다. 이 사용자 정의 Adapter 클래스는 BaseAdapter를 상속받습니다. 코드는 아래와 같습니다.
중요한 부분만 언급하면... Override해야할 매서드는 모두 4개로써 getCount, getItem, getItemId, getView입니다. 그리고 리스트 뷰의 항목에 대한 뷰를 생성하는 getView는 처음 호출될때 두번째 인자인 convertView가 null이며 이후 개발자가 직접 인스턴스를 생성해주면 이후 호출될때는 처음 호출될때 생성된 인스턴스가 전달되는 구조로써 인스턴스의 생성에 대한 부담을 최소화하기 위한 방안입니다.
이미 안드로이드의 사용자 정의 Adapter 만들기에 대한 내용은 여타의 다양한 개발 플랫폼에서도 사용되고 있는 구조이지만... 안드로이드를 통해 다시금 접해 봄으로써.. 이러한 구조에 익숙해져서 자신이 개발하고 있는 소프트웨어에 그 설계 구조 자체를 적용해 볼 수 있는 발전으로까지 이어가길 스스로에게 다짐해 봅니다.
|
김형준(Dip2K)
2010/09/01 19:13
2010/09/01 19:13
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/624 |
|
|
|
|
|
|
|
| 처음 Windows 운영체제에서 개발언어를 익혔을때 가장 매력적인 기능이 바로 타이머(Timer) 였습니다. 개발자가 지정한 시간 간격으로 자동으로 알아서 어떤 로직을 호출해서 실행시켜 주는 것이 마치... 컴퓨터에게 일을 맡겨 놓고 나는 신경끄고 놀수있다라는 가능성이 매력적이였나 봅니다.
그러나..... 실제 지금까지 개발 현장에서 단한번도 이 타이머를 사용해 본적은 없습니다. 이유는.. 정확도가 떨어지기 때문입니다. 그러니깐... 예를 들어 1초 간격으로 실행해라고 지정해 놓지만.. 정확히 1초 마다가 아니라 경우에 따라 큰 오차가 발생하기 때문입니다..
여하튼... 이런 저런 사정을 떠나... 안드로이드에도 타이머 기능이 존재하는데.. 이 타이머 기능에 대해 정리를 해 보았습니다. 매우 정확한 시간으로 어떤 일을 반복적으로 수행해야할 경우에는 사용하기에는 부적합하지만... 그래도 어떤 일을 주기적으로 반복해서 수행해야할 경우에 매우 요긴하게 사용할 수 있는.. 매우 손쉬운 기능이 바로 이 타이머이기 때문입니다..
정리하는 수준으로 글을 전개해 나갈 것이며 타이머에 대한 예제 코드가 매우 단순하기 때문에 바로 코드 나갑니다!
10번 코드가 바로 타이머를 위한 클래스로 CountDownTimer입니다. 18번 코드에서 생성하고 있는데... 다른 여느 타이머와는 다르게 반복될 시간 간격뿐만 아니라 작동될 시간까지도 지정합니다. 즉, 생성자에게 2개의 인자를 받는데 첫번째가 작동될 시간이며 두번째가 시간 간격입니다. 위의 경우 첫번째 인자값이 10*1000이므로 10초동안 수행되며, 두번째 인자가 1000이므로 1초 간격으로 수행됩니다. 19번 코드와 23번 코드에 나타난 onTick과 onFinish는 각각 타이머 수행 코드에 대핸 매서드와 타이머가 지정된 시간(여기서는 10초)이 되었을때 발생되는 매서드입니다.
이렇게 만든 타이머의 start 매서드와 cancel 매서드를 통해 시작시키거나 작동을 중지시킬 수 있습니다. cancel 매서드의 경우 여타 다른 환경의 타이머와 다르게 취소만 될뿐.. 중지하여 중지된 시점으로부터 재개할 수는 없습니다. 또한 확인해 본바로는 cancel 매서드를 onTick 매서드 안에서 호출할 경우 의도와 다르게 타이머가 중지하지 않습니다..
이해를 돕고자 위의 코드를 실행했을 경우 애뮬레이터에서 나타나는 UI는 아래 그림과 같습니다.

모바일에서 타이머의 기능을 어디에 활용할 수 있을까... 한번 생각을 해보면... 일정한 시간 간격으로 자신의 위치를 얻어오거나... 일정한 시간 간격으로 메일서버로부터 메일을 확인한다거나... 오히려 일반 데스크탑 환경에서보다 모바일에서 타이머의 기능은 매우 중요할듯합니다..
아뿔싸~ 레이아웃 리소스가 빠졌군요~! 실습을 하시는 분이라면 timerlayout.xml이라는 파일로해서 저장해주시면 됩니다.
|
김형준(Dip2K)
2010/08/26 10:57
2010/08/26 10:57
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/623 |
|
|
|
|
|
|
|
| 수년전에 오렐리라는 출판사에서 나온 자바의 2D API를 보면서... 이 API를 이용해 2D GIS 엔진을 자바로 만들면 정말 환상이겠구나... 라는 생각을 했던 적이 있었습니다. 그런데.. 안드로이드를 살펴보면서 또 다시 이런 생각이 다시 듭니다.. 안드로이드가 내세우는 주요 개발 언어가 자바라는 점과 이러한 생각은 우연이 일치이겠지만 말입니다. 또 다시 이러한 생각을 들게 만드는 안드로이드의 기능은 아래와 같은 기능 때문입니다. 즉, Path을 따라 사용자가 표현하고자 하는 텍스트를 자연스럽게 회전시켜주는 기능입니다.
참으로.. 아름답습니다! 그럼 어떻게 이렇게 하는지 안드로이드 맛보기 겸해서 코드를 잠시 살펴보도록 하겠습니다. 물론 안드로이드를 잘 아시는 분들은 걍.. 살짝 패스해주셔도 됩니다!
먼저 간단히 View를 하나 만듭니다. View 클래스는 안드로이드에서 위젯(UI 컨트롤)을 나타내는데 유용한 부모클래스입니다..
즉, 문자열이 표시될 방향을 결정할 Path 객체를 만들어주고.. Canvas의 drawTextOnPath 매서드를 통해 원하는 문자열을 표시해주기만 하는.. 매우 효율적인 API를 제공합니다. 이제 이 View를 실제로 사용하는 Activity를 정의합니다.
안드로이드에서 Activity는 실제로 화면에 표시되지는 않지만 화면을 구성하는 가장 핵심이 되는 단위로.. View를 컨트롤하여 화면에 개발자가 원하는 컨텐츠를 표시할 수 있습니다. 안드로이드의 2D 그래픽스.... 많은 모바일 API를 경험해 보지는 않았으나... 정말 이 정도로 뛰어난 2D 그래픽 API를 제공하는 모바일 개발 플랫폼이 있을까... 싶습니다..
|
김형준(Dip2K)
2010/08/24 12:21
2010/08/24 12:21
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/621 |
|
|
|
|
|
|
|
| 선언 태그에 대한 코드화... 이 문장이 의미하는 바는.. 예를 들어 .NET의 WPF에서 XAML로 작성된 선언적 태그들을 각 태그에 대한 C#등의 클래스로 코드화(정확히는 인스턴스화)라든지... 플렉스의 MXML로 작성된 선언적 태그들을.. 역시 각 태그에 대한 액션스크립트 클래스의 코드화를 해주는 것을 말합니다. 마찬가지로 안드로이드 역시 XML로 작성된 태그들을 각 태그에 해당되는 자바 클래스로 코드화 해주는 것이 존재합니다.. .NET이나 플렉스는 이런 전개(Inflation) 기능을 언어 차원에서 꽁꽁 숨겨두고 있지만.. 안드로이드는 개발자가 접근할 수 있도록 열어 놓았습니다. 아.. 여기서 혹시 .NET이나 플렉스 역시 열어 놓았다면 제게 알려주시기 바랍니다!
이 전개(Inflation) 기능을 안드로이드가 열어 놓은 이유는 무엇일까... 궁금했는데.. 그것은 바로 태그 하나 하나에 대한 부분적인 코드화를 위한 효율적인 방법을 제공하기 위함입니다. 예를 들어 다음과 같은 안드로이드 레이아웃 리소스에 해당되는 xml 코드가 있다고 칩시다..
딱.. 정확히.. 유일하게 Button에 대한 태그 정보만을 가지고 있습니다. 이를 안드로이드의 Button 클래스에 대해 인스턴스화를 하기 위해 개발자가 직접 전개(Inflation) 시키기 위해 전개를 위한 안드로이드 프레임웍에서 제공하는 전개 관리자를 얻어야 합니다. 방법은 3가지나 되는데.. 하나 하나 살펴보면 다음과 같습니다..
또는..
여기서 context_obj는 Activity와 같은 Context의 파생 클래스입니다. 그리고 마지막 방법은.. View 클래스의 inflate 정적 매서드를 통해 레이아웃 리소스의 ID를 인자로 받아 바로 전개시킬 수가 있습니다.
자.. 이제 전개를 수행해주는 클래스를 얻을 수 있으니.. 앞서 <Button>만을 가지고 있는 XML 데이터에 대해서 전개시키는 코드는..
위의 onCreate 매서드는 Activity의 매서드이며 전개 관리자를 얻는 방법중 앞서 세번째 방법을 사용했습니다. View.inflate의 두번째 인자가 바로 <Button>만을 가지고 있는 XML에 대한 리소스 ID입니다.
개발자에게 있어서.. 자신이 사용하는 개발툴이 개발자에게 무언가를 오픈하지 않고.. 내부적으로만 사용하고 있다는 것은.. 물론.. 안정성을 위해 어쩔 수 없는 것일 수도 있습니다. 하지만 이러한 안정성면을 떠나.. 개발자에게 최대한 접근할 수 있도록 오픈되었다는 것은 개발자에게 큰 매력이 아닐 수 없습니다..
|
김형준(Dip2K)
2010/08/21 17:48
2010/08/21 17:48
|
|
| Track this back : http://www.gisdeveloper.co.kr/trackback/620 |
|
|
|
|
Total : 982094
Today : 116
Yesterday : 582 |
|
|
|