Showing posts with label 안드로이드 개발. Show all posts
Showing posts with label 안드로이드 개발. Show all posts

2011/03/07

[Android Dev.] Activity 간 데이터 주고 받기

다른 Activity에 데이터 넘겨주기


Intent intentSubActivity = new Intent( this, SubActivity.class );

intentSubActivity.putExtra( "Name", "Intent Data" );
intentSubActivity.putExtra( "Age", 30 );
intentSubActivity.putExtra( "Marriage", false );

startActivity( intentSubActivity );





넘어온 데이터 받기


Intent intent = getIntent();

String strName = intent.getStringExtra( "Name" );
Integer nAge = intent.getIntExtra( "Age", 0 );
Boolean bMarriage = intent.getBooleanExtra( "Marriage", false );

String strMsg;
strMsg = "Name : " + strName + " Age : " + nAge + " Marrige : " + strMarriage;
Log.i( "SubActivity", strMsg );

INFO/SubActivity(xxx): Name : Intent Data Age : 30 Marrige : X

Original Post : http://neodreamer-dev.tistory.com/515

2010/09/18

[Android Tips] 화면 상태 확인 하기

현재 화면이 가로인지 새로인지 확인하는 방법은 화면 해상도를 확인하는 방법도 있겠지만 API 에서 제공하는 함수로도 확인 할 수 있다. 가로 혹은 세로 해상도가 같은 경우에는 API 함수를 이용하는 것이 보다 정확할 것이다.





Android 2.1 이하에서는 getOrientation() 만 동작하며 Android 2.2 이상에서는 getOrientation() 과 getRotation() 이 동작을 한다.






Android 2.1 이하


WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Display disp = wm.getDefaultDisplay();

int orientation = disp.getOrientation(); // Android 2.1
Log.i( "Orientation", "orientation : " + orientation );






Android 2.2 이상


WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Display disp = wm.getDefaultDisplay();

int rotation = disp.getRotation(); // Android 2.2
Log.i( "Rotation", "rotation : " + rotation );

switch ( rotation )
{
case Surface.ROTATION_0:
Log.i( "Roation", "Portrait : 0" );
break;

case Surface.ROTATION_90:
Log.i( "Roation", "Landscape : 90" );
break;

case Surface.ROTATION_180:
Log.i( "Roation", "Portrait : 180" );
break;

case Surface.ROTATION_270:
Log.i( "Roation", "Landscape : 270" );
break;
}
<

Original Post : http://neodreamer-dev.tistory.com/460

[Android Tips] 화면 해상도 알아내기


방법 #1


DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

int ScreenWidth = metrics.widthPixels
int ScreenHeight = metrics.heightPixels






방법 #2


WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Display dsp = wm.getDefaultDisplay();

int height = dsp.getHeight();
int width = dsp.getWidth();
<

Original Post : http://neodreamer-dev.tistory.com/459

2010/09/15

[Android Dev.] 화면 회전에 대응하는 UI 구성하기

안드로이드 기기를 보통 사용하는 세로(portrait) 방향 화면에서 가로(landscape) 방향 화면으로 전환하는 것에 대응 하기 위해 서는 서로 다른 Layout 을 구성하는 리소스(xml)를 만들어야 한다.





아주 단순한 layout 구성으로 기본적인 TextView 와 버튼 두개로 구성된 UI 이다. 파일 이름은 main.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"
android:layout_gravity="center_vertical|center_horizontal"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2"
/>
</LinearLayout>






위의 layout 구성은 아래와 같은 화면이다.






이 화면을 가로(Landscape)로 변경(에뮬레이터에서 Ctrl+F11)을 하면 아래와 같은 화면이 된다. UI 구성이 변하지 않은 화면이 나온다.






세로 방향 구성과는 다르게 가로 방향의 UI 구성을 새로 하기 위해서는 res 폴더에 layout-land 폴더를 만들고 layout 폴더에 있는 구성 파일과 동일한 UI 구성 파일(xml)을 만들어 작성을 하면 화면의 회전에 따라 각각의 UI 구성이 출력 된다.






아래는 layout-land 폴더에 작성한 main.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"
android:layout_gravity="center_vertical|center_horizontal"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical|center_horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2"
/>
</LinearLayout>
</LinearLayout>






이 소스를 실행 시켜서 화면 전환을 해 보면 아래와 같은 변화된 UI 의 화면을 볼 수 있다.

2010/07/05

[Android Dev.] Touch 이벤트 사용하기

Android 의 Touch 이벤트를 테스트 해 보았다.

Touch 이벤트는 TouchListener 를 등록하여 onTouch 함수를 오버라이드 하여 구현을 하거나 onTouchEvent 함수를 오버라이드 하여 구현할 수 있다.




두 방법간의 큰 차이는 없고 어떠한 함수를 통해서 Touch 이벤트를 핸들링 하는가만 다른 것 같다. Touch Listener 를 등록하여 구현하는 경우는 Activity 에 전달 되는 Touch 에서 전체적으로 핸들링 할 수 있지만 내부 View 의 onTouchEvent 를 오버라이드하여 구현하는 경우에는 해당 뷰의 Touch 이벤트에 국한 된다는 차이가 있는데 이는  Touch 구현 범위에 따라 선택을 하여야 할 것 같다.










ACTION_DOWN

ACTION_DOWN

ACTION_MOVE

ACTION_MOVE

ACTION_MOVE

ACTION_UP







Touch Listener 를 등록하여 구현하는 방법



import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TouchTest extends Activity implements OnTouchListener
{
/** Called when the activity is first created. */
TextView tvStatus;
Canvas2D canvas;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);

LinearLayout layout = new LinearLayout(this);
layout.setOrientation( LinearLayout.VERTICAL );

LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT );
layout.setLayoutParams( param );

