[Android] HTML 읽기 Android 2012. 3. 7. 11:35

http 통신은 다들 잘 알 것이다. 모바일 상에서는 java.net을 이용하여 이 내용을 사용하는데 get과 post가 자유롭다고 한다.

http 는 url을 통하여 데이터를 전송하는데 url 클래스 인자는 다음과 같이 두가지가 있다

URL(URL context, String spec)과 URL(String protocal, String host, int port, String file) 이다.

다음은 URL의 각 부분을 분리하는 메서드들이다.

메서드 리턴  설명 
String getProtocal() http  통신 프로토콜 
int getDefaultPort() 80 디폴트 포트 
int getPort() -1 URL의 포트, 없을 시 -1 
String getHost() www.url.com 서버주소
String getFile() /data?param=1 path와 쿼리
String getPath() /data 서버 경로
String getQuery() param=1 서버 전달 쿼리 변수 값

접속하는 주소가 정해지면 URLConnection 객체를 통해서 접근한다. 여기에 대한 메서드들은 다음과 같다.

메서드 설명 
setConnectTimeout(int timout) 연결 제한 시간을 1/1000 단위로 지정, 0일 경우 무한
setReadTimeout(int timeout) 읽기 제한 시간 지정, 0일 경우 무한
set UseCaches(Boolean flag) 캐시 사용 여부 지정
setDoInput(boolean flag) 입력 지정
setDoOutput(boolean flag) 출력 지정
setRequestProperty(String field, String value) 요청 헤더 값 설정
addRequestProperty(String field, String value)  헤더 속성 값 추가

다음은 간단히 HTML을 읽어오는 코드이다.

public class ImageViewActivity extends Activity{
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  Button r_btn = (Button)findViewById(R.id.read);
  r_btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    String html = DownloadHtml("http://google.com");
    EditText edit = (EditText)findViewById(R.id.edit_txt);
    edit.setText(html);
   }
  });
 } 
 private String DownloadHtml(String string) {
  StringBuilder html = new StringBuilder();
  try{
   URL url = new URL(string);
   HttpURLConnection connect = (HttpURLConnection)url.openConnection();
   if(connect!=null){
    connect.setConnectTimeout(1000);
    connect.setUseCaches(false);
    if(connect.getResponseCode()==HttpURLConnection.HTTP_OK){
     BufferedReader br = new BufferedReader(new InputStreamReader(connect.getInputStream()));
     for(;;){
      String line = br.readLine();
      if(line==null) break;
      html.append(line+'\n');
     }
     br.close();
    }
    connect.disconnect();    
   }
  }
  catch(Exception ex){}
  return html.toString();
 }
}

위에서 자바 코드를 썼지만 아파치 라이브러리를 이용하려면 다음과 같이 DownLoadHtml 부분을 바꿔 주면 된다.

HttpGet http = new HttpGet(string);
  DefaultHttpClient client = new DefaultHttpClient();
  String temp = "";
  try{
   HttpResponse response = client.execute(http); 
   String line = "";
   BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
   while((line=br.readLine())!=null){
    temp+=(line+'\n');
   }
   br.close();
  }
  catch(Exception ex){}
  return temp;

위에서 보면 메서드들을 이용해서 헤더를 통하여 오라클이나 타 데이터 베이스와도 통신이 가능 할 것이란 것을 추측 할 수 있다. 시간 나면 나중에 해 봐야겠다.

연결 관리자는 네트워크에 대한 정보를 조사하며 현재 상태와 연결 상태 변경 시 인텐트를 통하여 전체적으로 알려준다.

기본적으로 getSystemService(CONNECTIVITY_SERVICE) 를 통하여 그 정보를 얻으며 ConnectivitiManager로 리턴이 된다.

다음은 그 내용에 대한 간단한 내용을 확인 할 수 있는 코드 이다.

