막대그래프와 함께 자주 사용되는 그래프의 형태로는 아마도 원 그래프가 아닐까 합니다. 이번 포스팅에서는 앞에서 소개했던 achartengine 라이브러리를 사용하여 원 그래프를 표시해 보도록 하겠습니다.
상황설정
2011년도 분기별 판매 비율이라는 가정으로 다음의 표를 그래프로 표시해 봤습니다.
당연한 이야기이겠지만, 그래프에 나타나는 각 항목의 총 합이 100%가 되어야 하겠지요.
1/4분기
2/4분기
3/4분기
4/4분기
20%
30%
40%
10%
위의 표를 그래프로 표시한 실행 결과는 아래와 같습니다.
프로젝트의 생성 및 그래프 라이브러의 참조 추가
ChartEx라는 프로젝트를 kr.pe.hoyanet.chartex라는 패키지명으로 생성하고, 프로젝트 생성시 default로 나타나는 main.xml의 기본 TextView를 삭제한 후에 최 상위 LinearLayout에게 llBody라는 아이디를 부여했습니다. 이 과정은 앞에서 진행했던 기본 막대그래프 표시 예제와 동일하게 진행했습니다. achartengine을 사용하여 그래프를 표시하는 기본적인 방법은 다음의 포스팅을 참조하시기 바랍니다.
// 그래프 렌더러 생성
DefaultRenderer renderer = new DefaultRenderer();
상단 표시 제목과 글자 크기를 설정합니다.
// 상단 표시 제목과 글자 크기
renderer.setChartTitle("2011 분기별 판매비율");
renderer.setChartTitleTextSize(35);
위에서 표로 정의했던 각 항목에 대한 데이터를 선언합니다.
// 각 항목에 대한 데이터
double[] values = new double[] { 20, 40, 30, 10 };
각 항목별 이름을 지정합니다.
// 각 항목별 문구 지정
CategorySeries series = new CategorySeries("분기별 실적");
series.add("1/4분기", values[0]);
series.add("2/4분기", values[1]);
series.add("3/4분기", values[2]);
series.add("4/4분기", values[3]);
실행화면을 보면 그래프의 근처에 함께 표시되는 회색 작은 글자가 있습니다. 항목별 이름을 표시하는 것입니다.
그래프와 함께 표시되는 항목별 표시 문구의 글자 크기를 지정합니다.
// 그래프와 함께 표시되는 항목별 표시 문구의 글자 크기
renderer.setLabelsTextSize(15);
하단부에 표시되는 항목별 이름에 대한 글자 크기를 별도로 지정합니다.
// 하단부에 표시되는 문구의 글자 크기
renderer.setLegendTextSize(25);
각 항목에 연결할 컬러 지정합니다. 그래프의 항목과 페이지 하단부의 항목이름에 적용되는 색상값 입니다.
// 각 항목에 연결할 컬러 지정
int[] colors = new int[] { Color.BLUE, Color.GREEN, Color.MAGENTA, Color.YELLOW };
for (int color : colors) {
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(color);
renderer.addSeriesRenderer(r);
}
Zoom 버튼 표시 여부와 Zoom 기능 활성화를 지정합니다.
// Zoom 버튼 표시 여부
renderer.setZoomButtonsVisible(true);
// Zoom 기능 활성화
renderer.setZoomEnabled(true);
설정한 내용을 토대로 그래프 View 형태로 얻어 LinearLayout에 추가합니다.
// 그래프를 View로 얻어온다.
GraphicalView gv = ChartFactory.getPieChartView(this, series, renderer);
// 그래프의 화면 출력
LinearLayout llBody = (LinearLayout) findViewById(R.id.llBody);
llBody.addView(gv);
앞에서 소개했던 막대그래프 샘플에서 두가지 이상 분류에 대한 표현 방법을 살펴보도록 하겠습니다.
우선 실행화면을 살펴보면 아래와 같습니다.
두개의 실행화면중에서 우선 왼쪽의 형태를 살펴보고 그런 다음 오른쪽 형태로 변경해 보겠습니다.
(파라미터 값을 한개만 변경하면 형태가 바뀝니다.)
프로젝트의 생성 및 그래프 라이브러의 참조 추가
achartengine을 사용하여 그래프를 표시하는 기본적인 방법은 다음의 포스팅을 참조하시기 바랍니다.
프로그램안에서 사용해야 할 다량의 문자열들을 정의하는데 있어서 효율적인 방법은 소스코드에 모든 내용을 포함시키기 보다는 외부에 내용을 저장해 놓고 필요할 때 마다 읽어오는 방법입니다.
안드로이드에서는 문자열로서 사용하기 위한 데이터를 보관하기 위한 기법으로 리소스 XML에 내용을 기술하는 방법과 SQLite를 사용하는 방법, 그리고 assets 디렉토리를 사용하는 방법을 제공해 주고 있습니다.
오늘 소개할 내용은 assets 디렉토리에 저장된 텍스트 파일을 프로그램내로 읽어들이는 내용입니다.
assets 디렉토리
안드로이드 프로젝트를 이클립스 상에서 보면 assets라는 (평소에는 잘 사용하지 않는) 디렉토리에 있습니다. 프로그램과 직접적으로 연관되지 않은 비 리소스 파일들을 저장해 놓고 필요한 경우 스트림을 생성하여 읽어들이기 위한 저장공간입니다.
이 폴더안에 test.txt라는 파일을 넣었다고 가정하고 이 파일의 내용을 프로그램의 Runtime시에 읽어오는 방법을 소개하겠습니다.
AssetManager의 객체 생성
Context 클래스 내에 보면 getResource()라는 메소드가 있습니다. getResource()라는 메소드는 Resources 라는 클래스의 객체를 리턴합니다. 이 객체는 App이 갖고 있는 자원에 접근할 수 있는 객체입니다. 이 객체를 통해서 AssetManager라는 객체를 얻을 수 있습니다.
Context 클래스
Resources getResource(); 리소스 객체를 얻어옵니다.
만약 Activity안에서 AssetManager객체를 얻고자 한다면 다음과 같이 사용할 수 있습니다.
Resources r = getResource();
Context 클래스는 Activity 클래스의 상위 클래스이기 때문에 Activity 안에서는 Context클래스 내의 기능들을 자기것인양 사용할 수 있습니다.
리소스 객체를 얻은 후에는 이 리소스 객체를 통해서 AssetManager 객체를 얻어옵니다.
Resources클래스
AssetManager getAssets(); AssetManager 객체를 얻어옵니다.
AssetManager를 통하여 파일 열기
AssetManager 객체가 생성되면 이 객체의 open() 메소드를 사용하여 InputStream 객체를 얻을 수 있습니다. open() 메소드는 호출 시에 대상 파일의 이름을 문자열로 전달합니다. 파일이 위치한 경로는 이클립스 프로젝트 내의 assets 라는 폴더로 이미 확정이 되어 있는 상태이기 때문에 전달하는 파라미터는 파일의 이름만을 전달합니다. 주의하실 점은 이 메소드를 사용하려면 try { } ~ catch { } 블록으로 묶어 주어야 한다는 점 입니다. 그래서 Asset객체를 통해서 InputStream을 여는 과정은 다음과 같아집니다.
AssetManager am = m_context.getResources().getAssets();
InputStream is = null;
try {
is = am.open("contact.txt");
// 스트림을 사용합니다.
} catch (Exception e) {
// 에러가 발생한 경우의 처리
} finally {
if (is != null) {
try {
is.close();
is = null;
} catch (Exception e) {}
}
}
am = null;
test.txt 파일을 읽기
Context객체와 읽어야 할 파일이름을 전달하였을 때, 해당 파일의 내용을 읽어서 문자열로 리턴해 주는 함수를 구현해 본다면 다음과 같이 구현할 수 있겠습니다.
String readAsset(Context context, String file_name) {
AssetManager am = context.getResources().getAssets();
InputStream is = null;
// 읽어들인 문자열이 담길 변수
String result = null;
try {
is = am.open(file_name);
int size = is.available();
if (size > 0) {
byte[] data = new byte[size];
is.read(data);
result = new String(data);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
is = null;
} catch (Exception e) {}
}
}
am = null;
return result;
}
안드로이드 에뮬레이터는 정말이지 사람 속터지게 느립니다. 한번 실행버튼을 누르면 완전히 에뮬레이터가 부팅될 때 까지 3~5분 정도는 걸리는 듯 합니다.
그렇기 때문에 강의를 진행하면서도 안드로이드 핸드폰이 있는 분들은 가급적 핸드폰을 통해서 테스트를 하시도록 권해 드리고 있습니다.
이번에는 이클립스를 통한 실행을 에뮬레이터가 아닌 실제 단말기를 통해서 진행하는 과정에 대해서 소개해 보겠습니다.
안드로이드 단말 USB드라이버 설치
우선은 (Windows 운영체제에 한해서) 각 제조사에서 배포하는 안드로이드 USB 드라이버를 설치해야 합니다. 제조사별 드라이버 파일의 다운로드는 각 제조사 사이트를 참조하시기 바랍니다.
안드로이드 단말의 환경설정
USB연결을 통한 단말 디버깅 기능을 사용하기 위해서는 핸드폰에서 몇가지 설정을 해 주어야 합니다.
우선 PC와의 USB연결을 제거합니다. 핸드폰에서 "환경설정" 메뉴로 들어갑니다. 환경설정 메뉴 하위의 "응용프로그램"메뉴를 선택합니다.
응용 프로그램 페이지에 들어가면 우선 "알 수 없는 소스"항목에 대해서 체크가 되어 있어야 합니다.
안드로이드 폰은 구글 마켓을 통해서 다운로드 받는 프로그램을 제외한 모든 프로그램들을 "알 수 없는 소스"라고 인식합니다. (T-Store나 alleh Store등 역시 알 수 없는 소스 입니다.)
이클립스를 통해서 실행하는 프로그램이 "알 수 없는 소스"인 것은 두말할 필요가 없겠지요.
그 다음 맨 아래 있는 "개발"항목을 선택합니다.
페이지가 이동되면 "개발"페이지에 있는 체크박스들을 모두 체크합니다.
제조사에 따라서 "USB연결시 단말 화면이 꺼지지 않음"이라는 세가지 항목이 나타나는 경우가 있습니다.
아래 보이는 화면인 삼성 갤럭시S2의 화면입니다.
설정이 완료되면 화면을 빠져 나온 후에 USB를 통해서 PC와 연결합니다.
PC와 연결시 주의하실 점은 핸드폰에서 "USB저장소로 사용"이 활성화 되어 있으면 안된다는 것입니다.
이클립스에서의 실행
핸드폰이 연결된 후에 이클립스에서 RUN버튼을 누르면 다음과 같은 화면이 나타납니다.
에뮬레이터만 생성되어 있을 경우에는 구동중인 에뮬레이터가 보였지만, 핸드폰이 연결되면 연결된 핸드폰의 Serical Number가 함께 표시됩니다. 저 항목을 선택하고 "OK"버튼을 누르면 안드로이드 단말을 통해서 결과를 확인할 수 있습니다.
앞에서 진행했던 Hello World 예제를 단말기에서 실행한 모습입니다.
단말에서 실행한 후에 프로그램 목록을 살펴보면 조금전에 테스트한 항목이 설치되어 있는 것을 확인할 수 있습니다.
Run버튼 클릭시 Device Chooser 화면이 나타나지 않는 경우
간혹가다가 (사실은 꽤 자주) Run버튼을 클릭하였더니 아래와 같은 화면이 나타나지 않고 (단말기가 연결되어 있음에도 불구하고) 즉시 에뮬레이터가 구동되는 경우가 있습니다.
이 경우에는 이클립스의 설정이 유실되어서 그렇습니다.
이클립스 상에서 "Run > Run Configurations"메뉴를 선택합니다.
좌측의 메뉴 트리에서 "Android > 프로젝트이름"항목을 선택한 후에 화면 중앙에서 "Target"탭으로 이동합니다.
Target탭으로 이동하면 라디오 버튼이 두개 보입니다. "Manual"이라는 버튼과 "Automatic"이라는 버튼입니다.
Device Chooser 창이 나타나지 않는 경우는 이 두개의 라디오버튼이 "Manual"로 지정되지 않은 경우입니다.
"Manual"로 지정되면 매 실행시마다 어떤 장치(혹은 에뮬레이터)를 통해서 실행할 것인지를 물어보기 위해서 Device Chooser 화면이 나타납니다.
"Automatic"으로 지정되면 실행시마다 지정된 에뮬레이터로만 구동됩니다. (실제 단말은 Automatic)지정이 안됩니다. "Automatic"으로 지정된 후에는 그 하단에 있는 에뮬레이터 목록중에서 한가지를 지정해 주어야 합니다.
만약 "Automatic"으로 지정되고 실행할 에뮬레이터가 지정되지 않으면 이클립스에서 "Run"버튼을 눌렀을 때 아무런 응답이 없는 경우가 있으니 주의하시기 바랍니다.
반대로 이야기한다면 "Run"버튼을 눌렀을 때 이클립스가 아무런 응답이 없다면 이곳을 확인해 보면 된다는 이야기 입니다.
이클립스에서 가장 왼쪽에 있는 툴바 아이콘이 "New"아이콘 입니다. 이 아이콘을 클릭합니다.
"New"아이콘을 클릭하면 "New"대화상자가 나타납니다. 화면의 중앙부에 있는 선택항목 중에서 "Android > Android Project"항목을 선택하고 "Next"를 누릅니다.
새로운 안드로이드 프로젝트의 이름을 지정하는 화면이 나타납니다. "Project Name"은 이클립스상에서 이 작업을 구분하기 위한 단위 이름을 입력하는 공간입니다. 여기서는 "HelloWorld"라고 입력하겠습니다. 프로젝트 이름이 지정되면 "Next"버튼을 누릅니다.
안드로이드 프로젝트를 진행할 대상 버전을 지정합니다. 최상위 버전인 "Android 4.0.3"항목을 체크합니다.
체크를 한 다음 "Next"버튼을 누릅니다.
프로젝트 이름을 지정하고 나면 프로젝트의 정보를 입력하는 단계로 넘어가게 됩니다.
각각의 항목에 적절한 값을 입력한 후에 "Finish"버튼을 누르면 됩니다.
각 항목에 입력하는 값의 의미는 다음과 같습니다.
Application Name : 이 프로그램의 이름을 지정합니다. 실제로 이 어플리케이션이 단말기에 설치되었을 경우에 단말기의 프로그램 목록에 표시되는 이름입니다. 한글로 지정해도 무관합니다.
Package Name : 자바 패키지 이름입니다. 안드로이드는 OS에서 하나의 어플리케이션을 인식하는 단위가 패키지 단위가 됩니다. 그렇기 때문에 동일 패키지 이름이 설치하려는 단말기에 이미 존재한다면 설치가 진행되지 않습니다. (심지어 구글 마켓에 어플을 올릴 경우에도 다른 어플과 패키지 이름이 중복되면 등록이 거부됩니다.) 그러므로 패키지 이름은 가급적 고유한 이름을 지정해야 합니다.
패키지 이름은 보유하고 있는 도메인의 역순.프로젝트이름(소문자)로 짓는것이 일반적입니다.
Create Activity : 프로그램의 시작점이 되는 Main Class의 생성여부에 대한 결정과 메인 클래스의 이름을 짓는 부분입니다. 이 항목을 체크하지 않고 지나갈 경우 다시 생성하기 위해서는 꽤 번거로운 작업들을 진행해야 하므로 반드시 프로젝트 생성시에 지정해 주셔야 합니다.
Minimun SDK : 이 프로그램을 구동할 수 있는 최소 안드로이드 버전값을 지정합니다. 아래 화면에서는 Android 2.1로 지정되어 있습니다. 이 의미는 이 어플이 (앞에서 지정한 대로) Android 4.0.3 버전을 대상으로 개발이 되지만 Android 2.1까지 지원하겠다라는 의미가 됩니다.
설정이 완료되면 "Finish"버튼을 눌러서 프로젝트 생성을 완료합니다.
프로젝트 설정이 완료되면 다음과 같이 이클립스상에 프로젝트가 생성됩니다.
이클립스에서 src > 패키지이름 > 메인클래스.java 파일을 열어보면 기본적으로 필요한 소스들이 작성이 되어 있는 것을 확인할 수 있습니다.
결과 확인
소스 수정 없이 바로 한번 실행해서 기본 모양을 확인해 보겠습니다.
안드로이드 에뮬레이터를 구동한 상태에서 이클립스에 있는 "Run"버튼을 누르면 프로그램이 에뮬레이터를 통해서 구동됩니다.
간혹가다가 에뮬레이터가 구동중인데도 새로 에뮬레이터가 뜨는 경우가 있습니다. 이럴 때는 그냥 그러려니 하면서 기존에 실행중이던 에뮬레이터를 종료하시면 됩니다.
"Android Device Chooser"라는 창이 나타나면서 구동중인 에뮬레이터의 목록이 나타납니다.
화면이 상하 두칸으로 나뉘어 있는데, 위쪽은 현재 구동중인 에뮬레이터의 목록이 나타납니다.
아래쪽은 구동되지 않고 있는 에뮬레이터가 타나납니다.
만약 현재 구동중인 에뮬레이터가 없다면 아래 화면에서 아래쪽 항목을 선택하고 "OK"버튼을 누르면 됩니다.
다른 플렛폼들의 경우에는 개발한 소스를 테스트하기 위한 에뮬레이터가 완제품 형태로 제공되지만 안드로이드의 경우에는 개발자가 직접 에뮬레이터를 생성해 주어야 합니다.
이번 포스팅에서는 안드로이드 에뮬레이터를 생성해 보도록 하겠습니다.
이 과정은 Window와 Mac에서 공통으로 적용되는 내용입니다.
안드로이드 에뮬레이터 (AVD)의 추가
우선 이클립스에서 "Android Virtual Device Manager"를 실행시켜야 합니다. 이클립스의 AVD Manager 아이콘을 클릭합니다. (아래의 화면을 참고하세요.)
"Android Virtual Device Manager"라는 창이 나타나면 새로운 에뮬레이터를 생성하기 위해서 좌측에 있는 "New"버튼을 클릭합니다.
아래 화면과 같이 "Create new Android Virtual Device"라는 창이 나타납니다.
아래 화면을 참고해서 값을 입력(혹은 선택)하세요.
Name : 에뮬레이터에 부여하는 이름입니다. 한글만 아니라면 편하게 작성할 수 있습니다.
Target : 에뮬레이터에 탑제될 안드로이드 운영체제의 버전입니다. 여기서는 최신 버전을 적용했습니다.
SD Card > Size : 에뮬레이터에 탑제될 SD카드의 용량을 지정합니다.
나머지 항목을 기본값대로 지정하면 해상도가 WVGA800 (480x800) 사이즈인 에뮬레이터가 생성됩니다.
에뮬레이터가 생성되면 생성된 항목을 선택하고 "Start"버튼을 누르세요.
실행 확인창이 나타납니다. 그냥 "Launch"버튼을 누르시면 에뮬레이터가 구동됩니다.
에뮬레이터가 구동되면서 안드로이드 운영체제가 부팅됩니다. 이 화면에서 인내력을 요구합니다. 부팅... 상당히 느립니다.
부팅이 완료되고 나면 안드로이드 운영체제의 모습을 볼 수 있습니다.
에뮬레이터가 PC모니터를 벗어나는 경우
(주로 해상도가 작은 노트북에서 실행할 경우) 에뮬레이터가 컴퓨터의 모니터보다 커서 화면을 빠져 나가는 경우가 간혹 있습니다.
이 경우에는 에뮬레이터의 "Launch Options"에서 Sacle 값을 지정해서 해결할 수 있습니다.
아래 화면은 에뮬레이터를 시작할 때 나왔었던 확인창입니다. "Scale display to real size"체크박스를 체크하고 "Screen Size"란에 7이라고 입력한 후에 실행합니다. (1~10 / 값이 클수록 확대됨)
이번 포스팅은 윈도우 운영체제에서 안드로이드를 개발하기 위한 개발환경을 설정하는 과정을 소개하고자 합니다. 이 블로그에 안드로이드 관련 글들이 은근히 올라와 있는 시점에서 뒤늦게 이렇게 안드로이드 설정관련 포스티을 올리는 까닭은 제가 진행하고 있는 강의에서의 보조교제로서 이 포스팅을 활용하기 위해서 입니다.
안드로이드의 개발환경 구축단계는 다음의 과정을 거쳐서 진행됩니다.
JDK의 설치와 환경변수 설정
Eclipse Classic 버전의 다운로드 및 설치
Android SDK의 다운로드 및 설치
Android Development Tool (ADT) 플러그인의 설치
여기서는 설치가 완료된 전체 패키지를 압축하여서 나중에 다른 환경에서도 압축만 풀면 즉시 안드로이드 개발을 진행할 수 있도록 만들겠습니다.
JDK의 설치와 환경변수 설정
안드로이드 역시 자바기반에서 진행되는 개발이니만큼 JDK의 설치및 설정이 필수 입니다. JDK의 다운로드 및 설치는 다음의 포스팅을 참조하시기 바랍니다.
안드로이드 개발 툴킷은 이클립스의 플러그인 형태로 제공됩니다. 그렇기 때문에 안드로이드 개발을 위해서는 Eclipse를 다운로드 받아서 설치해야 합니다. 이클립스는 http://www.eclipse.org에서 다운로드 받을 수 있습니다.
사이트에 접속한 후 상단 메뉴에서 "Download"를 클릭하여 다운로드 페이지로 이동합니다. 다운로드 페이지에 나열되는 패키지들 중에서 "Eclipse Classic"버전을 설치되어 있는 운영체제의 버전에 맞게 선택합니다.
운영체제에 맞는 버전을 선택하면 다운로드 링크가 제공되는 페이지로 이동합니다. 여기서 아래 화면을 참조하여 이클립스를 다운로드 받습니다.
이클립스는 설치 패키지가 아닌 압축파일의 형태로 제공됩니다. C드라이브에 eclipse+andsdk-r16-win32-x86-64bit 라는 폴더를 만들고 그 안에 압축을 풀어둡니다. 이 때 폴더이름은 편하게 지으시면 됩니다. 다만 폴더 이름을 명시할 때 한글이나 공백이 들어가지 않도록 주의하시기 바랍니다.
이클립스의 압축이 모두 풀리면 그 안에 workspace라는 폴더를 생성합니다. 이 폴더에 소스파일들이 저장되도록 지정할 것입니다.
이제 이클립스를 실행하면 아래 화면과 같이 workspace를 물어보는 화면이 나타납니다. 이 화면에서 workspace의 경로를 앞에서 생성한 디렉토리로 지정하여 줍니다.
만약 이 단계를 무시하고 지나쳤다면 이클립스의 "File > Switch Workspace"메뉴를 통해서 다시 지정해 줄 수 있습니다.
Android SDK의 다운로드 및 설치
이클립스의 설치가 잘 마무리되면 이번에는 Android SDK를 다운로드 받아서 설치할 차례입니다.
Android SDK는 초기에는 단순히 압축파일의 형태로만 제공이 되었습니다. 후에 이 압축파일이 설치 패키지 형태로 변경이 되었는데 그렇다고 해서 변한것은 없습니다. 즉 설치 완료 후에 그 파일을 다시 압축해서 다른곳에 압축을 풀어도 정상적으로 사용이 가능하다는 것이죠.
이 점을 이용해서 이클립스가 설치된 디렉토리안에 android-sdk-windows라는 폴더를 만들고 그 경로에다 Android SDK를 설치할 것입니다.
그렇게 되면 설치 완료 후에 이클립스와 함께 통째로 압축하면 언제든지 재사용이 가능해 집니다.
안드로이드 SDK를 다운로드 받기 위해서 http://developer.android.com 에 접속합니다. 사이트에 접속한 후에 두번째 메뉴인 SDK를 클릭하면 운영제체 버전에 맞는 SDK를 다운로드 받을 수 있는 페이지가 나타납니다.
여기서는 Windows 환경에서 설치를 진행할 것이므로, Installer_r16_windows.exe 파일을 다운로드 받습니다.
다운로드가 완료되면 다운로드 받은 파일을 실행하여서 설치를 시작합니다.
설치 과정중에 JDK의 설치 여부를 확인합니다. 만약 JDK의 설치가 되어 있지 않다면 JDK를 설치하신 후에 다시 이 패키지를 실행하셔야 합니다.
SDK가 설치될 경로를 묻는 화면이 나타납니다. 앞에서도 이야기 했듯이 여기서는 C:\이클립스폴더\android-sdk-windows 경로에 이 패키지를 설치할 겁니다. 아래 화면을 참고하여서 "Browse"버튼을 누릅니다.
폴더 찾아보기 창이 나타나면 앞에서 생성했던 android-sdk-windows의 폴더를 지정하여 줍니다.
지정된 경로를 확인하고 "Next"버튼을 눌러서 설치를 계속 진행합니다.
시작메뉴 폴더를 물어봅니다. 가볍게 "Next"버튼을 누릅시다.
설치가 진행됩니다. 완료되면 여기서도 "Next"를 누릅시다.
설치가 완료되면 Android의 버전별 API를 내려받아야 합니다. 설치 완료 후 API 다운로드 창을 구동시키기 위한 "Start SDK Manager" 체크박스를 체크하고 "Finish"버튼을 눌러줍니다.
설치 프로그램이 종료되면서 Android SDK Manager라는 창이 나타납니다. 기본적인 SDK이외에 Android의 버전별 API와 추가적인 툴들을 내려받도록 하는 화면입니다.
Android API는 최신 버전인 Android 4.0.3 버전과 일반적으로 개발시에 최 하위 버전으로 적용하는 2.1버전만을 다운로드 받습니다. 1.6과 1.5는 지나치게 하위버전이여서 탑제되어 있는 단말기도 드물기 때문에 배제합니다.
실제 프로젝트 진행은 4.0.3으로 진행하면서 최하위 지원 버전을 2.1로 지정하기 위해서 위와 같이 체크합니다.
그 외에 Extra라는 추가 기능들도 포함시킵니다.
이용약관에 동의하고 다운로드를 진행합니다.
실제 다운로드가 진행됩니다. 이 과정이 상당히 오래 걸립니다. 저는 이거 걸어놓고 스타를 한판 했습니다. -.-;;;
다운로드가 완료되면 별다른 메시지가 나타나지 않고 진행되던 프로그래스바가 회색으로 바뀝니다. 그럼 이 창을 그냥 닫아주면 됩니다.
ADT의 다운로드와 설치
ADT란 Android Developement Tools의 줄임말로 이클립스에 설치되어 Android SDK를 다룰 수 있도록 도와주는 이클립스 플러그인을 말합니다.
ADT를 다운로드 받고 설치하기 위해서는 이클립스를 사용해야 합니다. 이클립스의 Help메뉴 하위의 "Install New Software"를 선택합니다.
"Install"창이 나타나면 우측 상단의 "Add"버튼을 누릅니다.
Add Repository창이 나타나면 Name 속성에 "ADT"라고 입력하고 Location 속성에는 다음의 주소를 입력합니다. 여기서 입력한 주소로부터 이클립스 플러그인을 내려받게 됩니다. 입력이 완료되면 "OK"버튼을 눌러 창을 닫고 원래의 화면으로 돌아갑니다.
https://dl-ssl.google.com/android/eclipse/
원래의 화면으로 돌아가면 화면 중앙의 목록에 잠시 "Pending..."이라는 메시지가 나타났다가 다운로드 받을 수 있는 항목들이 체크박스와 함께 나타납니다. 모든 항목을 체크한 후에 "Next"버튼을 눌러서 다운로드 받습니다.
선택한 항목을 확인하는 페이지 입니다. "Next"버튼을 누릅니다.
이용약관을 확인하는 페이지 입니다. 동의한다는 의미의 "I accept ..."에 체크하고 "Finish"를 누릅니다. 이 페이지의 내용을 꼼꼼히 읽어보실 분들은... 안말립니다. -_-;;;
다운로드가 시작됩니다. 이 과정이 상당히 오래 걸립니다. 식사라도 하고 오셔야 합니다.
다운로드 중에 Anti Virus 프로그램에 대한 경고가 나타나는 경우가 있습니다. 가볍게 "OK"를 누르시면 됩니다.
다운로드가 완료되면 이클립스를 재시작해야 한다는 메시지가 아래 화면과 같이 나타납니다. "Restart Now"를 눌러서 이클립스를 재실행 합니다.
이클립스가 재실행 되고 나면 아래 화면과 같이 Android API를 내려받는 창이 자동으로 나타납니다. 우리는 앞에서 Android SDK를 설치하면서 미리 받아두었기 때문에 여기서는 "Cancel"을 눌러서 창을 닫습니다.
이제 여기까지 진행한 후에 이클립스를 닫고 이클립스가 설치된 디렉토리를 통째로 압축하면 다른 PC에 가서도 동일한 경로에 압축만 풀어주면 바로 안드로이드 개발을 진행할 수 있습니다.
저는 압축을 풀기 전에 이클립스의 폰트를 변경하고 소스파일의 왼쪽에 라인수가 표시되는 설정을 추가한 후에 압축했습니다.
ChildBrowser plugin은 특정 URL 을 safari나 android의 웹브라우져가 아니라 어플리케이션내에서 새로운 창을 열어 해당 페이지를 보여주는 plugin입니다.
이 ChildBrowser 를 사용하면 App을 벗어나지 않고 외부 웹페이지를 보여주고자 하는 경우에 유용한데 특히 여러가지 사용예 중에서도 facebook/twitter 의 OAuth 인증을 위해서 많이 사용되는 plugin입니다. (페이스북 인증 방법에 대해서는 따로 설명하겠습니다.)
이번 포스팅에서는 안드로이드용 PhoneGap에 대한 사전 지식이 필요하므로, 이전 글에서 소개했던 Android용 PhoneGap에 인트로 페이지가 적용된 샘플에서 이어서 진행하겠습니다. 안드로이드용 PhoneGap을 적용한 기본 App의 작성단계에 대해서는 다음의 포스팅을 참조하시기 바랍니다.
우선 플러그인을 다운로드 받기 위해서 https://github.com/phonegap/phonegap-plugins 에 접속하여 Android용 플러그인을 다운로드 받습니다. (그 외에도 각 OS버전별 플러그인이 제공됩니다.)
Plugin을 다운로드 받은 github에서 Android/ChildBrowser 폴더 Readme 파일의 가이드를 따라 ChildBrowser plugin을 설치합니다.
설치 절차는 다음과 같습니다.
프로젝트에 src/com/phonegap/plugins/childBrowser 폴더를 만들고 ChildBrowser.java 파일을 이 폴더로 복사합니다. Eclipse 프로젝트를 Refresh(F5)하면 프로젝트의 src에 “com.phonegap.plugins.childBrowser” 이 표시됩니다. (대, 소문자에 주의할 것!)
지난번 글에서 iOS 플랫폼을 대상으로 한 PhoneGap 프로젝트를 생성해서 간단한 Hello World를 진행해 보았습니다.
iOS에서는 프로젝트 템플릿이 등록되기 때문에 비교적 간단하게 PhoneGap 프로젝트를 생성할 수 있었지만, 안드로이드에서는 PhoneGap이 jar 형태의 라이브러리로 제공되기 때문에 일반 안드로이드 프로젝트를 생성하고 그 안에 라이브러리와 몇가지 설정을 추가해 주는 형태로 진행됩니다.
PhoneGap 라이브러리 다운로드
안드로이드에서의 PhoneGap 프로젝트를 생성하기 위해서 우선 PhoneGap 라이브러리를 다운로드 받아야 합니다. http://www.phonegap.com 을 통해서 다운로드 받을 수 있습니다.
사이트에 접속한 후에 우측 상단의 Download 버튼을 클릭하여 다운받고, 압축을 풉니다. 압축을 풀면 모든 OS에 대한 라이브러리들이 들어 있습니다. 이 중에서 오늘은 Android 라는 폴더안의 내용을 사용할 겁니다.
하나를 받으면 모든 OS버전이 다 제공되기 때문에 앞에서 iOS에서의 사용을 목적으로 다운받아 놓으신게 있다면, 그 파일을 재사용하셔도 됩니다.
새로운 안드로이드 프로젝트의 생성
우선은 일반적으로 생성하던 새로운 안드로이드 프로젝트를 생성해야 합니다. 이클립스에서 "new"툴바 버튼을 클릭하여 "New"대화상자를 연 후, "Android > Android Project" 항목을 선택합니다.
각 항목의 입력값을 저는 아래와 같이 처리했습니다. 최상위 버전 (Google API 3.2) 를 선택하더라도 무관합니다. PhoneGap이 하위버전 호환성을 보장해 줄 것입니다.
PhoneGap 라이브러리의 등록
"Package Explorer"에서 프로젝트 이름을 마우스 우클릭하여 "New > Folder"를 선택합니다.
새로운 폴더를 생성하는 창이 나타나면 폴더의 이름을 "lib"라고 지정합니다.
다운로드 받아 압축을 풀어 놓은 PhoneGap 폴더에서 phonegap-1.1.0.jar 파일을 조금전에 추가한 lib 폴더 안으로 드래그 & 드롭 해서 넣습니다. 이 파일이 안드로이드 버전의 PhoneGap 라이브러리 입니다.
만약 이 과정에서 복사할지, 링크할지 물어보면, 복사하겠다고 선택해 주시면 됩니다.
"Package Explorer"에서 프로젝트 이름을 마우스 우클릭한 후, 맨 아래 있는 "Properties"항목을 선택하여 프로젝트 환경설정 창을 엽니다.
좌측의 메뉴에서 "Java Build Path"항목을 선택한 후, 우측의 "Libraries" 탭으로 이동하여 "Add JARs"버튼을 클릭합니다.
jar 추가 대화상자가 나타나면, 조금전에 추가한 lib 폴더 안의 "phonegap-1.1.0.jar" 파일을 지정해 줍니다.
폰갭은 HTML페이지를 디스플레이하기 위한 웹브라우저 라이브러리이지만, 거기에 추가적으로 하드웨어에 의존적인 기능을 플러그인이라는 형태로 제공합니다.
플러그인을 사용하기 위해서 플러그인의 정보를 담고 있는 XML 리소스를 추가합니다. PhoneGap 폴더에서 xml 이라는 폴더를 "Package Explorer"의 "res"폴더 안으로 드래그 & 드롭하여 복사합니다.
소스파일의 편집
프로젝트를 생성하면서 추가된 자바 소스파일을 열어서 다음의 내용으로 대체합니다.
package study.phonegap;
import android.os.Bundle;
import com.phonegap.*;
public class HelloPhoneGapActivity extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.loadUrl("file:///android_asset/www/index.html");
}
}
HTML 파일의 준비
위에서 작성한 소스코드를 보면, HTML 페이지의 경로가 "Package Explorer"상에서 "/assets/www/index.html" 파일로 지정되어 있는 것을 알 수 있습니다.
또한, 압축을 풀어 놓은 PhoneGap 라이브러리 폴더 안에 있는 phonegap-1.1.0.js 파일역시 /assets/www 폴더에 함께 넣습니다. 이 자바스크립트 파일은 폰갭의 플러그인을 HTML에서 호출해서 사용할 수 있도록 하기 위한 인터페이스 파일입니다. 폰갭 라이브러리는 처음 실행할 때, 이 파일을 찾기 때문에 HTML 페이지에서 정상적으로 로딩되지 않을 경우, 해당 페이지가 열리는데 약간의 딜레이가 있는 것 처럼 느껴질 수 있습니다.
해당 경로에 맞도록 파일을 생성합니다.
HTML 페이지에는 6라인에서 phonegap-1.1.0.js 파일을 참조시키고, 그 외의 내용은 jQuery Mobile을 적용하였습니다.
이클립스에서 "New" 툴바 아이콘을 클릭하여서 새로운 "Android Project" 를 생성합니다.
프로젝트의 정보는 아래와 같이 입력했습니다.
프로젝트에 리소스를 등록
생성된 안드로이드 프로젝트를 이클립스의 Package Explorer상에서 보면 res 라는 디렉토리가 있습니다. 이 디렉토리가 안드로이드에서의 리소스를 관리하는 역할을 합니다. 이 디렉토리 안의 drawable-hdpi 디렉토리에 우리가 사용하기 위한 이미지 리소스를 넣어야 합니다.
아래 그림과 같이 intro.png 파일을 드래그 & 드롭해서 넣습니다.
레이아웃의 편집
res/layout 폴더에는 화면에 보여주는 모습이 정의되어 있는 XML 파일들이 위치합니다. 이 파일의 내용을 자바 클래스가 읽어서 그 내용대로 화면에 표시하는 구조 입니다.
프로젝트를 생성하게 되면, 1개의 화면을 구성하기 위한 소스파일 (프로그램의 진입점이 됩니다.) 과 이 소스파일에서 읽기 위한 main.xml 파일이 생성됩니다. 이 main.xml 파일을 수정해서 인트로 화면을 구성하겠습니다.
/res/main.xml 파일을 엽니다. (처음 열리는데 시간이 좀 소요됩니다.)
화면의 중앙에 레이아웃의 모습이 표시되면 이클립스에서 기본으로 생성해 준, "Hello World..." 문자열이 표시됩니다. 그 문자열이 표시되고 있는 부분을 클릭해서 삭제합니다.
레이아웃에 이미지 적용
XML 레이아웃 편집화면 상에서 우측의 "Outline"이라는 부분에 화면에 표시될 컨트롤들의 계층구조가 트리형태로 표시됩니다.
Outline에 표시되고 있는 "LinearLayout" 이라는 항목을 더블클릭하면, Outline 창 부분에 해당 컨트롤의 속성을 지정할 수 있는 "Properties" 창이 나타납니다.
"Properties"창에서 "Background"라는 항목을 찾아서 우측의 "..."버튼을 클릭합니다.
리소스 선택창이 나타나면 "Drawable"이라는 항목의 트리를 확장해서 앞에서 등록해준 "intro.png"파일에 해당하는 "intro"라는 항목을 선택하고 "OK"버튼을 누릅니다.
그럼 아래와 같이 화면에 우리가 준비한 인트로 이미지가 배경화면으로서 등록됩니다. 이렇게 등록한 이미지는 화면 해상도에 상관없이 화면을 가득 채운 상태로 표시됩니다.
두번째 화면의 준비
프로젝트를 만들면서 생성된 첫 화면에 대한 XML파일과 자바 소스는 인트로 화면으로 사용할 계획이기 때문에, 인트로화면 다음에 보일 실질적인 프로그램의 메인화면 역할을 할 두번째 화면을 준비해야 합니다.
두번째 화면의 모습을 정의하기 위해서 레이아웃 XML 파일을 새롭게 추가합니다.
이클립스의 "New" 툴바 아이콘을 클릭하고, "New" 대화상자가 나타나면 Android > Android XML File 을 선택합니다.
"New Android XML File" 대화상자가 나타나면, 파일이름을 넣습니다. 여기서는 sub.xml 이라고 넣었습니다.
파일의 타입을 정의하는 라디오버튼에서 "Layout"항목을 선택하고, "Finish"버튼을 클릭합니다.
대화상자가 닫히면, "/res./layout/sub.xml" 파일이 생성되어 있습니다. 이 파일을 더블클릭해서 열어보면 비어있는 화면인 것을 알 수 있습니다.
레이아웃 편집기의 왼쪽에 나타나는 컨트롤 목록에서 "Form Widgets" 그룹안에 있는 "Large"라는 항목을 화면으로 드래그 & 드롭 합니다.
"Form Widget"은 안드로이드에서 사용하는 기본 컨트롤들을 담고 있는 그룹이며, 이중에서 "TextView", "Large", "Medium", "small" 이라는 항목은 텍스트를 표시하기 위한 "텍스트 뷰"라는 컨트롤 입니다. 모두 동일한 컨트롤이며, 기본적인 속성 값들에 대해서 차이를 보이는 부분입니다.
컨트롤을 추가한 후에 우측의 Outline 트리에서 추가된 컨트롤을 확인할 수 있습니다. "textView1"이라는 이름으로 추가 되어 있는 것을 확인할 수 있습니다.
우측의 Outline에서 textView1을 더블클릭하여 속성을 정의하기 위한 "Propertie" 탭으로 이동합니다. 여기서 "Text"라는 속성을 찾아서 우측의 "Hello Android!!!" 라고 입력합니다.
새로운 화면을 위한 소스파일 추가
이클립스의 "Package Explorer"에서 /src 폴더 하위의 현재 패키지 이름을 마우스 우클릭하여 "New" > "Class" 항목을 선택합니다.
새로운 클래스 생성을 위한 대화상자가 나타나면, 아래 화면을 참고해서 값을 입력합니다.
MySubActivity 라는 클래스를 android.app.Activity 라는 클래스를 상속시켜서 생성합니다.
새로운 클래스가 추가되면, 소스창에 다음의 소스코드를 작성합니다.
프로젝트를 처음 만들때 생성되는 소스파일의 내용과 동일합니다.
package study.introex;
import android.app.Activity;
import android.os.Bundle;
public class MySubActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sub);
}
}
10라인의 소스코드를 보면 setContetView 라는 함수에 R.layout.sub 라는 값이 전달됩니다. R.layout.sub 라는 값은 앞에서 추가한 레이아웃 XML 파일을 의미합니다. XML파일이 추가되면 "R.layout.파일명"의 형태로 값이 생성되며, 이 값을 setContetView 메소드에 전달함으로서 Activity를 상속한 자바 클래스가 XML파일을 읽어들일 수 있게 합니다.
새로운 화면을 위한 AndroidManifest.xml 파일 작업
안드로이드에서는 소스코드와 레이아웃을 아무리 잘 작성해도, 실제 프로그램이 실행될 때는 해당 화면을 호출하게 되면 런타임 에러가 발생합니다. 그 이유는 프로그램이 OS에 설치될 때, OS가 프로그램의 메타정보를 담고 있는 AndroidManifest.xml 파일을 읽어들여서 어떤 클래스들이 화면이라고 인식해야 하기 때문입니다. 그러므로, 화면을 추가하는 단계는 레이아웃 XML 생성 > 소스코드의 생성 > 화면 정보를 AndroidManifest.xml 파일에 등록 의 순서로 진행됩니다.
Package Explorer에서 "AndroidManifest.xml"파일을 열어서 편집창이 열리면, 화면 하단에 있는 5개의 탭 중에서 두번째 "Application" 탭으로 이동한 후에, 화면 하단쪽에 있는 "Application Nodes" 하위의 "Add"버튼을 누릅니다.
새로운 창이 열리면, "Activity"항목을 선택합니다.
만약, 위와 같은 화면이 나타나지 않고 아래 화면과 같이 라디오버튼과 Intent Filter, Meta data 라는 두 항목이 나타나면, 라디오버튼을 첫번째 것을 선택합니다. Application Nodes 에서 특정 항목을 선택한 후에 "Add"버튼을 눌러서 그 하위의 정보를 등록하기 위한 창이 디폴트로 나타나기 때문이니 크게 신경쓸 부분은 아닙니다.
"Application Nodes"에 새로운 "Activity"항목이 추가되면, 추가된 "Activity"를 선택하고 우측의 "Name" 항목의 "Browse"버튼을 클릭합니다.
찾아보기 창이 열리면서 현재 프로젝트 안에 있는 Activity를 상속받는 클래스들의 목록이 나타납니다.
여기서 우리가 앞에서 추가한 "MySubActivity"클래스를 선택해 줍니다.
로딩 다이얼로그의 추가
인트로 화면에서 작업이 진행중이라는 것을 사용자에게 알려주기 위해서 로딩다이얼로그를 현재 프로젝트에 추가합니다.
이제 모든 준비가 끝났으니, 프로그램 실행시에 로딩바를 표시하고, 3초 정도의 시간 후에 다음 페이지로 이동하는 작업을 처리하겠습니다.
프로젝트를 만들때 자동으로 생성된 IntroExActivity 소스를 아래의 내용으로 작업합니다.
package study.introex;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class IntroExActivity extends Activity implements Runnable {
@Override
public void onCreate(Bundle savedInstanceState) {
// Acitivity(화면) 초기화
super.onCreate(savedInstanceState);
// main.xml 파일을 읽어들인다.
setContentView(R.layout.main);
// 로딩 다이얼로그를 표시한다.
CDialog.showLoading(this);
// 딜레이 시간 수행을 위한 스레드 작업
(new Thread(this)).start();
}
@Override
public void run() {
// 3초 딜레이
try {
Thread.sleep(3000);
} catch (Exception e) {}
// 다이얼로그 닫음
CDialog.hideLoading();
// 화면 이동
Intent intent = new Intent(this, MySubActivity.class);
startActivity(intent);
// 단말기 Back버튼을 눌렀을 때, 인트로 화면으로 돌아오지 않도록 인트로 화면을 종료
finish();
}
}
실행결과 확인
실행하면 다음과 같은 결과를 확인할 수 있습니다.
인트로 화면이 나타나고, 로딩바가 나타난 상태에서 3초 후에, 두번째 화면으로 이동합니다.
요즘 안드로이드 프로젝트를 한건 하고 있습니다.
아이폰과 동시 개발이 진행되고 있는 건이여서 그런지, 디자이너분께서 보내주신 컴포넌트 요소들의 그래픽이 모두 아이폰의 그것과 닮아있습니다. 더더군다나 더 골치스러운것은 팝업창의 디자인도 모두 아이폰처럼 되어 있어서 직접 새로 해야 한다는 점입니다.
아이폰의 기본 컴포넌트 PSD파일은 잘 찾아서 사용하면서 안드로이드용은 못찾겠다고 하는 바람에 디자이너에게 전달할 자료를 찾다가 안드로이드용 컴포넌트 PSD 파일을 찾았습니다.
단어 자체의 뜻은 인조인간이다. 사용자를 위해 여러가지 심부름을 대신해준다는 뜻이라고 한다.
안드로이드는 누가 만드는가?
안드로이드는 OHA(Open Handset Aliance) 주체로 개발되고 있는 모바일 운영체제이다.
- 명목상 OHA가 개발주체이지만 실직적으로는 구글이 리드하고 있다.
안드로이드의 구성 및 특징
커널은 리눅스에 기반한다. 공식적으로 Java를 사용하고, C로 개발할 수 있는 NDK도 발표되었지만 아직 일반적이지는 않다.
안드로이드 내부에는 많은 외부 라이브러리가 포함되어 있어 거의 별도의 외부 라이브러리를 사용할 필요가 없다.
플랫폼에 내장되어 있는 프로그램들과 사용자가 만들어서 탑재하게 되는 프로그램이 동일한 API를 사용하게 되므로, 원한다면 기본 제공되는 프로그램들도 사용자가 원하는 것으로 교체 가능하다. 플랫폼을 구성하는 요소들을 자유롭게 선택할 수 있다는 면에서 유연성이 뛰어나다.
커널위에는 Application들이 공통적으로 사용하는 System library가 존재한다. library 는 장비의 전반적인 속도를 결정하는 중요한 요소여서 Java가 아닌 C로 개발되어 있다.
안드로이드 Runtime은 Dalvik Virtual Machine과 Java Core Library로 구성된다. 안드로이드는 Java Virtual Machine을 직접이용하지 않고 모바일 환경에 최적화된 Dalvik Virtual Machine을 사용한다.
(각 Process별로 별도의 Dalvik Virtual Machine이 할당되는 방식이다.)
Dalvik은 안드로이드 전용 가상머신으로 Java class파일을 직접 실행할 수 없으며 class파일을 dex포맷으로 변환해야 실행가능하다.
4가지 구성요소
응용프로그램은 아래의 컴포넌트 중 일부만을 가질 수도 있고 여러개를 가질 수도 있다.
Activity - 사용자 인터페이스를 구성하는 기본단위. 눈에 보이는 화면 하나가 Activity이며 여러개의 View들로 구성된다.
Service - UI가 없어 사용자의 눈에 직접적으로 보이지 않으며 Background에서 무한히 실행되는 컴포넌트이다. UI가 없으므로 사용자의 명령을 받아 들일 수 있는 Activity와연결해서 사용한다.
Brodcast Receiver - 시스템으로부터 전달되는 방송을 대기하고 신호 전달시 수신하는 역할을 한다. 신호만 대기할 뿐 UI를 따로 가지지는 않으므로 방송 수신시 방송의 의미를 해석하고 적절한 Activity를 띄우는 역할을 한다.
Content Provider - 다른 응용프로그램을 위해 자신의 데이터를 제공한다. 응용프로그램간에 데이터를 공유할 수 있는 합법적인 장치가 Conent Provider이다. ex) Database, 주소록
이 4가지 컴포넌트들은 서로 독립적으로 동작하므로 상호간의 통신을 위한 장치가 필요한데 이 역할을 Intent가 담당한다. Intent는 컴포넌트간의 통신수단이며 메시지에 대한 상세한 정보를 가진다.
스마트폰이 하나의 생태계를 이루면서 개인 개발자들도 어플리케이션을 만들어서 마켓을 통해서 판매할 수 있게 되었습니다. 그리고 그렇게 해서 많은 수익을 올리는 개발자들이 하나 둘씩 생겨나기 시작했고, 주위에서도 어플 한두개쯤은 올려서 차비 정도는 벌고 있다는 분들도 뵙게 됩니다.
유료 어플리케이션을 만들어서 다운로드 수익을 얻는것도 하나의 방법이지만, 무료 어플리케이션을 만들면서 프로그램 안에 광고를 넣고 광고 수익을 얻는 것도 하나의 좋은 수익모델이 될 수 있습니다.
한때, 구글 애드센스를 통해서 블로그에 광고를 삽입하고 광고 수익을 얻는 파워블로거들에 대한 이야기가 이슈가 된 적이 있었습니다.
애드센스를 WebView라는 컨트롤을 사용해서 앱 안에 넣는 방법도 가능하지만 구글에서는 원칙적으로 스마트폰용 앱에 개제되는 광고에 대해서는 금지하고 있습니다.
여기서는 스마트폰 전용 광고 플렛폼인 Cauly 를 사용해서 프로그램 안에 광고를 넣는 방법을 알아 보겠습니다.
(카올리는 현재 구글 마켓과 SKTelecom의 T-Store만을 지원하고 있습니다.)
1. Cauly 사이트를 통하여 인증키 발급받기
스마트폰에 광고를 넣기 위해서는 인증키를 발급 받아야 합니다. 다음의 절차를 통해서 인증키를 발급받을 수 있습니다.
상단 메인 메뉴에서 "App 관리"를 클릭하여 페이지를 이동한 후에, 화면 중간쯤의 "App 등록" 버튼을 누릅니다.
1-3. 플랫폼 선택 및 이용 약관 동의
화면 중간에서 "Android 플랫폼"을 선택합니다.
스크롤을 아래로 내려서 이용약관 동의에 채크하고 "다음" 버튼을 누릅니다.
1-4. 어플리케이션 정보 입력
어플리케이션의 정보를 입력하는 화면이 나오면, 적절하게 내용을 입력하고 "다음"을 선택합니다.
1-5. SDK 및 메뉴얼 다운로드와 연동키값 확인
등록 절차가 완료되면 SDK와 메뉴얼을 다운로드 받을 수 있는 다음의 화면이 나옵니다.
이 상태에서 스크롤을 아래로 내려보면, 입력한 내용을 확인할 수 있으며, 연동키값을 확인할 수 있습니다.
제 경우에는 연동키 값이 tI3zXBwa3 라고 발급되었습니다.
2. 안드로이드 프로그램에 광고 적용하기
이제는 개발중인 안드로이드 프로그램안에 광고를 넣을 차례입니다.
광고를 넣기 위해서는 Cauly SDK를 다운로드 받아야 합니다.
SDK를 다운받으면 광고를 보여주는 기능을 하는 라이브러리 (CaulySDK-V1.2.3.jar) 파일과 샘플 소스가 들어 있습니다.
2-1. 라이브러리 추가하기
진행 중인 프로젝트에 lib 라는 폴더를 만들고, 그 안에 카울리 라이브러리 파일 (CaulySDK-V1.2.3.jar)을 넣습니다.
2-2. 라이브러리를 프로젝트에 참조시키기 (1)
진행중인 프로젝트를 선택한 상태에서 "Project > Properties" 항목을 선택합니다.
2-3. 라이브러리를 프로젝트에 참조시키기 (2)
프로젝트에 대한 Properties 창이 나타나면 왼쪽 트리에서 "Java Build Path" 를 선택합니다.
오른쪽의 메인 화면이 변경되면 "Library" 탭을 선택하고 "Add JARs..." 버튼을 누릅니다.
2-4. 라이브러리를 프로젝트에 참조시키기 (3)
"Add Jars..." 버튼을 누르면 "JAR Selection" 이라는 팝업창이 뜹니다. 여기에서 2-1에서 추가해준 카올리 라이브러리를 선택한 후에 "OK"버튼을 누릅니다.
"OK"버튼을 눌러서 창이 닫히면, 그 전에 떠 있던 "Properties"창 역시 "OK"버튼을 누르고 닫습니다.
광고를 넣기 원하는 XML 페이아웃 파일에 다음의 내용을 추가합니다.
광고를 추가하게 되면 가로 영역에 fill_parent로, 세로영역의 일정 공간을 차지합니다.
아래 내용에서는 두 곳을 수정해야 합니다.
xmlns:app 속성에 들어가는 URL값의 맨 마지막이 자신의 프로젝트 패키지명이 되어야 하며, app:appcode값이 카올리 웹사이트에서 발급받은 연동키 값이 들어가야 합니다.
수정해야 하는 내용과 값은 함께 등록해 놓은 스크린샷을 참조하세요.
추가하는 XML에서 각 Attribute의 의미와 값의 범위는 이 섹션의 맨 아래에 등록한 표를 참조하세요.
다음과 같은 실행 결과가 나타나면, 정상적으로 처리가 된 것입니다.
광고가 나타나는 것을 확인했다면, 이제는 마켓에 올리게 됩니다.
카올리 사이트에서 연동키를 발급받으면 최대 1일 정도의 승인 기간이 소요 됩니다.
해당 기간 안에 마켓에 프로그램을 올리면 등록한 어플리케이션 연동키의 상태가 "개제전" 에서 "개제"로 변경되고 그 다음부터 그 광고는 이용자들의 클릭수에 대하여 수익을 얻을 수 있게 됩니다.
만약 어플리케이션에 광고를 적절치 못하게 넣었거나 카올리의 정책에 위배될 경우 승인 거절이 될 수 있습니다.
승인 거절이 될 수 있는 케이스에 대해서는 SDK와 함께 배포되는 가이드 문서를 참고하세요.
//Activity 의 display 로 부터 화면 사이즈를 알아낸다. Display display = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); int width = display.getWidth(); int height = display.getHeight();
(2) View에서 화면 해상도를 얻는 방법입니다. (Context를 사용할 수 있는 곳이면 어디서든...)
int mWidth = context.getResources().getDisplayMetrics().widthPixels; int mHeight = context.getResources().getDisplayMetrics().heightPixels;
위의 2번 방법은 다음과 같이도 사용 될 수 있습니다.
int mWidth = getContext().getResources().getDisplayMetrics().widthPixels; int mHeight = getContext().getResources().getDisplayMetrics().heightPixels;
// 웹페이지 띄우기
Uri uri = Uri.parse("http://www.google.com");
Intent it = new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);
// 구글맵 띄우기
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.Action_VIEW,uri);
startActivity(it);
// 구글 길찾기 띄우기
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=출발지주소&daddr=도착지주소&hl=ko");
Intent it = new Intent(Intent.ACTION_VIEW,URI);
startActivity(it);
// 다이얼러 띄우기
Uri uri = Uri.parse("tel:xxxxxx");
Intent it = new Intent(Intent.ACTION_DIAL, uri);
startActivity(it);
// 전화걸기
// 퍼미션을 잊지 마세요.
Uri uri = Uri.parse("tel.xxxxxx");
Intent it = new Intent(Intent.ACTION_CALL,uri);
startActivity(it);
// SMS/MMS 발송
Intent it = new Intent(Intent.ACTION_VIEW);
it.putExtra("sms_body", "The SMS text");
it.setType("vnd.android-dir/mms-sms");
startActivity(it);
// SMS 발송
Uri uri = Uri.parse("smsto:0800000123");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
it.putExtra("sms_body", "The SMS text");
startActivity(it);
// MMS 발송
Uri uri = Uri.parse("content://media/external/images/media/23");
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra("sms_body", "some text");
it.putExtra(Intent.EXTRA_STREAM, uri);
it.setType("image/png");
startActivity(it);
// 이메일 발송
Uri uri = Uri.parse("mailto:xxx@abc.com");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.setType("text/plain");
startActivity(Intent.createChooser(it, "Choose Email Client"));
Intent it = new Intent(Intent.ACTION_SEND);
String[] tos = {"me@abc.com"};
String[] ccs = {"you@abc.com"};
it.putExtra(Intent.EXTRA_EMAIL, tos);
it.putExtra(Intent.EXTRA_CC, ccs);
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.setType("message/rfc822");
startActivity(Intent.createChooser(it, "Choose Email Client"));
// extra 추가하기
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "Choose Email Client"));
// 미디어파일 플레이 하기
Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/song.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);
Uri uri = Uri.withAppendedPath(
MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
// 설치 어플 제거
Uri uri = Uri.fromParts("package", strPackageName, null);
Intent it = new Intent(Intent.ACTION_DELETE, uri);
startActivity(it);
// APK파일을 통해 제거하기
Uri uninstallUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);
// APK파일 설치
Uri installUri = Uri.fromParts("package", "xxx", null);
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
// 음악 파일 재생
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");
returnIt = new Intent(Intent.ACTION_VIEW, playUri);
// 첨부파일을 추가하여 메일 보내기
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/eoe.mp3");
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "Choose Email Client"));
// 마켓에서 어플리케이션 검색 (패키지명은 어플의 전체 패키지명을 입력해야 합니다.)
Uri uri = Uri.parse("market://search?q=pname:pkg_name");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
// 마켓 어플리케이션 상세 화면 (아이디의 경우 마켓 퍼블리싱사이트의 어플을 선택후에 URL을 확인해보면 알 수 있습니다.)
Uri uri = Uri.parse("market://details?id=어플리케이션아이디");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
// 구글 검색
Intent intent = new Intent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"searchString")
startActivity(intent);
일반적인 경우, 안드로이드 용 어플리케이션을 작성하게 되면 여러가지 Activity 들을 생성하게 됩니다. 이때, 가장 골치가 아픈 일 중 하나는 바로 Activity 와 Activity 간의 Flow 를 설계하고 이를 적절하게 구현하는 일입니다. (특히 안드로이드를 사용해보지도 않은 UX 팀과 함께 일하게 되는 경우라면 더욱 그러합니다...)
기본적으로 안드로이드 플랫폼 상에서 Activity 는 또 다른 Activity 를 시작할 수 있고, 각각의 Activity 는 차곡 차곡 Task 라고 불리우는 Activity Stack 에 쌓이게 됩니다. 사용자는 일반적으로 Back 버튼을 이용해서 현재 화면상에 보이는 Activity 를 종료 시키고, 바로 직전에 사용된 Activity 로 돌아갈 수 있습니다. 안드로이드 펍의 회색님의 말을 빌리자면, 인터넷 브라우저를 통해 웹페이지를 검색하는 것과 유사한 방식입니다.
하지만 이러한 방법만으로는 효과적인 UX Flow 를 구축하는데 어려움이있습니다. 다행히, 구글에서는 Activity 를 호출할 때 사용되는 Intent 에 적절한 플래그 값을 설정해서 Activity Stack 을 제어할 수 있는 방법을 제공해 줍니다. 이 플래그들은 FLAG_ACTIVITY 라는 접두어를 갖고 있는데, 종류가 다양해 헷갈리는 수도 있는데, 개인적으로 제가 가장 요긴하게 사용하고 있는 FLAG_ACTIVITY 네 가지를 소개해 봅니다.
먼저 FLAG_ACTIVITY_SINGLE_TOP 입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B 두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 다시 자기 자신인 B 를 호출 하는 경우라고 가정해 보겠습니다.
<FLAG_ACTIVITY_SINGLE_TOP>
호출하는 Activity B 가 이미 Task 의 가장 앞에 위치하는 경우, 또 하나의 B 를 생성하는 대신, 기존에 존재하는 B Activity 가 재활용됩니다. 이 때 B 가 재활용된다는 것을 개발자가 알아채고 새롭게 전달되는 Intent 를 사용할 수 있도록 B Activity 의 onPause() / onNewIntent() / onResume() 가 순차적으로 호출됩니다.
별 생각없이 동일한 Activity 를 여러번 생성하는 것은 메모리 사용량과 Activity 시작 속도 양쪽 모두에 악영향을 끼칠 수 있습니다. (특히 이미지가 덕지덕지 붙어 있는 Activity 라면). 이런 경우 FLAG_ACTIVITY_SINGLE_TOP 를 적절하게 활용하면 제법 큰 효과를 볼 수 있습니다.
두 번째는, FLAG_ACTIVITY_NO_HISTORY 플래그입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B 두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 A 를 호출한 후 에 (A->B->A) 사용자가 Back 키를 누르는 경우를 가정해 보겠습니다.
<FLAG_ACTIVITY_NO_HISTORY>
말 그대로, FLAG_ACTIVITY_NO_HISTORY 로 설정된 Intent 로 시작된 Activity B 는 Task 에 그 흔적을 남기지 않게 됩니다. B 에서 또다른 A 를 시작한 후, Back 을 누르면 일반적인 경우 이전에 실행되었던 B 가 나타나지만, NO_HISTORY 를 사용하는 경우 맨 처음에 실행 되었던 A 가 화면에 표시됩니다.
몇 가지 주의할 점이 있습니다. 우선 NO_HISTORY 를 사용하게 되면 Task 에 해당 Intent 의 정보가 기록되지 않기 때문에, A->B 인 상황 (그림에서 두 번째 단계...) 에서 홈키등을 눌러 다른 Task 로 전환된 후, 다시 본 Task 로 돌아오게 되면, A Activity 가 화면에 표시됩니다. 또한, B Activity 의 onDestroy() 가 호출되는 시점이 조금 애매합니다. 일반적인 예상과는 달리, B 에서 또다른 A Activity 를 호출하는 세 번째 단계에서는 onStop 까지만 호출되고, 이 후에 새롭게 호출된 A Activity 가 사라지는 순간 (네 번째 단계) 에서야 onDestroy() 가 호출 됩니다.
FLAG_ACTIVITY_NO_HISTORY 는 여러가지로 쓸모가 있는데, 특히 특정한 이벤트에 대한 알람등을 위해 다이얼로그 형태로 화면에 표시되는 Activity 들에 적용하기에 편리합니다. (대게의 경우 팝업은 해당 시점에 한번만 보여주면 되니까.)
다음으로 굉장히 유용한 플래그 두 가지를 동시에 설명해보고자 합니다.
FLAG_ACTIVITY_REORDER_TO_FRONT 와 FLAG_ACTIVITY_CLEAR_TOP 플래그입니다. 우선 간략하게 그림으로 살펴 보겠습니다. A Activity 에서 B Activity 를 그리고 B 에서 A 를 호출하는 상황을 가정해보았습니다. (A->B->A)
FLAG_ACTIVITY_REORDER_TO_FRONT 는 매우 특이하게도 Task 의 순서 자체를 뒤바꿔 줍니다. 이 플래그를 사용하면, 런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우 해당 Activity 를 새롭게 생성하는 대신, 아래쪽에 위치한 Activity 의 순서를 Task 의 가장 위로 끌어올려줍니다.
따라서 A->B->A 의 순서로 Activity 호출이 일어날때, 새로운 A 가 생성되는 대신 아래쪽에 위치한 A 가 위로 올라와 최종적으로 B->A 의 형태로 Task 가 구성되게 됩니다.
어떤 Activity 에서 특정 Activity 로 점프하는 형식의 Flow 를 구성해야하는 경우 요긴하게 사용될 수도 있지만, Task 의 순서를 뒤섞는 다는 점에서 사용에 주의를 기울일 필요가 있습니다. (별 생각없이 남발하게 되면 Back 키가를 누를 때 엉뚱한 Activity 가 표시되어 사용자들이 굉장히 혼란스러워 하는 경우가 있습니다.)
마지막으로 소개해 드릴 플래그는 바로 FLAG_ACTIVITY_CLEAR_TOP 입니다. 제가 개인적으로 가장 사랑스럽게 생각하는 녀석입니다. 이 플래그가 사용되는 경우 런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우, 해당 Activity 위에 존재하는 다른 Activity 를 모두 종료시켜 줍니다. 따라서 A->B->A 로 호출이 일어나는 경우, B Activity 가 종료 되고, A Activity 만 Task 에 남게 됩니다. (A->B->C->A 인 경우에도 마찬가지로 B와 C 가 종료되고 A 만 남게 됩니다.)
이 Flag 는 특정 어플리케이션의 대쉬보드 (혹은 홈) Activity 를 호출할 때 굉장히 유용하게 사용될 수 있습니다. 즉 하나의 어플리케이션이 하나 혹은 두 가지의 주요한 Activity 와 그 외 특정 값을 선택하는등 단순한 일을 수행하기 위한 여러 개의 Sub-Activity 로 구성되어 있다면, 주요 Activity 를 호출하는데 이 Flag 를 사용함으로서 어플리케이션의 홈버튼등을 손쉽게 구현할 수 있습니다. 또 이 Flag 는 FLAG_ACTIVITY_REORDER_TO_FRONT 와는 달린 Task 의 순서를 뒤섞지 않음으로 사용자에게도 큰 혼란을 주지 않습니다. (사용을 적극 권장합니다.)
한 가지 주의해야할 점은 A->B->A 형태로 Activity 를 호출 하고자 할 때, 단순히 FLAG_ACTIVITY_CLEAR_TOP 만을 사용하게 되면, 기존에 생성되었던 A Activity 가 종료된 후 (onDestroy() 가 호출됨) 새롭게 A 가 생성 (onCreate()) 됩니다. 만일 기존에 사용된 A Activity 가 계속 사용되기를 원한다면, SINGLE_TOP 플래그와 함께 사용해야 합니다.
휴... 생각보다 내용이 길어졌네요. 대부분 SDK 문서를 읽어보면 잘 나와있는 내용이라 새로운 내용은 없습니다만... 문서 읽기를 게을리한 덕분에 한창을 고생했던 기억이 떠올라 (특히 CLEAR_TOP) 유용하게 사용한 Flag 를 정리하는 겸 작성해 보았습니다~
애플리케이션을 제작하다 보면 파일을 입/출력 기능을 구현해야 하는 경우가 있습니다. 파일 입/출력을 수행하려면 파일의 경로를 꼭 알아야 하는데, 안드로이드에서 파일을 저장할 수 있는 경로는 다양합니다.
가장 크게 애플리케이션 데이터가 저장되는 영역(일반적으로 '내부 저장소(Internal Storage)'라 불림)와 사진, 비디오, 데이터 등을 저장하는 영역(일반적으로 '외부 저장소(External Storage)(주1)'라 불림)으로 나뉠 수 있으며, 각 영역별로 다시 캐시 데이터가 저장되는 영역, 데이터베이스가 저장되는 영역 등으로 나뉩니다.
(주1) 외부 저장소는 사용자 데이터(사진, 동영상, 등)이 저장되는 영역입니다. 일반적으로 이는 단말기의 외장 SD카드를 지칭하지만, 단말기에 따라서는 이 영역이 외장 SD카드가 아닌 단말기 내부에 탑재되어 있는 경우도 있었습니다. (넥서스S가 이에 해당) 또는, 단말기 내에 탑재된 외장 메모리 영역 외에 별도의 SD카드도 지원하는 단말기도 존재합니다. (갤럭시S가 이에 해당)
내부 저장소는 각 애플리케이션에서만 데이터를 읽고 쓸 수 있지만, 외부 저장소에는 특정 애플리케이션에서만 사용하는 애플리케이션 고유 영역과 공용 영역이 각각 존재합니다. 애플리케이션 고유 영역에는 각 애플리케이션에서 사용하는 데이터를 저장하며, 이 영역에 저장된 내용은 애플리케이션이 삭제될 때 같이 삭제됩니다.
공용 영역에는 사진, 비디오, 기타 파일 등을 저장하며 애플리케이션의 삭제에 영향을 받지 않습니다. 하지만, 외부 저장소에 저장된 데이터는 애플리케이션 고유 영역에 저장되어 있더라도 다른 애플리케이션에서 해당 데이터에 접근하는 것이 가능합니다.
각 영역의 경로가 필요할 때마다 해당 경로를 직접 써서 사용할 수도 있겠지만, 번거롭기도 하고 각 유형에 해당하는 경로를 그 때마다 찾아봐야 하므로 시간도 많이 소요됩니다. 이러한 이유로 안드로이드에서는 데이터가 저장되는 주요 경로를 간편하게 얻는 메서드를 제공합니다.
내부 저장소
1. 캐시(Cache) 저장 영역
캐시 디렉터리에는 애플리케이션에서 필요한 임시 파일들이 저장됩니다.
API File Context.getCacheDir()
내부 저장소의 캐시 디렉터리 경로를 반환합니다.
내부 저장소의 캐시 디렉터리 경로는 다음과 같이 구성됩니다.
/data/data/[패키지 이름]/cache
패키지 이름이 com.androidhuman.app 일 경우, 이 애플리케이션의 캐시 디렉터리 경로는 다음과 같습니다.
/data/data/com.androidhuman.app/cache
2. 데이터베이스(Database) 파일
애플리케이션에서 사용하는 데이터베이스 파일들이 저장됩니다.
API File Context.getDatabasePath(String name)
데이터베이스 파일의 경로를 반환합니다. 인자로 데이터베이스 파일의 이름을 넘겨줍니다.
데이터베이스 파일이 저장되는 경로는 다음과 같이 구성됩니다.
/data/data/[패키지 이름]/databases
패키지 이름이 com.androidhuman.app 일 경우, 데이터베이스 파일은 다음 경로에 저장됩니다.
/data/data/com.androidhuman.app/databases
3. 일반 파일 저장 영역
데이터베이스와 캐시를 제외한 애플리케이션에서 사용하는 일반 파일이 저장되는 영역입니다. 이 경로는 Context.openFIleOutput(String, int)를 사용하여 생성되는 파일이 저장되는 경로와 동일합니다.
API File Context.getFilesDir()
애플리케이션에서 사용하는 일반 파일들이 저장되는 경로를 반환합니다.
파일이 저장되는 경로는 다음과 같이 구성됩니다.
/data/data/[패키지 이름]/files
패키지 이름이 com.androidhuman.app 일 경우, 일반 파일은 다음 경로에 저장됩니다.
/data/data/com.androidhuman.app/files
애플리케이션에서 사용하는 각 일반 파일들의 경로를 가져오려면 다음 메서드를 사용합니다.
API File Context.getFileStreamPath(String name)
일반 파일이 저장된 공간에서 특정 이름을 가지는 파일의 경로를 반환합니다. 인자로 확장자를 포함한 파일 이름을 넘겨줍니다.
파일의 경로는 다음과 같이 구성됩니다.
/data/data/[패키지 이름]/files/[파일이름]
패키지 이름이 com.androidhuman.app 이고 파일 이름이 filename.ext일 경우, 파일의 경로는 다음과 같습니다.
API static File Environment.getExternalStorageDirectory()
외부 저장소의 최상위 경로를 반환합니다.
2.2 (Froyo) 이상을 기준으로 반환되는 최상위 경로는 일반적으로 다음과 같습니다.
/mnt/sdcard
2. 특정 데이터를 저장하는 영역
여러 애플리케이션에서 공용으로 사용할 수 있는 데이터들을 저장합니다. 데이터의 유형에 따라 별도의 디렉터리를 사용합니다.
API static File Environment.getExternalStoragePublicDirectory(String type)
데이터 유형에 따른 외부 저장소의 저장 공간 경로를 반환합니다. 인자로 디렉터리의 유형을 넘겨줍니다.
안드로이드에서는 총 7개 데이터 유형에 대한 표준 저장 경로를 제공합니다. Environment.getExternalStoragePublicDirectory()의 인자로 넘겨줄 수 있는 인자 및 각 인자의 경로는 다음과 같습니다.
인자명
설명
경로
Environment.DIRECTORY_ALARMS
알람으로 사용할 오디오 파일을 저장합니다.
/mnt/sdcard/Alarms
Environment.DIRECTORY_DCIM
카메라로 촬영한 사진이 저장됩니다.
/mnt/sdcard/DCIM
Environment.DIRECTORY_DOWNLOADS
다운로드한 파일이 저장됩니다.
/mnt/sdcard/Download
Environment.DIRECTORY_MUSIC
음악 파일이 저장됩니다.
/mnt/sdcard/Music
Environment.DIRECTORY_MOVIES
영상 파일이 저장됩니다.
/mnt/sdcard/Movies
Environment.DIRECTORY_NOTIFICATIONS
알림음으로 사용할 오디오 파일을 저장합니다.
/mnt/sdcard/Notifications
Environment.DIRECTORY_PICTURES
그림 파일이 저장됩니다.
/mnt/sdcard/Pictures
Environment.DIRECTORY_PODCASTS
팟캐스트(Poacast) 파일이 저장됩니다.
/mnt/sdcard/Podcasts
이 영역에 데이터를 저장하기 전에, 해당 디렉터리가 존재하는지 필히 확인해야 합니다. 이를 확인하기 위해 File.mkdirs()를 사용하여 디렉터리가 없을 경우 새 디렉터리를 생성합니다. 디렉터리가 존재하지 않을 경우 FileNotFoundException이 발생합니다.
외부 저장소-애플리케이션 고유 영역
1. 특정 데이터를 저장하는 영역
애플리케이션 고유 영역에도 공용 영역과 마찬가지로 각 데이터 유형별로 데이터를 저장하는 표준 디렉터리를 제공합니다.
API File Context.getExternalFilesDir(String type)
애플리케이션 고유 영역의 데이터 유형에 따른 외부 저장소의 저장 공간 경로를 반환합니다. 인자로 디렉터리의 유형을 넘겨줍니다.
사용자 인증과 관련된 기능에서 아이디와 비밀번호만으로도 인증처리는 가능하지만, 좀더 세심한 보안처리를 위해서는 특정 핸드폰 번호와 특정 단말기에서만 인증이 가능하도록 요구되는 경우도 종종 있습니다. 그러한 요구사항에 대응하기 위해서 사용되는 간단한 함수들을 정리해 봤습니다.
우선 이 포스팅에서 소개하는 함수는 퍼미션 추가가 필요합니다.
AndroidManifest.xml 파일에 android.permission.READ_PHONE_STATE 퍼미션을 추가합니다.