tvStatus = new TextView(this);
layout.addView( tvStatus );
tvStatus.setText( "Touch Status" );

canvas = new Canvas2D( this );
ViewGroup.LayoutParams canvasParam = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT );
layout.addView( canvas, canvasParam );

canvas.setOnTouchListener( this );

setContentView( layout );
}

class Canvas2D extends View
{
public Canvas2D(Context context)
{
super(context);
}

@Override
public void onDraw( Canvas canvas )
{
// Canvas 배경 설정
canvas.drawColor( Color.parseColor("#888888") );
}
}

@Override
public boolean onTouch( View v, MotionEvent event )
{
if ( v == canvas )
{
Log.i( "event", "Canvas2D onTouch" );

switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
String strMsg;
strMsg = "ACTION_DOWN X: " + event.getX() + " Y:" + event.getY();

tvStatus.setText( strMsg );
}
break;

case MotionEvent.ACTION_MOVE:
{
String strMsg;
strMsg = "ACTION_MOVE X: " + event.getX() + " Y:" + event.getY();

tvStatus.setText( strMsg );
}
break;

case MotionEvent.ACTION_UP:
{
String strMsg;
strMsg = "ACTION_UP X: " + event.getX() + " Y:" + event.getY();

tvStatus.setText( strMsg );
}
break;
}
}

return true;
}
}







onTouchEvent 함수를 오버라이드 하여 구현하는 방법



import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TouchTest extends Activity
{
/** Called when the activity is first created. */
TextView tvStatus;
Canvas2D canvas;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);

LinearLayout layout = new LinearLayout(this);
layout.setOrientation( LinearLayout.VERTICAL );

LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT );
layout.setLayoutParams( param );

tvStatus = new TextView(this);
layout.addView( tvStatus );
tvStatus.setText( "Touch Status" );

canvas = new Canvas2D( this );
ViewGroup.LayoutParams canvasParam = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT );
layout.addView( canvas, canvasParam );

canvas.setOnTouchListener( this );

setContentView( layout );
}

class Canvas2D extends View
{
public Canvas2D(Context context)
{
super(context);
}

@Override
public void onDraw( Canvas canvas )
{
// Canvas 배경 설정
canvas.drawColor( Color.parseColor("#888888") );
}

@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.i( "event", "Canvas2D onTouch" );

switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
String strMsg;
strMsg = "ACTION_DOWN X: " + event.getX() + " Y:" + event.getY();

tvStatus.setText( strMsg );
}
break;

case MotionEvent.ACTION_MOVE:
{
String strMsg;
strMsg = "ACTION_MOVE X: " + event.getX() + " Y:" + event.getY();

tvStatus.setText( strMsg );
}
break;

case MotionEvent.ACTION_UP:
{
String strMsg;
strMsg = "ACTION_UP X: " + event.getX() + " Y:" + event.getY();

tvStatus.setText( strMsg );
}
break;
}

return true;
}
}
}

<

Original Post : http://neodreamer-dev.tistory.com/450

2010/07/02

[Android Dev.] Emulator 창 쉽게 갈무리 하기

그 동안 Android 를 학습하면서 블로그를 위해 OpenCapture 라는 멋진 프로그램을 이용하여 갈무리하여 블로그에 글을 작성하였는데 이제 앞으로는 이 멋진 OpenCapture 프로그램을 사용하지 않게 될 것 같다.



Eclipse 의 DDMS Perspective 의 Device 창의 Capture Screen 메뉴를 이용하면 보다 쉽게 갈무리 할 수 있다.




Eclipse 창의 우측에 보면 다양한 Perspective 가 있는데 이중 DDMS 를 선택한다. 만약 DDMS 가 보이지 않을 때에는 왼쪽의 창 아이콘을 클릭하여 Other... 를 선택하여 DDMS 를 선택하면 된다.




이제 Emulator 를 실행한다.




그리고 Eclipse 의 여러 탭 중 Device 탭에 있는 Capture Screen 메뉴 혹은 아이콘을 클릭 한다.




그러면 아래와 같이 Emulator 화면을 갈무리한 창지 나타난다.




필요에 따라 회전도 복사도 가능하다. 저장을 하게 되면 아래와 같은 최종 결과를 얻을 수 있다.


2010/06/22

[Android Dev.] Activity 추가 및 전환 하기








Activity 추가하기


Activity 를 추가하려면 프로젝트에 Class 를 추가한다.


클래스 추가

클래스 추가 대화상자

Superclass 를 android.app.Activity 로 지정하여 클래스를 생성한다. 그리고 이 Activity 에 사용할 layout을 위한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">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello SubActivity"
/>
<Button
android:id="@+id/BtnReturnMain"
android:text="Return to Main Activity"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>












Activity 전환하기


추가 된 Activity 를 사용하기 위해 AndroidManifest.xml 에 추가를 한다. AndroidManifest.xml 에 Activity 를 추가 하는 것은 수동으로 하는 방법과 자동으로 하는 방법이 있다.






자동으로 하는 방법은 AndroidManifest.xml 파일을 열어 Application 탭에서 Application Nodes 에 Activity 를 추가한다.






추가하고 추가 된 Activity 를 선택하고 오른쪽의 Attributes for Activity 에 Name 를 생성한 Activity 를 할당하여 준다.






이렇게 지정을 하면 AndroidManifest.xml 파일은 아래와 같이 수정이 된다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.neodreamer.SwitchActivity"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
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="SubActivity">
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>






Main Activity 의 Layout 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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/BtnCallSub"
android:text="Call Sub Activity"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>





Main 에서 SubActivity 호출 코드


@Override
public void onClick(View v)
{
if ( v == btnCallSub )
{
Log.i( "onClick", "Call Sub Activity" );
Intent intentSubActivity = new Intent( this, SubActivity.class );
startActivity( intentSubActivity );
}
}






