2010년 10월 29일 금요일

안드로이드 위젯 가이드



안드로이드 위젯 가이드입니다.
아래 소스 코드 가져다가 개발하시면 편할 것 같네요.


AnalogClock


<AnalogClock
id="@+id/clock1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Button
<Button id ="@+id/button1"
android:text="Label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<Button id ="@+id/button2"
android:text="Label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:typeface="serif"
/>
<Button id ="@+id/button3"
android:text="Label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textStyle="bold_italic"
/>
CheckBox
<CheckBox id="@+id/plain_cb"
android:text="Plain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<CheckBox id="@+id/serif_cb"
android:text="Serif"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:typeface="serif"
/>
<CheckBox id="@+id/bold_cb"
android:text="Bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
/>
<CheckBox id ="@+id/italic_cb"
android:text="Italic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic"
/>
DatePicker
<DatePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content" >

...
// Required Java init code:
DatePicker dp =
(DatePicker)this.findViewById(R.id.widget27);

// for example init to 1/27/2008, no callback
dp.init(2008, 0, 27, Calendar.SUNDAY, null);
...
DigitalClock
<DigitalClock id="@+id/digitalclock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
EditText
<EditText id ="@+id/edittext1"
android:text="EditText 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<EditText id ="@+id/button2"
android:text="(206)555-1212"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:typeface="serif"
android:phoneNumber="true"
/>
<EditText id ="@+id/password"
android:text="SuperSecret"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold_italic"
android:password="true"
/>
Gallery
<Gallery
id="@+id/gallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
ImageButton
<ImageButton id="@+id/imagebutton"
android:src="@drawable/brush"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
ImageView
<ImageView id="@+id/imagebutton"
android:src="@drawable/brush"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
ProgressBar
<ProgressBar id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
RadioButton
<RadioGroup
id="@+id/widget1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
>
<RadioButton
id="@+id/widget2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Plain"
android:checked="false"
android:layout_gravity="left"
android:layout_weight="0"
>
</RadioButton>
<RadioButton
id="@+id/widget3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Serif"
android:checked="true"
android:layout_gravity="left"
android:layout_weight="0"
android:typeface="serif"
>
</RadioButton>
<RadioButton
id="@+id/widget25"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bold"
android:checked="false"
android:layout_weight="0"
android:layout_gravity="left"
android:textStyle="bold"
>
</RadioButton>
<RadioButton
id="@+id/widget24"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bold & Italic"
android:checked="false"
android:layout_weight="0"
android:layout_gravity="left"
android:textStyle="bold_italic"
>
</RadioButton>
</RadioGroup>
Spinner
<Spinner
id="@+id/widget1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectoronTop="false"/>
TextView
<TextView id="@+id/plain"
android:text="Plain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView id="@+id/serif"
android:text="Serif"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:typeface="serif"
/>
<TextView id="@+id/bold"
android:text="Bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
/>
<TextView id ="@+id/italic"
android:text="Italic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic"
/>
TimePicker
<TimePicker
id="@+id/widget3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>




[출처] - http://www.droiddraw.org/widgetguide.html









구글맵 API - GPS로 현재위치 받아와서 표시하기

 

 

 

 

현재 위치 표시

 

지도 위에 겹쳐서 표시되는 정보 중 가장 실용적인 것은 사용자의 현재 위치이다. 사용자는 자신의 위치로부터 정보를 얻으므로 현재 위치가 어디인가는 항상 표시해야 할 중요한 정보이다. 현재 위치를 표시하는 방법은 아주 원론적인데 위치 제공자로부터 위치를 조사하고 해당 좌표에 표식을 추가하면 된다. 그러나 앞에서 연구해 봤다시피 다량의 코드가 필요하다.

다행히 이 번거로운 작업을 대신 해 주는 오버레이가 제공된다. MyLocationOverlay 클래스는 이름이 의미하는 바대로 현재 위치를 조사하여 오버레이로 표시까지 해 준다. 이 객체를 생성하여 맵뷰의 오버레이로 추가해 놓기만 하면 내부적으로 위치 정보를 수신하여 현재 위치를 보여주며 더불어 나침반이 있는 장비인 경우 방향 정보까지도 같이 표시한다.

