Search results for '전체'

  1. 2019.06.10 -- [FMX] RAD 스튜디오 10.3.1에서 FCM 전송 설정하기
  2. 2019.05.30 -- 델파이 코드 주석 추가 및 문서화 방안
  3. 2019.05.24 -- [마이그레이션 사례] 워프비전(64-bit 애플리케이션)
  4. 2019.05.23 -- [VCL] 용량이 큰 JPEG 파일 다루기 - JPEG 라이브러리 조사
  5. 2019.05.17 -- [FMX] 안드로이드 권한 모델 적용 방법
  6. 2019.02.20 -- [FMX][팁] 파이어몽키 버튼의 배경색상 변경하기
  7. 2019.02.20 -- [FMX][팁] 파이어몽키 TComboBox 글자 크기 변경
  8. 2019.02.20 -- [개발환경설정] 윈도우즈 환경에 Git 설치하기
  9. 2019.01.30 -- 델파이 코드 작성 규칙
  10. 2019.01.23 -- 이더넷 어댑터 정보((MacAddress, IP 등) 목록 알아오기
  11. 2019.01.14 -- CEF4Delphi(크로미움 기반 웹브라우저) 컴포넌트 설치 및 실행하기 (3)
  12. 2019.01.14 -- [REST API] MAC(Message Authentication Code)/HMAC 델파이로 구현하기
  13. 2018.12.20 -- OAuth 2.0 연동 - 카카오 API(카카오톡 프로필) (1)
  14. 2017.12.19 -- RFID 리더(한미IT RF Prisma) 연동하기 - 델파이에서 JAR 이용 (2)
  15. 2017.12.06 -- WaitDialog 구현 - 재사용 가능한 프레임 구현하기
  16. 2017.11.22 -- [튜토리얼] 메일 전송(IdSMTP 이용) (2)
  17. 2017.11.22 -- [튜토리얼] FTP 업로드(TIdFTP 이용) (1)
  18. 2017.11.02 -- 델파이/C++빌더에 TTcpClient, TTcpServer, TUdpSocket 등록하기
  19. 2017.10.30 -- 안면인식(Face Detection) 라이브러리(안드로이드, iOS)
  20. 2017.10.30 -- TTS(Text-to-Speech) 라이브러리(윈도우, 맥OS, iOS, 안드로이드)

[FMX] RAD 스튜디오 10.3.1에서 FCM 전송 설정하기

2019.06.10 14:13

이 글은 Marco Cantu가 작성한 Firebase Android Push Notification Support with RAD Studio 10.3.1의 의역입니다.

 

구글은 다음과 같이 발표했습니다.  "GCM 서버와 클라이언트 API는 지원중단하며, 2019년 5월 29일에 삭제될 예정입니다. 안정적이고 확장가능한 GCM 인프라 및 많은 새로운 기능을 계승한 Firebase Cloud Messaging(FCM)으로 GCM 애플리케이션을 전환하십시오."

 

앞으로 파이어몽키 안드로이드 앱에서 푸시 알림 지원을 사용하려면, 구글의 Firebase를 사용해야 합니다. 이 글에서는 Delphi, C++Builder 및 RAD 스튜디오 10.3.1을 사용해 파이어몽키 안드로이드 앱에서 Firebase 푸시 알림 지원하는 과정을 소개합니다.

 

사전준비 - 안드로이드 푸시 알림 패치

시작에 앞서 IDE의 겟잇 패키지 매니저(Tools > Getit Package Manager...)에서 "Android Push Notification Patch 1.0"을 찾아 설치 버튼을 클릭 해 다운로드 합니다.("Android"로 검색)

 

최신 로드맵에서 소개했듯이 향후 10.3.2 릴리즈에서 이 지원을 더욱 간소화(RAD 서버의 Android Firebase 푸시 알림 지원 추가) 및 10.4의 Firebase 및 기타 관련 서비스의 전체 통합 지원 제공을 계획하고 있습니다.

 

Firebase에서 애플리케이션을 활성화하려면, 다음 3단계로 작업을 진행해야 합니다.

 

1, Firebase 프로젝트를 만들고 파이어몽키 프로젝트를 Google Firebase 콘솔에 등록

2, 파이어몽키 프로젝트를 새로 만들거나 기존의 프로젝트에 RAD 스튜디오 10.3.1 푸시 알림 구성

3, GCM(Google Cloud Messaging)  대신 Firebase를 지원하도록 파이어몽키 프로젝트 변경

 

Firebase 프로젝트 생성 및 Firebase 콘솔에 파이어몽키 프로젝트 등록

1, Google Firebase 콘솔(https://console.firebase.google.com/)에 접속 후 [새 프로젝트]를 클릭 합니다.

2, 필요한 사항을 설정하고 [프로젝트 만들기] 버튼을 클릭합니다.

 - 프로젝트 이름은 임의로 설정(예> FirebaseApp)

 - Cloud Firestore 위치는 현재(2019.05) 가장 가까운 asia-northeast1 추천

3, 프로젝트 생성 후 Project Overview 옆의 톱니바퀴 아이콘 클릭 후 [프로젝트 설정] 메뉴를 선택해 프로젝트 설정 화면으로 이동합니다.

4, 안드로이드 아이콘을 클릭하여 "Android 앱에 Firebase 추가 화면"으로 이동합니다.

 

5, 앱 등록 단계에서 Android 패키지 이름을 지정 후 [앱 등록] 버튼을 클릭합니다.

 - 파이어몽키 앱의 기본 패키지 이름은 com.embarcadero.프로젝트이름 입니다.

 - 파이어몽키 프로젝트를 FirebaseApp으로 생성 시 com.embarcadero.FirebaseApp으로 생성합니다.

 - 프로젝트 옵션(Application > Version Info의 package 항목)에서 패키지 이름 설정 가능합니다.

6, 구성 파일(google-services.json)을 다운로드 합니다. 

다운로드 후 [다음] 버튼 클릭 후 이후 단계는 건너 뛰기를 선택합니다.

 

7, 안드로이드 문자열 리소스 파일(strings.xml)을 편집합니다.

 - strings.xml 파일은 겟잇 패키지 매니저에서 다운로드한 파일에 포함되어 있습니다.
    (C:\Users\Public\Documents\Embarcadero\Studio\20.0\CatalogRepository\AndroidPushNotificationsPatch-1.0\FireBase)

 - strings.xml 파일을 파이어몽키 프로젝트 경로에 복사합니다.(예> C:\MyFirebaseApplication 등)

 - 복사한 strings.xml 파일을 텍스트 에디터 등으로 열어 다음을 수정합니다.

  * google_app_id와 gcm_defaultSenderId, fcm_fallback_notification_channel_label 항목만 두고 나머지 string 태그 삭제

  * google_app_id = mobilesdk_app_id

  * gcm_defaultSenderId = project_number
    (6단계에서 다운로드 받은 google-services.json 파일을 참조)

 

파이어몽키 프로젝트에 푸시 알림 구성

8, 파이어몽키 프로젝트를 생성(또는 기존 프로젝트 오픈) 합니다.

 

9, Firebase 콘솔에 등록된 프로젝트 이름과 일치하도록 FMX 프로젝트 이름을 변경합니다.

    (이 예제에서는 FirebaseApp으로 설정합니다.)

7단계에서 업데이트 한 strings.xml 파일과 동일한 경로에 프로젝트를 저장합니다.(예> C:\MyFirebaseApplication)

저장 후 안드로이드 플랫폼 선택 후 빌드를 실행해 해당 경로에 AndroidManifest.template.xml을 생성합니다. 이 파일은 마지막 단계에서 편집합니다.

 

10, Firebase 이벤트 로그를 표시하기 위해 TMemo 컴포넌트를 폼에 추가하고, MemoLog로 이름을 변경합니다.

다음 Form의 OnCreate 이벤트를 추가해 푸시 알림 서비스 초기화 및 연결을 위한 코드를 구현합니다.

 

이 코드는 겟잇 패키지 매니저에 포함되어 있는 Snippets.txt 파일을 참조하기 바랍니다.

Snippets.txt 파일에는 푸시 알림 서비스로 연결을 만드는 프로세스와 이벤트에 대한 코드가 포함되어 있습니다.

 

푸시 알림 서비스와 연결을 위한 코드를 OnCreate 이벤트에 복사합니다.

Snippets.txt의 1~2줄을 implimentation 아래에 추가합니다.

또한, interface uses 절에 System.PushNotification을 추가합니다.

이 서비스로 Firebase와 연결 후 장치아이디와 장치 토큰을 수신하게 됩니다. 필요한 변수와 이벤트를 private 영역에 선언합니다.

두개의 변수는 장치 아이디와 장치 토큰을 수신하는데 사용합니다.

OnServiceConnectionChange 이벤트는 연결 변경 시 장치 토큰을 얻는데 사용합니다.

OnReceiveNotificationEvent 이벤트는 푸시를 받기 위해 사용됩니다.

 

Snippets.txt를 참고해 2개의 이벤트를 구현합니다.

GCM 대신 FCM을 지원하도록 프로젝트 변경

11, IDE 오른쪽의 프로젝트 에서 Android > Libraries를 확장하고, 다음의 라이브러리를 각각 마우스 오른쪽 버튼을 이용해 수동으로 해제합니다.

  • cloud-messaging.dex.jar
  • google-analytics-v2.dex.jar
  • google-play로 시작하는 모든 Google Play 라이브러리

 

12, 프로젝트의 Libraries에 마우스 오른쪽 버튼을 누르고, [Add] 메뉴를 선택 해 Firebase 라이브러리들과 업데이트된 Google Play Services 라이브러리를 추가합니다.

(이 라이브러리 파일들은 겟잇 패키지 매니저에서 다운로드받은 파일들 중 jars 디렉토리에 있습니다.)

 

13, 다음 Firebase 지원을 위한 AndroidAPI.JNI.Firebase.pas와 업데이트된 FMX.PushNotification.Android.pas 파일을 프로젝트 경로에 복사 후 추가합니다.

(이 파일들은 겟잇 패키지 매니저에서 다운로드 받은 파일 중에 있습니다.)

 

14, IDE 메인 메뉴 중 Project > Deployment로 배포화면을 표시 후 프로젝트 경로의 strings.xml 파일을 추가합니다.

 

또한 strings.xml 파일의 Remote Path를 "res\Values\"로 업데이트 후 변경사항을 저장합니다.

 

15, 마지막 단계로 AndroidManifest.template.xml 파일을 변경합니다.(9단계에서 안드로이드 타겟인 프로젝트를 빌드해 생성)

 

Snippets.txt 파일 하단의 XML 구문을 복사해 <%receivers%>아래(</application> 태그 바로위)에 붙여넣기 합니다.

Firebase Clound Messaging 전송 테스트

16, FMX 앱을 안드로이드 장비에 배포합니다. 실행 시 앱은 자동으로 Firebase에 등록되고, 로그에 디바이스 토큰이 표시됩니다.

이 장비에 푸시메시지를 전송하려면 Firebase 토큰이 필요합니다. 로그에 표시된 토큰을 복사합니다.

 

17, 브라우저에서 Google Firebase 콘솔(https://console.firebase.google.com/) 접속 후 앞에서 만든 프로젝트를 선택합니다.

사이드 메뉴의 "성장 > Cloud Messaging" 메뉴를 선택 후 [Send your first message] 버튼을 클릭합니다.

 

18, 알림의 제목과 텍스트를 입력하고, [테스트 메시지 전송] 버튼을 클릭합니다.

16에서 선택한 Firebase 토큰을 "FCM 등록 토큰 추가" 항목에 입력 후 (+) 버튼 클릭해 토큰을 추가합니다.

[테스트] 버튼을 눌러 메시지를 전송합니다.

다음 화면과 같이 전송한 메시지가 안드로이드 화면에 표시되는 것을 확인할 수 있습니다. 또한 메시지는 안드로이드 알림센터에도 표시됩니다.

험프리.김현수 분류없음 FCM, FireBase Cloud Messaging, FMX, PushNotification, Push알림, 안드로이드 푸시

델파이 코드 주석 추가 및 문서화 방안

2019.05.30 17:09

주석은 코드를 더 읽기 쉽고, 유지보수하기 쉽게 할 수 있는 가장 기본적인 요소 중 하나입니다.

특히 팀단위로 개발하거나, 오랫동안 유지보수해야 하는 경우 진가를 발휘합니다.

 

이 글에서는 주석을 좀 더 효과적으로 달고, 내용을 문서화하는 방법을 소개합니다.

XMLDoc과 JavaDoc 주석의 특징과 추가 방법, 문서화 하는 방법을 알아봅니다.

 

XMLDoc과 JavaDoc 주석 추가

XMLDoc 주석

XMLDoc 주석의 특징

  • 3 중 슬래시(///)로 시작
  • XML 태그로 작성
  • 코드 에디터의 헬프 인사이트에 표시
  • XML 태그로 가독성이 다소 떨어짐

XML 주요 항목

  • <summary> 함수 또는 클래스에 대한 설명
  • <param name="파라메터 이름"> 파라메터에 대한 설명
  • <returns> 함수의 반환 값 설명
  • < exception cref="예외 유형"> 메소드에서 전달되는 예외

예시

XMLDoc의 특징

XML Doc 주석 추가 시 코드 에디터의 헬프 인사이트에 표시됩니다.

단, 선언부(interface 영역)에 XML Doc 추가 시에만 표시됩니다.

한가지 팁으로, 코드 템플릿에 템플릿을 추가하면 필요시 코드에디터에 주석을 쉽게 추가 할 수 있습니다.

(Ctrl + J > 키워드 입력 또는 키워드 입력 > Ctrl + J)

 

코드 템플릿 추가방법

View > Tool Windows > Templates 메뉴 선택

New Code Template 버튼 클릭

아래 코드 참고해 XML 태그 수정 후 저장(예> xmldoc.summary.xml)

xmldoc.summary.xml
0.00MB

 

또는 위 XML 태그로 xml 파일 생성(별도의 텍스트 에디터에서) 및 저장

템플릿 디렉토리에 xml 파일 복사

(10.3 기준 템플릿 디렉토리 : C:\Program Files (x86)\Embarcadero\Studio\20.0\ObjRepos\en\Code_Templates\Delphi)

 

JavaDoc 주석

자바의 주석 형식으로 주석을 작성하면, 별도 프로그램을 이용 문서화(HTML, CHM, PDF 등)가 가능합니다.

JavaDoc 주석의 특징

  • 블록 주성({** 시작 *}로 끝) 또는 한줄 주석(3 중 슬래시(///)로 시작)
  • 주석의 속성(태그)은 @으로 시작
  • XMLDoc에 비해 주석 가독성이 높음(짧음)

JavaDoc 주요 태그

  • 태그 없는 경우 함수에 대한 설명
  • @author 작성자
  • @version 버전
  • @param 메소드 파라메터 설명
  • @return 반환 값 설명
  • @throws 메소드에서 전달되는 예외

예시

 

주석 문서화

추가한 주석을 문서화(문서로 내보내기)하는 방법을 알아봅니다.

XMLDoc 주석 문서화

XMLDoc을 문서화 하기 위해서는 Model을 생성해야 합니다.

Projects 팬에서 Model View 탭을 선택 후 모델을 생성합니다.

Model View에서 문서화할 대상(프로젝트 또는 유닛) 선택 후 팝업메뉴에서 "Generate Documentation..." 메뉴를 선택 합니다.

문서화 범위(Scope) 및 옵션(Options)를 선택 후 [OK] 버튼을 클릭 합니다.

 

결과 예시

다음과 같이 XMLDoc 주석을 추가했습니다.

 

생성된 HTML은 다음과 같습니다.

JavaDoc 주석 문서화

JavaDoc 포맷의 주석을 문서화 하기 위해서는 별도의 프로그램을 이용해야 합니다.

이 글에서는 DelphiCodeToDoc를 이용해 문서화합니다.

 

DelphiCodeToDoc은 델파이로 제작된 오픈소스(GPL)로 자유롭게 설치하고 필요한 기능을 수정해 기여할 수 있습니다.

문서화 포맷으로 CHM, HTML, PDF를 지원합니다.(Configuration 화면의 Output options > Output Format에서 지정)

결과물이 썩 이쁘지는 않지만, 그렇게 나쁘지도 않습니다.

 

DelphiCodeToDoc(DCTD) 설치

DelphiCodeToDoc(DCTD) 실행

DelphiCodeToDoc.exe 실행 후 [New] 버튼 클릭(또는 File > New 메뉴 선택)

마법사 페이지에서 옵션 설정 및 대상 파일(또는 디렉토리) 선택 및 추가 후 [Finish]

메인화면에서 [Check and Build] 버튼 클릭(또는 Project > Check and Build 메뉴 선택)

빌드 시 CHM 도움말이 표시되고, 지정된 경로(Ouput Folder)에 지정된 포맷

 

결과 예시

DCTD에서 설정한 프로젝트 관련 내용 표시

프로젝트 이름을 한글로 설정 시 좌측 내용트리에 한글깨짐 현상이 있으나, 문서내에서는 정상출력 확인

 

프로시저에 대한 문서

@author, @version 태그 추가했지만, 문서에 표시되지 않음

웹으로 내보내기한 Unit에 대한 문서

총평

XMLDoc과 JavaDoc 주석을 추가하고 문서화 하는 내용을 살펴봤습니다.

 

XMLDoc은 주석에 XML 태그가 있어 코드내의 가독성은 떨어지지만, 헬프 인사이트에 표시된다는 장점이 있습니다.(단, 선언부에 주석을 달아야 합니다.

JavaDoc은 코드내 주석에 대한 가독성이 상대적으로 높지만, 헬프 인사이트 등으로 표시되지 않습니다.

 

문서의 결과물은 개인적으로 JavaDoc의 결과물이 더 다양하고 깔끔하다고 생각합니다.

또한 오픈소스여서 필요한 경우 직접 수정해 필요한 기능을 확장할 수 있습니다.(물론 쉽지 않습니다.)

 

위 내용을 종합적으로 판단한다면 저는 개인적으로 JavaDoc을 선호합니다. 이유는 XMLDoc은 선언부에 주석을 달아야 하기 때문에 구현부를 전체적으로 살펴볼때 JavaDoc의 주석 형식이 더 유용할 것으로 판단됩니다.

(또는 2개의 방식을 번갈아가며 사용해도 좋을 것 같습니다. 선언부는 XMLDoc, 구현부는 JavaDoc)

 

여러분들도 여러분들의 환경에 맞는 방식을 선택 해보시기 바랍니다.

 

참고로 위 방법 외에도 doxygen 등과 같은 주석 문서화하는 방법이 많습니다.

그리고 JavaDoc 주석을 문서화 하는 프로그램도 많을 것입니다.

혹시 아는 주석 문서화 방법이나 문서화 프로그램이 있다면 댓글로 알려주시면 감사하겠습니다.

 

참고 링크

험프리.김현수 Delphi/C++Builder DCTD, DelphiCodeToDoc, Javadoc, XMLDoc, 주석

[마이그레이션 사례] 워프비전(64-bit 애플리케이션)

2019.05.24 14:34

수원 영통구에 위치한 워프비전은 반도체 및 디스플레이 필름등의 검사 장비를 제공하는 업체입니다.

최근 카메라의 발전으로 이미지 해상도가 높아지고, 윈도우 10 등의 최신 운영체제 지원을 위해 마이그레이션을 진행했습니다.

워프비전 - 마이그레이션 컨설팅

  • 프로젝트 기간 : 2019년 4월(1개월)
  • 지원 방법 : 마이그레이션 컨설팅
  • 델파이 버전 : 델파이 2007 32-bit > 델파이 XE7 32/64-bit
  • 업무 범위
    • 메인 프로그램 : 2개 프로젝트(약 100여개 소스코드)
    • 컴포넌트 : 자체제작 2개, 오픈소스 2개

워프비전은 반도체 및 디스플레이 필름등의 검사 장비를 제공하는 업체로, 설비를 제어하고 관리하는 소프트웨어가 델파이로 개발되었습니다. 

 

마이그레이션 진행

워프비전은 최근 카메라의 발전으로 고해상도 이미지를 32-bit 환경에서 운용 시 메모리 부족 현상이 발생했습니다.

32-bit 프로세스에서 4GB의 메모리로 대용량 이미지 처리에 한계가 있어, 64-bit 지원으로 대용량 이미지 처리가 필요했습니다.

 

또한, 납품을 위해 구입하는 PC의 운영체제가 대부분 윈도우 10 64-bit가 설치되어 윈도우 10 대응을 위한 목적도 있고, 중국, 일본등의 고객사에게 현지언어를 지원하기 위한 멀티-바이트 문자열 지원도 하나의 이유였습니다.

 

마이그레이션 컨설팅

설비 소프트웨어 프로젝트의 경우 실질적인 소스코드의 양이 많지 않아 자체적으로 진행이 가능할 것으로 보였지만,  마이그레이션이라는 생소한 작업을 기존 업무와 병행하며 진행한다는 것이 생각보다 쉽지 않습니다.

더군다나 델파이 버전 업그레이드와 64-bit 지원 2가지를 진행해야 했기에 전문가의 도움을 받아 진행하는 것이 효과적이라 판단해 데브기어의 마이그레이션 컨설팅 프로젝트를 선택해 주셨습니다.

 

참고로, 저는 데브기어를 통해 3가지 방식으로 마이그레이션 작업을 지원합니다. 하단의 참고 항목을 확인해주세요.

 

핵심 과제

마이그레이션 작업의 핵심과제는 다음과 같습니다.

  • 델파이 버전 업그레이드
  • 64-bit 지원(32-bit와 병행 지원)
  • 자체 제작 컴포넌트 마이그레이션
  • 데이터 엑세스 컴포넌트 변경(FIBPlust > FireDAC)

작업 절차

64-bit 지원이 실질적인 핵심과제입니다. 하지만, 64-bit를 지원하는 델파이 버전으로 업그레이드가 선행되어야 합니다.

 

작업 절차는

  1. 델파이 2007(32-bit)을 델파이 XE7 32-bit로 마이그레이션
  2. 델파이 XE7 32-bit를 64-bit로 빌드 및 실행되도록 업그레이드

1차 작업에서 마이그레이션 작업을 대부분 처리하게 됩니다. 컴포넌트 전환 및 데이터 엑세스 컴포넌트 변경도 1차에서 완료됩니다.

2차 작업에서는 XE7 32-bit로 1차 완성된 결과물로 64-bit 지원하도록 작업합니다.

 

컴포넌트 전환

이 프로젝트의 특이점은 대부분의 UI 컨트롤들을 자체제작해 사용했다는 것입니다. 하지만 대부분 기본 컨트롤에 기능을 추가한 정도였습니다. 델파이 2007에서 델파이 XE7 32-bit로 마이그레이션 하는 과정에서 큰 이슈는 없었습니다.

 

그외 써드파티 컴포넌트들은 XE7을 지원하는 것들은 업그레이드 했고, 이벤트의 파라메터 데이터 타입이 변경되는 등의 작업정도로 진행했습니다.

그중 이슈는 오픈소스인 Toolbar2000의 경우 XE7을 지원하지 않았지만, 소스코드를 보유하고 있었기 때문에 소스코드를 컴파일 하며 문제가되는 부분을 직접 수정했습니다.(이후 64-bit 지원하도록 수정해 64-bit에서도 사용했습니다.)

 

 

데이터 엑세스 컴포넌트 변경

고객사는 Firebird를 DBMS로 사용했고, 데이터 엑세스 컴포넌트로 FIBPlus를 사용했지만, 내장된 데이터 엑세스 컴포넌트인 FireDAC 사용을 원했습니다.

 

reFind(마이그레이션 자동화 도구)를 이용해 컴포넌트 및 속성, 메소드등을 자동전환 하는 패턴을 직접 만들어 일괄 변경했습니다.

 

이미지 라이브러리 교체

해당 프로젝트에서는 JPEG 라이브러리로 인텔사의 IJL을 사용했습니다.

하지만 IJL은 64-bit를 지원하지 않아 다른 JPEG 라이브러리가 필요했습니다.

델파이 내장 JPEG 라이브러리인 TJPEGImage를 시도해 봤지만, 저장 시 성능이 좋지 않아 JPEG 라이브러리 검토 후 libJPEG-Turbo로 교채했습니다.

 

64-bit 지원

대부분의 코드들은 64-bit에서도 정상 동작합니다.

하지만, 일부 데이터 타입의 경우 32-bit와 64-bit의 크기가 달라 문제가 생길 수 있습니다.

이번 프로젝트의 대표적인 문제는 다음과 같습니다.

  • 포인터로 사용하는 변수가 Integer(또는 LongInt)로 선언된 경우
  • 포인터로 사용하는 변수를 Integer(또는 LongInt)로 형변환 하는 경우
  • 윈도우(또는 소켓) 핸들을 Integer 또는 LongInt로 사용하는 경우

대응방법은

  • 포인터의 경우 데이터 타입을 Pointer 또는 NativeInt로 지정
    (NativeInt의 경우 32bit에서 4Byte, 64bit에서 8Byte로 사용 됨)
  • 윈도우의 핸들의 경우 THandle로 명시적으로 데이터 타입 지정
  • 소켓 핸들의 경우 TSocket으로 명시적으로 데이터 타입 지정

참고자료

 

기타 기능 추가

VCL 스타일 적용 : http://tech.devgear.co.kr/delphi_news/414834

다국어 지원 : http://tech.devgear.co.kr/delphi_news/408214

 

마지막으로, 

최근 사용자들은 윈도우10 등의 64-bit 운영체제를 많이 사용합니다.

64-bit 운영체제 환경이라도 32-bit 애플리케이션을 개발해 배포 및 사용해도 윈도우즈의 호환성 모드로 잘 동작합니다.

많은 메모리 사용 등의 이슈가 있는 경우에 한해 64-bit 애플리케이션 개발을 검토하시기 바랍니다.

 

참고

저는 데브기어를 통해 3가지 방식으로 마이그레이션을 지원합니다.

마이그레이션 무상 컨설팅

마이그레이션 체크리스트와 가이드 문서를 제공합니다. 작성 후 메일을 보내주시면 이메일과 방문을 통해 컨설팅을 지원합니다.

 

마이그레이션 워크샵(4일)

마이그레이션을 좀 더 효과적으로 직접 진행하고 싶다면, 워크샵 과정에 참석하세요. 마이그레이션 자동화 방안, 가이드 문서 작성 등을 배우고, 혼자 해결하기 어려운 부분을 멘토링을 통해 해결해 더 쉽고, 빠르게 마이그레이션 할 수 있습니다.

마이그레이션 컨설팅(유상)

마이그레이션 시의 위험요소 파악, 전환체계(자동화 방안, 마이그레이션 가이드 작성 등) 구축 등을 경험많은 마이그레이션 전문가를 통해 진행할 수 있습니다.

  • 별도로 요청해 주세요.. : ask@embarcadero.kr

험프리.김현수 마이그레이션

[VCL] 용량이 큰 JPEG 파일 다루기 - JPEG 라이브러리 조사

2019.05.23 17:05

프로젝트 중 큰 용량의 JPEG 파일을 다룰 필요가 있어, 64-bit를 지원하는 JPEG 라이브러리를 조사한 내용 공유합니다.

 

고객사에서는 카메라에서 제공하는 이미지의 해상도가 높아짐(16384 x 29300)에 따라 64-bit 애플리케이션으로 마이그레이션을 계획했고, 성공적으로 완료했습니다.

JPEG 라이브러리

그 과정 중 검토한 JPEG 라이브러리는 다음과 같습니다.

  • TJPEGImage(VCL 내장 JPEG 라이브러리)
  • libJPEG-Turbo
  • Intel IJL / IPP(IJL 64-bit 미지원, IPP 상용)

고객사의 기존 프로젝트에서는 IJL을 이용해 JPEG을 다뤘지만, IJL은 개발이 중단되었고 64-bit를 지원하지 않아 검토 대상에서 제외되었습니다.(IPP로 통합되어 상용으로 판매 중)

 

TJPEGImage

TJPEGImage는 VCL에 내장된 라이브러리로 32-bit, 64-bit를 모두 지원합니다.

별도의 라이브러리 파일(*.dll 등)을 배포할 필요가 없고, 클래스 단위로 제공되고 매우 익숙합니다.

(단, 성능이 좋지 않다는 평가를 검색을 통해 확인하였습니다. 내부적으로 libJPEG으로 구현된 것으로 알고 있습니다.)

 

libJPEG-Turbo

libJPEG-Turbo는 SIMD 명령어를 사용해 JPEG 압축과 해제를 가속화 하는 JPEG 이미지 코덱입니다.

공식 웹사이트에서는 libJPEG 보다 2~6배 이상 빠르다고 합니다.

(크롬, 리눅스, 안드로이드 등에서 libJPEG 대신 libJPEG-Turbo를 사용)

 

델파이 연동은 아래 오픈소스들을 참고했습니다.

JPEG 라이브러리 성능 테스트

테스트 대상은 JPEG 파일 크기별 3종으로 진행했습니다.

  • 작은 사이즈(1600x1200)
  • 큰 사이즈(16384x12200)
  • 매우 큰 사이즈(16384x29300)

 

32-bit와 64-bit 애플리케이션으로 진행했습니다.(32-bit 애플리케이션에서 매우 큰 사이즈는 메모리 부족으로 진행할 수 없었습니다.)

기존 라이브러리와 비교하기 위해 32-bit에서 IJL도 진행했습니다.

 

테스트 코드는 JPEG 파일을 TBitmap으로 불러오거나 반대로 저장하도록 작성했습니다.(고객사에서 픽셀단위로 이미지 프로세싱 진행)

 

참고로, 

TJPEGImage의 Performace 속성을 jpBestSpeed로 설정했습니다. jpBestQuality로 설정 시 3~4배의 성능 차이가 발생합니다.)

JPEG 품질은 모두 75로 설정 했습니다.

테스트 환경

  • 개발도구 : 델파이 10.3.1
  • OS : 윈도우 10 64bit(MacOS의 VM위에서 운용)
  • 메모리 : 8GB

테스트 결과

JPEG 불러오기(Load)

Load 과정에서는 예상외로, TJPEGImage의 성능이 좋다는 결과를 확인했습니다.

 

32-bit 큰 이미지의 경우 libJPEG-Turbo 대비 40%(2028 : 1137) 성능향상을 확인 했습니다.

IJL과 libJPEG-Turbo은 약 10%의 성능차이를 확인할 수 있습니다.

 

64-bit 환경에서도 TJPEGImage가 libJPET-Turbo 대비 큰 이미지의 경우 30%, 매우 큰 이미지의 경우 약 17% 가량 성능이 좋은 것으로 확인했습니다.

 

JPEG 저장(Save)

저장하는 과정은 libJPEG-Turbo가 TJPEGImage 보다 속도가 빨랐습니다.

 

특히 32-bit의 큰 이미지의 경우, 유독 TJPEGImage의 성능이 매우 좋지 않은 결과가 나왔습니다.(libJPEG-Turbo 대비 약 5배의 시간 소요)

TJPEGImage의 내부 로직을 살펴본 결과 이미지의 행(Row)의 메모리를 한번에 복사하는 과정에서 시간을 많이 소요했습니다.(해결방법은 찾지 못했습니다.)

 

64-bit에서 저장은 libJPEG-Turbo가 TJPEGImage 대비 20~30% 속도가 빨랐습니다.

 

총평

JPEG 불러오기에서는 TJPEGImage가 JPEG 저장에서는 libJPEG-Turbo가 앞선 성능을 확인할 수 있었습니다.

 

문제는 32-bit 큰 이미지 저장 시 TJPEGImage가 매우 좋지 않은 성능을 보여, 최종 선택은 libJPEG-Turbo로 진행했습니다.

해당 이슈만 없다면, TJPEGImage도 좋은 선택일 것 같습니다.

 

만약, JPEG을 빠르게 다룰 필요가 있다면, 위 테스트 내용과 첨부된 테스트 코드를 이용해 여러분 환경에 맞도록 테스트 진행 후 선정해 보시기 바랍니다.

 

테스트 코드

JPEGPerformanceTest.zip
2.44MB

 

험프리.김현수 Delphi/C++Builder Delphi, JPEG, libJPEG-Turbo, TJpegImage

[FMX] 안드로이드 권한 모델 적용 방법

2019.05.17 11:25

파이어몽키로 안드로이드 앱 개발 시 장치에 접근하는 기능(예, 카메라 이용, 블루투스 이용 등) 개발 시 권한 설정이 필요합니다.

 

기존에는 Project > Options > Uses Permissions에서 필요한 권한을 설정하는 방식이었지만, 

안드로이드 API 최신버전은 런타임 시 권한을 요청하는 매커니즘으로 변경되었습니다.

 

기존의 권한 모델은 설치 시 전체 권한을 승인하는 방식이었습니다. 새로운 권한 모델은 기능 사용 시 개별 권한을 묻는 방식으로, 사용자는 기능 별 허용 및 거부가 가능해졌습니다.

기존 권한 요청 방식 새로운 권한 요청 방식

새로운 권한 요청 방식은 RAD 스튜디오 10.3 부터 적용되며, 

기존에 작성했던 안드로이드 프로젝트는 권한 요청하는 로직을 추가하도록 업데이트 해야 합니다.

 

안드로이드의 권한 요청 로직

안드로이드 권한 요청은 System.Permissions.pas에 구현된 PermissionsService.RequestPermissions 메소드를 호출하는 것으로 시작합니다.

 

다음 코드는 델파이 샘플 중 Location(Object Pascal/Mobile Snippets/Location)의 일부입니다.

procedure TLocationForm.swLocationSensorActiveSwitch(Sender: TObject);
begin
{$IFDEF ANDROID}
  if swLocationSensorActive.IsChecked then
    PermissionsService.RequestPermissions([JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION)],
      procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
      begin
        if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
          { activate or deactivate the location sensor }
          LocationSensor1.Active := True
        else
        begin
          swLocationSensorActive.IsChecked := False;
          TDialogService.ShowMessage('Location permission not granted');
        end;
      end)
  else
{$ENDIF}
    LocationSensor1.Active := False;
end;

위코드에서는 TLocationsSensor 즉, GPS 연동하는 코드 전에 안드로이드인 경우({$IFDEF ANDROD}) 위치 권한(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION)을 요청하는 코드가 추가되었습니다.

 

RequestPermissions 메소드의 파라메터는 다음과 같습니다.

procedure RequestPermissions(const APermissions: TArray<string>;
  const AOnRequestPermissionsResult: TRequestPermissionsResultEvent;
  AOnDisplayRationale: TDisplayRationaleEvent = nil); overload; virtual;

첫번째 파라메터는 요청하는 권한 문자열 배열, 두번째는 권한 요청 결과를 받아볼 수 있는 메소드, 세번째는 사용자에게 권한에 대한 안내를 할 수 있는 메소드입니다.

 

델파이 샘플의 AccessCameraApp의 코드에는 권한요청하는 로직이 다음과 같이 구현되어 있습니다.

procedure TAccessCameraAppForm.btnTakePhotoClick(Sender: TObject);
begin
  PermissionsService.RequestPermissions(
    [FPermissionCamera, FPermissionReadExternalStorage, FPermissionWriteExternalStorage],
    TakePicturePermissionRequestResult,
    DisplayRationale
  )
end;

// Optional rationale display routine to display permission requirement rationale to the user
procedure TAccessCameraAppForm.DisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc);
var
  I: Integer;
  RationaleMsg: string;
begin
  for I := 0 to High(APermissions) do
  begin
    if APermissions[I] = FPermissionCamera then
      RationaleMsg := RationaleMsg + 'The app needs to access the camera to take a photo' + SLineBreak + SLineBreak
    else if APermissions[I] = FPermissionReadExternalStorage then
      RationaleMsg := RationaleMsg + 'The app needs to read a photo file from your device';
  end;

  // Show an explanation to the user *asynchronously* - don't block this thread waiting for the user's response!
  // After the user sees the explanation, invoke the post-rationale routine to request the permissions
  TDialogService.ShowMessage(RationaleMsg,
    procedure(const AResult: TModalResult)
    begin
      APostRationaleProc;
    end)
end;

procedure TAccessCameraAppForm.TakePicturePermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
begin
  // 3 permissions involved: CAMERA, READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE
  if (Length(AGrantResults) = 3)
      and (AGrantResults[0] = TPermissionStatus.Granted)
      and (AGrantResults[1] = TPermissionStatus.Granted)
      and (AGrantResults[2] = TPermissionStatus.Granted) then
    TakePhotoFromCameraAction1.Execute
  else
    TDialogService.ShowMessage('Cannot take a photo because the required permissions are not all granted')
end;

1) 3가지 권한을 요청합니다.

2) DisplayRationale 메소드에서 필요한 권한에 대해 설명합니다.

3) 요청결과 메소드에서 권한일 모두 허용한 경우 기능을 실행합니다.

 

위에서 주의할 점은, 

권한에 대한 설명 시(DisplayRationale 메소드) 메시지 호출 후 비동기로 APostRationaleProc 메소드를 호출해야 합니다.

그리고, 권한에 대한 설명 메소드는 옵션으로 생략할 수 있습니다.

 

위 내용을 참고해 권한이 필요한 기능을 개발하는 경우 해당 기능 호출 전 권한을 요청하도록 추가 및 기존 코드를 변경하시기 바랍니다.

해당 기능은 안드로이드 앱 개발 시 적용해야 하는 기능으로, 다른 플랫폼 앱 개발 시 생략할 수 있습니다.

 

엠바카데로에서 제공하는 내용과 이미 적용된 샘플 앱의 목록은 다음 링크에서 확인할 수 있습니다.

 

다음 글들이 안드로이드 권한 모델 적용 내용이 업데이트 되었습니다.

 

험프리.김현수 파이어몽키 FMX, 권한요청, 안드로이드

[FMX][팁] 파이어몽키 버튼의 배경색상 변경하기

2019.02.20 16:37

파이어몽키 버튼(TButton)에 배경색을 입히는 작업을 안내합니다.


버튼은 배경색 관련 속성을 제공하지 않아 스타일을 변경 해 적용해야 합니다.


커스텀 스타일 변경

버튼에 우측마우스 클릭 후 [Edit Custom Style...] 메뉴를 선택 해 Style Designer 화면으로 이동합니다.


관련 스타일 검토

Structure 패널에서 추가된 스타일(Button2Style1) 선택 후 배경색 관련된 항목이 있는지 확인합니다.

background 항목의 경우 TButtonStyleObject로 배경을 이미지에서 지정하는 방식으로 직접 배경색을 지정할 수 없습니다.


배경을 지정할 컴포넌트 추가 및 설정

배경을 지정할 컴포넌트를 직접 추가합니다.

background 항목의 자식으로 Rectangle 컴포넌트를 추가합니다.


추가된 Rectangle 컴포넌트 선택 후 속성을 편집합니다.

  • Align = Client
  • Fill.Color = 원하는 색상
  • Opacity = 원하는 투명도
  • HitTest = False(클릭이 되지 않도록)
추가된 스타일(Button2Style1 등)의 StyleName 속성도 알아보기 좋게 변경합니다.(예> BlueButton, RedButton)

Style Designer의 툴바 가장 오른쪽의 Apply style 버튼을 클릭해 적용합니다.

버튼 스타일 적용
다시 폼 디자이너로 돌아와 버튼의 스타일을 지정합니다.



버튼 선택 후 StyleLookup 속성을 보면 앞에서 추가한 스타일을 선택할 수 있습니다. 스타일은 여러개의 버튼에 동일하게 적용할 수 있습니다.



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

[FMX][팁] 파이어몽키 TComboBox 글자 크기 변경

2019.02.20 16:18

파이어몽키의 TComboBox는 TextSetting과 같은 속성을 제공하지 않아 폰트 설정이 제한됩니다.


코드를 통해 콤보박스(TComboBox)의 폰트를 설정하는 방법을 안내합니다.

다음 코드는 콤보박스의 글자크기를 20으로 변경한 예제입니다.

procedure StyleComboBoxItems(ComboBox:TComboBox; Size:Single);
var
  Item : TListBoxItem;
  i : Integer;
begin

  for i := 0 to ComboBox.Count-1 do begin
    Item := ComboBox.ListItems[i];
//    Item.Font.Family := Family; //'Arial';
    Item.Font.Size := Size; //20;
    // Item.FontColor := TAlphaColorRec.Red;
    Item.StyledSettings := Item.StyledSettings - [TStyledSetting.Size];
    // Item.Text := '*'+Item.Text;
  end;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.Add('추가 항목');
  ComboBox1.Items.Add('추가 항목');
  ComboBox1.Items.Add('추가 항목');

  StyleComboBoxItems(ComboBox1, 20);
end;


결과는 아래와 같으며, 폰트의 글꼴 및 색상 변경은 위 코드를 참고해 기능 추가하시기 바랍니다.


참고



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

[개발환경설정] 윈도우즈 환경에 Git 설치하기

2019.02.20 13:50

Git 설치

다운로드

다음 링크에서 윈도우즈 인스톨러를 다운로드합니다.


git.exe 파일을 실행해 설치를 시작합니다.


라이선스 확인

라이선스 확인 후 [Next] 버튼을 클릭합니다.

설치할 컴포넌트 선택

중요한 항목은 이미 선택되어 있으니 [Next] 버튼 클릭합니다.


기본 편집기 선택

git에서 사용할 기본 편집기 선택, 가장 편한 에디터 선택 후 [Next] 버튼 클릭


PATH 환경설정

Git 명령을 실행할 환경을 선택 아래 설명을 참고해 선택 후 [Next] 버튼 클릭

(윈도우즈 명령 프롬프트에서도 Git 명령어 실행이 필요한 경우 2번째 옵션 선택)


Use Git from Git Bash only: Git Bash(Git에서 제공하는 명령어 입력 및 실행 프로그램)에서만 Git 명령어 수행

Git from the command line and also from 3rd-party software: 명령어(Git Bash와 명령 프롬프트커맨드라인)와 써드파티 소프트웨어에서 git을 사용할 수 있도록 (안전한)경로 추가

Use Git and optional Unix tools from the Windows Command Prompt: 윈도우 명령 프롬프트에서 Git과 유닉스 도구를 모두 사용

경고: 이것은 윈도우의 "find"와 "sort"와 같은 도구보다 우선함. 이 옵션은 영향을 알고 있는 경우에 한해 사용 할 것


SSH 프로그램 선택

Use OpenSSH(Git과 함께 제공하는 ssh.exe 사용) 선택 후 [Next] 버튼 클릭


HTTPS 연결 라이브러리 선택

Use the OpenSSL Libray(OpenSSL 라이브러리를 통해 인증서 검증) 선택 후 [Next] 버튼 클릭


Line ending 스타일 선택

첫번째 항목 선택 후 [Next] 버튼 클릭


Checkout Windows-style, commit Unix-style line endings: Checkout 시 윈도우 스타일, Commit 시 유닉스 스타일로 적용 

Checkout as-is, commit Unix-style line endings: Checkout 시 그대로, Commit 시 유닉스 스타일로 적용 

Checkout as-is, commit as-is: Checkout, Commit 둘다 그대로 사용, 크로스 플랫폼 프로젝트에서 이 옵션 사용하지 않는 것이 좋음


Git Bash의 터미널 에뮬레이터 선택

Use MinTTY 선택 후 [Next] 버튼 클릭


기타 옵션 선택

필요 옵션 선택 후 [Install] 버튼 클릭 해 설치



Enable file system caching: 파일 시스템 데이터를 메모리 캐쉬해 성능 향상

Enable Git Credential Manager: Github 등에 대한 다중 인증 지원을 위해 Git Credential Manager 활성화

Enable symbolic links: 심볼릭 링크 활성화


설치 완료


험프리.김현수 Team Thoth/오픈소스

델파이 코드 작성 규칙

2019.01.30 13:37

데브기어에서 진행 중인 프로젝트 과정에서 사용 중인 코드작성 규칙을 공유합니다.

https://docs.google.com/document/d/1eYWWv_YJRl-FYw3FkcIaBRSzaHsL0V-zRjA2rzJsPZM



험프리.김현수 Delphi/C++Builder

이더넷 어댑터 정보((MacAddress, IP 등) 목록 알아오기

2019.01.23 16:08

윈도우에 설치된 네트워크(이더넷 어댑터) 정보를 알아오는 방법입니다.(10.3 리오에서 구현했습니다.)


uses 절에 Winapi.IPTypes, Winapi.IPHlpAPi 추가해야 합니다.

var
  I: integer;
  NumInterfaces: DWORD;
  AdapterInfo: array of TIpAdapterInfo;  // uses Winapi.IpTypes
  OutBufLen: ULONG;
begin
  GetNumberOfInterfaces(NumInterfaces); // uses Winapi.IpHlpApi
  SetLength(AdapterInfo, NumInterfaces);
  OutBufLen := NumInterfaces * SizeOf(TIpAdapterInfo);
  GetAdaptersInfo(@AdapterInfo[0], OutBufLen);

  Memo1.Lines.Clear;
  for I := 0 to NumInterfaces - 1 do begin
    if AdapterInfo[I].Description = '' then
      Continue;
    Memo1.Lines.Add(AdapterInfo[I].Description);
    Memo1.Lines.Add(AdapterInfo[I].IpAddressList.IpAddress.S);
    Memo1.Lines.Add(Format('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x',
      [AdapterInfo[I].Address[0], AdapterInfo[I].Address[1],
       AdapterInfo[I].Address[2], AdapterInfo[I].Address[3],
       AdapterInfo[I].Address[4], AdapterInfo[I].Address[5]]));
  end;

기타 정보도 TIpAdapterInfo 구조체를 통해 알아올 수 있습니다.


메모에 출력된 결과 화면


참고


험프리.김현수 Delphi/C++Builder

CEF4Delphi(크로미움 기반 웹브라우저) 컴포넌트 설치 및 실행하기

2019.01.14 17:06

REST API 관련 컨설팅 중 학습한 내용을 공유합니다.


고객사의 요청으로 VendHQ 사의 REST 서비스와 연동을 진행했습니다.

OAuth 2.0 연동 중 웹브라우저 이슈가 있어 해결방안을 공유합니다.


OAuth 2.0 인증 시 크게 3가지 단계로 진행합니다.
1) 서비스의 인증페이지에 로그인 해 인증코드를 받는다.
2) 인증코드를 이용해 엑세스 토큰을 취득한다.
3) 엑세스 토큰을 이용해 서비스에 접근한다.

