구경모 kookyungmo@gmail.com 본수업교재에는안드로이드프로그래밍정복 ( 김상형 / 한빛미디어 ) 의내용이일부포함되어있습니다. Google 이제작 / 공개한 Open Source 모바일운영체제 개발주체는 OHA(Open Handset Alliance) 컨소시엄이나실질적인리더는구글 (Google) 임 Linux Kernel 기반비독점개방플랫폼 라이선스비용이없음 ( 개발툴, 관련문서모두무료제공 ) 개발이자유로움 개발툴의문제발생시기술지원을받을수없음 JAVA 를이용하여프로그래밍가능 JAVA, XML 관련지식필요
2005 년 7 월, 개발시작 안드로이드사를구글에서인수 2007 년 11 월, 안드로이드첫버전릴리즈 휴대용장치운영체제로서무료공개한다고발표 2008 년 10 월, 최초의상용안드로이드폰출시 (HTC 사의 G1) 2013 년 3 월 4 일현재 버전 발표시기 API LEVEL 주요특징및추가된기능 점유율 1.0 2008년 9월 23일 1 첫버전, HTC Dream에탑재 - 1.1 2009년 2월 9일 2 마켓지원, 뷰의패딩개선, 새로운권한추가. - 1.5(Cupcake) 2009년 4월 30일 3 AVD 지원, 홈스크린위젯, 비디오레코딩, 음성인식 - 1.6(Donut) 2009년 9월 15일 4 다양한밀도지원, TTS, 제스처 0.1% 2.0(Éclair) 2009년 10월 26일 5 Exchange 지원, 다중계정, Email 통합, 블루투스 1.9% 2.2(Froyo) 2010년 5월 20일 8 성능향상, 외부저장장치에앱설치, 플래시지원 7.6% 2.3(Gingerbread) 2010년 12월 6일 9 인터넷전화, 근거리무선통신 44.1% 3.0(Honeycomb) 2011년 2월 22일 11 태블릿전용, Motorola Xoom에탑재, Google TV 지원 (3.2) 1.2% 4.0(Ice Cream Sandwich) 2011년 10월 19일 14 2.3.x 기기들과 이론적으로호환 28.6% 4.1(Jelly Bean) 2012년 6월 27일 16 UI 기능 / 성능적향상 (triple buffering등지원 ) 이돋보임 14.9% 4.2(Jelly Bean) 2012년 10월 29일 17 LG Nexus 4 및 Samsung Nexus 10에탑재 1.6% 4.3?(Key Lime Pie) 2013년 2/4분기? http://en.wikipedia.org/wiki/android_version_history
현재까지도가장많이사용되고있는버전 주요추가기능 인터넷기반의전화프로토콜이기본탑재 근거리무선통신 (NFC : Near Field Communication) 지원 다운로드관리자시스템서비스공개 장비에장착된모든카메라사용가능 UI 향상및버튼의보안향상등 Android 2.3.3 on Google Nexus S 최신버전 (2013 년 2 월 11 일공개 ) 주요추가기능 Photo Sphere 파노라마사진 제스처인식이용키보드입력 잠금해제화면에서카메라바로사용가능 전원관리기능강화 멀티유저사용가능 ( 태블릿 only) 세번터치를통한줌, 두손가락을이용한이동및줌기능 그룹메시지기능 블루투스게임패드및조이스틱지원 블루투스오디오스트리밍버그수정 다운로드알림기능개선 갤러리앱애니메이션및로딩속도개선 Android 4.2 on Google Nexus 4
인스턴스화할수있는 4 가지컴포넌트로구성 액티비티 (Activity) 서비스 (Service) 방송수신자 (Broadcast Receiver) 콘텐트제공자 (Content Provider) 응용프로그램은이들중일부만을가질수도있고여러개를가질수도있음 사용자인터페이스를구성하는기본단위 눈에보이는화면하나가 Activity 이며여러개의뷰들로구성 응용프로그램은필요한만큼의 Activity 를가질수있으며그중어떤것을먼저보여줄지지정가능
UI 가없어사용자눈에직접적으로보이지않음 백그라운드에서무한히실행되는컴포넌트 전형적인예로미디어플레이어를들수있는데비활성화된상태라도노래는계속재생되어야함 UI 가없으므로사용자의명령을받아들일수있는 Activity 와연결해서사용됨 시스템으로부터전달되는방송을대기 / 수신 예를들어배터리가떨어졌다거나사진을찍었다거나네트워크전송이완료되었다는등의신호를받음 신호만대기할뿐 UI 를따로가지지는않으므로방송수신시방송의의미를해석하고적절한 Activity 를띄우는역할
다른응용프로그램을위해자신의데이터를제공 Android 는보안이엄격하여다른응용프로그램의데이터를함부로액세스하지못함 응용프로그램간에데이터를공유할수있는유일하게합법적인장치 선수과목 JAVA XML 레이아웃배치와리소스정의, 응용프로그램설정구성등에 XML 문서를광범위하게사용 Eclipse 꼭테스트할기기가필요하지는않음 단, 풍부한모바일사용경험필요
안드로이드개발환경의특징 Google 에의해개발된통합개발환경이아니므로사용할버전이나운영체제에따라약간씩달라지는부분이있고사소한버그도있어충분한주의가필요 안드로이드개발관련프로그램설치순서 JDK(Java SE 7u17) ( http://www.oracle.com/technetwork/java/javase/downloads/index.html ) Android SDK 32-bit ( http://developer.android.com ) Eclipse 3.6.2 이상 ( http://eclipse.org/downloads/ ) ADT Plug-in ( eclipse 설정내에서 https://dl-ssl.google.com/android/eclipse/ ) Android Platform-tools 사용빈도수가많은플랫폼 (API 10) 및최신플랫폼 (API 16) 다운로드 AVD 생성및옵션조정 문서 docs 폴더에는안드로이드개발관련문서들이제공 HTML 포맷이므로웹브라우저를통해읽을수있음 샘플 platforms 폴더안에샘플프로젝트제공 각버전별로디렉토리가구성되어있으며버전이높을수록예제의개수도늘어남 개발툴 tools 폴더에컴파일러, 디버거, 에뮬레이터등개발에꼭필요한프로그램들제공
안드로이드폰에뮬레이터 AVD 는소프트웨어적으로만든가상의장비이지만진짜 Android 폰과기능이동일함 History 1.1 버전까지는에뮬레이터가기본제공되어간편하기는했지만다양한테스트를하기에는여러가지문제가있었음 1.5 버전부터는 AVD 를필요한만큼만들어두고번갈아가면서사용할수있도록바뀜 기본에뮬레이터가없어최소한한대이상의 AVD 를직접생성해야함 <AVD 의생성 > < 실제해상도와맞춤가능 > < 이름및해상도, Target Platform 을지정 >
워크스페이스의문자셋을 UTF-8 로변경 Preference-General-Workspace-Text file encoding-[other UTF-8] 주석맞춤법검사기능해제 Preference-General-Editors-TextEditors-Spelling-Enable spell checking 옵션해제 import 문자동정리기능사용 Preference-Java-Code Style-Organize Imports 의 Number of imports needed for * 옵션의값을 1 로변경 필요없는코드는무시하도록설정 Preference-Java-Compiler-Errors/Warnings-Unnecessary code 의모든옵션 Ignore 로변경 ADB connection time out(ms) 의값을재설정 프로젝트의골격생성안드로이드프로젝트로생성
Application Name 실행시보여지는앱자체의이름 Play Store, 응용프로그램관리화면에서사용되는이름 Project Name 프로젝트이름으로만사용됨 프로젝트를저장하는폴더명으로사용됨 Package Name 생성하는클래스가저장될이름 Play Store 에서앱을식별하는식별자로사용 ( 유일한이름 ) 예 ) kr.ac.cup.testprogram < 새프로젝트의생성 > 기타 Minimum Required SDK 응용프로그램이지원하는최소한의 SDK 버전 Target SDK 등 < 아이콘및액티비티생성여부확인 > < 아이콘생성마법사 ( 다해상도아이콘자동생성 )>
< 액티비티종류선택 > < 액티비티파일생성 > Activity Name : 소스코드가저장될 JAVA 파일의파일명 MainActivity.java 가됨 Layout Name : 화면디자인이저장될 XML 파일의파일명 activity_main.xml이됨 소문자, 밑줄, 숫자만사용가능하며이후소스코드에서이파일명을이용하여호출됨 새로운프로젝트를만들면자동으로생성되는폴더와파일 src MainActivity.java 메인소스파일 응용프로그램동작기술 gen R.java 프로젝트내의각종개체에접근할수있는 ID 정의 ( 자동완성 / 수정불가 ) assets 폴더 텍스트, 비디오, 오디오, database 등의파일저장 res drawable 이미지파일저장 ( 해상도별로제작 ) res layout activity_main.xml 개체들의레이아웃및응용프로그램의모양정의 res values strings.xml 문자열정의 AndroidManifest.xml 프로젝트의버전, 이름, 구성등에대한정보
실행설정 마법사가만들어준프로젝트는안드로이드가요구하는기본코드와리소스를모두포함하고있으므로그자체로이미실행가능 메뉴의 Run Run ( Ctrl + F11 ) 실행 Android Application 선택 에뮬레이터구동후자동실행 에뮬레이터를기동하는데시간이오래걸리므로프로그램개발시종료하지않고사용하는것이좋으며, 프로그램을수정한후재실행을하면이미실행되어있는에뮬레이터에수정된프로그램이다시설치되어실행된다. < 프로그램실행화면 > Manifest 응용프로그램의구성정보및속성을관리 어플리케이션을실행하는어플리케이션을위한정보 권한, 기본연동요소 ( 사용하는기능 ) 등정보포함 프로젝트에상관없이 AndroidManifest.xml 으로이름불변 하단의마지막탭 (AndroidManifest.xml) 클릭후텍스트기반편집가능
Layout GUI 디자인뷰에서마우스로레이아웃편집및확인가능 보통프로그램안에서직접기술하지않고 XML 로기술하여작성 Relative Layout Linear Layout 가장흔하게사용되는레이아웃 차일드를수평또는수직으로나란히배열하는컨테이너 Values strings.xml 파일 응용프로그램의구성정보중문자열정의 / 관리 R.java 코드및 XML 파일에서참조하는리소스 ID 정의 개발툴이자동으로생성 / 관리하므로개발자가임의로편집해서는안되며그럴필요도없다. Visual C++ 의 resource.h 에해당
strings.xml : hello_world 문자열정의 main.xml : 정의된문자열을 Relative Layout의 Text View에넣는다 MyFirstAndroidApp.java : setcontentview 메서드호출, 레이아웃을액티비티에배치 R.java : 각파일들이참조하는객체의 ID 정의 AndroidFirst.java 액티비티생성 R.layout.activity_main 레이아웃배치 main.xml LinearLayout TextView @string/hello_world R.java strings.xml activity_main, hello 등의명칭정의 hello_world = Hello World! MyFirstAndroidApp.java 수정 XML 레이아웃과코드레이아웃모두사용가능 TextView 객체를생성및초기화한후 setcontentview 매서드로전달
XML 레이아웃의장점 코드와데이터가완벽하게분리되어개발자와디자이너의분담작업이용이 조건에따라레이아웃을통째로교체할수있으므로호환성확보, 국제화에유리 레이아웃만수정할때는컴파일하지않아도되므로개발속도빠름 구조와속성을함축적으로기술하며레이아웃재활용도가능 실제프로젝트에서는코드레이아웃과 XML 레이아웃모두사용하며, 두방법을동시에적용하는것도가능 디자인타임에결정되는정적레이아웃은주로 XML 을사용하고실행중에결정해야하는동적레이아웃은코드를사용하는것이보편적 에러처리 Eclipse는소스가편집될때마다주기적으로백그라운드컴파일을수행하고, 구문의타당성을점검하여그결과를편집창에표시 에러발생시편집기왼쪽에 ⅹ표시가나타나며, mouse over시에러에대한상세설명표시
새프로젝트생성시마법사이용 프로젝트별로디렉토리를구성하고관련파일들을계층적으로생성 새프로젝트는항상현재열려진워크스페이스에소속패키지탐색기는워크스페이스에포함된모든프로젝트의구성파일을나타냄특정프로젝트실행시패키지탐색기팝업메뉴 Run 명령실행프로젝트를닫는별도의명령은필요하지않음 프로젝트삭제시패키지탐색기를통해야한다. Delete 항목에서체크박스선택시프로젝트구성파일전체삭제 ( 체크하지않으면프로젝트목록에서만삭제됨 ) Export 이클립스에서워크스페이스간의프로젝트이동관리기능 대상프로젝트의팝업메뉴 Export 명령선택 Archive File : 프로젝트를압축파일로생성 File System : 프로젝트폴더의사본생성 Import 백업된파일복원기능 팝업메뉴 Import 명령선택 압축파일선택후압축을해제할폴더지정시압축해제및패키지탐색기에등록됨
New Android Project 생성시, Android Sample Project 를선택하면 SDK 버전별로제공되는예제소스를새로운프로젝트로생성하여사용가능 LunarLander 를선택 주어진연료를활용하여우주선을달에안전하게착륙시키는게임 LunarLander Snake JetBoy
SDK에도도움말문서가포함되어있지만 SDK 발표시점의자료일뿐이므로가급적이면웹에서최신자료를보는것이좋으며, 구글에서지원하는개발자를위한사이트를주로참조한다. Api Guide : 안드로이드의주요구조에대한개론을설명해놓은일종의자습서 Reference : 안드로이드의시스템클래스에대한레퍼런스제공 패키지목록 패키지에포함된클래스목록 뷰 android.view 화면에뭔가를그리는데관련된인터페이스들과클래스 화면의직사각형의영역을나타냄 위젯 android.widget ImageView, FrameLayout, EditText, Button 등의컨트롤 레이아웃 다른위젯 ( 또는레이아웃 ) 을담는컨테이너역할 view 의일종이지만화면에아무것도그리지않음
모든연구 / 개발은기존연구를분석하는것이중요 안드로이드구성요소및인터페이스사용방법을익히는데도움
아이디어정리 어플리케이션개요 메뉴구조도 Story Board 상용앱의아이디어정리 타로홀릭 (Tarot Holic) MMI * 실제 T-Store 납품시제작된내용임 암산왕의설계및구현 서비스명 타로홀릭 (TarotHolic) Channel T-Store / Android Market Platform Android 출시국가 Korea 서비스설명 모험과사랑, 직업, 여행, 그리고인생의앞날등사용자가궁금해하는모든질문에훌륭한멘토가되어줄타로점어플리케이션 Screen Shot (Run mate) 4컷삽입 Main 타로스프레드방법선택타로 78장이미지와의미설정 ( 페이스북연동등 ) 기대효과 앱의구매를통해더이상 ' 애기동자 ' 나 ' 장미선녀 ' 님에게복채를낭비할필요가없고 주머니에타로카드대신넣고다니며실제인생고민을비롯많은질문에대한해답을바로얻을수있다.
0 Depth 1 Depth 2 Depth 3 Depth Intro Main Sub Menu Contents 1. Home 2. Fortune information 메뉴 -APP소개및동작방법설명 질문입력 사용자중심 (3종) 카드배열 심층적해석 (6종) 카드배열 타로홀릭 타로카드소개 타로홀릭사용방법 JK APP으로메일보내기 카드선택방법선택 -직접선택방법 - 수정구투영 ( 속성 ) 방법 Loading 화면 ( 제작자로고출력 ) 3. History 기존에저장된타로점목록 목록클릭하여내용확인 Major 22장 / Sword 14장 / Cup 14장 / 4. Browse 5종 78장의타로카드리스트 Pentacle 14장 / Wand 14장 각카드의이미지및해석수록 메인화면 ( APP 이름출력 ) 5. Setting 일반설정 -역방향카드사용여부 - 스프레드정보 -버전정보 히스토리기록삭제기능 네트워크 ( 페이스북연동 ) Description 0. Intro 1. Main 화면 0 1 1-1. Information 1-2. Fortune : 타로점을보는메뉴 1-3. History : 기존에저장된타로점목록 1-4. Browse : 타로카드리스트 1-5. Setting : APP 설정값변경 1 2 3 4 5
1 1 Description 1-1. Information : About Tarot-holic 1-1-1. 타로카드소개 1-1-2. 타로홀릭사용방법 1-1-3. 개발자에게메일보내기 1 2 3 Description 1-1-2. 타로홀릭사용방법 2 1-1-3. 개발자에게메일보내기 3
Description 2 1-2. Fortune : 사용자중심 (3 종 ) 배열, 또는심층적해석 (6 종 ) 배열중한가지방법을선택한후카드선택방법을결정 1-2-1. 직접카드선택 1-2-2. 수정구투영 ( 속성 ) 1 2 Description 1-2-1. 직접카드선택 : 78장의카드중직접선택 1 2 3 1-2-2. 수정구투영 ( 속성 ) : 수정구를눌러카드랜덤선택 1-2-3. 선택된카드정보출력
3 1 Description 1-3. History : 기존에저장된타로점목록 1-3-1. 저장된타로점결과출력 구상중 구상중 Description 1-4. Browse : 타로카드리스트 4 1 1-4-1. 선택된타로카드정보출력
Description 1-5. Setting : APP 설정값변경 5 1-5-1. 타로카드를역방향으로도섞을지선택 1-5-2. 스프레드정보표시여부설정 1 2 1-5-3. 히스토리의모든기록삭제기능 1-5-4. 페이스북연동기능 3 4 개요 MMI(Man-Machine Interface) 세부기능 부가기능
개요 화면에출력되는숫자를모두더하는두뇌게임 향후뺄셈, 곱셈등다양한형태로응용이가능 MMI
세부기능 부가기능 초기화면에서메인화면전환시앱정보출력 copyright 정보출력 화면전환이부드럽게되도록함 메인화면에광고출력 무료어플리케이션의수입원
새안드로이드프로젝트생성 Project Name : amsanwang Activity Name : amsanwang 암산왕 화면구성 View 의속성값들을이용 textsize layout_width layout_height gravity
사용자를대면하는실체 여러개의뷰가모여하나의액티비티를구성하고, 이러한액티비티가모여하나의응용프로그램이됨 레이아웃은액티비티안에뷰를배치하는기법을뜻함 뷰 위젯 : 직접적으로보이며사용자인터페이스를구성. 흔히컨트롤이라고부름 뷰그룹 : 뷰를담는컨테이너역할을하며, 이부류의클래스들을레이아웃이라함 * 뷰그룹이면서도위젯처럼사용되는클래스도있으며, 특정위젯을상세히알고싶으면그슈퍼클래스들부터연구해야함 Object AnalogClock EditText AutoCompleteTextView View TextView Button CompoundButton Chronometer CheckBox DigitalClock RadioButton ImageView ImageButton ToggleButton SurfaceView GLSurfaceView VideoView SeekBar ProgressBar AbsSeekBar RatingBar * 단축키 Ctrl+T 를이용하여각객체의계층보기가가능
id 뷰를칭하는이름을정의하며, 코드나 XML 문서에서뷰를참조할때 id를사용하므로직관적인이름을붙이는것이좋다. 형식 : @[+]id/id @ : id를리소스 (R.java) 에정의하거나참조한다는뜻. 필수! + : ID를새로정의한다는뜻. 참조시생략가능 id : 예약어 / : 뒤에원하는이름을작성하되, ID는고유한명칭이므로명령규칙에맞아야하며, 뷰끼리중복되어서는안됨 ex) android:id= @+id/name : 텍스트뷰에 name이라는 id를부여 XML 문서에 ID를지정하면이이름이 R.java에정수형상수로정의 코드에서뷰를참조할시 findviewbyid 메서드호출, 인수로참조할뷰의 id를전달함 모든뷰에 id를의무적으로지정할필요는없으며, 코드에서참조할필요없는위젯은보통 id를생략 layout_width, layout_height 뷰의폭과높이를지정. 수평 / 수직각방향모두크기지정가능 속성값으로아래의세가지중하나의값을가짐 fill_parent : 부모의주어진크기를다채움 wrap_content : 내용물의크기만큼만채움 정수크기 : 지정한크기에맞춤 ex) Start 라는캡션을가지는버튼배치 지정한크기가액면대로다받아들여지지않으며, 주위다른위젯들의크기에영향을받음 명시적인크기지정시정수와단위를함께사용하며, 이단위는크기를지정하는모든속성에공통적으로적용 * 단위 : px, in, mm, pt, dp ( 또는 dip), sp ( 또는 sip)
background 뷰의배경을지정하며, 색상및이미지등의여러가지객체로지정가능 색상지정시네가지형식이적용되며, 배경뿐만아니라색상을지정하는모든속성에적용 #RGB #ARGB #RRGGBB #AARRGGBB ex) #ff0000 (#f00): 빨간색, #0000ff : 파란색 padding 뷰와내용물간의간격을지정 ( 즉안쪽여백 ) padding 속성값을지정하여 4 방향에대한여백조절가능 속성값 : paddingleft, paddingtop, paddingright, paddingbottom visibility 뷰의표시유무를지정하며, 속성값으로아래의세가지중하나의값을가짐 visible : 보이는상태임 invisible : 숨겨진상태이되자리는차지함 gone : 숨겨지며자리도차지하지않음 gravity 내용물의위치를지정하며, 수평, 수직방향에대해각각정렬방식을지정가능 두속성을같이지정할때는 연산자를이용하며, 이때연산자양쪽으로공백이전혀없어야함 각정렬방식은비트필드로정의, center, fill 은수평, 수직정렬상태플래그의조합으로정의
액티비티추가 Activity Name : mainmenu 버튼추가 @+id/btnstart @+id/btnhighscore 게임시작 최고기록 액티비티전환 * 첫화면에추가 인텐트 타이머의사용 Handler handle = new Handler(); handle.postdelayed(new Runnable() { @Override public void run() { Intent intent = new Intent(amsanwang.this, mainmenu.class); startactivity(intent); finish();, 3000); 안드로이드응용프로그램을구성하는 4가지컴포넌트중하나로가장빈번히사용사용자를대면한다는면에서실질적으로가장중요한요소화면하나에대응되며입출력기능이없어내부에뷰나뷰그룹을가짐 setcontentview 메서드 액티비티가생성될때마다호출되며, 액티비티안에뷰를배치하는명령액티비티하나는독립된기능을수행하며, 서로중첩되지않음액티비티추가시 *.java와 *.xml파일각각생성보안상의이유로응용프로그램에포함된모든액티비티는반드시매니페스트에등록후사용 ( 매니페스트에등록되지않은액티비티는존재하지않는것으로취급 )
안드로이드의컴포넌트끼리통신하기위한메시지시스템메인액티비티혼자작업을수행하면반복이심해지고형식성도떨어지므로다른액티비티를호출하여일을분담 ( 메서드가다른메서드를호출하여작업을분담하는이유와동일 ) 액티비티및컴포넌트간수행할작업에대한정보및작업결과리턴을위해서사용명시적인텐트액티비티호출메서드 void startactivity (Intent intent) - 인수 : 인텐트안에호출대상및작업내용정보가들어있으며메서드호출전에먼저인턴트객체에설정 인텐트생성자 암시적인텐트 Intent (String action [,uri uri] Intent (Context packagecontext, Class<?> cls) Intent (String action, Uri uri, Context packagecontext, Class<?> cls) - Intent (Context packagecontext, Class<?> cls) : 내부의서브액티비티호출시사용되는생성자. 액티비티클래스구현을위한컨텍스트, 호출할액티비티클래스정보가인수로전달된다. Timer, TimerTask 를사용하는방법 CountDownTimer 를사용하는방법 Handler 를사용하는방법 TimerTask task = new TimerTask() { public void run() { Log.d( run task, run() ); ; Timer timer = new Timer(); timer.schedule( task, 5000, 3000 ); new CountDownTimer(100, 100) { @Override public void ontick(long millisuntilfinished) { // TODO Auto-generated method stub ; @Override public void onfinish() { Log.d("count down", "onfinish()"); Handler mhandler = new Handler(); mhandler.postdelayed(new Runnable() { @Override public void run() { Log.d("handler", "run()");, 3000);
액티비티추가 Activity Name : game Activity Name : highscore 버튼동작설정 setonclicklistener() 액티비티전환 Button btn1 = (Button)findViewById(R.id.btnStart); btn1.setonclicklistener( new View.OnClickListener() { @Override public void onclick(view v) { Intent intent = new Intent( mainmenu.this, game.class ); startactivity(intent); ); 정답 / 오답버튼배치 레이아웃이용 SCORE : 5 LEVEL : 3 문제출제영역배치 텍스트뷰세부설정 5
LinearLayout 차일드뷰를수평, 수직으로일렬배치하는레이아웃으로, 가장단순하면서직관적이며사용빈도가높음 orientation 뷰의배치방향을결정하는속성 ( 디폴트는 horizontal) vertical : 차일드를위에서아래로수직으로배열 horizontal : 차일드를왼쪽에서오른쪽으로수평배열 gravity 내용물의위치를지정하며, 수평, 수직방향에대해각각정렬방식을지정 두속성을같이지정할때는 연산자를이용하며, 이때연산자양쪽으로공백이전혀없어야함 baselinealigned 높이가다른차일드뷰를수평으로정렬시하단정렬지정 ( 디폴트 true) layout_weight 중요도에따라차일드의크기를균등분할 중요도가 0이면자신의고유한크기만큼, 1 이상이면형제뷰와의비율에따라부모의영역을균등하게배분 padding, margin 여백과관련된속성 padding 뷰와내용물간의간격지정 뷰의입장에서볼때안쪽여백을뜻하며뷰자체의속성 4면모두동일한여백이지정되며, paddingleft, paddingtop, paddingright, paddingbottom 으로4면의개별여백지정가능 margin 뷰와부모와의간격을지정하며, 근처에형제뷰가있으면동일한간격으로여백생성 뷰의입장에서볼때바깥여백을뜻하며레이아웃의속성
RelativeLayout 위젯과부모와의위치관계또는위젯끼리의관계를지정 위젯끼리의관계지정을위하여기준이되는위젯에 id 를반드시지정 리소스컴파일러는빠른배치를위해위젯간의관계를한번에 (one pass) 읽으며, 특정뷰가다른뷰의위치에종속적일때기준이되는뷰를먼저정의해야함 ex: A 를 B 의위에배치하고싶다면 XML 문서상에 B 를먼저기술한후 A 를나중에기술 A B <RelativeLayout> <B android:id= @+id/b /> <A layout_above= @id/b /> </RelativeLayout> [ 원하는배치 ] [ XML 문서 ] RelativeLayout 의예 좌상단의이미지를제일먼저배치, 그아래삭제버튼을배치 부모의위쪽변에이름을붙이면서동시에이미지의오른쪽에배치 부모의오른쪽에전화번호를붙이되이름과베이스를맞추어정렬 설명문자열은이름밑에붙이되왼쪽변을이름과나란히맞춤 [ 정상적인결과 ] [ 베이스를맞추지않은결과 ]
FrameLayout 차일드를배치하는규칙없이모든차일드는프레임의좌상단에표시 차일드가두개이상일때는추가된순서대로겹쳐서표시 ViewGroup의서브클래스로 addview, removeview 등의메서드로실행중에차일드를추가, 삭제할수있으며, getchildcount 메서드로차일드의개수조사가능 필요한차일드만표시하고겹쳐진차일드는숨겨둘수있음 차일드의보임상태는개별뷰의 visibility 속성을사용하여조정하며실행중에도조건에따라뷰의보임상태변경가능 속성 foreground - 차일드의위쪽에살짝얹히는이미지를지정. 반투명한색상, 이미지사용가능 foregroundgravity - 전경의이미지를배치할방법을지정하며, 디폴트는 fill 임 measureallchildren - 모든차일드의크기를다측정할것인지, 보이거나숨겨진차일드의크기만적용할것인지를지정. 디폴트는 false 여서 GONE 상태의차일드크기는측정하지않음 TableLayout 표형식으로차일드를배치하는레이아웃으로바둑판모양임 테이블은임의개수 TableRow 객체로구성되며, TableRow 안에임의개수열이배치되고, 이를셀이라부르며셀에는차일드뷰가존재 테이블의전체크기는행 (TableRow)* 열 ( 셀 ) 이됨 테이블의차일드들은정해진규칙에따라크기가결정되므로크기속성에대한제약존재 TableRow 객체의높이는항상 wrap_content로강제됨 : 여러개의행이한테이블에공존해야하기때문 layout_width 속성은따로지정할수없으며항상 fill_parent로가정 : 셀에배치되는자식뷰는무조건주어진셀안에배치되기때문 [ TableLayout 예제 ] [ TableLayout 예제 ]
text 텍스트뷰의가장중요한속성으로출력할문자열을지정 리터널및리소스로대입 문자열 형식 @[ 패키지 :]type:name 설명 겹따옴표로문자열을싸서바로대입한다. \ 문자가들어가면이스케이프된다. \n 은개행이며 \uxxxxx 는유니코드문자이다. 리소스에대한레퍼런스로지정한다. 보통 string.xml 에문자열을정의해놓고 @string/id 식으로지정한다.?[ 패키지 :][type:]name 테마속성으로지정한다. textcolor 문자열의색상을지정하며, 디폴트는불투명한밝은회색 #RRGGBB 나 #AARRGGBB 형식으로각색상요소들의강도지정 textsize 텍스트의폰트크기를지정하며, 실수타입으로지정할때숫자뒤에 sp, dp, px, in, mm 등의단위를같이지정 textstyle 폰트의속성을지정 normal, bold, italic 중하나를쓰거나 로묶어두개이상의상수값을지정가능 ex: bold italic, normal italic typeface 글꼴의모양을지정하며, normal, sans, serif, monospace 중하나로선택가능 모바일환경에서내장된폰트개수에제약이있음
width, height 텍스트뷰의폭과높이이며크기값과단위를같이지정 텍스트뷰는단독으로존재하는경우는거의없고대부분레이아웃안에서차일드로존재하기때문에이두속성은거의사용되지않음 singleline 텍스트가위젯의폭보다길때강제로한줄에출력 속성의디폴트는 false 로폭보다더긴줄은자동으로아래쪽으로개행 game.xml (1/2) <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal"> <ProgressBar android:id="@+id/progressbar1" style="?android:attr/progressbarstylehorizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:text="score : 5" android:layout_width="fill_parent" android:id="@+id/textscore" android:layout_height="wrap_content" android:gravity="right" android:textsize="10pt" /> <TextView android:text="level : 3" android:layout_width="fill_parent" android:id="@+id/textlevel" android:layout_height="wrap_content" android:gravity="right" android:textsize="10pt" /> <TextView android:text= 5" android:id="@+id/textquiz" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margintop="40pt" android:layout_marginbottom="20pt" android:textsize="30pt" /> game.xml (2/2) <LinearLayout android:layout_height="40pt" android:layout_width="fill_parent"> <Button android:id="@+id/btn0" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/btn1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_height="40pt" android:layout_width="match_parent"> <Button android:id="@+id/btn2" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/btn3" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> </LinearLayout> </LinearLayout>
Toast 간단한알림메시지를액티비티화면위에출력 public void maketext(context context, CharSequence text, int duration); 게임초기화점수 = 0; 레벨 = 2; 시간 = 60; 퀴즈초기화 정답 = 0; 숫자개수 = 0; 화면삭제 = false; 화면삭제? 숫자삭제및화면삭제 = false; 숫자생성 Random rand = new Random(); int val = rand.nextint(9) + 1; 숫자개수 == 레벨 오답생성 숫자표시 정답 += 숫자숫자개수 ++ 숫자표시및화면삭제 = true; 정답? 점수 ++ 남은시간? 게임종료
전체게임에서사용하는오브젝트 / 변수 퀴즈한문제에서사용하는오브젝트 / 변수 int nlevel; int nscore; int nremain; Handler clock; int nprecount; Handler counter; int nanswer; int ncorrect; int ncount; boolean bdelete; Handler quiz; ProgressBar bar; TextView mytext; Button btn1, btn2, btn3, btn4; 게임초기화 퀴즈초기화 public void initgame() { // init variables nscore = 0; nlevel = 2; nremain = 60; nprecount = 3; bdelete = false; // start timers counter.sendemptymessagedelayed(0, 1000); public void initquiz() { // init variables nanswer = 0; ncorrect = 0; ncount = 0; bdelete = false; btn1.settext(""); btn2.settext(""); btn3.settext(""); btn4.settext(""); btn1.setenabled(false); btn2.setenabled(false); btn3.setenabled(false); btn4.setenabled(false); if( nremain > 0 ) quiz.sendemptymessagedelayed(0, 500);
문제출제 1~9 까지의숫자를무작위로생성 Random.nextInt() 를이용 오답생성 0~3 까지의숫자를무작위로생성 문제에서생성된숫자를뺀숫자부터버튼에출력 ex) 문제가 19 이고생성된숫자가 2 인경우, 오답은 17, 18, 19, 20 네개의숫자가됨. 문제생성 오답생성 Random rand = new Random(); // create quiz final int val = rand.nextint(9) + 1; mytext.settext( String.valueOf(val) ); nanswer += val; ncount++; bdelete = true; if( nremain > 0 ) quiz.sendemptymessagedelayed(0, 500); public void createincorrectanswer() { Random rand = new Random(); int val = rand.nextint(4); final int inc = nanswer - val; ncorrect = val; btn1.settext( String.valueOf( inc + 0 )); btn2.settext( String.valueOf( inc + 1 )); btn3.settext( String.valueOf( inc + 2 )); btn4.settext( String.valueOf( inc + 3 )); btn1.setenabled(true); btn2.setenabled(true); btn3.setenabled(true); btn4.setenabled(true);
AlertDialog 사용 AlertDialog.Builder AlertDialog.Builder alert = new AlertDialog.Builder(AmsanwangActivity.this); alert.seticon(r.drawable.icon); alert.settitle("game OVER"); alert.setmessage(nscore + " 점을획득하였습니다.\n 기록을저장하시겠습니까?"); alert.setpositivebutton alert.setnegativebutton 액티비티간데이터송수신 intent.putextra intent.getintextra("hi-score", 0); 인텐트는액티비티간에인수와리턴값을전달하는도구로도이용 Bundle 타입의 Extras를활용, 이름과값의쌍으로된임의타입의정보를원하는개수만큼전달가능 Extras에값을저장하는메서드 거의모든타입에대해오버로딩되어있다. Intent putextra (String name, int value) Intent putextra (String name, String value) Intent putextra (String name, boolean value) - name : 전달하는인수의이름이며, 임의 ( 중복되지않게 ) 지정가능 Extras 에저장된값은아래의메서드로꺼낸다. int getintextra (String name, int defaultvalue) String getstringextra (String name) Boolean getbooleanextra (String name, boolean defaultvalue) - 값이전달되지않았을경우두번째인수로지정한디폴트가리턴, 문자열은 null 이리턴 - 입력뿐아니라리턴값을돌려줄때사용가능하며, 적당한이름으로값을넣어두면호출원에서약속된이름으로리턴값을꺼내사용
인수와리턴값 : 인텐트를통해전달호출을요청한대상에대한정보가포함리턴값을돌려주는액티비티는아래의메서드로호출 public void startactivityforresult (Intent intent, int requestcode) - 두번째인수 : 호출한대상을나타내는식별자 - 호출되는액티비티별로고유의번호를붙여야하며, 0 이상의중복되지않는정수를넘기며, 음수일경우리턴받지않음 호출된액티비티가종료후아래의메서드가호출된다. protected void onactivityresult (int requestcode, int resultcode, Intent intent) - 리턴값을받으려면메서드를재정의해야한다. - requestcode : 액티비티를호출할때전달한요청코드 - resultcode : 액티비티의실행결과 리스트뷰의사용 Adapter View HIGH SCORE 프레퍼런스의사용 SharedPreferences 클래스 1 XXX 20 2 XXX 10 3 XXX 5 4 XXX 3 5 XXX 2 초기화
리스트뷰 어댑터뷰의대표위젯으로항목들을수직으로펼쳐서보여주며, 스크롤을지원 리스트뷰에표시할데이터원본을준비 - 배열을원본으로할때는아래의생성자로어댑터를초기화 Widget/listtest.xml <?xml version= 1.0 encoding= utf-8 > <LinearLayout xmls:android=http://schemas.android.com/apk/res/androrid android:orientation= vertical android:layout_width= fill_parent android:layout_height= fill_parent > <ListView android:id= @+id/list android:layout_width= fill_parent android:layout_height= fill_parent /> </LinearLayout> Widget/ListTest.java public class ListTest extends Activity { public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.listtest); // 데이터원본준비 ArrayList<String> argeneral = new ArrayList<String>(); argeneral.add( 김유신 ); argeneral.add( 이순신 ); argeneral.add( 강감찬 ); argeneral.add( 을지문덕 ); // 어댑터준비 ArrayAdapter<String> Adapter; Adapter = new ArrayAdapter<String> (this, android.r.layout.simple_list_item_1, argeneral); // 어댑터연결 ListView list = (ListView)findViewById(R.id.list); list.setadapter(adapter); 첫번째인수는현재컨텍스트로액티비티를넘겨줌두번째인수는항목을표시할레이아웃의리소스 ID - 레이아웃안에는텍스트뷰, 이미지뷰, 체크박스, 라디오버튼등을배치 - 안드로이드에서제공하는레이아웃사용가능 - 시스템이목록표시용으로미리정의해놓은것으로 android.r. 뒤에 ID를지정 리소스 ID Simple_list_item_1 Simple_list_item_2 설명 하나의텍스트뷰로구성된레이아웃 두개의텍스트뷰로구성된레이아웃 Simple_list_item_checked 오른쪽에체크표시가나타난다. Simple_list_item_single_choice 오른쪽에라디오버튼이나타난다. Simple_lsit_item_multiple_choice 오른쪽에체크버튼이나타난다. 세번째인수는어댑터로공급될데이터의원본이며, 두가지타입에대해오버로딩되어있음 - 위쪽생성자 : List 인터페이스를지원하는컬렉션객체가원본으로, ArrayList가대표적이며, LinkedList, Stack 등이있음 - 아래쪽생성자 : 단순배열을원본으로한다. 배열은초기화할때크기가결정되므로데이터의추가나삭제가불가능 정적데이터는배열보다 XML 리소스의사용이더유리하므로실제는잘사용하지않음
어댑터객체준비후리스트뷰의메서드를호출하여연결 void setadapter (T adapter) - 어댑터는리스트뷰에출력할데이터원본을가지며, 원본을출력할뷰를생성하여리스트뷰에제공 - 리스트뷰는어댑터가제공한뷰를사용자에게보여줌 - 사용자로부터터치입력을받아항목선택및스크롤처리배열도일종의리소스이며, 문자열배열은 string-array 엘리먼트로작성한다. - name 속성 : 배열리소스의이름지정 - item 엘리먼트 : 배열요소나열 코드에서문자열배열을직접정의하는것은비효율적이며관리에도불리 고정적인문자열은리소스에정의해놓고사용하는것이좋음 [ ListText 예제실행결과 ] arrays.xml <?xml version= 1.0 encoding= utf-8?> <resources> <string-array name= country > <item> 신라 </item> <item> 고구려 </item> <item> 백제 </item> <item> 당나라 </item> <item> 발해 </item> <item> 옥저 </item> <item> 동예 </item> <item> 부여 </item> <item> 대한민국 </item> </string-array> </resources> 리스트뷰에항목을넣거나뺄때는어댑터와연결된원본을편집 원본을편집한후 BaseAdapter의메서드를호출하여참조하고있는원본데이터가변경되었음을알림 어댑터는메서드가호출될때원본을다시읽고변경된원본에맞게뷰를생성하여리스트뷰로재공급리스트뷰의항목을클릭하면 AdapterView.OnItemClickListener 인터페이스의 onitemclick 메서드가호출 항목클릭시점을알고싶다면이리스너를구현한후리스트뷰의 setonitemclicklistener 메서드로등록 onitemclick으로 4개의인수전달 어댑터뷰, 항목뷰, 항목의위치, 항목의고유 ID Widget/ListAddDel.java - 2 Button.OnClickListener mclicklistener = new View.OnClickListener() { public void onclick(view v) { EditText ed = (EditText)findViewById(R.id.newitem); switch(v.getid()) { case R.id.add: String text = ed.gettext().tostring(); if (text.length()!= 0) { Items.add(text); ed.settext( ); Adapter.notifyDataSetChanged(); break; case R.id.delete: int id; id=list.getcheckeditemposition(); if (id!= ListView.INVALID_POSITION) { Items.remove(id); list.clearchoices(); Adapter.notifyDataSetChanged(); break; ; AdapterView.OnItemClickListener mitemclicklistener = new AdapterView.OnItemClickListener() { public void onitemclick(adapterview parent, View view, int position, lond id) { String mes; mes = Select Item = + Items.get(position); Toast.makeText(ListAddDel.this, mes, Toast.LENGTH_SHORT).show(); ;
커스텀뷰를사용하면항목안의배치를원하는대로할수있으며, 커스텀배치를위해서는어댑터를맞춤형으로새롭게만들어야함어댑터는어떤정보를레이아웃의어느위젯에출력할지를지정 Widget/icontext.xml <?xml version= 1.0 encoding= utf-8?> <RelativeLayout xmlns:android=http://schemas.android.com/apk/res/android android:layout_width= fill_parent android:layout_height= 60px android:padding= 5px > <ImageView android:layout_width= wrap_content android:layout_height= wrap_content android:id= @+id/img android:layout_alignparentleft= true /> <TextView android:width= wrap_content android:heigth= wrap_content android:id= @+id/text adnroid:textcolor= #00ff00 android:textsize= 13pt android:layout_torightof= @id/img /> <Button android:layout_width= wrap_content android:layout_height= wrap_contnet android:id= @+id/btn android:layout_alignparentright= true android:text= 주문 /> </RelativeLayout> Widget/ListIconText.java - 1 public class ListIconText extends Activity { ArrayList<MyItem> aritem; public void oncreate(bundle savedinstancestate) { super.oncreate(savedintancestate); setcontentview(r.layout.listtest); aritem = new ArrayList<MyItem>(); MyItem mi; mi = new MyItem(R.drawable.icon, 삼성노트북 ); aritem.add(mi); mi = new MyItem(R.drawable.icon, LG 세탁기 ); aritem.add(mi); mi = new MyItem(R.drawable.icon, 대우마티즈 ); aritem.add(mi); MyListAdapter MyAdapter = new MyListAdapter(this, R.layout.icontext, aritem); ListView MyList; Mylist = (ListView)findViewById(R.id.list); Mylist.setAdapter(MyAdapter); // 리스트뷰에출력할항목 class MyItem { MyItem(int aicon, String aname) { Icon = aicon; Name = aname; int Icon; String Name; MyItem 클래스 : 리스트뷰에출력할항목하나를표현 - Icon 은출력할이미지, Name 는그옆에표시할문자열임 MyListAdapter : 리스트뷰에게이항목의집합을제공하는어댑터클래스 - 생성자에서어댑터구현을위해필요한정보를전달받음 Widget/ListIconText.java - 2 // 어댑터클래스 class MyListAdapter extends BaseAdapter { Context maincon; LayoutInflater Inflater; ArrayList<MyItem> arsrc; int layout; public MyListAdapter(Context context, int alayout, ArrayList<MyItem> aarsrc) { maincon = context; Inflater = (LayoutInflater)context.getSystemService( Context.LAYOUT_INFLATERE_SERVICE); arsrc = aarsrc; layout = alayout; public int getcount() { return arsrc.size(); public String getitem(int position) { return arsrc.get(position).name; public long getitemid(int position) { return position; Widget/ListIconText.java - 3 // 각항목의뷰생성 public view getview(int position, View convertview, ViewGroup parent) final int pos = position; if (convertview == null) { convertview = Inflater.inflate(layout, parent, false); ImageView img = (Imageview)convertView.findViewById(R.id.img); img.setimageresource(arsrc.get(position).icon); TextView txt = (TextView)convertView.findViewById(R.id.text); txt.settext(arsrc.get(position).name); Button btn = (Button)convertView.findViewById(R.id.btn); btn.setonclicklistener(new Button.OnClickListener() { public void onclick(view v) { String str = arsrc.get(pos).name + 를주문합니다. ; Toast.makeText(maincon, str, Toast.LENGTH_SHORT).show(); ); return convertview;
[ ListIconText 예제실행결과 ] [ ListAddDel 예제실행결과 ] 응용프로그램의설정정보를영구적으로저장하는장치로, 사용자옵션선택사항이나프로그램자체의구성정보를주로저장 SharedPreferences 클래스 프레프런스의데이터를관리하는클래스 응용프로그램내의모든액티비티가공유하며, 한쪽액티비티에서수정시다른액티비티에서도수정된값을읽을수있음 응용프로그램의고유한정보이므로외부에서는읽을수없음 컨텍스트의아래메서드로생성한다. SharedPreferences getsharedpreferences (String name, int mode) 첫번째인수 : 프레프런스를저장한 XML 파일의이름 두번째인수 : 파일의공유모드로 0이면읽기쓰기가가능 (MODE_WORLD_READABLE 읽기공유, MODE_WORLD_WRITEABLE 쓰기공유 )
프레프런스는키와값의쌍으로데이터를저장 키는정보의이름이며값은정보의실제값 여러타입의정보를저장할수있으며가장자주사용되는타입은정수, 문자열논리형으로아래의메서드를이용하여읽을수있음 int getint (String key, int defvalue) String getstring (String key, String defvalue) boolean getboolean (String key, boolean defvalue) 읽는데이터타입이다를뿐이며사용방법은동일 key 인수 : 데이터의이름지정 defvalue 인수 : 값이없을때적용할디폴트지정 최초실행될때에는프레프런스가생성되기전이어서디폴트가리턴되므로여기서지정한디폴트가곧프로그램설정의초기값이됨 프레프런스클래스자체에는값을읽는메서드만제공되며값을기록하는메서드는이너클래스인 SharedPreferences.Editor 가제공 값을읽는것에비해변경할때는동기화를해야하며 Editor 는모든변경을모아두었다가한꺼번에적용하는기능을제공 데이터저장시프레프런스의 edit 메서드를호출하여 Editor 객체를먼저얻어야하며, Editor 객체에는값을저장하고관리하는메서드가제공 SharedPreferences.Editor putint(string key, int value) SharedPreferences.Editor putboolean(string key, int value) SharedPreferences.Editor putstring(string key, String value) SharedPreferences.Editor remove(string key) Boolean commit() SharedPreferences.Editor clear() 저장하는데이터타입에따라각각의기록메서드가제공 put* 메서드로값을저장한후에반드시 commit 메서드를호출해야실제파일에저장 만약두개의스레드가동시에프레프런스를편집할시나중에적용한내용만남음
onpause로프레프런스에데이터를저장하며, 액티비티가종료되기전에반드시거침 프레프런스객체얻기 getsharedpreferences 메서드를이용하여, PrefTest 프레프런스를 open 파일명이액티비티명과같을땐아래의방법으로호출가능 SharedPreferences pref = getpreferences(0); Editor 객체얻기 프레프런스에정보를기록하기위해 edit 메서드를이용 사용자가에디트에입력한정보를먼저읽음 문자열타입 : gettext().tostring() 정수타입은문자열을정수로변환하여읽으며, 예외처리필수! 프레프런스로정보출력 이름 (Name) : putstring() 학번 (StNum) : putint() 저장후 commit 메서드호출 Data/PrefTest.java public class PrefTest extends Activity { TextView textname; TextView textstnum; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.preftest); textname = (TextView)findViewById(R.id.name); textstnum = (TextView)findViewById(R.id.stnum); SharedPreferences pref = getsharedpreferences("preftest",0); String Name = pref.getstring("name", " 이름없음 "); textname.settext(name); int StNum = pref.getint("stnum",20101234); textstnum.settext("" + StNum); public void onpause() { super.onpause(); SharedPreferences pref = getsharedpreferences("preftest",0); SharedPreferences.Editor edit = pref.edit(); String Name = textname.gettext().tostring(); int StNum = 0; try { StNum = Integer.parseInt(textStNum.getText().toString()); catch (Exception e) { edit.putstring("name", Name); edit.putint("stnum", StNum); edit.commit(); 메모리가부족하면 onstop, ondestroy 는호출되지않을수도있으므로반드시 onpause에서저장해야한다.