Search results for 'Firemonkey/기능제어'

  1. 2017.03.20 -- 블루투스 바코드 스캐너(BI-07) 안드로이드 라이브러리를 델파이에서 연동하는 방법
  2. 2016.09.22 -- 모바일 디바이스 화면 방향전환 이벤트 수신하기
  3. 2016.04.04 -- [OSX/맥] 맥의 스크린세이버 비활성화/활성화 시키기 (2)
  4. 2015.07.27 -- [XE8] 모바일 앱에서 클래식 블루투스를 이용해 데이터 전송하기 (2)
  5. 2015.06.26 -- [하이브리드 앱 개발] 웹페이지에서 델파이 함수 호출하기
  6. 2015.06.25 -- TWebbrowser의 "tel:, sms:" 링크가 동작하지 않는 이슈 해결방법
  7. 2015.02.12 -- [XE7] 안드로이드 블루투스 활성화 조회와 설정하기
  8. 2015.02.11 -- [XE7] 안드로이드 WiFi 상태조회와 설정하기
  9. 2014.12.03 -- [XE7] 자체적으로 원격푸쉬알림(GCM, APN) 전송 구현방법 (8)
  10. 2014.11.21 -- 안드로이드 라이브러리(jar 파일) 활용 사례(안드로이드 열기 대화상자 구현)
  11. 2014.11.10 -- [앱테더링] VCL앱을 모바일앱으로 쉽게 확장할 수 있는 앱테더링 자세히 살펴보기! (7)
  12. 2014.11.04 -- 안드로이드 기기에 설치된 앱 목록표시와 실행하기
  13. 2014.10.24 -- 웹브라우저를 지원하지 않는 플랫폼(윈도우, OS X)에서 웹브라우저 지원하기
  14. 2014.09.23 -- IoT와 RAD Studio(Bluetooth 이용)
  15. 2014.09.22 -- 병렬(패러럴) 컴퓨팅 라이브러리 소개
  16. 2014.09.12 -- [NFC] 안드로이드에서 NFC 연동 방법
  17. 2014.07.14 -- 안드로이드에서 음성인식 및 TTS(Text To Speach)
  18. 2014.07.14 -- 안드로이드 SMS 목록 얻어오기(샘플)
  19. 2014.06.19 -- 연락처(주소록)을 제어하는 방법(안드로이드, iOS) (4)
  20. 2014.05.27 -- Baas(Backend as a Service)와 RAD Studio(GCM, APN, 푸시알림 가능) (3)

블루투스 바코드 스캐너(BI-07) 안드로이드 라이브러리를 델파이에서 연동하는 방법

2017.03.20 17:03

S모전자에서 의뢰한 휴대용 바코드 스캐너와 연동한 내용 공유합니다.

휴대용 바코드 스캐너는 JAR 형태의 안드로이드 라이브러리를 제공합니다.

이 과정을 통해 델파이와 안드로이드 라이브러리 연동하는 내용을 소개합니다.


휴대용 바코드 스캐너 연동



위 영상의 휴대용 바코더 스캐너는 클래식 블루투스 기반으로 연결을 제공합니다.

해당 안드로이드 앱은 델파이로 제작했으며, JAR 파일을 이용해 스캐너와 연동합니다.


JAR 파일 연동과정은 아래와 같습니다.

1, 준비(라이브러리 준비 및 분석)

2, 델파이용 안드로이드 라이브러리 브릿지 파일 생성

3, 델파이 프로젝트에 안드로이드 라이브러리 추가

4, 브릿지 파일을 이용해 안드로이드 라이브러리 연동


기타 안드로이드 라이브러리 연동 시 참고사항

델파이 샘플 프로젝트


준비(라이브러리 준비 및 분석)

대상 장비(Point Mobile BI-07)

Point Mobile: BI-07

링크: http://www.pointmobile.co.kr/item.php?it_id=1381210470&ca_id=401010


라이브러리 준비 및 분석

안드로이드와 iOS 라이브러리를 제공합니다.
안드로이드 라이브러리(jar) : 다운로드
라이브러리 관련 문서 및 샘플 : 다운로드

대부분의 라이브러리 제공 시 연동 문서와 샘플코드를 제공합니다.

문서를 잘 숙지하고, 샘플코드를 분석합니다. 대략적으로 소스코드를 파악하되 해당 라이브러리 호출하는 부분은 정확히 숙지해야 합니다.

델파이용 안드로이드 라이브러리 브릿지 파일 생성

델파이에서 안드로이드 라이브러리를 사용하기위해 브릿지 파일을 생성해야 합니다.

브릿지 파일 생성

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

아래 커맨드를 이용해 브릿지 파일(Androidapi.JNI.PM3SDK_BI07.pas)을 생성합니다.
D:\ProjectExt\SamsungElectronics>set path=%PATH%;"c:\Program Files (x86)\Embarcadero\Studio\18.0\bin\converters\java2op"

D:\ProjectExt\SamsungElectronics>java2op -jar .\SDK\PM3SDK_connectByAddress.jar -unit AndroidapiJNI.PM3SDK_BI07
Warning: error opening ReservedWordsOP.txt
Warning: error opening ReservedWordsC.txt
Parsing xml: c:\Program Files (x86)\Embarcadero\Studio\18.0\bin\converters\java2op\bootclasses.xml
Parsing jar: D:\ProjectExt\SamsungElectronics\SDK\PM3SDK_connectByAddress.jar

D:\ProjectExt\SamsungElectronics>

생성된 결과


델파이 프로젝트에 안드로이드 라이브러리 추가

라이브러리 추가

멀티-디바이스 폼 애플리케이션(파이어몽키) 프로젝트에서 대상 플랫폼(Target Platform)을 안드로이드로 설정 후 Libraries 항목에 JAR 파일(안드로이드 라이브러리)을 추가합니다.


델파이 브릿지 파일 추가

해당 라이브러리를 사용하기 위해 델파이 브릿지 파일(Androidapi.JNI.PM3SDK_BI07.pas)을 프로젝트에 추가합니다.

브릿지 파일 확인을 위해 컴파일 합니다.

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

E2029 오류 조치방법

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

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

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

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

브릿지 파일을 이용해 안드로이드 라이브러리 연동

라이브러리 연동 문서와 샘플코드를 참고해 기능을 구현했습니다.

그 중 가장 빈번히 사용되는 자바 객체 생성과 처음 구현해본 자바 핸들러 콜백함수 구현, 가장 어렵게 변환했던 자바 오브젝트로 캐스팅된 바이트 배열에서 데이터 가져오기 3가지 내용 소개합니다.

자바 객체 생성

브릿지 파일은 라이브러리에 구현된 클래스 인터페이스가 다음과 같이 구현되어 있습니다.

(BluetoothChatService 클래스)

위와 같이 자바 클래스는 2개의 인터페이스와 1개의 클래스로 정의됩니다.


JBluetoothChatServiceClass 인터페이스는 클래스 함수와 속성, 상수를 제공합니다.(생성하기 전 사용)

JBluetoothChatService 인터페이스는 인스턴스 함수와 속성, 상수를 제공합니다.(생성해서 사용)


델파이에서 자바 객체 생성은 아래와 같이 클래스.JavaClass.Init(파라메터) 형식으로 구현합니다.

var
  FChatService: JBluetoothChatService;
...
  FChatService := TJBluetoothChatService.JavaClass.init(Context, FHandler);

자바 핸들러 콜백함수 구현

바코드 스캐너에서 바코드 데이터 수신은 핸들러의 콜백함수를 통해 받습니다.

그 자바코드는 아래와 같습니다.
private final Handler mHandler = new Handler() {
}

mChatService = new BluetoothChatService(mContext, mHandler);
SendCommand.SendCommandInit(mChatService, mHandler);

델파이에서는 다음과 같이 구현했습니다.

1) 핸들러 콜백함수 정의

type
  THandleMessageEvent = procedure(msg: JMessage) of object;
  TCharServiceHandlerCallback = class(TJavaLocal, JHandler_Callback)
  private
    FOnHandleMessage: THandleMessageEvent;
  public
    function handleMessage(msg: JMessage): Boolean; cdecl;

    property OnHandleMessage: THandleMessageEvent read FOnHandleMessage write FOnHandleMessage;
  end;

주의할 점은, 인터페이스(JHandler_Callback)를 상속받은 메소드(handleMessage)는 public 영역에 구현해야 합니다.

습관적으로 델파이와 같이 private 영역에 선언 시 "Segmentation fault (11)" 오류(잘못된 메모리 영역 참조)로 상당히 고생했습니다.


2) 핸들러, 콜백 객체 생성, 이벤트 연결(OnHandleMessage)

  private
    FHandler: JHandler;
    FCallback: TCharServiceHandler;

  FCallback := TCharServiceHandlerCallback.Create;
  FCallback.OnHandleMessage := ChatServiceHandleMessage;

  Context := TAndroidHelper.Context;
  Looper := TJLooper.JavaClass.getMainLooper;
  FHandler := TJHandler.JavaClass.init(Looper, FCallback);

  FChatService := TJBluetoothChatService.JavaClass.init(Context, FHandler);
  TJSendCommand.JavaClass.SendCommandInit(FChatService, FHandler);

콜백 객체 생성 후 OnHandleMessage 이벤트를 연결해 데이터를 수신합니다.

핸들러 생성 시 콜백 객체를 파라메터로 전달합니다.

핸들러 객체는 BluetoothChatService와 SendCommand 객체 생성 시 파라메터로 전달합니다.


3) 핸들러 콜백과 연결된 이벤트 발생

procedure TPointMobileBluetoothChatService.ChatServiceHandleMessage(
  msg: JMessage);
var
  DeviceName, JData: JString;
begin
  Log.d(msg.what.ToString);
  case msg.what of
  MESSAGE_STATE_CHANGE:
    ProcessHandlerStateChage;
  MESSAGE_BARCODE:
    ProcessHandlerBarcord(msg.obj, msg.arg1);
  MESSAGE_DEVICE_NAME:
    begin
      DeviceName := msg.getData.getString(StringToJString('device_name'));
      Log.d('Device name: ' + JStringToString(DeviceName));
    end;

  // 필요한 이벤트 추가 할 것
  end;
end;

스캐너 라이브러리는 바코드 정보 수신 시 핸들러 콜백과 연결된 이벤트로 데이터를 제공합니다.(이벤트가 발생합니다.)

자바 오브젝트로 캐스팅된 바이트 배열(byte[]) 데이터 가져오기

어디에서도 참고할 내용이 없어 가장 고생했던 내용입니다. 델파이 내부 구조를 분석하고 예측해서 구현했습니다.


자바에서 다음과 같이 오브젝트를 바이트 배열로 치환(캐스팅)하는 코드입니다.

byte[] BarcodeBuff = (byte[]) msg.obj;


델파이에서는 다음과 같이 구현했습니다.