이슈는 1)번 과정에서 발생했습니다.
델파이 내장 웹브라우저 컴포넌트(TWebBrowser)가 vend사의 로그인 페이지를 정상 출력하지 않아 다음 단계로 진행되지 않습니다.(vend사에서 표준을 지키지 않고 페이지를 만든것으로 예상됩니다.)

다음과 같이 스타일이 적용되지 않고, 허용 버튼(Allow Access) 클릭이 되지 않습니다.

해당 이슈는 VCL과 FMX 두가지 TWebBrowser가 동일합니다.


그래서 다른 대안으로 크롬미움 기반 웹브라우저 써드파티 컴포넌트(크로미움)를 테스트 해봤습니다.
해당 컴포넌트로는 인증 페이지가 정상 출력되고, 인증코드를 받아오는 부분까지 정상 진행되었습니다.


크로미움 기반 웹브라우저 컴포넌트 설치

CEF4Delphi는 크로미움 기반 웹브라우저 써드파티 컴포넌트로 오픈소스로 진행됩니다.

깃허브 저장소를 통해 제공하고 있습니다.

CEF4Delphi를 사용하려면 컴포넌트 설치 후 실행(및 배포) 시 크로미움 관련 라이브러리들을 함께 배포해야 합니다.


CEF4Delphi 다운로드