public class ImageViewActivity extends Activity{
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  EditText edit = (EditText)findViewById(R.id.edit_txt);
  String temp = "";
  ConnectivityManager manager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo[] info1 = manager.getAllNetworkInfo();
  for(NetworkInfo n_info : info1){
   temp+=(n_info.toString()+"\n\n");
  }
  NetworkInfo info2 = manager.getActiveNetworkInfo();
  temp+=("Active : \n" + info2.toString()+"\n");
  edit.setText(temp);
 } 
}
여기서 하나 명심 할 것은 웹뷰를 이용 할 때와 같이 매니페스트 파일에 permission을 추가 해 줘야 한다.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


[Android] Thread Android 2012. 3. 6. 17:52
스레드는 한번에 여러개의 작업을 할 수 있다는 것을 프로그래머라면 다들 알 것이다. 프로세스 보다 작은 작업 스케쥴러임을..

생성 방법은 자바랑 별 차이가 없다.

class Thread extends Thread{
     public void run(){
     }
}
라는 클래스를 만들어 주고 그냥 돌리면 된다. 하나 차이가 있다면 setDaemon 을 이용하여 백그라운드에서 데몬처럼 이용하는지를 지정 할 수 있다.

다른 방법으로도 동일한게 있다. 바로 Runable을 확장해서 사용하는 방법이다.

class Thread implements Runable{
     public void run(){
     }
}

여기까지는 자바를 해 본 사람들이라면 다들 알 것이라 생각한다.

하지만 어떤 컴포넌트에 접근해서 쓰레드 안에서 접근하려면 오류가 난다. 이는 크로스 쓰레드 문제라는 것을 다들 알 것이다.

이를 해결하려면 자바에서 이용했던 핸들러 객체를 이용하면 된다.

Handler handler = new Handler(){
   public void handleMessage(Message msg){
   }
}

메세지를 구분하려면 msg.what 을 이용하면 된다.

위와 같이 구현 한 후 호출하는 부분에서 sendEmptyMessage와 같이 이용해서 접근 해야한다. C#에서 친다면 대리자를 이용한 Invoke 를 이용한 것이다.

또 다른 방법으로는 post를 이용하는 방법이다. 사용 방법은 아래와 같다. 단 핸들러 객체는 반드시 생성 해 둬야한다.

handler.post(new Runable(){
   public run(){
    }
});

핸들러로 메세지 전달하는 방법에도 안드로이드는 좀 신기 한 듯 하다.

Message 객체를 생성해서 obtain을 이용해서 넣을 수 있다.

Message msg = Message.obtain();
msg.what = value
msg.arg1 = value
처럼 한 후 sendMessage를 이용하여 핸들러에 전달한다. 여기서 arg1은 하나의 값, 하나를 더 보내자면 arg2를 해서 전달하면 된다.
다른 인자 값으로는 핸들러, what, arg1, arg2, obj 가 들어가는데 이들 형식은 핸들러를 제외하고 3개는 int 마지막 하나는 obj 타입이다.
그리고 recycle 메서드가 있는데 이놈은 다시 한번 메세지 풀에 다시 집어 넣는다. 하지만 이후 접근해서는 안된다.

또한 루퍼(Looper) 라는 것이 있다. 루퍼는 메세지를 전달 해 주는 역할을 한다.

prepare()를 이용하여 루퍼를 준비하고 loop()를 이용하여 실행한다. 이는 quit()가 실행 될 때 까지 작업을 한다.

루퍼를 구현하는 함수는 다음과 같다.

Thread getThread() - 현재 연결된 스레드 가져옴

static Looper getMainLooper() - 메인 스레드 루퍼 구현

static Looper myLooper() - 현재 스레드의 루퍼 구현

또한 스케쥴링에 의한 제어도 가능하다. 모두 어떤 프로세스를 실행 했을 때 어느정도 딜레이가 되거나 데이터가 제때 완료되어 나오지 않음을 경험 한 적이 있을 것이다.

안드로이드는 쓰레드 클래스를 이용 할 때와 Runable 이용하여 작업 시 각기 메세지를 보낼 절대 시간을 지정하거나 딜레이를 가지고 전달하는 방법이 있다.

쓰레드 클레스 경우 - sendMessageAtTime(Message,long)와 sendMessageDelayed(Message,long)

