업데이트 내역

2019-05 : 안드로이드 권한 모델 변경(런타임 시 권한 요청)이 적용되도록 업데이트

2019-10 : 안드로이드 권한 모델 적용에 위치(ACCESS_FILE_LOCATION) 항목 추가

 

 

위 동영상(위험 지역 경보 시스템 데모) 중 위험 지역 진입 시 경보를 발생하는 앱을 따라하기를 통해 만들어 봅니다.

 

위험지역 진입 경보앱 만들기

❑ 앱 소개

 

 

앱 소개

이 앱은 위험지역에 진입 시 화면과 경고음으로 위험지역에 진입을 경고해 주는 (프로토 타입)앱입니다.

 

 

따라하기의 목적

따라하기를 통해 비콘을 이용한 위치기반 앱 개발을 시작합니다.

 

이 따라하기에서는 다음 내용을 다룹니다.

  • 비콘 컴포넌트를 이용해 비콘과의 거리를 활용합니다.
  • UI 컨트롤의 투명도에 애니메이션 효과를 적용해 화면경고 기능을 구현합니다.
  • 사운드 파일(*.mp3)을 앱과 배포해 경보음으로 사용합니다.

 

따라하기

 

0, 사전 준비사항

1, 빈 멀티-디바이스 애플리케이션 프로젝트를 생성하고 저장합니다.

2, 메인 UI를 만듭니다.

3, 위험 경보 UI를 추가합니다.

4, 위험경고 화면 효과, 경고음 기능을 추가합니다.

5, 비콘 컴포넌트 추가 후 이벤트를 만듭니다.

6, 비콘과 거리를 기반으로 위험지역 경보 이벤트를 발생합니다.

7, 블루투스 권한설정

8, 디바이스에 배포하고 테스트합니다.

 

0, 사전 준비사항

개발 도구 준비하기

델파이(또는 RAD Studio)를 실행합니다.(이 실습은 델파이 XE8 버전으로 작성되었습니다.)

만약, 델파이가 설치되지 않았다면 아래의 페이지에서 델파이를 다운로드 받아 설치 후 진행하시기 바랍니다.

 

따라하기에서 사용할 리소스 다운로드

 DangerZoneAlertRes.zip

 

위 파일을 다운로드 후 적당한 위치에 압축해제하시기 바랍니다.

 

비콘 준비하기

비콘을 준비합니다.(시중에서 다양한 비콘을 판매하고 있습니다. 저는 Beacon B1을 이용해 진행했습니다.)
시중에서 판매되는 (표준을 지키는)대부분의 비콘과 연동됩니다.

 

비콘 정보 확인/설정하기

비콘의 UUID와 Major Id, Minor Id를 알아야 합니다. 제조사 사이트 또는 비콘 스캐너 앱을 통해 파악할 수 있습니다.
보통 같은 제품의 비콘은 동일한 UUID, Major Id, Minor Id로 설정되어있습니다. 비콘 별로 구별하기 위해 Major Id, Minor Id를 변경해야 하는데, 제조사의 안내에 따라 Major Id, Minor Id를 다르게 설정하기 바랍니다.(대부분 제조사에서 전용 앱을 제공합니다.)

 

1, 빈 멀티-디바이스 애플리케이션 프로젝트 생성

  1. File > New > Multi-Device Application - Delphi 메뉴를 선택 하고, Blank Application을 선택해 프로젝트를 생성합니다.
  2. File > Save all 메뉴를 선택 해 유닛이름을 "MainForm.pas"로 프로젝트 이름을 "DangerZoneAlert"으로 저장합니다.

2, 메인 UI를 만듭니다.

모바일 앱 스타일로 화면 구성하기 위해 폼디자이너 스타일을 Android로 변경합니다.

 

다음화면과 표를 이용해 위험지역 경보 앱 메인 UI를 개발합니다.
(이 따라하기는 비콘 활용 기능에 집중하기 위해 최소한의 UI로 구성했습니다.)

 

 

상위 오브젝트

오브젝트

속성