CEF4Delphi 깃허브 페이지에서 컴포넌트를 다운로드 합니다.(Clone or download > Download ZIP)


다운로드 받은 파일을 압축 해제 후 적절한 라이브러리 저장 경로에 이동합니다.(해당 경로의 패키지를 설치하고 델파이에 링크하게 됩니다.)


CEF4Delphi 컴포넌트 설치

델파이를 실행하고 다운로드 받은 파일들에서 .\packages\CEF4Delphi.dpk 패키지 프로젝트 파일을 엽니다.

프로젝트에서 오른쪽 마우스 클릭 후 팝업 메뉴에서 인스톨 메뉴를 선택해 설치합니다.

 


라이브러리 패스 추가

패키지 설치 후 CEF4Delpih 소스코드를 델파이 라이브러리 패스에 추가합니다.


델파이 라이브러리 화면을 표시합니다.

Tools > Options, Language > Delphi Options > Library


플랫폼을 선택 후 Library path에 CEF4Delphi 소스 디렉토리를 추가합니다.


CEF4Delphi 프로그램 실행

패키지(컴포넌트)를 정상 설치 후 데모를 실행하면 오류가 발생합니다.

내장 된 데모 중 SimpleBrowser2(.\CEF4Delphi\demos\SimpleBrowser2)를 열고 실행 시 다음과 같은 오류가 발생합니다.