Runable 경우 - postAtTime(Runable, long)와 poatDelayed(Runable,long)

위와 같이 핸들러에 연결하여 이용하면 된다. 또한 핸들러를 직접 만들지 않고 컴포넌트 상에서도 접근하여 이용 할 수가 있다.

좀 더 효율 적으로 하기 위해 AsyncTask(1.5버전에서 제공) 하는데 솔직히 필자로 봣을 때는 (안드로이드 프로그래머가 아니라..) 그런 상황이 오면 이용을 할 만하겠다 싶긴하지만 필요성을 못 느끼고 있다..(고수님들이 보시면 설명 좀 해주시면 감사하겠습니다.)
[Android] Popup Window Android 2012. 3. 6. 15:43
팝업 윈도우는 임의의 뷰를 담는 컨테이너로 현재 액티비티 위에 잠깐 열리는 윈도우다.

이것은 액티비티 전환 없이!! 잠시 열리는 화면을 보여 줄 때 적절한 것 같다. 이는 다이얼로그와 거의 흡사한 형태이다.

먼저 따로 팝업용으로 레이아웃을 하나 만든다. 그 다음 아래와 같은 코드를 넣어보면 어떤 형태인지 확인이 가능 할 것이다.

public class ImageViewActivity extends Activity{
 PopupWindow m_pop;
 View m_popup_view;
 LinearLayout m_linear;
 Button m_btn;
 
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  m_linear = (LinearLayout)findViewById(R.id.main);
  m_popup_view = View.inflate(this, R.layout.subactivity, null);
  m_pop = new PopupWindow(m_popup_view,200,100,true);
  m_btn = (Button)findViewById(R.id.btn1);
  m_btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    //m_pop.showAtLocation(m_linear, Gravity.NO_GRAVITY, 50, 100);//지정위치
    //m_pop.showAtLocation(m_linear, Gravity.CENTER, 0, 0);//중앙
    //m_pop.showAtLocation(m_linear, Gravity.HORIZONTAL_GRAVITY_MASK|Gravity.BOTTOM, 0, 0);//수평중앙,수직바닥
    m_pop.setAnimationStyle(-1);
    m_pop.showAsDropDown(m_btn);
   }
  });  
  Button btn = (Button)m_popup_view.findViewById(R.id.btn2);
  btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    m_pop.dismiss();
   } 
  });
 } 
}

위에서 보면 showAtLocation을 이용하여 원하는 위치로 배정 할 수가 있다. 그라비티의 경우를 감안하여야 한다.

또한 위에서 보면 dismiss() 함수를 볼 수 있는데 이는 팝업을 닫는 것이며, isShowing()으로 팝업이 열렸는지 닫혔는지 구분이 가능하다.

그리고 m_pop.setAnimationStyle(-1);    m_pop.showAsDropDown(m_btn); 부분을 확인 할 수가 있는데 -1은 디폴트 애니메이션 효과를 나타낸다. 0일 경우에는 효과를 사용하지 않는 것이며 showAsDropDown을 이용하여 버튼에 이벤트를 연결 한 것이다.
[Android] Custom Dialog Android 2012. 3. 6. 15:09
사용자가 정의하는 다이얼로그를 이야기 한다.

먼저 다른 레이아웃에다가 다이얼로그에 위치 시킬 내용들을 xml 형식으로 구현 한 후 다음과 같이 코드를 입력해보면 다이얼로그도 자유롭게 이용 할 수 있을 것이다.

물론 여기서 다중 선택이나 이러한 내용을 접목하는 것은 개인 역량에 달려있다.

