2010년 7월 8일 목요일

선택한 폴더의 경로 가져오기

void CTestDlg::OnBnClickedButton1()

{

    // TODO: 여기에컨트롤알림처리기코드를추가합니다.

    ITEMIDLIST *pBrowse;

    char pathName[260];

    int count = 0;

     

   

    CString title = (CString)"폴더를선택하세요";

    BROWSEINFO brInfo;

    brInfo.hwndOwner = GetSafeHwnd();

    brInfo.pidlRoot = NULL;

   

    brInfo.pszDisplayName = (LPWSTR)pathName;

    brInfo.lpszTitle = title;

    brInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;

    brInfo.lpfn = NULL;

    brInfo.lParam = 0;

    ::ZeroMemory(pathName, 260);

    pBrowse = SHBrowseForFolder(&brInfo);

    if(pBrowse != NULL)

    {

        ::SHGetPathFromIDList(pBrowse, (LPWSTR)pathName);

       

    }

   

    UpdateData(TRUE);

    m_Path.SetWindowText((LPCTSTR)pathName);

    strPath.Format((CString)"%s\\*.*", pathName);

     

   

    CFileFind find;

   

    CString fName;

   

    find.FindFile((LPCTSTR)strPath);

       

    while(find.FindNextFile())

    {

        fName = find.GetFileName();

        if(find.IsDirectory() != TRUE)

            fileList.Add(fName);

    }

}

선택한 폴더내에 있는 모든파일들을 파일리스트에 저장

환경설정 파일(ini) 사용

INI 파일의 구성은 크게 3부분으로 구성된다.

Section, Key, Value 이다.

[Section]

Key = value

이런 형태라고 볼 수 있다.

정보가져오기

GetPrivateProfileString, GetPrivateProfileInt 함수를 사용.

정보쓰기

WritePrivateProfileString, WritePrivateProfileInt 함수를 사용.

이미 파일이 생성되어 있지 않더라도 위의 쓰기 함수들을 이용하면 자동으로 생성이 되는 것을

확인 할 수 있다.

CString and char*

CString 형을 char문자열로 변환해서 사용하고 싶으시면

CString str = "abcdef";

Char* ch = (char *)(LPCTSTR)str;

이런 식으로 사용하셔도 됩니다.

AfxBeginThread 함수사용

전역변수로 CWinThread 변수 선언

CwinThread *pThread;

원하는 코드내에 다음과 같이 사용

pThread = AfxBeginThread(ThreadChangedMonitor, NULL);

Thread 구현부

UINT ThreadChangedMonitor(LPVOID lParam)

{

    구현

}

지정폴더 변화 감시 함수

자신이 원하는 폴더에서의 변화를 감지하고 싶을때가 있을 것이다.

이러한 변화 감지를 위해서 WIN32 API 는 FindFirstChangeNotification 과 FindNextChangeNotification 함수를 제공한다.

다음은 MSDN에 정의되어 있는 내용이다.

HANDLE WINAPI FindFirstChangeNotification(

__in LPCTSTR lpPathName,

__in BOOL bWatchSubtree,

__in DWORD dwNotifyFilter

);

LpPathName 은 경로, bWatchSubtree 는 하위폴더까지 감시할 것인지를 dwNotifyFilter 는 변화알림에 대한 상태필터이다.

dwNotifyFilter 에 들어갈 값들에 대한 정의이다.

Value

Meaning

FILE_NOTIFY_CHANGE_FILE_NAME

Any file name change in the watched directory or subtree causes a change notification wait operation to return. Changes include renaming, creating, or deleting a file name.

FILE_NOTIFY_CHANGE_DIR_NAME

Any directory-name change in the watched directory or subtree causes a change notification wait operation to return. Changes include creating or deleting a directory.

FILE_NOTIFY_CHANGE_ATTRIBUTES

Any attribute change in the watched directory or subtree causes a change notification wait operation to return.

FILE_NOTIFY_CHANGE_SIZE

Any file-size change in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change in file size only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.

FILE_NOTIFY_CHANGE_LAST_WRITE

Any change to the last write-time of files in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change to the last write-time only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.

FILE_NOTIFY_CHANGE_SECURITY

Any security-descriptor change in the watched directory or subtree causes a change notification wait operation to return.

전역변수 선언하기

MFC 프로그래밍을 하다가 전역변수 선언을 해야 할 때가 있다.

전역변수 선언은 다음과 같이 하면 되겠다.

[Stdafx.h]

extern 자료형 변수명;

[stdafx.cpp]

자료형 변수명;

이렇게 선언을 해주면 프로젝트 내에서라면 어디서든 사용 할 수 있게 된다.

2010년 7월 6일 화요일

또 다시 C++의 세계로.....

또 다시 C++의 세계로 돌아갑니다.

인턴에서 지금 하는 일이 C++ 기반으로 해야하는 거라서 다시 돌아가게 되었네요.

근데 몇년전이라서 제대로 기억이 안나는 ㅠ.ㅠ

서적도 다 집에 있거나 학교에 있고......

틈나는 대로 서점에서 서적좀 구해서 좀 봐야되겠습니다.

새로 입문하는 기분으로 다시 돌파해야겠네요. 쯔~~~업

2010년 7월 2일 금요일

안드로이드 가사지원 음악 플레이어

완성이라고 하기에는 너무 미흡한 나의 첫 안드로이드 어플리케이션이 완성됐다?? 아니 됐었다.

사실 이 포스팅은 제작을 완료한지 좀 지난시점에서야 올리게 됐다 ㅡ,ㅡ;;

머 이래저래 정신이 없었던 것도 있고 귀차니즘도 좀 있고 해서..... ㅋㅋ

어플에 대해서 잠시 소개를??

아직은 부족한 어플이다. 좀 더 보완해야 할 점도 있고........

먼저 제목그대로 가사를 가져오는 어플이다.

프로그램을 실행시켜 보면 음악을 듣고 그 음악에 대한 가사정보를 가져온다.

순전히 나를 위한 어플이다 ㅡ,ㅡ;;;;;

배포를 해 볼까도 했지만 저작권의 문제때문에 배포는 불가!!!

또한 UI가 문제가 많을 것 같기도 하다. 내 모토로이에 최적화된 UI이고 촌스럽기까지 하다 ㅋㅋ