오류 내용을 보면 CEF3 바이너리가 누락되었다는 내용입니다.

일반적으로 위와 같은 오류의 조치방법은 실행파일과 같은 경로 또는 시스템 패스에 해당 라이브러리들을 복사하는 방법이 있습니다.

하지만 CEF4Delphi는 소스코드 내에서 해당 경로를 지정하는 방법을 제공합니다.


CEF 바이너리 지정

SimpleBrowser2의 프로젝트 파일을 열면 다음과 같이 GlobalCEFApp 전역변수와 각종 경로를 지정하는 코드가 주석처리 되어 있습니다.

경로를 지정하는 코드의 주석을 풀고, 해당 경로에 CEF 바이너리를 넣거나 경로를 임의로 지정할 수 있습니다.


GlobalCEFApp.FrameworkDirPath := 'cef'; 경로는 실행파일과 같은 경로의 cef 디렉토리를 의미합니다.


우리는 위의 코드에서 주석 해제 후 지정한 디렉토리(.\cef)에 CEF 바이너리를 복사하도록 하겠습니다.

CEF 바이너리 다운로드

CEF4Delphi 깃허브 페이지에서 CEF 바이너리를 다운로드 제공합니다.

윈도우즈 32비트 플랫폼 애플리케이션에서 CEF 이용 시 32 bits를 다운로드 합니다.
(64비트 프로젝트 개발 시 64 bits를 다운로드 합니다.)


