Making the Connection: Programming Devices Gadgets with RAD Studio

2014.02.13 11:23

David I와 Jim McKeeth가 진행하는 웹세미나 동영상입니다.

RAD Studio에서 외부 장비들과 연결하는 방법에 대해 소개합니다.


아래와 같은 다양한 장비와 연결하는 내용을 확인 할 수 있습니다.

저는 개인적으로 아두이노와 연결하는 방법이 궁금한데 도움이 될 것 같아 좋네요^^

  • Google Glass
  • IP Camera and IO Controller
  • Ballistic Chronograph
  • Leap Motion 3D input
  • Z-Wave Home Automation
  • Barcode scanning
  • Emotiv EPOC brain computer interface
  • Philips Hue Wireless LEDs
  • Ouya
  • Kinect
  • And more!


http://youtu.be/fdxDj-r8gU0


자료는 

http://cc.embarcadero.com/item/29699?cid=701G0000000t41S&elq=9a929d2384c04cccbc1bab27527282c8&elqCampaignId=

저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

험프리.김현수 험프리.김현수 RAD Studio 정보 Barcode scanning, Device, Firemonkey, Google Glass, Kinect, Rad Studio, Z-Wave, 장치연동

안드로이드에서 ComPort에 접근할 수 있는 파이어몽키 컴포넌트

2014.02.12 13:19


WinSoft에서 안드로이드로 ComPort를 이용할 수 있는 파이어몽키 컴포넌트를 제공합니다.

물론 안드로이드 라이브러리를 Import해서 구현할 수도 있지만, 델파이로 만든 컴포넌트가 활용성이 좋을 것 같네요.

아래의 코드는 해당 컴포넌트를 사용하는 샘플코드입니다.

아래의 링크를 타고 가시면 트라이얼 버전을 다운로드 할 수 있으니, 테스트해보시고 원하시는 앱을 만드셨으면 합니다.

procedure TFormMain.MemoKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
  AComPort.WriteByte(Ord(KeyChar));
end;

procedure TFormMain.TimerTimer(Sender: TObject);
var Text: string;
begin
  Text := AComPort.ReadUtf8;
  if Text <> ” then
    Memo.Text := Memo.Text + Text;
end;


자세한 내용은 아래에서

http://www.fmxexpress.com/access-the-com-port-on-android-with-delphi-xe5-firemonkey-component/


컴포넌트는 아래이 링크에서

http://www.winsoft.sk/acomport.htm


확인하실 수 있습니다.

저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

험프리.김현수 험프리.김현수 파이어몽키 android, ComPort, Delphi, Firemonkey, WinSoft

  1. Blog Icon
    영원한초보

    데모 프로그램을 보면 Devices에서 하나를 골라야 하는데 어떤 디바이스를 골라야 하나요? OPEN 버튼을 클릭하면 대부분 권한이 없거나 그런 파일이나 디렉토리가 없다고 메시지가 나오네요. 다른 설정할 곳이 필요한가요?

  2. 저도 소개차원에서 남긴 글이어서 자세한 테스트를 진행해 보지 못했습니다. 해당 제공사 사이트에서 질문하시면 답변 얻으실 수 있겠습니다.

모바일개발 심화

2014.02.06 01:07



안녕하세요. 험프리 김현수입니다.


이글에는 안드로이드와 iOS 개발 시 참고 할만한 글들을 모으려 합니다.

따라가기 형태가 아니며, 내용을 훑어 보시고 필요한 정보는 방문해서 지식을 얻으셨으면 좋겠습니다.


(계속 작성 중입니다. 좋은 정보 있으면 댓글로 알려주세요.)