그래도 한 번 써보고 싶으신 분은 개인적으로 연락을 ㅋㅋㅋㅋㅋ

촌스러운 UI 공개 ㅋㅋㅋㅋ 이런쪽은 너무 약하다. ㅋㅋ 천상남자라서 일까....

마지막 사진은 가사정보를 텍스트파일로 저장한 것이다. 그래서 한 번 가사를 봤던 곡은

다시 인터넷 접속 필요없이 로컬로 볼 수 있다. 적은 데이터도 아껴 사용하자?? 이런거?

몰랐었는데 멜론 플레이어도 이런식으로 되어 있더라.

dcf 파일은 모토로이 내부로 돌아가는 drm 서비스 때문에 재생은 가능하나 가사정보는 받아오지 못했다.

결국은 mp3 파일만 가능하다는 결론.

아무튼 허접한 안드로이드 프로젝트는 잠시 접어두어야........

2010년 6월 19일 토요일

Back Key Intercept

기본적으로 안드로이드 에서는 Back Key 를 누르게 되면 Activity Destroy() 함수를 호출하게 된다.

그렇다면 Back Key 에 어떠한 기능을 넣고자 할 때에는 어떻게 해야 할 것인가?

소스에 다음의 코드를 삽입하면 된다.

위의 if 코드에 원하는 코드를 삽입하면 Back Key 를 인터셉트하여 처리할 수 있다.

안드로이드 XmlPullParser

파서의 종류는 여러 개가 있다. 특히 자바에서 많이 쓰이는 DOM 파서와 SAX 파서가 그것인데

안드로이드 에서는 주로 많이 쓰이고 있는 파서가 XmlPullParser 이다. 사용법도 간단하다.

다음과 같은 방법으로 사용하면 된다

.

프로젝트 진행용으로 만든 코드기 때문에 태그부분도 파싱해야 할 경우에는

Case XmlPullParser.START_TAG 부분을 추가해서 코드를 짜면 된다.

액티비티를 투명하게

프로그램을 디자인하다 보면 뒤에 배경을 투명하게 처리하고 싶을 때가 있다.

그럴 경우 onCreate 메소드에 다음과 같은 코드를 추가해주면 된다.

   

getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND, WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

이렇게 추가해주면 다음과 같은 결과를 볼 수 있다.

리스트뷰 활용


리스트뷰 를 사용을 하게 되면 리스트뷰에 나와있는 리스트들을 클릭하면 어떤 반응을 할 지 정해야 한다.

그런 코드를 짜고자 할 때에는 위와 같이 OnListItemClick 메소드를 오버라이드 시켜주면 된다.

알송가사 서버?

진행중인 프로젝트가 알송가사 서버를 사용해야 하기 때문에 어떻게 가사를 정확하게 받아와야 하는지 알아야만 했다.

그린세상님의 BLOG 에서 많은 정보를 얻어 올 수 있었다.

먼저 MP3파일의 구조부터 확인해보자.

MP3 파일의 기본적인 구조는 이러하며 ID3 TAG는 버전이 V1.0, V1.1, V2.0 3가지가 있다.

가사 요청 PACKET 내용

<?xml version='1.0' encoding='UTF-8'?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://www.w3.org/2003/05/soap-envelope' xmlns:SOAP-ENC='http://www.w3.org/2003/05/soap-encoding' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:ns2='ALSongWebServer/Service1Soap' xmlns:ns1='ALSongWebServer' xmlns:ns3='ALSongWebServer/Service1Soap12'>

<SOAP-ENV:Body>

<ns1:GetLyric5>

<ns1:stQuery>

<ns1:strChecksum>

MD5

</ns1:strChecksum>

<ns1:strVersion>1.93</ns1:strVersion>

<ns1:strMACAddress></ns1:strMACAddress>

<ns1:strIPAddress></ns1:strIPAddress>

</ns1:stQuery>

</ns1:GetLyric5>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

MD5 값에 들어갈 내용은 MP3파일에서 ID태그 부분을 제외한 순수 음악 데이터부터 163840 바이트를 읽어서 MD5 HASH 처리한 값이 들어가게 된다.

2010년 4월 11일 일요일

안드로이드 Application Fundamentals part 3/3

안드로이드의 각 컴포넌트(액티비티, 서비스, 브로드캐스트 리시버)들은 자신들만의 LifeCycle, 즉 생애주기를 가지고 있다.

여기서는 각각의 생애주기들에 대해서 설명해보려고 한다.

1. Activity Lifecycle

액티비티의 상태

  1. 활성(Active)
  • 현재 화면에 액티비티가 표시되는 상태
  1. 일시정지(Paused)
  • 화면에서 액티비티가 보이지만 사용자와 상호작용 할 수 없는 상태, 즉 화면에는 보이지만

    포커스가 없이 흐려진 상태를 말하기도 합니다.

  1. 정지(Stopped)
  • 다른 액티비티에 의해서 화면이 완전히 가려진 상태를 말합니다.

액티비티 상태변화에 따른 메소드 호출

Method

Description

Killable?

다음 호출자

onCreate()

액티비티가 생성될 시에 호출

No

onStart()

 

onRestart()

액티비티가 정지하였다가 다시 시작하게 될 때 호출

No

onStart()

onStart()

액티비티가 사용이 가능하게 되기전에 호출

No

onResume() 
or
onStop()

 

onResume()

액티비티가 사용자와 상호작용하기 전에 호출

유의할점은 액티비티 스택의 제일 위에 있어야 함.

No

onPause()

onPause()

액티비티가 사용자와 상호작용을 중단할 때 호출

Yes

onResume() 
or
onStop()

onStop()

액티비티가 완전히 화면에서 사라질 때 호출

Yes

onRestart()
or
onDestroy()

onDestroy()

액티비티가 완전종료될 때 호출

Yes

nothing

액티비티 생애주기 다이어그램

Saving Activity State

안드로이드는 메모리절약을 위해 액티비티를 강제 종료 시킬수 있다. 하지만 사용자는 그 액티비티의 이전 상태를 원할수도 있는데
강제종료되기 전의 상태를 보관하기 위해 onSaveInstanceState 메소드를 구현할 수 있다. 이 메소드는 onPause 메소드가 호출되기전에 호출한다.

Cordinating Activites