function JObjectToStr(const AJObject: JObject): string;
var
  LObj: ILocalObject;
  ObjID: Pointer;
  JBytes: TJavaArray;
  JData: JString;
begin
  Result := '';

  if JStringToString(AJObject.getClass.getCanonicalName) <> 'byte[]' then
    Exit;

  if AJObject.QueryInterface(ILocalObject, LObj) = 0  then
    ObjID := LObj.GetObjectID
  else
    Exit;

  JBytes := TJavaArray(WrapJNIArray(ObjID, TypeInfo(TJavaArray)));
  JData := TJString.JavaClass.init(JBytes, 0, JBytes.Length);
  Result := JStringToString(JData);
end;

var
  Data: string;
begin
  Data := JObjectToStr(msg.obj);
end;


안드로이드 라이브러리 연동 참고사항

가장 좋은 참고자료는 파이어몽키 소스코드였습니다.


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


그중 아래 경로의 소스코드들을 참고하시기 바랍니다.(Delphi 10.1 베를린 버전 기준)


안드로이드 SDK 브릿지 파일들

안드로이드 SDK 델파이 브릿지 파일이 포함되어 있습니다. 자바 소스코드의 객체이름을 다음 경로의 소스코드들에서 찾아 필요한 경우 uses 절에 추가 후 사용합니다.

C:\Program Files (x86)\Embarcadero\Studio\18.0\source\rtl\android

파이어몽키 라이브러리

다음 경로 중 FMX.AddressBook.Android.pas과 같이 Android가 포함된 파일들을 참고하기 바랍니다.

위 안드로이드 SDK 브릿지 파일들을 이용한 코드들로 구현되어 있습니다.

C:\Program Files (x86)\Embarcadero\Studio\18.0\source\fmx



델파이 샘플 프로젝트


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

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

험프리.김현수 험프리.김현수 Firemonkey/기능제어 FMX, JNI, PointMobile, 바코드스캐너, 안드로이드

모바일 디바이스 화면 방향전환 이벤트 수신하기

2016.09.22 10:23

모바일 디바이스의 방향을 가로 또는 세로, 그리고 역방향으로 돌리는 동작을 알아낼 수 있습니다.


파이어몽키 프레임워크에서 제공하는 기능으로 TMessageManager에 구독해 이벤트를 받을 수 있습니다.

(부가적으로 이런 개발 방식을 옵저버 패턴이라고 합니다.^^)



위 스크린샷은 

1) 시작(폼생성) 시 TMessageMenager에 TOrientationChageMessage에 대해 OrientationChaged 이벤트를 구독하고

2) 종료 시 : 구독을 해지합니다.

3) 현재 스크린 방향은 IFMXScreenService.GetScreenOrientation 메소드를 통해 알아 올 수 있습니다.


자세한 내용은 아래 샘플코드를 통해 확인하세요.

델파이 10.1 베를린 버전으로 작성되었습니다.

ScreenOrientation-Berlin.zip




해당 내용은 델파이 부트캠프 - 델파이 게임 개발 소스코드를 살펴보다 발견했습니다.

델파이 부트캠프: 게임 개발 - http://community.embarcadero.com/blogs?view=entry&id=8785

델파이 게임개발 소스코드(Github) : https://github.com/EmbarcaderoPublic/DelphiArcadeGames

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

험프리.김현수 험프리.김현수 Firemonkey/기능제어

[OSX/맥] 맥의 스크린세이버 비활성화/활성화 시키기

2016.04.04 13:25

볼랜드포럼에서 무대뽀님이 남겨준 팁 공유합니다.(작업한 내용 공유해주셔서 감사합니다^^)