공통기능

    Android 특화기능

    ▶ Android API 접근

    iOS 특화기능

    ▶ 외부 서비스 연동

    참고정보

    ▶ 공개 소스

    추가자료


    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 android, Firemonkey, ios, Rad Studio, 네이티브개발, 델파이, 멀티플랫폼, 안드로이드, 파이어몽키

    1. 필요한 정보 남겨주시면 찾아서 추가하겠습니다. 조회 수는 많은데 의견이 너무 없네요^^ 많이 남겨 주세요.

    2. Blog Icon
      반벽이

      델파이로 안드로이드 어플개발에 필요한 정보가 많이 있어서 감사한 마음으로 보고 있습니다
      선리플 후 의견 더 달아볼께요~^^ 감사합니다.

    3. 도움이 되셨다니 너무 좋습니다. 앞으로도 꾸준한 정보 기대하세요^^

    파이어몽키에서 안드로이드 외부 라이브러리(jar 파일) 이용(Import jar)

    2014.02.05 18:20

     안녕하세요. 험프리 김현수 입니다. 그간 많은 분들이 질문주셨던 내용인데요. 이제야 정리되어 소개해 드립니다.


     안드로이드에서 외부라이브러리 사용하려면 so, jar 파일을이용하는 2가지 방법이 있습니다. 이번에 소개할 내용은 jar 파일을 이용해 외부 라이브러리를 활용하는 내용입니다.

     간단하게 소개를 먼저하면, 필요한 jar 파일을 포함한 classes.dex 파일을 생성 후 배포 시 앞에서 생성한 classes.dex 파일을 배포하여 소스상에서 jar파일에 포함된 자바클래스를 활용하는 방식입니다.


    아래의 순서대로 진행되어야 하며 순서에 맞춰 설명하겠습니다.


    1. 사용자 classes.dex 파일 생성
      • APK 구조와 jar 파일의 위치
      • java 소스파일 또는 jar 파일 준비
      • 빌드
        • (옵션) java 소스파일 컴파일
        • jar 파일 생성
        • jar 파일을 dex 파일로 변환
        • dex 파일 병합
    2. 배포파일 관리
    3. Java Interface 파일 생성
    4. 구현 및 확인

    프로젝트 구성

    • JarBridge
      • [Java]
        • [output] - 빌드 시 자동생성
          • [dex] classes.dex - 빌드 후 생성
        • [src] kr\co\devgear\test\Foo.java
        • build.bat
      • JarBridgeDemo.dpr 등 - 프로젝트 및 폼 파일
      • JavaFoo.pas -Java Interface 정의 유닛

    사용자 classes.dex 파일 생성

    ▶ APK 구조와 jar파일의 위치

    apk 파일을 압축유틸리티로 열면 위와 같은 구조로 되어 있습니다. 그 중 jar 파일을 포함할 파일은 classes.dex 파일입니다. 여러분의 jar 파일은 아래의 빌드단계를 거처 classes.dex 파일로 변환됩니다.


    dex 파일이란?

    더보기

    ▶ Java 소스파일(또는 jar 파일) 준비

     저는 인터페이스 테스트를 위해 아래의 자바코드를 간단하게 작성했습니다. (워낙 간단하니 따로 설명드리지 않겠습니다.)

     해당 자바코드는 아래의 빌드 단계에서 jar파일을 생성합니다. 만약, 다른 jar 파일을 이용할 경우 아래의 코드는 작성하지 않아도 됩니다.

    package kr.co.devgear.test;
    
    import android.app.Activity;
    import android.widget.Toast;
    
    public class Foo
    {
        public void printMsg(final Activity activity)
        {
             activity.runOnUiThread(new Runnable()
             {
                   @Override
                    public void run()
                    {
                        Toast.makeText(activity.getApplicationContext(), "Hello world from a Java .jar library", Toast.LENGTH_SHORT).show();
                    }
             });
        }
    
        public int getInteger(){
            return 99;
        }
    
        public String getString(){
            return "Foo string";
        }
    }


    ▶ 빌드

     준비된 자바 소스파일을 jar로 만들어 새로운 classes.dex에 포함하는 작업을 위해 아래의 배치파일을 사용합니다. (빌드파일은 Brian long(http://blog.blong.com)이 공개한 빌드파일을 참고해서 수정 되었습니다. 많은 도움이 되었습니다.)


    빌드파일은 아래의 내용을 진행합니다.

    1. Compiling the Java source file - 자바소스를 컴파일
    2. Creating jar containing the new classes - jar 파일을 만들고
    3. Converting from jar to dex - jar 파일을 dex 파일로 변환 후
    4. Merging dex files - 3에서 생성된 dex 파일을 Embarcadero의 dex파일과 병합
    만약, 보유한 jar파일을 이용하는 경우 3, 4 단계만 진행하도록 배치파일을 수정 후 사용바랍니다.

    @echo off
    
    setlocal
    
    if x%ANDROID% == x set ANDROID="C:\Users\Public\Documents\RAD Studio\12.0\PlatformSDKs\adt-bundle-windows-x86-20130522\sdk"
    
    set SRC_PATH=src\kr\co\devgear\test\Foo.java
    set LAST_DOMAIN=kr
    set ANDROID_PLATFORM=%ANDROID%\platforms\android-17
    set DX_PATH=%ANDROID%\build-tools\android-4.2.2
    set DX_LIB=%DX_PATH%\lib
    set EMBO_DEX="C:\Program Files (x86)\Embarcadero\RAD Studio\12.0\lib\android\debug\classes.dex"
    set PROJ_DIR=%CD%
    set VERBOSE=0
    
    echo.
    echo Compiling the Java source file
    echo.
    mkdir output\classes 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose
    javac %VERBOSE_FLAG% -Xlint:all -classpath %ANDROID_PLATFORM%\android.jar -d output\classes -source 1.6 -target 1.6 %SRC_PATH%
    
    
    echo.
    echo Creating jar containing the new classes
    echo.
    mkdir output\jar 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=v
    jar c%VERBOSE_FLAG%f output\jar\test_classes.jar -C output\classes %LAST_DOMAIN%
    
    
    echo.
    echo Converting from jar to dex...
    echo.
    mkdir output\dex 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=--verbose
    call %DX_PATH%\dx --dex %VERBOSE_FLAG% --output=%PROJ_DIR%\output\dex\test_classes.dex --positions=lines %PROJ_DIR%\output\jar\test_classes.jar
    
    echo.
    echo Merging dex files
    echo.
    java -cp %DX_LIB%\dx.jar com.android.dx.merge.DexMerger  %PROJ_DIR%\output\dex\classes.dex %PROJ_DIR%\output\dex\test_classes.dex %EMBO_DEX%
    
    echo Tidying up
    echo.
    del output\dex\test_classes.dex
    del output\jar\test_classes.jar
    rmdir output\jar
    
    echo.
    echo Now we have the end result, which is output\dex\classes.dex
    
    :Exit
    
    pause
    
    endlocal

    배치파일의 경로는 RAD Studio XE5를 기준으로 설정되어 있어, 기본 경로로 설치하셨을 경우 아래의 2가지 변수외에는 그대로 사용하실 수 있습니다.

    • SRC_PATH : java 소스파일의 상대경로로 수정
    • LAST_DOMAIN : 도멘인의 마지막을 입력(e.g. kr, com, net 등)


    위의 배치파일을 실행하면 output\dex\classes.dex 파일이 생성됩니다. 아래의 배포파일 관리에서 해당 파일이 사용됩니다.

    배포파일 관리

    안드로이드 모바일 프로젝트를 생성하면 배포파일 목록에 엠바카데로에서 제공하는 classes.dex이 등록되는데, 우리는 jar파일이 포함된 classes.dex를 배포해야 합니다.



    위의 그림과 같이 기본 지정된 classes.dex파일을 선택해제 하시고, Add files 버튼을 이용해 위에서 만든 classes.dex 파일을 추가하고 아래와 같이 속성을 변경합니다.

    classes.dex

    • Platform : Android
    • Remote Path : classes\

    Java Interface 파일생성

    위의 자바파일(Foo.java)을 참고해 아래의 JavaFoo 유닛을 만들었습니다.

    자바파일 구조

    • package kr.co.devgear.test;
    • public class Foo
      • public void printMsg(final Activity activity)
      • public int getInteger()
      • public String getString()


    unit JavaFoo;
    
    interface
    
    uses
      Androidapi.JNIBridge,
      Androidapi.JNI.JavaTypes,
      Androidapi.JNI.APP;
    
    type
      JFoo = interface;
    
      JFooClass = interface(JObjectClass)
       ['{94F03A5A-B62B-401E-BE8D-2A96B77FA542}']
       function init: JFoo;
      end;
    
      [JavaSignature('kr/co/devgear/test/Foo')]
      JFoo = interface(JObject)
        ['{66CA87AA-1A6B-4039-A4E0-EB771BC2F4A5}']
        procedure printMsg(const AActivyty: JActivity);
        function getInteger: Integer; cdecl;
        function getString: JString; cdecl;
      end;
    
      TJFoo = class(TJavaGenericImport<JFooClass, JFoo>) end;
    
    implementation
    
    end.

    위의 과정이 어렵다면 Android2DelphiImport tool(유료: 0.25 bitcoin)을 이용할 수 있습니다.

    위의 링크의 설명은 어떤 jar파일도 pas파일로 변환해준다는 내용이 있습니다.
    (비트코인으로 결재를 하네요^^)


    파이어몽키 - 안드로이드 SDK 전체 랩핑(Wrapping) 파일

    • http://blog.hjf.pe.kr/185

    구현 및 확인

    아래와 같이 JavaFoo 파일을 uses에 넣고 버튼을 누르면 JFoo 생성 후 자바 메소드를 호출하면 응답을 받을 수 있습니다.

    uses
      JavaFoo,
      Androidapi.JNI.JavaTypes,
      FMX.Helpers.Android;
    
    {$R *.fmx}
    
    procedure TForm1.Button2Click(Sender: TObject);
    var
      Foo: JFoo;
    begin
      Foo := TJFoo.JavaClass.init;
    
      Edit1.Text := IntToStr(Foo.getInteger);
      Edit2.Text := JStringToString(Foo.getString);
    
      Foo.printMsg(SharedActivity);
    end;

    아래는 넥서스 7에서 실행한 화면입니다.


    참고



    관련 글


    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 Firemonkey, Import jar, java library import

    1. Blog Icon
      김동익

      JavaFoo unit에 있는 두 개의 인터페이스 ID값은 어떻게 생성이 된 건가요? 생성규칙이 있는 건가요?

    2. 임의의 GUID 값을 넣은것이구요.
      델파이 상에서는 Ctrl + Shift + G를 누르면 임의의 GUID 값을 생성 할 수 있습니다.

    3. Blog Icon
      차칸

      안녕하세요. xe5에서 jar파일을 쓰는법을 검색하다가 여기까지 왔는데요. 질문해도 괜찬나요?
      글대로 따라해서 작동은 됬는데 기존에 가지고있는 jar파일에서 변수타입이 hashtable<string,string> 일경우
      xe5에서 인터페이스에 함수를 만들때 어떻게 해줘야하나요?
      예를들면 java함수 String이면 xe5에서는 JString으로 가능한데 hashtable은 검색하다 해결방법을 못찾아서 문의드립니다.

    4. API를 사용하실 경우 반드시 모든 것을 안드로이드 샘플과 똑같이 하실 필요는 없습니다. 자바클래스 선언만 델파이로 컨버팅 하신 후에 HashTable같은 목록은 델파이의 Collection을 사용하셔도 좋구요 전통적인 TList를 사용하셔도 됩니다.(http://docwiki.embarcadero.com/CodeExamples/XE5/en/Generics_Collections_TList_(Delphi))

      꼭 HashTable을 사용하셔야 한다면, HashTable을 먼저 컨버팅하시고 그 컨버팅한 객체를 사용하실 수 있습니다.(http://developer.android.com/reference/java/util/Hashtable.html)

      JString 등은 이미 델파이에서 컨버팅한 자료형입니다.

    5. Blog Icon
      차돌이

      좋은 자료 감사합니다. 위의 자료를 참고하여 classes.dex 파일을 수정한후 Deployment 에서 변경된 파일로 변경후 실제 안드로이드 폰에 올릴경우 아래와 같은 에러메시지가 발생합니다. 혹시 관련해서 아시는 방법이 있으신가요? install_failed_uid_changed

    6. 정확한 답변은 아니겠지만 의심가는것이 있어 답변 드려봅니다.

      혹시 다른 버전의 델파이에서 동일한 프로젝트 명으로 배포된 apk가 있지 않으신가요?
      (혹시 모르니)프로젝트 명 변경 후 시도해 보세요.

      또는 JFooClass, JFoo의 GUID(['{94F03A5A-B62B-401E-BE8D-2A96B77FA542}'])를 재 생성(Ctrl + Alt + G) 해서 시도해 보세요.

    7. Blog Icon
      차돌이

      일단은 프로젝트 명을 변경하여 디바이스에 올라가는것을 확인하였습니다. 감사합니다.

    8. Blog Icon
      홍박

      먼저 좋은자료 ㄳ드립니다.
      "배포파일 관리 " 메뉴는 어디에 있는가요? 아무리찾아도 안보이는군요 사용 IDE 는 XE5 입니다. 답변ㄳ드립니다.

    9. Project > Deployment 메뉴를 선택하시면 됩니다.

    10. Blog Icon
      홍박

      ㄳ합니다~ ^^

    11. Blog Icon
      홍박

      작업하다가 궁금한점이 있어서 질문드립니다.
      PROGRAMFILES~ Embarcadero\RAD Studio\12.0\lib\android\debug\classes.dex 이 경로에 있는 파일이
      완전히 새로운파일로 교체되는것인가요?
      . 혹시 교체가 된다면 다음부터 1,2,3,4 과정없이 선언만으로 다른프로젝트에 사용 가능한것인지?
      알고싶습니다 무더위가 기승을 부리네요 수고하세요~

    12. 결과적으로 배포되는 classes.dex 파일은 엠바카데로에서 기본으로 제공하는 classes.dex를 포함하도록 배치파일에서 구성됩니다.

      만약 동일한 외부 jar파일을 사용하실것이라면 동일한 classes.dex파일을 다양한 앱에서 사용해도 됩니다.

    13. Blog Icon
      홍박

      친절한 답변 감사합니다 다른경로에 xe 를 설치해서 배치파일을 그대로쓰면 설치된게 아작날까바 아직 실행은 못해봤습니다 아직 자바초보라 자바컴파일 하는것도 많이 어렵네요 자주 들러겠습니다 수고하세요

    14. 네. 감사합니다.
      다양한 시도해 보시고 문제가 되거나 공유할 만한 거리가 있으면
      댓글로 공유 부탁드려요^^

    15. Blog Icon
      나들이

      저어 도움을 부탁드립니다.
      예제를 따라 해보니 잘됩니다. 근데 이렇게 한 후 seattle 에서 안드로이드 서비스를 추가하려는데 잘되지가 않더군요. ㅜㅜ
      시애틀에 안드로이드 서비스를 추가하니까 class 가 세개가 자동으로 classas.dex에 들어가는 것 같은데 뭘 어떻게 해야할지 모르겠습니다. 한 수 부탁드립니다.

    안드로이드 테마를 이용한 Splash Window 구현

    2014.02.05 09:53

    RAD Studio XE7부터는 프로젝트 옵션에서 스플래쉬 이미지를 쉽게 변경할 수 있습니다.

    RAD Studio XE6 이전 버전에서 아래 내용을 참고하기 바랍니다.


    안녕하세요. 험프리 김현수입니다.


    델파이 모바일로 앱을 만들면, iOS에서는 스플래쉬 윈도우가 표시된 후 앱이 구동되지만 안드로이드의 경우 스플래쉬 윈도우가 없이 검은색 화면이 표시된 후 앱이 구동됩니다.

    델파이 모바일 개발의 경우 엔터프라이즈 개발에 주요 초점이 맞쳐져 있어, 쉬운개발과 빠른개발에 더 강점을 갖고 있어 큰 이슈가 되지는 않지만 B2C등의 개인 사용자에게 배포할 경우 때때로 눈에 거슬리기도 합니다.


    위의 이슈(검은 화면 이후 앱 구동)를 해결하기 위한 방법은 3가지 정도가 될 것 같습니다.


    1. 앱을 최대한 빨리 띄우고 시간이 걸리는 부분은 앱이 구동된 이후에 수행
    2. 안드로이드 테마를 이용해서 스플래쉬 윈도우 출력
    3. 자바코드로 스플래쉬 윈도우용 Activity(화면)을 구성


    위의 3가지 방법 중 제일 좋은 방법은 3번 항목입니다. 별도의 스플래쉬 윈도우를 자바코드로 작성하고, 구동 시점에 스플래쉬 윈도우 출력 후 앱을 구동하는 방법입니다.

    하지만, 3번 항목으로 구현하게 되면 자바코드를 작성 후 컴파일하고, 패키징하는 작업이 델파이만을 사용하시는 분들에게는 꽤 번거롭고 어려운 작업입니다. 

    (그리고, 스플래쉬 윈도우를 초기에 구동하게되면 델파이에서 앱의 진입점을 찾지 못해 디버깅 작업을 진행 할 수 없습니다.)


    위의 이유로 제일 간단하고 디버깅도 가능한 2번째 항목으로 스플래쉬 윈도우 구성하는 방법을 설명합니다.

    안드로이드 테마를 이용한다는 것은 기본 테마를 변경하는 것이므로, 구현 후 전체적인 구성을 반드시 확인해야 합니다. 

    파이어몽키의 경우 기본적으로 테마위에 컨트롤들이 올라가는 것이므로, 큰영향을 주지 않을 것으로 생각됩니다.


    혹시 테마를 이용할 경우 이슈가 있으면 댓글 부탁드립니다


    안드로이드 테마를 이용해 스플래쉬 윈도우를 구성하려면 아래의 순서를 진행하면 됩니다.


    1. 프로젝트 생성 및 디렉토리 구조
    2. 스플래쉬 이미지 준비
    3. Styles.xml 파일 준비 - 스플래쉬 윈도우를 xml로 구성합니다.
    4. AndroidManifast.template.xml 파일 수정
    5. 배포파일 등록


    프로젝트 생성 및 디렉토리 구조

    Firemonkey Mobile Application으로 새로운 프로젝트를 생성하고, 프로젝트를 지정된 경로에 저장합니다.(e.g. D:\Projects\SplashWindow)

    지정된 경로 하위에 res 디렉토리를 생성하고 아래의 단계를 거처 스플래쉬 이미지 파일과 styles.xml 파일을 생성합니다.

    • SplashWindowTheme
      • res
        • splash.png
        • styles.xml
      • 프로젝트 소스파일

    스플래쉬 이미지 준비

    스플래쉬 윈도우를 추가할 프로젝트를 생성하고 스플래쉬 윈도우에 표시할 이미지를 준비합니다. 확장자는 이미지 포맷인 경우 무관합니다.

    저는 아래와 같은 이미지(splash.png, 768 * 1024)로 준비했습니다.

    styles.xml 파일 준비

    splash.png, splash.jpg등으로 스플래쉬 이미지를 이용하실 경우 아래 파일을 그대로 사용해도 됩니다.

    
    
    • <style name="MyTheme.NoTitleBar.SplashWindow" parent="@android:Theme.Holo">
      • name은 아래의 AndroidManifast에서 android:theme에서 사용 할 style 명
      • parent는 상속받을 안드로이드의 테마를 입력합니다.
    • <item name="android:windowBackground">@drawable/splash</item>
      • 스플래쉬로 등록할 파일을 지정합니다.
      • 배포 시 [res/drawable] 경로에 splash.png 이미지 파일이 함께 배포되어야 합니다.

    AndroidManifast.template.xml 파일 수정


    프로젝트 파일을 저장한 경로를 보시면 AndroidManifast.template.xml 파일이 자동 생성됩니다.(만약, 파일이 없을 경우 Platform Target을 Android로 설정 후 컴파일 하면 생성됩니다.)

    해당파일을 RAD Studio에 추가하거나 텍스트 에디터 등으로 열고, 아래와 같이 android:theme를 수정합니다.

    (아래의 문구는 styles.xml의 style.name과 반드시 같아야 합니다.)

    기존 : android:theme="%theme%">

    변경 : android:theme="@style/MyTheme.NoTitleBar.SplashWindow">

    배포파일 등록


    준비한 스플래쉬 이미지와 styles.xml 파일을 앱과 함께 배포 합니다.


    Project > Deployment 메뉴를 통해 [] 화면을 표시하고 Add file 버튼을 이용해 res\ 경로에 있는 2개의 파일을 업로드 하고 아래와 같이 내용을 변경합니다.

    splash.png

    • Platform : Android
    • Remote Path : res\drawable\

    styles.xml

    • Platform : Android
    • Remote Path : res\values\


    컴파일을 하고 실행하면 아래와 같이 스플래쉬 윈도우가 실행되고, 메인화면이 표시되는 것을 확인 할 수 있습니다.


    http://www.youtube.com/watch?v=J2kXdGzzMzY


    참고



    소스파일



    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 android, Firemonkey, RAD Studiio Mobile

    1. Blog Icon
      오실장

      스타일 이용하는것 정말 간편하고 좋은 방법이군요..!!
      엠바카데로에서 델파이 컴파일러에 기본으로 제공해도 전혀 무리가 없어 보이는데 왜 이런 방법들을 개발자들이 찾아내야 하는지 하는 아쉬움이 있군요..
      이제라도 좋은 방법을 찾아 냈으니 다행입니다..수고 하셨습니다..ㅎㅎ

      참고로 샘플에서 알려주신 styles.xml 안의 <item name="android:windowFullscreen">true</item> 속성을
      TRUE로 하게 되면 실행되는 앱의 속성도 풀스크린으로 나오게 되므로
      상단 상태바가 사라지게 되는데 앱의 기본설정대로 상태바가 보여야 한다면
      false 로 해서 지정하고 스플래시 이미지를 띄워도 괜찮을것 같군요.
      (이부분은 개발되는 앱의 특성이니 보시는분들 참고하시라고 제가 댓글로 알려 드립니다..^^)

      안드로이드 테마도 parent="@android:Theme" 으로 지정하면
      테마 변경없이 적용 가능 합니다. (단말기에 따라 차이는 있을수 있습니다.)

      그리고 본문 내용중
      [변경 : android:theme="@style/MyThem.NoTitleBar.SplashWindow"]
      의 문구에 MyThem 'e' 가 빠졌네요...^^ 입력하기 구찮아서 복사해서 쓰니 에러나서 한참 들여다 봤습니다..ㅋㅋ

    2. 오실장님 의견 주셔서 감사합니다^^
      원래 안드로이드의 경우 기본으로 스플래쉬를 지원하지 않기때문에 엠바카데로에서 뺀것 같은데요. 앱의 덩치가 커지면서 구동이 늦어지는 이슈까지 고려하지 않은 것은 분명히 엠바의 실수 같아요. 다음 버전에 성능적인 향상도 기대해보고 있습니다^^

      e가 빠진건 수정했습니다.

    3. Blog Icon
      조봉기

      res를 프로젝트 생성폴더 밑에 두고 해당 이미지와 xml을 놓고 실행하면 해당 리소스 파일이 없다고 합니다. 도움을 좀 주실수 있나요?

    4. 배포파일 등록 시 이미지와 xml파일을 선택하시고 remote path를 설정하시면 됩니다. 리소스 파일이 없다는 것은 실행시 나오는 메시지 인가요?

    5. Blog Icon
      조봉기

      먼저 운영자님의 답변에 감사드립니다.
      제가 운영자님의 블로그에 있는데로 프로젝트 폴더에 res생성해서 해당 splash.png, styles.xml 을 가져다 놓고
      AndroidManifast.template.xml 수정해서 디버깅 하면

      [PAClient Error] Error:E2312 G:\project\splashtest\Android\Debug\splashtest\AndroidManifest.xml:21:error:Error:No resource found that matches the given name(at 'theme' with value '@style/MyTheme.NoTileBar.SplashWindow')

    6. 우선 원인은 @style/MyTheme.NoTitleBar.SplashWindow을 찾지 못하는 것 같습니다.
      위의 오류 메시지를 보면 TileBar로 "t"가 빠져있는데요. 그게 원인이 아닐까 예상합니다.^^

    7. Blog Icon
      조봉기

      해결했습니다. 재가 배포등록 전단계까지하고 디버깅을 해서 그랬습니다. 친절한 답변감사드립니다.

    8. 도움이 되셨다니 너무 기분이 좋습니다^^

    9. Blog Icon
      김영환

      좋은 정보 감사드립니다!!
      제가 만든 앱은 메인이 뜨는데 약 3초정도의 시간이 걸립니다. 그래서 스플래쉬가 뭔지 확인하기도 전에 지나가 버리면서 약 2초정도를 블랙화면에서 기다려야합니다. 스플래쉬 대기시간을 약2초정도로 조정할 수는 없는건가요? 감사^^

    10. 만약 안내해 주실 내용이 있다면, 메인화면 전에 안내화면을 2초 정도 띄우고 사라지는 방법이 좋을 것 같습니다.
      XX팡 등의 게임도 스플래쉬 이후에 업데이트 체크 등의 안내화면이 지나서 메인화면이 뜨는 방식을 참고하시면 좋겠네요^^

    11. Blog Icon
      아가머하노

      안녕하세요. 글을 보고 적용하다 보니 잘 안되어 글을 남깁니다.

      AndroidManifast.template.xml 파일에서 해당 styles.xml파일에 있는 name을 수정하고

      F9를 누르니 자꾸 AndroidManifast.template.xml파일을 다시 생성하여 넣어놓은 내용이 초기화가 됩니다.

      이 경우 어떻게 해야할까요? 조언 부탁드리겠습니다.

    12. 안드로이드 매니페스트 파일은 2종류가 있습니다.

      AndroidManifast.template.xml 파일과 AndroidManifast.xml 파일
      전자는 파일이 없을 경우 최초 생성이되고, 후자는 매번 컴파일시마다 생성됩니다.
      아마 두개의 파일을 혼돈하셨을 것 같은데요.
      프로젝트 파일이 저장된 경로를 다시 확인해보시기 바랍니다^^

    13. Blog Icon
      아가머하노

      아 제가 파일명을 잘못썼는데
      AndroidManifest.xml 파일이 계속 다시 생성됩니다.
      Deploy에서 있는 경로에 있는 파일에다가 썼는데도
      자꾸 초기화가 되네요..

    14. Blog Icon
      아가머하노

      하나 더 궁금한건

      XE5사용중인데...IndyFTP를 Android에 올리면 파일을 업로드 및 다운로드가 정상적으로 이뤄지지않고
      에러가 발생합니다. 동일한 소스를 Windows에서 할때는 잘되구요.
      구글링해보니 저와 비슷한경우의 사람을 발견했는데...아쉽게도 답변이 없네요..
      제가 잘못사용하고 있는건지...아니면 IndyFTP 컴포넌트에 버그가 있는건지...

      조언 좀 부탁드리겠습니다.

    15. Blog Icon
      아가머하노

      아 제가 착각했습니다. 감사합니다.^^

    16. Blog Icon
      삽질맨

      스플래시가 잠깐 나왔다가 사라져서..로딩시간이 좀 오래인경우,
      스플래시보여지는 화면의 시간을 길게 늘려서 조정할 수 있는 방법이 있을까요?

    17. 스플래쉬가 나왔다 사라진 것은 이미 앱이 로딩되었다는 의미입니다.
      이런 경우는 앱 실행시(Create, Show) 어떤한 작업을 하기 때문인 것으로 보이는데요.
      FormCreate나 FormShow에는 데이터를 불러오는 등의 오래걸리는 작업을 넣지 않는 것이 좋습니다.
      아래 링크를 참고해서 앱이 완전히 구동된 이후에 오래걸리는 작업을 처리하시면 해결되실것으로 보입니다.
      http://blog.hjf.pe.kr/207

    18. Blog Icon
      옹아

      위 소스로 돌려본 결화 스플래쉬는 잘 작동 됩니다. 스플래쉬가 나왔다 사라지면 앱이 로딩이 되었다고 하셨는데
      기존 앱에 버튼화면만 해서 돌리면 스플래쉬가 나왔다 사라지고 버튼 화면이 나오기 전 검은 화면이 1~2초 남아 있습니다.. 스플래쉬를 사용한 이유가 앱이 구동되기전 검은 화면을 안보이게 하는건데 1~2초 검은 화면은 안드로이드 테마로 스플래쉬 시간은 컨트롤 할수 없는건가요??

    19. Blog Icon
      dskim

      수고 많으십니다.

      스마트폰 델파이 책 1 권, 2 권 감사히 공부하고 있는 델파이 코딩 초보자입니다.

      메인 페이지 띄우기 전에 로고 화면 하나 또는 둘 연달아 띄우고 메인 화면으로 이동 했으면 하는데요

      상기와 같이 안드로이드 구현 한다고 하면,,

      해당 기능을 아이폰에는 동일하게 어떻게 구현 하면 될까요 ?.

      또한 상기 기능을

      "메인폼을 얼리지 않고(Idle 상태) 대기하기.(TStopWatch 활용)" 게시판 부분을 이용하여 구현하는 것도

      가능한 부분인지요 ??

      현재 델파이 코딩 생 초보자입니다.

      자세히 예를들어 설명해 주시면 대단히 감사 하겠습니다.

      오늘도 좋은 하루 되세요.....

    매주 금요일 제공되는 파이어몽키 스타일파일

    2014.01.28 09:41

    모바일과 데스크탑용 파이어몽키 스타일파일을 매주 금요일마다 제공한다는 아주 반가운 소식이 있어 전합니다.

    한주에 하나씩 공개를 하고, 현재 2가지의 스타일을 제공해 다운로드받을 수 있습니다.

    스크린샷을 보면 정말 멋지네요^^


    아래의 링크에서 매주 새로운 스타일을 만나보세요.

    http://blogs.embarcadero.com/tlaborde


    The Friday's Design #1




    http://blogs.embarcadero.com/tlaborde/2014/01/17/the-fridays-design-1-firemonkey-desktop-and-mobile-design-with-delphi-xe5/


    The Friday's Design #2



    http://blogs.embarcadero.com/tlaborde/2014/01/24/the-fridays-design-2-firemonkey-desktop-design-with-delphi-xe5/



    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 Firemonkey, Friday's design, style

    파이어몽키 모바일(iOS, Android)에서 사용자 파일 배포 및 사용

    2013.12.27 11:15

    사진 및 스타일파일등을 앱에 포함해서 배포할 일이 있습니다.

    iOS와 안드로이드에서 사용자의 파일을 배포하고 사용하는 방법입니다.


    우선 배포할 파일을 준비합니다.

    배포파일 추가는 IDE 메인메뉴에서 Project > Deployment 메뉴를 통해 할 수 있습니다.



    위의 Add files 버튼을 누르고 열기대화상자에서 배포할 파일을 선택합니다. 파일이 추가되면 목록에서 추가한 파일을 선택하고

    아래와 같이 플랫폼을 iOS와 Android로 선택하고 Remote Path를 변경합니다.



    iOS 배포파일 추가

    Platform - [iOSDevice, iOSSimulator]

    Remote Path - StartUp\Documents


    Android 배포파일 추가

    Platform - [Android]

    Remote Path - assets\internal


    배포파일을 코드에서 사용하려면 아래와 같은 코드로 가능합니다.


    uses
      System.IOUtils;
    
    procedure TForm3.Button1Click(Sender: TObject);
    begin
      Image1.Bitmap.LoadFromFile(TPath.Combine(TPath.GetDocumentsPath, 'Koala.jpg'));
    end;


    관련글



    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 Deployment, Firemonkey, 파이어몽키

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

    2013.12.16 14:28
    안드로이드 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 등의 글로 찾아뵙겠습니다.

    감사합니다.

    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 android api, Android to firemonkey, Firemonkey, JNI, toast

    1. 좋아요!! 많이 눌러주세요^^

    2. Blog Icon
      GHat

      안녕하세요 델파이 공부중인 한 학생입니다..
      델파이에서 안드로이드의 nfc 기능을 사용하려니 컴포넌트도없고...
      어떻게해야할지 막막합니다ㅠㅠ
      toast메세지 구현한것처럼 AndroidAPI 를 직접 가져다가 컨버팅해야할것같은데.. 어떻게해야할까요?

    3. 반갑네요^^ 델파이를 공부하신다고 하니...
      NFC 개발이 필요하다면 우선 NFC에 대한 정보를 먼저 익히시고 관련 샘플을 델파이로 컨버팅하며 익혀야 합니다.

    4. Blog Icon
      김주일

      안녕하세요 ?
      델파이는 잘 모르고 C 빌더를 사용하고 있는 사람 입니다.

      다른건 모두 이해가 가는데
      ['{F227353E-DCE9-404B-8129-6B1BEFE68151}'] 와
      ['{FC9B3DFD-38CC-4693-9F11-7F3E3647683F}'] 는

      어떻게 정해지는지 모르겠습니다 ?
      그리고 C Builder 로도 API 인터페이스가 가능한가요 ?


    5. 해당 문자열은 GUID이며 Ctrl + Alt + G를 누르면 세상에서 유일한 ID를 생성하고 사용할 수 있습니다.
      API 인터페이스 처리하는 부분은 C++빌더로도 가능합니다.
      (하지만 방법은 좀더 찾아보셔야 겠네요^^)

    6. 보고 따라했는데도 안되어서 파일을 그대로 가져다가 프로젝트에 올리고 uses절에서 호출하고.. 실행문 가져다가 했는데 빨간줄이 나옵니다..
      실행방법 알고 싶습니다..

      CallInUiThread
      SharedActivityContext
      StrToJCharSequence

      어디에 정의되있는건가요..?

    Firemonkey에서 Android Toast Message 사용하기

    2013.12.15 23:54

    Android API를 Firemonkey에서 사용하는 방법을 설명하기 위해 

    Toast Message를 사용하는 방법을 샘플로 만들어 봤습니다.

    (다음 글에서는 컨버팅하는 방법을 설명하겠습니다.)


    아래의 화면과 같이 위치를 지정해서 토스트메시지를 출력하면 Lock걸지 않는 메시지가 나왔다가 사라집니다.

    (아래의 샘플은 100% Firemonkey(delphi)로 만들어 졌습니다.)



    혹시 확인해 보고 싶으신 분은 아래 APK 다운로드 해보세요.^^(당연히 iOS에서는 동작하지 않습니다.)



    토스트 메시지는 아래의 문서를 참고해서 컨버팅 했구요.

    http://developer.android.com/reference/android/widget/Toast.html


    토스트 메시지 위치를 지정하기 위해 아래의 문서도 컨버팅 했습니다.(그냥 상수처리해도 될걸 그랬는데요. 내주말 ㅠㅜ)

    http://developer.android.com/reference/android/view/Gravity.html


    관련된 소스는 아래의 Github사이트를 참고해주세요.(Follow 해주시면 감사하구요^^)

    https://github.com/hjfactory/FMX.Devgear/tree/master/Samples/Android_Toast


    대략 소스는 아래와 같습니다.



    다음 글에서는 안드로이 API를 파이어콩키에서 사용하는 자세한 방법을 설명해 보겠습니다.

    감사합니다.

    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 android, Converte android to firemonkey, Firemonkey, FMX, toast, Toast Message

    Image URL로 TImage에 이미지 로드

    2013.12.13 00:37

    웹에 있는 이미지를 표시해야 할 것 같아 간단하게 라이브러리 형태로 만들었어요.

    TBitmap을 class helper로 확장했습니다.

    소스가 몇 줄 되지 않으니 설명은 생략합니다.


    iOS(아이폰5), Android(Nexus 7), 윈도우(Windows 7)에서 모두 정상 동작 확인했습니다.


    참고하세요^^







    사용법


    procedure TForm3.Button1Click(Sender: TObject);
    var
      Size: Int64;
    begin
      Image1.Bitmap.LoadFromUrl('http://cfile2.uf.tistory.com/image/2353573E529FDAAC032731', Size);
    
      Memo1.Lines.Add('1 : ' + Format('W: %d, H: %d, S: %d', [Image1.Bitmap.Width, Image1.Bitmap.Height, Size]))
    end;
    
    procedure TForm3.Button2Click(Sender: TObject);
    begin
      Image1.Bitmap.LoadFromUrl('http://cfile2.uf.tistory.com/image/2353573E529FDAAC032731');
    
      Memo1.Lines.Add('2 : ' + Format('W: %d, H: %d', [Image1.Bitmap.Width, Image1.Bitmap.Height]))
    end;
    
    procedure TForm3.Button3Click(Sender: TObject);
    begin
      Image1.Bitmap.LoadThumbnailFromURL('http://cfile2.uf.tistory.com/image/2353573E529FDAAC032731', 100, 100);
    
      Memo1.Lines.Add('3 : ' + Format('W: %d, H: %d', [Image1.Bitmap.Width, Image1.Bitmap.Height]))
    end;


    쓰레드로 처리하도록 변경해 사용법의 첫번째 사이즈 정보를 얻어오는 부분은 제외됩니다.

    (깃허브의 소스코드를 참고하세요. https://github.com/hjfactory/FMX.Devgear)

    구현부

    unit FMX.Devgear.HelperClass;
    
    interface
    
    uses
      System.Classes, FMX.Graphics;
    
    type
      TBitmapHelper = class helper for TBitmap
      public
        procedure LoadFromUrl(AUrl: string);
    
        procedure LoadThumbnailFromUrl(AUrl: string; const AFitWidth, AFitHeight: Integer);
      end;
    
    implementation
    
    uses
      System.SysUtils, System.Types, IdHttp, IdTCPClient, AnonThread;
    
    procedure TBitmapHelper.LoadFromUrl(AUrl: string);
    var
      _Thread: TAnonymousThread;
    begin
      _Thread := TAnonymousThread.Create(
        function: TMemoryStream
        var
          Http: TIdHttp;
        begin
          Result := TMemoryStream.Create;
          Http := TIdHttp.Create(nil);
          try
            try
              Http.Get(AUrl, Result);
            except
              Result.Free;
            end;
          finally
            Http.Free;
          end;
        end,
        procedure(AResult: TMemoryStream)
        begin
          if AResult.Size > 0 then
            LoadFromStream(AResult);
          AResult.Free;
        end,
        procedure(AException: Exception)
        begin
        end
      );
    end;
    
    procedure TBitmapHelper.LoadThumbnailFromUrl(AUrl: string; const AFitWidth,
      AFitHeight: Integer);
    var
      Bitmap: TBitmap;
      scale: Single;
    begin
      LoadFromUrl(AUrl);
      scale := RectF(0, 0, Width, Height).Fit(RectF(0, 0, AFitWidth, AFitHeight));
      Bitmap := CreateThumbnail(Round(Width / scale), Round(Height / scale));
      try
        Assign(Bitmap);
      finally
        Bitmap.Free;
      end;
    end;
    
    end.


    안드로이드 환경에서 8bit GIF 이미지가 표시되지 않는경우

    아래와 같이 FMX.Graphics.Android.pas 파일을 수정하세요. 결과적으로 IsGIFStream 메소드에서 GIF 여부를 파악하는 부분이 잘못되어 있어 8bit GIF 표시에 문제가 있습니다.

    class function TBitmapCodecAndroid.IsGIFStream(const Stream: TStream): Boolean;
    const
      IDCharCount = 3;
    type
      GIFByteArray = array[0..IDCharCount-1] of Byte;
    const
      GifBytes: GIFByteArray = ($47, $49, $46); // G I F
    var
      I: Integer;
      PrevPosition: Int64;
      ReadBytes: GIFByteArray;
    begin
      if (Stream = nil) or (Stream.Size < IDCharCount) then
        Exit(False);
    
      Result := True;
      PrevPosition := Stream.Position;
      try
        Stream.ReadBuffer(ReadBytes, IDCharCount);
        for I := Low(ReadBytes) to High(ReadBytes) do
          if ReadBytes[I] <> GifBytes[I] then
            Exit(False);
      finally
        Stream.Position := PrevPosition;
      end;
    end;

    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 class helper, Firemonkey, Image url, TImage

    1. Blog Icon
      epilogs

      빌드해보니 아래와 같은 오류가 발생하네요.
      뭔가 설치를 추가로 해야하나보군요..^^

      [dcc32 Fatal Error] Unit3.pas(27): F1026 File not found: 'C:\Users\홍길동\Downloads\BitmapUrl\FMX.Devgear.Extentsions.dcu'

    2. 폼의 유닛에서 uses에서 오타가 있었습니다.
      다시 올렸구요. uses 절에 FMX.Devgear.Extensions;로 변경하시면 됩니다^^

    3. Blog Icon
      8비트24비트

      BitmapUrlDemo 소스로 테스트해본 결과

      안드로이드 환경에서는 가져오는 이미지가 8비트 형식일때 그림이 제대로 불러와지지 않네요
      ex) http://img.naver.net/static/www/u/2013/0731/nmms_224940510.gif

      24비트(jpeg)는 잘 보여지구요. (예제로 쓰인 그림도 이 경우더군요)

      윈도우에서는 잘만되니 모바일에서는 무언가 더 설정이 필요한건가요??

    4. 본문 하단의 내용을 참고하세요.

    Delphi XE5 and RAD Studio XE5 Android and iOS Code Samples

    2013.12.12 01:16

    안드로이와 iOS(아이폰)을 하나의 코드로 개발하는 RAD Studio XE5 모바일 샘플코드입니다.



    http://www.embarcadero.com/products/delphi/android-ios-code-samples-xe5


    다양한 샘플코드 및 구현영상(1분 내외)을 보실 수 있어요^^


    Device Sensors
    Accelerometer
    Gyroscope
    Location
    OrientationSensor
    Device Services
    DeviceInfo
    MessageAlerts
    Notifications (Send/Cancel)
    Notifications
      (Set Badge Number)

    PhoneDialer
    ShareSheet
    Touch/Gestures
    InteractiveGestures
    TabSliding

    Database Storage
    IBLite
    SQLite



    Native Controls
    CustomPicker
    DatePicker
    HorizontalScroll
    Media
    AccessCameraApp
    CameraComponent
    CameraRoll
    AudioRecPlay
    WebBrowser
    PlayAudioFile


    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 Firemonkey, XE5

    StyleBook Resources Text Editor 패치

    2013.12.05 13:32
    파이어몽키 스타일을 사용하면 매우 풍부하고 있어 보이게(?) 프로그램을 표현 할 수 있습니다.
    스타일 수정 시 약간의 편리한 기능의 패치가 있어 소개합니다.

    StyleBook Resources Text Editor

    내용 : Style designer로만 편집 가능했던 Resource를 Text Editor에서 수정 가능
    대상 : Delphi XE4 이상
    패치방법 : 
     1) 아래 링크에서 다운로드
     2) 다운받은 *.bpl파일을 특정 위치(라이브러리 등)로 이동
     3) Components > Install Package > Add > 위의 *.bpl 선택

    아래와 같이 Resource Property가 (Resource) > (TStrings)로 바뀌고 (TStrings) 더블클릭 시 String List Editor 윈도우가 호출 됩니다.(기존 (Resource) 더블 클릭 시 Style designer가 표시되었습니다.)
    패치 후 StyleBook 아이콘을 더블 클릭하면 Style designer로 넘어갈 수 있습니다.
    패치 이후 StyleBook Resource


    저작자 표시 비영리 동일 조건 변경 허락
    신고
    크리에이티브 커먼즈 라이선스
    Creative Commons License

    험프리.김현수 험프리.김현수 파이어몽키 Firemonkey, StyleBook

    [후기] RAD Studio XE3.5 - Delphi for iOS

    2013.03.08 13:04

    3월 8일 데브기어가 주관하는 델파이 세미나가 진행되었습니다.


    주요 주제는 Delphi for iOS(with Firemonkey)였습니다.


    Firemonkey란?


    하나의 델파이(또는 C++) 소스로 Win32, Win64, OSX(MacOS), iOS, Android(준비 중)에서 실행 가능한 어플리케이션을 개발 할 수 있는 Native Compiler 프레임웍입니다.


    세미나 내용이 궁금하신 분들이 계실 것 같아 기록합니다.

    개인적으로 생각나는 부분만 적으니 내용이 다소 다를 수도 있습니다.


    발표자는

    옆집 아저씨같은 푸근한 인상의 고든 리(Gordon Li)님이 진행하셨구요.

    고드 리는 엠바카데로 중국, 대만, 아세안 지역의 수석 에반젤리스트로 활동 중이라고 합니다.



    여러 주제의 세션이 있었지만 시간에 얽매이지 않고 흐름에 맞게 진행되어 괜찮았지요.


    생각나는 내용만 간단하게 적어보겠습니다.




    | 첫번째 주제는 "멀티 디바이스"


    • 태블릿과 노트북 중 태블릿 비율이 50%를 넘어가는 시기(2013년)
    • 전문가들은 2012년 초에는 2016년으로 예상, 2012년 중후반에는 2015년으로 예상
    • 하지만 2013년 1월에는 올해(2013년)이 50%이상을 태블릿이 점유할 것으로 예상

    • 향후 새로운 스마트 기기(iWatch, Start TV..)가 빠른 속도로 추가됨이 예상
    • 다른 언어와 다르게 파이어몽키는 
      One Source, Multi platform, Multi device 개발 가능
    • 네이티브 개발 만이 사용자의 빠른 반응 속도로 좋은 UX 제공 가능

    • 현재 Mobile Studio는 Beta 테스트 중 (XE3.5 Beta 9)
    • 올 하반기 XE4 발표 예상
    • Android 버전은 개발완료 테스트 중




    | 샘플시연


    • Stylelookup으로 아이폰에 맞는 UI를 Properties에서 변경 후 iOS Emulator 및 iPhone에서 실행
    • Standard Action으로 플랫폼의 특화 기능(사진찍기, 사진불러오기, 공유 등)을 사용
    • 사진찍기, 사진불러오기 및 애니메이션, Effect 시연
    • REST API와 JSON을 통해 데이터 수신 후 WebBrowser에 구글맵 출력
    • TabControl 및 ListBox등 아이폰 친화 UI 구현
    • 보통 대만에서 시연하면 박수와 함성이 터지는데 한국사람은 자기를 싫어하는 것 같다며 호응 유도
    • 샘플의 기능을 XCode 6년차 개발자와 누가 먼저 만드는지 내기
    • Firemonkey 하루, XCode 약 2주 걸렸다 함
    • 단편적인 비교인 듯, 반대의 경우(XCode 개발하기 쉬운 기능을 Firemonkey로 쉽게 개발 할 수 있을까?)는 어떨까 생각해 봄

    | 차세대 컴파일러


      • LLVM 차세대 컴파일러 명 = NextGen
        • Classic compiler : Win32, Win64, OSX, iOS Emulator
        • NextGen compiler : iOS, Android


      • 향후 Classic compiler 영역도 차츰 NextGen으로 교체 예정
      • C++ Builder 64bit에서 2~10배의 성능을 확인 함
      • LLVM의 가비지콜렉션에 의한 제한이 있음
        • Pointer 사용을 제한할 것
        • Static array 대신 Dynamic array를 사용할 것
        • With문을 없앨 것

      | 기타


        • 파이어몽키 관련 도서를 데브기어에서 번역 중
        • 번역 완료 후 이북형태로 무료 배표 예정
        • (Q&A)애플과 계약된 PAS Bridge(?)로 PAServer가 막힐 일은 없을 것으로 예상
        • (Q&A)앱의 속도는 Native API를 직접 호출 하므로 XCode로 작성하는 것과 비슷할 것이라 함

        | 총평


          엠바카데로에서 파이어몽키에 사할을 거는 듯한 느낌입니다. 
          초반에 고든 리가 어찌나 파이어몽키가 좋다고 자랑을 하기도 하고, David I의 31일 비디오(http://tech.devgear.co.kr/11735)를 봐도 이전과는 다른 엠바카데로의 모습인 것 같습니다.

          기능적인 부분에서는 
          기본적으로 캡슐화 되어 제공되는 플랫폼의 특화 기능이 참 편리하고 좋을 듯하지만, 그 기능 이외의 작업을 추가해야 할 경우 대부분의 개발자는 멘붕이 올듯 함(기본지식이 없이 제공해주는 것만 사용하므로 기본기능 제어가 힘들 듯)

          마지막으로
          개발 업체들을 얼마나 파이어몽키로 끌어 올 수 있는가가 성공의 관건일 듯 합니다.
          저는 개인적으로 그리 낙관적이지 않다고 생각합니다.
          긴시간 델파이의 VCL에 익숙해진 개발자(특히 SI 업체)와 업체들이 문법만 같은 새로운 프레임웍을 자발적으로 사용할지 의문이네요.
          차라리 요즘 추세와 같이 오픈소스 개발자나 개인 개발자들을 독려하여 흥미를 유발시켜,
          레퍼런스나 참고자료가 어느정도 쌓여야만 업체나 기존 개발자들도 관심을 갖고 들여다 보지 않을까 생각합니다.

          그러기 위해서는 라이센스 정책도 좀 더 유연하게(예를 들면 저렴한 개인 라이센스 등: Starter Edition처럼 기능 다 막아놓은것 말고) 델파이 빠들에 프렌들리하게 다가가야 하지 않을까 개인적으로 생각하며 마칩니다.


          저작자 표시 비영리 동일 조건 변경 허락
          신고
          크리에이티브 커먼즈 라이선스
          Creative Commons License

          험프리.김현수 험프리.김현수 교육, 세미나 Delphi, Delphi for iOS, Firemonkey, ios개발, NextGen, Rad Studio, XE3.5, 파이어몽키

          1. Blog Icon
            O*X

            수고하셨습니다.^^
            세미나 내용이 궁금했는데 이렇게 정리 한 글 보니 도움이 많이 돼네요. ㅎ
            국내에는 업체들의 개발 플랫폼이 델파이7에 고착되어 유지 보수의 성향이 심하다 보니,
            Delphi IDE 변화나 플랫폼 업그레이드 변화에 따른 대응이나 실험적인 측면이 더딘 감이 많은것 같네요. 저희 회사도 마찬가지로 델파이7에서 현재는 XE2로 컨버전 작업이 조금씩은 이루어 지고 있답니다.

            아무쪼록 Delphi가 국내 환경에서 관심을 많이 받았으면 하는 바램이랍니다.

            앞으로도 좋은 글 부탁드려요~

          2. 감사합니다. 생각보다 많은 분들이 관심을 갖어 주셔서. 글을 쓴 보람을 느끼네요.

            앞으로도 파이어몽키, 델파이 관련 글들 꾸준히 남길테니 관심 부탁드립니다. 감사합니다.^^

          3. 데브기어에서 제공하는 파이어몽키 이북 링크 입니다.
            http://bit.ly/VNzUQL

          [FMX] 다이나믹한 UI 효과 - Float animation effect

          2013.03.05 16:35

          대부분의 분들은 파이어몽키로 멀티플랫폼 지원을 위한 개발을 생각하고 계실텐데요.

          파이어몽키는 멀티플랫폼 기능외에도 다양한 기능이 포함되어 있습니다.


          대표적으로 

          3D 효과 및 벡터형식의 부드러운 출력, RoateAngle 및 Scale 등의 신규 속성 등이 추가되었습니다.


          오늘은 

          새로운 기능 중 하나인 FloatAnimation에 대해 소개하려 합니다.


          FloatAnimation은 단어 그대로 Float을 Animation하는 놈입니다.


          좀 더 자세히 설명하면, 

          지정한 Start와 Stop에 해당하는 Float 값사이를 지정된 시간(Duration)에 맞춰 다양한 효과(Interpolation: 보간)로 값을 변경하는 놈입니다.


          우선 샘플을 보시면 아래의 영상은 마우스 휠(업/다운) 시 마우스 주변에 효과를 주고. 특정 Zoom 이상인 경우 RoundRect 메시지를 표시하고 서서히 사라지는 효과를 주었습니다.

          (구현 내용은 아래 첨부한 소스파일을 참고하시구요.)


          FloatAnimation은 TAniThread(FMX.Types.pas)에 의해 쓰래드로 진행이 되어 

          다른작업에 영향을 주지 않고도 UI에 다양한 효과 및 재미난 기능을 매우 쉽게 넣을 수 있습니다.


          FloatAnimation을 사용하는 방법은 두가지 인데요.


          첫째, 

          애니메이션 효과를 줄 컨트롤의 자식으로 TFloatAnimation을 등록 후 설정하여 사용하는 방법

          둘째,

          애니메이션 효과를 줄 컨트롤에 .AnimationFloat() 메소드를 이용하여 직접 효과를 주는 방법


          두개 중 편리한 방법을 사용하시면 될 것 같습니다.


          아래의 영상은

          AnimationType과 TInterpolationType을 지정하고 어떤 효과가 나는지 확인하는 샘플입니다.

          (당겼다가 가기[Back], 공튀기기[Bounce] 등의 효과를 확인 할 수 있습니다.)


          그리고 위 영상의 주요코드


          uses
            System.TypInfo;
          
          procedure TForm3.FormCreate(Sender: TObject);
          var
            Animation: TAnimationType;
            Interpolation: TInterpolationType;
          begin
            Circle1.Position.X := 0;
            Circle1.Position.Y := (Panel1.Height - Circle1.Height) / 2;
          
            // Circle이 멈출 위치를 계산
            FLastValue := Panel1.Width - Circle1.Width;
          
            // 콤보박스에 속성을 표시합니다.
            for Animation in [Low(TAnimationType)..High(TAnimationType)] do
              cbbAnimation.Items.AddObject(GetEnumName(TypeInfo(TAnimationType), Ord(Animation)), TObject(Animation));
            cbbAnimation.ItemIndex := 0;
          
            for Interpolation in [Low(TInterpolationType)..High(TInterpolationType)] do
              cbbInterpolation.Items.AddObject(GetEnumName(TypeInfo(TInterpolationType), Ord(Interpolation)), TObject(Interpolation));
            cbbInterpolation.ItemIndex := 0;
          end;
          
          procedure TForm3.Button1Click(Sender: TObject);
          begin
            if rbTFloatAnimation.IsChecked then
            begin
              FloatAnimation1.PropertyName := 'Position.X';
              FloatAnimation1.StartValue := 0;
              FloatAnimation1.StopValue := FLastValue;
              FloatAnimation1.Duration := 1;
              FloatAnimation1.AnimationType := TAnimationType(cbbAnimation.Items.Objects[cbbAnimation.ItemIndex]);
              FloatAnimation1.Interpolation := TInterpolationType(cbbInterpolation.Items.Objects[cbbInterpolation.ItemIndex]);
              FloatAnimation1.Start;
            end
            else
            begin
              Circle1.Position.X := 0;
              Circle1.AnimateFloat(
                  'Position.X',
                  FLastValue,
                  1,
                  TAnimationType(cbbAnimation.Items.Objects[cbbAnimation.ItemIndex]),
                  TInterpolationType(cbbInterpolation.Items.Objects[cbbInterpolation.ItemIndex])
              );
            end;
          end;
          

          사용방법은 어렵지 않습니다.

          그래도 다양한 효과를 위해서는 TInterpolationType과 TAnimationType을 잘 설정해 주어야 합니다.

          글로 설명하는 것 보다 샘플프로그램 다운로드하셔서 실행해 보시는게 좋을 것같네요.


          샘플프로그램 실행파일 

          FloatAnimation.zip


          샘플프로그램 소스파일

          FloatAnimationSrc.zip


          경고창 애니메이션 효과 소스

          ThAlertAnimation.pas

          Zoom 애니메이션 효과 소스

          ThZoomAnimation.pas


          아래는 엠바카데로의 도움말입니다. 참고하세요.


          http://docwiki.embarcadero.com/Libraries/XE3/en/FMX.Types.TInterpolationType

          Value Meaning

          itLinear

          A linear interpolation. The property value this animation applies to changes constantly over time.

          itQuadratic

          A quadratic function is applied to the path between the start and stop points. The slope of the path is zero at the start point and increases constantly over time. A scalar is applied to the function to make the endpoint fall on the path.

          itCubic

          The interpolation is of the form y = x**3. The slope of the path is zero at the start point and increases much faster than the quadratic function over the path.

          itQuartic

          The interpolation is of the form y = x**4. The slope of the path is zero at the start point and increases much faster than the quadratic function over the path.

          itQuintic

          The interpolation is of the form y = x**5. The slope of the path is zero at the start point and increases much faster than the quadratic function over the path.

          itSinusoidal

          The interpolation is of the form y = sin(x). The slope of the path is zero at the start point and places the first inflexion of the sin curve (x=pi) at the stop point.

          itExponential

          The interpolation is of the form y = e**x. The slope of the path is one at the start point and increase much faster than the quadratic function over the path.

          itCircular

          The path between the start and stop point for this interpolation is a quarter of a circle. The slope of the path is zero at the start point and verticle at the stop point.

          itElastic

          The path does not follow a geometric interpolation. The value (y coordinate) may decrease, moving back toward the Start Value, but time (x value) must always move in a positive direction.

          itBack

          The path does not follow a geometric interpolation. The value (y coordinate) may decrease, moving back toward the Start Value, but time (x value) must always move in a positive direction.

          itBounce

          The path depicts a bouncing ball. The path is made up of circular curves with curvature away from the straight line that connects the start and stop points. These curves are connected by sharp points.


          http://docwiki.embarcadero.com/Libraries/XE3/en/FMX.Types.TAnimationType

          Value Meaning

          atIn

          The curve that applies to the TInterpolationType for this animation starts at the starting value of the property animated.

          atOut

          The curve that applies to the TInterpolationType for this animation starts at the ending value of the property animated and proceeds backwards to the starting value.

          atInOut

          The curve that applies to the TInterpolationType for this animation starts at both the starting value and the ending value of the property animated and meets at the center point.


          저작자 표시 비영리 동일 조건 변경 허락
          신고
          크리에이티브 커먼즈 라이선스
          Creative Commons License

          험프리.김현수 험프리.김현수 파이어몽키 Animation Effect, AnimationFloat, Dynamic UI, Firemonkey, FloatAnimation, FMX, 파이어몽키

          [작업일지] 문자입력은 보류 중.

          2013.01.29 02:23

          2월 20일 발표가 잡혔다. 그래서 발표준비를 해야한다. ㅠㅜ

          (살짝쿵 홍보 RT:FM 프로그래머로 사는 법

           http://onoffmix.com/event/12062)


          난 천상 개발자인가보다 발표보다 개발이 더 좋으니...


          문자입력을 어떻게 처리할까 고민하고 참고소스도 들여다 보는데...

          음... 예상대로 많이 어렵다.


          에디터를 만든다는 것 만만치 않다.


          우선 클릭하고 입력하고 선택, 이동만 되게 하고

          다음 더블클릭해서 수정되게 하고

          다음 여러줄 입력 할 수 있게 하고

          나중에 글자별 스타일 적용 시키고~


          후후 쉽게 가야지~ 

          IME처리가 문제예요~ 영어만하면 입력받아서 문자 그려주면 될 것 같구먼...


          아무튼 문자입력은 잠정 보류 입니다.


          PS - 미래를 준비하기 위해 딴일도 해야하는뎅 ㅠㅜ 동시에 몇개씩 일을 하니 내가 집중을 못하징(행복한 볼멘소리)





          글만쓰면 서운하니까 팁하나!!


          GUI와 Unittest입니다.

          자세한 내용은 없고 아래 동영상 한번 보시고...

          힌트는 "이벤트를 발생"

          FIremonkey와 DUnit으로 작업된 Thoth Canvas 테스트입니다.


          혹시 자세한 정보(방법, 샘플)를 원하시면 댓글 주세요^^



          저작자 표시 비영리 동일 조건 변경 허락
          신고
          크리에이티브 커먼즈 라이선스
          Creative Commons License

          험프리.김현수 험프리.김현수 Team Thoth DUnit, Firemonkey, TDD, Thoth Canvas, unittest

          [FMX] Firemonkey 구조 - 어떻게 하나의 코드로 여러 플랫폼에서 실행 될까?

          2012.06.23 03:04

          이번에는 이리저리 파이어몽키 소스 보며 익혔던 간단한 구조에 대해 설명하려 합니다.

          (딱, 제가 아는 만큼만 소개합니다.^^)


          파이어몽키는 멀티 플랫폼을 지원하는 델파이 프레임웤 입니다.

          어떻게 파이어몽키는 하나의 소스로 여러개의 플랫폼을 지원할까요?

          여러개의 플랫폼을 지원하는 열쇠는 FMX.Platform.pas의 Platform: TPlatform에 있습니다.
          (C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\source\fmx에 소스파일이 있습니다.)


          FMX.Platform의 TPlatform 클래스를 보시면 대부분(거의 다)이 추상메소드(virtual; abstract;) 입니다. 구현이 안되어 있다는 것이죠.

          그리고 메소드명이 상당히 플랫폼에 종속적인 냄새를 풍깁니다.

          CreateWindow(창을 생성하는 건 OS에서 해주겠죠.)
          CreateTimer(타이머도 OS에서 이벤트를 발생해 줍니다.)
          WaitMessage(메시지 처리도 OS와 연관이 있지요.) 등등 모두 플랫폼에 종족적인 메소드들입니다.

          그리고 소스 디렉토리에 보시면 FMX.Platform.Win과 FMX.Platform.Mac 두개의 플랫폼 관련 유닛파일을 보실 수 있습니다.

          즉, FMX.Platform의 TPlatform을 상속받은 클래스들이 구현되어 있겠죠.

          맞습니다. 각 파일을 보시면 TPlatformWin과 TPlatformCocoa 두개의 클래스가 TPlatform을 상속받습니다.

          물론 추상메소드들도 모두 구현되어 있습니다.

          TPlatformWin은 Windows API를 이용하여 구현이 되어 있고, TPlatformCocoa는 OS X API로 구현이 되어 있습니다.


          그럼 어떻게 Firemonkey는 플랫폼에 맞는 TPlatform 객체를 사용할까요?

          위의 질문에 답하기 위해 먼저 프로젝트 소스파일을 들여다 보겠습니다.

          Delphi XE2에서 <Firemonkey HD Application> 프로젝트를 생성하시면 아래와 같은 소스코드를 기본적으로 생성합니다.

          program Project1;
          
          uses
            FMX.Forms,
            Unit1 in 'Unit1.pas' {Form1};
          
          {$R *.res}
          
          begin
            Application.Initialize;
            Application.CreateForm(TForm1, Form1);
            Application.Run;
          end.
          

          위의 프로젝트 소스를 보면 도무지 참조하는 유닛이 FMX.Forms 밖에 없습니다.


          그럼 FMX.Forms 유닛을 살펴보겠습니다.

          주욱 보시면 VCL에서도 익숙한 TApplication, 앞으로 친하게 지내야될 TCommonCustomForm 등등의 클래스 등이 보입니다.

          그리고 제일 아래에 보면 우리가 찾던 Platform 관련된 코드가 보입니다.

          initialization
            RegisterFmxClasses([TApplication], [TApplication]);
            Screen := TScreen.Create(nil);
            Platform := PlatformClass.Create(nil);
            System.Classes.RegisterFindGlobalComponentProc(FindGlobalComponent);
          
          finalization
            System.Classes.UnregisterFindGlobalComponentProc(FindGlobalComponent);
            FreeAndNil(Screen);
            // Platform global is freed in FMX.Types
          

          위 코드의 4번째 줄을 보시면

          Platform := PlatformClass.Create(nil);

          이라고 PlatformClass를 이용해 TPlatform 객체를 생성해 할당합니다.


          자 그럼 다시 PaltformClass를 따라가 봅니다.

          FMX.Platform.pas에 PlatformClass 함수가 구현되어 있습니다.

          function PlatformClass: TPlatformClass;
          begin
            Result := ActualPlatformClass;
          end;

          그럼 ActualPlatformClass는 어디에 구현되어 있을까요?


          예상하시는 분들도 있겠지만 위에서 설명한 Platform별 유닛(FMX.Platform.Win, FMX.Platform.Mac)에 구현되어 있습니다.

          MSWINDOWS의 경우 TPlatformWin을 반환하고

          MACOS의 경우 TPlatformCocoa를 반환합니다.

          근데 의문이 듭니다. 어떻게 델파이는 2개중에 하나를 선택할까요?

          그건 바로 Conditional define($IFDEF)을 이용합니다.

          FMX.Platform의 구현부(implementation) 시작을 보시면 아래와 같은 코드를 보실 수 있습니다.

          {$IFDEF IOS}
          uses
            FMX.Platform.iOS, FMX.Canvas.iOS, FMX.Context.GLES;
          {$ENDIF}
          
          {$IFDEF MACOS}
          uses
            FMX.Platform.Mac, FMX.Canvas.Mac, FMX.Context.Mac;
          {$ENDIF}
          
          {$IFDEF MSWINDOWS}
          uses
            FMX.Platform.Win, FMX.Context.DX9;
          {$ENDIF}
          
          

          보시면 아시겠지만 IOS, MACOS, MSWINDOWS 별로 다른 유닛을 참조하도록 되어있습니다.

          위의 3가지는 모두 Firemonkey가 지원하는 플랫폼입니다.

          즉 Project Manager의 Target platform에서 Platform을 선택하면 그에 맞는 값(IOS, MACOS, MSWINDOWS)이 내부적으로 정의됩니다.

          그래서 결국은 Target platform에 맞는 TPlatform 객체를 이용하여 OS에 맞는 API를 사용하여 실행됩니다.


          좀더 설명을 하자면 위의 프로젝트 소스를 보시면 아래와 같이 Application을 실행(RUN)하는 코드를 볼 수 있습니다.

          Application.Run;

          Run 메소드를 살펴보면 아래와 같이 Platform에 따른 코드를 사용하여 Application을 실행합니다.

          procedure TApplication.Run;
          begin
            FRunning := True;
            AddExitProc(DoneApplication);
            try
              Platform.Run; // Platform의 Run 실행
            finally
              FRunning := False;
            end;
          end;
          
          // MSWINDOWS에 맞게 Application 실행
          procedure TPlatformWin.Run;
          begin
            { checking for canvas }
            if GlobalUseDirect2D then
              SetD2DDefault;
          
            Application.RealCreateForms;
            repeat
              try
                Application.HandleMessage;
              except
                Application.HandleException(Self);
              end;
            until Application.Terminated;
          end;
          
          // MACOS 맞게 Application 실행
          procedure TPlatformCocoa.Run;
          begin
            Application.RealCreateForms;
            CreateApplicationMenu;
            FRunLoopObserver := CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, True, 0, RunLoopObserverCallback, nil);
            CFRunLoopAddObserver(CFRunLoopGetCurrent, FRunLoopObserver, kCFRunLoopCommonModes);
            NSApp.Run;
          end;
          

          다른 메서드 또는 다른 유닛(FMX.Types 등)에서 Platform 전역변수를 이용하도록 구현되어 있습니다.


          다시한번 정리하면, 

          1, Project 소스에서 FMX.Forms 참조(uses)

          2, FMS.Forms의 Initialization에서 FMS.Platform.pas 유닛의 PlatformClass를 통해 Platform 생성

          3, FMS.Platform는 각 플랫폼 유닛의 ActualPlatformClass 함수 호출하여 Platform에 맞는 TPlatform 객체 형 방ㄴ환

          4, 단, Platform에 맞는 유닛을 $IFDEF를 이용하여 결정($IFDEF는 Target platform 선택 시 정의)


          이상으로 Firemonkey에서 Platform에 맞게 실행되는 구조를 두서없이 설명했습니다.

          감사합니다. 끝~


          PS - 다음에는 Firemonkey를 실질적으로 사용하기 위한 팁들을 몇개 소개하겠습니다.^^

          신고
          크리에이티브 커먼즈 라이선스
          Creative Commons License

          험프리.김현수 험프리.김현수 파이어몽키 Firemonkey, FMX, FMX 구조, multi platform

          [FMX,VCL 비교] #1 VCL의 Canvas와 FMX의 Canvas 차이

          2012.06.20 12:52

          파이어몽키로 작업하다보면 VCL과의 차이점으로 어려움을 겪는 경우가 많습니다.

          그동안 작업하며 습득한 차이점을 한가지한가지 풀어놓으려 합니다.

          그중 첫번째 Canvas 입니다.

          일반적으로 TImage에 Drawing을 하는 예제로 구성하였습니다.
          VCL과 FMX의 동일한 기능을 구현했으니 비교해 보시면 좋을 것 같습니다.

          FMX 코딩시 주의점

          1, TImage.Picture.Bitmap => TImage.Bitmap : VCL의 Picture 객체가 빠졌습니다.

          2, Bitmap.Canvas.BeginScene ~ EndScene, Bitmap.BitmapChange : Canvas에 그리기고 화면에 표시하기 위한 절차입니다.

          3, Brush => Fill, Pen => Stroke 등으로 속성들이 약간씩 변했습니다.

          4, MoveTo, LineTo => DrawLine

          5, FMX의 기본적인 좌표가 Single 형이기 때문에 Bitmap의 Pixel 단위인 Integer로 형변환(Round, Trunc)이 필요합니다.


           이하 소스코드 입니다. 빈프로젝트에 아래 소스 복사하면 컴파일 됩니다.(Unit명만 주의) 폼에 컨트롤이 없습니다.

          | VCL Canvas Freeline Draw

          unit Unit1;
          
          interface
          
          uses
            Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
            Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
          
          type
            TForm1 = class(TForm)
              procedure FormCreate(Sender: TObject);
            private
              { Private declarations }
              FDownPos: TPoint;
              FImage: TImage;
          
              procedure MouseDown(Sender: TObject; Button: TMouseButton;
                Shift: TShiftState; X, Y: Integer);
              procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
            public
              { Public declarations }
            end;
          
          var
            Form1: TForm1;
          
          implementation
          
          {$R *.dfm}
          
          procedure TForm1.FormCreate(Sender: TObject);
          begin
            FImage := TImage.Create(Self);
            FImage.Parent := Self;
            FImage.Align := alClient;
            FImage.OnMouseDown := MouseDown;
            FImage.OnMouseMove := MouseMove;
            FImage.Picture.Bitmap.SetSize(FImage.Width, FImage.Height);
            FIMage.Picture.Bitmap.Canvas.Brush.Color := clBlack;
            FImage.Picture.Bitmap.Canvas.FillRect(FImage.ClientRect);
            FImage.Visible := True;
          end;
          
          procedure TForm1.MouseDown(Sender: TObject; Button: TMouseButton;
            Shift: TShiftState; X, Y: Integer);
          begin
            if ssLeft in Shift then
              FDownPos := Point(X, Y);
          end;
          
          procedure TForm1.MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
          begin
            if ssLeft in Shift then
            begin
              with FImage.Picture.Bitmap.Canvas do
              begin
                Pen.Color := clRed;
                Pen.Width := 3;
                MoveTo(FDownPos.X, FDownPos.Y);
                LineTo(X, Y);
              end;
          
              FDownPos := Point(X, Y);
            end;
          end;
          
          end.
          


          | FMX Canvas Freeline Draw

          unit Unit2;
          
          interface
          
          uses
            System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
            FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Objects;
          
          type
            TForm2 = class(TForm)
              procedure FormCreate(Sender: TObject);
            private
              { Private declarations }
              FDownPos: TPointF;
              FImage: TImage;
          
              procedure MouseDown(Sender: TObject; Button: TMouseButton;
                Shift: TShiftState; X, Y: Single);
              procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
            public
              { Public declarations }
            end;
          
          var
            Form2: TForm2;
          
          implementation
          
          {$R *.fmx}
          
          procedure TForm2.FormCreate(Sender: TObject);
          begin
            FImage := TImage.Create(Self);
            FImage.Parent := Self;
            FImage.Align := TAlignLayout.alClient;
            FImage.OnMouseDown := MouseDown;
            FImage.OnMouseMove := MouseMove;
            FImage.Bitmap.Create(Round(FImage.Width), Round(FImage.Height));
            FImage.Bitmap.Canvas.BeginScene;
            FImage.Bitmap.Canvas.Fill.Color := claBlack;
            FImage.Bitmap.Canvas.FillRect(FImage.ClipRect, 0, 0, AllCorners, 1);
            FImage.Bitmap.Canvas.EndScene;
            FImage.Visible := True;
          
          end;
          
          procedure TForm2.MouseDown(Sender: TObject; Button: TMouseButton;
            Shift: TShiftState; X, Y: Single);
          begin
            if ssLeft in Shift then
              FDownPos := PointF(X, Y);
          end;
          
          procedure TForm2.MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
          begin
            if ssLeft in Shift then
            begin
              with FImage.Bitmap.Canvas do
              begin
                BeginScene;
                Stroke.Color := claRed;
                StrokeThickness := 3;
                DrawLine(FDownPos, PointF(X, Y), 1);
                EndScene;
              end;
              FImage.Bitmap.BitmapChanged;
          
              FDownPos := PointF(X, Y);
            end;
          end;
          
          end.
          



          신고
          크리에이티브 커먼즈 라이선스
          Creative Commons License

          험프리.김현수 험프리.김현수 파이어몽키 Canvas, Firemonkey, FMX, FMX VCL 차이, 파이어몽키