하나의 액티비티가 다른 액티비티를 호출할 때 이 2개 이상의 액티비티들은 생명주기를 경험하게 된다.

  1. 현 액티비티의 onPause() 호출
  2. 다음 액티비티의 onCreate() -> onStart() -> onResume() 호출
  3. 다음 액티비티가 멈추게 될경우 onStop() 호출후 이전 액티비티에서 onResume() 호출

2. Service Lifecycle

서비스의 생명주기 메소드들은 액티비티 메소드들이 Protected 인데 반해 Public 이다.

위의 오른쪽 그림과 같이 서비스가 다른것들에 의해 바인드 되어 지는 것을 허용한다면 onBind(), onUnbind(), onRebind() 메소드들이 호출된다.

3. Broadcast Receiver Lifecycle

브로드캐스트 리시버는 하나의 콜백 메소드만을 가진다.

  • void onReceive(Context curContext, Intent broadcastMsg)

리시버에 브로드캐스트 메시지가 도착하면 onReceive() 메소드가 호출해 메시지 포함하는 인텐트 오브젝트를 전다한다.
브로드캐스트 리시버는 위 메소드가 실행하는 동안만 활성화가 이루어진다.
활성화된 브로드캐스트 리시버를 가진 프로세스는 강제종료 되는 것으로부터 보호된다.

4. Processes and Lifecycle

안드로이드는 메모리 부족사태가 오면 오래된 프로세스를 죽일 수 밖에 없는데, 어떤 프로세스를 유지하고 어떤 프로세스를 죽일 것인지 결정하기 위해
중요성 계층구조(importance hierarchy)를 이용한다. 이 중요성 계층구조를 통해서 어떤 것이 더 중요한지 결정을 내릴 수 있다. 중요성의 순서는 다음과 같다.

  1. 포어그라운드 프로세스는 사용자가 현재 수행하고 있는 것을 위해 요구되는 프로세스이다. 만약 하나의 프로세스가 아래와 같은 조건을 보유하고 있다면
    그것은 포어그라운드 프로세스로 간주된다.
    1. 프로세스가 사용자와 상호작용하는 액티비트를 실행하고 있다.
    2. 프로세스가 사용자와 상호작용하고 있는 액티비티에 연결되어진 서비스를 포함하고 있다.
    3. 프로세스가 생명주기 콜백메소드중 하나를 실행하고 있는 서비스 오브젝트를 가지고 있다.
    4. 프로세스가 onReceive() 메소드를 실행하고 있는 브로드캐스트 리시버 오브젝트를 가지고 있다.
  2. 비저블(visible) 프로세스는 어떤 포어그라우든 컴포넌트도 보유하지 않은 프로세스이다. 그러나 그것은 여전히 스크린 상에서 사용자가 보는 것에 영향을
    미칠 수 있다. 만약 아래와 같은 조건을 보유하고 있다면 이 프로세스는 비쥬얼한 것으로 간주된다.
    1. 프로세스가 포어그라운드가 아니지만 여전히 사용자에게 보이는 액티비트를 보유하고 있다.
    2. 프로세스가 비저블 액티비티에 연결된 서비스를 포함하고 있다.
  3. 서비스 프로세스는 startService() 메소드를 사용해서 시작된 서비스를 실행하고 있으면서, 위의 2개의 카테고리에 속하지 않는 프로세스이다. 비록 서비스
    프로세스는 사용자가 보는 어떤 것과도 직접 결부되지는 않지만 그것들은 일반적으로 사용자가 신경쓰는 것들을 하고있다. 그래서 시스템은 모든 포어그라운드
    프로세스와 비저블 프로세스를 계속 유지할 정도로 메모리가 충분치 않는 경우를 제외하고는 서비스 프로세스를 유지한다
  4. 백그라운드프로세스는 현재 사용자의 눈에 보이지 않는 액티비티를 보유하고 있는 프로세스이다. 이들 프로세스는 직접적으로 사용자의 행위에 영향을 주지 않으며, 포어그라운드, 비저블,
    서비스 프로세스를 위한 메모리 재요청을 위해 언제든 강제 종료될 수 있다. 통상적으로 많은 백그라운드 프로세스가 존재하고 있으며, 그러므로 그것들은 가장 최근에 사용자에게 보여진
    액티비티를 가진 프로세스가 가장 최후에 강제 종료될 수 있도록 하기 위한 LRU(Least Recently Used, 최근에 가장 적게 사용된) 목록으로 관리된다. 만약 액티비티가 정확한 생명주기
    메쏘드들을 구현하고 있고 그것들의 현재 상태를 정확하게 포착하고 있다면, 그것이 속한 프로세스가 강제종료되는 것은 사용자에게 유해한 영향을 끼치지 않을 것이다.
  5. 엠프티(empty) 프로세스는 어떤 형태의 활성화된 컴포넌트도 보유하고 있지 않는 프로세스이다. 이러한 프로세스를 유지하는 유일한 이유는, 그 안에서 다음 번에 실행되어야 하는 컴포넌트의 구동시간을 개선하기 위한 캐쉬cache로써의 역할 때문이다. 시스템은 프로세스 캐쉬와 하단에 놓여있는 커널 캐쉬 간의 시스템 전역에 걸친 리소스들에 대한 균형을 유지하기 위해 가끔 이런 프로세스를 강제 종료시킨다.

2010년 4월 10일 토요일

안드로이드 Application Fundamentals part 2/3

Activities and Tasks

하나의 액티비티는 또 다른 액티비티를 시작시킬 수 있다. 그렇게 시작시킬 수 있는 액티비티에는 다른 애플리케이션이 정의한 액티비티도 포함된다. 안드로이드에는 그 위치를 보여줄 수 있는 액티비티가 존재한다. 그러므로 여러분의 액티비티에 필요한 모든 것은, 인텐트 오브젝트에 필요한 정보들을 추가한 후 그것을 startActivity()의 파라미터로 전달하는 것이다.