CEF4Delphi 컴포넌트의 경로 하위 bin 디렉토리에 다운로드 받은 파일을 압축해제 합니다.

CEF 바이너리 복사

SimpleBrowser2 데모를 컴파일하면 .\CEF4Delphi\bin 디렉토리에 실행파일이 생성됩니다.
(Project > Options > Delphi Compiler > Output directory가 "..\..\bin"으로 설정)


bin 디렉토리 하위에 cef 디렉토리를 생성합니다.


CEF 바이너리 파일 중 아래 디렉토리의 모든 파일과 디렉토리를 생성한 cef 디렉토리에 복사합니다.

  • Release\*.*
  • Resources\*.*

이후 다시 데모 프로젝트를 실행하면 오류없이 정상 실행을 확인할 수 있습니다.


배포 시에도 실행파일 하위 cef 디렉토리를 함께 배포하거나, CEF 바이너리 디렉토리를 지정해야 합니다.


관련/참고 링크



험프리.김현수 데이터 엑세스

  1. Blog Icon
    bioman

    좋은 자료 공유 감사합니다.

  2. Blog Icon

    비밀댓글입니다

  3. 다음 링크의 파일을 다운로드 받아 압축해재 후 사용하시기 바랍니다.(7zip 등의 압축프로그램을 이용해 압축해제 해보세요.)
    32bit
    http://opensource.spotify.com/cefbuilds/cef_binary_3.3626.1886.g162fdec_windows32.tar.bz2
    64bit
    http://opensource.spotify.com/cefbuilds/cef_binary_3.3626.1886.g162fdec_windows64.tar.bz2

[REST API] MAC(Message Authentication Code)/HMAC 델파이로 구현하기

2019.01.14 11:56

REST API 관련 컨설팅 중 학습한 내용을 공유합니다.


한 고객사의 요청으로 Unleashed 사의 REST 서비스와 연동을 진행했습니다.

그 과정 중 HMAC(해시 기반 메시지 인증 코드) 구현 과정을 공유합니다.


HMAC은 Unleashed 사 뿐아니라 AWS의 REST API 연동에도 사용되는 등 많은 REST 서비스에 구현되는 내용입니다.


MAC과 HMAC

먼저 MAC(Message Authenticate Code: 메시지 인증 코드)를 살펴봅니다.