개발자가 해야할 잡스러운 처리를 모두 대신 해 주므로 굉장히 편리한 클래스이다. 그러나 이 기능들이 동작하려면 백그라운드에서 여분의 코드를 계속 실행해야 하므로 배터리 성능에는 부정적이다. 그래서 기능을 켜고 끌 수 있는 메서드들을 제공한다. 액티비티가 실행중일 때만 이 기능들이 필요하므로 onResume에서 켜고 onPause에서 정지시키는 것이 합리적이다.

 

boolean enableMyLocation()

void disableMyLocation()

boolean enableCompass()

void disableCompass()

 

 다음 메서드는 처음 위치가 조사될 때 실행될 러너블을 등록한다. 이 러너블은 분리된 스레드에서 실행되며 첫 조사된 위치로 이동하는 등의 처리를 할 수 있다.

 

boolean runOnFirstFix(Runnable runnable)

 

현재 위치는 파란색의 반짝거리는 원으로 표시되는데 이 표식을 탭하면 다음 메서드가 호출된다. 이 메서드를 재정의하면 현재 위치를 탭 했을 때의 처리를 수행할 수 있된 단, 메서드를 재정의하려면 상속을 받아야 한다는 점에서 약간 번거롭기는 하다.

 

boolean dispatchTap()

 

모든 것이 자동화되어 있으므로 이 클래스를 사용하는 것은 굉장히 쉽다. 객체 만들어 오버레이에 추가하고 적당한 때에 기능을 켜 주기만 하면 나머지는 내부에서 알아서 처리한다.

 

location/MyLocationOverlay

public class OverlayLocation extends MapActivity {

     MapView mMap;

     MyLocationOverlay2 mLocation;

 

     protected boolean isRouteDisplayed() {

          return false;

     }

 

     public void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.location_mapviewtest);

 

          mMap = (MapView)findViewById(R.id.mapview);

          MapController mapControl = mMap.getController();

          mapControl.setZoom(13);

          mMap.setBuiltInZoomControls(true);

 

          GeoPoint pt = new GeoPoint(37881311, 127729968);

          mapControl.setCenter(pt);

 

          mLocation = new MyLocationOverlay2(this, mMap);

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

          overlays.add(mLocation);

 

          mLocation.runOnFirstFix(new Runnable() {

              public void run() {

                   mMap.getController().animateTo(mLocation.getMyLocation());

              }

          });

     }

 

     public void onResume() {

          super.onResume();

          mLocation.enableMyLocation();

          mLocation.enableCompass();

     }  

 

     public void onPause() {

          super.onPause();

          mLocation.disableMyLocation();

          mLocation.disableCompass();

     }

 

     class MyLocationOverlay2 extends MyLocationOverlay {

          public MyLocationOverlay2(Context context, MapView mapView) {

              super(context, mapView);

          }

         

          protected boolean dispatchTap() {

              Toast.makeText(OverlayLocation.this, "여기가 현재 위치입니다.",

                        Toast.LENGTH_SHORT).show();

              return false;

          }

     }

}

 

춘천 시청을 지도 중앙에 표시했으며 현재 위치 오버레이를 생성하여 살짝 얹어 놓았다. onResume에서 현재 위치와 나침반 기능을 활성화시키고 onPause에서는 두 기능을 정지시킨다. 현재 위치가 처음 확인될 때 해당 좌표로 이동하는 러너블을 등록해 놓았으므로 위치 정보가 수신되는 즉시 현재 위치가 화면 중앙에 올 것이다.

현재 위치는 위치 제공자로부터 수신되는데 알다시피 에뮬레이터에서는 불가능하다. 그래서 DDMS로 가짜 좌표를 던져 주어야 이 예제가 동작하는 것을 볼 수 있다. 위도를 37.9로 살짝 수정해서 보내면 다음과 같이 지도가 이동한다. 실 장비에서는 장비를 들고 이동해야 현재 위치가 조사될 것이다.

 

 

dispatchTap 메서드에서는 현재 위치를 탭했을 때 토스트로 클릭을 받았음만 확인해 보았다. 이 메서드에서 true를 리턴하면 현재 위치에 대한 처리가 완료된 것으로 인식하여 현재 위치 표식이 사라져 버리므로 표식을 계속 유지하려면 false를 리턴해야 한다. 이 메서드를 재정의하기 위해 MyLocationOverlay2 클래스를 상속받았다.