값(또는 설명)

 Form1

 ToolBar1

 

 

 ToolBar1

 Label1

 Align

 Client

 Text

 위험지역 경보 앱

 TextSettings.HorzAlign

 Center

 Switch1

 Align

 Right

 Form1

 Image1

 MultiResBitmap

 "factory.png 선택"

 StatusBar1

 Height

 32

 StatusBar1

 Label2

 Align

 Client

 Text

 위험지역과의 거리: 

 

 

3, 위험 경고 UI를 추가합니다.

위험 지역 진입 시 화면으로 경고를 주기위한 UI를 추가합니다. 붉은색 배경에 안내문구를 표시하고, 화면을 깜빡이게 합니다.

화면을 깜빡이는 기능은 다음 단계에서 진행합니다.

 

다음화면과 표를 이용해 위험 경보 UI를 추가합니다.

 

 

 

상위 오브젝트 

 오브젝트

 속성

 값(또는 설명)

 Form1

 Rectangle1

 Align

 Client

 Fill.Color

 Red

 Opacity

 0.8

 Rectangle1

 Layout1

 Align

 Center

 Width/Height

 228/186(적당히)

 Layout1

 Label3

 Text

 위 그림 참고(위험지역에 ...)

 lblDistance
 (TLabel)
 Align  Bottom
 Name  lblDistance

 TextSettings.Font.Size

 24
 TextSettings.HorzAlign  Center

 

4, 위험경고 화면 효과, 경고음 기능을 추가합니다.

 

위험지역 진입을 알리기위해 경고음을 발생하고, 경고화면을 표시 후 화면을 깝빡여주는 기능을 구현합니다.

 

경고음을 실행하기위해 TMediaPlayer 컴포넌트를 경고화면을 깜빡이기 위해 TFloatAnimation 컴포넌트를 추가합니다.

 

Rectangle1의 FloatAnimation은 Opacity 속성 추가 메뉴(Create New TFloatAnimation)를 선택해 생성합니다.

 

 

 

상위 오브젝트

오브젝트

속성

값(또는 설명)

 Form1

 MediaPlayer1

 

 

 Rectangle1

 FloatAnimation1

 Autoreverse

 True

 Duration

 1

 Loop

 True

 PropertyName  Opacity

 StartValue/StopValue

 0.8/0.2

 

 

경고음 사운드 파일 배포등록하기

 

구현에 앞서 경고음으로 사용할 사운드파일을 배포관리자에 등록힙니다.

  1. 메인메뉴에서 Project > Deployment 메뉴를 선택해 Deployment 윈도우를 표시합니다.
  2. Add files 버튼을 누르고 "alert.mp3"파일을 선택해 추가합니다.
  3. 배포 플랫폼 선택 콤보박스를 Android platform과 iOS Device platform으로 선택하고, 아래를 참고해 Remote Path를 수정합니다.
  • Android platform - assets\internal\
  • iOS Device platform - StartUp\Documents\

 

경고 기능 구현하기

 

private 영역에 아래 코드를 참고해 4개의 메소드를 선언합니다.

 

1 private
2   { Private declarations }
3   procedure StartWarning;// 위험지역 진입 경고 시작
4   procedure StopWarning; // 위험지역 진입 경고 중지
5  
6   procedure StartSiren;  // 사이렌 시작
7   procedure StopSiren;   // 사이렌 중지
8 public

 

Ctrl + Shift + C 단축키(Complete Class at Cursor)를 이용해 메소드의 구현부를 자동완성합니다.

아래 코드를 참고해 구현부를 완성합니다.

 

01 procedure TForm1.StartSiren;
02 begin
03   MediaPlayer1.FileName := TPath.Combine(TPath.GetDocumentsPath, 'alert.mp3');
04   MediaPlayer1.Play;
05 end;
06  
07 procedure TForm1.StopSiren;
08 begin
09   MediaPlayer1.Stop;
10 end;
11  
12 procedure TForm1.StartWarning;
13 begin
14   Rectangle1.Visible := True;
15   FloatAnimation1.Enabled := True;
16  
17   StartSiren;
18 end;
19  
20 procedure TForm1.StopWarning;
21 begin
22   Rectangle1.Visible := False;
23   FloatAnimation1.Enabled := False;
24  
25   StopSiren;
26 end;