맵 뷰어는 다른 애플리케이션 내에 정의되어 있고 다른 애플리케이션 프로세스 상에서 실행되고 있음에도 불구하고, 사용자에게 맵 뷰어는 여러분의 액티비티처럼 동일한 애플리케이션의 일부분처럼 비춰질 것이다. 안드로이드는 두 개의 액티비티를 같은 태스크내에 유지함으로써 이런 사용자 경험user experience을 유지시킨다. 그것은 하나의 스택 내에 정렬된 관련 액티비티들의 그룹이다. 일반적으로, 그것은 사용자가 애플리케이션 런처에서 선택했던 액티비티이다. 스택의 최상위 액티비티는 현재 실행중인 액티비티이다. 그것은 사용자 액션을 위해 포커스 된 액티비티이다. 하나의 액티비티가 다른 것을 시작할 때 새로운 액티비티는 스택에 푸쉬(push)되며, 실행중인 상태의 액티비티가 된다. 이전 액티비티는 여전히 스택에 남아있다. 사용자가 BACK 키를 누를 때 현재의 액티비티는 스택으로부터 팝(pop)되며, 이전의 액티비티는 실행중인 액티비티로 재개resume된다.

태스크 안에서 모든 액티비티는 하나의 단위로 함께 움직인다. 전체 태스크(전체 액티비티 스택)는 포어그라운드foreground로 가져와 질 수 있으며, 또한 백그라운드background로 보내질 수도 있다. 사용자가 HOME 키를 누르고 애플리케이션 런처로 간다. 그리고 새로운 애플리케이션(실제로 새로운 태스크)을 선택한다. 현재 태스크는 백그라운드로 가고, 새로운 태스크에 대한 루트 액티비티가 보여진다. 그런 다음 잠시 후, 사용자가 홈 스크린으로 돌아가서 이전 애플리케이션(이전 태스크)을 다시 선택한다. 스택에 모두 네개의 액티비티를 가지고 있는 그 태스크가 앞으로 온다. 그곳에서 사용자가 BACK 키를 누르면, 스크린에는 사용자가 조금 전에 떠났던 이전 태스크의 루트 액티비티가 보여지지는 않는다. 대신에 스택의 최상위의 액티비티가 제거되고 같은 태스크 내의 이전 액티비티가 보여진다.

 

Affinities and new tasks

디폴트로 애플리케이션 내의 모든 액티비티는 서로에 대해 하나의 어피니티affinity를 갖는다. 즉, 동일 태스크에 속하는 그것들 모두에 대해 하나의 설정preference이 존재한다. 하지만 각각의 액티비티에 대한 개별적인 어피니티affinity가 <activity> 엘리먼트의 task Affinity 애트리뷰트를 통해 설정될 수 있다. 다른 애플리케이션들내에 정의된 액티비티들이 하나의 어피니티affinity를 공유할 수도 있으며, 또한 같은 애플리케이션 내에 정의된 액티비티들에게 다른 어피니티affinity가 지정될 수도 있다. 어피니티affinity는 두 가지의 조건하에서 동작하게 된다. 액티비티를 런치하는 인텐트 오브젝트가 FLAG_ ACTIVITY_ NEW_ TASK 플래그를 포함하고 있고, 그리고 액티비티에 allowTaskReparenting 애트리뷰트 값이 “true”로 설정되어 있을 때이다.

 

Launch modes

네 개의 다른 런치 모드가 <activity> 엘리먼트의 launchMode 애트리뷰트에 지정될 수 있다.

"standard" (the default mode)

"singleTop"

"singleTask"

"singleInstance"

 

어떤 태스크가 인텐트에 응답하는 액티비티를 보유할 것인가? “standard” 와 “singleTop” 모드에 대해서 인텐트 오브젝트가 FLAG_ACTIVITY_NEW_TASK 플래그를 가지지 않았다면, 그것은 인텐트를 만들었던(그리고 startActivity()를 호출했던) 액티비티가 있는 태스크이다. FLAG_ACTIVITY_NEW_TASK 플래그를 인텐트 오브젝트가 포함하고 있는 경우라면, 이전 섹션의 “어피니티와 신규 태스크”에서 설명된 것처럼 다른 태스크가 선택된다.

 

새로운 클래스 인스턴스가 새로운 인텐트를 처리하기 위해 런치될 것인가? 디폴트 “standard” 모드에 대해서는, 새로운 인스턴스가 모든 신규 인텐트에 응답하도록 생성된다. 각각의 인스턴스는 단지 하나의 인텐트를 처리한다. “singleTop” 모드에 대해서는, 만약 그것이 타겟target 태스크의 최상위 액티비티 스택에 존재한다면, 이미 존재하는 클래스 인스턴스가 신규 인텐트 처리를 위해 재사용된다. 만약 그것이 최상위에 존재하지 않다면 재사용되지 않는다. 대신 신규 인텐트를 위한 새 인스턴스가 생성되고, 스택에 푸쉬push된다.

그러나 D의 런치 모드가 “singleTop” 이라면, (그것이 스택의 최상위에 있기 때문에) 기존에 있는 인스턴스가 새로운 인텐트를 처리하게 될 것이고 스택은 A-B-C-D로 남는다. 반면 도착한 인텐트가 타입 B 액티비티에 대한 것이라면, B가 “standard”든 “singleTop”이든 상관없이 (B가 스택의 최상위에 없기 때문에) 새로운 B 인스턴스가 런치될 것이다. 그러므로 결과적으로 스택은 A-B-C-D-B가 될 것이다

 

Clearing the stack

사용자가 오랫동안 하나의 태스크를 떠나 있다면, 시스템은 루트 액티비티를 제외한 모든 액티비티를 태스크에서 제거한다. 사용자가 다시 그 태스크로 돌아왔을 때, 오직 최초의 액티비티만이 존재한다는 것 이외에 그것은 사용자가 그것을 떠났을 때와 같다. 이 아이디어는, 어느정도 시간이 지난 후 사용자는 그들이 이전에 하던 것을 포기했을 것이라는 것이고 뭔가 새로운 것을 시작하기 위해 그 태스크로 돌아왔을 거라고 생각하는 것이다.

alwaysRetainTaskState 애트리뷰트

만약 태스크의 루트 액티비티에 이 애트리뷰트가 “true”로 설정된다면, 앞서 언급된 디폴트 동작은 발생하지 않는다. 태스크는 긴 시간 지난 이후에도 스택 내의 모든 액티비티들을 유지한다.

clearTaskOnLaunch 애트리뷰트

만약 태스크의 루트 액티비티에 이 애트리뷰트가 “true”로 설정된다면, 사용자가 태스크를 떠났다가 다시 돌아올 때마다, 스택은 루트 액티비티를 제외하고 모두 제거된다. 바꾸어 말하면 그것은 alwaysRetainTaskState와 정반대이다. 일시적으로 떠났다고 하더라도, 사용자는 항상 그것의 최초 상태로 태스크에 돌아오게 된다.

