3일차 정리
1. Adapter 
   : Adapter 역시 widget이다. Adapter는 여러가지 view에 맞게 설정하여 사용할 수 있다.
2. Layout : LinearLayout, TableLayout등 다양한 레이아웃이 있다.    
3. Custom View 
    - onDraw[UI], onMeasure[Size], onTouchEvent[Event] 를 신경써서 만든다.


어제에 만든 Custom View에 이벤트를 달아보자.

1. View의 Observer들을 등록해서 사용할 수 있도록 Interface 클래스를 만든다.
2. CustomView는 Interface를 상속받아 이벤트를 정의한다.

메뉴(p140)
    메뉴는 일종의 버튼과 같은 기능으로 모바일 장치에서 볼 수 있는 아래에 메뉴와 같은 기능이다. 안드로이드에서는 작은 화면에 최적화 된 3단계의 메뉴를 제공하고 있다.
  1. Icon Menu
     - 화면아래에서 나오는 메뉴. 
     - 최대 6개의 메뉴를 지원한다.(3단으로 두줄)
  2. 확장 메뉴
     - 6개 이상의 메뉴를 리스트 성격으로 보여주는 메뉴
     - 아이콘은 사용할 수 없다.
  3. 하위 메뉴(Sub Menu)
      - 하위 메뉴를 붙여서 사용할 때
* 추가적으로 Context Menu가 있다. Context Menu는 특정 View를 3초이상 눌렀을때 뜨는 메뉴이다.

일반적으로 Menu, MenuItem, SubMenu 클래스로 동작 시킬 수 있다.Menu는 Menubar의 성격을 지니며 MenuItem은 하나의 항목이다. SubMenu는 하위 메뉴 클래스로 이들은 직접 생성하지 않고 Activity의 메서드를 이용하여 만들 수 있다. 메뉴를 붙이기 위해서는 onCreateOptionMenu를 오버라이드 받아서 작성한다. 

onCreateOptionMenu(Menu m){
// 그룹아이디, item 아이디. 순서, 등을 설정한다.
m.add(groupid, menuitemID, order, text)
m.add(...)
}

메뉴에서 Event를 등록해 사용하기 위해서는 두가지 방법을 이용할 수 있다. 

1. MenuItem에 Event Listener를 연결:
      onCreateOptionMenu에서 Menu를 생성하고 각 Itme에 이벤트를 달아서 처리한다.
2. Actitivity 의 Method 이용 :
      onOptionMenuSelected()를 오버라이드 해서 사용. 메뉴의 어떤 것이 눌려도 이 함수가 호출되며, 파라메터로 전달되는 메뉴의 ID를 이용하여 제어한다.


동적으로 메뉴 항목 업데이트 하기
   Activity의 onPrepareOptionsMenu는 화면에 뜰 때마다 반복적으로 불리운다. 이를 이용하여 동적으로 프로그램할 수 있다.

컨택스트 메뉴(p148)
   -  View 자체에서 지원하는 방법과 Activity에서 사용하는 두가지 방법이있다.

<예제> 메뉴 만들기
메뉴 키를 누르면 메뉴를 뛰우고 팝업 창을 뒤우도록 만들어 보자.


1. 메뉴를 위한 상수를 선언한다.

2. Activity의 onCreateOptionsMenu와 onMenuItemSelected 를 오버라이드 받아 작성한다.
   2.1 onCreateOptionMenu
     # 그룹은 설정하지 않고 메뉴를 식별하기 위해 선언한 아이디 MENU_POPUP, MENU_DATA을 설정한다.
     # 메뉴에 보이는 글자는 PopUp과 Data다.

   2.2 메뉴가 눌렸을 때 동작을 위하여 onMenuItemSelected를 오버라이드 한다.
    # 파라메터로 넘어오는 MenuItem을 이용하여 어떤 버튼이 눌렸는지 확인하고 그에 따라 동작을 수행하도록 작성한다.
 
  # Context는 Android에서 선언한 상위 class이다. onClick에서 이너클러스에서 context는 this를 알수가 없으므로 상위 클래스의 context를 넘겨주어야 한다. 즉, onMenuItem...을 상속 받아 사용한 class 이름의 this를 넘겨준다. (Context에 대해 좀더 알아보자!!!)

