본문 바로가기

파이어몽키

안드로이드 API를 파이어몽키에서 사용하기(Toast 메시지 구현)

안드로이드 API를 파이어몽키에서 사용방법을 공유합니다. 제가 이해한 내용 기반으로 작성해서 틀린부분이 있을 수 있으니 혹시 틀린부분이 보이시면 댓글달아 주세요.

안드로이드 API 사용을 위해 파이어몽키로 변환할 대상은 안드로이드 Toast를 기반으로 설명하겠습니다.

Toast는 아래의 그림과 같이 하단에 잠시 나타났다가 사라지는 메시지입니다. 파이어몽키에는 제공하지 않습니다.



설명은 아래의 순서대로 진행하겠습니다.

1, 안드로이드 API 문서확인
2, 파이어몽키에서 안드로이드 API 접근 시 구성
3, 안드로이드 API 컨버팅
4, 사용법 및 샘플코드

안드로이드 API 문서확인

변환할 대상인 Toast의 안드로이드 문서는 아래 링크에서 확인 할 수 있습니다.


위쪽 문서는 API 문서구요, 아래의 문서는 샘플코드 문서입니다.


우선 위의 API문서를 보시면 대략 아래와 같은 단락으로 구성되어있으니 숙지해 주시구요.
  • Contants
  • Public Constructors
  • Public Methods - 
  • Inherited Methods
  • Fields(Toast에서는 미사용)


파이어몽키에서 안드로이드 API 접근 시 구성

unit Android.JNI.Toast;

interface

{$IFDEF ANDROID}
uses
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText;

type
  JToast = interface;

  JToastClass = interface(JObjectClass)
  ['{F227353E-DCE9-404B-8129-6B1BEFE68151}']
    {Property methods}
    function _GetLENGTH_LONG: Integer; cdecl;
    function _GetLENGTH_SHORT: Integer; cdecl;
    {Methods}
    function init(context: JContext): JToast; cdecl; overload;
    function makeText(context: JContext; text: JCharSequence;
      duration: Integer): JToast; cdecl;
    {Properties}
    property LENGTH_LONG: Integer read _GetLENGTH_LONG;
    property LENGTH_SHORT: Integer read _GetLENGTH_SHORT;
  end;

  [JavaSignature('android/widget/Toast')]
  JToast = interface(JObject)
  ['{FC9B3DFD-38CC-4693-9F11-7F3E3647683F}']
    {Methods}
    procedure cancel; cdecl;
    function getDuration: Integer; cdecl;
    function getGravity: Integer; cdecl;
    function getHorizontalMargin: Single; cdecl;
    function getVerticalMargin: Single; cdecl;
    function getView: JView; cdecl;
    function getXOffset: Integer; cdecl;
    function getYOffset: Integer; cdecl;
    procedure setDuration(value: Integer); cdecl;
    procedure setGravity(gravity, xOffset, yOffset: Integer); cdecl;
    procedure setMargin(horizontalMargin, verticalMargin: Single); cdecl;
    procedure setText(s: JCharSequence); cdecl;
    procedure setView(view: JView); cdecl;
    procedure show; cdecl;
  end;
  TJToast = class(TJavaGenericImport<JToastClass, JToast>) end;
{$ENDIF}

implementation

end.


파이어몽키에서 Android API 사용하기 위해서는 JavaClass영역(JToastClass)과 JavaInterface영역(JToast)으로 구성 후 
실제 파이어몽키에서 사용할 수 있는 Class(TJToast)로 Generic형태로 Import해 사용합니다.
  • JToastClass - JavaClass interface
  • JToast - JavaInterface interface
  • TJToast - Delphi에서 사용할 Class

위와 같이 구성하기 위해서는 아래의 Unit들이 사용(uses)됩니다.
  • Androidapi.JNIBridge
  • Androidapi.JNI.JavaTypes
  • Androidapi.JNI.GraphicsContentViewText


안드로이드 API 컨버팅

델파이에서 구현할 부분은 크게 JavaClass와 JavaInterface입니다.

안드로이드 API문서를 보며 어느 부분을 JavaClass와 JavaInterface에 구현할지에 대해 알아보겠습니다.



위 그림의 붉은색 사각형에 포함된 내용이 JavaClass에 포함되고 나머지는 JavaInterface에 포함됩니다.