finishOnTaskLaunch 애트리뷰트

이 애트리뷰트는 clearTaskOnLaunch와 비슷하다. 그러나 그것은 전체 태스크가 아닌, 하나의 액티비티에서 동작한다. 그리고 그것은 루트 액티비티를 포함한 모든 액티비티를 제거할 수 있다. 이것이 “true”로 설정되면, 액티비티는 현재 세션에 대한 태스크의 부분으로만 남게된다. 만약 사용자가 떠났다가 태스크에 돌아오면 그것은 더 이상 존재하지 않는다.

스택에서 액티비티가 제거되도록 하는 다른 방법이 있다. 만약 인텐트 오브젝트가 FLAG_ACTIVITY_CLEAR_TOP 플래그를 가지고 있고, 타겟target 태스크가 그것의 스택에 해당 인텐트를 처리해야 하는 타입의 액티비티 인스턴스를 이미 가지고 있다면, 그것이 스택의 최상위 존재해서 그 인텐트에 응답할 수 있도록 하기 위해 그 위의 모든 액티비티들은 제거된다. 만약 지정된 액티비티의 런치 모드가 “standard”라면, 그것 또한 스택에서 제거될 것이고, 새로운 인스턴스는 도착한 인텐트를 처리하기 위해 시작될 것이다. 왜냐하면 런치 모드가 “standard” 일 때 새로운 인스턴스는 새로운 인텐트를 위해 항상 생성되기 때문이다.

 

Starting tasks

액티비티는 그것의 인텐트 필터에 액션을 “android.intent.action.MAIN”으로 지정하고 카테고리를 “android.intent.category.LAUNCHER”로 지정함으로써, 태스크에 대한 시작점으로 설정된다(이 필터 타입의 예제가 이전의 인텐트 필터 섹션에 있다). 이런 종류의 필터는 액티비티에 대한 아이콘과 라벨이 애플리케이션 런처에서 보여지도록 하며, 사용자에게 태스크를 런치하고 태스크가 런치된 이후 언제든 그 태스크로 다시 돌아갈 수 있는 두 가지 방법 모두를 제공한다.

이 두 번째 능력은 중요하다. 사용자는 태스크를 떠날 수도 있어야 하고, 나중에 그것으로 돌아갈 수도 있어야 한다. 이런 이유로, 액티비티가 태스크를 항상 시작시키는 두 개의 런치 모드, 즉 “singleTask”와 “singleInstance”는 액티비티가 MAIN 과 LAUNCHER 필터를 가지고 있을 때만 사용되어야 한다. 예를 들어 만약 이 필터가 없다면 무슨 일이 발생할까? 상상해 보라. 인텐트는 새로운 태스크를 시작하는 “singleTask” 액티비티를 런치하고, 사용자는 그 태스크에서 일을 하면서 약간의 시간을 보낸다. 사용자는 그런 다음 HOME 키를 누른다. 태스크는 이제 뒤에 놓이고, 홈스크린에 의해 가려진다. 그리고 그것은 애플리케이션 런처에서 나타나지 않기 때문에, 사용자는 그곳에 다시 돌아갈 방법이 없게 된다.

FLAG_ACTIVITY_NEW_TASK 플래그에도 비슷한 어려움이 수반된다. 만약 이 플래그가 새로운 태스크를 시작하는 액티비티를 만들고, 사용자가 그곳을 떠나기 위해 HOME 키를 누른다면, 사용자가 그곳으로 다시 돌아갈 수 있는 몇 가지 방법이 있어야 한다. 노티피케이션Notification 매니저와 같은 어떤 엔티티entity들은, 결코 그것들의 소유 영역이 아닌, 외부 태스크에서 액티비티를 시작시킨다. 그러므로 그들은 startActivity()에 파라미터로 전달하는 인텐트에 항상 FLAG_ACTIVITY_NEW_TASK를 놓는다. 만약 여러분이 이 플래그를 사용할 수도 있는 외부 엔티티에 의해 호출될 수 있는 액티비티를 가지고 있다면, 사용자가 그것이 시작된 태스크로 다시 돌아갈 수 있는 독자적인 방법을 갖게 하도록 주의하라.

 

참고 문서 : http://developer.android.com/guide/topics/fundamentals.html

 

안드로이드 Application Fundamentals part 1/3

Application Fundamentals

 

 안드로이드 application Java 프로그래밍 언어로 작성된다. 컴파일된 Java 코드는 SDK에 존재하는 aapt 유틸리티에 의해 안드로이드 패키지로 묶여지며, 이렇게 하나로 압축된 아카이브(archive) 파일에는 .apk 접미사가 부쳐진다. 이 파일은 모바일 디바이스에 안드로이드 application을 배포하고 설치하기 위한 수단이다.

 

l  기본적으로 모든 application은 자신의 리눅스 프로세스 내에서 실행된다. 안드로이드는 임의의 application 코드가 실행될 필요가 있을 때 그 프로세스를 시작시키며, 그것이 더 이상 필요치  않고 다른 application이 시스템 자원을 요구할 때 그 프로세스를 종료시킨다.

 

l  각각의 프로세스는 자기 자신의 Java 가상머신을 가진다. 그러므로 application 코드는 다른 모든 application 코드와는 격리되어 실행된다.

 

l  각각의 application에는 고유한 리눅스 User ID가 부여된다. Application을 구성하는 파일들은 해당 사용자와 해당 application 그 자신에게만 보여지도록 권한이 설정된다.

 

 두개의 application에 대해 동일한 User ID를 공유할 수 있도록 배치하는 것이 가능하다. 그런 경우에 두 개의 application은 각자 다른 application의 파일을 볼 수 있을 것이다. 시스템 자원을 절약하기 위해 동일한 ID를 가지는 application은 또한 동일한 리눅스 프로세스 안에서 실행되도록 배치되며, 동일한 가상머신을 공유한다.

 