Sub 에서 MainActivity 로 돌아가는 코드


@Override
public void onClick(View v)
{
if ( v == btnReturnMain )
{
finish();
}
}

2010/05/21

Android 2.2 Froyo SDK 설치하기

Android Froyo 와 SDK 공개 소식을 듣고 업데이트가 가능한지 SDK 설치 폴더의 setup 을 실행시켜 보았더니 업데이트 항목에 2.2 버전에 대한 업데이트 항목이 추가 되었다.





업그레이드 도중 tools 설치가 실패하는 경우가 있는데 이는 eclipse 를 실행한 상태에서 업데이트를 실행하여서 그런다. 시스템 부팅후 java및 android 개발 관련 툴을 실행하지 않고 업데이트를 수행하면 잘 된다.


SDK 업데이트를 마치고 eclipse 를 실행하여 업데이트 항목이 있나 확인해 보니 개발 툴 관련 업데이트가 있어 이 또한 설치를 해 주었다.



이제 Froyo 개발 준비가 된 것이다.<

Original Post : http://neodreamer-dev.tistory.com/444

Android NDK, Revision 4 공개

Android Froyo 공개와 발 맞추어 NDK 도 업그레이드 된 버전이 공개가 되었다. Froyo API 를 지원 한다.



Android NDK, Revision 4 (May 2010)


  • Provides a simplified build system through the new ndk-build build command.

  • Adds support for easy native debugging of generated machine code on production devices through the new ndk-gdb command.

  • Adds a new Android-specific ABI for ARM-based CPU architectures, armeabi-v7a. The new ABI extends the existing armeabi ABI to include these CPU instruction set extensions:


    • Thumb-2 instructions

    • VFP hardware FPU instructions (VFPv3-D16)

    • Optional support for ARM Advanced SIMD (NEON) GCC intrinsics and VFPv3-D32. Supported by devices such as Verizon Droid by Motorola, Google Nexus One, and others.




  • Adds a new cpufeatures static library (with sources) that lets your app detect the host device's CPU features at runtime. Specifically, applications can check for ARMv7-A support, as well as VFPv3-D32 and NEON support, then provide separate code paths as needed.

  • Adds a sample application, hello-neon, that illustrates how to use the cpufeatures library to check CPU features and then provide an optimized code path using NEON instrinsics, if supported by the CPU.

  • Lets you generate machine code for either or both of the instruction sets supported by the NDK. For example, you can build for both ARMv5 and ARMv7-A architectures at the same time and have everything stored to your application's final .apk.

  • To ensure that your applications are available to users only if their devices are capable of running them, Android Market now filters applications based on the instruction set information included in your application — no action is needed on your part to enable the filtering. Additionally, the Android system itself also checks your application at install time and allows the installation to continue only if the application provides a library that is compiled for the device's CPU architecture.

  • Adds support for Android 2.2, including a new stable API for accessing the pixel buffers of Bitmap objects from native code.



<

Original Post : http://neodreamer-dev.tistory.com/443

Android 2.2 Froyo SDK 공개!!





드디어 Android Froyo 가 공개가 되었다. Froyo 공개 후 SDK 도 공개가 되었다.



Froyo(2.2) 가 기존 2.1 버전에 비해 성능이 20~30배 정도 좋아졌다는데 성능 이외에도 많은 것이 기대 되는 버전이다.



Android 2.2 Platform

Android 2.2 Platform Highlights<

Original Post : http://neodreamer-dev.tistory.com/442

2010/05/13

[Android Dev.] Tab 선택 이벤트 잡기

TabActivity 를 이용한 Tab UI 구현할 때, 사용자가 Tab 을 바꿀 경우 TabHost 의 setOnTabChangedListener 함수를 이용하여 Tab 이 바뀌는 순간을 알아 차릴 수 있다.













package com.neodreamer.MyTab;

import android.app.TabActivity;
import android.os.Bundle;
import android.widget.TabHost;
import android.widget.Toast;
import android.widget.TabHost.OnTabChangeListener;

public class MyTab extends TabActivity implements OnTabChangeListener
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

TabHost tabHost = getTabHost();

TabHost.TabSpec spec;

// 첫 번째 탭
spec = tabHost.newTabSpec( "Tab 01" );
spec.setIndicator( "Tab 01",
getResources().getDrawable( R.drawable.icon ) );
spec.setContent( R.id.TabView1 );
tabHost.addTab( spec );

// 두 번째 탭
spec = tabHost.newTabSpec( "Tab 02" );
spec.setIndicator( "Tab 02" );
spec.setContent( R.id.TabView2 );
tabHost.addTab( spec );

// 세 번째 탭
spec = tabHost.newTabSpec( "Tab 03" );
spec.setIndicator( "Tab 03" );
spec.setContent( R.id.TabView3 );
tabHost.addTab( spec );

tabHost.setCurrentTab( 0 );

// Tab Change 이벤트 리스너 등록
tabHost.setOnTabChangedListener( this );
}

@Override
public void onTabChanged(String tabId)
{
String strMsg;
strMsg = "onTabChanged : " + tabId;
Toast.makeText( this, strMsg, Toast.LENGTH_SHORT ).show();
}
}

<

Original Post : http://neodreamer-dev.tistory.com/438

2010/05/12

[Android Dev.] SQLite Database 사용하기

Android 에서 SQLite Database 를 사용하려면 SQLiteOpenHelper, SQLiteDatabase 클래스를 상속받아 구현을 해야 히지만 복잡하고 귀찮아서 그냥 Activity 안에 구현해 보았다.





Activity 의 Layout 은 버튼하나와 수행 결과를 보여 줄 TextView 만 배치하였다.

