Android Programming/ko
│
English (en) │
日本語 (ja) │
한국어 (ko) │
русский (ru) │
中文(中国大陆) (zh_CN) │
Custom Drawn Interface/Android도 보세요
일반적인 안드로이드 프로그래밍을 아는 것은 라자루스 안드로이드 인터페이스를 개발에 매우 유용하다.
방법...
NDK OpenGL 예제 빌드하기
다음 단계를 따르시요:
1 단계 - 안드로이드 NDK, 안드로이드 SDK 및 Ant.를 다운로드하고 설치하세요. 더 많은 정보는 다음에: 안드로이드 SDK와 에뮬레이터 및 폰을 사용한 안드로이드 인터페이스
2 단계 - 프리-컴파일 된 FPC 크로스-컴파일러를 설치한다. 설명은 이곳에: Android_Interface#Using_the_pre-compiled_compiler
3 단계 - 최신 라자루스 ccr소스포지 코드를 다운로드 한다:
svn co https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr lazarus-ccr
또는 만약 너무 크다고 생각한다면 lazarus-ccr/bindings/android-ndk 폴더만 다운로드하면 된다.
4 단계 - 파스칼 라이브러리를 빌드한다.
lazarus-ccr/bindings/android-ndk/examples/opengltest/opengltest.lpi 프로젝트를 연다.
Project->Project Options->Paths로 가서 "Libraries -Fl"이라고 쓰인 곳에서 이 값을 확인한다:
/home/felipe/Programas/android-ndk-r5/platforms/android-9/arch-arm/usr/lib
각자의 시스템에 있는 NDK와 최소 요구 안드로이드 API 레벨의 폴더를 가르키는 정확한 패스로 변경한다.
이제 라자루스에서 프로젝트를 빌드한다.
5 단계 - 빌드환경을 구성한다.
opengltest/local.propertie 파일을 열고 이 라인을 다음과 같이:
sdk.dir=/home/felipe/Programas/android-sdk-linux
이것을 SDK 위치로 변경한다.
6 단계 - APK를 빌드한다.
터미널을 역고 다음 명령을 입력한다:
cd lazarus-ccr/bindings/ndk/examples/opengltest/android ant debug
APK파일이 opengltest/android/bin/에 위치해 있을 것이다.
7 단계 - APK를 설치한다.
이 단계에서 퍼미션에 관한 에러가 발생하면 다음 글을 읽어라: 리눅스에서 장치의 인식
폰에서 APK를 설치하는 명령은:
cd opengltest/android ~/Programas/android-sdk-linux/platform-tools/adb install bin/OpenGLNDKTest-debug.apk 2395 KB/s (107299 bytes in 0.043s) pkg: /data/local/tmp/OpenGLNDKTest-debug.apk Success
이미 설치되어 있다는 에러 메세지가 나오면 다음 명령으로 설치할 수가 있다:
~/Programas/android-sdk-linux/platform-tools/adb uninstall com.pascal.opengltest
그리고 나서 새로이 추가된 아이콘을 통해 폰에서 실행하는 동안 무슨 로그가 있는지 알려면 adb logcat을 실행하면 된다:
~/Programas/android-sdk-linux/platform-tools/adb logcat
스크린 metrics 읽기
먼저 TDisplayMetrics에 정확한 정보를 넣는다:
uses androidutil;
var
MyDisplayMetrics: TDisplayMetrics;
Str: string;
//
lHeight, lWidth: Integer;
xdpi, ydpi, lScreenSize: Single;
begin
// ..
// 객체
MyDisplayMetrics := TDisplayMetrics.Create;
Activity.getWindowManager().getDefaultDisplay().getMetrics(MyDisplayMetrics);
그리고 나면 TDisplayMetrics에 읽을 수 있다:
lHeight := MyDisplayMetrics.heightPixels();
lWidth := MyDisplayMetrics.widthPixels();
xdpi := MyDisplayMetrics.xdpi();
ydpi := MyDisplayMetrics.ydpi();
lScreenSize := sqrt(sqr(lHeight / ydpi) + sqr(lWidth / xdpi));
ldensity := MyDisplayMetrics.density();
ldensityDpi := MyDisplayMetrics.densityDpi();
scaledDensity := MyDisplayMetrics.scaledDensity();
많은 장치가 xdpi 와 ydpi가 다르다. 그러므로 위에서 계산한 lScreenSize 를 믿지마라. 스마트폰이 10 인치로 되어 있더라도, 정확한 값은 4 주변이다.
안드로이드 기기에 대한 세부사항
무척 많은 안드로이드 기기가 있이 때문에, 기기에 대한 몇가지 정보를 추적하는 것이 유용할 수 있다. 안드로이드 기기에 대해 위키피디아에서 비교한 [ http://en.wikipedia.org/wiki/Comparison_of_Android_devices] 것과[1]에 있는 프로세서의 자세한 명세를 읽어봐야 한다.
스마트폰
제조사 | 모델 | 안드로이드 API 이름 (빌드.모델) | 프로세서 | 안드로이드 버전 | 멀티터치 | 기타 |
---|---|---|---|---|---|---|
HTC | Wildfire | HTC Wildfire | armv6 | 2.1=>2.2 | Yes | - |
Sony Erricson | Xperia X10 | X10i | armv7 | 1.6=>2.1 | No | - |
태블릿
제조사 | 모델 | 안드로이드 API 이름 (빌드.모델) | 프로세서 | 안드로이드 버전 | 멀티터치 | 기타 |
---|---|---|---|---|---|---|
Toshiba | Folio 100 Tablet | TOSHIBA_FOLIO_AND_A | armv7 | 2.2 | Yes | - |
프로세서 호환(ARMv6 vs ARMv7) 순서에 따른 기기 리스트
ARMv7 기기리스트:
- Advent Vega (P10AN01)
- Dell Streak, Streak 7
- HTC Desire
- HTC Desire Z (T-Mobile G2)
- HTC Desire HD
- HTC Droid Incredible
- HTC EVO 4G, EVO Shift 4G
- HTC Glacier (T-Mobile myTouch 4G)
- HTC Inspire 4G
- HTC Nexus One
- HTC Thunderbolt 4G
- Huawei Ideos S7
- LG Optimus Z
- Motorola Atrix 4G
- Motorola Bravo
- Motorola Cliq 2 - untested
- Motorola Defy
- Motorola Droid 2, Droid 2 Global
- Motorola Droid Pro (Motorola PRO)
- Motorola Droid X
- Motorola Xoom
- POV Mobii Tegra Tablet
- Samsung Continuum (i400)
- Samsung Galaxy S (i9000, Captivate, Fascinate, Vibrant, Epic 4G)
- Samsung Galaxy Tab
- Sharp IS03
- Sony Ericsson Xperia X10
- Toshiba AS100
- Viewsonic gTablet
- Acer Liquid E
- Acer Liquid (Liquid A1)
- Archos 101 Internet Tablet
- Motorola Charm
- Motorola Droid (Milestone)
- Samsung Galaxy S 4G
- Samsung Nexus S
ARMv6 프로세서 리스트:
- Android SDK 에뮬레이터
- Asus Garmin nuvifone A50 (T-Mobile Garminfone)
- Augen GENTouch 78 Tablet
- Coby Kyros Internet Tablet (MID7015)
- Geeksphone One, Geeksphone Zero
- HTC Aria
- HTC ChaCha
- HTC Dream (T-Mobile G1, Android Dev Phone 1)
- HTC Droid Eris
- HTC Espresso (T-Mobile myTouch 3G Slide)
- HTC Hero (T-Mobile G2 Touch)
- HTC Legend
- HTC Magic (T-Mobile myTouch 3G, T-Mobile G1 Touch)
- HTC Salsa
- HTC Tattoo
- HTC Wildfire
- Huawei Ascend
- Huawei Ideos U8150-B (T-Mobile Comet)
- Huawei U8110 (T-Mobile Pulse Mini)
- Huawei U8230
- LG Ally (Apex) (LG VS740)
- LG GW620 (Eve, InTouch Max, LinkMe)
- LG Optimus, Optimus M, Optimus T, Optimus S, Optimus V
- LG Vortex
- LG P500
- MAG iMiTO iM7
- vMAG iMiTO iM7S
- Motorola Backflip
- Motorola Citrus
- Motorola Cliq (MB200)
- Motorola Dext
- Motorola Devour
- Motorola i1
- Motorola Spice XT300
- Motorola Quench XT5 XT502
- Pandigital Novel
- Samsung GT-S5570 Galaxy Mini
- Samsung i5500 Galaxy 5 (Corby)
- Samsung i5700 Galaxy Portal (Spica)
- Samsung i5800 Galaxy 3
- Samsung i7500 Galaxy
- Samsung Intercept
- Samsung M900 Moment
- Samsung S5830 Galaxy Ace
- Samsung Transform
- Sanyo ZIO M6000
- Sony Ericsson Xperia X8
- Sony Ericsson Xperia X10 Mini
- Sony Ericsson Xperia X10 Mini Pro
- Superpad 10.2" Tablet PC
- Viewsonic ViewPad 7 Tablet
- Velocity Micro T103 Cruz tablet
- Vodafone 845
- ZTE Blade
폰에서 사운드와 비디오 재생하기
각각의 폰은 서로 다른 코덱이 설치되어 있어서 네이티브 미디어플레이어가 폰에 따라 다른 포멧으로 플레이 할 수가 있다는 것을 의미한다. 다음은 각 폰의 네이티브 미디어 플레이어가 어떤 포맷을 플레이하는지 모여주는 표이다:
전화기 | 안드로이드 | webm - VP8 | m4v - H.264 | ogv - Theora | mp4 - H.264 | mov - H.264 | avi - RLE | mpg - MPEG-1 | wmv - WM9 | 3gp - MPEG-4 |
---|---|---|---|---|---|---|---|---|---|---|
에뮬레이터 | 1.6 | x | x | x | x | x | x | x | x | OK |
에뮬레이터 | 2.1 | x | x | x | x | x | x | x | x | OK |
Nexus One | 2.2 | x | OK | x | OK | x | x | x | x | OK |
HTC Desire | 1.6 | x | OK | x | OK | x | x | x | OK | OK |
Toshiba Folio 100 | 2.2 | x | OK | x | OK | x | x | x | OK | OK |
Xperia X10 | 2.1 | x | OK | x | x | x | x | x | OK | OK |
Xperia X8 | 2.2 | x | OK | x | x | x | x | x | x | OK |
HTC Wildfire | 2.1 | x | OK | x | x | x | x | x | x | OK |
HTC Desire HD | 2.2 | x | OK | x | OK | x | x | x | x | OK |
Galaxy Tab | 2.2 | x | OK | x | x | x | x | x | x | OK |
myPhone A210 | 1.6 | x | OK | x | x | x | x | x | x | OK |
Motorola Milestone | 2.1 | x | OK | x | x | x | x | x | OK | ? |
Milestone 2 | 2.2 | x | OK | x | x | x | x | x | 사운드만 | OK |
안드로이드 파일 시스템
안드로이드는 어플리케이션이 데이터 디렉토리를 얻을 때 getApplicationContext().getFilesDir()의 사용을 추천하며 이 루틴은 HTC Wildfire에서는 /data/data/<패키지 명> 을 반환한다.
어플리케이션의 네이티브 라이브러리는 /data/data/<패키지>/lib 에 위치한다.
읽고 쓰고 새로운 파일을 생성하고 파일을 실행 시키기 좋은 곳은 /data/data/<패키지 명> 이다.
새로운 Java 어플리케이션의 생성
이 정보는 LCL-CustomDrawn-Android의 구현을 도와주는데 유용할 수 있다.
일반적인 설명은 이곳에 있다: http://developer.android.com/guide/developing/other-ide.html
가상 키보드를 보이고 / 숨기기
이곳을 보세요: http://android-codes-examples.blogspot.com/2011/11/show-or-hide-soft-keyboard-on-opening.html
나타내기:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
키보드 감추기 위해서는:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(singleedittext.getWindowToken(),0);
안드로이드 JNI
JNI (Java Native Interface)를 사용하여 대부분의 안드로이드 SDK API들과 다른 Java 라이브러리를 호출 할 수 있다.
Java 타입과 파스칼 JNI 타입에 대한 표
인터페이스를 제외한 모든 Java 타입들은 JNI에서 문제없이 표시할 수 있다. 각각의 Java 타입에 대해 javaEnvRef^^.GetMethodID 과 같이 루틴에서 사용되는 VM 타입에 대응하는 것이 존재한다. 또한 JNI 네이티브 타입이 있으며, 이는 lazarus/lcl/interfaces/customdrawn/android/jni.pas 유닛에 선언되어 있고 파스칼로 작성된 JNI 코드에서 이용되는 타입이어야 한다. 파스칼에서 동등한 타입이 비교를 위해 제공 되며, JNI 코드를 작성할 때는 jni.pas 에서 선언된 타입이어야 한다.
Java Types | VM 시그너쳐 | jni.pas에서의 Types | 파스칼에서 | 설명 |
---|---|---|---|---|
boolean | Z | jboolean | Boolean | |
byte | B | jbyte | Byte | |
char | C | jchar | Word | |
short | S | jshort | Shortint | |
int | I | jint | Integer | |
long | J | jlong | Int64 | |
float | F | jfloat | Single | |
double | D | jdouble | Double | |
a class, ie: String or InputStream | L<full class name> ie: Ljava/lang/String; | jobject | N/A | |
Array, ie: int[] | [<type-name> ie: [I | N/A | ||
A method type | (arg-types)ref-type | JMethodID | N/A | |
void | V | N/A | procedure |
예제 1: Java 오브젝트를 생성하고 Java 메서드를 호출하기
다음 Java 코드에 대응하는 파스칼 JNI 코드를 원한다고 하자.
HttpGet javaRequest = new HttpGet();
URI myURI = new URI("http://magnifier.sourceforge.net/");
javaRequest.setURI(myURI);
먼저 프로세스에 포함되는 모든 Class ID를 얻어야 한다. 그리고 나서 사용할 모든 메서드의 ID를 얻고 호출을 한다. 만약 호출이 파라메터를 가진다면, 배열로 전달한다. 다음 파스칼 네이티브 코드는 위의 Java 코드에 대응한다:
uses jni, customdrawnint;
var
javaClass_HttpGet, javaClass_URI: jclass;
javaMethod_HttpGet_new, javaMethod_HttpGet_setURI,
javaMethod_URI_new: jmethodid;
javaRequest, javaURI: jobject;
javaString: jstring;
lParams: array[0..2] of JValue;
lNativeString: PChar;
begin
DebugLn(':>LoadHTMLPageViaJNI');
// 먼저 필요한 모든 클래스에 대하여 FindClass를 콜한다.
javaClass_HttpGet := javaEnvRef^^.FindClass(javaEnvRef,
'org/apache/http/client/methods/HttpGet');
javaClass_URI := javaEnvRef^^.FindClass(javaEnvRef,
'java/net/URI');
// 이제 모든 메서드 ID를 얻는다
DebugLn(':LoadHTMLPageViaJNI 1');
javaMethod_HttpGet_new := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_HttpGet, '<init>', '()V');
javaMethod_HttpGet_setURI := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_HttpGet, 'setURI', '(Ljava/net/URI;)V');
javaMethod_URI_new := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_URI, '<init>', '(Ljava/lang/String;)V');
// HTTP 응답 객체에 대한 새로운 인스턴스를 생성한다
// HttpGet javaRequest = new HttpGet();
javaRequest := javaEnvRef^^.NewObject(javaEnvRef,
javaClass_HttpGet,
javaMethod_HttpGet_new);
DebugLn(':LoadHTMLPageViaJNI 4 javaRequest='+IntToHex(PtrInt(javaRequest), 8));
// 응답 객체에 URI를 추가한다
// URI javaURI = new URI("http://magnifier.sourceforge.net/");
lParams[0].l := javaEnvRef^^.NewStringUTF(javaEnvRef, 'http://magnifier.sourceforge.net');
javaURI := javaEnvRef^^.NewObjectA(javaEnvRef,
javaClass_URI, javaMethod_URI_new, @lParams[0]);
javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[0].l);
// javaRequest.setURI(javaURI);
lParams[0].l := javaURI;
javaEnvRef^^.CallVoidMethodA(javaEnvRef, javaRequest,
javaMethod_HttpGet_setURI, @lParams[0]);
예제 2: 정적 메서드 호출
Bass 클래스에 있는 다음 정적 메서드를 호출하기를 원한다고 하자. http://jerome.jouvie.free.fr/nativebass/javadoc/org/jouvieje/bass/Bass.html
public static native int BASS_StreamCreateFile(String file, long offset, long length, int flags);
먼저 프로세스에 포함된 모든 Class ID를 얻고 정적 메서드의 ID를 얻으며 배열과 함께 파라메터를 넣어 호출한다:
uses jni, customdrawnint;
var
javaClass_Bass: jclass;
javaMethod_Bass_BASS_StreamCreateFile: jmethodid;
javaString: jstring;
lParams: array[0..3] of JValue;
lRetInt: jint;
begin
// 먼저 필요한 모든 클래스에 대하여 FindClass를 콜한다.
javaClass_Bass := javaEnvRef^^.FindClass(javaEnvRef, 'org/jouvieje/bass/Bass');
// 모든 메서드 ID
javaMethod_Bass_BASS_StreamCreateFile := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaClass_Bass, 'BASS_StreamCreateFile', '(Ljava/lang/String;JJI)I');
// 호출한다.
lParams[0].l := javaEnvRef^^.NewStringUTF(javaEnvRef, '/path/to/file');
lParams[1].j := 0; // 오프셋
lParams[2].j := 200; // 길이
lParams[3].i := 0; // 플래그
lRetInt := javaEnvRef^^.CallStaticIntMethodA(javaEnvRef, javaClass_Bass, javaMethod_Bass_BASS_StreamCreateFile, @lParams[0]);
javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[0].l);