public class ImageViewActivity extends Activity{
 Button btns;
 boolean[] m_flag = {false,false,false,false};
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  btns = (Button)findViewById(R.id.btn1);
  btns.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    final LinearLayout linear = (LinearLayout)View.inflate(ImageViewActivity.this, R.layout.subactivity, null);
    AlertDialog.Builder alt = new AlertDialog.Builder(ImageViewActivity.this);
    alt.setTitle("Title");
    alt.setIcon(R.drawable.ic_launcher);
    alt.setView(linear);
    alt.setPositiveButton("확인", new DialogInterface.OnClickListener() {     
     public void onClick(DialogInterface dialog, int which) {      
      EditText first = (EditText)linear.findViewById(R.id.txt_edit1);
      EditText second = (EditText)linear.findViewById(R.id.txt_edit2);
      TextView txt = (TextView)findViewById(R.id.txt_view);
      txt.setText(first.getText()+" "+second.getText());
     }
    });
    alt.setNegativeButton("닫기", null);
    alt.show();  
   }
  });  
 } 
}
[Android] Dialog -2 Android 2012. 3. 6. 14:25

다이얼로그 선택에서 기본은 하나만 선택 할 것인지 다중으로 선택 할 것인지를 나타낸다.

setItems를 할 경우 뒤 쪽에 선택 부분이 나타나지 않고 xml 상에 정의된 배열 데이터가 그대로 나타나지만,

setSingleChoiceItems 를 이용해서 다이얼로그 속성을 싱글 선택일 경우 선택 부분이 라디오 버튼으로 나온다.

다음 코드를 보면 이 두개의 차이를 볼 수가 있다.

public class ImageViewActivity extends Activity{
 Button btns;
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  btns = (Button)findViewById(R.id.btn1);
  btns.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    AlertDialog.Builder alt = new AlertDialog.Builder(ImageViewActivity.this);
    alt.setTitle("Title");
    alt.setIcon(R.drawable.ic_launcher);
    //alt.setItems(R.array.array, new DialogInterface.OnClickListener() {
    alt.setSingleChoiceItems(R.array.array, 0, new DialogInterface.OnClickListener() {
     @Override
     public void onClick(DialogInterface dialog, int which) {
      // TODO Auto-generated method stub
      String[] temp = getResources().getStringArray(R.array.array);
      TextView txt = (TextView)findViewById(R.id.txt_view);
      txt.setText(temp[which]);
     }
    });
    alt.setNegativeButton("닫기", null);
    alt.show();    
   }
  });  
 } 
}
다른 경우로 멀티로 선택 가능 한 경우이다. 위의 코드에서 한 부분을

alt.setMultiChoiceItems(R.array.array, m_flag, new DialogInterface.OnMultiChoiceClickListener() {     
     public void onClick(DialogInterface dialog, int which, boolean isChecked) {
      m_flag[which] = isChecked;
      String[] temp = getResources().getStringArray(R.array.array);
      TextView txt = (TextView)findViewById(R.id.txt_view);
      String result = "";
      for(int i=0;i<m_flag.length;i++){
       if(m_flag[i]){
        result+=temp[i] + " ";
       }
       else{
        result.replace(temp[i]+" ", "");
       }
      }
      txt.setText(result);
     }
    });

대체하면 아이템의 마지막 부분에 체크 박스 형태가 생기면서 여러개를 선택 할 수 있다.

실행을 해 보면 그 차이를 알 수가 있을 것이다.

[Android] Dialog - 1 Android 2012. 3. 6. 13:50
안드로이드 상에서는 토스트보다 다이얼로그를 이용하여 경고 등과 같은 내용들을 표시한다.

왜냐면 토스트는 일정 시간이 지나면 자연적으로 사라지기 때문이다. 물론 finish를 이용하여 다이얼로그도 사라지게는 가능하다.

AlertDialog 같은 경우는 프로세스상 non-blocking 형태로 그 아래 코드까지 모두 사용된다. 여기에서 주의가 필요하다.

그 아래 코드에 finish 를 실행한다면.. 당연히 사라질테니까 말이다.

AlertDialog는 생성자가 protected 처리가 되어 있어서 Builder로 생성해야한다. AlertDialog.Builder(Context context) 를 호출하여 이용하면 된다.  그리고 다이얼로그를 보여주는데는 Show 와 Create 두가지 방법이 있다.

