ch03애플리케이션과 액티비티 만들기

*이번 장에서는 애플리케이션의 수명 주기와 안드로이드 런타임이 이 수명 주기를 관리하는 방식에 대해 좀더 배운다


- 안드로이드 애플리케이션 구성요소

*액티비티 : 뷰를 사용해 정보를 보여주고 사용자 액션에 반응하는 그래픽 사용자 인터페이스를 형성한다.

*서비스 : 화면에 보이지 않은 채 실행되어,데이터 소스와 화면에 보이는 액티비티들을 업데이트하고 알림을 생성한다.

*콘텐츠 공급자 : 애플리케이션 데이터베이스를 관리하고 공유하는 데 사용된다.

*인텐트 : 간단한 메시지 전달 프레임워크다.메시지를 방송하고 의도를 전달할 수 있다.

*브로드캐스트 수신자 : 수신되는 인텐트에 반응해 자동으로 여러분의 애플리케이션을 시작시킬 것이다.

*알림 : 사용자의 현재 액티비티가 가진 포커스를 빼앗거나 방해함 없이 사용자에게 신호 할 수 있도록 해준다.


-애플리케이션 매니페스트 소개

*매니페스트는 애플리케이션과 애플리케이션이 가진 컴포넌트의 구조 및 메타데이터를 정의하도록 해준다.

* applicatin : 애플리케이션 노드는 속성을 사용해 애플리케이션을 위한 메타데이터(타이틀,아이콘,테마 등)을 지정한다

* activity : activity 태그는android:name 속성으로 클래스 이름을 지정한다.

* service

* provider : 콘텐츠 공급자에 대해 사용된다.

* receiver : receiver 태그를 추가하면 애플리케이션을 띄우지 않고서도 브로드 캐스트 수신자를 등록할 수 있다.

* uses - permission : 애플리케이션이 올바로 동작하는 데 필요하다고 생각되는 권한을 선언한다.

* permission : 권한 정의를 생성하는데 사용된다.

* instrumentation : 액티비티와 서비스를 테스트하기 위한 프레임워크를 제공한다.


- 매니페스트 에디터 사용하기

* Application Attributes (애플리케이션 속성) 패널에서는 아이콘, 레이블, 테마 등을 포함한 애플리케이션의 속성을 지정할 수 있다.


-안드로이드 애플리케이션 수명 주기

*애플리케이션 컴포넌트는 반드시 애플리케이션 상태에 생기는 변화에 귀 기울여 그에 따라 적절히 반응해야 하며, 불시 종료에 대비하도록 특히 신경 써야 한다.

*각 애플리케이션의 메모리와 프로세스 관리는 런타임에 의해 배타적으로 처리된다.


-애플리케이션 우선순위와 프로세스 상태 이해하기

*자원 회수를 위해 종료되는 프로세스의 순서는 주인 애플리케이션의 우선순위에 따라 결정된다.

* 1.활성 프로세스(중요한 우선순위) > 2.화면에 보이는 프로세스 3. 시작된 서비스 프로세스(높은 우선순위) > 4. 백그라운드 프로세스 5. 빈 프로세스(낮은 우선순위)

*활성 프로세스 : 사용자가 현재 상호작용하고 있는 컴포넌트를 가진 주인 애플리케이션이다.

*화면에 보이는 프로세스 : 눈에 보이긴 하지만 포그라운드에 있지 않거나 사용자 이벤트에 반응하지 않는다.

*시작된 서비스 프로세스 : 화면에 보이는 인터페이스 없이 계속 돼야 하는 지속적인 처리를 지원한다.

*백 그라운드 프로세스

*빈 프로세스


-리소스 외부화 하기

 *이미지와 문자열 상수 같은 비 코드 리소스를 코드 외부에 유지하는 것은 항상 좋은 습관이다.

 *기본 레이아웃, 애플리케이션 아이콘,문자열 리소스 정의를 담고 있는 values, drawable, layout 리소스를 위한 하위 폴더를 res폴더 안에 생성할 것이다.

 *지원되는 간단한 값에는 문자열, 색상,치수, 그리고 문자열 배열이나 정수 배열 등이 있다.

 *문자열 : string 태그로 지정된다.

 *색상 : color 태그를 정의한다.

 *치수(dimen) :  테두리와 글꼴 높이 같은 레이아웃 상수를 생성하는 데 유용하다.

 *스타일 : 뷰에 의해 사용되는 속성 값을 지정함으로써 애플리케이션이 일관된 룩앤필을 유지하도록 해준다. 스타일은 style태그의 parent속성을 통해 상속을 지원한다.

 *드로이블(drawable) : 비트맵과 나인패치(늘어날 수 있는 PNG) 이미지가 해당된다.

 *레이아웃: 코드에서 레이아웃을 분리하는 것은 다양한 화면,크기, 방향 또는 키보드 및 터치 스크린의 존재유무와 같이 서로 다른 하드웨어 구성을 위해 최적화된 레이아웃을 만들 수 있게끔 해준다.

 *애니메이션 : 트윈드 애니메이션(alpha, scale, translate, rotate, set태그:duration, startOffset, fillBefore, fillAfter, Interpolator), 프레임 바이 프레임 애니메이션

 *코드에서 리소스 사용하기 : 코드에서는 static클래스 R을 사용해 리소스를 접근한다. 기본 새 프로젝트는 R.stringR.drawable 하위클래스를 포함한다.

 *리소스에서 다른 리소스 참조하기 : @표기법을 사용한다, @[packagename:] resourcetype/resourceidentifier

 *시스템 리소스 사용하기 : android.R을 통해 사용가능한 네이티브 안드로이드 리소스 클래스를 사용한다.

 *현재 테마에서 스타일 참조하기 : ?android: 를 사용한다

 *여러 가지 언어와 하드웨어를 위한 리소스 만들기

 *런타임 구성 변경 : 런타임 구성 변경을 감지하는 액티비티를 가지려면, 매니페시트 노드에 android:configChanges 속성을 추가한 뒤 구성 변경을 지정(orientation, keyboardHidden, fontScale, locale, keyboard, touchscreen or navigagion)


 -안드로이드 액티비티 좀더 자세히 살펴보기

 *애플리케이션을 위한 사용자 인터페이스 화면을 만들기 위해서는, Activity 클래스를 확장하고, 뷰를 사용해 사용자 상호작용을 제공한다

 *액티비티 만들기 : 새로운 액티비티를 생성하려면, Activity 클래스를 확장한 다음 사용자 인터페이스를 정의하고 원하는 기능을 구현한다.

 *액티비티 수명주기 : 활성Active(화면에 보이고 포커스를 가지며 사용자 입력을 받는다, 다른 액티비티가 활성화되면 기존의 활성 액티비티는 일시 중지될 것이다)

일시 중지Paused(투명한 액티비티나 화면 전체를 사용하지 않는 액티비티가 그 앞에 활성화되는 경우 도달된다),

중지Stopped(화면에 보이지 않을 경우 "중지"된다)

비활성Inactive(종료되고 난 이후와 띄워지기 이전 비활성상태로 있는다)

 *상태 변화 모니터링 : 액티비티가 자신의 전체수명full lifetime, 가시수명visible lifetime, 활성수명active lifetime 사이를 전이할 때 호출되는 일련의 이벤트 핸들러들을 제공한다.

* onCrete() : 전체 수명 시장 시 호출

* onRestoreInstanceState() : onCrete가 종료된 후 호출되며, UI 상태 복구에 사용

* onRestart() : 가시 수명으로 이어지기 전, 액티비티 처리를 위해 호출

* onStart() : 가시 수명 시작 시 호출

* onResume() : 활성 수명 시작 시 호출

* onSaveInstanceState() : 활성 수명 끄트머리에서 UI 상태 변화를 저장하기 위해 호출

* onPause() : 활성 수명의 끝에서 호출

* onStop() : 가시 수명의 끝에서 호출

* onDestroy() : 전체 수명의 끝에서 호출

*전체 수명 : onCrete ~onDestroy  

*가시 수명 : onStart ~ onStop

*활성 수명 : onResume ~ onPause

*안드로이드 액티비티 클래스 : MapActivity, ListActivity, ExpandableListActivity, ActivityGroup

ch04 사용자 인터페이스 만들기


 - 기본적인 안드로이드 UI디자인

 *뷰 : 비주얼 인터페이스 요소(컨트롤 또는 위젯으로 보통 알려진)를 위한 기본 사용자 인터페이스 클래스다

 *뷰 그룹 : 여러 개의 자식 뷰를 담을 수 있는 뷰 클래스의 확장이다.

 *액티비티 : 사용자에게 보여지는 윈도우나 화면을 나타낸다.


 - 뷰 소개

 *컨트롤은 보통 상대적으로 간단한 기능을 구현하는 뷰의 확장을 가리키는 반면,위젯은 대개 복잡한 컨트롤과 좀더 복잡한 뷰의 확장 모두를 가리킨다.

 *뷰를 사용해 액티비티 사용자 인터페이스 만들기 : 사용자 인터페이스를 설정하려면 setContentView를 호출하고 나타낼 뷰 인스턴스(보통 레이아웃)을 전달한다. findViewById 메서드를 사용하면 레이아웃 내에 사용된 뷰의 레퍼런스를 얻을 수 있다.

 *안드로이드 위젯 도구 상자(TextView, EditText, ListView, Spinner(복합컨트롤), Button, CheckBox, RadioButton)


 - 레이아웃 소개

 *레이아웃은 화면 위에 있는 자식 컨트롤의 위치를 제어하기 위해 설계된 ViewGroup클래스의 확장이다.

 * FrameLayout(쌓음), LinearLayout(수평 수직),RelativeLayout(상대적으로 정의), TableLayout(행과 열의 격자), AbsoluteLayout(절대좌표)

 *외부 리소스를 사용해 XML로 구현하는 것이 선호되며,레이아웃 XML은 반드시 단일 루트 엘리먼트를 가져야 한다.


- 새로운 뷰 만들기

 *기존 뷰 수정하기 : 기존 컨트롤에 기반을 둔 위젯을 만들려면,원하는 컨트롤을 확장하는 새로운 클래스를 생성한다.

 *할 일 목록 커스터마이즈하기 :

1.TextView를 확장하는 TodoListItemView 클래스를 만든다.

2.res/values폴더에 color.xml 리소스를 만든다.

3.dimens.xml리소스 파일을 만들고 종이의 여백 폭을 위한 새로운 값을 추가한다.

4.종이 배경과 여백을 그리는 데 사용할 Paint 객체들을 저장하기 위한 private인스턴스 변수들을 만든다.

5. onDraw를 재정의한 뒤 Paint 객체로 종이이미지를 그린다.

6. Res/layout 폴더에 todolist_item.xml리소스를 만든다.

7. ToDoList 액티비티 클래스의 onCreate에서 ArrayAdapter에 전달된 매개변수를 R.layout.todolist_item 레이아웃으로 바꾼다.

 *복합 컨트롤 : 서로 연결되어 배치된 여러 자식 컨트롤을 담는 원자적이면서도 재사용 가능한 위젯이다. 자식 컨트롤의 위치를 지정하는 데 가장 적합한 레이아웃 클래스 하나를 골라 이를 확장한다. 레이아웃을 새 복합 컨트롤에 사용하기 위해서는 해당 복합 컨트롤의 생성자를 오버라이드 한 다음, LayoutInflate시스템 서비스의 inflate메서드를 사용해 레이아웃 리소스를 부플린다. Inflate메서드는 레이아웃 리소스를 취하고 부풀려진 뷰를 리턴한다.

 *커스텀 위젯과 컨트롤 만들기 : 빈 캔버스로부터 새 컨트롤을 만들려면 ViewSurface 클래스 중 하나를 확장한다. View 클래스는 Canvas객체 하나를 비롯하여 일련의 그리기 메서드와 Paint 클래스를 제공한다. SurfaceView는 그리기를 지원하고 3D 그래픽스를 위해 OpenGL을 사용하는 캔버스를 제공한다.

*새 비주얼 인터페이스 만들기 : 비주얼 인터페이스를 나타내려면, onMeasureonDraw메서드를 재정의할 필요가 있다.

*컨트롤 그리기 : Canvas 클래스는 원,,사각형, 텍스트, 드로어블(이미지)등 기본 2D 객체를 그리기위한 메서드를 가지고 있다. DrawablePaint클래스를 조립해 사용한다.