<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/BtnTestSQLite"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="Test SQLite"
/>
<TextView
android:id="@+id/TxtResult"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>



버튼이 눌려지만 Database 를 테스트하는 명령이 수행되고 그 결과를 TextView에 출력 하였다.

@Override
public void onClick(View v)
{
// 데이터베이스 열기 (생성)
m_db = openOrCreateDatabase( "test.db", Context.MODE_PRIVATE, null );

if ( !m_db.isOpen() )
{
Log.e( "SQLite", "openOrCreateDatabase ... Fail" );
return;
}

Log.i( "SQLite", "openOrCreateDatabase ... OK" );

String strSQL;

try
{
// member 테이블이 존재하면 삭제
strSQL = "DROP TABLE IF EXISTS member;";
m_db.execSQL( strSQL );

// member 테이블이 존재하지 않으면 생성
strSQL =
"CREATE TABLE IF NOT EXISTS member " +
"(" +
" c_name TEXT" +
" , c_alias TEXT" +
" , c_age INTEGER" +
");";
m_db.execSQL( strSQL );
Log.i( "SQLite", "Create Table ... OK" );

// Insert 구문을 이용한 Row 삽입
for ( int i = 0; i < 3; ++i )
{
strSQL =
"INSERT INTO member ( c_name, c_alias, c_age )" +
" VALUES ( 'code_" + Integer.toString( i ) + "'," +
" 'test', " + Integer.toString( i + 2 ) +
" );";
m_db.execSQL( strSQL );

Log.i( "SQLite", "Insert data " + i + " ... OK" );
}

// ContentValues 를 이용한 데이터 삽입
ContentValues cvInsert = new ContentValues();
cvInsert.put( "c_name", "neo" );
cvInsert.put( "c_alias", "dreamer" );
cvInsert.put( "c_age", "20" );
m_db.insert( "member", null, cvInsert );

cvInsert.put( "c_name", "neo2" );
cvInsert.put( "c_alias", "dreamer2" );
cvInsert.put( "c_age", "40" );
m_db.insert( "member", null, cvInsert );

// rawQuery 함수를 이용한 데이터 질의
m_cursor = m_db.rawQuery( "SELECT * FROM member", null );
if ( m_cursor != null )
{
if ( m_cursor.moveToFirst() )
{
String strRow = "--------------------------------\n";
for(int i = 0 ; i < m_cursor.getColumnCount() ; i++ )
{
strRow += m_cursor.getColumnName(i) + " | ";
}
strRow += "\n";
txtResult.setText( strRow );

do
{
strRow = "";
for(int i = 0 ; i < m_cursor.getColumnCount() ; i++ )
{
strRow += m_cursor.getString(i) + " | ";
}
strRow += "\n";
txtResult.setText( txtResult.getText() + strRow );
} while ( m_cursor.moveToNext() );
}
}
m_cursor.close(); // 커서 닫기

// rawQuery 함수에 parameter 를 이용한 데이터 질의
String strParam[] = { "neo" };
m_cursor = m_db.rawQuery( "SELECT * FROM member WHERE c_name = ?", strParam );
if ( m_cursor != null )
{
if ( m_cursor.moveToFirst() )
{
String strRow = "--------------------------------\n";
for(int i = 0 ; i < m_cursor.getColumnCount() ; i++ )
{
strRow += m_cursor.getColumnName(i) + " | ";
}
strRow += "\n";
txtResult.setText( txtResult.getText() + strRow );

do
{
strRow = "";
for(int i = 0 ; i < m_cursor.getColumnCount() ; i++ )
{
strRow += m_cursor.getString(i) + " | ";
}
strRow += "\n";
txtResult.setText( txtResult.getText() + strRow );
} while ( m_cursor.moveToNext() );
}
}
m_cursor.close(); // 커서 닫기

// query 함수를 이용할 데이터 질의
String strColumn[] = { "c_name", "c_age" };
String strSelection = "c_name like 'neo%'";
m_cursor = m_db.query( "member", strColumn, strSelection,
null, null, null, null );
if ( m_cursor != null )
{
if ( m_cursor.moveToFirst() )
{
String strRow = "--------------------------------\n";
for(int i = 0 ; i < m_cursor.getColumnCount() ; i++ )
{
strRow += m_cursor.getColumnName(i) + " | ";
}
strRow += "\n";
txtResult.setText( txtResult.getText() + strRow );

do
{
strRow = "";
for(int i = 0 ; i < m_cursor.getColumnCount() ; i++ )
{
strRow += m_cursor.getString(i) + " | ";
}
strRow += "\n";
txtResult.setText( txtResult.getText() + strRow );
} while ( m_cursor.moveToNext() );
}
}
m_cursor.close(); // 커서 닫기
}
catch ( SQLException e )
{
// SQL 예외 처리
Log.e( "SQLException", e.getMessage() );
}
finally
{
// Database 닫기
m_db.close();
Log.i( "SQLite", "Database Close ... OK" );
}
}


Log를 통해 진행 상황을 모니터링 한 내용이다.

05-12 23:26:20.110: INFO/SQLite(213): openOrCreateDatabase ... OK
05-12 23:26:20.190: INFO/SQLite(213): Create Table ... OK
05-12 23:26:20.200: INFO/SQLite(213): Insert data 0 ... OK
05-12 23:26:20.210: INFO/SQLite(213): Insert data 1 ... OK
05-12 23:26:20.240: INFO/SQLite(213): Insert data 2 ... OK
05-12 23:26:20.400: INFO/SQLite(213): Database Close ... OK

<

Original Post : http://neodreamer-dev.tistory.com/437

2010/05/11

[Android Dev.] 편리한 Eclipse 의 Intellisense(?)

이전 글 에서는 Import 되지 않는 Widget 을 쉽게 Import 해 주는 Elipse 의 기능에 대해 다루었는데 다른 기능이 있는지 확인해 보았다.



