Contents 학습목표 지금까지 배운 내용을 총정리하며 개발 툴에 대한 고급 사용법을 익힌다. 학습내용 개발툴
7.2.1 기억력 게임 - 예제(마지막 나온 도형 클릭하기) 규칙 화면을 벗어나서는 안된다. 도형 좌상단 좌표는 항상 뷰의 영역 안쪽이지만 크기도 난수로 결정하므로 우하단이 뷰를 벗어 날 수 있다. 이경우 좌표를 재선정해야 한다. 기존 도형과 겹쳐서는 안된다. 보기에 좋지 않고 사용자가 화면을 클릭할 때 어떤 도형을 클릭했는지 판별하기 애매한 문제가 있다.
7.2.1 기억력 게임 - 예제(마지막 나온 도형 클릭하기) C07_MemoryPower.java public class C07_MemoryPower extends Activity { GameView gv; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); gv = new GameView(this); setContentView(gv); } //도형 하나에 대한 정보 class Shape { final static int RECT = 0; final static int CIRCLE = 1; final static int TRIANGLE = 2; int what; int color; Rect rt; // 게임 뷰 : 실질적인 메인이다. class GameView extends View { // 그리기 모드. 빈화면 또는 도형 출력 final static int BLANK = 0; final static int PLAY = 1; // 게임 진행 속도 final static int DELAY = 1500; // 현재 그리기 모드 int status; // 생성된 도형의 목록 ArrayList<Shape> arShape = new ArrayList<Shape>(); Random Rnd = new Random(); Activity mParent; C07_MemoryPower.java public GameView(Context context) { super(context); mParent = (Activity)context; // 빈 화면으로 시작하고 잠시 후에 게임 시작 status = BLANK; mHandler.sendEmptyMessageDelayed(0,DELAY); } public void onDraw(Canvas canvas) { // 검정색 배경으로 지운다. 빈 화면이면 지우기만 하고 리턴 canvas.drawColor(Color.BLACK); if (status == BLANK) { return; // 도형 목록을 순회하면서 도형 정보대로 출력한다. int idx; for (idx = 0; idx < arShape.size(); idx ++) { Paint Pnt = new Paint(); Pnt.setAntiAlias(true); Pnt.setColor(arShape.get(idx).color); Rect rt = arShape.get(idx).rt; switch (arShape.get(idx).what) { case Shape.RECT: canvas.drawRect(rt, Pnt); break; case Shape.CIRCLE: canvas.drawCircle(rt.left + rt.width()/2, rt.top + rt.height()/2, rt.width()/2, Pnt); break; case Shape.TRIANGLE: Path path = new Path(); path.moveTo(rt.left + rt.width()/2, rt.top);p ath.lineTo(rt.left, rt.bottom); path.lineTo(rt.right, rt.bottom); canvas.drawPath(path, Pnt); break;
7.2.1 기억력 게임 - 예제(마지막 나온 도형 클릭하기) C07_MemoryPower.java public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { int sel; sel = FindShapeIdx((int)event.getX(), (int)event.getY()); // 빈 바닥을 찍었으면 무시한다. if (sel == -1) { return true; } // 마지막 추가된 도형을 제대로 찍었으면 다음 단계로 진행. // 빈 화면 잠시 보여준 후 새 도형 추가 if (sel == arShape.size()-1) { status = BLANK; invalidate(); mHandler.sendEmptyMessageDelayed(0,DELAY); // 엉뚱한 도형을 찍었으면 질문 후 게임 종료 또는 재시작 } else { new AlertDialog.Builder(getContext()) .setMessage("재미있지! 또 할래?").setTitle("게임 끝") .setPositiveButton("함더", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { arShape.clear(); }}) .setNegativeButton("안해", new DialogInterface.OnClickListener() { mParent.finish(); }}).show(); return false; C07_MemoryPower.java // 새로운 도형을 목록에 추가한다. void AddNewShape() { Shape shape = new Shape(); int idx; boolean bFindIntersect; Rect rt = new Rect(); // 기존 도형과 겹치지 않는 새 위치를 찾는다. for (;;) { // 크기는 32, 48, 64 중 하나 선택 int Size = 32 + 16 * Rnd.nextInt(3); // 위치는 난수로 선택 rt.left = Rnd.nextInt(getWidth()); rt.top = Rnd.nextInt(getHeight()); rt.right = rt.left + Size; rt.bottom = rt.top + Size; // 화면을 벗어나면 안된다. if (rt.right > getWidth() || rt.bottom > getHeight()) { continue; } // 기존 도형 순회하며 겹치는지 조사한다. bFindIntersect = false; for (idx = 0; idx < arShape.size(); idx ++) { if (rt.intersect(arShape.get(idx).rt) == true) { bFindIntersect = true; // 겹치지 않을 때 확정한다. 겹치면 계속 새 위치 선정한다. if (bFindIntersect == false) { break; // 새 도형 정보 작성. 모양, 색상 등을 난수 선택한다. shape.what = Rnd.nextInt(3);
7.2.1 기억력 게임 - 예제(마지막 나온 도형 클릭하기) C07_MemoryPower.java switch (Rnd.nextInt(5)) { case 0: shape.color = Color.WHITE; break; case 1: shape.color = Color.RED; case 2: shape.color = Color.GREEN; case 3: shape.color = Color.BLUE; case 4: shape.color = Color.YELLOW; } shape.rt = rt; arShape.add(shape); // x, y 위치의 도형 번호를 찾는다. 도형이 없는 위치면 -1 리턴 int FindShapeIdx(int x, int y) { int idx; for (idx = 0; idx < arShape.size(); idx ++) { if (arShape.get(idx).rt.contains(x, y)) { return idx; return -1; C07_MemoryPower.java // 새 도형을 추가하고 화면을 다시 그린다. 딜레이를 주기 위해 핸들러를 사용했다. Handler mHandler = new Handler() { public void handleMessage(Message msg) { AddNewShape(); status = PLAY; invalidate(); String title; title = "MemoryPower - " + arShape.size() + " 단계"; mParent.setTitle(title); }};}}
7.2.2 디버깅 - 방법 디버깅 하기 위해서는 매니페스트에 다음 플래그를 지정한다. <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> 매니페스트에 debuggable 속성을 켜야 사용할 수 있다. 왼쪽 거터 영역을 더블클릭하거나 Ctrl + Shift + B를 누르면 중단점이 설정되며, 다시한번 설정하면 중단점이 토글된다. 중단점을 설정하고 F11(Run/Debug)을 눌러 디버깅을 시작한다. 디버깅을 위해 Debug 퍼스펙티브로 전환하겠다는 것을 알리는 메시지(퍼스펙티브 : 뷰의 집합)
7.2.2 디버깅 - 방법 Debug 퍼스펙티브로 전환 메시지에서 [Yes]를 클릭하면 개발에 필요한 뷰에서 디버깅에 필요한 뷰들의 집합으로 재배치된다.
7.2.2 디버깅 - 방법 Debug 단축키 모음 단축키 설 명 F5 메서드 안으로 추적해 들어간다. F6 다음 명령문을 실행한다. F7 메서드의 끝까지 실행하고 리턴한다. F8 다음 중단점까지 실행한다. Ctrl + R 커서가 있는 지점까지 실행한다. Ctrl + F2 디버깅을 중단한다. F6키를 눌러 indShapeIdx 메서드 호출문까지 실행 후 F5를 눌러 메서드 안쪽까지 추적해 들어가보면 다음 그림과 같다.
7.2.3 DDMS DDMS 안드로이드 장치나 애뮬레이터의 내부작동 및 상태를 모니터링 에뮬레이터에서 통화/SMS/위치정보 등을 가상으로 설정하여 개발 시에 특정한 상황을 설정할수 있는 장치 디버깅 툴
7.2.3 DDMS
7.2.3 DDMS DDMS Debug Proccess 버튼 Update Heap 버튼 Dump HPROF file 버튼 디버그 하려는 프로세스를 선태갛고 버튼을 클릭하면 해당 프로세스를 디버깅 DDMS Update Heap 버튼 해당 프로세스의 Heap Memory 정보를 확인할 수 있도록 설정 동적 메모리 할당을 의미 특정 프로세스 목록에서 위의 버튼을 클릭하면 Heap탭에 힙 메모리 사용에 대한 통계수치봄 Dump HPROF file 버튼 힙 덤프 정보 파일을 추출 sdk의 tools 아래에 sdkhprof-conv.exe를 통해 표준 HPROF파일로 변환뒤에, jhat이나 eclipse Memory Anallzer Too(MAT)등의 힙 덤프 분석툴로 상세한 메모리 상태를 Cause GC 버튼 해당프로세스에게 가비지 콜랙션을 요청하고, 가비지 콜랙션 되지 않는 메모리를 개략적으로 알 수 있음 Update Threads 버튼 프로세스 내의 현재 스래드 활동정보를 갱신하여 보여줌 프로세스를 선택하고 버튼을 클릭하면 현재 프로세스가 사용하고 있는 스레드 정보를 Threads탭에서 확인 Start Method Profiling 버튼 프로세스의 특정 시간 동안에 활동한 메소드 점유정보를 기록/분석 녹음기로 음성을 녹음하듯이 실행중인 프로세스의 리정 시간 동안 사용한 메소드의 점유 정보를 reporting Stop Process 버튼 종료하고자 하는 프로세스를 선택하고 버튼을 클릭하면 선택된 프로세스를 강제로 종료할 수 있음 Screen Capture 선택된 장치의 현재화면을 캡쳐 매뉴얼 작업이나 프로그램 스크린샷 할 때 사용
7.2.4 Logcat LogCat이란? 안드로이드의 로그를 확인하는 기능으로, 안드로이드 단말의 로그는 Log.v(), Log.d(), Log.i(), Log.w(), Log.e()로 출력되고, 이를 통해 에러가 발생한 위치의 로그를 찾아 오류를 수정할 수 있음
7.2.4 Logcat 로그를 출력할 때는 다음과 같은 메서드를 사용한다. static int Log.d (String tag, String msg [, Throwable tr]) static int Log.e(String tag, String msg [, Throwable tr]) static int Log.w(String tag, String msg [, Throwable tr]) static int Log.i(String tag, String msg [, Throwable tr]) static int Log.v(String tag, String msg [, Throwable tr])
7.2.4 Logcat - 예제 xmlns:tools="http://schemas.android.com/tools" Input/LogTest.java public class LogTest extends Activity { private static final String TAG = "LogTest"; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.logtest); Log.v(TAG,"onCreate"); findViewById(R.id.btn1).setOnClickListener(mClickListener); findViewById(R.id.btn2).setOnClickListener(mClickListener); } public void onDestroy() { super.onDestroy(); Log.v(TAG,"onDestroy"); Button.OnClickListener mClickListener = new Button.OnClickListener() { public void onClick(View v) { MediaPlayer player; switch (v.getId()) { case R.id.btn1: Log.v(TAG,"First Button Pressed"); break; case R.id.btn2: Log.v(TAG,"Second Button Pressed"); }; Input/LogTest.java <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" tools:context=".LogTest" > <Button android:id="@+id/btn1" android:layout_height="wrap_content" android:text="Button" /> android:id="@+id/btn2" android:layout_below="@+id/btn1" </LinearLayout>
7.2.4 Logcat - 예제
7.2.5 adb adb adb(Android Debug Bridge) : 명령 행에서 장비의 상태를 관리하는 툴이다. adb기능이 대부분이 DDMS에서도 사용이 가능하므로 자주 사용하지 않는다. adb는 다음 3가지 요소가 협력적으로 동작하여 개발 컴퓨터와 장비간 통신 수행한다. 클라이언트 : 개발 컴퓨터에서 실행되는 관리 툴, adb자체가 대표적이며 이 외에 ADT플러그인이나 DDMS도 클라이언트로 동작 서버 : 개발 컴퓨터에서 백그라운드로 실행되며 클라이언트와 데몬을 중계하는 역할을 한다. 데몬 : 장비에서 백그라운드로 동작하며 클라이언트로부터 전달된 명령을 장비에서 수행한다. 연결 장비가 여러 개이면 어떤 장비에 대해 명령을 수행할 것인지를 지정해야 하는데 이때는 다음 세 개의 플래그 중 하나를 사용한다. 플래그 설 명 -d 실장비에 대해 명령을 수행한다. 실장비가 두 개 이상 연결되어 있으면 에러 처리된다. -e 에뮬레이터에 대해 명령을 수행한다. 에뮬레이터가 두 개 이상 연결되어 있으면 에러 처리된다. -s 일련번호 명령을 수행할 장비의 일련번호를 지정한다. 해당 일련번호의 장비가 존재하지 않으면 에러 처리된다.