나침반 기능도 켜 두기는 했지만 에뮬레이터에서는 나침반이 없을 뿐더러 DDMS에도 나침반 흉내 기능이 제공되지 않으므로 이 기능을 확인해 볼 방법이 없다. 실장비가 있어야만 방향 정보를 확인해 볼 수 있다. 실장비에서 실행하면 화면 우 하단에 빨간색 바늘을 가진 나침반이 나타나 현재 방향을 표시하며 장비를 회전시키면 나침반이 따라 움직인다.

 

 

[출처] - http://www.winapi.co.kr/android/

 

2010년 10월 21일 목요일

사람과 사람과의 관계속에 오는 엇갈린 오해로 인한 속상함

속상한 일이 생겼었는데

근데 미덥지 않지만 오해풀고

겨우겨우 속상함 지워냈는데

다시또 마음과 엇갈린 오해로

속상한 일이 발생할거 같아

느껴지는데 내가 어떻게 해야 할지 모르겟어

맞받아서 대할 수 있겟지만

그럴수록 점점 멀어지겟지

용기내서 내가 먼저 다가가야겟어

이것땜에 다른것에 신경쓸수 없어

용기가 필요해 ..  

2010년 10월 14일 목요일

TabWidget 각 페이지별 액티비티 보여주기 - 2

 

 

결과화면



main.xml
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
        <TabWidget android:id="@android:id/tabs"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
            <FrameLayout android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
        </FrameLayout>
    </LinearLayout>
</TabHost>

sub_layout1.xml / sub_layout2.xml / sub_layout3.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" >
  <TextView
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:textSize="20sp"
      android:gravity="center"
      android:text="Tab #"/>
</LinearLayout>

TabLayout.java file
package com.tablayout;

import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;

public class TabLayout extends TabActivity {
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        Resources res = getResources();
       
        //탭들을 품을 TabHost의 객체를 가져온다.
        //TabActivity를 확장했기 때문에 getTabHost() 사용한다.
        //Activity를 확장했다면 (TabHost)findViewById()를 사용해야 한다.
        TabHost tabHost = getTabHost();
       
        //각각의 탭이 지닐 기능을 정할 TabSpec 객체 등록
        TabHost.TabSpec spec;
       
        //각각의 탭이 어떤 Activity를 보여줄지 결정하는 정보를 담은 Intent 객체 등록
        Intent intent;  
       
        //이 Intent는 SubActivity1를 보여준다.
        intent = new Intent().setClass(this, SubActivity1.class);

        //새로운 Spec을 만들고 탭을 구별할 태그 등록
        spec = tabHost.newTabSpec("Tab1");

        //탭에 표시 될 문자아이콘을 등록
        //android.R.drawable에는 안드로이드에서 기본적으로 제공하는 drawable가 들어있다.
        spec.setIndicator("TAB1",res.getDrawable(android.R.drawable.ic_menu_agenda));

        //탭에 Intent 등록
        spec.setContent(intent);

        //TabHost에 첫번째 탭 등록
        tabHost.addTab(spec);
       
        //spec의 매소드들을 나열해서 코딩 가능
        intent = new Intent().setClass(this, SubActivity2.class);
        spec = tabHost.newTabSpec("Tab2").setIndicator("TAB2",
                                        res.getDrawable(android.R.drawable.ic_menu_edit)).setContent(intent);
        tabHost.addTab(spec);

        intent = new Intent().setClass(this, SubActivity3.class);
        spec = tabHost.newTabSpec("Tab3").setIndicator("TAB3",
                                        res.getDrawable(android.R.drawable.ic_menu_help));.setContent(intent);
        tabHost.addTab(spec);
    }
}

SubActivity1.java / SubActivity2.java / SubActivity3.java
package com.tablayout;

import android.app.Activity;
import android.os.Bundle;

public class SubActivity1 extends Activity{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sub_layout#);
    }
}

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.tablayout"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".TabLayout"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 사용할 Activity는 아래와 같이 꼭 등록해야 사용할 수 있다.
   android:name=".ActivityName" <- 이름앞에 꼭 . 을 써야 한다. -->
        <activity android:name=".SubActivity1" android:label="SubActivity1" />
        <activity android:name=".SubActivity2" android:label="SubActivity2" />
        <activity android:name=".SubActivity3" android:label="SubActivity3" />
    </application>