*컨트롤 크기 바꾸기 : onMeasure 메서드는 두 개의 매개변수(widthMeasureSpec, heightMeasureSpec)를 전달, 뷰의 높이와 폭을 setMeasuredDimension메서드에 전달한다.

 *사용자 상호작용 이벤트 다루기 : 가상 이벤트 핸들러(onKeyDown, onKeyUp, onTrackballEvent, onTouchEvent)

 *나침반 뷰 예제 만들기 :

1. CompassView 클래스를 만든다. 컨트롤 초기화에 사용될 initCompassView메서드를 추가하고 이를 각 생성자에서 호출한다. 2. onMeasure 메서드를 재정의해 가장 짧은 변의 길이를 계산하고, setMeasuredDimension을 사용해 이 값을 높이와 폭으로 설정한다.

3.나침반을 그리는 데 사용할 색상과 텍스트 문자열을 저장하는 두 개의 새로운 리소스파일을 만든다.

4.CompassView클래스에서 방위표시를 위한 새로운 프로퍼티 하나를 추가하고 이를 위한 get,set메서드를 만든다. 5.initCompassView 메서드에서 각 리소스의 레퍼런스를 얻고,문자열 값은 인스턴스 변수로 저장, 색상 값은 클래스 범위의 새로운 Paint객체들을 만드는 데 사용한다.

6.String및 Paint 객체들을 사용해 나침반 면을 그린다.

7.main.xml레이아웃리소스를 수정해 TextView 레퍼런스를 새로 만든 CompassView로 바꾼다.

 *커스텀 컨트롤 사용하기



- 메뉴 만들고 사용하기

 *안드로이드 메뉴 시스템 소개(아이콘 메뉴 : 메뉴 버튼을 누르면 화면 하단에 나타난다. , 확장 메뉴 : 사용자가 아이콘 메뉴에서 자세히 메뉴 항목을 선택할 때 나타난다. , 하위메뉴: 하위 메뉴를 부동 윈도우에 나타낸다.)

 *액티비티 메뉴 정의하기 : onCreateOptionMenu 메서드를 재정의.메뉴를 채우려면 Menu 객체에 add메서드를 사용한다.

 *메뉴 항목 옵션 : 체크 박스와 라디오 버튼(setGroupCheckable),단축 키(setShortcut), 간결한 제목(setTitleCondensed),아이콘(setIcon), 메뉴 항목 클릭 리스너(setOnMenuItemClickListener),인텐트(setIntent)

 *동적으로 메뉴 항목 업데이트하기 : 액티비티의 onPrepareOptionsMenu메서드를 재정의하면, 메뉴가 표시될 때마다 애플리케이션 상태에 기반해 메뉴를 수정할 수 있다.

 *메뉴 선택 처리하기 : onOtionsItemSelected메서드라는 단일 이벤트 핸들러를 사용해 다룬다.

 *하위메뉴와 컨텍스트 메뉴 : 하위메뉴만들기(addSubMenu메서드)

*컨텍스트 메뉴 사용하기 : 컨텍스트 메뉴는 현재 포커스를 가진 뷰에 의해 맥락화되며, 트랙볼이나 가운데 D-패드 버튼 또는 뷰를 약 3초간 누르면 나타난다.

*컨텍스트 메뉴 만들기 : onCreateContextMenu핸들러를 재정의해, View 클래스에 대한 일반적인 컨텍스트 메뉴를 만든다.

*컨텍스트 메뉴 선택 다루기 : 액티비티에 onContextItemSelected메서드를 재정의하는 기법을 사용할 수 있다.

 *할 일 목록 예제 계속 :

1.메뉴 기능을 지원하기 위해 필요한 패키지들(Menu, MenuItem, ContextMenu, AdapterView)ToDoList액티비티 클래스에 임포트한다.

2.각 메뉴 항목을 위한 유일한 ID를 정의하는 private static final 변수를 추가한다.

3. onCreateOptionsMenu 메서드를 재정의하고, 할 일 추가 메뉴 항목과 할 일 삭제 메뉴 항목을 추가한다. 각 항목에 대해 적절한 텍스트를 설정하고 아이콘 리소스와 단축키를 할당한다.

4.컨텍스트 메뉴를 만든다. onCreate를 수정해 ListView가 컨텍스트 메뉴를 받도록 등록한다. 그런 다음 onCreateContextMenu를 재정의해 메뉴에 삭제 항목을 추가한다.

5. onPrepareOptionsMenu 메서드를 재정의해,애플리케이션 상황에 기반하여 메뉴의 겉모습을 바꾼다.

6. todoItems와 ListView 컨트롤의 범위를 onCreate메서드 이상으로 늘린다.( ArrayAdapterEditText 동일한 작업)

7.메뉴 아이템 클릭 처리, onOptionsItemSelectedonContextItemSelected메서드를 재정의해 새 메뉴 항목을 다루는 스텁을 실행한다.

8.각 스텁을 구현해 새로운 기능을 제공한다.

9.새 항목이 추가된 후 텍스트 입력 박스를 감춘다. 새 항목 추가 후 cancelAdd함수를 호출하도록 onCreate 메서드에 있는 onKeyListener를 수정한다.

10.일관된 UI를 보장하기 위해 main.xml레이아웃을 수정하여 사용자가 새로운 항목 추가를 선택할 때까지 텍스트 입력 박스를 감춘다.




ch05인텐트,브로드캐스트 수신자, 어댑터, 그리고 인터넷


- 인텐트 소개

* 인텐트intents는 어떠한 액션이 수행되어야 한다는 의향을 선언할 수 있도록 해주는 메시지 전달 메커니즘이다. 새 액티비티를 시작(명시적,암시적), 시스템 전역에 메시지 방송, 인터넷 연결 상태나 배터리 충전 수준의 변화 같은 시스템 이벤트 알림 등에 사용된다.

* 인텐트를 이용해 액티비티 띄우기 : startActivity(myIntent); myIntent와 가장 필적한 액티비티 하나를 찾아 시작시킨다.

** 명시적으로 새 액티비티 시작시키기 : 읽어 들일 클래스를 지정 (Intent intent = new Intent(MyActivity.this, MyOtherActivity.class)

** 암시적 인텐트와 늦은 런타임 바인딩 : 익명의 애플리케이션 컴포넌트가 액션 요청을 서비스 할 수 있게 함. 데이터의 어느 한 부분에 대해 수행되는 액션을 요청(Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-2368));

** Linkify 소개 :하이퍼 링크를 자동으로 생성하는 도우미 클래스