JavaClass 구현 할 항목

  JToast = interface;

  JToastClass = interface(JObjectClass)
  ['{F227353E-DCE9-404B-8129-6B1BEFE68151}']
    {Property methods}
    function _GetLENGTH_LONG: Integer; cdecl;
    function _GetLENGTH_SHORT: Integer; cdecl;
    {Methods}
    function init(context: JContext): JToast; cdecl; overload;
    function makeText(context: JContext; text: JCharSequence;
      duration: Integer): JToast; cdecl;
    {Properties}
    property LENGTH_LONG: Integer read _GetLENGTH_LONG;
    property LENGTH_SHORT: Integer read _GetLENGTH_SHORT;
  end;
  • Inherited Methods
    • JToastClass = interface(JObjectClass)와 같이 안드로이드 API에 기술된대로(java.lang.Object) interface를 상속받아 사용합니다.
  • Constants(상수)
    • 안드로이드 API 상수는 Properties로 구성되며 read 절에 _Get을 추가하여 선언됩니다.
    • 만약, END, BEGIN과 같은 상수는 &END, &BEGIN과 같이 &를 앞에 추가하여 구성됩니다.
    • Property methods에 _Get이 포함된 read 함수가 선언되며 호출규칙은 cdecl으로 지정합니다.
  • Public Constructors(생성자)
    • 생성자는 init();로 선언되며, 안드로이드의 인자를 그대로 선언해 줍니다.
      (JContext 등의 클래스는 이미 엠바카데로에서 선언(Androidapi.JNI.GraphicsContentViewText)해 놓았으니 매번 구현할 필요없이 잘 찾아서 사용하면 될것 같네요.)
    • 생성자도 cdecl로 호출규칙을 지정하고, Init는 JObjectClass에서 이미 구현되었으므로 overload로 method를 분개합니다.
    • JavaInterface를 반환합니다.(그래서 JToast = interface;를 미리 선언해야 합니다.)
  • Public Methods(Static)
    • Public Methods에 나열된 메소드 중에서 static으로 선언된 메소드들은 JavaClass에 선언해야 합니다.
    • 저는 static으로 선언된 메소드 중 2번째인 CharSequence text가 2번째 인자로 들어간 메소드만 사용했습니다.
      (모든 메소드를 모두 구현해야 할 필요는 없습니다.)

JavaInterface 구현 할 항목

  [JavaSignature('android/widget/Toast')]
  JToast = interface(JObject)
  ['{FC9B3DFD-38CC-4693-9F11-7F3E3647683F}']
    {Methods}
    procedure cancel; cdecl;
    function getDuration: Integer; cdecl;
    function getGravity: Integer; cdecl;
    function getHorizontalMargin: Single; cdecl;
    function getVerticalMargin: Single; cdecl;
    function getView: JView; cdecl;
    function getXOffset: Integer; cdecl;
    function getYOffset: Integer; cdecl;
    procedure setDuration(value: Integer); cdecl;
    procedure setGravity(gravity, xOffset, yOffset: Integer); cdecl;
    procedure setMargin(horizontalMargin, verticalMargin: Single); cdecl;
    procedure setText(s: JCharSequence); cdecl;
    procedure setView(view: JView); cdecl;
    procedure show; cdecl;
  end;

  TJToast = class(TJavaGenericImport<JToastClass, JToast>) end;

  • class path
    • 아래와 같이 API문서의 상단에서 class path를 확인하고 JavaSignature를 구성합니다.
  • Inherited Methods
    • JavaInterface도 JObject를 상속받습니다.
  • Public methods
    • Public methods에서 static으로 선언된 항목을 제외하고 선언합니다.
    • 대부분의 자료형은 이미 Androidapi.JNI.JavaTypes에 선언되었으나 해당 Unit을 참고합니다.


마지막으로 JavaClass(JToastClass)와 JavaInterface(JToast)를 TJavaGernericImport 클래스를 이용해서 실제로 사용할 Delphi class를 선언할 수 있습니다.


사용법 및 샘플코드

var
  Toast: JToast;
begin
  CallInUiThread(procedure
  begin
    Toast := TJToast.JavaClass.makeText(SharedActivityContext, StrToJCharSequence(AMsg), TJToast.JavaClass.LENGTH_SHORT);
    Toast.show;
  end);
end;


위의 코드가 Toast 메시지를 화면에 출력하는 샘플코드입니다.

안드로이드 가이드 문서를 참고해서 만들었습니다.


안드로이드 API를 구현한 후에는

TJToast.JavaClass이후에 JavaClass에 선언된 메소드들을 호출하고 반환받은 객체에서 JavaInterface의 메소드를 사용할 수 있습니다.


그리고, CallInUiThread의 경우  UI와 관련된 경우 Thread 처리하지 않으면 화면이 얼어버리는 현상이 발생해서 추가했습니다.

(그냥 구현했더니 얼어버려서, 엠바카데로 소스를 참고했습니다.)


마치며

대부분의 안드로이드 API는 이미 엠바카데로에서 구현해 놓았습니다.

(C:\Program Files (x86)\Embarcadero\RAD Studio\12.0\source\rtl\android 참고: 설치 기본경로 기준)


다만, 안드로이드에 특화된 기능등은 구현되지 않은 것이 있을 것입니다.

그럴경우 위에서 설명한 내용 참고하시면 충분히 포팅하여 사용할 수 있을것 같습니다.

(제 글이 도움이 되었으면 좋겠네요. 만약 어려운 부분이 있으시면 답글 주세요. 함께 고민해 보겠습니다.)


그럼 다음에는 iOS library 사용법이나 NDK 등의 글로 찾아뵙겠습니다.

감사합니다.



델파이 10.2 도쿄 버전에서는 아래 코드를 사용하면 됩니다.

JToast 인터페이스는 공식적으로 Androidapi.JNI.Widget 유닛에 선언되었습니다.

implementation

uses
  Androidapi.Helpers,
  Androidapi.JNI.Widget;

{$R *.fmx}

procedure ToastMessage(const AValue: string);
var
  Toast: JToast;
begin
  Toast := TJToast.JavaClass.makeText(SharedActivityContext, StrToJCharSequence(AValue), TJToast.JavaClass.LENGTH_SHORT);
  Toast.show;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ToastMessage('test');
end;