(출처: https://ko.wikipedia.org/wiki/메시지_인증_코드)


MAC는 발신자(Sender)와 수신자(Receiver) 사이에 메시지 변조 여부를 확인하기 위한 메시지 인증 방식입니다.

위 그림을 통해 설명하면, 

Sender는 보내는 메시지(MESSAGE)와 지정된 키(Key)를 조합해 MAC을 만들고 메시지와 MAC을 전달합니다.

Receiver는 메시지와 MAC를 수신 후 메시지와 지정된 키를 조합해 MAC을 만들어 수신한 MAC과 비교해 데이터의 위변조를 판단할 수 있습니다.


HMAC(Hashed MAC)는 MAC Algorithm에 해쉬 함수를 적용해 암호화 하는 방식입니다.


HMAC 예시

제가 진행한 Unleashed 사는 API 요청 시 HTTP 해더에 다음 정보를 포함해야 합니다.

  • Content-Type, Accept
  • api-auth-id
  • api-auth-signature
Content-type과 Accept는 송수신 시의 데이터 포맷인 application/json을 입력하면 됩니다.
api-auth-id는 서비스 등록 시 발급받은 API ID를 입력하면 됩니다.
api-auth-signature는 HMAC을 생성해 입력해야 합니다.

서비스 제공사의 문서를 보면 HMAC-SHA256을 어떻게 만들어야 하는지 안내합니다.

위 문서 중 일부는 다음과 같습니다.

The method signature must be generated by taking the query string, and creating a HMAC-SHA256 signature using your API key as the secret key.
(메소드 시그니처는 쿼리 스트링을 가져와 API Key를 시크릿 키로 HMAC-SHA256 시그니처를 생성해야 한다.)

위에서 API 키는 서비스 등록시 발급받은 값입니다.


쿼리 스트링은 URL 중 "?" 뒤의 문자열입니다. 예를 들면

Customers?customerCode=ACME 중 customerCode=ACME가 쿼리 스트링입니다.


HMAC-SHA256은 다음과 같이 구현할 수 있습니다.

HMAC-SHA256

다음 샘플은 쿼리스트링(ProductCode=XXX)와 API Key(UNLEASHED_API_KEY: 상수)를 이용해 HMAC을 SHA256으로 시그니처를 생성해 HTTP 해더에 추가하는 내용입니다.

uses
  System.Hash,          // sha256
  System.NetEncoding;   // base64

var
  signature: string;
  param: string;
begin
  param := 'ProductCode=' + AProductCode;

  // PHP: base64_encode(hash_hmac('sha256', $request, $key, true));
  signature := TBase64Encoding.Base64.EncodeBytesToString(
                  THashSHA2.GetHMACAsBytes(param, UNLEASHED_API_KEY, SHA256));

  RESTRequest1.Params.AddItem('api-auth-id', UNLEASHED_API_ID, pkHTTPHEADER);
  RESTRequest1.Params.AddItem('api-auth-signature', signature, pkHTTPHEADER, [poDoNotEncode]);
end;


추가 학습할 내용

HMAC 인증외에 OAuth 2.0 인증도 많이 사용됩니다.

다음 글을 통해 OAuth 2.0을 통해 카카오 API에 연동하는 내용을 살펴볼 수 있습니다.

다음 글들을 통해 REST API를 이해하고 실습할 수 있습니다.

험프리.김현수 데이터 엑세스

OAuth 2.0 연동 - 카카오 API(카카오톡 프로필)

2018.12.20 01:35


이 글에서는 OAuth 2.0을 이용해 카카오 API와 연동하는 방법을 델파이를 통해 알아봅니다.

이 글을 통해 카카오톡 프로필 정보와 사진을 델파이 애플리케이션에서 불러오는 예제를 작성할 수 있습니다.


OAuth 2.0

API(또는 서비스) 이용 시 인증(Authentication)과 리소스(제공 서비스)에 대한 권한부여(Authorization)는 필수사항입니다. 인증과 권한부여의 대표적인 방법 중 하나가 OAuth입니다.


OAuth는 서버와 클라이언트 사이에 인증을 완료 시 권한부여의 결과로 엑세스 토큰(Access Token)을 발급하고, 이 엑세스 토큰을 이용해 클라이언트는 API(또는 서비스)에 접근 및 서비스를 요청하게 됩니다. 서버는 엑세스 토큰 기반으로 서비스와 권한에 대한 접근 여부를 판단해 데이터를 제공합니다.


OAuth는 현재 2.0 버전을 제공하며, 카카오, 구글, 페이스북에서 OAuth 2.0을 통해 서비스에 대한 인증 및 권한부여를 사용하고 있습니다.


OAuth 2.0에 대한 내용은 자세한 내용은 이 글의 하단 "관련/참고 링크"를 통해 알아볼 수 있습니다.


OAuth 2.0 사용 시 API 인증 흐름

다음 그림은 카카오 API 서비스에 접근하기 위해 OAuth 2.0 인증의 흐름을 7 단계로 나타냅니다.

0, 카카오 서비스를 이용하려면 사전에 앱을 등록 후 앱의 API 키를 발급받아야 합니다.


1, 카카오 서비스에 접근하기 위해 카카오 로그인 페이지를 웹브라우저에 표시합니다.


2, 사용자는 로그인 페이지에 ID, 비밀번호를 입력해 인증을 요청합니다.


3, 카카오 인증서버는 사용자를 인증하고 사용자 인증완료 페이지로 리다이렉션합니다. 이때 인증 코드를 함께 전달합니다.


4, 애플리케이션은 리다이렉션 URL을 분석해 인증코드를 획득합니다.


5, 애플리케이션은 카카오 인증서버에 제대로 인증된 사용자인지 확인 요청을 합니다.


6, 카카오 인증서버는 인증된 사용자임을 확인하고, 엑세스 토큰(Access Token)을 발급합니다.


7, 애플리케이션은 발급받은 엑세스 토큰을 이용해 카카오 API 서버에 접근합니다.



델파이로 OAuth 2.0 구현

위의 API 흐름을 카카오 OAuth와 카카오톡 프로필과 연동하는 과정을 델파이를 통해 구현해봅니다.


다음과 같은 데모를 구현합니다.


구현 과정은 크게 준비 + 3단계로 구분됩니다.

[준비] 카카오 서비스에 앱 등록 및 API 키 발급

[1단계] 인증페이지에 로그인 해 인증코드 취득

[2단계] 인증코드로 엑세스 토큰 취득

[3단계] 엑세스 토큰으로 서비스 접근


[준비] 앱 등록 및 API 키 발급

카카오 서비스를 이용하기 위해서는 사전에 앱을 등록 후 API 키를 발급받는 과정이 필요합니다.
다음 링크를 방문해 앱을 생성하고, REST API 키를 획득합니다.

앱 만들기

앱 이름을 입력하고 [앱 만들기] 버튼을 클릭합니다.

앱을 생성하면 다음 그림과 같이 키가 생성됩니다. 우리는 REST API 키를 사용할 것이므로 REST API 키를 복사해 보관해 둡니다.

하단의 설정 링크를 눌러 상세 설정화면으로 이동합니다.


플랫폼 추가

기본 정보 화면에서 [플랫폼 추가] 버튼을 누릅니다.


웹을 선택하고, 여러분들의 사이트 도메인을 입력합니다. [추가] 버튼을 누릅니다.


사이트 도메인과 Redirect Path를 확인 후 [저장] 버튼을 누릅니다.

사이트 도메인 + Redirect Path(저의 경우 http://hjf.pe.kr/oauth)는 실제 존재하는 페이지를 지정해야 합니다.

이 페이지는 카카오 로그인 후 리다이렉션되는 페이지로 아무 기능이 없더라도 페이지를 생성해 놔야 합니다.(페이지가 없으면 404 not found 오류가 발생합니다.)


운영하는 서비스가 없이 테스트 목적이라면 제 도메인을 등록하도록 합니다.(하지만 언제든 페이지를 삭제할 수 있으니 테스트 목적으로만 사용하시기 바랍니다.)


사용자 관리 활성화

사용자 관리 메뉴로 이동 후, 사용자 관리를 활성화 합니다. 

우리는 카카오 프로필 정보에 접근할 것이므로 프로필 정보 하단의 수집목적을 적절히 입력하고, [설정] 버튼을 클릭합니다.


앱 등록 및 API 키 발급 과정이 완료되었습니다.


[준비] 프로젝트 생성 및 화면 구성

이 예제는 델파이 10.3 리오 버전을 이용해 작성되었습니다. XE5이후 버전에서 문제가 없을것으로 생각됩니다. 다른 버전으로 진행 시 문제가 있다면 댓글을 통해 문의 주시기 바랍니다.

이 예제는 Multi-device Application(FMX 프레임워크)로 작성합니다. VCL Form Application으로 진행 가능하지만, 일부 속성 및 메소드, 이벤트에 차이가 있을 수 있습니다.

File > New > Multi-Device Application 메뉴를 선택 후 Blank Application을 선택 해 프로젝트를 생성합니다.

다음 화면을 참고해 화면을 구성합니다.


[1단계] 로그인 및 인증코드 취득

카카오 인증서버에 로그인 후 인증코드를 받는 과정을 개발합니다.(위의 API 인증 흐름의 1~4 단계 과정입니다.)


카카오 개발가이드 중 사용자 관리-로그인 부분의 문서를 참고해 개발합니다.


[Request]


[Response]


Request와 같이 페에지를 표시 후 사용자 로그인 성공 시 Response와 같이 redirect_url로 페이지 이동됩니다. 이때 인증 코드(authorize_code)가 함께 전달됩니다.


Button1 클릭 이벤트에 다음과 같이 코드를 입력합니다.

procedure TForm1.Button1Click(Sender: TObject);
var
  url: string;
  param: string;
begin
  Edit1.Text := '';

  url := 'https://kauth.kakao.com';
  param := '/oauth/authorize?client_id={app_key}&redirect_uri={redirect_uri}&response_type=code';
  param := param.Replace('{app_key}', API_KEY);
  param := param.Replace('{redirect_uri}', 'http://hjf.pe.kr/oauth');

  WebBrowser1.URL := url + param;
  WebBrowser1.Navigate;
end;

API_KEY는 상수로 implementation 위에 등록했습니다.(앱 생성 시 등록한 REST API 키를 XXXXX 대신 입력합니다.)

const
  // 카카오톡 개발자 사이트에서 앱 등록 후 API키를 등록하세요.
  API_KEY = 'XXXXXXXXXXXXXXXXX';

implementation

로그인 성공 시 인증코드 수신하는 내용을 작성합니다. WebBrowser1의 OnDidFinishLoad(페이지 전환 완료) 이벤트 생성 후 다음 코드를 입력합니다.

procedure TForm1.WebBrowser1DidFinishLoad(ASender: TObject);
var
  url: string;
  code: string;
begin
  Memo1.Lines.Add('WebBrowser1DidFinishLoad' + WebBrowser1.URL);

  if Edit1.Text <> '' then
    Exit;

  url := WebBrowser1.URL;

  if Pos('code=', url) > 0 then
  begin
    code := Copy(url, Pos('code=', url) + Length('code='), Length(url));
    if Pos('&', code) > 0 then
      code := Copy(code, 1, Pos('&', code)-1);

    Edit1.Text := code;
  end;
end;

제일 첫줄은 URL을 메모에 출력하는 로그성 기능입니다.


13~20줄에서 변경된 URL 중 인증코드 파라메터("code=")가 있는 경우 인증코드 값을 가져와 Edit1.Text에 설정합니다.


[2단계] 엑세스 토큰 취득

인증코드를 받은 다음, 이를 이용해 실제로 API를 호출할 수 있는 엑세스 토큰(Access Token)을 받아오는 내용을 구현합니다.


이 부분도 카카오 개발가이드 중 사용자 관리-로그인, 사용자 토큰 받기 부분의 문서를 참고해 개발합니다.


[Request]


[Response]


위 문서와 같이 POST로 요청 후 받은 응답 값(json 포맷)에서 access_token 값을 취득해야 합니다.

이 기능은 REST Client 프레임워크를 이용해 개발합니다.


화면에 TRESTClient, TRESTRequest, TRESTResponse 3개의 컴포넌트를 추가 합니다.


[3. 엑세스 토큰 취득] 버튼의 클릭 이벤트에 다음과 같이 구현합니다.
(아래 과정은 디자인 타임에서 컴포넌트에 직접 설정해도 무관합니다.)

procedure TForm1.Button2Click(Sender: TObject);
var
  token: string;
begin
  RESTClient1.BaseURL := 'https://kauth.kakao.com/';

  RESTRequest1.Resource := 'oauth/token';
  RESTRequest1.Method := rmPOST;
  RESTRequest1.Params.Clear;
  RESTRequest1.Params.AddItem('grant_type',   'authorization_code');
  RESTRequest1.Params.AddItem('client_id',    API_KEY);
  RESTRequest1.Params.AddItem('redirect_uri', 'http://hjf.pe.kr/oauth');
  RESTRequest1.Params.AddItem('code',         Edit1.Text);

  RESTRequest1.Execute;

  Memo1.Lines.Text := RESTResponse1.Content;

  if RESTResponse1.JSONValue.TryGetValue<string>('access_token', token) then
    Edit2.Text := token;
end;

개발가이드와 같이 요청 정보를 RESTClient와 RESTRequest 컴포넌트의 속성과 파라메터에 설정한 후 실행(RESTRequest1.Execute;) 후 받은 응답에서 엑세스 토큰(access_token)을 받아 Edit2.Text에 설정합니다.


엑세스 토큰을 받는 과정까지 마쳤습니다. 이제 엑세스 토큰을 이용해 카카오톡 프로필 정보에 접근해 데이터를 연동 할 수 있습니다.


[3단계] 카카오톡 프로필과 연동

엑세스 토큰을 얻었다면 카카오톡 프로필 서비스와 연동해 프로필 정보를 받아올 수 있습니다.


카카오 개발가이드 중 카카오톡-프로필요청 부분의 문서를 참고해 개발합니다.



[Request]


[Response]


위 문서와 같이 GET으로 요청 후 프로필 정보와 프로필 이미지 정보를 받아올 수 있습니다.
주의사항은 요청 시 Authorization 항목이 포함되어 권한 컴포넌트를 하나더 사용합니다.

화면에 TRESTClient, TRESTRequest, TRESTResponse, TOAuth2Authenticator 4개의 컴포넌트를 추가 합니다.


그리고, 프로필 이미지를 받기 위한 컴포넌트를 화면에 추가합니다.

[4, 카카오톡 프로필 조회] 버튼의 클릭 이벤트에 다음과 같이 구현합니다.

procedure TForm1.Button3Click(Sender: TObject);
var
  Url: string;
  Stream: TMemoryStream;
begin
  OAuth2Authenticator1.AccessToken := Edit2.Text;

  RESTClient2.BaseURL := 'https://kapi.kakao.com/';
  RESTClient2.Authenticator := OAuth2Authenticator1;

  RESTRequest2.Client := RESTClient2;
  RESTRequest2.Response := RESTResponse2;

  RESTRequest2.Resource := 'v1/api/talk/profile';
  RESTRequest2.Execute;

  Memo1.Lines.Text := RESTResponse2.Content;

  Url := RESTResponse2.JSONValue.GetValue<string>('profileImageURL');

  RESTClient3.BaseURL := Url;
  RESTClient3.Authenticator := OAuth2Authenticator1;
  RESTRequest3.ExecuteAsync(procedure
    begin
      Stream := TMemoryStream.Create;
      try
        Stream.WriteData(RESTResponse3.RawBytes, RESTResponse3.ContentLength);
        ImageControl1.Bitmap.LoadFromStream(Stream);
      finally
        Stream.Free;
      end;
    end
  );
end;

6번째 라인에서 권한 컴포넌트에 엑세스 토큰을 설정합니다.


8~17 라인에서 프로필 정보를 요청하고, 응답받은 컨텐츠 내용을 메모에 출력합니다.


19번째 라인에서 프로필 이미지 URL을 추출합니다.


21~33 라인에서는 프로필 이미지를 비동기(Async)로 받아 이미지 컨트롤에 표시합니다.


완료 및 테스트

카카오톡 프로필과 연동하는 예제 구현이 완료되었습니다.

작성한 프로젝트를 실행해 여러분의 카카오 계정을 이용해 테스트 진행할 수 있습니다.

완성된 프로젝트 파일

추가 학습할 내용

카카오 서비스 연동 및 인증(OAuth 2.0)은 REST API 기반으로 구현됩니다. 다음 글들을 통해 REST API를 이해하고 실습할 수 있습니다.
REST 클라이언트에 대한 개념을 아래 글을 통해 습득하실 수 있습니다.

관련/참고 링크


험프리.김현수 데이터 엑세스

  1. delphi7 사용중입니다.
    TRESTClient, TRESTRequest, TRESTResponse
    컴포넌트 어디에서 다운받을 수 있을까?

    처음접하는 컴퍼넌트라 도움이 필요합니다.

RFID 리더(한미IT RF Prisma) 연동하기 - 델파이에서 JAR 이용

2017.12.19 09:17

(아래 내용은 델파이 10.2 도쿄 릴리즈 1과 릴리즈 2에서 작성된 내용으로 다른 버전에서는 일부 내용이 다를 수 있습니다.)


개발 컨설팅을 통해 의뢰한 작업 중 RFID 리더 연동한 내용 공유합니다.

(3일간의 개발 컨설팅으로 RFID 리더, TMAP 연동, 원격 데이터 연동 기술을 전파하는 작업을 진행했습니다.)


RFID 리더와 연동은 제조사에서 제공하는 라이브러리(안드로이드 JAR)를 이용했습니다.

이 과정을 통해 델파이에서 JAR 파일 연동하는 내용을 확인할 수 있습니다.


RFID 리더 연동



위 영상의 RFID 리더는 RFID 태그의 값을 읽고, 바코드의 값을 읽어 안드로이드 앱에 데이터를 전달합니다.

안드로이드 앱은 장비를 구동 및 설정하고, 장비가 읽은 데이터를 받아 화면에 표시합니다.


안드로이드 앱은 델파이(파이어몽키)를 이용해 개발했으며, 장비와 연동하는 부분은 제조사에서 제공한 JAR 형태의 라이브러리를 이용했습니다.


델파이에서 JAR 파일 연동 과정은 아래와 같습니다

1, 작업 준비

2, 델파이용 JAR 브릿지 파일 생성

3, 델파이 프로젝트에 JAR 파일 추가

4, 브릿지 파일로 JAR 연동 코드 작성


기타  참고사항

 - 안드로이드 연동 시 참고사항

 - 프레임을 이용해 재사용 가능한 화면 제작

샘플 프로젝트


작업 준비

대상 장비 - 한미IT RF Prisma


한미IT RF Prisma

제품 링크 : http://www.hanmiit.co.kr/hanmiit/handler/Main-Start


제품 문의

한미IT영업 임상기과장 skyoflsk@hanmi.co.kr


라이브러리 준비 및 분석

위 제품 링크 페이지에서 SDK Download 메뉴를 이용해 SDK 관련 파일을 제공합니다.

(안드로이드, iOS, 윈도우용 라이브러리를 제공합니다. 이글에서는 안드로이드 라이브러리만 다룹니다.)


다운로드 받은 압축파일에는 SDK 파일과 문서, 샘플이 포함되어 있습니다.

(앱스토어에서 RFPrisma로 검색 해 샘플 앱을 설치할 수 있습니다.)

문서와 샘플을 통해 제공하는 기능을 확인하고, 대략적인 사용법을 익히도록 합니다. 특히 라이브러리를 호출하는 부분은 정확히 숙지해야 합니다.


델파이용 JAR 브릿지 파일 생성

델파이에서 JAR 파일을 연동하기 위해 브릿지 파일(JAR 파일에 대한 델파이 인터페이스)을 생성해야 합니다.

브릿지 파일 생성

Java2OP.exe를 이용 델파이 브릿지 파일을 생성합니다. Java2OP는 JAR 파일 또는 Java 소스파일을 호출할 수 있는 델파이 코드를 생성합니다.(참고: 파이어몽키에서 외부 라이브러리 연동하기(jar. so, a))


아래 커맨드를 이용 브리지 파일(Androidapi.JNI.rfidreaderapi.pas)을 생성합니다.
set path=%PATH%;"c:\Program Files (x86)\Embarcadero\Studio\19.0\bin\converters\java2op"

java2op -jar ..\SDK\rfid.reader.api.jar -unit Androidapi.JNI.rfidreaderapi
위 코드를 명령 프롬프트에서 바로 입력 및 실행하거나, 배치파일(*.bat)로 실행할 수 있습니다.
(*.jar 파일의 경로를 상대경로로 입력 시 주의하시기 바랍니다. 절대경로를 이용해도 됩니다.)

델파이 프로젝트에 JAR 파일 추가

라이브러리 추가

멀티-디바이스 애플리케이션(파이어몽키) 프로젝트에서 타겟 플랫폼을 안드로이드로 설정 후 트리를 펼쳐 Libraries 항목에 JAR 파일을 추가해야 합니다.

델파이 브릿지 파일 추가

JAR와 연동하기 위해 델파이 브릿지 파일(Androidapi.JNI.rfidreaderapi.pas)을 프로젝트에 추가합니다.

브릿지 파일 확인을 위해 컴파일 후 오류를 조치합니다.


만약, 컴파일 시 E2029 오류 발생 시 다음을 참고해 조치합니다.

E2029 오류 조치방법

E2029 오류는 예약어를 용도와 다른 곳에서 사용할 경우 발생합니다.

오류가 발생하는 예약어 키워드 앞에 "&"을 추가해 해결합니다.

(예> type -> &type, in -> &in)

(참고: http://tech.devgear.co.kr/delphi_qna/420082)


브릿지 파일로 JAR 연동 코드 작성

JAR와 연동하는 코드는 아래와 같이 클래스를 이용해 작성했습니다.

FMX.HanmiIT.RFIDReader.pas


구현한 내용 중 다음 내용을 살펴보겠습니다.

1, 인스턴스 메소드와 클래스 메소드 접근

2, 자바 이벤트 리스너 설정


인스턴스 메소드와 클래스 메소드 접근

RF Prisma JAR 라이브러리에는 독특하게 클래스 메소드를 많이 사용하도록 구현되어 있습니다.


연동 시 델파이 클래스(TJATRfidManager)는 클래스 인터페이스(JATRfidManagerClass)와 인스턴스 인터페이스(JATRfidManager) 쌍으로 이뤄집니다. 

클래스 인터페이스(JATRfidManagerClass)는 객체를 생성하기 전의 클래스를 통해 접근하는 함수, 속성, 상수를 제공합니다. 자바코드를 사용하는 경우 "델파이클래스명.JavaClass.클래스메소드" 형식으로 JavaClass 속성을 통해 자바 클래스에 접근해야 합니다.

인스턴스 인터페이스(JATRfidManager)는 객체 생성 후 사용가능한 인스턴스 함수와 속성 상수를 제공합니다.

이 라이브러리에는 객체(JATRfidReader 등) 생성 시 아래와 클래스 메소드를 이용합니다. 해당 객체의 추가 기능은 인스턴스 메소드로 제공합니다.
var
  FReader: JATRfidReader;
...
  FReader := TJATRfidManager.JavaClass.getInstance;

  FReader.setEventListener(FEventListener);
  FReader.connectDevice(StringToJString(AAddress));
  FReader.setStoredMode(Value);
  FReader.setReportMode(Value);

자바 이벤트 리스너 설정

연동 시 가장 우려하던 부분입니다. RFID 태그를 읽거나 연결상태 가 변경되는 등 장비에서 동작해 발생하는 이벤트 정보를 리스너(JATRfidEventListener)를 통해 앱에서 받습니다.


리스너 구현시 메인 클래스(TRfidReader)에서 바로 리스너 인터페이스를 위임받아 구현해도 되지만, 복잡해 지기 때문에 별도의 클래스에서 이벤트 리스너를 구현하고 필요한 정보만 받도록  분리해 구현했습니다.


이벤트 리스너 구현 선언부

type
  TRfidEventListner = class(TJavaLocal, JATRfidEventListener)
  private
    FHandler: IRfidEventHandler;
  public
    constructor Create(AHandler: IRfidEventHandler);

    { JATRfidEventListenerClass }
    procedure onAccessResult(P1: JATRfidReader; P2: Jtype_ResultCode; P3: JActionState; P4: JString; P5: JString; P6: Single; P7: Single); cdecl;
    procedure onActionChanged(P1: JATRfidReader; P2: JActionState); cdecl;
    procedure onCommandComplete(P1: JATRfidReader; P2: JCommandType); cdecl;
    procedure onDebugMessage(P1: JATRfidReader; P2: JString); cdecl;
    procedure onDetactBarcode(P1: JATRfidReader; P2: JBarcodeType; P3: JString; P4: JString); cdecl;
    procedure onLoadTag(P1: JATRfidReader; P2: JString); cdecl;
    procedure onReadedTag(P1: JATRfidReader; P2: JActionState; P3: JString; P4: Single; P5: Single); cdecl;
    procedure onRemoteKeyStateChanged(P1: JATRfidReader; P2: JRemoteKeyState); cdecl;
    procedure onStateChanged(P1: JATRfidReader; P2: JConnectionState); cdecl;
  end;

위와 같이 JTARfidEventListener 인터페이스를 위임받고, 해당 인터페이스의 함수를 정의합니다.


주의할 사항은 Create 메소드의 파라메터로 IRfidEventHandler 인터페이스를 받아 FHandler에 저장하도록 구현합니다.


델파이 이벤트 인터페이스 선언부

IRfidEventHandler는 아래와 같이 필요한 메소드만 정의했습니다. 특히 파라메터는 사용하기 편하도록 델파이 자료형으로 재정의 했습니다.

type
  IRfidEventHandler = interface
  ['{FFEB910C-3BB8-48CA-BE11-B09CC07E53AC}']
    // Rfid Reader
    procedure ReadedTag(AReader: JATRfidReader; ATag: string);
    procedure StateChagned(AReader: JATRfidReader; AState: TConnectionState);

    // Barcode
    procedure ActionChagned(AReader: JATRfidReader; AState: TActionState);
    procedure DetactBarcode(AReader: JATRfidReader; ABarcodeType, ACodeId, ABarcode: string);
  end;


메인 클래스에서 델파이 이벤트 인터페이스 위임
위 인터페이스는 메인 클래스에서 위임받았고, 이벤트 핸들러 생성 시 파라메터로 전달합니다.
그리고, FReader 객체에 이벤트 리스너를 설정(setEventListener)합니다.
type
  TRFIDReader = class(TInterfacedObject, IRfidEventHandler)
...
procedure TRFIDReader.InitReader;
begin
...
  FEventListener := TRfidEventListner.Create(Self);
...
  FReader := TJATRfidManager.JavaClass.getInstance;
  FReader.setEventListener(FEventListener);
end;

이벤트 발생 시 델파이 이벤트 인터페스를 통해 전달
JATRfidEventListener에서 이벤트 발생 시 IRfidEventHandler에 이벤트를 전달하도록 구현했습니다.
procedure TRfidEventListner.onStateChanged(P1: JATRfidReader;
  P2: JConnectionState);
var
  State: TConnectionState;
begin
  if Assigned(FHandler) then
  begin
    State := TConnectionState.Disconnected;
    if P2.getState = TJConnectionState.JavaClass.Connected.getState then
      State := TConnectionState.Connected
    else if P2.getState = TJConnectionState.JavaClass.Connecting.getState then
      State := TConnectionState.Connecting
    else if P2.getState = TJConnectionState.JavaClass.Listen.getState then
      State := TConnectionState.Listen
    ;

    FHandler.StateChagned(P1, State);
  end;
end;

이후 이벤트 정보를 받은 메인 클래스에서 비지니스 로직을 수행하도록 구현합니다.

기타 참고사항

안드로이드 연동 시 참고사항

가장 좋은 참고자료는 파이어몽키에 구현된 안드로이드 연동한 내용을 참고하는 것입니다.

(델파이 정품 설치 시 설치경로 하위의 source 디렉토리에는 파이어몽키 라이브러리 소스코들이 포함되어 있습니다.)


그중 다음 소스코드들을 참고하면 아주 좋습니다.

안드로이드 SDK 브릿지 파일

기본 안드로이드 SDK 델파이 브릿지 파일이 아래 경로에 포함되어 있습니다.
  • C:\Program Files (x86)\Embarcadero\Studio\19.0\source\rtl\android - 10.2 도쿄 기준

파이어몽키 라이브러리

파이어몽키 컴포넌트와 라이브러리 등을 어떻게 구현했는지 아래 경로의 파일들에서 살펴볼 수 있습니다.

  • C:\Program Files (x86)\Embarcadero\Studio\19.0\source\fmx - 10.2 도쿄 기준


프레임을 이용해 재사용 가능한 화면 제작

일부 기능적인 화면들이 필요한데 다른 프로젝트에서도 활용할 만한 기능들이어서 재사용 가능하도록 구현해봤습니다.

libs 디렉토리에 포함된 3개의 프레임입니다.

  • FMX.UI.OverflowMenu.pas - 메인 화면의 우측 상단의 연결 팝업 메뉴 구현
  • FMX.UI.SelectBluetoothDeviceDialog.pas - 블루투스 장비를 탐색 후 장비 선택 정보 제공하도록 구현
  • FMX.UI.WaitDialog.pas - 비동기로 진행하는 블루투스 장비 연결을 기다리는 화면
프레임을 사용한 이유는 화면의 일부 영역을 표현하기 위함입니다.
프레임은 화면을 포함한 객체입니다.(Create, Destroy, Show, Hide 이벤트 등을 제공하지 않아 필요한 경우 직접 구현해야 합니다.)
화면등에서 객채 생성하는 코드를 줄이기 위해 클래스 메소드로 기능 호출하도록 구현했습니다.

클래스 메소드로 기능화면 호출
위 유닛 파일을 유즈절(uses)에 추가 후 아래와 같이 기능을 호출할 수 있습니다.
  TWaitDialog.Show('블루투스를 활성화 합니다.', 2000);

  TOverflowMenu.Settings.Top := ToolBar1.Height + 1;
  TOverflowMenu.Settings.Width := Width * 0.9;
  TOverflowMenu.Settings.RightPadding := 10;
  TOverflowMenu.ShowMenu([
      'Connect to last bluetooth device',
      'Connect to new bluetooth device'],
    procedure(AIndex: Integer; AText: string)
    begin
      case AIndex of
        0: ConnectToLastDevice;
        1: ConnectToNewDevice;
      end;
    end);

자세한 별도의 글을 통해 소개하도록 하겠습니다.(그 전에는 직접 소스코드를 통해 내용을 확인하시기 바랍니다.)

기타 궁금한 내용은 댓글 또는 http://blog.hjf.pe.kr/482의 댓글을 참고하거나 등록해 주세요.


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

  1. 블루투스 바코드 스캐너(BI-07) 안드로이드 라이브러리를 델파이에서 연동하는 방법( http://blog.hjf.pe.kr/452 )도 참고하시기 바랍니다.

  2. Blog Icon
    주만지

    와와와.. 저희 회사도 rfid 연동하는데 시간 날때 한번 해봐야 겠어여
    한국엔 라드 자료가 많이 없는데 우연히 구글링하다 들어와서 잘 보고 갑니다^^*
    네이버라면 친추하겠는데,,ㅠ
    혹시 가끔 모르는 거 들어와서 여쭤 봐도 될까요? ㅋ

WaitDialog 구현 - 재사용 가능한 프레임 구현하기

2017.12.06 13:36

얼마전 진행한 모바일 개발 컨설팅에서 블루투스 장비와 연결 후 기다리는 동안 표시할 화면이 필요했습니다.

WaitDialog라는 화면을 만들었는데 이 화면은 앞으로도 많이 사용하게 될 것 같아 TFrame을 이용해 재사용 가능하도록 구현해 봤습니다.


WaitDialg 구현에 아래 기술을 사용했습니다.

1) TFrame

2) 클래스 메소드

3) 싱글톤 패턴


이 내용을 학습하면

1) 자주 사용하는 화면을 프레임으로 제작 해 재사용 할 수 있습니다.

