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

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

 

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

 

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

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

 

 

 

 

기본 구성

 

❑ 웹페이지 구성

 

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script language="JavaScript">
// 델파이에서 호출하는 자바스크립트 메소드
function callJSMethodFromDelphi(){
    alert("[JS] Call from delphi");
}
 
// 델파이 메소드를 호출하는 자바스크립트 함수 2종
function callDelphiMethodFromJS(){
    window.location = "jscall://callDelphiMethodFromJS";
}
 
function callDelphiMethodFromJSWithParam(){
    window.location = "jscall://callDelphiMethodFromJSWithParam?Hello|1234";
}
</script>

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

1
2
<input type="button" value="Call delphi method" onclick="callDelphiMethodFromJS();"><br>
<input type="button" value="Call delphi method(with parameters)" onclick="callDelphiMethodFromJSWithParam();">

 

❑ 델파이 앱 화면 구성

 

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

 

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

 

델파이 코드

 

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

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

 

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

 

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

 

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

 

테스트 결과

 

 

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

 

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

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

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

 

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

 

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

 

이벤트

 발생 조건

 OnDidFailLoadWithError

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

 OnDidFinishLoad

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

 

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

 

 

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

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

 

 

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

 

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

 

1
2
3
4
5
6
7
function callDelphiMethodFromJS(){
    window.location = "jscall://callDelphiMethodFromJS";
}
 
function callDelphiMethodFromJSWithParam(){
    window.location = "jscall://callDelphiMethodFromJSWithParam?Hello|1234";
}

 

 

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

 

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

 

 포맷 정의

용도 

 jscall:// 

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

 callDelphiMethodFromJSWithParam

 호출할 델파이 코드명

 ?Hello|1234

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

 

 

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

 

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

 

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

 

1
2
3
4
5
6
7
8
9
10
11
procedure TForm1.WebBrowser1ShouldStartLoadWithRequest(ASender: TObject;
  const URL: string);
var
  MethodName: string;
  Params: TArray<tvalue>;
begin
  if ProcessMethodUrlParse(URL, MethodName, Params) then
  begin
    CallMethod(MethodName, Params);
  end;
end;</tvalue>

 

 

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

 

메소드 URL 분석

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// URL format
//  jscall://{method name}?{Param1}|{ParamN}
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<string>;
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;</string>

 

❑ 분석한 메소드 호출

 

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

 

1
2
3
4
5
6
7
8
9
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를 이용해 메소드이름으로 메소드를 찾아 호출하는 방법으로도 구현할 수 있습니다.

 

조건문으로 메소드 호출

 

 

1
2
3
4
5
6
7
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를 이용해 메소드 호출

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

 
번호 제목 글쓴이 날짜 조회 수
공지 [DelphiCon 요약] 코드사이트 로깅 실전 활용 기법 (Real-world CodeSite Logging Techniques) 관리자 2021.01.19 18067
공지 [UX Summit 요약] 오른쪽 클릭은 옳다 (Right Click is Right) 관리자 2020.11.16 16393
공지 [10.4 시드니] What's NEW! 신기능 자세히 보기 관리자 2020.05.27 19021
공지 RAD스튜디오(델파이,C++빌더) - 고객 사례 목록 관리자 2018.10.23 24640
공지 [데브기어 컨설팅] 모바일 앱 & 업그레이드 마이그레이션 [1] 관리자 2017.02.06 26010
공지 [전체 목록] 이 달의 기술자료 & 기술레터 관리자 2017.02.06 21383
공지 RAD스튜디오(델파이, C++빌더) - 시작하기 [1] 관리자 2015.06.30 41974
공지 RAD스튜디오(델파이,C++빌더) - 모바일 앱 개발 사례 (2020년 11월 업데이트 됨) 험프리 2014.01.16 177266
1063 [개발팁 시리즈] 델파이/C++빌더 VCL 애플리케이션을 개발한다면? 꼭 확인하세요! 관리자 2019.11.20 478
1062 주요 OS 시장 점유율 - 윈도우와 안드로이드! file 관리자 2019.11.19 590
1061 윈도우 버전 점유율 변화: 2009년부터 2019년 현재까지! file 관리자 2019.11.18 391
1060 [델파이 샘플 코드] 안드로이드, iOS, OSX, 윈도우, 리눅스, HTML5 관리자 2019.11.13 681
1059 FCM 전송 구헌혀기 - 앱 서버 프로토콜 사용 메시지 전송 험프리 2019.11.08 1142
1058 [고객사례-게임, 델파이] Rise of Legions 관리자 2019.11.08 803
1057 [데모 영상] 델파이 프로젝트에 구글 시트 연동하기 (엔터프라이즈 커넥터 활용) 관리자 2019.11.08 576
1056 델파이 코드 컨버전 빠르게 완료하기 관리자 2019.11.06 612
1055 엔터프라이즈 커넥터 무료 제공 (업데이트 서브스크립션 계약중인 고객 대상) 관리자 2019.10.31 451
1054 InterBase ToGo 모바일용 라이선스 배포하기 file 데브기어 2019.10.30 500
1053 DLL 폼에서 VCL 폼 스타일 적용하기 file 김원경 2019.10.28 5872
1052 [고객 사례- 의료, 델파이] 의료용 소프트웨어(폐활량&심전도 체크) - Advanced Spirometer and ECG 관리자 2019.10.25 654
1051 [고객사례-소셜네트워크, 델파이] KisKis 관리자 2019.10.25 1124
1050 이 달의 기술자료 - 2019년 11월 file 험프리 2019.10.25 382
1049 IBM 왓슨과 인공지능(AI) 활용하기 - 델파이/C++빌더 관리자 2019.10.25 695
1048 [발표자료] 20191017 실전 사례로 살펴보는 소프트웨어 현대화 전략 file 관리자 2019.10.23 391
1047 윈도우 10 지원과 좋은 UX 구현을 위해 기억해야 할 점 관리자 2019.10.22 650
1046 [개발사례-유통분야] 20년된 프로그램을 현대식 마이크로서비스 아키텍처로 전환 관리자 2019.10.22 1106
1045 [개발팁] TBooleanHelper.ToString 그리고 TUseBoolStrs 관리자 2019.10.21 287
1044 RAD스튜디오의 iOS 13 및 안드로이드 64-bit 대응 관리자 2019.10.21 563