일단 Eclpise 에서 구문 오류가 발생하면 오류 발생 위치에 빨간 물결 무늬의 밑줄을 출력해 주는데 이 오류 부분에 마우스 커서를 올려 놓으면 이 문제를 해결 하기 위한 팝업 윈도우를 보여준다.



아래는 Activity 의 속한 버튼에 대하여 setOnClickListener 함수를 호출하였을때 발생하는 오류에 대한 팝업 윈도우 이다.





팝업 윈도우에서 맨 마지막에 있는 Let '...' implements 'OnClickListener' 메뉴를 선택하게 되면 해당 class 선언문에 implements OnClickListener 구문이 추가 된다. class 에 implements 구문이 추가되면 abstract method(onClick) 개 구현되지 않았아서 클래스 이름에 에러 표시가 되는데 클래스 이름에 마우서 커서를 올려 놓으면 팝업 윈도우가 활성화 되고 method 를 추가 할 수 있는 메뉴가 나온다.





이 윈도우에서 "Add unimplemented methods" 메뉴를 선택하면 아래와 같은 코드가 class 에 추가 된다.

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
<

Original Post : http://neodreamer-dev.tistory.com/436

[Android Dev.] Import 를 편하게 해주는 Eclipse 기능

안드로이드를 공부하면서 코딩을 하다보면 위젯을 많이 사용하게 된다. 위젯을 처음 사용할때마다 import 를 시켜주어야 하는데 처음에는 일일이 입력을 했었는데 Eclipse 에서 Import 를 아주 편하게 해 주는 기능을 찾았다.


Import 되지 않은 위젯을 사용하게 되면 아래 이미지에서 처럼 ...cannot be resolved to a type 이라는 에러가 발생한다.



이 때, Import 되지 않아 에러가 발생한 위젯에 마우스 커서를 올려 놓으면 잠시후에 아래 이미지와 같은 팝업 윈도우가 나타난다.



이 팝업 윈도우에서 맨 위에 있는 Import... 메뉴를 선택하면 해당 위젯이 Import 가 되고 에러가 사라진다.<

Original Post : http://neodreamer-dev.tistory.com/435

2010/05/06

[Android Dev.] Canvas.drawPosText 의 불편한 진실

이전 Android 에서의 2D Drawing 에 관련한 글을 올렸었는데 그 글에서 drawPosText 함수의 에러에 대한 글을 썼었다.



2010/05/06 - [Dev Story/Android] - [Android Dev.] 2D Drawing



다른 텍스트 출력은 문제가 없는데 drawPosText 함수만 호출하면 문제가 발생하여 그에 대한 원인을 찾느라 시간을 좀 허비했다. API 문서를 좀더 자세히 읽어 봤더라면 시간을 절약할 수 있었을 것이다.



이 함수는 아래와 같은 형태를 갖고 있다.



public void  drawPosText(String  text, float[] pos, Paint  paint)




Parameters

text     The text to be drawn

pos     Array of [x,y] positions, used to position each character

paint     The paint used for the text (e.g. color, size, style)




함수만 보고 이 함수의 기능이 주어진 문자를 주어진 좌표 배열에 출력을 해주는 것이라고 생각하고 아래와 같은 코드로 테스트를 해 보았다.

myPaint.setARGB( 0, 255, 0, 255 );
float[] pos = new float[] {
60, 50,
60, 420
};
canvas.drawPosText( "Android drawPosText", pos, myPaint );





이 코드가 60,50 과 60,420 좌표에 "Android drawPosText"를 그려 줄 것이라고 예상을 했지만 예상을 깨고 에러 화면만을 보여 주었다.

잘못 된 drawPosText 함수 사용에 따른 에러화면

잘못 된 drawPosText 함수 사용에 따른 에러화면



어렵게 예제 자료를 찾아서 확인해 보았더니 drawPosText 함수의 기능을 주어진 문자열의 각 문자를 좌표 배열의 각각의 위치에 출력하는 기능이였다. API 문서에도 아래와 같이 설명이 되어 있었다.


Draw the text in the array, with each character's origin specified by the pos array.




그래서 아래와 같은 코드로 테스트를 해 보았더니 에러 없이 문자를 출력해 주었다. (보라색 비뚤비뚤 Android 글자)

myPaint.setARGB( 128, 255, 0, 255 );
float[] pos = new float[] {
160, 20,
170, 25,
180, 20,
190, 25,
200, 20,
210, 25,
220, 20
};
canvas.drawPosText( "Android", pos, myPaint );



Canvas의 drawPosText 를 이용한 문자 출력

Canvas의 drawPosText 를 이용한 문자 출력





아래 코드를 수행하여 보면 보다 명확하게 알 수 있다.

Paint paint = new Paint();
paint.setColor( Color.GREEN );
float[] pos = new float[] { 60, 50, 60, 420 };
String strMsg = "AB";
canvas.drawPosText( strMsg.toCharArray(), 0, strMsg.length(), pos, paint );



Canvas의 drawPosText 를 이용한 문자 출력

Canvas의 drawPosText 를 이용한 문자 출력



<

Original Post : http://neodreamer-dev.tistory.com/432

[Android Dev.] 2D Drawing

Android 의 2D 드로잉은 Canvas 객체를 이용하여 하는데 Canvas 의 사용에 있어 중요한 객체가 Paint 객체인데 이 Paint 객체에는 드로잉에 필요한 각종 설정을 담고 있다.



위의 이미지를 출력하기위한 코드이다.

public class My2D extends Activity 
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE); // 타이틀바 제거
setContentView( new My2DView( this ) );
//setContentView(R.layout.main);
}