2) 클래스 메소드를 활용해 코드를 짧게 사용 할 수 있습니다.

결과화면

결과 화면은 아래와 같습니다.


구현한 내용

화면구성

파이어몽키 프레임을 이용해 WaitDialog 화면을 구성했습니다.

파이어몽키에서 TFrame은 폼디자이너에서 화면을 구성할 수 있는 객체입니다. UI 컴포넌트와 논비주얼 컴포넌트를 화면에 추가하고 사용할 수 있습니다.


WaitDialog 코드

type
  TWaitDialog = class(TFrame)
    rctBackground: TRectangle;
    lytMessage: TLayout;
    rctMessageBG: TRectangle;
    lblMessage: TLabel;
    AniIndicator1: TAniIndicator;
    Timer: TTimer;
    procedure TimerTimer(Sender: TObject);
  private
    class var FInstance: TWaitDialog;
  private
    { Private declarations }
  public
    { Public declarations }
    destructor Destroy; override;

    class procedure Show(ATitle: string = ''; ATimeout: Integer = -1);
    class procedure Hide;
  end;

implementation

{$R *.fmx}

{ TFrame1 }

class procedure TWaitDialog.Show(ATitle: string; ATimeout: Integer);
begin
  if not Assigned(FInstance) then
    FInstance := Create(nil);

  FInstance.Parent := Application.MainForm;
  FInstance.Align := TAlignLayout.Client;
  FInstance.BringToFront;
  FInstance.Visible := True;

  if ATitle <> '' then
  begin
    FInstance.lblMessage.Text := ATitle;
  end;

  if ATimeout > 0 then
  begin
    if ATimeout < 1000 then
      ATimeout := 1000;
    FInstance.Timer.Interval := ATimeout;
    FInstance.Timer.Enabled := True;
  end;