Create를 이용 할 경우 protected Dialog onCreateDialog(int id) 를 이용하여 생성 될 시 어떤 형태를 보여 주는가를 나타 낼 수 있으며, protected void onPrepareDialog(int id, Dialog dialog) 여기에서 그 내용을 적용 시킬 수 있다.

다음은 간단한 예제 코드이다.

public class ImageViewActivity extends Activity{
 Button btns;
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  btns = (Button)findViewById(R.id.btn1);
  btns.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    AlertDialog.Builder alt = new AlertDialog.Builder(ImageViewActivity.this);
    alt.setTitle("Title");
    alt.setMessage("대화상자 오픈");
    alt.setIcon(R.drawable.ic_launcher);
    alt.setPositiveButton("OK", new DialogInterface.OnClickListener() {     
     @Override
     public void onClick(DialogInterface dialog, int which) {
      showDialog(0);      
     }
    });
    alt.setNeutralButton("DON'T", new DialogInterface.OnClickListener() {     
     @Override
     public void onClick(DialogInterface dialog, int which) {
      // TODO Auto-generated method stub
      
     }
    });
    alt.setNegativeButton("NO", new DialogInterface.OnClickListener() {     
     @Override
     public void onClick(DialogInterface dialog, int which) {
      // TODO Auto-generated method stub
      
     }
    });
    alt.setCancelable(false);
    alt.show();    
   }
  });  
 }
 
 protected Dialog onCreateDialog(int id){
  switch(id){
   case 0 :
    return new AlertDialog.Builder(ImageViewActivity.this).setTitle("Title").setMessage("Create").setPositiveButton("OK", null).create();   
  }
  return null;
 }
 
 protected void onPrepareDialog(int id, Dialog dialog){
  super.onPrepareDialog(id, dialog);
  switch(id){
   case 0 :
    dialog.setTitle("TestTitle");
   break;
  }
 }
}
코드를 보면 setPositiveButton,setNeutralButton,setNegativeButton 부분이 보일 것이다. 말 그대로 승인, 중립, 거부의 경우를 나타낸다.

또한 이들의 첫번째 인자는 버튼에 나타내는 텍스트를 의미하며 두번째 인자는 해당 이벤트를 연결 한 것이다.

이 이벤트 내용을 따로 정의하여 클릭 할 때 마다 다이얼로그를 생성하여 여러 작업을 수행 할 수가 있다.
[Android] Custom Tab Android 2012. 3. 5. 18:01
커스텀 탭은 HostTab을 이용하지 않고 사용자가 마치 탭을 사용하는 것 처럼 겹쳐지는 화면들을 나타 낼 때 이용한다.

간단한 예제를 보면 다음과 같다.

XML 코드에서는 전체 레이아웃을 라이너로 잡고 그 아래에 프레임 레이아웃과 라디오 그룹을 이용한 것이다.

물론 프레임 레이아웃 내에는 두개의 라이너 레이아웃과 일반 텍스트 뷰로 표기 된 내용이 들어 있다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <FrameLayout
        android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_weight="1">
        <LinearLayout
            android:id="@+id/first"
            android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:visibility="visible">
      <EditText
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="test layout"
      />
      <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="input"
      />
     </LinearLayout>
     
        <LinearLayout
            android:id="@+id/second"
            android:orientation="vertical"
            android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:visibility="invisible">
      <CheckBox
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="check1"
      />
      <CheckBox
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="check2"
      />
     </LinearLayout>
     
        <TextView
             android:id="@+id/txt_view"
             android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:text="option"
          android:visibility="invisible"
  />
    </FrameLayout>
   
    <RadioGroup
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="65px"
        android:layout_weight="0"
        android:gravity="center_vertical"
        android:checkedButton="@+id/btn1"
        >
       <RadioButton
           android:id="@+id/btn1"
           android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="txt1"
       />
       <RadioButton
           android:id="@+id/btn2"
           android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="txt2"
       />
       <RadioButton
           android:id="@+id/btn3"
           android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="txt3"
       />
    </RadioGroup>
</LinearLayout>

위 내용은 쉽게 다들 알 것이다.