class My2DView extends View
{
public My2DView(Context context)
{
super(context);
}

@Override
public void onDraw(Canvas canvas)
{
// Canvas 배경 설정
canvas.drawColor(Color.parseColor("#030303"));

// Bitmap 을 Canvas 에 뿌리기
Bitmap bm = BitmapFactory.decodeResource(
getResources(), R.drawable.icon);
canvas.drawBitmap(bm, 100, 100, null);

// 드로잉을 위핸 Paint 객체 생성
Paint myPaint = new Paint();
myPaint.setAntiAlias( true ); // AntiAliasing 설정

// 선 그리기
myPaint.setColor( Color.parseColor("#FF0000") ); // 선 색상 설정
canvas.drawLine( 10, 10, 100, 100, myPaint );

// 도형 그리기
myPaint.setARGB( 128, 0, 255, 255 ); // 색상 설정
canvas.drawCircle( 200, 300, 100, myPaint ); // 원 그리기
myPaint.setARGB( 128, 255, 0, 255 ); // 색상 설정
canvas.drawCircle( 100, 250, 100, myPaint ); // 원 그리기

myPaint.setARGB( 128, 255, 0, 0 ); // 색상 설정
// 10x10 크기의 모서리가 둥근 사각형 그리기
canvas.drawRoundRect(
new RectF(150.0f, 60.0f, 300.0f, 160.0f),
10.0f, 10.0f, myPaint );

Path myPath = new Path(); // 패스 생성
// 패스에 시계방향 원형 추가
myPath.addCircle( 200, 300, 100, Direction.CW );
myPaint.setARGB( 128, 0, 255, 255 ); // 색상 설정
myPaint.setTextSize( 15 ); // 폰트 크기 설정
// 패스를 따라 5pixel 떨어진 글자 출력
canvas.drawTextOnPath(
"Hello Android 2D",
myPath, 0.0f, -5.0f, myPaint );

// 문자 출력
myPaint.setColor( Color.CYAN ); // 색상 설정
canvas.drawText( "Android drawText", 20, 20, myPaint );

myPaint.setARGB( 0, 255, 0, 255 );
float[] pos = new float[] { 60, 50, 60, 420 };
//canvas.drawPosText( "Android drawPosText", pos, myPaint );
}
}
}





다른 것은 어렵지 않게 되는데 맨 마지막 시도한 drawPosText 는 잘 되지 않는데 이 함수만 실행하면 프로그램이 다운되어 버린다. 관련 자료를 찾고 있는데 쉽지가 않다.<

Original Post : http://neodreamer-dev.tistory.com/431

2010/05/02

[Android Dev.] Thread 사용하기

Android 의 Thread 를 사용해 보았다. 이미 올린 글에서 Progress Dialog 를 제어 하면서도 사용을 해 보았지만 개념이 쉽게 와 닿지 않아 다시 공부해 보았다.



Android 의 Thread 는 Thread 껍데기를 담당하는 Thread 객체와 실제 실행되는 부분을 담당하는 Runnable 객체로 구성이 되는데 Android 에서는 Multi Thread 를 지원을 하지만 여러 Thread 에서 메인 UI를 제어하지 않고 하나의 Thread 혹은 Handler 라는 객체에서 담당을 하도록 한다.



Thead의 생성의 Thread 객체를 생성할 때, Runnable 객체를 넘겨주어 생성을 한다.


public  Thread  (Runnable  runnable)



Thread 의 테스트를 위해 아래와 같은 메인 UI를 작성하였다.



<?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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<ProgressBar
android:id="@+id/ProgressBar01"
style="?android:attr/progressBarStyleHorizontal"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<Button
android:text="@+id/Button01"
android:id="@+id/Button01"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</LinearLayout>



Progress bar 와 쓰레드 동작시킬 버튼이다.



아래 소스는 아주 간단하게 버튼이 눌렸을 때 Thread를 생성하여 Progress bar를 진행시키는 코드 이다.

ProgressBar progress01;
Button btn01;

progress01 = (ProgressBar)findViewById( R.id.ProgressBar01 );
btn01 = (Button)findViewById( R.id.Button01 );
btn01.setOnClickListener( this );

public void onClick( View v )
{
if ( v == btn01 )
{
new Thread(new Runnable()
{
public void run()
{
progress01.setProgress( 0 );
progress01.setMax( 100 );

for ( int i = 0; i <= 100; ++i )
{
progress01.setProgress( i );

SystemClock.sleep(100);
}

//Toast.makeText(MyThread.this, "Thread Finished", Toast.LENGTH_SHORT).show();
}
}
).start();
}
}





위의 소스 중에 Toast 메세지를 출력하는 부분이 있는데 이 부분의 주석을 해제하고 실행하면 아래와 같은 예외가 발생을 하는데 왜 그런지는 모르겠고 Backgroud Thread 에서 메인 UI를 제어하려고 시도해서 인 것을 생각이 된다.



Handler 를 이용한 Message Queueing 방식

다음은 Handler 를 이용한 message queueing 방식을 이용하는 Thread 를 생성하여 보았다. Thread 에서 Handler 에게 message 를 보내어 Handler 가 받은 message 를 처리하며 UI 작업을 하도록 하는 것이다.

Handler myHandler = new Handler()
{
public void handleMessage( Message msg )
{
if ( msg.what == -1 )
{
progress01.setProgress( 0 );
progress01.setMax( 100 );
}
else if ( msg.what == -100 )
{
Log.i( "INFO", "Finish Thread!!!" );
Toast.makeText(MyThread.this, "Finish Thread!!!", Toast.LENGTH_SHORT).show();
}
else
{
progress01.setProgress( msg.what );
}
}
};