*** 네이티브 링크 타입 : 브라우저나 이메일, phone 등을 위한 링크를 제공한다.(Linkify.addLink(textView, Linkfy.WEB_URLS | Linkfy.EMAIL_ADDRESSES); (android:autoLink="phone | email" )

*** 커스텀 링크 문자열 만들기 : 하이퍼링크로 표시하고자 하는 텍스트와 일치하도록 새로운 RegEx 패턴을 만든다.

(Pattern p = Pattern.compile("\\bquake[0-9]*\\b", flags); Linkify.addLinks(myTextView, p , "content://com.paad.earthquake/earthquakes/");

*** 매치 필터 사용하기 : RegEx 패턴 매치에 추가 조건을 더하려면 MatchFilteracceptMatch메서드를 구현한다.

*** 변형 필터 사용하기 : 링크 텍스트에 의해 생성된 암시적 URI를 수정함으로써 텍스트 문자열을 서싲화하는데 더 많은 자유를 준다. transformUrl 메서드를 구현한다.

** 액티비티 결과 리턴하기 : startActivity로 시작된 액티비티는 종료할 때 어떠한 피드백도 제공하지 않는다. 액티비티를 그의 부모에 연결된 서브 액티비티로 시작하면 서브 액티비티가 종료할 때 자신의 부모 액티비티 안에 있는 이벤트 핸들러를 호출하기 때문에 결과를 리턴할 수 있다.

*** 서브 액티비티 띄우기 : startActivityForResult(intent, SHOW_SUBACTIVITY);

*** 결과 리턴하기 : finish를 호출하기 전에 setResult를 호출하여 호출 액티비티에 결과를 리턴한다.

*** 서브 액티비티 결과 다루기 : 서브 액티비티가 종료되면 부모 액티비티에 있는 onActivityResult 이벤트 핸들러가 호출된다. onActivityResult의 매개변수(요청코드,결과코드,데이터)

** 네이티브 안드로이드 액션 : static문자열로서 사용가능한 Intent 클래스에 있는 네이티브 액션들(ACTION_ANSWER, ACTION_CALL, ACTION_DELETE, ACTION_DIAL, ACTION_EDIT, ACTION_INSERT, ACTION_PICK, ACTION_SEARCH, ACTION_SENDTO, ACTION_SEND, ACTION_VIEW, ACTION_WEB_SEARCH )

* 인텐트 필터를 이용해 암시적 인텐트 서비스하기 :인텐트 필터는 액티비티, 서비스, 그리고 브로드캐스트 수신자를 특정한 종류의 데이터에 대한 액션을 수행할 수 있는 존재로 등록하는 데 사용된다. 인텐트 필터 노드에 액션(액션의 이름),범주(상황조건),데이터(실행할 수 있는 데이터에 대한 명세)를 지정할 수 있다.(action(android:name), category(ALTERNATIVE, SELECTED_ALTERNATIVE, BROWSABLE, DEFAULT, GADGET, HOME, LAUNCHER), data(android:host, android:mimetype, android:path, android:path, android:port, android:scheme)

** 안드로이드가 인텐트 필터를 해결하는 방법 :지정된 데이터에 주어진 액션을 실행할 수 있는 액티비티가 여러 개 존재한다면, "가장 좋은 것"이 시작된다.

** 인텐트 필터 매치에 반응하기 : 인텐트의 데이터와 액션은 getDatagetAction 메서드로 얻는다.인텐트의 엑스트라 번들에 저장된 추가 정보는 타입에 안전한 get<type>Extra 메서드로 얻는다.

** 책임 떠넘기기 : startNextMatchingActivity 메서드를 이용해, 액션 처리의 책임을 다음 베스트 매칭 애플리케이션 컴포넌트로 넘길 수 있다.

** 연락처 선택 예제 : 1. ContactPicker액티비티 생성 2.main.xmlListView컨트롤 포함되도록 수정(연락처 표시) 3. listitemlayout.xml레이아웃 리소스 생성(텍스트 뷰 포함) 4. onCreate메서드 재정의, 호출 인텐트로부터 데이터 경로 얻어옴,연락처 사람들에 대한 데이터URI를 만들고 SimpleCursorArrayAdapter를 이용해 리스트 뷰에 바인딩, ItemClickListener를 리스트 뷰에 추가 5.매니페스트에 intent-filter 태그를 연락처 데이터에 대한 선택액션 지원을 추가하도록 수정 6. ContentPickerTester 액티비티 생성, 새로운 레이아웃 리소스(선택된 연락처 표시, 시작버튼) 7.ContentPickerTester의 버튼에 클릭 리스너를 추가하여, 버튼이 PICK_ACTION과 연락처 데이터베이스 URI를 지정해 새로운 서브 액티비티를 암시적으로 시작하도록 만듬 8.서브 액티비티가 리턴하면,그 결과를 이용해 선택된 지인의 이름으로 텍스트 뷰를 채움 9. 테스트 도구를 매니페스트에 추가, uses-permission태그에 READ_CONTACTS 권한을 추가

* 플러그 인과 확장성을 위한 이넨트 필터 사용 :런타임 메뉴 채움은 주어진 타입의 데이터에 대해 액션 수행이 가능한 새로운 컴포넌트를 만드는 경우에 옛 기능을 새 기능으로 바꿀 수 있는 능력을 준다

** 애플리케이션에 익명 액션 제공하기 : 액션을 다른 액티비티를 위해 사용할 수 있도록 만들려면, intent-filter 태그를 이용해 액션을 해당 액티비티의 매니페스트 노드 내에 알린다.

** 액티비티 메뉴에 익명 액션 통합하기 : 액션을 찾는데 사용되는 인텐트와 더불어 옵션 플래그, 호출 클래스 이름, 사용할 메뉴 그룹,메뉴 ID값을 여러분이 채우고자 하는 메뉴에 대한 addIntentOptions에 전달한다.

* 이벤트 방송을 위한 인텐트 사용 : sendBroadcast메서드를 이용해 메시지를 컴포넌트들 간에 익명으로 방송하는 데 사용될 수 있다.

** 인텐트로 이벤트 방송하기 : Intent intent = new Intent(NEW_LIFEFORM_DETECTED); sendBroadcast(intent)

** 브로드캐스트 수신자로 방송에 귀 기울이기 : BroadcastReceiver 클래스를 확장하고 onReceive 이벤트 핸들러를 재정의

*** 애플리케이션 매니페스트에 브로드캐스트 수신자 등록하기 : receiver 태그를 applicaion 노드 내에 추가한다.

*** 코드로 브로드캐스트 수신자 등록하기 : registerReceiver(r, filter);

** 네이티브 안드로이드 브로드캐스트 액션(ACTION_BOOT_COMPLETED, ACTION_CAMERA_BUTTON, ACTION_DATE_CHANGED & ACTION_TIME_CHANGED, ACTION_GTALK_SERVICE_CNNECTED & ACTION_GTALK_SERVICE_DISCONNECTED, ACTION_MEDIA_BUTTON, ACTION_MEDIA_EJECT, ACTION_MEDIA_MOUNTED & ACTION_MEDIA_UNMOUNTED, ACTION_SCREEN_OFF & ACTION_SCREEN_ON, ACTION_TIMEZONE_CHANGED)


- 어댑터 소개

* 어댑터는 데이터를 사용자 인터페이스 뷰와 바인드하는 브리징 클래스이다.

* 안드로이드가 제공하는 어댑터 몇가지(ArrayAdapter, SimpleCursorAdapter)

* 어댑터를 이용한 데이터 바인딩 : 어댑터 인스턴스를 뷰의 setAdapter 메서드에 전달해 호출한다.

** 할 일 목록 ArrayAdapter 커스터마이징 1. ToDoItem 클래스 생성. 항목 데이터의 요약을 리턴하도록 toString메서드 재정의 2. ArrauListArrayAdapter 변수타입을 문자열 대신 ToDoItem의 객체를 저장하도록 수정, onKeyListener핸들러를 업데이트 4. 커스텀 레이아웃을 두 번째 TextView를 포함하도록 수정 5. ArrayAdapter의 변형을 호가장하는 새로운 클래스 ToDoItemAdapter 생성 getView재정의해 ToDoItem 객체에 있는 작업과 날짜 프로퍼티를 레이아웃 내의 뷰에 할당 6. ArrayAdapter 선언을 ToDoItemAdapter 로 바꿈

** SimpleCursorAdapter 사용하기 : SimpleCursorAdapterCursor로부터 열을 커스텀 레이아웃 정의를 사용하는 리스트 뷰에 바인드 할 수 있도록 해준다. SimpleCursorAdapter는 현재 컨텍스트,레이아웃 리소스, 커서, 그리고 사용할 열들의 이름을 담은 배열과 그에 대응하는 열의 데이터 값을 표시하기 위해 사용할 뷰의 리소스 ID를 담은 배열을 전달함으로써 생성된다.


- 인터넷 리소스 사용하기

* 인터넷 네이티브 애플리케이션을 만드는 데의 이점 :대역폭(데이트 업데이트 시에만 대역폭을 사용하도록 제한 가능), 캐싱(살아있는 연결 없이도 가능한 많은 기능을 제공하기 위해 데이터를 캐시 가능), 네이티브 기능(풍부한 사용자 경험 제공),

* 인터넷 연결을 위한 세가지 연결 기법(GPRS, EDGE,그리고 3G), Wi-Fi

* 인터넷 리소스에 접속하기 <uses-permission android:name ="android.permission.INTERNET"/>

* 인터넷 리소스 이용 극대화하기 : 전송되는 데이터량을 제한해 사용자 경험을 최적화하고, 애플리케이션이 네트워크 정전과 대역폭 제한을 충분히 잘 다룰 수 있도록 견고하게 만들자.


- 다이얼로그 소개

* 안드로이드 다이얼로그는 자신을 띄운 액티비티를 부분적으로 가리는 부동 윈도우floating window.

* 다이얼로그 구현방법 : 다이얼로그 계열 클래스 사용, 다이얼로그 테마가 적용된 액티비티, 토스트

* Dialog 클래스 : Dialog d = new Dialog(MyActivity.this); d.setTitle("다이얼로그 제목"); d.setContentView(R.layout.dialog_view); d.show();

** AlertDialog 클래스 :사용자에게 여러 개의 버튼 중 하나만 선택할 수 있는 형태로 보통 OK,Cancel, 그리고 YesNo로 이루어진 버튼

** 전문 입력 다이얼로그 (DatePickerDialog, TimePickerDialog, ProgressDialog) : 사용자 입력을 위한 인터페이스를 제공

** 다이얼로그 사용과 관리 : onCreateDialog, onPrepareDialog 이벤트 핸들러

* 액티비티를 다이얼로그로 사용하기 :  매니페스트에 추가 할 때 android:style/Theme.Dialog 테마를 적용


- 지진 뷰어 만들기

1. Earthquake 액티비티 생성. main. xml레이아웃 리소스를 수정(리스트 뷰 컨트롤 하나 추가) 2.새 클래스 Quake 생성(지진별 세부정보를 저장하는 데 사용), toString 메서드 재정의 해 리스트 뷰 안에 있는 각 지진을 위해 사용될 문자열 제공 3.Earthquake액티비티에서 onCreate 메서드 재정의(Quake 객체들의 ArrayList를 저장, ArrayAdater 이용해 ListView에 바인드) 4.지진 피드 처리 5. 인터넷 접근 권한 부여(매니페스트에 uses-permission) 6.Earthquake 액티비티에 지진 피드에 접속하고 이를 파싱하는 refresh Earthquake메서드 새엉. 각각의 지진 정보를 추출한 뒤 이를 파싱해 날짜,진도,링크,위치를 얻음. 각각의 지진 정보 파싱을 마치고 나면,이를 새로운 addNewQuake 메서드에 전달 7.새로 처리된 각각의 지진 정보를 받아 지진 ArrayList에 추가하도록 addNewQuake메서드를 업데이트, 8. 시작 시 onCreate 메서드가 refreshEarthquakes를 호출하도록 수정 9.프로젝트 실행 10. 사용자가 필요 시 지진 피드를 새롭게 갱신할 수 있도록 하는 새로운 메뉴 항목 만들기 10.1 해당 메뉴 옵션을 위한 새로운 외부 문자열 추가 10.2 onCreateOptionMenuonOptionItemSelected 메서드를 재정의 해 지진 정보 갱신 메뉴 항목을 표시하고 처리 11. 사용자가 리스트에서 지진 정보를 선택할 때,다이얼로그 박스를 열어 그에 대한 세부 정보를 살펴볼 수 있도록 하기 11.1 항목이 클릭될 때 표시할 다이얼로그 박스를 위해 새로운 quake_details.xml레이아웃 리소스를 만듬 11.2지진 항목이 선택될 때마다 다이얼로그 박스를 표시하는 ItemClickListener를 리스트 뷰에 추가하도록 onCreate 메서드를 수정 11.3 onCreateDialogonPrePareDialog메서드를 재정의해, 지진 세부 정보 다이얼로그를 만들고 그 안에 내용을 채움 11.4 USGS에 대한 링크를 하이퍼링크로 만들기 위해 다이얼로그를 링키파이 하기. 다이얼로그 박스의 XML레이아웃 리소스 정의가 autolink 속성을 갖도록 조정



ch06데이터 저장, 검색, 그리고 공유

  • 안드로이드의 데이터 저장 기법
    • 공유 환경설정
    • 파일
    • SQLite 데이터베이스
    • 콘텐트 공급자
  • 공유 환경설정
    • 애플리케이션내 컴포넌트내에서만 공유, 다른 애플리케이션은 사용불가
    • SharedPreference.Editor 클래스 이용, 지원 타입 : boolean, int, long, float, String
    • Bundle매개변수 이용: onSaveInstanceState, onCreate 이벤트 사용 (onSaveInstanceState는 액티비티가 종료 호출에 의해서나 사용자가 뒤로 가기버튼을 누름으로서 종료되고 있는 경우가 아닌, 비활성화되는 경우에만 호출된다)
    • 할일 목록 액티비티 상태 저장 예제
    • 지진 뷰어 환경설정 예제
  • 파일
    • FileOutputStream, FileInputStream
    • 애플리케이션간 파일을 공유하기 위해서는 콘텐트 공급자를 이용 해야함
    • Context.MODE_APPEND   Context.MODE_WORLD_READABLE   Context.MODE_WORLD_WRITEABLE
    • 프로젝트내 res/raw 폴더에 파일리소스를 추가, openRawResource 메소드로 사용
    • 파일관리 메소드 : deleteFile, fileList
  • SQLite
    • 관계형 데이터베이스 시스템(RDBMS), 특징 : 오픈소스/표준준수/경량/단일계층, 저장위치 :  /data/data/<package_name>/databases
    • 컬럼의 데이터 타입이 정의 되지 않고 각 컬럼의 행별로 데이터 타입이 정의
    • 데이터베이스 쿼리는 Cursor 객체로 리턴 된다.
    • Cursor 함수
      • moveToFirst : 첫번째 행으로 이동, 쿼리된 데이터가 읽어들일때 항상 실행, 데이터가 없는 경우 false 반환
      • moveToNext : 커서를 다음 행으로 이동
      • moveToPrevious : 커서를 이전 행으로 이동
      • getCount : 쿼리된 데이터의 수
      • getColumnIndexOrThrow : 지정된 컬럼에 대한 인덱스를 반환
      • getColumnName : 열이름 리턴
      • getColumnNames : 모든 열이름을 String 배열로 리턴
      • moveToPosition : 지정한 행으로 이동
      • getPosition : 현재 커서 위치 반환
    • 액티비티내에서 커서를 관리하는 메소드 : startManagingCursor, stopManagingCursor
    • SQLiteOpenHelper : 데이터베이스를 관리하는 클래스,  생성자 / onCreate / onUpgrade 메소드를 재정의
    •  SQLiteOpenHelper 없이 openOrCreateDatabase 메소드를 사용 가능
    • 데이터베이스 설계시 고려사항
      • 파일은 데이터베이스에 저장하지 않고 경로 저장
      • 테이블에 자동증가키 사용(인덱스키로 사용)
    • 데이터베이스 조회 쿼리
      • query 메소드 사용
      • Cursor android.database.sqlite.SQLiteDatabase.query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
        • boolean distinct : 결과 값에 대한 유일한 값만 가져올지에 대한 여부
        • String table : 쿼리할 테이블 명
        • String[] columns : 쿼리대상 열명
        • String selection : 쿼리의 조건절을 구성
        • String[] selectionArgs : selection에 들어간 ? 와일드문자를 대체할 문자열
        • String groupBy : 데이터를 묶을 그룹 조건 정의
        • String having : groupBy 지정된 경우 그룹 조건 정의
        • String orderBy : 결과의 정렬 조건
        • String limit : 결과 값의 행 개수를 제한을 정의
    • 데이터베이스 입력
      • insert 메소드 사용
      • long android.database.sqlite.SQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values)
        • String table : 입력할 테이블명
        • String nullColumnHack : 널값을 대체할 문자
        • ContentValues values : 입력할 데이터 키/값 조합 - void android.content.ContentValues.put(String key, String value)
    • 데이터베이스 수정
      • update 메소드 사용
      • int android.database.sqlite.SQLiteDatabase.update(String table, ContentValues values, String whereClause, String[] whereArgs)
        • String table : 입력할 테이블명
        • ContentValues values : 수정할 데이터 키/값 조합
        • String whereClause : 조건절 구성
        • String[] whereArgs : 조건절에 들어간 ? 와일드문자를 대체할 문자열
    • 데이터베이스 삭제
      • delete 메소드 사용
      • int android.database.sqlite.SQLiteDatabase.delete(String table, String whereClause, String[] whereArgs)
        • String table : 입력할 테이블명
        • String whereClause : 조건절 구성
        • String[] whereArgs : 조건절에 들어간 ? 와일드문자를 대체할 문자열
    • 데이터베이스 연결 닫기 : 액티비디에서 onDestory 메소드에서 데이터베이스를 닫는다
  • 콘텐트 공급자
    • 애플리케이션 간에 데이터를 공유할 수 있도록 하는 인터페이스
    • URI 모델을 이용해 접근
    • ContentResolver 클래스 사용
    • Cursor android.content.ContentResolver.query(Uri uri, String[] projection, String selection, String[]  selectionArgs, String sortOrder)
      • Uri uri : 질의하고자 하는 콘텐트 공급자의 데이터의 URI
      • String[] projection : 질의에 들어갈 컬럼명
      • String selection : 조건절
      • String[]  selectionArgs : 조건절에 들어간 ? 와일드문자를 대체할 문자열
      • String sortOrder : 결과의 정렬 조건
    • Uri android.content.ContentResolver.insert(Uri url, ContentValues values)
    • int android.content.ContentResolver.bulkInsert(Uri url, ContentValues[] values)
    • int android.content.ContentResolver.delete(Uri url, String where, String[] selectionArgs)
    • int android.content.ContentResolver.update(Uri uri, ContentValues values, String where, String[] selectionArgs)
    • 콘텐트 공급자에서 파일 접근 : openOutputStream, openInputStream
  • 네이티브 안드로이드 콘텐트 공급자
    • Browser : 브라우저 콘텐드 공급자를 이용
    • Callog : 착발신 통화 내역
    • Contacts : 주소록
    • MediaStore : 오디오, 비디오, 이미지 등
    • Settings : 설정공급자
    • 콘텐트 공급자 생성 : ContentProvider 클래스 상속을 받아서 구현
    • public static CONTENT_URI 변수 선언
    • 공급자 URI 형식 : content://com.<회사명>.provider.<앱명>/<데이터경로> [/<행번호>]
    • 공급자 등록 : 매니페스트에 authorities 등록

ch7  맵, 지오코딩, 그리고 위치기반 서비스


- 위치기반 서비스 이용하기

- LocationManager : 위치기반 서비스에 대한 고리를 제공

- LocationProvider : 장치의 현재 위치를 결정하는데 사용되는 서로 다른 각각의 위치검색 기술을 표현


- 테스트 공급자를 이용해 에뮬레이터 설정하기

- 에뮬레이터 위치 공금자의 위치 업데이트 하기

- 이클립스 DDMS Location Control을 사용

- Manual : 특정 위도/경도를 지정

- KML : 지점간 경로를 xml 형태로 기록하여 이동경로를 표현 (참고: http://mygeoposition.com/)

- GPX :


- 위치 공급자 선택하기

- getProvider를 호출

String providerName = LocationManager.GPS_PROVIDER;

LocationProvider gpsProvider;

gpsProvider = locationManager.getProvider(providerName);


- 이용할 수 있는 공급자 찾기

- LocationManager.GPS_PROVIDER

- LocationManager.NETWORK_PROVIDER

장치에 이용할 수 있는 공급자 리스트를 얻기 위해서는getProviders를 호출

List<String> providers = locationManager.getProviders(True);


- 요구 기준에 기반해 공급자 찾기

- Criteria Class : 사용자의 요구사항에 적합한 위치공급자의 기준을 명시

setAccuracy(Criteria.ACCURACY_COARSE / Criteria.ACCURACY_FINE) : 정확도

setPowerRequirement(Criteria.POWER_LOW / ) :전력소비량

setAltitudeRequired(true / false) : 고도데이터 사용 유무

setBearingRequired(true / false) :방위데이터 사용 유무 ***확인

setSpeedRequired(true / false) :속도데이터 사용 유무

setCostAllowed(true / false) :비용 들지 여부


- LocationManager.getBestProvider(criteria, {true|false})

요구사항에 가장 부합하는 위치공급자를 리턴.

boolean 현재 사용 가능한 공급자로 결과를 제한


- LocationManager.getProvider(criteria, {true|false})

요구사항에 부합하는 위치공급자를 리스트형태로 리턴.



- 내 위치찾기

LBS(Location Based Services)에 대한 접근은 Location Manager를 이용.

Location Manager 접근위해getSystemService()를 이용해 LOCATION_SERVICE의 인스턴스를 요청


LocationManager locationManager;

locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);


use-permission Manifast파일에 추가

<use-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<use-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>


위치정보는 getLastKnownLocation메서드에 Location Provider를 전달함으로써 찾을 수 있다.

String provider = LocationManager.GPS_PROVIDER;

Location location = locationManager.getLastKnownLocation(provider);

* getLastKnownLocation : location provider에 현재위치를 업데이트하도록 요청하지는 않음.

* 리턴받은 location객체는 위도,경도, 방위, 고도, 속도, 위치 수정이 이뤄진 시간 등을 포함할 수 있고 get메소드를 사용해 얻을 수 있다.


- 움직임 추적

- locationManager.requestLocationUpdates(provider, 밀리초, 거리, LocationListener)

위치가 바뀔 때 마다 업데이트된 위치 정보를 얻음.

-locationManager.removeUpdates(LocationListener)

위치정보 업데이트를 중단함.


- 근접 경보 사용하기

사용자가 특정 위치로 이동하거나 그 위치에서 벗어날 때 어플리케이션이 반응하도록하는 기능.

근접 경보 발생시 intent를 생성.보통은 broadcast intent를 생성.

발생시킬 intent를 지정하려면

Intent intent = new Intent(MY_ACTIVITY);

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, -1, intent, 0);


- 지오코더 사용하기

주소와 경도/위도 맵 좌표간의 정보를 서로 변환.

Geocoder class는 두가지 지오코딩 기능을 제공

Forward Geocoding : 특정 주소의 위도와 경도를 찾는다

Reverse Geocoding : 주어진 위도와 경도에 대한 주소를 찾는다


Geocoder goecoder = new Geocoder(getApplicationContext(), Locale.getDefault());


- 역방향 지오코딩

대상 위도와 경도를 지오코더의getFromLocation메소드에 전달,

일치하는 주소 리스트 리턴하거나 없을경우 null리턴.


- 순방향 지오코딩

getFromLocationName메소드 호출.

List<Address> 형태의 결과 값을 리턴.



- 맵기반 액티비티 만들기

- MapView MapActivity소개

MapView : 실제 맵 뷰

MapActivity :맵 뷰를 포함할 수 있는 새로운 activity를 만들기 위해 상속받아야할 class.

Overlay :맵에 주석을 다는데 사용되는 class

MapController : 맵을 제어. 중심 위치와 확대 단계를 설정.

MyLocationOverlay : 현재 위치와 장치의 방향을 표시하는데 사용

ItemizedOverlay, OverlayItem : 둘이 함께 사용되어drawable 및 그와 연관된 텍스트를 이용해 표시되는 map marker를 만듦


- 맵기반 액티비티 만들기

MapActivity를 상속받은 새로운 액티비티 생성.

액티비티에서 보여줄 레이아웃에는 MapView추가. (apiKey를 포함)

도로정보를 화면 출력 시isRoutDisplayed를 재정의.

Manifast 파일

<use-library android:name="com.google.android.maps"/> 추가

<use-permission android:name="android.permission.INTERNET"/> 추가


- 맵뷰 구성하고 사용하기

mapView.setSatellite(true) :위성 뷰

mapView.setStreetView(true) : street

mapView.setTraffic(true) :예상 교통량


map Zoom Controls 사용을 위해

View zoomControls = mapView.getZoomControls();

mapView.addView(zoomControls, MapView.LayoutParams);

mapView.displayZoomControls(true);


- 맵 컨트롤러 사용하기

MapView를 이동/확대 시.

getController를 이용해 MapView Controller 레퍼런스를 얻는다.

MapViewController mc = MapView.getController();


Location객체에 저장된 위도 경도 값을 이용하려면 GeoPoint에 백만단위로 변환한 뒤 저장

Double lat = 37.123 * 1E6;

Double lng = 123.123 * 1E6;

GeoPoint point = new GeoPoint(lat.intValue(), lng.intValue());


MapView 중심을 다시 잡거나 확대하려면

MapController.setCenter(point); //point위치가 화면 중앙에 오도록 설정.

MapController.setZoom(1); : 1~21


새로운 위치로 이동시MapController.animateTo(point)를 이용해 부드러운 화면 이동 처리


- 오버레이 만들고 사용하기

- 새 오버레이 만들기

Overlay를 상속받는 새로운 클래스 생성.

draw메소드를 재정의해 화면에 보여질 데이터 표기.

onTap을 재정의해 사용자 클릭에 반응한다.


- 프로젝션 소개

Projection 클래스는 위도/경도 좌표와 x/y화면 픽셀 좌표간을 바꿀 수 있도록 해준다.

Projection projection = mapView.getProjection();

GeoPoint Point로 혹은 그 반대로 바꾸려면 fromPixel, toPixel메소드 이용


- 오버레이 추가하고 제거하기

MapView는 현재 표시되는 오버레이들의 리스트를 갖고 있다.

getOverlays를 호출해 이에 대한 레퍼런스를 얻는다

List<Overlay> overlays = mapView.getOverlays();


맵뷰에 오버레이를 추가하려면

overlays.add(새로추가할Overlay);

mapView.postInvalidate(); //맵 위의 변경사항을 업데이트


- MyLocationOverlay소개

현재 위치와 방향을 MapView위에 보여주도록 설계된 오버레이

MyLocationOverlay를 사용하려면

List<Overlay> overlays = mapView.getOverlays();

MyLocationOverlay mylocationoverlay = new MyLocationOverlay(this, mapView);

overlays.add(mylocationoverlay);


나침반과 마커 모두를 활성화 하기위해서는

mylocationoverlay.enableCompass();

mylocationoverlay.enableMyLocation(mapView.getMapController());


- ItemizedOverlay OverlayItem소개

MapView에 간단한 마커기능을 제공

맵에 ItemizedOverlay마커레이어 추가하려면

ItemizedOverlay<OverlayItem>을 상속받는 클래스 만든다.

size 메소드를 재정의해 표시할 마커 수 리턴.

createItem 메소드 재정의해 각 마커의 인덱스에 기반한 새로운 OverlayItem생성.

클래스 생성자에서 populate()를 호출해 각 OverlayItem이 생성되도록 만든다.


맵에 ItemizedOverlay를 추가하려면

List<Overlay> overlays = mapView.getOverlay();

MyItemizedOverlay markers = new MyItemizedOverlay(이미지);

overlays.add(markers);



8장 백그라운드에서 작업하기  - 발표: 2010년 03월 3일(수) - 오후 07시 30분 ~




8장 목차


 

사용자 삽입 이미지

  1. Service소개

    1. 서비스 만들고 제어하기
    2. 서비스에 액티비티Binding하기
  2. 백그라운 작업자Thread 이용하기

    1. 새로운 스레드 만들기
    2. GUI 작업을 위한 스레드 동기화(Handler)
  3. Toast만들기

    1. 토스트 만들기
    2. 토스트 커스터마이징 하기
  4. Notification소개

    1. 알림 관리자 소개
    2. 알림 만들기
    3. 알림 발생시키기
    4. 고급 알림 기법 (소리, 진동, 불빛)
    5. 진행중 알림과 강조 알림
  5. Alarm이용하기


주요 용어: Service, Bind, Thread, Handler, Toast, Notification, 소리, 진동, 불빛, Alarm



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1. 서비스 소개


  - 서비스는 백그라운드에서 실행되어지며, 비활성 액티비티보다 더 높은 우선순위를 갖는다.

  - 사용자 입력에 직접 의존하지 않는 동작을 규칙적이며 연속적으로 수행할 때 사용하면 좋다.

  - 서비스의 시작과 종료는 다른서비스, 엑티비티, 브로드캐스트 수신자를 포함한 다른 애플리케이션으로부터 가능하다.

  - 서비스 활용 사례 (별도의 쓰레드를 통해서 사용 가능하다)

     . 파일 다운로드

     . Media Player

  - 안드로이드 소프트웨어 스택내의 서비스 사용 사례

     . Location Manger

     . Media Controller

     . Alarm Manager 등


  • 서비스와 바인딩 서비스의 생명주기



사용자 삽입 이미지





1.1 서비스 만들고 제어하기

사용자 삽입 이미지



    1) 서비스를 상속 받은 MyService class를 만든다.

    2) MyService에서 onCreate(), onStart() 메소드를 재정의해서 자신의 기능을 구현한다.

    3) 새로 만든 Service는 Manifest에 등록한다.

    4) MyController 클래스에서 startService()를 통해서 MyService를 시작한다.

    * 한번 생성된 서비스를 다시 startService()로 실행할 때는 onCreate()는 타지 않고 onStart() 실행됨(상기그림의 회색선)

       또한 여러번 시작한 서비스라 할지라도 종료는 stopService()로 단 한번만으로 종료 된다.