사운드파일 경로 설정을 위해 사용한 TPath가 선언된 System.IOUtils 유닛을 유즈절에 추가합니다.

 

5, 비콘 컴포넌트 추가 후 이벤트를 만듭니다.

비콘 컴포넌트(TBeacon)는 안드로이드, iOS, OSX를 지원합니다. 타겟 플랫폼을 안드로이드로 변경 후 폼위에 비콘 컴포넌트를 추가합니다.

 

 

모니터링 대상 비콘 등록

비콘을 모니터링하기 위해 비콘 정보를 등록합니다.

  • Beacon1 컴포넌트의 MonitorizedRegions 속성을 선택 후 확장 버튼을 클릭합니다.
  • 편집창에서 Add new 버튼을 눌러 항목을 추가합니다.
  • 대상 비콘의 UUID, Major, Minor 값을 입력합니다.

(만약, Major, Minor 값을 -1로 설정하면 UUID만 이용해 대상을 탐색합니다.)

 

 

비콘 인스턴스 할당하기

비콘 변수를 선언하고, BeaconEnter, BeaconExit 이벤트에서 비콘 인스턴스를 할당해줍니다.

private 영역에 변수를 선언합니다.

1 private
2   { Private declarations }
3   FBeacon: IBeacon;

 

 비콘 컴포넌트의 OnBeaconEnter, OnBeaconExit 이벤트 핸들러를 만들고 비콘 인스턴스를 할당합니다.

(이벤트 핸들러는 이벤트의 우측 영역을 더블클릭하면 생성됩니다.)

 

01 procedure TForm1.Beacon1BeaconEnter(const Sender: TObject;
02   const ABeacon: IBeacon; const CurrentBeaconList: TBeaconList);
03 begin
04   FBeacon := ABeacon;
05 end;
06  
07 procedure TForm1.Beacon1BeaconExit(const Sender: TObject;
08   const ABeacon: IBeacon; const CurrentBeaconList: TBeaconList);
09 begin
10   FBeacon := nil;
11 end;

 

비콘 컴포넌트 동작을 활성화하기

안드로이드 권한 모델 변경으로 10.3 이상의 버전은 런타임 시 권한 요청하도록 변경이 필요합니다.
 
10.2 이전 버전
스위치(Switch1)를 키면 비콘이 동작하도록 Switch1의 OnSwitch 이벤트 핸들러 생성 후 아래 코드를 입력합니다.
1
2
3
4
procedure TForm1.Switch1Switch(Sender: TObject);
begin
  Beacon1.Enabled := Switch1.IsChecked;
end;
 
10.3 이상 버전(런타임 시 권한 요청)
구현부 uses 절에 필요한 유닛을 추가합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
implementation
 
uses
  System.Permissions,
{$IFDEF ANDROID}
  Androidapi.JNI.Os,
  Androidapi.JNI.JavaTypes,
  Androidapi.Helpers,
{$ENDIF}
  FMX.DialogService;
 
{$R *.fmx}

 

스위치(Switch1)를 키면 권한을 요청하고, 비콘이 동작하도록 Switch1의 OnSwitch 이벤트 핸들러 생성 후 아래 코드를 입력합니다.(2019-10-23: 위치(ACESS_FINE_LOCATION) 권한이 없어 비콘이 실행되지 않아 추가)

 

 

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
procedure TForm1.Switch1Switch(Sender: TObject);
begin
{$IFDEF ANDROID}
  if Switch1.IsChecked then
  begin
    PermissionsService.RequestPermissions(
      [
        JStringToString(TJManifest_permission.JavaClass.BLUETOOTH),
        JStringToString(TJManifest_permission.JavaClass.BLUETOOTH_ADMIN),
        JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION)
     ],
      procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
        begin
          if (Length(AGrantResults) = 3)
          and (AGrantResults[0] = TPermissionStatus.Granted)
          and (AGrantResults[1] = TPermissionStatus.Granted)
          and (AGrantResults[2] = TPermissionStatus.Granted) then
            { activate or deactivate the location sensor }
            Beacon1.Enabled := True
          else
          begin
            Switch1.IsChecked := False;
            TDialogService.ShowMessage('블루투스 권한이 없습니다.');
          end;
        end);
  end
  else
    Beacon1.Enabled := False;
{$ELSE}
  Beacon1.Enabled := Switch1.IsChecked;
{$ENDIF}
end;