end;

class procedure TWaitDialog.Hide;
begin
  if not Assigned(FInstance) then
    Exit;
  FInstance.Visible := False;
  FInstance.DisposeOf;
end;

procedure TWaitDialog.TimerTimer(Sender: TObject);
begin
  Timer.Enabled := False;
  Hide;
end;

destructor TWaitDialog.Destroy;
begin
  FInstance := nil;

  inherited;
end;

initialization
finalization
  TWaitDialog.Hide;

클래스 메소드

WaitDialog를 보여주고 감추는 메소드(Show, Hide)를 클래스 메소드(class procedure, class function)로 구현했습니다.

클래스 메소드는 클래스를 생성하기 전에 호출할 수 있는 메소드로 Create 등이 대표적인 클래스 메소드입니다.


클래스 메소드를 사용한 이유는 WaitDialog를 호출하는 측의 코드를 최대한 짧게 작성할 수 있도록 하기위해서 입니다.


싱글톤 패턴

클래스 메소드를 사용 후 객체를 생성하기 위해 클래스 변수(class var)를 사용했습니다. 


객체 생성은 Show 메소드에서, 객체 해제는 Hide 메소드에서 합니다. Hide 시키지 않고 앱을 종료하는 경우를 대비 finalization에서 Hide 메소드를 호출 합니다.


싱글톤 패턴은 프로그램 내에서 객체를 하나만 생성하는 디자인 패턴입니다. 위 예제에서 객체는 하나만 생성합니다.

만약, 다른 곳에서 싱글톤 객체가 필요하다면 아래와 같은 코드를 추가할 수 있습니다.

class function TWaitDialog.Instance: TWaitDialog; begin if not Assigned(FInstance) then FInstance := Create; Result := FInstance; end; class procedure TWaitDialog.ReleaseInstance; begin if Assigned(FInstance) then FInstance.DisposeOf; end; initialization finalization TWaitDialog.ReleaseInstance;

위와 같이 구현하면 TWaitDialog.Instance를 이용해 접근하면 객체를 유일하게 사용할 수 있습니다.(너무 멀리까지 나갔네요.^^)

사용방법

uses FMX.WaitDialog;

  TWaitDialog.Show;
  TWaitDialog.Show('잠시만 기다려 주세요.');
  TWaitDialog.Show('잠시만 기다려 주세요.', 10000);

  TWaitDialog.Hide;

uses 절에 유닛을 추가하고, Show 클래스 메소드를 다양한 방식으로 호출해 화면을 표시합니다.

비동기 동작이 완료된 경우 Hide 클래스 메소드를 호출하면 화면이 감춰집니다.


데모 프로젝트

WaitDialog.zip


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

[튜토리얼] 메일 전송(IdSMTP 이용)

2017.11.22 14:27

IdSMTP, IdMessage를 이용 메일 전송 예제


참고코드

procedure TForm2.Button1Click(Sender: TObject);
begin
  SMTP.Host := ''; // host address
  SMTP.Port := 25;

  MailMessage.From.Address := ''; // From email address
  MailMessage.Recipients.EMailAddresses := Edit2.Text;//'hskim@embarcadero.kr';

  MailMessage.Subject := Edit1.Text;
  MailMessage.Body.Text := Memo1.Lines.Text;
  MailMessage.CharSet := 'UTF-8';
  SMTP.Connect;
  SMTP.Send(MailMessage);
  if SMTP.Connected then
    SMTP.Disconnect;

  ShowMessage('');
end;

샘플 프로젝트

SendMail.zip


문단제목




험프리.김현수 Delphi/C++Builder

  1. 파일 첨부
    // uses IdAttachmentFile;
    MailMessage.MessageParts.Clear;
    TIdAttachmentFile.Create(MailMessage.MessageParts, Filename);

  2. 감사합니다 ~~~

[튜토리얼] FTP 업로드(TIdFTP 이용)

2017.11.22 14:24

IdFTP를 이용 로컬 파일을 서버로 업로드하는 예제

  • 로컬파일 선택
  • 업로드 시 프로그레스바로 진행률 표시

참고 코드

procedure TForm2.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
    Edit1.Text := OpenDialog1.FileName;
end;

procedure TForm2.Button2Click(Sender: TObject);
var
  LocalPath, RemotePath: string;
begin
  LocalPath := Edit1.Text;
  RemotePath := 'test/' + ExtractFileName(LocalPath);

  IdFTP1.Host := 'hjf.pe.kr';
  IdFTP1.Port := 21;
  IdFTP1.Passive := True;
  IdFTP1.Username := '';  // FTP user
  IdFTP1.Password := '';  // FTP password
  IdFTP1.Connect;

  IdFTP1.Put(LocalPath, RemotePath);

  IdFTP1.Disconnect;
end;

procedure TForm2.IdFTP1Work(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin
  ProgressBar1.Position := AWorkCount;
end;

procedure TForm2.IdFTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Int64);
begin
  ProgressBar1.Max := AWorkCountMax;
end;

샘플 프로젝트

IdFTPUpload.zip


문단제목





험프리.김현수 Delphi/C++Builder

  1. Blog Icon
    SquareRoot

    Put으로 파일 전송할 경우 ftp에서 내려 받았을때 파일이 깨지는데 어떡게 해야될까요.

    zip 파일 업로드 해봤는데 받아보니 손상된 파일이라네요.

델파이/C++빌더에 TTcpClient, TTcpServer, TUdpSocket 등록하기

2017.11.02 14:30

TTcpClient, TTcpServer, TUdpSocket 컴포넌트 들이 어느 버전에서 부터인지 모르지만, 기본 컴포넌트에서 빠져있습니다.


위 3개 소켓 컴포넌트를 등록하는 방법을 안내합니다.

(이 글은 RAD Studio 10.2 도쿄 버전을 기준으로 안내합니다.)


1, 윈도우 탐색기로 열고 다음 경로(기본 샘플 경로)로 이동합니다.

C:\Users\Public\Documents\Embarcadero\Studio\19.0\Samples\Object Pascal\VCL\InetWinSockets


2, RAD Studio에서 "inetwinsockets.dpk" 프로젝트를 엽니다.


3, 프로젝트 매니저의 팝업 메뉴에서 Install 메뉴를 선택 해 설치합니다.


4, 델파이 라이브러리 패스에 위 경로를 추가합니다. 

(또는 "Web.Win.Sockets.pas"를 델파이 라이브러리 패스에 포함된 곳에 복사합니다.)


5, 툴팔렛트의 "Internet" 카테고리에 컴포넌트 추가를 확인합니다.


만약, 컴포넌트 추가 후 컴파일 시 "Web.Win.Sockets" 유닛을 찾을 수 없다면 4 단계(라이브러리 패스에 추가)를 검토하시기 바랍니다.


관련링크







험프리.김현수 분류없음

안면인식(Face Detection) 라이브러리(안드로이드, iOS)

2017.10.30 15:02

델파이 개발 그룹인 grijjy 팀(블로그: https://blog.grijjy.com/)에서 안면인식(Face Detection) 라이브러리를 공개했습니다.


이 라이브러리리는 안드로이드와 iOS에 내장된 사진에서 얼굴을 감지하는 기능을 이용해, 하나의 라이브러리로 제공합니다.


안면인식 기술 개발이 필요하거나, 여러 플랫폼 기능을 하나의 라이브러리로 개발하고자 하는 경우 참고하면 아주 좋습니다.


안면인식(안드로이드, iOS)

  • https://blog.grijjy.com/2017/09/11/face-detection-on-android-and-ios/


험프리.김현수 Delphi/C++Builder

TTS(Text-to-Speech) 라이브러리(윈도우, 맥OS, iOS, 안드로이드)

2017.10.30 14:52

델파이 개발 그룹인 grijjy 팀(블로그: https://blog.grijjy.com/)에서 문자를 읽어주는 TTS(Text-to-speech) 라이브러리를 공개했습니다.


이 라이브러리는 윈도우, 맥OS, iOS, 안드로이드를 지원합니다.

(grijjy 팀에서 크로스 플랫폼 추상화 레이어 설계를 연습하기 위해 제작했으며, 각 플랫폼 API TTS 기능을 하나의 라이브러리(컴포넌트)로 제공합니다.)


해당 기능이 필요하거나, 공통된 여러 플랫폼의 API를 하나의 라이브러리(컴포넌트)로 제작하는 방법을 참고하면 아주 좋겠습니다.


Cross Platform Text-to-Speech

참고




험프리.김현수 Delphi/C++Builder