Application Components

 안드로이드의 가장 큰 특징으로는 한 application에서 엘리먼트의 사용을 허가 할 경우 다른 application에서의 사용이 가능하다. 이런 작업을 위해서는 어떤 application의 특정 영역이 필요할 때 시스템은 application 프로세스를 시작할 수 있어야 하고, 그 영역에 대한 Java 오브젝트를 인스턴스화 할 수 있어야 한다. 그러므로 안드로이드 application은 다른 대부분의 시스템에서의 application와 달리 하나의 시작점을 가지지 않는다. 대신 시스템이 그것을 필요로 할 때 인스턴스화하고 실행할 수 있는 기본적인 컴포넌트들이 존재한다.

 

Activities

 액티비티는 사용자가 착수할 수 있는 하나의 포커스 된 시도에 대한 비쥬얼 사용자 인터페이스를 나타낸다. 예를 들어 액티비티는 사용자들이 선택할 수 있는 메뉴 아이템 리스트를 나타내거나 사진과 함께 그것의 캡션을 나타낼 수도 있다.

 하나의 application은 단지 한 개의 액티비티로 구성될 수도 있으며, 몇 개의 액티비티를 포함하고 있을 수도 있다.

 각각의 액티비티에는 그리기draw가 가능한 하나의 디폴트 윈도우가 부여된다. 하나의 액티비티는 또한 추가적인 윈도우(팝업 Dialog)를 사용할 수 있다.

 뷰 계층구조는 Activity.setContentView() 메소드에 의해 액티비티의 윈도우 내에 위치하게 된다. 그 컨텐트뷰는 그 계층구조의 최상위에 있는 뷰 오브젝트이다.

 

Services

 서비스는 사용자에게 보여지는 인터페이스를 가지지 않는다. 하지만 오히려 정해지지 않은 시간동안 백그라운드에서 실행된다. 예를 들어 서비스는 사용자가 다른 일에 주의를 기울이는 동안에 백그라운드 음악을 재생할 수 있다. 또한 그것은 네트워크 상에서 데이터를 가져오거나, 또는 어떤 것을 계산해서 그 결과를 필요로 하는 액티비티에게 제공할 수도 있다.

 액티비티와 다른 컴포넌트처럼, 서비스도 application 프로세스의 메인 쓰레드 내에서 실행되므로 서비스가 다른 컴포넌트 또는 사용자 인터페이스에 의해 방해 받지 않도록 하기 위해서 음악 재생같이 시간을 요하는 작업들을 위해서는 종종  또 다른 쓰레드를 만들어서 작동시킨다.

  

Broadcast receivers

 브로드캐스트 리시버는 아무 것도 하지 않는 컴포넌트지만, 브로드캐스트 공지를 수신하고 응답한다. 많은 브로드캐스트는 시스템 코드에서 발생된다.(시간대 변경, 배터리 부족, 사진 촬영, 언어설정 변경 등에 대한 Message )

 브로드캐스트 리시버는 사용자 인터페이스를 보여주지 않지만 그것이 수신한 정보에 응답하는 액티비티를 시작하거나, 또는 사용자에게 알려주기 위해 노티피케이션 매니저를 사용할 수 있다.

 

Content providers

 컨텐트 프로바이더는 다른 애플리케이션에게 유용한 특정 애플리케이션의 데이터 집합을 만든다. 그 데이터는 파일 시스템 내, SQLite 데이터베이스 내, 또는 의미있는 다른 어떤 방식으로 저장될 수도 있다.

 

 

Activating components: intents

 컨텐트 프로바이더는 컨텐트 리졸버 요청의 대상이 될 때 활성화된다. 하지만 다른 세 가지 컴포넌트, 즉 액티비티, 서비스, 그리고 브로드캐스트 리시버는 Intent라 불리는 비동기적인 메시지에 의해 활성화된다. Intent는 컨텐트 메시지를 보유하고 있는 Intent 오브젝트다. Intent는 액티비티와 서비스에 대해서, 그것에게 요청되는 액션을 가리키고 그 액션이 처리해야 하는 데이터의 URI를 나머지 다른 것들과 함께 명시한다.

 

각각의 컴포넌트 타입을 활성화하기 위한 별도의 메소드가 있다.

l  액티비티는 Intent오브젝트를 Context.startActivity() 또는 Activity.startActivityForResult()에 파라미터로 전달함으로써 실행된다. 이것에 응답하는 액티비티는 getIntent() 메소드를 호출함으로써 그것을  실행하도록 한 초기 Intent를 볼 수 있다.

l  하나의 액티비티는 흔히 그 다음번 액티비티를 시작시킨다. 만약 그것이 자신이 시작시킨 액티비티로부터 결과를 리턴받고자 한다면, 그것은 start Activity() 대신에 startActivityForResult()를 호출해야 한다.

 

l  서비스는 Context.startService()Intent오브젝트를 파라미터로 전달함으로써 시작된다.. 안드로이드는 서비스의 onStart() 메소드를 호출하고 그곳에 Intent오브젝트를 전달한다.

 

l  applicationContext.sendBroadcast(), Context.sendOrderedBroadcast(), 그리고 Context.sendStickyBroadcast() 같이 다양하게 변형된 메소드에 Intent오브젝트를 전달함으로써 브로드캐스트broadcast를 만들어낼 수 있다.

 

Shutting down components

컨텐트 프로바이더는 컨텐트 리졸버의 요청에 응답하는 동안에만 활성화되어 있다. 그리고 브로드캐스트 리시버도 브로드캐스트 메시지에 응답하는 동안에만 활성화되어 있다. 그러므로 이러한 컴포넌트는 명시적으로 종료시켜야 할 필요가 없다. 반면, 액티비티는 사용자 인터페이스를 제공한다. 이것은 사용자와 오랜시간 동안 대화를 하며 활성화 상태로 남아 있다. 심지어는 대화가 지속될 수 있는 한, 그것이 사용되지 않는idle 상태에도 활성화 상태로 남는다.

l   액티비티는 finish() 메소드의 호출을 통해 스스로 종료될 수 있다. 그리고 finishActivity()를 호출함으로써, 다른 액티비티를 종료시킬 수도 있다.

l   서비스는 stopSelf() 메소드의 호출이나 Context.stopService()를 호출함으로써 종료될 수 있다.

 또한, 컴포넌트는 그것이 더 이상 사용되지 않을 때, 또는 안드로이드가 더 많은 활성화된 컴포넌트를 위해 메모리를 회수해야 할 때 시스템에 의해 종료될 수 있다.


 

The manifest file