6, 비콘과 거리를 기반으로 위험지역 경보 이벤트를 발생합니다.

이제 모든 준비는 완료되었고, 비콘과의 거리를 계산해 위험지역 진입 경보 이벤트를 발생하면 됩니다.

위험지역 진입에 대한 경보는 아래와 같은 기준으로 시작하고 중단합니다.

 

위험지역 진입 경보 기준

  1. 비콘과의 거리가 1.0미터 이하인 경우 위험지역으로 간주한다.
  2. 경보가 아닌 상태에서 위험지역에 3초이상 연속으로 머무른 경우 경보를 시작한다.
  3. 경보가 발생중인 상태에서 위험지역을 3초이상 연속으로 벗어난 경우 경보를 중단한다.

비콘과 거리를 주기적으로 확인하기 위해 타이머 컴포넌트(Timer1)를 폼에 추가합니다.

 

아래 변수를 private 영역에 선언합니다.

1 FIsWarning: Boolean;         // 경고 중인가?
2 FDangerAreaStaySecs,         // 위험지역에 머무른 시간(초)
3 FDangerAreaOutSecs: Integer// 위험지역에서 벗어난 시간(초)

 

 

Timer1의 OnTimer 이벤트 핸드러를 생성하고, 아래 코드를 추가합니다.

01 procedure TForm1.Timer1Timer(Sender: TObject);
02 var
03   InDangerArea: Boolean// 위험지역에 있는가?(비콘과의 거리가 1m 이내인가?)
04 begin
05   if Assigned(FBeacon) then
06   begin
07     InDangerArea := FBeacon.Distance <= 1;
08  
09     // 경고 중 아님
10       // 위험지역에 3초간 머무른 경우 경고 시작
11     if not FIsWarning then
12     begin
13       if InDangerArea then
14         Inc(FDangerAreaStaySecs)
15       else
16         FDangerAreaStaySecs := 0
17       ;
18  
19       if FDangerAreaStaySecs >= 3 then
20       begin
21         FIsWarning := True;
22         StartWarning;
23         FDangerAreaStaySecs := 0
24       end;
25     end
26     // 경고 중
27       // 위험지역을 3초 이상 벗어난 경우 경고 중단
28     else if FIsWarning then
29     begin
30       if not InDangerArea then
31         Inc(FDangerAreaOutSecs)
32       else
33         FDangerAreaOutSecs := 0;
34  
35       if FDangerAreaOutSecs >= 3 then
36       begin
37         FIsWarning := False;
38         StopWarning;
39         FDangerAreaOutSecs := 0;
40        end;
41     end;
42  
43     // 위험지역과의 거리를 표시
44     lblDistance.Text := FBeacon.Distance.ToString;
45     Label3.Text := '위험지역과의 거리: ' + FBeacon.Distance.ToString + ' m';
46   end;
47 end;

 

7, 블루투스 권한설정

(이 과정은 안드로이드 플랫폼을 사용하지 않는 경우 생략할 수 있습니다.)

비콘은 블루투스 LE(Low Energy) 기반으로 통신합니다.  블루투스 사용권한을 설정합니다.

Project > Options 메뉴를 선택 후 Uses Permissions 화면으로 이동합니다.

 

Bluetooth와 Bluetooth admin 두개의 권한을 사용하도록 설정합니다.

8, 디바이스에 배포하고 테스트합니다.

처음 디바이스에 배포하는 경우 먼저 모바일 개발환경 설정하고 진행하기 바랍니다.

 

개발을 완료했습니다. 이제 준비된 개발환경으로 플랫폼을 선택 후 Run > Run Without Debugging 메뉴를 이용해 실행하고 테스트 합니다.

 

 

테스트 방법 : 

  • 앱을 실행 후 비콘과 1미터 이내로 접근 후 3초이상 머무르면 경고가 발생
  • 경고 발생 중 1미터 초과 거리로 이동 후 3초이상 머무르면 경고 중단