1.<service android:enabled="true" android:name=".MyServic"></service>




암시적 서비스 실행

명시적 서비스 실행

 startService(new Intent(MyService.MY_ACTION);

startService(new Intent(this, MyService.class);

* MyService 클래스에 MY_ACTION을 포함시키고, 인텐트 필더에 MY_ACTION을 공급자로 등록해야 한다.





서비스명을 통한 서비스 종료

명시적 서비스 종료

 ComponentName service

   = startService(new Intent(this, MyService.class);

 stopService(new Intent(this, service.getClass());

try{

  Class serviceClass

    = Class.forName(service.getClassName());

stopService(new Intent(this, serviceClass);

}catch(ClassNotFoundException e){}








바인더에 대해서

Binder는 리눅서 커널에 있는 Binder를 통해서 관리된다.

사용자 삽입 이미지


사용자 삽입 이미지




1) ServiceManager는 BinderDriver 에 대한 special Node 0 로 동작

2) ServiceProvider (예 : AudioFlinger) 는 자신의 RPC에 대한 Interface를 ServiceManager proxy object에 대한 Interface를 통해 등록한다.

  - 이 과정을 통해 BinderDriver에서는 ServiceProvider로의 path를 생성

3) Service User는 사용하려는 Service에 대한 Interface를 생성하는데, 이를 위해 ServiceManager에게 RPC call을 통해 요청한다.

4) ServiceManager는 Bind되어있는 Object들의 목록에서 해당하는 ServiceProvider에 대한 Node를 요청한 ServiceUser에게 return

5) ServiceUser는 return된 Node정보를 통해 해당 Service Provider로의 RPC를 수행함