소스파일:

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

1. Intent
  인텐트는 컴포넌트와 컴포넌트를 연결하기 위해 사용하는 메세지 전달 메커니즘이다. 이는 컴퍼넌트를 연결하기위해 안드로이드 시스템내에 인텐트를 발생시켜 실행 시키는 것이다. 4개의 컴포넌트 (Activity, BroadcastReceiver, ContentsProvider, Service) 중에서 ContnentProvider를 제외한 컴포넌트들은 인텐트로실행 시킬 수 있다.

데이터를 보내는 쪽(class A)에서는 Intent 객체를 선언하고 받는 쪽 클래스(class B)를 파라메터로 넘겨주면 된다.
 
Intent i = new Intent(this, B.class);
// 데이터를 넘기고 싶을 때는 i.putExra 등을 사용한다.
StartActivity(i);

인텐트를 받은 쪽인 B Class에서는 onCreate, onResume이 불리우게 되고, Intent 객체를 얻기 위해서는 getIntent를 사용하여 객체를 얻어간다.

Intent i = getIntent();
i.get..(key);

인텐트를 받은 B class에서 하던일을 마치고 보낸 A class를 다시 실행하려면 보내는 A class에서 StartActivityForResult()로 인텐트를 넘겨 주어야 한다.(백 버튼을 눌러 돌아가는 것과는 차이가 있다)
StartActivityForResult(i, RequestCode);   // RequestCode는 ID 값으로 볼 수 있다.

이렇게 받은 B class에서는 finish() 를 호출하면 이전 class로 돌려 줄 수 있다.
finish(resultCode)로 마치면 A class에서는 onResultActivity 함수가 호출이 된다. 이때 ResultCode로 B class에서 보낸 인테트를 구별하기 위해서 ResultCode를 사용한다. 그리고, resultCode를 통해 실패, 성공 등의 결과 상태를 알려 줄 수 있다. class A에서는 이정보를 이용하여 결과를 처리해 준다.

onResultActivity(intent, RequestCode, resultCode);

그럼, 우리가 모르는 수 많은 다른 클래스를 사용하려면 어떻게 해야하는가?

* 인텐트를 호출하는 방법에는 명시적 인텐트 와 암시적 인텐트가 있다.
   - 명시적 인텐트: 대상 컴퍼넌트의 클래스 명을 직접 명시. 
   - 암시적 인텐트: 클래스 명을 명시하지 않는다. 인텐트를 생성할 때 intent-filter 정보를 설정한다.
< 매니페스트 파일에 설정된 인텐트 필터>       

intent-filter는 매니페스트에 등록이 되어 있는 정보로 action, category, data 정보를 가지고 있다. 암시적 인텐트는 이러한 인텐트 필터를 사용하여 Activity를 실행한다. 필터리하는 순서는 action, category, data 순서로 진행한다.

action을 어떠한 서비스를 제공하는지에 대한 설명을 제공하며, 지정하려면 android:name 속성을 이용한다. 문자열로 사용한다. action은 여러개 지정할 수도 있다. action을 지정하지 않으면 다음 필터로 통과되어 진다. 네이티브 안드로이드 액션은 교재 p169 에서 확인할 수 있다.

category는 서비스되어야 하는 상황 조건을 지정하는 문자열이다. 사용자가 임의로 정하기도 하지만 android에서 지정해놓은 것을 많이 사용하고 지정하지 않는 경우도 많다. category를 셋팅하지 않으면 DEFAULT로 설정되어 있다(매니페스트에는 반드시 선언되어있어야 한다.)

data는 자기가 서비스 할수 있는 데이터 형태를 선언한다. 

안드로이드가 인텐트 필터를 해결하는 방법(p173)

* Linkify 소개(p163)
클래스 안에 자동으로 링크를 걸어 실행 할 수 있도록 도와주는 클래스이다. 웹, 이메일, 폰형식 을 기본으로 지원하고 있으면 문자열 패턴을 등록하여 사용할 수 있다.