public void onClick( View v )
{
if ( v == btn01 )
{
new Thread(new Runnable()
{
public void run()
{
Message msg = myHandler.obtainMessage();
msg.what = -1;
myHandler.sendMessage( msg );

for ( int i = 0; i <= 100; ++i )
{
msg = myHandler.obtainMessage();
msg.what = i;
myHandler.sendMessage( msg );

SystemClock.sleep(100);
}

msg = myHandler.obtainMessage();
msg.what = -100;
myHandler.sendMessage( msg );
}
}
).start();
}
}





Handler 에게로 Message를 보내기 위해서는 Handler 에서 obtainMessage 함수를 이용해 Message 객체를 받아와서 필요한 정보를 담아 다시 Handler 에게 보내는 것이다. Handler 는 받은 메세지를 순서대로 handleMessage 함수를 통해 처리한다.



이 때, Handler 에게 Message 를 보내는 방법이 여러가지가 있다.


  • final boolean sendMessage(Message  msg)

    Message 를 Handler 의 Message Queue 에 맨 마지막에 추가한다.




  • final boolean sendMessageAtFrontOfQueue(Message msg)

    Message 를 Handler 의 Message Queue 의 맨 앞에 추가한다.




  • boolean sendMessageAtTime(Message msg, long uptimeMillis)

    Message 를 특정 시각(장비 가동후 지난 시간)이 되면 Queue에 추가한다.




  • final boolean sendMessageDelayed(Message msg, long delayMillis)

    Message 를 특정 시간이 지난 후에 Queue에 추가한다.





Foreground Thread에 post 메세지에 의한 방법

또 다른 방법은 UI 핸들링을 하는 Foreground Thread 를 두고 Background Thread 에서 post 함수를 이용하여 처리하는 방식이다.

Handler myHandler = new Handler();

private Runnable fgTask = new Runnable()
{
@Override
public void run()
{
int nCur = progress01.getProgress();

if ( nCur != progress01.getMax() )
{
nCur++;
progress01.setProgress( nCur );
}
else
{
Toast.makeText( MyThread.this, "Finish Thread", Toast.LENGTH_SHORT).show();
}
}
};

public void onClick( View v )
{
if ( v == btn01 )
{
new Thread(new Runnable()
{
public void run()
{
for ( int i = 0; i <= 100; ++i )
{
myHandler.post( fgTask );

SystemClock.sleep(100);
}
}
}
).start();
}
}





위의 두가지 Thread 운영 방식은 유사하게 동작을 하며 버튼이 눌려지면 Thread 를 동작하여 Progress 바의 진행을 시킨다.

동작중인 Progress

동작중인 Progress

동작을 마친 Progress

동작을 마친 Progress



<

Original Post : http://neodreamer-dev.tistory.com/430

2010/04/29

[Android Dev.] ProgressDialog 사용하기



Android 에서 기본적으로 제공하는 ProgressDialog 를 생성하는 것은 간단하다. 아래의 코드만으로 ProgressDialog 가 생성이 된다.

progDialog1 = new ProgressDialog( this );
progDialog1.setProgressStyle( ProgressDialog.STYLE_HORIZONTAL );
progDialog1.setMessage( "Test" );
progDialog1.setCancelable( true );





하지만 이 ProgressDialog 의 진행상황을 반영하기 위해서는 Thread 를 구현해야 한다. 아직은 java의 Thread를 이해하지 못해서 i티거 님의 블로그에 있는 Android Thread 강좌에서 발췌하여 실행시켜 보았다.

static final int MY_PROGRESS1 = 7;

ProgressDialog progDialog1;

:
:

case R.id.BtnProgress1:
{
showDialog( MY_PROGRESS1 );

new Thread(new Runnable()
{
int nProgress;
@Override
public void run()
{
for(nProgress = 0; nProgress <= 100; ++nProgress )
{
runOnUiThread( new Runnable()
{
public void run()
{
progDialog1.setProgress(nProgress);
}
});

SystemClock.sleep(100);
}

dismissDialog( MY_PROGRESS1 );
}
}).start();
}
break;




Thread 에 대해서는 좀 더 공부를 해 봐야 겠다.<

Original Post : http://neodreamer-dev.tistory.com/428

2010/04/28

[Android Dev.] Custom Dialog 생성하기