* 인용) http://andstudy.springnote.com/pages/4314107 / 수원안드로이드플랫폼스터디



서비스에서 바인더를 사용하는 이유:

* 액티비티가 서비스에 바인딩되면, 그 액티비티는 해당 서비스 인스턴스 자체에 대한 레퍼런스를 유지하고 실행중에 서비스에 대해 메서드를 호출할 수 있도록 해 준다.

* 일반 서비스는 MyController 액티비티가 서비스의 동작을 알지 못하게 은밀하게 동작한다면, 바인딩된 서비스는  액티비티가 상태를 파악하고 제어할 수 있도록 해 준다.


* 서비스가 바인드되고 나면, 서비스가 가지고 있는 모든 public 메서드와 프로퍼티는 onServiceConnected핸들러를 통해서 얻어진 serviceBinder객체를 통해서 이용 가능하다.

* 브로드캐스트 인텐트 또는 서비스 시작시 사용되는 인텐스 익스트라 번들을 이용해서 간단히 다른 프로세스로 실행 중인 서비스와 간단히 통신할 수 있다.

* 좀더 단단히 결합된 연결을 원할 경우에는 AIDL을 이용하면 된다.




1.2 서비스에 액티비티 바인딩하기


    서비스 작성 순서

사용자 삽입 이미지



     서비스 동작

사용자 삽입 이미지



예제) Toast를 사용한 Service Bind 예제:PAAD08_service.zip


일반 서비스와 바인드서비스의 사용예

사용자 삽입 이미지 사용자 삽입 이미지

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2.백그라운 작업자Thread 이용하기


사용자 삽입 이미지


2-1.백그라운드의 thread의 필요성

 - 모든 콤포넌트는 하나의 Main thread위에서 동작한다.

 - 따라서 시간이 많이 걸리는 작업을 하면 화면에 보이는 Activity뿐만아니라 다른 모든 콤포넌트까지 불록시킨다.

 - 이때 "Application Unresponsive" 메시지가 출력될 것이다.


2-2 백그라운드 thread 활용 추천

 - 입력 이벤트(키 눌림)에 대해서 5초 이내에 반응하지 않을 때

 - onReceive 핸들러를 10초 이내에 완료하지 않는 Broadcast Receiver

 - 이런 현상이 발생되는 주요 작업 사항으로는

   . 파일작업

   . 네트워크 조회

   . 데이터베이스 트랜잭션

   . 복잡한 계산


 2-3 백그라운드 스레드 사용의 결론

  - 느리고 시간이 많이 드는 모든 작업을 Main thread에서 Child thread로 옮기는 것이 좋은 습관이다.


 2-4 새로운 thread와 GUI 작업을 위한 thread 동기화

사용자 삽입 이미지



  - 골격 코드



01.// GUI Handler 처리..
02.private Handler handler =new Handler();
03.

04.// 이 메서드는 메인 GUI 스레드에서 호출된다.

05.private void mainProcessing(){
06.// 이는 시간이 많이 드는 작업을 자식 스레드로 옮긴다.
07.Thread thread =new Thread(null, doBackgroundThreadProcessing,"Background");
08.thread.start();
09.}
10.

11.// 백그라운드 처리 메서드를 실행하는 Runnable

12.private Runnable doBackgroundThreadProcessing =new Runnable(){
13.@Override
14.public void run() {
15.backgroundThreadProcessing();
16.}
17.};
18.

19.// 백그라운드에서 몇 가지 처리를 수행하는 메서드

20.private void backgroundThreadProcessing(){
21.//[필요한 코드]
22.// 처리가 끝나고 결과를 UI로 출력을 해야 할 때 아래 핸들러를 추가해서 사용한다.
23.handler.post(doUpdateGUI);
24.}
25.

26.// GUI 업데이트 메서드를 실행하는 Runnable.

27.private Runnable doUpdateGUI =new Runnable(){
28.@Override
29.public void run() {
30.updateGUI();
31.}
32.};
33.

34.private void updateGUI() {

35.// [[ 필요한 UI 코드 ]]
36.}


   Thread를 만드는 핵심 코드

    private void mainProcessing(){
     Thread thread = new Thread(null, doBackgroundThreadProcessing, "Background");
     thread.start();
    }

   =>> Thread(ThreadGroup group, Runnable runnable, String threadName)


   Thread와 GUI연결을 위한 핵심 코드

    handler.post(doUpdateGUI);  

     ==>> post(Runnable r)


  - Handler를 사용하는 이유

   Child Thread는 GUI를 갖고 있지 않다. 모든 GUI는 Main thread가 갖고 있어서 뷰, Toast등은 모두 Main thread에서 처리해야됨

   따라서 handler를 통해서 child thread의 처리 결과를 Main thread에서 처리할 수 있게 해준다.


 - Handler 클래스의 추가 메소드

   . pastDelayed: 포스팅을 늦추어 처리한다. / handler.postDelayed(doUpdateGUI,5000)

   . pastAtTime : 포스팅을 특정 시간에 실행하도록 한다.


 - UIThreadUtilities 클래스

   이 클래스는 runOnUIThread를 갖고 있어서 View, Activity, Dialog와 같은 thread에서 메소드를 강제적으로 실행해 줌


 - Thread에서 꼭 기억해야 할 사항


" 애플리케이션 컴포넌트에서, 알림과 인텐트는 항상 GUI 스레드에서 수신되고 처리된다.
  다른 모든 경우에 있어, GUI스레드(뷰 같은)에서 생성된 객체와 명시적으로 상호작용하거나 메시지를 표시하는 작업은
  메인 스레드에서 띄워져야만 한다."


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


3.Toast 만들기

 

사용자 삽입 이미지
======>
사용자 삽입 이미지
 



토스트란?

- 형태: 몇 초간만 화면에 보였다가 페이드 아웃되는 일시적 다이얼로그.    

- 특징: 포커스를 훔치지 않으며 비 모달로 활성화 애플리케이션에 방해를 주지 않는다.

- 용도: 앱에 방해주지 않고 정보를 사용자에게 쉽게 제공한다.


원형


1.Toast.makeText(this,"10분 남았습니다",1000).show();
2.public static Toast makeText (Context context, CharSequence text,int
3.duration)

 - makeText: 표준 토스트 표시 윈도우를 생성하는 static 메서드

   > context: 애플리케이션 컨텍스트

   > text : 표시할 텍스트 메시지

   > duration : 다이얼로그가 표시될 시간

 - show() : 이것을 통해서 토스트를 화면에 진정으로 표시하게 된다.


  • 위치변경: mToast.setGravity(Gravity.CENTER, offesetX, offsetY); mtoast.show();

사용자 삽입 이미지


- 커스텀View를 통해 모양변경: mToast.setView(customLayout);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


4.Notification 소개


용도

- 액티비티를 사용하지 않고 사용자에게 알리는 기능

- notification manager를 사용함

- 화면이 보이지 않는 앱 콤포넌트에서 주의 이벤트를 발생하는데 선호하는 방식이다.

기능

  > 새로운 상태바 아이콘 만들기

  > 확장 상태바 윈도우에서 추가 정보표시  (인테트 사용)

  > 불빛/LED 동작

  > 진동 알림

  > 가청 경보 울림


Notification Manager / 시스템서비스

- 레퍼런스는 콘텍스트의 serviceName을 인자로 사용하는 getSystemService()메소드를 통해서 얻는다.

- 용도: 새로운 알림을 만듬, 기존 알림을 수정할 수 있음, 기존 알림을 제거할 수 있음



사용방법

사용자 삽입 이미지


* 상기 내용중 noti.FLAG_SHOW_LIGHTS => Notification.FLAG_SHOW_LIGHTS로 정정함



01.String svcName = Context.NOTIFICATION_SERVICE;
02.NotificationManager notificationManager;
03.notificationManager = (NotificationManager)getSystemService(svcName);
04.

05.// 상태바 구성

06.int icon = R.drawable.icon;
07.String tickerText ="알림"
08.long when = System.currentTimeMillis();
09.Notification noti =new Notification(icon, tickerText, when);
10.

11.// 확장 상태바 윈도우 구성

12.Context context = getApplicationContext();
13.String expandedText ="확장 상태 텍스트";
14.String expandedTitle ="알림 제목";
15.Intent intent =new Intent(this, MyActivity.class);
16.PendingIntent launchIntent = PendingIntent.getActivity(context,0, intent,0);
17.noti.setLatestEventInfo(context, expandedTitle, expandedText, lauchIntent);
18.

19.// 상태바 반복 숫자 표시 구성

20.noti.number++;
21.

22.// 사운드 효과 구성

23.noti.sound = ringURI;
24.

25.// 진동 효과 구성

26.long[] vibrate =new long[] = {1000,1000,1000,1000,1000};
27.noti.vibrate = vibrate;
28.

29.// LED 효과 구성

30.noti.ledARGB = color.RED;
31.noti.ledOffMS =0;
32.noti.ledOnMS =1;
33.noti.flags = noti.flags | Notification.FLAG_SHOW_LIGHTS;
34.

35.// 확장 상태바 윈도우에 진행중 또는 강조 구성

36.noti.flags = noti.flas | Notification.FLAG_ONGOING_EVENT;
37.//noti.flags = noti.flas | Notification.FLAG_INSISTENT;
38.

39.// 상기 구성 내용 알림 발생 레퍼런스ID관리 필요

40.int notificationRef =1;
41.noticationManager.notify(notificationRef, noti);
42.

43.// 해당 레퍼런스 ID의 알림 취소, 상태바, 확장 상태바 윈도우 내용 삭제됨 단, 효과는 진행됨

44.noticationManager.cancel(notificationRef);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5. Alarm 소개



- 알람은 미리 예정된 시간에 인텐트를 발생키는 애플리케이션 독립적인 방법

- 애플리케이션 범위 밖에서 설정 가능BroadCast Receiver와 함께 Alarm이 조합 될 때 더욱 강력한 위력을 발휘한다.

  (BroadCast Receiver의 BOOT_COMPLETED를 설정하면 전원 재부팅시에 알람을 새로 시작시킬 수도 있다.)

- 활용: 애플리케이션을 실행시킴, 액션을 수행하는 알람을 설정할 수 있음
   > 알람 시계

   > 규칙적으로 네트워크 조회

   > 시간, 비용이 많이 드는 작업을 유후때 실행할 수 있도록 예약 할 수 있다.

- 설정의 유지 및 해제

  > 절전모드 일때도 알람은 활성화 되어 있다. (RTC, 백업배터리)

  > 절전모드에서 알람이 실행되어야 할때 WakeUp 여부를 선택할 수 있도록 설정할 수 있다.

  > 모든 알람은 전원 재부팅시 모두 소멸된다.


* 애플리케이션이 실행되어 있을 때는 알람을 사용하는 것보다는 Timer와 Thread를 사용하는 것을 권장한다.

  이것은 시스템 리소스를 더욱 잘 제어할 수 있기 때문이다.


- 핵심코드


1.alarms.set(alamType, timeOrLenghtOfWait, pendingIntent):

 > alarmType: 알람타입

 > timeOrLengthOfWait: 트리거시간

 > pendingIntent: 트기거될 때 발생시킬 대기 인텐트


- AlarmType: 트리거 시간의 종류가 wakeup여부에 따라서 4종류가 있다.

   > RTC

   > RTC_WAKEUP

   > ELAPSED_REALTIME

   > ELAPSED_REALTIME_WAKEUP


사용자 삽입 이미지

01.AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
02.

03.String MY_RTC_ALARM = “MY_RTC_ALARM”;