<예제> 인텐트를 발생시키기.
1. Activity1를 만들고 button을 누르면 Activity1으로 이동하도록 하자.
   - 이때 다시 Activity1의 버튼을 누르면 Main으로 돌아가도록 하자.
<메인 화면>

<Activity1 화면>

2. 암시적 인텐트를 사용해서 동작 시켜 보자.
3. 네이티브 액티비티인 전화걸기를 시작시켜 보자.

1. 프로젝트를 새로 시작한다.
  - 새로 만든 프로젝트의 엑티비티를 Main.java라 하고, 매니페스트에서 Activity하나를 추가 한다.
  - 각각에 필요한 버튼을 추가 한다. Activity1에서 사용할 layout 파일(activity1.xml)파일도 추가한다.
<main.xml>
  - activity.xml도 똑같이 작성하고 버튼의 id 만 activity_button으로 수정하자.

2. Main.java 에 버튼 이벤트시 동작을 추가 한다.
<버튼을 만들고 이벤트를 등록 한다.>

 3. Main.java에서 onClick 함수를 오버라이드 해서 Intent를 발생 시킨다.
<메인의 온클릭>
  3.1 명시적으로 Activity1 을 액티비티 시킨다. 이때 intent에 데이터를 넘길수 도 있다.
      - startActivity를 사용하면 결과를 받지 않고 돌아오지 않는다.
      - startActivityForResult면 결과를 돌려받아 다시 Main을 뛰운다.

  3. 2 암시적인 처리를 위해서는 매니페스트 파일에 반드시 intent-filter를 설정해 주어야 한다.      
     - 예제를 위해서 intent-filter를 다음과 같이 설정해준다.
     - category에 DEFAULT를 주지 않으면 에러가 발생한다.
<Activity1의 intent-filter 설정>
  3.3 전화를 걸기 위해서는 ACTION_CALL 액션을 주고 데이터에 uri를 설정하여 던져주면 된다.

# 인텐트 한줄이면 전화도 걸수 있고, 주소록 , 웹서치등도 할수 있다. .....정말 간편하다...

4. Activity1.java에서는 Intent를 받아서 처리하는 코드를 작성해준다.
   - 버튼도 추가해서 결과 값을 돌려 줄수있도록 해보자.
< Activity1.java에서 intent 처리하기>

# 이외에도 전화번호부, 웹서치, 지도 보기 등 인텐트 호출 방법은 소스에서 확인하자.
소스 코드:
  - broadcast message에 의해 동작할 컴포넌트다. 브로드캐스트는 메세지를 받는 용도로만 사용해야한다.
  - 10초 이상의 메세지를 처리하고 있으면 시스템에서 에러를 발생 시킨다. 즉, 이벤트를 전달하고 인텐트를 발생 시키는 목적으로만 사용한다. 
  - 브로트케스트를 발생 시키고 싶으면 인텐트를 생성해서 sendBroadcast(intent)를 호출하면 된다.(p185)
  - 안드로이드에서는 브로드케스트용 인텐트 액션을 따로 정의 해놓고 있다.
  - 브로드캐스트 리시버를 만들려면 BroadcastReceiver 클래스를 상속 받아서 만들면 된다.
  - 오버라이드 해야하는 메서드는 onReceiver 하나 이다.

<예제>부팅이 완료되면 애플리케이션이 실행 되도록 해보자.

1. 매니페스트 파일에 리시버를 하나 추가 하고 인텐트 필터 액션을 추가해준다.
    - 부팅이 완료 되었을 경우 퍼미션을 추가 해주어야 한다.(use-permission)

    - 매니패스트에 인턴트필터를 추가해준다. 

    - 메니페스트 마법사에서 어플리케이션탭에서 리시버를 추가하고 액션을 추가해서 만들어준다.
    - 클래스는 MyReceiver
    - 생성된 자바에 다음과 같이 코드를 추가해 보자.
  
 - 부팅되면 Activity1을 바로 실행한다. 애뮬레이터를 종료했다가 다시 시작해보자.
                     

Posted by 빨간 양말