다음은 자바 코드이다.

전체적으로 보면 각각의 뷰를 설정하고 인덱스로 구분하여 화면을 보여주고 있는 형태이다.

public class ImageViewActivity extends Activity{
 View view1,view2,view3;
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main);
  view1 = findViewById(R.id.first);
  view2 = findViewById(R.id.second);
  view3 = findViewById(R.id.txt_view);
  ((Button)findViewById(R.id.btn1)).setOnClickListener(listener);
  ((Button)findViewById(R.id.btn2)).setOnClickListener(listener);
  ((Button)findViewById(R.id.btn3)).setOnClickListener(listener);
 }
 
 Button.OnClickListener listener = new Button.OnClickListener(){
  public void onClick(View v){
   switch(v.getId()){
   case R.id.btn1 :
    ChangePage(1);
    break;
   case R.id.btn2 :
    ChangePage(2);
    break;
   case R.id.btn3 :
    ChangePage(3);
    break;    
   }
  }
 };
 
 void ChangePage(int index){
  view1.setVisibility(View.INVISIBLE);
  view2.setVisibility(View.INVISIBLE);
  view3.setVisibility(View.INVISIBLE);
  
  switch(index){
  case 1:
   view1.setVisibility(View.VISIBLE);
   break;
  case 2:
   view2.setVisibility(View.VISIBLE);
   break;
  case 3:
   view3.setVisibility(View.VISIBLE);
   break;
  }
 }
}

한가지 명심 할 점이 있다면 클릭 리스너를 생성하고 끝에 ; << 세미콜론을 명심하자...

메세지만 안보고 빨간 엑스만 뜨길래 이놈은 왜 이래 하면서 한참 고뇌에 빠졌다;;

C#을 하다가 다시 자바 쪽 공부를 하면서 병행하니 조금;; 헛갈리긴 한다.

또한 버튼을 적용시키고 리스너를 넣을 때 선 선행 되어야 하는것이 버튼 쪽을 전체 ()로 묶어주고 그 다음에 이벤트를 연결해야한다.
[Android] Tab Android 2012. 3. 5. 17:01

여기서 탭은 CS에서 본 탭과 동일한 기능이다.

간단하게 라이너 레이아웃과 하나의 텍스트뷰를 넣고 각기 탭에 대한 기능을 구현 해 보면 다음과 같다.

일단 먼저 XML 파일은 생략한다. 처음에 프레임 레이아웃을 먼저 잡아주고 그 안에 라이너와 텍스트뷰를 넣어서 구성했다.

public class ImageViewActivity extends TabActivity{
 TabHost m_tab;
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  TabHost m_tab = getTabHost();
  
  LayoutInflater inflater = LayoutInflater.from(this);
  inflater.inflate(R.layout.main, m_tab.getTabContentView(),true);  
  m_tab.addTab(m_tab.newTabSpec("tag").setIndicator("first").setContent(R.id.first));
  m_tab.addTab(m_tab.newTabSpec("tag").setIndicator("second").setContent(R.id.second));
  m_tab.addTab(m_tab.newTabSpec("tag").setIndicator("third").setContent(R.id.m_txt_view));
 } 
}

간단히 표시 해 보면 위와 같이 할 수 있다. 다른 방법으로는 setContent 형식으로 표시 하는 방법이 있다.

그 코드는 다음과 같다.

public class ImageViewActivity extends TabActivity{
 Factory m_factory; 
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);  
  m_factory = new Factory(this);
  TabHost tab = getTabHost();
  
  Drawable icon = getResources().getDrawable(R.drawable.ic_launcher);
  LayoutInflater inflater = LayoutInflater.from(this);
  inflater.inflate(R.layout.main, tab.getTabContentView(),true);  
  tab.addTab(tab.newTabSpec("tag1").setIndicator("first",icon).setContent(m_factory));
  tab.addTab(tab.newTabSpec("tag2").setIndicator("second",icon).setContent(m_factory));
  tab.addTab(tab.newTabSpec("tag3").setIndicator("third",icon).setContent(m_factory));
 } 
}