04.String ALARM_ACTION = “MY_ELAPSED_ALARM”;
05.

06.PendingIntent rtcIntent = PendingIntent.getBroadcast(this,0,new Intent(MY_RTC_ALARM),1);

07.PendingIntent elapsedIntent = PendingIntent.getBroadcast(this,0,new Intent(ALARM_ACTION),1);
08.

09.// Wakeup and fire intent in 5 hours.

10.Date t =new Date();t.setTime(java.lang.System.currentTimeMillis() +60*1000*5);
11.alarms.set(AlarmManager.RTC_WAKEUP, t.getTime(), rtcIntent);
12.

13.// Fire intent in 30 mins if already awake.

14.alarms.set(AlarmManager.ELAPSED_REALTIME,30*60*1000, elapsedIntent);
15.

16.// Cancel the first alarm.

17.alarms.cancel(rtcIntent);

알람을 반복해서 발생시키기

alarms.setRepeating(
AlarmManager.RTC_WAKEUP, //AlarmType,       특정시간에 깨워서라도 실행 시키고자 할때 그냥 하려면 RTC
System.currentTimeMillis(),     //triggerAtTime,   RTC로 하면 시간단이가 달라진다.  
1000,                                 //interval               알람 울림 간격            

pi                                     //PendingIntent            

);


상기의 것을 사용할 경우 너무 자주 깨어나면 아래 것을 사용한다.

 alarms.setInexactRepeating(type, triggerAtTime, interval, operation)
 - 정해진 시간에 실행되고 작업 수행시 종료된다.

 - 정해진 시간은 AlarmManager.INTERVAL_FIFTEEN_MINUTES을 거의 사용한다.






PAAD 11장 고급 안드로이드 개발  - 발표: 2010년 03월 10일(수) - 오후 07시 30분

11장 목차


  1. 편집증 환자, 안드로이드

    1. 리눅스 커널 보안
    2. 권한 소개 (Permission)
    3. 권한 선언과 적용하기
    4. 인텐트 방송에 권한 적용하기
  2. AIDL을 이용해 서비스를 위한 IPC 지원하기

    1. AIDL 인터페이스 구현하기

      1. 커스텀 클래스 객체 전달하기
      2. AIDL 정의 만들기
      3. IPC 인터페이스 구현하고 노출하기
  3. 인터넷 서비스 이용하기
  4. 리치 유저 인터페이스 구축하기

    1. 애니메이션으로 작업하기 (tweendanimation, frame by frame)

      1. 트윈드애니메이션 (소개, 만들기, 적용하기, 리스너)
      2. 레이아웃 뷰 그룹 애니메이션 (만들기, 이용하기)
      3. 프레임 바이 프레임 만들고 이용하기
    2. 애플리케이션에 테마로 스킨 입히기
    3. 고급 캔버스 그리기

      1. 캔버스
      2. 페인트 활용
      3. 투명 이용하기
      4. 셰이더 소개
      5. 그레이디언드 셰이더 정의하기
      6. 셰이더 타일 모드 이용하기
      7. MaskFilter 이용하기
      8. ColorFilter 이용하기
      9. PathEffect 이용하기
      10. Xfermode 바꾸기
      11. 앤티앨리어싱으로 페인트 품질 높이기
      12. 2D 그래픽스를 위한 하드웨어 가속
      13. 캔버스 드로잉 베스트 프랙티스
    4. 오버레이에생명력 불어 넣기
    5. SurfaceView소개

      1. 언제 SurfaceView을 이용해야 하나?
      2. 새로운 SurfaceView 컨트롤 만들기
      3. SurfaceView로 3D 컨트롤 만들기
  5. 인터랙티브한 컨트롤 만들기

    1. 터치 스크린 이용하기

      1. 터치 이벤트 처리
      2. 움직임 추적하기
    2. 장치 키와 버튼 이용하기 (D패드 포함)
    3. 트랙볼 이용하기


주요 용어: Permission, AIDL, tween Animation, layoutview group animation, thema, Canvas, SurfaceView, touch event, overlay
1. 편집증환자 안드로이드 / 권한 - Permission

1) 리눅스 커널 보안

샌드박스내의 리소스

01_sandbox.PNG 

안드로이드의 보안

 - 리눅스 커널에 기반한 보안 수준

 - 패키지 설치시 User ID부여. 이것으로 자기 영역을 부여 받고 보호 받는다.

 - 상호 프로세스, 리소스에 대한 사용 제한이 따르게 된다.


어플리케이션간 통신

 - 안드로이드 샌드박스로 격리된 프로세스간에 통신 기능을 제공한다.

 - BroadCast Intent, Service, Content Provider, AIDL이 이런 역할을 수행한다.


안드로이드 권한(Permission)

 - 통신 기능의 내용을 제어하기 위해서 시작과 끝점에서 Permission

을 점검하는 기능이 부여 되어 있다.


Permission이 점검 당하는 시점

- 시스템 내부로의 호출 시점

- 액티비티 시작 시점

- 브로드캐스트 보내는 시점

- 켄텐츠프로바이더 접근 시점

- 서비스 바인딩 시점 또는 시작 시점


 - 점검결과로 퍼미션에 적합하면 동작되고, 부적합하면 실행되지 않고, 알림도 없다 단지 log로는 남는다.

   부적합시에 일부 Exception이 발생될 수 있다.

2) 권한 - Permissions

2-1) 권한의 소개

사용자 삽입 이미지


데이터를 손상시키는 악의적인 애플리케이션, 민감한 정보에 대한 접근, 외부 통신 채널 또는 하드웨어 리소스 남용을 예방하는데 사용됨

- Native Component는 권한 요구사항을 갖는다.

  > android.manifest.permission 에서 네이티브 권한 문자열을 확인할 수있다. (앱에 별도로 지정된 것은 확인 안됨)

  > 이런 권한이 정의된 네이티브 컨포너트는 <uses-permission>을 사용해서 접근할 수 있다.


사용자 삽입 이미지

- androidmanifest.xml에 기술된 권하은 애플리케이션 설치 시점에 분석 표시 되며 설치 승인 및 거부를 할 수 있다.  

- 설치 시점에 권한 확인을 하고 나면 이후로는 해당 권한은 재평가 되지는 않는다.


사용자 삽입 이미지



2-2) 권한의 선언, 적용

다른 패키지들이 내 패키지내의 콤포넌트를 접근 제어하고자 할때 권한을 선언해서 사용할 수 있다.

권한 선언:

permission 태그를 사용해서 선언

사용자 삽입 이미지

  



   <permission

android:name=”com.paad.DETONATE_DEVICE”

android:protectionLevel=”dangerous”

android:label=”Self Destruct”

android:description=”@string/detonate_description”>

   </permission>


protectionLevel속성: 이 레벨을 설정에 따라서 사용자가 퍼미션을 요구하는 애플리케이션 알수 있거나,

해당 퍼미션이 누가 사용하는지 알수 있게 해 준다.

허가할 권한의 접근 수준: normal, dangerous, signature, signatureOrSystme

permissionGroup속성:

 선택 사항으로 단지 시스템이 사용자에게 퍼미션 표시를 돕기 위해서 사용된다.

 표준 시스템 그룹에서 정의한 사항을 표기하는 것이 좋다.

 직접 정의도 가능하다. 그렇지만 사용자에게 퍼미션UI를 단순화 하기 위해서 표준것을 사용하는 것이

좋다.



Lavel속성, Description속성:

 퍼미션 정의에 필수 사항이다.

 Lavel: 퍼미션 리스트에 나타나고, 퍼미션이 보호하는 기능의 핵심부분을 몇개의 단어로 기술할 것

 Desc..: 퍼미션 상세보기에 나타나고, 두문장으로 기술하는데

          첫번째문장은 퍼미션의 설명,

           두번째는 퍼미션 부여시 발생될 수 있는 나쁜 것이 무엇인지를 사용자에게 경고해 주는 내용을 기술한다.




아래 adb명령을 통해서 시스템의 퍼미션 정보를 볼 수 있다.


adb shell pm list permissions

 이 명령을 통해서 시스템에 현재 정의된 퍼미션들을 볼 수 있다.


adb shell pm list permissions -s

 -s 옵션은 사용자가 보는 방식과 같은 방식으로 볼 수 있다.

 




권한 적용:

권한 적용은 AndroidManifest.xml의 각 컴포넌트 태그내에 android:permission속성을 기술하면된다.

- Activity: 권한을 추가해 액티비티를 띄우는 다른 애플리케이션의 능력을 제어한다.

- BroadCast Receiver: 여러분의 수신자로 어떤 애플리케이션이 브로드캐스트 인텐트를 전송할 수 있는지 제어한다.

  > sendBroadcast(myIntnet, REQUIRED_PERMISSION);

- Contents Provider :  콘텐츠 공급자의 읽기 접근과 쓰기 작업을 제어한다.

   > android:readPermission, android:writePermission

  > URI퍼미션: 액티비티에게 그 인텐트 내의 특정 데이터 URI에 대한 접근 퍼미션을 부여한다.

- Service : 서비스 시작하거나 바인드하는 다른 애플리케이션의 능력을 제어한다.


   <activity

android:name=”.MyActivity”

android:label=”@string/app_name”

android:permission=”com.paad.DETONATE_DEVICE”>  //<== 나의 컴포넌트에 permission 속성과 권한 문자열 지정

   </activity>



그밖에 퍼미션 관련 기능

(해당 퍼미션이 부여되어 있는지를 정수 값으로 리턴해 준다.) - Context.checkCallingPermission()

   서비스를 호출할때 요구되는 퍼미션 문자열을 사용해서 호출한다.

- Context.checkPermission(String, int, int)

   이것은 다른 프로세스에 대해서 PID를 사용해서 그 프로세스의 퍼미션을 점검할 수 있다.
- PackageManager.checkPermission(String, String)
   앱의 패키지명을 알고 있을 때 사용한다.

2. AIDL을 이용해 서비스를 위한 IPC 지원하기

AIDL : Android Interface Definition Language

  •  서비스와 애플리케이션 콤포넌트간에 프로세스 간의 통신(IPC)을 지원하기 위한 안드로이드 인터페이스 정의 언어이다.
  •  이것은 Remote Call Procedure(RPC)로 COM이나 Corba와 비슷하다.
  •  Client와 Server사이의 값을 전달하기 위해 proxy클래스를 사용한다.
  •  두개의 프로세스간 통신 할 수 있도록 코드를 생성할 때 사용되는 IDL언어로 Java에도 IDL이 있고

       JDK의  jdk/bin/idl.exe을 통해서 인터페이스를 해석해 준다.

       이것을 Android에서는 AIDL로 정의하고 AIDL Tool을 제공한다.  

원리:

- IPC를 통해서 객체를 전달하려면 OS 수준의 기본요소(Primitive)로 해체할 필요가 있다.

  이렇게 해야지 하부 운영체제(OS)가 이를 애플리케이션의 경계 너머로 전달 할 수 있다.

- AIDL은 프로세스가 객체를 주고 받을 수 있도록 하는 코드를 단순화하는데 이용된다.

- 이 것은 프로세스간에 객체 매개변수를 받아 들이고 리턴하며,  

   값을 리턴할 수 있는 Public 메소드를 나의 서비스 내에 만들 수 있도록 해 준다.


AIDL 문법

- AIDL이 지원하는 Data Type

  • Primitive Java Data Type(import 불필요)
  • String, List, Map, CharSequence (import 불필요)
  • 다른 AIDL-generated interface (반드시 import 필요)
  • Parcelable protocol 을 구현한 클래스 (반드시 import필요)

- method : 매개변수가 0개 이상 / return 값: void or value

- 매개변수: primitive 값 또는 다른 AIDL로 정의된 parameter

- 매개변수 direction : 매개변수가 값 타입인지, 레퍼런스 타입인지 나타내기 위해 방향 태그가 필요함

                                  in / out / inout (primitive를 제외하고는 반드시 표기 필요 primitive default는 in임)

- 같은 패키지내 인터페이스라 하더라도 반드시 import를 해 줘야 한다.


커스텀 클래스 객체 전달하기

Parcelable인터페이스를 통해서 내 애플리케이션 클래스를 AIDL과 호환되도록 만든다.

- 객체를 프로세스간 경계를 넘어 마셜링될 수 있는 parcel내에 저장되는 기본 타임으로 분해 할 수 있도록 해준다.