무대뽀님께서 맥용 애플리케이션 개잘 중 맥의 스크린 세이버를 비활성화 시키는 질문을 볼랜드포럼에 올려서 간단히 댓글을 드렸더니 멋지게 기능을 완성하셨네요.(http://firemonkey.borlandforum.com/impboard/impboard.dll?action=read&db=firemonkey_qna&no=146)


제가 작성한 답변입니다.

맥 개발자 라이브러리에 아래와 같은 샘플이 있습니다. 

https://developer.apple.com/library/mac/samplecode/SceneKitWWDC2014/Listings/Scene_Kit_Session_WWDC_2014_AAPLAppDelegate_m.html 

그 중 아래 코드를 호출하면 됩니다. 
IOPMAssertionID _assertionID; 

- (void)disableDisplaySleeping { 
    CFStringRef reasonForActivity = CFSTR("Scene Kit Presentation"); 
    IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &_assertionID); 


- (void)enableDisplaySleeping { 
    if (_assertionID) 
        IOPMAssertionRelease(_assertionID); 


위가 잠자는걸 막는 거고 아래는 막은걸 해지하는 겁니다. 

위 메소드 들은 Macapi 중 IOKit에 구현되어 있습니다.(즉 맥의 라이브러리를 이용해야 한다는 거죠.) 
아쉽게도 파이어몽키에 구현된 IOKit을 보면 구현된 API가 몇가지 안됩니다. 
(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\rtl\osx\Macapi.IOKit.pas) 

위 문서와 애플 기술문서를 참고하셔서 필요한 API를 추가하시고 호출하는 코드를 작성해 보시기 바랍니다. 
아래 애플 기술문서가 도움이 될것입니다. 
https://developer.apple.com/library/mac/documentation/IOKit/Reference/IOPMLib_header_reference/#//apple_ref/c/econst/kIOPMAssertionLevelOn 


위 내용을 참고로 Macapi.IOKit.pas에 필요한 메소드를 추가/확장했습니다.

기존의 유닛(C:\Program Files (x86)\Embarcadero\Studio\17.0\source\rtl\osx\Macapi.IOKit.pas)을 확장하기 위해서는 유닛파일(*.pas)를 복사 해 프로젝트 파일(*.dpr)과 같은 경로에 복사후 수정하면 프로젝트 파일과 같은 경로의 유닛을 먼저 참조합니다.


unit Macapi.IOKit 

... 

const 
  kIOMasterPortDefault: mach_port_t = 0; 
  kIOPlatformUUIDKey = 'IOPlatformUUID'; 

  // add 
  kIOPMAssertionLevelOff = 0; 
  kIOPMAssertionLevelOn  = 255; 
  kIOPMAssertionTypeNoDisplaySleep = 'NoDisplaySleepAssertion'; 

... 
type 
... 
function ... 
... 
function IOObjectRelease(anObject: io_object_t): kern_return_t; cdecl; external libIOKit name _PU + 'IOObjectRelease'; 

// add // AssertionID는 Uint32의 포인터형 
function IOPMAssertionCreateWithName(AssertionType : CFStringRef; AssertLevel : uint32_t; 
  AssertionName : CFStringRef; AssertionID : uint32_t) : uint32_t; cdecl; external libIOKit name _PU + 'IOPMAssertionCreateWithName'; 
function IOPMAssertionRelease(AssertionID : uint32_t) : uint32_t; cdecl; external libIOKit name _PU + 'IOPMAssertionRelease'; 


추가한 API를 사용하는 코드는 아래와 같습니다. 버튼을 눌러 비활성화/활성화 시킵니다.

TForm1 = class(TForm) 
  procedure BtnDisableClick(Sender: TObject); 
  procedure BtnEnableClick(Sender: TObject); 
private 
  FSleepAssert : UInt32; 
public 
end; 

implementation 

uses 
  Macapi.IOKit, Macapi.CoreFoundation; 

............ 
procedure TForm1.BtnDisableClick(Sender: TObject); 
begin 
  FSleepAssert := 0; 
  IOPMAssertionCreateWithName(CFSTR(kIOPMAssertionTypeNoDisplaySleep), kIOPMAssertionLevelOn, CFSTR('MyProject is Good'), FSleepAssert); 
  if FSleepAssert = 0 then 
    ShowMessage('Disable Failed!!'); 
end; 

procedure TForm1.BtnEnableClick(Sender: TObject); 
begin 
  if FSleepAssert > 0 then 
    IOPMAssertionRelease(@FSleepAssert); 
end; 

다시한번 좋은 자료 공유해 주신 무대뽀님에게 감사인사를 전합니다.

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

험프리.김현수 험프리.김현수 Firemonkey/기능제어

  1. Blog Icon
    무대뽀

    제가 Disable에만 신경쓰느라 미쳐 못봐서 실수한부분이 있었네요. 번거롭지만 다시 수정 부탁드려요 ^^;;
    function IOPMAssertionRelease(AssertionID : Pointer) : uint32_t; ... 에서
    파라메터가 Pointer가 아닌 uint32_t 입니다. ㅠ_ㅠ
    function IOPMAssertionRelease(AssertionID : uint32_t) : ... 이고
    예제의 파라메터도 @FSleepAssert가 아닌 @뺀 FSleepAssert로 수정 부탁드릴께요.

    정리된 자료들 아주 잘 보고있습니다. 정말 도움이 많이 되고있습니다.!!
    이자리에서나마 정말 고마움을 표합니다. ^^*

  2. 네. 수정했습니다.
    도움이 되셨다니 제가 감사합니다.
    무대뽀님도 정리차원에서 많은 자료 공유 부탁드립니다.

[XE8] 모바일 앱에서 클래식 블루투스를 이용해 데이터 전송하기

2015.07.27 18:16

지난 7월 24일 사물인터넷 앱 개발 with RAD Studio 교육을 진행했습니다.

교육이 끝나고 한 교육생분이  "클래식 블루투스로 데이터 전송이 잘되지 않아요."라는 질문을 받고 테스트한 내용 공유합니다.


클래식 블루투스 기능 테스트는 RAD Studio 기본 샘플 중 "Classic Bluetooth Basic app"으로 진행했습니다.

Classic Bluetooth Basic app

RAD Studio XE8 사용자는 다음 경로에서 샘플을 확인할 수 있습니다.

C:\Users\Public\Documents\Embarcadero\Studio\16.0\Samples\Object Pascal\Mobile Samples\Device Sensors and Services\Bluetooth\Classic Bluetooth Basic app


이 샘플은 다음 기능을 포함하고 있습니다.

  • 하나의 앱에서 서버(서비스 생성)와 클라이언트 역할을 모두 제공합니다.
  • 장비를 탐색하고, 페어링하고, 서비스를 탐색합니다.
  • 연결된 서비스로 데이터를 전송하고, 서비스는 데이터를 수신합니다.

❑ 다른 서비스에 접속 시 주의할 점과 처리방법

이 샘플은 문자열 전송 서비스를 목적으로 구현되어 있습니다.(클라이언트 소켁 생성 시 문자열 전송 서비스의 GUID(상수)를 이용해서 클라이언트 소켓을 생성합니다.)

다른 서비스와 접속하도록 하려면 선택한 서비스의 GUID를 이용해 클라이언트 소켓을 생성하도록 수정해야 합니다..


위 내용을 적용하기 위해 아래와 같이 샘플 코드를 변경했습니다.


1, 선택한 서비스의 GUID를 보관하기 위한 변수 선언

서비스 콤보박스(ComboBoxService)에서 선택한 서비스의 GUID를 보관하기 위해 private 영역에 변수를 선언

FServiceGUID: string;


2, 서비스 콤보박스 변경 시 변수에 서비스 GUID 할당

ComboBoxService의 OnChange 이벤트에 선택한 서비스의 GUID를 변수에 할당하도록 구현

procedure TForm1.ComboBoxServicesChange(Sender: TObject);
var
  itemText: string;
begin
  if ComboBoxServices.ItemIndex >= 0 then
  begin
    itemText := ComboBoxServices.Items[ComboBoxServices.ItemIndex];
    FServiceGUID := Copy(itemText,
                          Pos('--> ', itemText) + Length('--> '),
                          Length(itemText));
  end;
end;


3, 선택한 서비스의 GUID로 클라이언트 소켓 생성하도록 수정

상수(ServiceGUI)로 선언된 문자열 전송 서비스 GUID 대신 선택한 서비스의 GUID로 클라이언트 소켓을 생성하도록 아래와 같이 수정

procedure TForm1.SendData;
var
  ToSend: TBytes;
  LDevice: TBluetoothDevice;
begin
  if (FSocket = nil) or (ItemIndex <> ComboboxPaired.ItemIndex) then
  begin
    if ComboboxPaired.ItemIndex > -1 then
    begin
      LDevice := FPairedDevices[ComboboxPaired.ItemIndex] as TBluetoothDevice;
      // [데브기어] 상수로 정의된 서비스 GUID 대신 ComboServices의 GUID 값으로 변경
//      DisplayR.Lines.Add(GetServiceName(ServiceGUI));
      DisplayR.Lines.Add(GetServiceName(FServiceGUID));
      DisplayR.GoToTextEnd;
      // [데브기어] 상수로 정의된 서비스 GUID 대신 ComboServices의 GUID 값으로 변경
//      FSocket := LDevice.CreateClientSocket(StringToGUID(ServiceGUI), False);
      FSocket := LDevice.CreateClientSocket(StringToGUID(FServiceGUID), False);
      if FSocket <> nil then
      begin
// 생략


테스트 환경과 결과

❑ 테스트 환경

테스트는 아래 그림과 같이 블루투스 모듈과 블루투스 모듈을 USB로 연결할 수 있는 USB-TTL 모듈을 이용해 블루투스 데이터를 ComPort로 읽어 오도록 구성했습니다.(관련 장비는 다모아 시스템(www.dma.kr)의 최낙구 대표님께서 제공해 주셨습니다.)


테스트에 사용한 모듈은 아래와 같습니다.

❑ 모바일 앱 - 블루투스 장비와 연결, 데이터 전송


블루투스 장비와 페어링

블루투스 장비와 연결하기 위해서는 페어링 과정이 필요합니다.

[Discover devices] 버튼으로 주변의 장비를 탐색하고, 탐색한 장비 선택 후 [Pair] 버튼으로 페어링 시도합니다.


이미 페어링 되어 있는 장비라면 위 과정을 생략할 수 있습니다.(위 페어링 과정은 OS에서 제공하는 페어링 기능을 이용할 수도 있습니다.)

블루투스 장비로 데이터 전송

페어링된 장비를 선택 후 [Services] 버튼을 누르면 장비에서 제공하는 서비스를 가져올 수 있고, 서비스를 선택 후 [Service Demo] 탭에서 [Send text to] 버튼으로 서비스로 문자열을 전송할 수 있습니다.

COM Port 소프트웨어

위 과정을 통해 모바일에서 전송한 데이터는 블루투스 모듈을 통해 ComPort로 데이터를 수신할 수 있습니다.




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

험프리.김현수 험프리.김현수 Firemonkey/기능제어 XE8, 블루투스, 클래식 블루투스

  1. 베를린 기준 샘플 컴파일 시 Permission Denied.
    pm에서 블루투스 권한이 하나 안들어가 있어서 다시 부여하고..
    컴파일해서 페어링, 서비스 탐색까지 확인되나
    시리얼 전송 시 Java.IOException 나옵니다.
    해당 샘플에 문제가 있어 보입니다.

    다른 아두이노, 라즈베리, AVR 같은 임베디드 단말이나 마켓에 있는 다른 앱으로는 BT와 시리얼 통신이 잘 이루어집니다.

    테스트 환경은 안드로이드 4.4.2 6.0.1 두가지 입니다.

  2. 글쎄요. 샘플에 문제가 있다고 단정지으면 답이 없어질것 같습니다.(단, 어느 지점이 문제가 있다고 정확한 지적은 발전될 수 있습니다^^)

    저도 처음 시도할때 시행착오를 많이 겪었는데요. 결과적으로 보면 페어링과 연결(GUID)이 잘못된 부분을 찾아내서 해결하니 정상 연결 및 데이터 송수신을 확인할 수 있었습니다.

    문제가 있으시다고 보시면 디버그 모드로 실행하셔서 문제를 확인하고, 문제를 해결하거나 피해가는 형태로 개발해 보시면 반드시 해결할 수 있을 겁니다.

[하이브리드 앱 개발] 웹페이지에서 델파이 함수 호출하기

2015.06.26 14:00

델파이는 성능좋은 네이티브 모바일 앱을 개발할 수 있는 개발 도구입니다.

모든 기능을 네이티브로 개발할 수 있지만, 이미 반응형 웹페이지를 갖고 있는 경우 일부 기능을 웹브라우를 통해 구현해 하이브리드 형태로 개발 할 수 있습니다.


이 경우 델파이 코드에서 웹페이지의 자바스크립트를 호출하는 방법은 웹브라우저에서 제공하는 메소드(EvaluateJavaScript)를 사용할 수 있지만, 반대로 웹브라우저에서 델파이 코드를 호출하는 방법은 잘 모르실 것 같아 샘플을 만들어 공개합니다.


이글에서는 다음 기능을 소개합니다.

  • 델파이 코드로 웹브라우저의 자바스크립트 코드 호출하기
  • 웹브라우저에서 델파이 메소드 호출하기(파라메터 포함)


기본 구성

❑ 웹페이지 구성

웹페이지(http://hjf.pe.kr/fmx/hybrid.php)의 자바스크립트 코드는 다음과 같습니다.

웹페이지에서 델파이 코드 호출은 아래와 같이 2개의 버튼으로 처리합니다..

	

❑ 델파이 앱 화면 구성


델파이에서 자바스크립트 호출하기

델파이에서 웹브라우저 안의 자바스크립트 호출은 EvaluateJavaScript 메소드를 이용합니다. 자바스크립트 함수 뿐 아니라 여러줄의 구문도 실행할 수 있습니다.

델파이 코드

델파이에서 자바스크립트의 callJSMethodFromDelphi 함수 실행

procedure TForm1.Button1Click(Sender: TObject);
begin
  WebBrowser1.EvaluateJavaScript('callJSMethodFromDelphi();');
end;

웹페이지의 자바스크립트 코드

자바스크립트는 다음과 같이 메시지 다이얼로그를 출력하도록 되어있습니다.

function callJSMethodFromDelphi(){
	alert("[JS] Call from delphi");
}

테스트 결과

EvaluateJavaScript 메소드 자세히 보기(웹브라우저 html 코드를 적용할 수 있는 LoadFromStrings 메소드도 활용도가 높습니다.)

웹페이지에서 델파이 메소드 호출하기

웹페이지에서 델파이 메소드를 호출하는 원리는 아래와 같습니다.

  1. 델파이는 웹브라우저 주소가 변경되면 이벤트를 받을 수 있다.
  2. 웹페이지에서 웹브라우저 주소를 변경할 수 있다.
  3. 웹페이지에서 주소를 http:// 형태의 페이지 주소가 아닌, 델파이 메소드를 호출하라는 사용자 포맷의 주소를 호출한다.
  4. 델파이에서 주소 변경 이벤트 발생 시 사용자포맷 주소인 경우, 주소를 분석 해 델파이 메소드를 호출한다.

❑ 델파이 파이어몽키용 웹브라우저 주소 변경 이벤트 종류

웹브라우저(TWebBrowser)의 주소변경 이벤트는 다음과 같습니다.

이벤트

 발생 조건

 OnDidFailLoadWithError

  페이지 로드 중 에러가 난 경우 발생

 OnDidFinishLoad

  페이지 로드가 완료한 경우 발생
 OnDisStartLoad  페이지 로드를 시작할때 발생
 OnShouldStartLoadWithRequest

  요청에 의해 페이지 로드를 시작할때 발생


이 데모에서는 페이지 로드 요청 시 발생하는 OnShouldStartLoadWithRequest 이벤트를 이용합니다.

(메소드 호출과정에 페이지가 로드되지 않기 때문에 OnDisStartLoad 이벤트는 발생하지 않습니다.)


❑ 웹페이지에서 델파이 메소드 호출하기

웹페이지에서 델파이 메소드 호출은 아래 자바스크립트를 호출해 동작합니다.

function callDelphiMethodFromJS(){
	window.location = "jscall://callDelphiMethodFromJS";
}

function callDelphiMethodFromJSWithParam(){
	window.location = "jscall://callDelphiMethodFromJSWithParam?Hello|1234";
}


위 자바스크립트 코드는 웹페이지 주소(window.location)를 변경하는 코드로, 사용자 포맷(jscall://)으로 주소를 변경합니다.


제가 정의한 포맷은 다음과 같습니다.(임의로 정한 규칙임으로 원하는 방식으로 정의해서 사용하기 바랍니다.)

 포맷 정의

용도 

 jscall:// 

 델파이 코드를 호출하는 주소라는 의미

 callDelphiMethodFromJSWithParam

 호출할 델파이 코드명

 ?Hello|1234

 "?" 뒤에는 파라메터를 추가합니다. 파라메터는 파이프("|")로 구분합니다.


다음으로 웹페이지에서 위 포맷으로 주소 변경 시, 델파이에서 감지해 메소드를 호출하도록 구현합니다.

❑ 델파이에서 사용자 포맷 주소 감지하고 분석하기

델파이 웹브라우저 OnShouldStartLoadWithRequest 이벤트에는 아래와 같이 구현했습니다.

procedure TForm1.WebBrowser1ShouldStartLoadWithRequest(ASender: TObject;
  const URL: string);
var
  MethodName: string;
  Params: TArray;
begin
  if ProcessMethodUrlParse(URL, MethodName, Params) then
  begin
    CallMethod(MethodName, Params);
  end;
end;


ProcessmethodUrlParse 메소드로 URL을 분석하고, 메소드 URL인 경우 메소드를 호출하는 CallMethod를 호출합니다.

메소드 URL 분석

// URL format
//  jscall://{method name}?{Param1}|{ParamN}
//  e.g> jscall://callDelphiMethodFromJSWithParam?Hello|1234
function TForm1.ProcessMethodUrlParse(AUrl: string;
  var MethodName: string; var Parameters: TArray<TValue>): Boolean;
const
  JSCALL_PREFIX = 'jscall://';
  JSCALL_PREFIX_LEN = Length(JSCALL_PREFIX);
var
  I: Integer;
  ParamStr: string;
  ParamArray: TArray;
begin
  Result := False;

  // iOS에서 특수기호(|)가 멀티바이트로 넘어옴
  AUrl := TNetEncoding.URL.Decode(AUrl);

  if AUrl.IndexOf(JSCALL_PREFIX) = -1 then
    Exit(False);

  if AUrl.IndexOf('?') > 0 then
  begin
    MethodName := AUrl.Substring(JSCALL_PREFIX_LEN, AUrl.IndexOf('?')-JSCALL_PREFIX_LEN);

    ParamStr := AUrl.Substring(AUrl.IndexOf('?')+1, Length(AUrl));
    ParamArray := ParamStr.Split(['|']);
    SetLength(Parameters, length(ParamArray));
    for I := 0 to Length(ParamArray)-1 do
      Parameters[I] := ParamArray[I];
  end
  else
    MethodName := AUrl.Substring(JSCALL_PREFIX_LEN, MaxInt);
  if MethodName.IndexOf('/') > 0 then
    MethodName := MethodName.Replace('/', '');

  Result := not MethodName.IsEmpty;
end;

❑ 분석한 메소드 호출

웹페이지에서 호출할 델파이 메소드는 아래와 같이 자바스크립트와 동일한 이름으로 작성했습니다.

procedure TForm1.callDelphiMethodFromJS;
begin
  ShowMessage('[DELPHI] Call from JS');
end;

procedure TForm1.callDelphiMethodFromJSWithParam(AStr1, AStr2: string);
begin
  ShowMessage(Format('[DELPHI] Call from JS(%s, %s)', [AStr1, AStr2]));
end;

텍스트 타입의 메소드이름으로 메소드를 호출하는 방법은 간단하게 조건문으로 호출하는 방법도 있고, RTTI를 이용해 메소드이름으로 메소드를 찾아 호출하는 방법으로도 구현할 수 있습니다.

조건문으로 메소드 호출

function TForm1.CallMethod(AMethodName: string; AParameters: TArray<TValue>): TValue;
begin
  if AMethodName = 'callDelphiMethodFromJS' then
    callDelphiMethodFromJS
  else if AMethodName = 'callDelphiMethodFromJSWithParam' then
    callDelphiMethodFromJSWithParam(AParameters[0].AsString, AParameters[1].AsString);
end;


RTTI를 이용해 메소드 호출

function TForm1.CallMethod(AMethodName: string; AParameters: TArray<TValue>): TValue;
var
  RttiCtx: TRttiContext;
  RttiTyp: TRttiType;
  RttiMtd: TRttiMethod;
begin
  RttiCtx := TRttiContext.Create;
  RttiTyp := RttiCtx.GetType(Self.ClassInfo);
  if Assigned(RttiTyp) then
  begin
    RttiMtd := RttiTyp.GetMethod(AMethodName);
    if Assigned(RttiMtd) then
      Result := RttiMtd.Invoke(Self, AParameters);
  end;
  RttiMtd.Free;
  RttiTyp.Free;
  RttiCtx.Free;
end;

테스트 결과



<주의>

안드로이드 앱의 웹브라우저에서 델파이 코드 호출 시 ERR_UNKNOWN_URL_SCHEME 오류가 발생하는 경우 다음 글을 참고해 조치하기 바랍니다.


 - http://blog.hjf.pe.kr/378


샘플 다운로드

다운로드 : 

HybridAppDemoSrc.zip



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

험프리.김현수 험프리.김현수 Firemonkey/기능제어

TWebbrowser의 "tel:, sms:" 링크가 동작하지 않는 이슈 해결방법

2015.06.25 19:31

델파이로 하이브리드 앱 개발 시 안드로이드 환경에서 전화걸기 링크(tel:)를 클릭하면 웹페이지 오류(ERR_UNKNOWN_URL_SCHEME)가 표시됩니다.

원래는 전화걸기 기능이 실행되야 합니다.


이 글은 안드로이드 하이브리드 앱에서 웹브라우저(TWebBrowser)의 전화걸기, 문자전송 등의 링크 클릭 시 해당 기능이 동작하도록 처리하는 방법을 안내합니다.


먼저 웹페이지의 구성과 증상을 살펴봅니다.

웹페이지 구성과 증상

웹페이지(http://hjf.pe.kr/fmx/hybrid.php)에는 아래와 같이 전화걸기, 문자전송, 메일 전송 링크를 제공합니다.

	[Phone number]  / 
	[Send sms]  / 
	[Send mail]


위 페이지를 안드로이드 앱의 웹브라우저에 표시하고, 전화걸기 링크를 클릭하면 다음과 같이 웹 페이지 오류가 표시됩니다.

위 오류가 발생하는 원인은 링크를 클릭하면 관련 액티비티가 처리해야 하는데 웹페이지로 인식해 웹브라우저가 분석하는데 실패하기 때문입니다.

그럼 링크 클릭 시 페이지 이동 대신 기능 액티비티를 표시하도록 수정해보니다.

파이어몽키 안드로이드 웹브라우저 소스 수정

위 링크 이슈를 해결하기 위해서는 파이어몽키 안드로이드 웹브라우저의 소스(FMX.WebBrowser.Android.pas)를 수정 해야합니다.(아래 과정은 델파이 XE8 기준으로 설명합니다. 다른 버전은 소스의 경로와 소스코드 내용 중 일부가 다를 수 있습니다.)

1, 안드로이드 소스코드 복사

아래 경로에서 안드로이드 웹브라우저 소스(FMX.WebBrowser.Android.pas)파일 복사합니다.

  • C:\Program Files (x86)\Embarcadero\Studio\16.0\source\fmx\FMX.WebBrowser.Android.pas (XE8 기준)
위 파일을 델파이 프로젝트 파일(*.dproj)과 같은 경로에 붙여넜습니다.

프로젝트 경로에 파일을 복사한 이유는 델파이 컴파일러는 프로젝트 파일의 경로의 소스파일을 우선적으로 참고해 컴파일합니다. 위 특징을 이용해 프레임워크 소스코드를 프로젝트 파일과 같은 경로에 놓고 수정하면 수정된 내용이 적용되어 컴파일 됩니다.


2, 파이어몽키 소스코드 수정

위에서 복사한 소스코드를 델파이 IDE > File > Open 메뉴로 엽니다.
그리고, shouldOverrideUrlLoading 메소드 구현부를 수정하겠습니다.

shouldOverrideUrlLoading 메소드는 웹뷰의 URL 변경 시 발생되며, URL에 따라 호스트 애플리케이션이 제어할 수 있는 기회를 주는 이벤트입니다.(안드로이드 기술문서: shouldOverrideUrlLoading)

리턴 값이 True이면 호스트가 제어하기 때문에 화면을 이동하지 않고, False이면 화면을 이동합니다.

다음 코드를 참고해 shouldOverrideUrlLoading 메소드 구현부를 수정합니다.

function TAndroidWebBrowserService.TWebBrowserListener.shouldOverrideUrlLoading(
  P1: JWebView; P2: JString): Boolean;
var
  Url: string;
  Intent: JIntent;
begin
  Url := JStringToString(P2);

  FWBService.ShouldStartLoading(Url);
  Result := False;

  // 리턴값이 True이면 페이지를 랜더링하지 않음
    // http 또는 https 인 경우 False(랜더링 함)
    // 그 외 True(렌더링 안함)  로딩을 중지 함(P1.stopLoading)
  if (Url.StartsWith('http://') or Url.StartsWith('https://')) then
    Result := False
  else
  begin
    // tel:, sms:, mailto:, geo: 등은 해당 Activity 실행
    Intent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW,
      TJnet_Uri.JavaClass.parse(P2));
    try
      SharedActivity.startActivity(Intent);
      Result := True;
    except
    end;
  end;

  // 렌더링 안하므로 로딩 중지
  if Result then
    P1.stopLoading;
end;

3, 테스트

위와 같이 수정하고 빌드 후 전화번호 링크를 클릭하면 아래와 같이 관련된 기능이 동작합니다.


참고 글



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

험프리.김현수 험프리.김현수 Firemonkey/기능제어

[XE7] 안드로이드 블루투스 활성화 조회와 설정하기

2015.02.12 09:39

일본인 개발자인 山本隆(야마모토 타카시)의 글을 참고해 안드로이드에서 블루투스 활성여부 조회와 설정하는 내용을 공유합니다.

블루투스 활성여부 조회

uses
  Androidapi.JNI.Bluetooth;

procedure TForm2.Button1Click(Sender: TObject);
var
  Adapter: JBluetoothAdapter;
begin
  Adapter := TJBluetoothAdapter.JavaClass.getDefaultAdapter;
  if Adapter.isEnabled then
    ShowMessage('Bluetooth가 활성화 되어있습니다.')
  else
    ShowMessage('Bluetooth가 활성화 되지 않았습니다.');
end;

블루투스 활성화 설정

uses
  Androidapi.JNI.Bluetooth;

procedure TForm2.Button2Click(Sender: TObject);
var
  Adapter: JBluetoothAdapter;
begin
  Adapter := TJBluetoothAdapter.JavaClass.getDefaultAdapter;
  if Adapter.enable then
    ShowMessage('Bluetooth를 활성화합니다.')
  else
    ShowMessage('사용할 수 없습니다.');
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  Adapter: JBluetoothAdapter;
begin
  Adapter := TJBluetoothAdapter.JavaClass.getDefaultAdapter;
  if Adapter.disable then
    ShowMessage('Bluetooth를 비활성화합니다.')
  else
    ShowMessage('사용할 수 없습니다.');
end;

블루투스 권한이 있는지 확인

uses
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText;

procedure TForm2.Button3Click(Sender: TObject);
  function HasPermission(const Permission: string): Boolean;
  begin
    Result := SharedActivityContext.checkCallingOrSelfPermission(StringToJString(Permission)) = TJPackageManager.JavaClass.PERMISSION_GRANTED
  end;

begin
  if HasPermission('android.permission.BLUETOOTH') then
    ShowMessage('Bluetooth 통신 권한이 있습니다.')
  else
    ShowMessage('Bluetooth 통신 권한이 없습니다');

  if HasPermission('android.permission.BLUETOOTH_ADMIN') then
    ShowMessage('Bluetooth 설정 수정 권한이 있습니다.')
  else
    ShowMessage('Bluetooth 설정 수정 권한이 없습니다.');
end;

  • 블루투스 관련 권한(Project Options > Uses Permissions)이 필요합니다.
    • Bluetooth
    • Bluetooth admin

샘플프로그램 다운로드

ProjectSetBluetooth.zip

참고 글


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

험프리.김현수 험프리.김현수 Firemonkey/기능제어 XE7, 블루투스, 안드로이드

[XE7] 안드로이드 WiFi 상태조회와 설정하기

2015.02.11 10:44

일본인 개발자인 山本隆(야마모토 타카시)의 글을 참고해 안드로이드 앱에서 Wifi 상태를 읽고 키고끄는 기능을 구현해 보고 공유합니다.

❑ 안드로이드 WifiManager 델파이 브릿지 파일 생성

Java2OP 툴을 이용해 WifiManager 델파이 브릿지 파일을 만듭니다.

Java2OP.exe -classes android.net.wifi.WifiManager -unit Androidapi.JNI.WifiManager


위 명령어를 실행하면 아래와 같이 Androidapi.JNI.WifiManager.pas 유닛파일이 생성됩니다. 



해당 유닛파일을 프로젝트 경로 또는 본인이 관리하는 라이브러리 경로에 복사합니다.(저는 D:\Projects\common\rtl\XE7\android 경로에 복사 후 Option > Library Path에 경로를 등록했습니다.)


만약, 아래와 같은 "Missing JDK. Please install JDK 1.7+ or make sure that it is in your PATH" 메시지가 표시된다면


 커맨드라인에서 아래의 명령어를 이용해 환경변수에 추가 후 다시 시도하기 바랍니다.(도움말)
SET PATH=%PATH%;C:\Program Files\Java\jdk1.7.0_25\bin


❑ Androidapi.JNI.WifiManager 유닛을 이용해 WiFI 제어기능 구현

새로운 프로젝트를 생성하고, 위에서 생성한 Androidapi.JNI.WifiManager를 추가합니다.

uses 절에 구현에 필요한 유닛을 추가합니다.

uses
  Androidapi.Helpers,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNIBridge,
  Androidapi.JNI.WifiManager;

WiFi 설정(키고 끄기)하기

procedure SetWifiEnabled(AEnable: Boolean);
var
  Obj: JObject;
  WifiManager: JWifiManager;
begin
  Obj := SharedActivityContext.getSystemService(TJContext.JavaClass.WIFI_SERVICE);
  if Obj = nil then
    Exit;

  WifiManager := TJWifiManager.Wrap((Obj as ILocalObject).GetObjectID);
  WifiManager.setWifiEnabled(AEnable);
end;

WiFi 상태 조회

function IsWifiEnabled: Boolean;
var
  Obj: JObject;
  WifiManager: JWifiManager;
begin
  Obj := SharedActivityContext.getSystemService(TJContext.JavaClass.WIFI_SERVICE);
  if Obj = nil then
    Exit;

  WifiManager := TJWifiManager.Wrap((Obj as ILocalObject).GetObjectID);
  Result := WifiManager.isWifiEnabled;
end;

❑ 사용자 권한 설정

위 Wifi 제어와 상태조회 기능을 사용할 경우 사용자 권한을 추가해야 합니다.

Project Option > Uses permissions

  • Access wifi state : Wifi 상태 조회

  • Change wifi state : Wifi 상태 설정

❑ 최종 화면과 소스코드


참고 글



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

험프리.김현수 험프리.김현수 Firemonkey/기능제어

[XE7] 자체적으로 원격푸쉬알림(GCM, APN) 전송 구현방법

2014.12.03 09:43

스페인의 델파이 개발자(fgonzalez.visiblogs.com/)가 자체적으로 원격푸쉬 알림 기능을 구현한 동영상을 소개합니다.


RAD Studio에서 원격 푸쉬 알림(Remote Push Notification)을 구현하기 위해서는 XE6 버전에 추가된 BaaS 클라이언트 컴포넌트를 통해 가능했는데요. 

이 동영상에서는 IdHttp(안드로이드), TCPClient(iOS) 컴포넌트 등을 활용해 푸쉬 메시지를 전송하고, System.PushNotification 클래스를 활용해 푸쉬 메시지를 수신하는 내용을 소개합니다.


동영상은 스페인어로 이야기를 합니다. 팁을 드리면 유투브의 자막을 한국어로 설정하고 화면과 코드위주로 보시면 충분히 이해할 수 있습니다.


참고 글


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

험프리.김현수 험프리.김현수 Firemonkey/기능제어 APN, Firemonkey, gcm, ios, push, Remote Push Notification, 안드로이드

  1. Blog Icon
    석만근

    와우 감사합니다.
    전 서버를 웹페이지로 구현하고 Post방식으로 날렸는데 바로 날리네요;; 구글로 ㅎㅎ
    그리고 왠지 될것 같은데.... 당채 말을 알아들을수가 없네요
    감사합니다. 도움이 많이 될듯합니다.

  2. 그래도 개발자들에게는 코드가 있어 위안이 됩니다^^
    시도해 보시고 팁될만한 것 있으면 공유해주세요.
    감사합니다.^^

  3. Blog Icon
    오진성

    감사합니다 ^^
    잘되네요 근데 궁금증이있는데요
    message를 한글로 보내면 한글이 깨져서 나오든데 ... 어떻게 해결해야하나요 ?

  4. Blog Icon
    정상언

    한글 깨지는 분 저도 고생 좀 했는데
    AData := TStringStream.Create(AJson.ToString) 이부분을

    다음 처럼 하면 되네요
    AData := TStringStream.Create(AJson.ToJSON);

  5. Blog Icon
    키위

    영상을 통해 푸쉬 메세지 전송에 성공 했습니다.
    그런데 푸쉬를 여러개 받으면 받은만큼 아이콘과 알림이 생기는데
    이걸 어떻게 아이콘 하나에 "x개 메세지"로 만들수 있을까요?...
    여기저기 검색을 해봐도 통.. 찾을 수가 없네요.
    보내는놈, 받는놈, manifest file, 서비스.. 어디를 건드려야 하는지도 감이 안잡히네요.ㅡㅡ

  6. Blog Icon
    난다요

    푸시연구 중인데 도저히 모르겠어서 질문올립니다.

    여기 홈페이지에서 동영상 보면서 만들고 있는데요

    다른건 다 이해가 가는데

    DeviceToKen := '';

    이 디바이스토큰값을 어디서 가져오는지 모르겠습니다.

    혹시 아시는분은 자세히 설명좀 부탁드립니다. ㅜㅜ

  7. Blog Icon
    하이요

    종료시에 push를 받고싶은데
    그럴려면 안드로이드 스튜디오의 경우 gradle 파일을 수정하던데...
    델파이에서는 어떻게 해야하나요?

  8. 다음글을 참고해 종료 이벤트를 감지해보세요.
    WillTerminate 이벤트에 푸쉬를 발생하세요.
    http://blog.hjf.pe.kr/114

    푸쉬를 발생하는 내용은 아래 링크를 참고하세요.
    http://docwiki.embarcadero.com/RADStudio/Berlin/en/Mobile_Tutorial:_Using_Notifications_(iOS_and_Android)

안드로이드 라이브러리(jar 파일) 활용 사례(안드로이드 열기 대화상자 구현)

2014.11.21 10:35

파란크리스마스 블로그를 운영하시는 파란산타님께서 안드로이드 라이브러리를 활용해 열기 대화상자를 구현한 내용이 있어 공유합니다.(안드로이드 라이브러리 사용하는 내용을 아주 쉽게 정리해 주셨습니다.)


본문에서는 

파이어몽키의 안드로이드 플랫폼에서는 열기 대화상자(TOpenDialog)를 제공하지 않기 때문에 오픈소스인 android-file-dialog의 라이브러리(*.jar)를 이용해 열기 대화상자를 구현한 내용입니다.

(아래 내용을 참고하시면 직접 만든 안드로이드 라이브러리를 델파이에서 사용하는 방안을 익힐 수 있습니다.)


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

험프리.김현수 험프리.김현수 Firemonkey/기능제어

[앱테더링] VCL앱을 모바일앱으로 쉽게 확장할 수 있는 앱테더링 자세히 살펴보기!

2014.11.10 18:35

앱테더링(App Tethering)?

앱 테더링은 2개의 개별적인 앱을 서로 연결(테더링)해서 데이터를 주고 받을 수 있는 기술입니다.

앱테더링 기술을 이용해 VCL어플리케이션에서 모바일로 데이터를 제공하면 모바일에서 뷰어만 빠르게 만들어 아주 빠르고 쉽게 모바일앱을 개발할 수 있습니다.

(모바일 앱의 동작을 다시 VCL 앱으로 전송해 사용자의 액션과 모바일 이미지등을 VCL 앱에서 사용하면 더 강력한 시스템으로 탈바꿈할 수 있습니다.)

❑ 앱테더링 컴포넌트

앱 테더링은 TTetheringManager, TTetheringAppProfile 두개의 컴포넌트를 통해 구현할 수 있습니다. 이번글에서는 각 컴포넌트의 자세한 속성과 이벤트에 대해서는 다루지 않습니다. 하지만 아래의 "앱테더링 데모를 통해 기능 살펴보기" 단계를 보시면 주요한 대부분의 속성과 이벤트를 다루고 있기 때문에 충분히 기능을 익힐 수 있습니다.

더 자세히 알고 싶은 기능(속성, 이벤트)는 엠바카데로 기술 도움말(영문)을 통해서 익혀보시기 바랍니다.

아래는 앱테더링 기술이 제공하는 대표적인 속성입니다.

앱테더링의 대표 기능

  • 동일한 서브넷에서 동반자앱 자동탐색 기능(P2P기반으로 별도의 서버 구성이 필요하지 않습니다.)
  • 지정한 IP / 지정한 서브넷(192.168.1.0: 192.168.1.1 ~ 192.168.1.255)에서 탐색 시도
  • 블루투스 기반 앱테더링
  • String / Stream 기반 데이터 전송 기능 제공(Stream이므로 사실상 모든 데이터 전송 가능)
  • 동반자앱에 공개된 Action(명령)을 원격에서 호출하는 Remote Action 기능제공
  • VCL / FMX 2개의 프레임워크 지원
    • VCL 앱을 모바일과 연결해 쉽게 모바일로 전환/확장 할 수 있는 가능성 제공
    • 모바일에서 센서를 연결하면 VCL앱을 IoT로 바로 확장 가능
아래 데모영상을 통해 여러분들의 가능성을 만들어 보시기 바랍니다.

앱테더링 데모를 통해 기능 살펴보기

아래 데모영상은 VCL 어플리케이션을 모바일 앱으로 확장하기 위해 앱테더링 기술의 가장 기본적인 부분을 설명합니다. 

데모영상을 보시고 기능을 익히신 후 앱테더링 기능을 여러분의 프로젝트에 도입하면 어떤 기능을 확장할 수 있을지 생각해 보시고 여러분의 제품에 적용해보시기 바랍니다.


위 데모는 총 9개의 (최소한의 기능의)단계를 통해 진행합니다.

  • 탐색과 접속
    • 1단계, 동일 서브넷에서 접속대상 탐색시도
    • 2단계, 탐색된 테더링 매니저 표시
    • 3단계, 선택 매니저와 연결(페어링), 비밀번호 인증
    • 4단계, 탐색된 테더링 프로필 표시
    • 5단계, 선택 페어링과 연결(페어링)
  • 데이터 송수신
    • 6단계, 문자열 데이터 전송
    • 7단계, 데이터 수신하기(문자열, 스트림)
    • 8단계, 이미지(스트림) 데이터 전송
    • 9단계, 원격지에 정의된 액션(명령) 호출

1, 동일 서브넷에서 접속대상 탐색시도하기

테더링매니저의 DiscoverManagers 메소드를 통해 주변(동일 서브넷)의 동반자 앱을 탐색합니다.

procedure TForm2.btnDiscoverManagerClick(Sender: TObject);
begin
  InitControls;

  LogAndInfo('동일 서브넷에서 접속대상을 찾습니다.');
  // (#1) 주변에서 TetheringManager 발견명령
  TetheringManager.DiscoverManagers;

  // (#2) TetheringAppProfile의 Group 기반으로 자동 연결
//  TetheringManager.AutoConnect(3000);

  //  (#3) 대상을 지정해 접속할 수 있습니다.
//  TetheringManager.DiscoverManagers(3000, 127.0.0.1);
end;

AutoConnect(#2, TetheringAppProfile의 Group이 동일한 대상으로 자동 접속), 접속 대상을 지정(#3)등 다양한 접속 방식을 제공합니다.

2, 발견된 테더링 매니저 정보표시

탐색(DiscoverManagers)이 완료되면 TetheringManager의 OnEndManagersDiscovery 이벤트가 발생하고, ARemoteManagers 파라메터를 통해 탐색된 매니저정보를 제공합니다.

procedure TForm2.TetheringManagerEndManagersDiscovery(const Sender: TObject;
  const ARemoteManagers: TTetheringManagerInfoList);
var
  Info: TTetheringManagerInfo;
begin
  cbxRemoteManagers.Items.Clear;
  for Info in ARemoteManagers do
  begin
    Log(Format('[검색된 매니저]'#13#10#9'%s'#13#10#9'%s'#13#10#9'%s'#13#10#9'%s', [
      Info.ManagerIdentifier,
      Info.ManagerName,
      Info.ManagerText,
      Info.ConnectionString
    ]));
    cbxRemoteManagers.Items.Add(Format('%s(%s)', [Info.ManagerText, Info.ConnectionString]));
  end;
  if cbxRemoteManagers.Items.Count > 0 then
  begin
    cbxRemoteManagers.ItemIndex := 0;
    btnPairManager.Enabled := True;
  end;
  LogAndInfo(Format('접속 대상이 [%d]건 발견되었습니다.', [ARemoteManagers.Count]));
end;

3, 선택한 매니저와 연결(페어링)

접속할 대상 매니저를 선택 후 페어링(PairManager)을 시도합니다.

// 선택한 매니저와 연결
procedure TForm2.btnPairManagerClick(Sender: TObject);
var
  N: Integer;
begin
  if cbxRemoteManagers.ItemIndex < 0 then
    Exit;

  N := cbxRemoteManagers.ItemIndex;
  LogAndInfo(TetheringManager.RemoteManagers[N].ManagerText + ' - 매니저와 페어링 시도');
  TetheringManager.PairManager(TetheringManager.RemoteManagers[N]);
end;

// 매니저 비밀번호 설정
procedure TForm2.TetheringManagerRequestManagerPassword(const Sender: TObject;
  const ARemoteIdentifier: string; var Password: string);
begin
  Password := edtPassword.Text;

  TThread.Synchronize(TThread.CurrentThread,
    procedure begin
      LogAndInfo('[비밀번호 요청] - ' + edtPassword.Text);
    end);
end;

매니저간 페어링 시도 시 서로의 비밀번호를 통해 연결을 허용합니다. 만약 매니저간의 비밀번호가 맞지 않다면, TetheringManager 컴포넌트에서 인증오류(OnAuthErrorFromLocal, OnAuthErrorFromRemote) 이벤트가 발생하고 페어링은 실패합니다.

비밀번호는 TetheringManager.Password 속성을 통해서도 설정할 수 있습니다.

4, 발견된 테더링 프로필 정보표시

매니저간 연결(페어링)되면 TetheringManager의 OnEndProfilesDiscovery 이벤트가 발생되며 ARemoteprofiles 파라메터를 통해 탐색된 프로필 정보를 제공합니다.

// 프로필 발견완료 이벤트
procedure TForm2.TetheringManagerEndProfilesDiscovery(const Sender: TObject;
  const ARemoteProfiles: TTetheringProfileInfoList);
var
  Info: TTetheringProfileInfo;
begin
//  Log('TetheringManagerEndProfilesDiscovery');
  cbxRemoteProfiles.Items.Clear;
  for Info in ARemoteProfiles do
  begin
    Log(Format('[앱 프로필]'#13#10#9'%s'#13#10#9'%s'#13#10#9'%s'#13#10#9'%s'#13#10#9'%s', [
      Info.ManagerIdentifier,
      Info.ProfileIdentifier,
      info.ProfileText,
      Info.ProfileGroup,
      Info.ProfileType

    ]));
    cbxRemoteProfiles.Items.Add(Format('%s(%s)', [Info.ProfileText, Info.ProfileType]));
  end;
  if cbxRemoteProfiles.Items.Count > 0 then
  begin
    cbxRemoteProfiles.ItemIndex := 0;
    btnPairProfile.Enabled := True;
  end;
  LogAndInfo(Format('대상 프로필 [%d]건 발견되었습니다.', [ARemoteProfiles.Count]));
end;

5, 선택한 프로필과 연결

접속할 대상 프로필을 선택(TetheringAppProfile.Connect)하여 페어링 시도합니다.

// 선택한 프로필과 연결
procedure TForm2.btnPairProfileClick(Sender: TObject);
var
  N: Integer;
begin
  if cbxRemoteProfiles.ItemIndex < 0 then
    Exit;

  N := cbxRemoteProfiles.ItemIndex;
  LogAndInfo(TetheringManager.RemoteProfiles[N].ProfileText + ' - 프로필과 페어링 시도');
  if TetheringAppProfile.Connect(TetheringManager.RemoteProfiles[N]) then
  begin
    LogAndInfo('페어링 성공!!');
    InitControls;
  end;
end;

페어링이 완료되면 데이터 전송, 데이터 수신, 원격 액션 호출등의 작업이 가능해 집니다.

6, 문자열 전달

TetheringAppProfile.SendString 메소드를 통해 명령어, 데이터등의 문자열 데이터를 전달할 수 있습니다.

procedure TForm2.btnSendStrHelloClick(Sender: TObject);
begin
  LogAndInfo('문자열 전달 - 동반자 모바일앱에 Hello 전달');
  TetheringAppProfile.SendString(
    TetheringAppProfile.ConnectedProfiles.First,
    'HELLO',
    '안녕? App Tethering!!!');
end;

procedure TForm2.btnSendStrRSClick(Sender: TObject);
begin
  LogAndInfo('문자열 전달 - 동반자 모바일앱에 ReverseString 전달');
  TetheringAppProfile.SendString(
    TetheringAppProfile.ConnectedProfiles.First,
    'ReverseString',
    '반갑습니다.');
end;

SendString 메소드는 3개의 파라메터를 전달합니다.

  1. 전송할 앱 프로필 객체
  2. 수신 시 리소스의 힌트로 받을 수 있는 설명(Description)
  3. 문자열 데이터 값
ReverseString 문자열 데이터는 상대방(모바일 앱)에서 수신 시 글자를 뒤집어(반갑습니다. > .다니습갑반) 다시 전송하도록 구현되었습니다.

7, 데이터 수신

상대방 동반자앱에서 데이터를 보내면 TetheringAppProfile의 OnResourceReceived 이벤트를 통해 데이터를 수신할 수 있습니다. 문자열 데이터, 이미지 데이터(Stream)등이 모두 OnResourceReceived 이벤트를 통해 수신합니다.

procedure TForm2.TetheringAppProfileResourceReceived(const Sender: TObject; const AResource: TRemoteResource); begin case AResource.ResType of // 데이터(SendString) TRemoteResourceType.Data: begin // ReverseString을 받은 모바일에서 전송한 응답 if AResource.Hint = 'EchoString' then LogAndInfo('EchoString : ' + AResource.Value.AsString) end; // 스트림(SendStream) TRemoteResourceType.Stream: begin // 모바일에서 전송한 이미지 if AResource.Hint = 'FMXIMG' then begin LogAndInfo('이미지 수신'); LoadImage(AResource.Value.AsStream); end; end; end; end;

AResource 파라메터 주요 속성

  • AResource.ResType
    • SendString으로 전송 시 TRemoteResourceType.Data로 SendStream으로 전송 시 TRemoteResourceType.Stream으로 수신
  • AResource.Hint
    • SendString과 SendStream의 Description 파라메터에 입력한 값을 담고 있습니다.
  • AResource.Value
    • SendString과 SendStream의 Value(AString, AStream)에 입력한 값을 담고 있습니다.

8, 데이터 전달 - 이미지전송

이미지, 파일 등의 데이터를 TStream으로 변환해 동반자 앱으로 전달 할 수있습니다.(TStream은 TMemoryStream, TFileStream, TStringStream 등의 부모클래스이므로  다양한 데이터를 전달할 수 있습니다.)

procedure TForm2.btnSendStreamImageClick(Sender: TObject);
var
  Stream: TMemoryStream;
begin
  LogAndInfo('데이터 전달 - 이미지 데이터를 TStream으로 동반자 모바일앱에 전달');
  Stream := TMemoryStream.Create;
  try
    Image1.Picture.Graphic.SaveToStream(Stream);
      TetheringAppProfile.SendStream(TetheringManager.RemoteProfiles.First,
      'VCLIMG',
      Stream
    );
  finally
    Stream.Free;
  end;
  PageControl1.TabIndex := 2;
//  TetheringAppProfile.SendStream()
end;

9, 원격지의 명령 호출(이미지 전송 요청) 

TetheringAppProfile.RunRemoteAction 메소드를 통해 원격지에 공개된 Action을 실행 할 수 있습니다.

// 원격지의 액션 호출
procedure TForm2.btnRunRemoteActionClick(Sender: TObject);
begin
  LogAndInfo('원격 명령 호출 - 원격지(동방자 모바일 앱)의 ActionSendImg 액션 호출');
  TetheringAppProfile.RunRemoteAction(
    TetheringManager.RemoteProfiles.First,
    'ActionSendImg'
  );
  PageControl1.TabIndex := 3;
end;

모바일 앱의 TetheringAppProfile에는 Actions 속성에 아래와 같이 Action이 등록되어 있습니다.

TetheringAppProfile의 Actions에 등록된 Action(명령)은 외부로 공개(IsPublic)할 수 있어 외부에서 RunRemoteAction 메소드를 통해 호출할 수 있습니다.

❑ 위 데모 소스코드 받기

앱테더링 데모 더 살펴보기...

RAD Studio XE7의 샘플 프로젝트에는 아래의 다양한 앱테더링 데모가 있습니다.

  • 앱테더링 샘플 프로젝트 경로

    • C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\RTL\Tethering

❑ BDShoppingList

  • 앱테더링 기술을 이용해 데스크탑의 쇼핑 데이터를 모바일에 제공합니다.

  • 모바일 화면에서 쇼핑항목의 구매를 선택하면 구매명령을 데스크탑으로 전달해 구매처리를 완료합니다.

  • 데스크탑과 모바일은 변경된 데이터를 수시로 동기화합니다.

  • http://docwiki.embarcadero.com/CodeExamples/XE7/en/RTL.BDShoppingList_Sample

❑ DesktopCast

❑ MediaPlayer

❑ PhotoWall


참고 글




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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 app tethering, Rad Studio, XE7, 앱테더링

    1. Blog Icon
      좋은남자

      이건 다른 질문인데요.. VCL 폼의 디자인이 깔끔한데.. 어디서 바꾸신 건가요? 데모 소스를 받아서 보니 Project - Option - Application - Appearance 에서 바꾸신 것 같지 않은데요..궁금합니다.

    2. VCL 스타일을 바꾼 것입니다. 해당 스타일은 프리미엄 스타일로 XE7 사용자들은 무료로 다운로드 및 사용할 수 있습니다.
      http://blog.hjf.pe.kr/253

    3. Blog Icon
      황영일

      안녕하세요. 반갑습니다. 앱테더링 데모에서 블루투스 아답터 설정하고 하면 접속대상를 찾지못합니다. 어떻게 하는지 알려주시면 감사 감사

    4. 혹시 페어링 하셨나요? 블루투스틑 페어링 된 상태에서 데이터를 주고 받을 수 있습니다.

    5. Blog Icon
      황영일

      블루투스 페어링도 해보았습니다. 안됩니다.
      network 테더링 하면 잘됩니다.
      아래것이 대한 것이 더궁금해서 몇자적습니다.
      클래식 블루투스및 블루투스 샘플을 테스트 하는데 페어링도 되고 서비스도 맞추었는데 소켓에 send하고 read할때 8바이트 보내면 read시 8바이트 길이가 나오는데 실제 데이터는 null입니다. xe7 샘플소스 그대로라 잘되야 될것 같은데 제가 뭘잘못했는지 이해가 되지 않습니다. 환경적인 요인인지 맨붕입니다. 도와주세요 ㅠㅠ

    6. Blog Icon
      푸름

      안녕하세요?
      항상 좋은 글 감사드립니다
      다름이 아니오라 앱테더링이라는게
      예제에서는 모바일과 윈도우인데
      모바일(안드로이드)-모바일(안드로이드)도 가능한가요?
      기본적으로 하고 싶은것은 다른 모바일의 특정폴더에서 이미지나 동영상을 가져오는걸 하고 싶습니다.

    7. 네 모바일과 모바일간에도 사용 가능합니다.

    안드로이드 기기에 설치된 앱 목록표시와 실행하기

    2014.11.04 11:53

    파이어몽키 개발자 커뮤니티 네이버 카페(http://cafe.naver.com/delphifmx)에서 가을이다 님이 올려주신 내용입니다.

    (RAD Studio 모바일(멀티-디바이스) 개발에 관심이 있으시면 반드시 가입해야 하는 까페입니다. 가입하세요.)


    안드로이드 기기에 설치된 앱의 목록을 표시하고 앱을 실행하는 예제입니다.


    uses
      Androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNI.JavaTypes,
      FMX.Helpers.Android,
      AndroidApi.Helpers,
      Androidapi.JNIBridge;
    
    // 중략
    
    var
      PM: JPackageManager;
      mainIntent: JIntent;
      LaunchIntent: JIntent;
      pkgAppsList: JList;
      ri: JResolveInfo;
      iter: JIterator;
      midlist : TStringList;
    begin
      PM := SharedActivityContext.getPackageManager;
      mainIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_MAIN, nil);
      mainIntent.addCategory(TJIntent.JavaClass.CATEGORY_LAUNCHER);
      pkgAppsList := PM.queryIntentActivities(mainIntent, 0);
      midlist := TStringList.Create;
      iter := pkgAppsList.iterator;
      while iter.hasNext do
      begin
        ri := TJResolveInfo.Wrap((iter.next as ILocalObject).GetObjectID);
        mIdList.Add(JStringToString(ri.activityInfo.applicationInfo.packageName));
      end;
      LaunchIntent := PM.getLaunchIntentForPackage(StringToJString(mIdList[2]));
    
    // 해당을 실행하려면 아래처럼,..,
    // SharedActivityContext.startActivity( LaunchIntent )
    
      showmessage(  mIdList.Text );
    end;

    댓글에서 수달님 께서 안드로이드 2.3.4 버전에서 정상동작을 확인하셨고, uses 절을 알려주셔서 포함했습니다.


    참고






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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어

    웹브라우저를 지원하지 않는 플랫폼(윈도우, OS X)에서 웹브라우저 지원하기

    2014.10.24 09:25

    RAD Studio와 AppMethod에서 멀티플랫폼으로 개발할 수 있지만, 아쉽게도 몇개의 컨트롤은 제한적인 플랫폼에서만 사용할 수 있습니다.

    웹브라우저가 그 중하나인데요. 일본의 엠바카데로 MVP 개발자인 Hosokawa Jun가 윈도우와 OS X에서 사용할 수 있도록 소스코드와 설명을 공개했습니다.


    일본어로 되어 있으므로 번역기를 통해 내용을 확인하시기 바랍니다.


    그리고 웹브라우저의 소스코드는 Github에 있습니다.

    TWebBrowser 뿐 아니라 다양한 소스코드가 공개되어 있으니 살펴보면 많은 도움이 될것입니다.


    참고



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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 TWebBrowser

    IoT와 RAD Studio(Bluetooth 이용)

    2014.09.23 16:16


    사물인터넷, 세상의 모든 것과 연결하다는 의미입니다. 최근 다양한 스마트 장비와 센서들이 다양하게 나오고 서로 연결하며 모든 것을 연결하는 시대로 가고 있습니다.


    이번 글에서는 RAD Studio에서 세상이 모든 것과 연결 하는 방법에 대해 알아 보겠습니다.


    그전에 몇가지 사례에 대해 알아봅니다.


    <사례 1>

    최근 MIT 대학에서는 화장실에 센서를 달고 화장실 사용 정보를 기숙사의 학생들에게 제공하는 시도가 있었습니다.

    이 시도가 꽤 학생들에게 반응이 좋았습니다. 그 이후 해당 대학에서는 세탁실의 세탁기와 건조기에도 센서를 달아 언제 현재 세탁이 가능한지 언제 세탁기를 사용할 수 있는지에 대한 정보를 학생들에게 제공하는 프로젝트를 추가 진행했다고 합니다.


    <사례 2>

    국내의 스마트 양식장 사례입니다. 민물장어를 키우는 양식장에 수온, 용존산소량등의 센서를 달고 모니터링해 성공한 사례입니다. 민물장어는 환경에 대단히 민감해 그 전까지는 직원들이 2~6시간 간격으로 수십~수백개의 수조를 일일히 점검했습니다.

    이 과정을 센서를 통한 모니터링 시스템을 구축한 결과 PC와 스마트폰으로 손쉽게 모니터링 및 위급시 빠르게 대처할 수 있어 폐사율도 낮추고 직원의 수고도 줄이며 금전적으로 큰 이익을 본 사례로 소개되었습니다.


    위 사례 뿐 아니라 우리 삼과 연결되 사례가 많습니다.

    대표적으로 시계, 안경 등의 웨어러블 디바이스를 통한 방법과 신발, 칫솔, 기저귀, 팔찌, 심장박동기 등을 통해 건강정보를 수집해 더 쾌적한 삶을 살 수 있도록 도움을 주는 다양한 시도가 진행되고 있습니다.


    RAD Studio도 이러한 시대의 흐름에 맞춰 다양한 플랫폼은 물론, 사물인터넷을 위한 기능을 추가하고 있습니다.


    RAD Studio와 IoT(블루투스)

    오늘은 최근 출시된 RAD Studio XE7에 추가된 사물인터넷 기능 중 Bluetooth 기능에 대해 소개합니다.

    ❑ 블루투스

    RAD Studio에서는 아래와 같은 방식으로 블루투스를 지원하고 있습니다.

    • Bluetooth LE 컴포넌트
    • Bluetooth LE 라이브러리
    • Classic bluetooth 라이브러리
    • Bluetooth를 이용한 앱 테더링


    플랫폼 별 기능 지원 버전

    ❑ 블루투스 참고 문서



    ❑ 블루투스 샘플

    RAD Studio XE7 설치 사용자 기준

    [C++ 빌더]
    • C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\CPP\Mobile Samples\Device Sensors and Services\Bluetooth 
    • C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\CPP\RTL\Tethering 
    [델파이(Object Pascal)]
    • C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\Mobile Samples\Device Sensors and Services\Bluetooth 
    • C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\RTL\Tethering

    온라인


    참고글



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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어

    병렬(패러럴) 컴퓨팅 라이브러리 소개

    2014.09.22 10:09

    최근들어 PC는 물론이고 스마트폰에서도 멀티코어 CPU를 이용해 성능을 극대화 시키고 있습니다. RAD Studio는 XE7에서 이러한 멀티코어 CPU를 최대한 활용할 수 있는 패러럴 컴퓨팅 라이브러리를 추가해 멀티코어 CPU를 최대한 활용할 수 있도록 지원하고 있습니다.


    패러럴 컴퓨팅 라이브러리에 대해 알아봅니다.

    병렬(패러럴) 컴퓨팅 러이브러리

    패러럴 컴퓨팅 라이브러리(Parallel Computing Library)란?

    • 멀티코어 CPU를 이용해 최적의 성능을 낼 수 있도록 다수의 CPU에서 병렬(패러럴)로 작업
    • 비동기 연산작업에 사용되어 멀티코어 컴퓨터와 장비 최대한 활용 가능 
    • 기존 코드에 손쉽게 통합하도록 라이브러리 형태로 지원 
    • VCL과 FMX, 델파이와 C++빌더에서 모두 사용 가능


    패러럴 라이브러리를 이용해 고성능이 필요한 작업을 병렬로 처리해 최적의 성능을 발휘하는 코드로 변경할 수 있습니다.

    ❑ 참고자료

    동영상

    패러럴 라이브러리 관련 글

    ❑ 샘플코드

    RAD Studio XE7의 샘플경로에 위의 동영상에서 진행된 "Conways Game of Life"샘플코드가 포함되어 있습니다.

    샘플경로

    • Delphi : C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\Object Pascal\RTL\Parallel Library
    • C++ : C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\CPP\RTL\Parallel Library


    샘플을 테스트 방법
    1. 샘플 프로젝트 컴파일 및 실행
    2. [Load] 버튼으로 "*.LIF" 파일 선택
    3. [Re-center] 버튼으로 중앙으로 이동(변경을 확인할 수 있도록)
    4. [Start] 버튼으로 실행
    5. Parallel 체크박스로 패러럴이 적용된 성능과 적용되지 않은 성능 비교

    인터넷 상에서는 아래의 경로를 통해 샘플코드 확인 할 수 있습니다.


    ❑ 마무리

    패러럴 라이브러리는 델파이(Object Pascal)과 C++ 빌더를 사용해 VCL과 FMX(멀티 디바이스) 모두에서 병렬 프로그램을 지원하고, 윈도우, 맥, 안드로이드, iOS에서 사용할 수 있습니다.

    단, 무분별하게 사용하면 다른 프로세스에 영향을 주거나 배터리 소모가 빠를 수 있으니 필요한 곳에 적절히 사용하시기 바랍니다.

    관련글



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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 XE7, 페러럴

    [NFC] 안드로이드에서 NFC 연동 방법

    2014.09.12 10:20



    지난 9월 10일 새로운 아이폰(아이폰 6, 아이폰 6 플러스)에 NFC 기능이 포함된 애플페이가 소개되었습니다.


    NFC(근거리 무선 통신: Near Field Communication)

    근거리 무선 통신(近距離無線通信, Near Field Communication, NFC)는 13.56MHz의 대역을 가지며, 아주 가까운 거리의 무선 통신을 하기 위한 기술이다. 현재 지원되는 데이터 통신 속도는 초당 424 킬로비트다. 교통, 티켓, 지불 등 여러 서비스에서 사용할 수 있다.

    위키백과 참고


    델파이에서도 NFC 기능을 이용할 수 있는데요. 안드로이드에서 NFC 기능을 이용하는 방법을 소개합니다.


    Embarcadero의 MVP 이자 다양한 플랫폼 SDK와 API 연동하는 다양한 방법을 소개한 Brian Long의 글입니다.

    아주 상세하게 기본부터 설명을 하기 때문에 곱씹어 보면 다방면에서 도움이 될 자료입니다.


    또다른 엠바카데로의 MVP인 Daniel Magin도 브라이언 롱의 글을 참고해 부연했습니다.

    향후 애플에서 NFC 관련 기술을 공개하면 iOS에서의 NFC 연동에 관한 내용도 소개할 수 있기를 기대합니다.



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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 NFC

    안드로이드에서 음성인식 및 TTS(Text To Speach)

    2014.07.14 09:51


    현재(2014년 7월)에 진행되고 있는 Developer Skill Sprints에 아주 다양한 내용들이 올라오고 있습니다.

    그 중 최근 개인적으로 관심을 두고 있는 음성인식 및 글자를 읽어주는 기능(TTS)을 소개하는 내용을 짐 매키트(Jim McKeeth)가 발표했습니다.


    음성인식 및 TTS는 최근 웨어러블 디바이스가 다양해 지며 기존의 터치 인터페이스를 대치하는 방안으로 두각을 보이고 있는데요. 구글 글래스, 스마트 워치, 스마트 카 등에서 다양하게 사용될 것으로 예상됩니다.


    이번 발표에서는 슬라이드와 데모 소스코드가 공개되었고 곧 동영상도 유튜브를 통해 공개될 것이므로 관심 갖으시면 많은 도움이 되실 것 같습니다.


    추가: 공개된 유투브 동영상 추가합니다.


    그리고 다음 링크를 통해 Developer Skill Sprints 정보를 더 확인해 보세요.


    참고글


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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 Developer Skill Sprints, Firemonkey, Jim McKeeth, TTS, 음성인식

    안드로이드 SMS 목록 얻어오기(샘플)

    2014.07.14 09:20

    러시아의 델파이 개발자가 안드로이드의 SMS 목록을 얻어오는 샘플을 공개했습니다.

    해당 블로그를 보니 안드로이드 관련된 아주 다양한 정보들이 있네요. 한번 살펴보시면 많은 도움이 되실 듯 합니다.

    단, 러시아어로 되어 있어 구글 자동번역기를 이용하면 될 것 같습니다.



    참고



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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 Firemonkey, SMS, 샘플코드, 안드로이드

    연락처(주소록)을 제어하는 방법(안드로이드, iOS)

    2014.06.19 15:59

    연락처에 접근하는 방법을 문의하셔서 해당 내용 안내해드리고 공유차 기록합니다.


    http://www.fmxexpress.com/access-device-contacts-with-delphi-xe5-firemonkey-on-android-and-ios/


    http://www.fmxexpress.com/access-android-contacts-manager-with-firemonkey-in-delphi-xe5/


    http://www.fmxexpress.com/access-ios-contacts-with-firemonkey-in-delphi-xe5/


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

    험프리.김현수 험프리.김현수 Firemonkey/기능제어 android, ios, 기능, 연락처, 주소록

    1. Blog Icon
      이윤희

      소중한 정보 감사드립니다~ ^^
      아직 많은 부분이 어색하네요. 하나씩 알아가는 재미도 있구요...
      김현수님 블로그의 많은 포스팅 자료가 도움이 되고 있습니다.
      감사합니다~

    2. 네 도움이 되신다니 보람이 됩니다.^^
      앞으로도 많은 시도해보시고 궁금하신 점이나 함께 공유하실 만한 내용 있으시면 다양하게 조언 부탁드립니다.
      감사합니다.^^

    3. Blog Icon
      컴퓨터정보공학과

      컴공과 학생입니다. xe7에서 안드로이드로 주소록 제어하기를 해보려고 하는데 여기에 나온 데모버전을 실행해봤더니 오류가 엄청뜨는데 이 오류만 잡으면 돌아갈수있을까요?

    4. XE7 안드로이드의 경우
      ContactsManager의 uses 절에 Androidapi.Helpers를 추가하세요.

    Baas(Backend as a Service)와 RAD Studio(GCM, APN, 푸시알림 가능)

    2014.05.27 11:36

    BaaS(Backend as a Service)

    BaaS는 Backend as a Service 약자로 모바일에서 필요한 Backend 기능을 추상화하여 표준 API(JSON 등)로 제공하는 클라우드 서비스의 한 종류 입니다.

    Backend as a service - http://en.wikipedia.org/wiki/BaaS


    더보기


    간단히 설명하면, 여러분이 앱을 만드는 경우 앱에서 사용하기 위한 데이터, 사용자 정보등의 Backend 기능을 여러분의 서버에 구성하지 않고, BaaS 사이트(또는 연동)에서 제공하는 기능을 설정(커스터마이징) 후 이용하는 방식입니다. 별도의 여러분의 Backend 서비스 개발 과정이 생략되어 개발 시간을 대폭 단축 할 수 있습니다.


    대표적인 BaaS 제공자로는 Kinvey, Pharse, Bass.io(국내)가 있으며 제공되는 기능은 푸시알림, SNS 연동, 사용자 관리, 데이터 관리, 이미지/사운드 등의 파일 관리 등이 있습니다.


    RAD Studio XE6에서도 새롭게 BaaS 관련된 컴포넌트가 추가되었습니다.


    현재는 대표적인 BaaS 서비스인 Kinvey와 Pharse를 제공합니다.

    BaaS 컴포넌트


    BaaS 컴포넌트는 위와 같이 제공자 컴포넌트와 서비스 기능 컴포넌트로 구분됩니다.

    서비스 기능 컴포넌트는 BaaS에서 제공되는 대표적인 기능을 사용할 수 있는 컴포넌트이며, 기능별로 추상화(표준화)되어 제공되어 제공자별로 별도로 구성하지 않아도 됩니다. 앱 개발 시 서비스 기능 위주로 개발하고 제공자를 연결하면 제공자의 서비스와 연결되도록 아주 유연한 구조로 설계가 되어있습니다.

    즉, 향후 제공자가 추가된다면, 기존에 구현된 기능을 그대로 사용하고 제공자 컴포넌트만 변경해 적용 할 수 있습니다. 


    그리고 BaaS 컴포넌트는 멀티플랫폼을 지원하여, VCL과 FMX에서 모두 사용이 가능합니다.

    즉, VCL에서 사용자 및 데이터 관리와 푸시메시지 전송등을 기존의 어플리케이션에서 적용할 수도 있습니다.

    BaaS 관련 샘플

    다음은 엠바카데로에서 제공하는 BaaS 컴포넌트 관련 설명과 샘플소스입니다. 

    (개인적으로 GCM 부분을 따라해 봤는데 아주 쉽게 되었습니다.)

    ▶ Remote Notification(GCM, APN)


    Mobile Tutorial: Using Remote Notifications


    메시징 서비스 설정 - 구글과 애플에서 클라우드 서비스 사용을 위한 설정


    클라우드 서비스에 구글과 애플 계정 연결 설정


    어플리케이션 구현 - 컴포넌트를 이용 클라우드 메시지 수신하도록 구현 및 테스트


    데이터에 트리거(Trigger)를 걸어 데이터 변경 시 데이터 전송

    데스크탑에서 클라우드 메시지 전송


    ▶ Storage 이용

    BaaS 컴포넌트를 이용한 ToDo List


    사용자 계정관리(생성)


    ▶ 파일 업로드/다운로드


    Uploading images to the cloud with BaaS in RAD Studio XE6


    C++빌더 샘플 다운로드


        ▶ VCL 어플리케이션에서 특정 사용자에게 푸쉬메시지 전송

        Custom Endpoint 설정과 어플리케이션 데모

        참고



        관련글



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

        험프리.김현수 험프리.김현수 Firemonkey/기능제어 BAAS, Delphi, Kinvey, Pharse, Rad Studio

        1. Blog Icon
          희아

          문의드립니다. XE6 에서의 GCM 지원은 결국 상용화되어있는 것을 이용하는 것 뿐인가요?
          메시지밖에 안보내는데도...
          비용을 들이지 않고 작업하려면 Send/Receive 를 통신이나 java를 이용하여 개발해 포함시켜야 하는건가요?
          XE5 에서 개발된 샘플을 이용해보려하는데 쉽지않네요.

        2. 네 BaaS를 사용하지 않으려면 위글의 참고 항목의 링크를 확인하시면 직접 GCM/APN을 구현할 수 있습니다.
          말씀하신대로 BaaS 컴포넌트를 이용할때 보다 상당히 어렵습니다.

        3. Blog Icon
          정상언

          국내 bass.io 서비스는 7월28일자로 종료되었다네요
          https://www.facebook.com/backendservice