class Factory implements TabHost.TabContentFactory{
 Context m_context;
 Factory(Context context){
  m_context = context;
 }
 
 public View createTabContent(String tag){
  TextView text = new TextView(m_context);
  text.setText(tag);
  return text;
 }
}

별반 차이는 크게 없다. 하나 있다면 별도의 클래스를 생성하여 보낸 것인데 여기서 TabContentFactory를 확장하여 처리를 하였다.

이런 경우 각기 tag 값에 의해 다양하게 화면을 구성 할 수가 있다.

물론 Intent 또한 setContent에 적용하여 사용 할 수도 있다.

먼저 두 폼간의 데이터를 주고 받는 코드는 다음과 같다.

public class ImageViewActivity extends Activity{
 TextView m_txt;
 final static int ACT_EDIT = 0; 
 public void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  m_txt = (TextView)findViewById(R.id.m_txt);
  Button m_btn = (Button)findViewById(R.id.m_btn);
  m_btn.setOnClickListener(new Button.OnClickListener(){
   public void onClick(View v){
    Intent intent = new Intent(ImageViewActivity.this,subActivity.class);
    intent.putExtra("in_txt", m_txt.getText().toString());
    startActivityForResult(intent, ACT_EDIT);
   }
  });
 } 
 
 protected void onActivityResult(int requestcode, int resultcode, Intent data){
  switch(requestcode){
   case ACT_EDIT :
    if(resultcode == RESULT_OK){
     m_txt.setText(data.getStringExtra("out_txt"));
    }
    break;
  }
 }
}

public class subActivity extends Activity{
 EditText m_txt;
 public void onCreate(Bundle savedInstanceSatate){
  super.onCreate(savedInstanceSatate);
  setContentView(R.layout.subactivity);
  m_txt = (EditText)findViewById(R.id.s_txt);
  Intent intent = new Intent();
  m_txt.setText(intent.getStringExtra("in_txt"));
  Button s_btn_ok = (Button)findViewById(R.id.s_btn_ok);
  Button s_btn_cancel = (Button)findViewById(R.id.s_btn_cancel);
  s_btn_ok.setOnClickListener(lisentner);
  s_btn_cancel.setOnClickListener(lisentner);  
 }
 Button.OnClickListener lisentner = new View.OnClickListener() {
  Intent intent;
  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub
   switch(v.getId()){
   case R.id.s_btn_ok :
    intent = new Intent();
    intent.putExtra("out_txt", m_txt.getText().toString());
    setResult(RESULT_OK,intent);
    finish();
    break;
   case R.id.s_btn_cancel :
    setResult(RESULT_CANCELED);
    finish();
    break;
   }
  }
 };
}

이렇게 메인과 서브로 나뉜다. 당연히 매니페스트 파일에서 액티비티는 등록 해 줘야한다.

여기에서보면 putExtra 라는 것이 있다. 이는 액티비티로 서로 값을 전달하기 위해 쓰이며

int, String, Boolean 을 이용하여 보낼 수 있다. 첫번째 이름은 중복되지 않는 키 값이라 생각하면 된다.

이 값들을 확인 하려고 할 때는 getIntExtra, getStringExtra, getBooleanExtra를 이용하여 각기 타입에 맞는 값을 불러온다.

위에 함수 중 startActivityForResult(Intent, int) 형태가 보일 것이다.

이는 해당하는 액티비티를 호출하기 위해 어떤 액티비티의 리턴인지 구분 하기 위해 이용된다.

동시에 onActivityResult(int, int, Intent) 메서드가 보일 것이다. 이는 호출된 액티비티가 종료 되면서 실행 되는 부분으로 액티비티에서 전달하는 값을 표현하고자 한다면 이 메서드 내에서 처리 하면 된다.

마지막으로 setResult 함수를 살펴보면 성공시에는 intent 내용을 전달하지만 그렇지 않을 경우는 처리 하지 않는 것으로 정의 했다. 여기서 intent라고 표현된 내용은 리턴 값 내용이다.