작성 방법

 1) Parcelable객체를 상속받는 내 클래서를 만든다.

 2) writeToParcel메소드를 구현한다. : 클래스를 분해를 위해서 필요

 3) Parcelable.Creator객체 생성 : 들어오는 Parcel에 기반한 새로운 객체를 생성할 Public static필드

 4) describeContents()

 5) AIDL 정의 : 내 서비스에 대한 AIDL인터페이스 정의할 때 이용하도록 하기 위함

    (parcelable Quke; )


AIDL 정의 만들기

- aidl파일: 프로세스를 넘나들 수 있는 서비스를 위해서 정의하며, 서비스가 구현할 인터페이스에 포함될 메서드와 필드를 정의한다.

- AIDL문법에 준수해서 내용을 작성한다.

- 주의 사항으로는 매개변수 마샬링에는 비용이 많이들기에 각 매개변수의 방향을 제한해야 한다.


파일: IEarthquakeService.aidl

package com.paad.earthquake;

import com.paad.earthquake.Quake;

interface IEarthquakeService {

List<Quake> getEarthquakes();

void refreshEarthquakes();

}



서비스에서 IPC 인터페이스 구현하고 노출하기

- ADT플러그인은 .aidl파일이 저장되면 "자바 interface파일 코드"가 자동 생성되어진다.
- 이 인터페이스는 내부클래스인 stub을 포함하는데 추상클래스로 우리가 만드는 서비스에서 확장애서 실젱 작업할 내용을 넣어 놓는다.
- 구현된 기능과 인터페이스는 클라이언트에 정보를 노출해야 한다.
   이 방법은 해당 인터페이스의 인스턴스를 리턴하도록 onBind메서드에 재정의함으로 가능하다.

액티비티에서 IPC 서비스 이용하기

- IPC서비스를 바인드한다.
- ServiceConnection 클래스를 포함해서 onServiceConnected 메소드를 재정해서 사용한다.

AIDL 프로젝트의 클래스 구성도


사용자 삽입 이미지



AIDLServiceProject 생성

   (1) IMyService.aidl정의

   (2) AIDL툴에 의해 코드 생성 확인

   (3) IMyService.Stub클래스에서 Remote Service메소드 정의

   (4) MyService생성

        AndroidManifest.xml에 MyService를 등록

        AIDLClientProject 생성

   (5) IMyService.aidl정의

   (6) AIDL툴에 의해서 코드 생성 확인

   (7) ServiceConnection클래스 정의

   (8) Service Client 정의의


실행순서

   1) AIDLService 실행

   2) AIDLClient 실행


3. 인터넷 서비스 이용하기

  • 구글의 g데이터 서비스

  • 야휴! 파이프
  • 구글 앱 엔진
  • 아마존 웹 서비스

4. 리치 인터페이스 구축하기

4.1.1 트윈드에니메이션

소개:

 - 최소의 리소스 비용으로 깊이나 움직임 또는 피드백을 제공하기 위한 간단한 방법을 제공한다.

  (직접 캔버스에 다시 그리는 것에 비해 훨씬 쉽고 다소 리소스가 적게든다.)

 - 단일 리소스에 대해서 복수개의 인스턴스를 취급할때 여러 상태를 가질 수 있다.

  (Drawable을 사용할때는 한쪽의 인스턴스에 리소스의 상태 변형하면 다른쪽 인스턴스로 영향을 받음)


제공 가능한 효과:

 - 일련의 방향

 - 크기의 변화

 - 위치 이동

 - 불투명 변화


사용예:

 - 액티비티 간 전환

 - 액티비티 내에 있는 레이아웃 간 전화

 - 같은 뷰 내에 표시된 서로 다른 콘텐트 간 전환

 - 진행 상태를 표시하기 위한 모래시계 뷰 회전

 - 부정확하거나 유효하지 않은 데이터 입력을 표시하기 위한 입력 박스 흔들기


트윈드 애니메이션 만들기

사용자 삽입 이미지

 - 코드 방식


애니메이션시퀀스 (애니메이션, 애니메이션셋 모두 사용가능)

 - .setRepeatMode(): 값으로 RESTART(반복), REVERSE(앞뒤로 왔다 갔다)

 - .setRepeatCount(): 반복하고자 하는 숫자, 또는 INFINITE

 * 이 메소드를 사용하지 않을 경우 기본값으로 한 번 실행됨


 - 외부 리소스 방식

사용자 삽입 이미지


 * xml 파일 위치: res\anim\

 코드


 코드 방식  외부 리소스 방식
 

   // ---- Tweened animations

    // Create the AnimationSet

    animationSet = new AnimationSet(true);


    // Create a rotate animation.

    RotateAnimationrotate = new RotateAnimation(

           0, 360,                                                      RotateAnimation.RELATIVE_TO_SELF,0.5f,

           RotateAnimation.RELATIVE_TO_SELF,0.5f);

    rotate.setFillAfter(true);

    rotate.setDuration(1000);


    // Create a scale animation

    ScaleAnimationscale = new ScaleAnimation(

            1, 0,                                                         1, 0,                                                         ScaleAnimation.RELATIVE_TO_SELF, 0.5f,                        ScaleAnimation.RELATIVE_TO_SELF, 0.5f);

   scale.setFillAfter(true);

   scale.setDuration(500);

   scale.setStartOffset(500);


    // Create an alpha animation

    AlphaAnimationalpha = new AlphaAnimation(1, 0);

   scale.setFillAfter(true);

   scale.setDuration(500);

    scale.setStartOffset(500);


    // Add each animation to the set

    animationSet.addAnimation(rotate);

   animationSet.addAnimation(scale);

   animationSet.addAnimation(alpha);


    animationSet.setRepeatMode(Animation.RESTART);

    animationSet.setRepeatCount(Animation.INFINITE);

    myView.startAnimation(animationSet);  

 

 <?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android"

  android:shareInterpolator="true">

  <rotate

   android:fromDegrees="0"

   android:toDegrees="360"

   android:pivotX="50%"

   android:pivotY="50%"

   android:startOffset="0"

   android:duration="1000"

  />

  <scale

   android:fromXScale="1.0"

   android:toXScale="0.0"

   android:fromYScale="1.0"

   android:toYScale="0.0"

   android:pivotX="50%"

   android:pivotY="50%"

   android:startOffset="500"

   android:duration="500"

  />

  <alpha

   android:fromAlpha="1.0"

   android:toAlpha="0.0"

   android:startOffset="500"

   android:duration="500"

  />

</set>


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ImageView myView;
= (ImageView) findViewById(R.id.myViewId);
AnimationmyAnimation
= AnimationUtils.loadAnimation(this, R.anim.myXML);
myView.startAnimation(myAnimation);
 

style="line-height: 2em;">