안드로이드는 애플리케이션의 컴포넌트를 시작하기 전에, 컴포넌트의 존재를 인식해야 한다. 그러므로 애플리케이션은 매니페스트 파일에 그것들의 컴포넌트를 선언한다. 그리고 그 매니페스트 파일은 안드로이드 패키지, .apk 파일 내에 포함된다. 이 패키지는 애플리케이션의 코드, 파일, 리소스 또한 보유하고 있다.

 그러나 매니페스트의 주요한 작업은 안드로이드에게 application의 컴포넌트를 알려주는 것이다.

 

Intent filters

Intent 오브젝트는 그것의 대상이 되는 컴포넌트를 명시적으로 지정할 수 있다. 만약 그렇다면, 안드로이드는 (매니페스트 파일 내의 선언들에 기초해서) 그 컴포넌트를 찾아 내고 그것을 활성화한다. 하지만 타겟이 명시적으로 지정되지 않으면, 안드로이드는 Intent를 처리할 수 있는 최선의 컴포넌트를 찾아내야 한다. 이것은 해당 Intent 오브젝트와 그 Intent의 잠재적 대상이 될 수 있는 컴포넌트들의 Intent 필터를 비교함으로써 이루어진다. 컴포넌트의 Intent 필터는 안드로이드에게 해당 컴포넌트가 처리할 수 있는 Intent의 종류를 알려준다. 컴포넌트에 대한 다른 필수적인 정보들처럼, Intent 필터도 매니페스트 파일 내에 선언된다.

컴포넌트는 인텐트 필터를 얼마든지 가질 수 있다. 그리고 각각의 필터는 각기 다른 능력capability을 선언할 수 있다. 만약 컴포넌트가 어떤 필터도 가지지 않는다면, 그것은 인텐트의 대상으로 컴포넌트를 명시적으로 지정하는 인텐트에 의해서만 활성화될 수 있다.

코드 내에서 생성되어 등록된 브로드캐스트 리시버에 있어서, 인텐트 필터는 IntentFilter 오브젝트에 의해 직접적으로 인스턴스화 된다. 나머지 모든 필터들은 매니페스트 내에서 설정된다.

 

참고 문서 : http://developer.android.com/guide/topics/fundamentals.html

2010년 4월 4일 일요일

Symbian OS 설치하기

Symbian OS 설치하기

Symbian OS를 지원하는 어플리케이션을 만들기 위해서는 당연히 개발환경이 구비되어 있어야 합니다. 이 페이지 에서는 Symbian 개발을 위해 쓰이는 언어중 C++를 선택해서 개발환경을 준비하는 것을 포스팅 해봅니다.

먼저 설치를 위해 필요한 툴과 킷트 들을 다운로드 받아야 합니다.

먼저 Active Perl을 설치하도록 합니다.

별다른 설정값을 줄 필요없이 다음으로 넘어가시면 무난하게 설치가 됩니다.

다음으로 ADT를 설치하시고

후에 다운받은 SDK 압축파일을 압축을 풀어준후에 설치를 진행하시면

Symbian Os 어플리케이션을 개발하기 위한 준비는 끝나게 됩니다.

C++기반으로한 Symbian OS 개발은 Carbide C++라는 툴을 통해서 개발을 하게 되는데 설치를 하셨다고해서 바탕화면에 바로가기가 생성이 안되니

시작->모든프로그램->Symbian Foundation ADT 1.4->Carbide C++ 로 찾아가셔서 실행파일을 실행시키면 툴을 실행하실 수 있습니다.

처음 실행을 하시게 되면 다음과 같이 workspace를 지정해줘야 하게 되는데 기본적으로 되어 있으니 바로 OK를 눌러주셔도 무방합니다.

실행을 하시면 다음과 같은 화면이 뜨면서 시간이 꽤 걸릴수도 있으니 차분히 기다리길 바랍니다.

첫 화면은 어디선가 많이 본 것 같다고 생각하시는 분들이 많을 겁니다. JAVA 개발에 주로 많이 쓰이는 툴인 Eclipse와 상당히 유사한 외형을 가진 툴입니다.

오늘은 간단하게 HelloWorld를 찍어보는 어플을 제작해서 에뮬레이터로 실행을 해볼 것 입니다. 참고로 Symbian Emulator는

먼저 File->New->Symbian OS C++ Project를 클릭해주시면 새로운 프로젝트를 생성하기 위한 다이얼로그가 화면에 나오게 됩니다.

위의 화면에서 GUI Application with UI Designer를 선택하시고 Next를 눌러주시면 됩니다.

위와 같은 화면이 나오면 Project name 란에 프로젝트 이름을 적어주시면 됩니다. HelloWorld라는 어플리케이션을 제작할 것이니 저는 HelloWorld라고 적고 진행해 나가겠습니다.

다음은 Symbian OS SDK를 정하는 화면입니다. 저희가 다운로드 받아서 설치한 것을 선택해서 진행할 수 있습니다. 나중에 다른 SDK로 개발하실 분들은 다른버전을 다운로드 받아서 설치하시고 개발해 나가시면 됩니다. 원하는 버전을 선택하고 Next를 눌러서 진행을 해줍니다.

다음은 어플리케이션 속성페이지 입니다. 별로 체크할부분은 없으니 Next로 넘어가주시면 됩니다.

다음은 UI 디자인을 선택하는 화면인데 간단하게 HelloWorld를 찍을 어플리케이션이므로 empty를 선택하시고 Next로 넘어가시면 됩니다.

Container의 타입과 이름을 설정하는 부분인데 기본값들이 이미 들어가져 있으므로 수정없이 넘어갈 수 있습니다. 그 밑의 support view switching에도 체크가 되어 있습니다. 저희가 지금 만들 HelloWorld는 하나의 View 만으로 구성되어 있지만 나중에 확장시키는데 편하게 하기 위해서 저 부분은 체크를 해주시는게 좋습니다.

다음과 같이 프로젝트를 생성하게 되면 왼쪽의 프로젝트창에 저희가 설정해두었던 프로젝트가 나오게 되고 메인화면에는 컨테이너가 보이게 됩니다.

자 프로젝트가 생성되었으니 빌드를 해보고 에뮬레이터를 실행시켜보도록 합니다.

Carbide C++에서 시계같이 생긴 아이콘 옆의 화살표 화면을 선택하셔서 원하는 SDK를 지정하시고 바로 옆에 있는 망치모양의 아이콘을 클릭을 해주시면 빌드 가 진행이 됩니다.