Custom Dialog 를 만들어보기위해 Android Developer 사이트의 예제(http://developer.android.com/guide/topics/ui/dialogs.html#CustomDialog)를 사용해 보았는데 에러가 발생하였다.

// Custom Dialog 생성 예제
Context mContext = getApplicationContext();
Dialog dialog = new Dialog( mContext );

dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");

TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource( R.drawable.icon );



에러 발생 화면

에러 발생 화면



이 문제가 발생한 것은 Dialog 생성시 생성자에 Context 를 넘겨 주도록 되어 있는데 예제에서는 getApplicationContext() 를 호출하여 Context를 가져와서 넘겨 주었는데 이 부분에 문제가 있어 보인다. Dialog 생성자 호출 부분을 this 로 넘겨주면 에러가 발생하지 않고 Dialog가 생성이 되었다.



Custom Dialog 생성에 사용한 xml layout 리소스

<?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="wrap_content">
<Button
android:text="@+id/Button01"
android:id="@+id/Button01"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
<TextView
android:text="@+id/TextView01"
android:id="@+id/TextView01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<EditText
android:text="@+id/EditText01"
android:id="@+id/EditText01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>



//Context mContext = getApplicationContext();
Dialog dialog = new Dialog( this );

dialog.setContentView( R.layout.mydialog );
dialog.setTitle( "MyDialog 1" );

Button btnMyDlg = (Button)dialog.findViewById( R.id.Button01 );
btnMyDlg.setText( "My Button on Custom Dialog" );

dialog.show();





Android 의 Dialog 는 Title 영역과 View 영역으로 나뉘어 지며 Title 영역은 Title 을 지정하지 않아도 사라지지 않고 자리를 차지 한다. 따라서 Titlte 을 지정하지 않을 경우 아래와 같이 아무것도 표시되지 않은 영역이 남아있다.

Title 을 지정하지 않는 Dialog

Title 을 지정하지 않는 Dialog



Title 이 필요없는 경우에는 AlertDialog 를 이용하여 Dialog 를 생성하는 것도 하나의 방법이다.<

Original Post : http://neodreamer-dev.tistory.com/427

2010/04/27

[Android Dev.] 날짜/시각 선택 대화상자 사용하기

Android 에서 기본으로 제공하는 날짜와 시각을 선택하는 대화상자를 사용하는 예이다.



날짜선택 대화상자(DatePickerDialog)와 시각선택 대화상자(TimePickerDialog) 는 해당 다이얼로그 생성해서 보여주기만 하면 되는데 이때 사용자가 설정한 날짜나 시각을 반영하기 위해서는 약간의 작업이 필요하다.



두 대화상자의 호출은 크게 차이가 없다. 차이가 있다면 다루는 데이터가 차이가 있어 나타나는 것이다. 대화상자를 생성할 때 사용자가 Set 버튼을 누를때 발생할 이벤트를 처리할 Callback 함수를 지정하여 처리하면 된다.


날짜 및 시각 선택 대화상자 호출 버튼

날짜 및 시각 선택 대화상자 호출 버튼

날짜 선택 대화상자

날짜 선택 대화상자

날짜 선택 대화상자

선택된 날짜 처리 화면




DatePickerDialog 생성자


public  DatePickerDialog  (Context  context,



DatePickerDialog.OnDateSetListener  callBack,


int year, int monthOfYear, int dayOfMonth)







Parameter



context : 선택 대화상자가 실행 될 Context (보통 Activity)



callBack : 사용자가 Set 버튼을 선택 했을 때 처리할 Callback 함수



year : 초기 년도



monthOfYear : 초기 월



dayOfMonth : 초기 날짜





DatePickerDialog 대화 상자를 생성할 때 넘겨주는 Callback 함수는 DatePickerDialog.OnDateSetListener 로 아래와 같은 형태를 하고 있다.



public abstract void  onDateSet  (DatePicker  view,



int year, int monthOfYear, int dayOfMonth)







Parameters



view : The view associated with this listener.



year : 선택된 년도.



monthOfYear : 선택된 월 (0-11)



dayOfMonth : 선택 한 날짜






날짜 및 시각 선택 대화상자 호출 버튼

날짜 및 시각 선택 대화상자 호출 버튼

시각 선택 대화상자

시각 선택 대화상자

시각 선택 대화상자

선택된 시각 설정 화면




TimePickerDialog 생성자



public  TimePickerDialog  (Context  context,



TimePickerDialog.OnTimeSetListener  callBack,
int hourOfDay, int minute, boolean is24HourView)







Parameters



context : 선택 대화상자가 실행 될 Context (보통 Activity)


callBack : 사용자가 Set 버튼을 선택 했을 때 처리할 Callback 함수



hourOfDay : 초기 시간



minute : 초기 분



is24HourView : 24시간 사용 여부





TimePickerDialog 대화 상자를 생성할 때 넘겨주는 Callback 함수는TimePickerDialog.OnTimeSetListener 로 아래와 같은 형태를 하고 있다.



public abstract void  onTimeSet  (TimePicker  view, int hourOfDay, int minute)







Parameters



view : The view associated with this listener.



hourOfDay : 선택 된 시각의 시



minute : 선택 된 시각의 분






TextView tvDate;
Button btnDate;
TextView tvTime;
Button btnTime;

Calendar calDateTime = Calendar.getInstance();

// Date Set Listener
DatePickerDialog.OnDateSetListener dateSetListener =
new DatePickerDialog.OnDateSetListener()
{
@Override
public void onDateSet( DatePicker view, int year, int monthOfYear,
int dayOfMonth )
{
calDateTime.set( Calendar.YEAR, year );
calDateTime.set( Calendar.MONTH, monthOfYear );
calDateTime.set( Calendar.DAY_OF_MONTH, dayOfMonth );

String strDate;
strDate =
Integer.toString( year ) + "/" +
Integer.toString( monthOfYear ) + "/" +
Integer.toString( dayOfMonth );
tvDate.setText( strDate );
}
};

// Time Set Listener
TimePickerDialog.OnTimeSetListener timeSetListener =
new TimePickerDialog.OnTimeSetListener()
{
@Override
public void onTimeSet( TimePicker view, int hourOfDay, int minute )
{
calDateTime.set( Calendar.HOUR_OF_DAY, hourOfDay );
calDateTime.set( Calendar.MINUTE, minute );

String strTime;
strTime =
Integer.toString( hourOfDay ) + ":" +
Integer.toString( minute );
tvTime.setText( strTime );
}
};

:
tvDate = (TextView)findViewById( R.id.TVDate );
btnDate = (Button)findViewById( R.id.BtnDate );
btnDate.setOnClickListener( this );
tvTime = (TextView)findViewById( R.id.TVTime );
btnTime = (Button)findViewById( R.id.BtnTime );
btnTime.setOnClickListener( this );
:
case R.id.BtnDate:
{
// Call Date Picker
new DatePickerDialog(
MyDialog.this,
dateSetListener,
calDateTime.get( Calendar.YEAR ),
calDateTime.get( Calendar.MONTH ),
calDateTime.get( Calendar.DAY_OF_MONTH )
).show();
}
break;

case R.id.BtnTime:
{
// Call Time Picker
new TimePickerDialog(
MyDialog.this,
timeSetListener,
calDateTime.get( Calendar.HOUR ),
calDateTime.get( Calendar.MINUTE ),
true
).show();
}
break;
}
:

Original Post : http://neodreamer-dev.tistory.com/426