애니메이션 리스너 이용하기 (애니메이션, 애니메이션셋 모두 사용가능)

 - 애니메이션이 시작하거나 끝날 때 호출 되는 이벤트 핸들러를 만들도록 해준다.

 - .setAnimationListener(new AnimationListener(){}

   > onAnimationEnd()    : 완료한 후

   > onAnimationRepeat() : 반복 시작 때

   > onAnimationStart()  : 새로 시작할 때



4.1.2 Layout과 View Animation만들기

소개

LayoutAnimation

 - View Group을 애니메니션하고 미리 결정된 순서에 따라서 각 자식 View 애니메이션(애니메이션셋)을 적용에 이용됨

LayoutAnimationController클래스: View Group에 있는 자식 View에 적용된 애니메이션을 지정한다.

 - LayoutAnimationController: 각 View의 시작 Offset값과 자식 View의 애니메이션 순서을 선택할 수 있다.

   (순서: Animation효과가 적용될 자식View순서 값: forward, reverse, random)

 - GridLayoutAnimationController: 격자 행과 열 레퍼런스를 이용해 자신 뷰의 애니메니션 순서를 지정


LayoutAnimation만들기

- 외부 리소스 방식

사용자 삽입 이미지


- 코드 방식

사용자 삽입 이미지


* .scheduleLayoutAnimation(): 강제적으로 ViewGroup을 다시 실행한다. (단 layoutAnimation이 설정되어 있어야 효과가있다.)

  ?? 이 애니메이션은 ViewGroup이 다음 번 배치될 때 실행 될 것이다. ?? 뭔소리??


LayoutAnimationListener

 - ViewGroup에 객체에 리스너를 부착할 수 있다. (콜백함수는 Animation리스너와 동일하다.)


코드


<!-- popin.xml-->

<set xmlns:android="http://schemas.android.com/apk/res/android"

  android:interpolator="@android:anim/accelerate_interpolator">

  <scale

   android:fromXScale="0.0" android:toXScale="1.0"

   android:fromYScale="0.0" android:toYScale="1.0"

   android:pivotX="50%"    

   android:pivotY="50%"

   android:duration="400"

  />

</set>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<!-- popinlayout.xml-->

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"

  android:delay="0.5"

  android:animationOrder="reverse"

  android:animation="@anim/popin"

 />

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

<!-- main.xml-->

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:id="@+id/layout"

  android:orientation="vertical"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  android:layoutAnimation="@anim/popinlayout"

  >

 ...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ViewGroup을 사용한 코드 방식

 LayoutAnimationControllerlayoutAni;

 layoutAni = AnimationUtils.loadLayoutAnimation(MyActivity.this, R.anim.popinlayout);

 viewGroup.setLayoutAnimation(layoutAni);




4.1.3 프레임 바이 프레임 애니메이션 만들고 이용하기

소개

- 프레임마다 이미지가 선택된 전통적인 셀기반 만화영화 기법과 가깝다.

- 프레임마다 백그라운드으로 사용되는 일련의 Drawable객체를 지정하고, 이것을 애니메이션 처리한다.


만들기

- XML draw 파일 만들기

  Item 태그를 사용해서 애니메이션될 실제 이미지와 표시될 시간을 정의한다.

  <item android:drawble="@drawable/rocekt1" android:duration="500"/>

  이것을 그룹화 animation-list 태그를 갖이 사용한다.

- .setBackgroudResource()를 사용해서 ImageView객체와 애니메이션(XML)을 배경으로 설정한다.

- .setBackgroudDrawable()을 사용해서 리소스 레퍼런스 대신 드로어블 인스턴스를 사용한다.

- 애니메이션의 start()메소드를 사용해서 애니메이션을 실행한다.



코드


<!-- animated_rocket.xml-->

<animation-list xmlns:android=”http://schemas.android.com/apk/res/android

android:oneshot=”false”>

<item android:drawable=”@drawable/rocket1” android:duration=”500” />

<item android:drawable=”@drawable/rocket2” android:duration=”500” />

<item android:drawable=”@drawable/rocket3” android:duration=”500” />

</animation-list>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ImageView image = (ImageView)findViewById(R.id.my_animation_frame);

image.setBackgroundResource(R.drawable.animated_rocket);

AnimationDrawable animation =
(AnimationDrawable)image.getBackground(); animation.start();


style="line-height: 2em;">

4.2 애플리케이션 테마로 스킨 입히기

소개

테마는 애플리케이션이 일관된 LookAndFeel을 나타내도록 보장하는 방법


적용방법

 - manifest.xml에 application, activity 태트내에 다음 내용을 기록한다.

   android:theme="@android:style/Theme.Light"

 - Theme.Black : 검은 배경에 하얀 전경 컨트롤 및 텍스트 사용한다.

 - Theme.Light : 하얀 배경에 어두운 테두리 및 텍스트를 사용한다.

 - Theme.Translucent : 부분적으로 투명한 폼을 사용한다.

4.3 고급 캔버스 그리기

캔버스?

 비티맵Bitmap이나 서피스Surface 오브젝트에 대한 실질적인 비트bit 컴포지션compositing을 처리하는 그리기를 하는 표면surface.

 canvas는 비트맵을 래핑하고 draw메서드를 노출한다.


그리기 기본 구성요소

 - Canvas: 하부에 있는 비트맵에 그리기 기본요소를 칠하는 그리기 메서드 제공

 - Paint : "브러시"라고도 불리며 Paint는 기본요소가 비트맵 위에 어떻게 그려지는지 지정할 수 있도록 함

 - Bitmap : 그리기가 수행되는 표면

사용자 삽입 이미지

 


안드로이드 그리기 API

 - 비트맵, 원, 선, 사각형, 텍스트

 - 둥근 모서리 사각형

 - 투명도

 - gradient fill

 - anti-aliasing

 * 백터 그래픽스는 지원하지 않음

 * 전통적인 래스터 스타일의 다시 그리기 이동


Canvas와 Paint의 관계


사용자 삽입 이미지






canvas.drawXXX(): 이것을 사용하여서 화면에 실제 그린다.



 drawARGB 캔버스를 한가지 색으로 칠한다
 drawRGB 캔버스를 한가지 색으로 칠한다.
 drawArc

사각형 경계 영역 내에서 두 각 사이의 호를 그린다.

 drawBitmap 캔버스에 비트맵을 그린다. 대상 크기를 지정하거나 변형을 위한 매트릭스를 이용하면 겉모습을 변경할 수 있다.
 drawBitmapMesh 매시를 이용해 비트맵을 그린다. 매시는 매시 안에 있는 점을 이동함으로써 대상의 겉모습을 조작할 수 있다
 drawCircle 주어진 점을 중심으로 지정된 반지름 크기의 원을 그린다.
 drawLine 두 점 사이에 선(혹은 일련의 선)을 그린다.
 drawOval 지정된 사각형을 경계로 하는 타원을 그린다.
 drawPaint 캔버스 전체를 지정된 페인트로 칠한다.
 drawPath 지정된 패스를 그린다. Path객체는 종종 그리기 기본요소 집합을 하나의 객체안에 담는데 이용한다.
 drawPicture 지정된 사각형 안에 Picture객체를 그린다.
 drawPosText 각 문자의 오프셋을 지정하는 텍스트 문자열을 그린다.
 drawRect 사각형을 그린다.
 drawRoundRect 둥근 모서리를 가진 사각형을 그린다.
 drawText 캔버스 위에 텍스트 문자열을 그린다. 텍스트 폰트, 크기, 색상, 랜더링 속성은 모두 Paint객체에서 설정한다.
 drawTextOnPath 지정된 패스를 따라 텍스트를 그린다.
 drawVertices 일련의 정점들로 지정된 여러 삼각 패치를 그린다.
 drawColor 캔버스를 한가지 색으로 칠한다.



Paint 활용하기

paint클래스는 페인트브러쉬와 팔레트를 표현한다.

Paint객체를 수정해서 그릴때 이용되는 색상, 스타일, 폰트, 특수효과(투명,세이더,필터 등)를 제어할 수 있다.


.setColor() : 페인트 색상선택

.setStyle() : 객체의 윤곽, 일부을 채우고 등의 작업

.parseColor(): 해당 색상을 투명하게 처리

.setAlpha() : 불투명 처리

.setShader() : 솔리드 색상으로 칠해준다. 세이더의 가장 흔한 것으로 그레디언트로 채움은 것

 참고: ComposeShader, BitmapShader, GradientShader

.setMaskFilter(): 모서리에 알파채널변화로 효과주기. (BlueMaskFilter, EmbossMaskFilter)

.setColorfilter(): RGB채널 변화로 효과 주기(이것은 알파채널을 무시한다.)

 참고: ColorMatrixColorFilter, LightColorFilter, PorterDuffColorFilter

.setPathEffect(): 그리는 방법을 제어한다. 도형의 모서리 모양을 바꾸거나, 윤곽선을 제어한다.

 참고: CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect, ComposePathEffect

.setXfermode(): 캔버스에 이미 그려진 것 위에 새로 칠하는 방법

 참고: AvoidXfermode, PixelXorfermode, PorterDuffXfermode

.setSubpixelText() : 그려지는 사선을 부드럽게 하기 위해 안티앨리어싱을 적용해 준다. (성능이 떨어뜨릴 수 있음)

.setAntiAlias() : 그려지는 사선을 부드럽게 하기 위해 안티앨리어싱을 적용해 준다. (성능이 떨어뜨릴 수 있음)


2D 그래피스를 위한 하드웨어 가속

- HW설정하기 : 2D 그래픽랜더링을 위해서 HW가속기를 사용하자.

  myActivity.requestWindowFeature(Window.FATURE_OPENGL);

- 이 효과에 해당되지 않는 요소 존재한다. 특히 Path가 해당하지 않는다.

- invalidate()는 캔버스 랜더링을 새로 하도록 한다.00


캔버스 드로잉 베스트 프랙티스

- 하드웨어 가속을 고려해라 : 추천한다.

- 크기와 방향을 고려해라 : 뷰와 오버레이 만들때 해상도와 크기에 대한 고려를 해야 한다.

- 객체는 정적으로 한 번만 만들자 : 객체 생성 비용이 매우 비싸다. 페인트, 패스, 세이더는 한번 만들어서 계속 사용

- onDraw는 비싸다는 사실을 기억해라 : 캔버스를 다시 그리는 일을 최소화 한다. 아래 3가지가 팀이다.

- 캔버스 변환을 이용해라 :캔버스내의 엘리먼트를 수정하지 말고 캔버스를 변환하도록 하라.

- 애니메이션을 이용해라 : 뷰를 직접 그리기 보다는 미리 정의된 애니메이션을 이용해라

- 비트맵과 나인패치를 이용해라: 이미지 정적이용시 직접 그리기보다는 이것을 사용하라.


맵 오버레이에 생명력 불어넣기

- Skip합니다.


4.5 SurfaceView 소개

SurfaceView 소개

 - SurfaceView는 뷰 계층 구조 내에서 드로잉 전용 공간을 제공하는 뷰에 대한 특수한 서브클래스 이다.

 - 그 목적은 시스템의 뷰 계층 구조가 그릴 준비가 될 때까지 애플리케이션이 기다리지 않도록 하기 위해

   애플리케이션의 보조 쓰레드에게 이러한 드로잉 공간을 제공하는데 있다.

 - 이 것은 View파생 클래스와 정확히 동일한 방식으로 이동한다. (애니메니션, 레이아웃 등 사용 가능)

 - Canvas 메소드를 이용한 대부분의 지원하며, OpenGL ES 라이브러리를 완벽히 지원한다.


용도:

 - 이것은 리소스가 많이 들거나 빠른 업데이트, 높은 프레임 속도를 요구할 때 특히 유용하다.

 - 단, 메모리의 소비가 발생될 수 있기에 사용시 신중을 기해야 한다.


사용예:

 - 구글 어쓰

 - 인터렉티브 게임에 탑재된 3D 이미지 표시

 - 실시간 카메라 미리보기


SurfaceView 컨트롤 만들기

주요 코드 설명

SurfaceHolder.callback:

 - 상속받은 나의 클래스에는 실제 SurfaceView가 있지 않다 이 SurfaceHolder를 통해서 연결되지고

 - 기반이 되는 서피스의 생성, 변경, 종료에 대한 이벤트를 알려 주는 인터페이스

 - 이것은 서피스의 이벤트를 Callback형태로 제공해서 내가 언제 drawing할지 알게해준다.

getHolder(): surfaceHolder 얻어 온다.

 holder.addCallBack(this) : 내가 만든 객체가 SurfaceHolder 콜백을 수신하고자 한다는 것을 SurfaceHolder에게 알림

 surfaceHolder.lockCanvas(): 서피스를 잠그고 그리기 위한 캔버스를 리턴 받는다. 이제 우린 그릴 캔버스를 확보한 것이며,

 이 캔버스는 이전 상태를 갖고 있기에 drawColor()로 초기색으로 변경하거나, drawBitmap()로 배경을 재설정해야할 것이다.

 sufaceHolder.unlockCanvasAndPost(): 캔버스 락을 풀고 현재 이미지를 랜더링한다.  


CallBack 메소드

 init(): 새로운 SurfaceHolder를 만들고 이 클래스를 SurfaceHolder의 콜백으로 지정한다.

 resume(): 그래픽 업데이트 스레드를 만들기 시작한다.

 pause(): 그래픽스 업데이트 스레드를 종료한다.

 surfaceCreated(): 인너 클래스의 child Thread를 실행한다.

 surfaceDestroyed(): 서피스를 종료을 위해서 pause()를 호출한다.

 surfaceChanged() : 서피스의 크기변경에 대응하는 메소드


MySurfaceViewThread

  - 인너클래스로  실제 작업을 수행하는 Child Thread와 Canvas Draw를 처리하는 메소드를 포함한 클래스

  run(): 오버라이드해서 스레드가 정지될 때까지 드로잉 루프를 반복한다.

  requestExitAndWait() : 스레드를 완료 상태로 표시하고 join()를 통해서 메인 스레드에 결합한다. (실제 화면에 그려진다.)

  onWindowResize() : 서피스 크기 변화를 준다.


사용자 삽입 이미지

 

 * OpenGL ES를 사용한 SurfaceView 3D 컨트롤은 APIDemo의 GLSurfaceView를 참조할 것.


public classMySurfaceViewextendsSurfaceViewimplementsSurfaceHolder.Callback {

  private SurfaceHolder holder;
  private MySurfaceViewThread mySurfaceViewThread;
  private boolean hasSurface;

MySurfaceView(Context context) {
    super(context);
    init();
  }
 
  private void
init() {
    // Create a new SurfaceHolder and assign this class as its callback.
    holder =
getHolder();
    holder.
addCallback(this);
    hasSurface = false;
  }

  public voidresume() {
    // Create and start the graphics update thread.
    if (mySurfaceViewThread == null) {
mySurfaceViewThread= newMySurfaceViewThread();

      if (hasSurface == true)
mySurfaceViewThread.start();
    }
  }

  public voidpause() {
    // Kill the graphics update thread
    if (mySurfaceViewThread != null) {
      mySurfaceViewThread.
requestExitAndWait();
      mySurfaceViewThread = null;
    }
  }

  public voidsurfaceCreated(SurfaceHolder holder) {
    hasSurface = true;
    if (mySurfaceViewThread != null)
mySurfaceViewThread.start();
  }

  public voidsurfaceDestroyed(SurfaceHolder holder) {
    hasSurface = false;
pause();
  }

  public voidsurfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if (mySurfaceViewThread != null)
      mySurfaceViewThread.
onWindowResize(w, h);
  }

  //--------------------------------------------------------------------------

  classMySurfaceViewThreadextendsThread{
    private boolean done;

MySurfaceViewThread() {
      super();
      done = false;
    }

    @Override
    public void
run() {
      SurfaceHolder surfaceHolder = holder;
     
      // Repeat the drawing loop until the thread is stopped.
while(!done) {
        // Lock the surface and return the canvas to draw onto.
        Canvas
canvas=surfaceHolder.lockCanvas();

        // TODO: Draw on the canvas!

        // Unlock the canvas and render the current image.
surfaceHolder.unlockCanvasAndPost(canvas);
      }
    }

    public voidrequestExitAndWait() {
      // Mark this thread as complete and combine into
      // the main application thread.
done= true;
      try {
join();
      } catch (InterruptedException ex) { }
    }

    public voidonWindowResize(int w, int h) {
      // Deal with a change in the available surface size.
    }
  }
}



 

5. 인터랙티브한 컨트롤 만들기


사용자 삽입 이미지


Touch Key Event

 - onTouchEvent()

 - Start, Move, End

 - RawX, RawY  X, Y

 - getPressure() 터치의 정도의 정보도 확보 가능함 (0:압력 없음, 1:보통압력)

 - getSize() 접촉면의 정규화 크기를 측정할 수 있다. (0: 매우 정밀 1:굵은 터치)

 - getHistory() 움직임을 추적을 도와 준다. 과거의 값과 현재 발생된 모든 이벤트 저장

 - getHistorical*() 위치 인덱스를 주면 각각의 시간, 압력, 면적, 위치를 얻을 수 있다.

 - Sample 예제: FingerPaint

Key Event

 - onKeyup(), onKeyDown()

 - Down, Up, Repeat(?)

 - 포함되는 키: 키보드, D패드, 볼륨, 뒤로가기, 전화걸기, 전화끊기

 - 미포함 키: 홈 (하나의 앱에 묶이지 않게 하기 위해 용도를 예약한 것 때문임)

 - keyCode메개변수: 눌려진 키 값

 - keyEvent매개변수: 특정키의 수행을 돕기 위해서 기능, 시프트, 심벌메타키를 감지하는 메서드 제공

   또한 KeyDown,KeyUp도 감지한다.

TrackBall Event

 - onTrackballEvent()

 - MotionEvent매개변수 : 마지막 트랙볼의 움직임에 대한 상대적인 움직임 값을 x, y로 제공

 - D패드를 사용해도 동일한 움직임을 나타낸다.(??)


리스너 부착해서 이용하기

 - 해당 뷰에 .set*Listener를 사용하면 서브클래싱하지 않아도 된다.


'Android > Tip&Tech' 카테고리의 다른 글

안드로이드(android) ListView + ArrayAdapter ANDROID  (0) 2010.11.04
listview에 버튼넣기  (0) 2010.11.03
AIDL이 뭘까나?  (0) 2010.11.03
안드로이드 서비스 팁  (0) 2010.11.03
Sending SMS Messages  (2) 2010.11.03

+ Recent posts