빌드가 완료가 되면 바로옆의 Play버튼처럼 생긴 아이콘을 클릭을 해주시면 실행마법사가 화면에 나오게 됩니다.

에뮬레이터위에 바로 실행시킬 어플리케이션 여기서는 방금 만든 HelloWorld 프로젝트를 선택하시고 Finish를 눌러서 실행시키면 됩니다.

먼저 위와 같은 화면이 뜨지 않고 먼저 에뮬레이터 설정하는 화면이 뜰 것입니다. 언어설정, 시간설정등과 같이 모든 설정이 끝나시면 위와 같은 화면을 만나실 수 있습니다.

Symbian은 많은 사용자를 확보하고 있는 Nokia의 주력 OS입니다. 아직 한국에는 많이 정착하진 않았지만 그만큼 안정성도 높고 많은 사용자수를 확보하고 있으므로 그 활용성은 높다고 볼 수 있다고 생각됩니다. 이 블로그를 통해서 Symbian을 공부하시는 분들에게 어느정도 그 밑거름이 되었으면 하는바램입니다.

윈도우 모바일 개발환경 구축

윈도우 모바일(Windows Mobile) 개발환경 구축

윈도우 모바일의 개발환경은 기본적으로 Visual Studio(2005 SP1 이상의 버전)에 SDK를 추가로 설치하여 구축할 수 있다.

 

설치하는 PC의 환경은 Windows7 운영체제와 Visual Studio 2008에 설치를 하였다.

 

대학생의 신분인 사람들은 Visual Studio를 간단한 인증을 통해 무료로 사용하는 방법이 있다.

드림스파크라는 마이크로소프트에서 대학생을 대상으로 Windows Server와 Visual Studio, SQL등 개발에 관련된 프로그램을 무료로 다운받아 설치할 수 있도록 하고 있다.

 

드림스파크 주소 : https://www.dreamspark.com/Default.aspx

 

 

윈도우 모바일을 설치할 때 Windows XP일 경우 ActiveSync 4.5를 반드시 설치해야 한다.

 

Active Sync 4.5 설치 다운로드 : http://www.microsoft.com/windowsmobile/ko-kr/downloads/microsoft/activesync-download.mspx

 

 

SDK 다운로드 주소

Windows Mobile 6 Professional Edition SDK (윈도우 모바일 6버전)

http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&DisplayLang=en

Windows Mobile 6 Professional SDK Refresh.msi

454.7 MB

 

Windows Mobile 6.5 Developer Tool Kit  (윈도우 모바일 6.5버전)

http://www.microsoft.com/downloads/details.aspx?familyid=20686A1D-97A8-4F80-BC6A-AE010E085A6E&displaylang=en

Windows Mobile 6.5 Professional Developer Tool Kit (USA).msi

225.0 MB

 

 

한글 에뮬레이터 다운로드
Windows Mobile 6 Emulator Localization Images (한글 에뮬레이터의 설치)
http://www.microsoft.com/downloads/details.aspx?FamilyID=38c46aa8-1dd7-426f-a913-4f370a65a582&DisplayLang=en

0412/Windows Mobile 6 Professional Images (KOR).msi

206.9 MB

 

SDK 설치

간단하게 클릭 몇번을 통해 쉽게 설치가 가능하다.

 

 

한글 에뮬레이터 설치

SDK와 거의 같은 방식으로 간단하게 설치가 된다.

 

 

 

실행

프로젝트 생성

(그림은 클릭하시면 큰화면으로 보실 수 있습니다)

새 프로젝트 생성에 들어가면 Smart Device탭에서 프로젝트를 생성할 수 있다.

확인을 누르면 위 그림의 우측에 있는 화면이 보이는데 기본적으로 SDK 5.0 버전이 선택되어 있으므로 자신이 원하는 버전을 선택하여 프로젝트를 생성하면 된다.

 

예제 프로그램

예제 프로그램으로 간단한 텍스트 출력과 시스템에서 배터리에 대한 정보를 받아와 프로그래스 바로 보여주는 프로그램을 만들어 보았다.

툴박스에서 Label을 선택하여 간단하게 마우스로 그려 넣을 수 있다.

그 다음 우측 하단 부분(오른쪽 그림)의 옵션 설정으로 쉽게 편집이 가능하다.

 

배터리 정보를 보여줄 ProgressBar를 같은 방식으로 그려 넣어준다.

 

배터리의 정보를 받아 오기 위해 References를 추가 한다.(Project - Add Reference..)

Microsoft.WindowsMobile.Status

Microsoft.WindowsMobile

 

다음으로 코드 부분에서 Using 선언문을 추가 해 준다.

using Microsoft.WindowsMobile.Status;

 

다음과 같이 소스 코드를 추가하여 준다.

 

public partial class Form1 : Form

{

   private SystemState battery;

 

   private void Form1_Load(object sender, EventArgs e)

   {

      battery = new SystemState(SystemProperty.PowerBatteryStrength);

      battery.Changed += new ChangeEventHandler(batteryState_changed);

 

      UpdateBatteryStrength(SystemState.PowerBatteryStrength);

   }

 

   void batteryState_changed(object sender, ChangeEventArgs args)

   {

      UpdateBatteryStrength((BatteryLevel)args.NewValue);

   }

 

   void UpdateBatteryStrength(BatteryLevel Level)

   {

 

      switch (Level)

      {

            case BatteryLevel.VeryHigh:

            pb1.Value = 100;

            break;

            case BatteryLevel.High:

            pb1.Value = 75;

            break;

            case BatteryLevel.Medium:

            pb1.Value = 50;

            break;

            case BatteryLevel.Low:

            pb1.Value = 25;

            break;

            case BatteryLevel.VeryLow:

            pb1.Value = 0;

            break;

      }

   }

}

 



F5를 눌려 실행할 가상 장치를 선택하여 프로그램을 테스트 한다.

선택된 가상장치가 실행되고 작성한 프로그램을 자동으로 업데이트 시킨다.

에뮬레이터 창에서 File - Configure..로 들어가 Peripherals 탭에서 배터리의 양을 임의로 변경시킬 수 있다.

 

 

참고 블로그 : http://devlog.hoyanet.pe.kr/11

                  http://windowsmobile7.tistory.com/