</manifest>



[출처] - http://androandro.tistory.com/4

2010년 10월 10일 일요일

안드로이드 단말기에서 디버깅하기

단말기를 컴퓨터에 연결하는 절차는 매우 간단합니다. 제가 개발하는 환경이 윈도우 환경이다보니.. 윈도우 환경 기준으로 적어보도록 하겠습니다.

1. 일단 USB 케이블 (G1의 단자는 Mini-USB 단자입니다)을 컴퓨터에 연결하면 새 하드웨어 추가 마법사가 실행됩니다.
2. Android Phone, ADB 의 드라이버를 설치할 겁니다. 자동으로 검색 하면 잘 안되니 경로를 지정해야 합니다.
   USB 드라이버는 안드로이드 SDK 폴더의 usb-driver 폴더에 있으니, 그 폴더를 경로로 설정한 후 설치를 수행합니다.
3. 잠시 기다리면 설치가 완료됩니다. :)



새 하드웨어 검색 마법사가 뜹니다. 어차피 연결하나 안하나 상관없으므로 아무거나 누른 후 다음 버튼을 누릅니다.


자동으로 설치는 안되므로, 직접 USB 드라이버가 있는 위치를 지정해주어야 합니다. 목록 또는 특정 위치에서 설치를 선택한 후, 다음 버튼을 누릅니다.


USB 드라이버가 있는 폴더를 설정합니다. USB 드라이버는 SDK 폴더의 usb_driver 폴더에 있습니다.


폴더 설정도 완료되었으므로, 다음 버튼을 눌러줍니다.


설치가 진행중입니다. :)



이 과정이 끝나면 G1과 컴퓨터가 정상적으로 연결됩니다. 아마 G1의 Notification Bar에 "USB Connected" 및 "USB debugging connected"가 표시될 겁니다.

"USB Connected"는 G1에 들어가있는 SD카드의 내용을 컴퓨터에서 읽을 준비가 되었다는 것들 뜻합니다. 컴퓨터에서 G1의 SD카드 내용을 읽으려면 아래의 USB Connected 패널을 눌러 "Mount" 를 선택해야 컴퓨터에서 SD카드 내의 내용을 읽고 쓰는 것이 가능합니다. 사용이 끝나고 G1을 컴퓨터와 분리하기 전에는 반드시 "Unmount"를 눌러 안전하게 분리를 해야합니다 ^^

아, 그리고 SD카드를 G1에 넣을 때도 마찬가지로.... 넣을 때는 자동으로 Mount까지 되어서 그냥 두면 되지만, 뺄 때에는 SD카드를 빼기 전에 SD카드 메뉴에서 Unmount를 한 후 제거해야 합니다. 그렇지 않을 경우 자칫 파일이 손상될 위험이 있습니다.

지금까지는 휴대폰에 메모리카드를 넣고 뺄 때 이런 것을 한 적이 없어서.. 처음에는 적응하는데 조금 시간이 걸렸습니다 -ㅁ-


USB debugging connected 는 말 그대로 컴퓨터의 IDE를 통해 실제 기기에서 실행되는 어플리케이션들의 디버깅이 가능함을 뜻합니다. 만약, 이게 활성화되어있지 않다면 Settings - Application - Development - USB debugging을 활성화시켜주시면 됩니다.


기기를 연결한 후, DDMS 탭의 Devices 창을 보면 현재 연결되어 있는 단말이 바로 보입니다.


현재 제 단말기의 버전이 1.6이므로, 1.6용으로 작성된 어플리케이션을 실행하면 다음과 같은 화면이 뜨면서 단말기에서 실행할 지, 에뮬레이터에서 실행할 지 선택할 수 있습니다.


여기까지 간단하기 실제 기기를 이용하는 방법에 대해서 알아보았습니다. 그리 어렵지 않지요?

물론... 이렇게 하지 전에 루팅하고, Cyanogen Mod같은 커스텀 롬을 설치하는 과정, 초기에 활성화(Activation)하기 등은 조금 까다롭기는 하지만 Cyanogen 위키에는 한글화된 문서도 올라와 있고, 활성화(Activation)는 안드로이드펍에 방법이 잘 정리되어 있으니 참고하시면 됩니다. :)