사물인터넷

 

참고자료


번호 제목 글쓴이 날짜 조회 수
공지 [DelphiCon 요약] 코드사이트 로깅 실전 활용 기법 (Real-world CodeSite Logging Techniques) 관리자 2021.01.19 14355
공지 [UX Summit 요약] 오른쪽 클릭은 옳다 (Right Click is Right) 관리자 2020.11.16 13021
공지 [10.4 시드니] What's NEW! 신기능 자세히 보기 관리자 2020.05.27 15529
공지 RAD스튜디오(델파이,C++빌더) - 고객 사례 목록 관리자 2018.10.23 21048
공지 [데브기어 컨설팅] 모바일 앱 & 업그레이드 마이그레이션 [1] 관리자 2017.02.06 22296
공지 [전체 목록] 이 달의 기술자료 & 기술레터 관리자 2017.02.06 17929
공지 RAD스튜디오(델파이, C++빌더) - 시작하기 [1] 관리자 2015.06.30 38219
공지 RAD스튜디오(델파이,C++빌더) - 모바일 앱 개발 사례 (2020년 11월 업데이트 됨) 험프리 2014.01.16 173732
543 [시애틀] FireDAC NoSQL 드라이버로 몽고DB를 완벽 지원합니다. Humphery 2015.09.04 969
542 [시애틀] 개발 효율성을 극대화할 수 있도록 멀티-모니터를 활용해 개발환경 레이아웃을 구축할 수 있습니다. Humphery 2015.09.04 643
541 [발표자료] 9월 3일 "사물인터넷 실제 구현하기, DeepDive" 관리자 2015.09.04 450
540 [시애틀] 알림, 계약(Contract) 등의 윈도우 10 서비스 기능을 컴포넌트와 API로 쉽게 활용할 수 있습니다. 험프리 2015.09.02 764
539 [시애틀] VCL 스타일이 공용 대화 상자와 웹브라우저까지 적용됩니다. Humphery 2015.09.02 474
538 [시애틀] VCL 스타일을 적용해 1분만에 윈도우 10 최신신 룩앤필을 적용할 수 있습니다. 험프리 2015.09.02 1231
537 [시애틀] 윈도우 10 용 새 VCL UI 컨트롤로 윈도우 10 UI를 손쉽게 적용할 수 있습니다. 험프리 2015.09.02 2369
536 초대합니다! 새로운 RAD Studio : 윈도우 10 혜택을 누리세요! file 관리자 2015.08.28 288
535 이 달의 기술자료 - 2015년 09월 file 험프리 2015.08.26 489
534 [다음 버전 정보] C++11을 32비트 윈도우 앱 개발에서 사용할 수 있습니다. Humphery 2015.08.25 551
533 [다음 버전 정보] 안드로이드 서비스로 백그라운드 작업을 실행할 수 있습니다. Humphery 2015.08.25 770
532 [앵콜세미나] 사물인터넷 실제 구현하기, DeepDive!: 비콘, 스마트조명, 블루투스 체중계 관리자 2015.08.19 523
531 20150811 사물인터넷 실제 구현하기 DeepDive 세미나 발표자료 관리자 2015.08.12 489
530 RAD Studio VCL/FMX 앱에 윈도우 10 스타일 적용하기 file 관리자 2015.07.30 837
» [따라하기] 위험지역 경보 시스템 #1 - 위험지역 진입 경보앱 만들기 [1] Humphery 2015.07.30 3715
528 [사물인터넷 동영상] 위험 지역 경보 시스템 관리자 2015.07.28 493
527 [XE8] IDE 설정값을 내보내고 불러올 수 있어, 일관된 IDE 설정을 유지할 수 있습니다. file Humphery 2015.07.28 564
526 이 달의 기술자료 - 2015년 08월 험프리 2015.07.28 642
525 데이터스냅에서 제공하는 JSON 포맷 데이터 사용(분석)하기 [1] file Humphery 2015.07.20 3746
524 [XE8] 모바일 튜토리얼 무료 다운로드(영문), 총 364페이지 관리자 2015.07.09 1530