モバイル チュートリアル:位置センサを使用する(iOS および Android)
モバイル チュートリアル:モバイル アプリケーション開発(iOS および Android) への移動
目次
このチュートリアルを開始する前に、次のチュートリアルを読んで実行してください。
- モバイル チュートリアル:リスト ボックス コンポーネントを使用してテーブル ビューを表示する(iOS および Android)
- モバイル チュートリアル:Web ブラウザ コンポーネントを使用する(iOS および Android)
- モバイル チュートリアル:レイアウトを使用してフォームのさまざまなサイズや向きを調整する(iOS および Android)
メモ: Android デバイスでは、TLocationSensor に[おおよその位置情報へのアクセス]および[詳細な位置情報へのアクセス]の権限を設定する必要があります。
このチュートリアルでは、(緯度と経度を使用して)モバイル デバイスの位置を確認し、逆ジオコーディングによって次の図のような人が読み取れる住所に変換します。
ユーザー インターフェイスの設計
このデモ アプリケーションの設計には、2 つの主要コンポーネントが含まれています。TListBox(左側)と TWebBrowser です。
メモ: この作業を進める前に、[プロジェクト マネージャ]で、アクティブなターゲット プラットフォームを
[iOS デバイス]
または[Android]
に設定してください。そうでなければ TWebBrowser コンポーネントを追加できません。
TListBox および TWebBrowser コンポーネントを、フォーム上にドロップします。
- TListBox の Align プロパティを
Left
に設定して、UI の左側を確保します。その後、リスト ボックスの下に次のサブコンポーネントを作成します。- 以下のサブコンポーネントを含む TListBoxHeader コンポーネント
- テキスト "Location Demo" 付きの TLabel コンポーネント
- TLocationSensor のオン/オフを選択するための TSwitch(Switch1)コンポーネント
- テキストが "Your Location" の TListBoxGroupHeader
- 名前が "ListBoxItemLatitude"、テキストが "Latitude" の TListBoxItem
- 名前が "ListBoxItemLongitude"、テキストが "Longitude" の TListBoxItem
- テキストが "Current Address" の TListBoxGroupHeader
- 名前が "ListBoxItemAdminArea"、テキストが "AdminArea" の TListBoxItem
- 名前が "ListBoxItemCountryCode"、テキストが "CountryCode" の TListBoxItem
- 名前が "ListBoxItemCountryName"、テキストが "CountryName" の TListBoxItem
- 名前が "ListBoxItemFeatureName"、テキストが "FeatureName" の TListBoxItem
- 名前が "ListBoxItemLocality"、テキストが "Locality" の TListBoxItem
- 名前が "ListBoxItemPostalCode"、テキストが "PostalCode" の TListBoxItem
- 名前が "ListBoxItemSubAdminArea"、テキストが "SubAdminArea" の TListBoxItem
- 名前が "ListBoxItemSubLocality"、テキストが "SubLocality" の TListBoxItem
- 名前が "ListBoxItemSubThoroughfare"、テキストが "SubThoroughfare" の TListBoxItem
- 名前が "ListBoxItemThoroughfare"、テキストが "Thoroughfare" の TListBoxItem
- 以下のサブコンポーネントを含む TListBoxHeader コンポーネント
- Web ページ(Google マップ)を表示するための TWebBrowser コンポーネント(WebBrowser1)。Align プロパティを
Client
に設定します。
これらのコンポーネントを作成したら、すべての TListBoxItem 項目を選択し、StyleLookup プロパティに listboxitemleftdetail を選択します。これによって TListBoxItem にラベルと詳細テキストの両方が表示されます。
位置センサ
位置センサは、TLocationSensor コンポーネントにラップされています。
デバイスで移動が検出されると、TLocationSensor で OnLocationChanged イベントが発生します。TLocationSensor の感度は Distance プロパティと Accuracy プロパティで調整することができます。
- Distance プロパティは、位置センサにデバイスの位置を再検索させ、新しい位置情報を返させるために、デバイスが最低でも移動しなければならない距離(メートル単位)を示します。たとえば Distance を "10" に設定すると、"10 メートル" 移動したときに TLocationSensor で OnLocationChanged イベントが発生します。
- Accuracy プロパティは、センサが地理的にデバイスの位置を検索するときの、デバイスが実際に存在する地理的位置に対する精度(メートル単位)を表します。
- ヒント: アプリケーションに必要な最低の精度を指定してください。精度が高くなればなるほど、センサによる位置の決定に必要な時間と処理能力が増えるからです。推奨値は、Distance=0、Accuracy=0 です。
位置センサ コンポーネントからの位置情報(緯度、経度)の読み取り
TLocationSensor コンポーネントをアクティブ化して使用できるようにしなければなりません。TSwitch コンポーネントや他のアプリケーション イベントなどの入力によって、TLocationSensor をオン/オフすることができます。
- [ツール パレット]から TLocationSensor コンポーネントを配置します。
- フォーム デザイナで TSwitch コンポーネントを選択します。
- [オブジェクト インスペクタ]で[イベント]タブの OnSwitch イベントをダブルクリックします。
- OnSwitch イベント ハンドラに以下のコードを追加します。
procedure TForm1.Switch1Switch(Sender: TObject);
begin
LocationSensor1.Active := Switch1.IsChecked;
end;
void __fastcall TForm1::Switch1Switch(TObject *Sender)
{
LocationSensor1->Active = Switch1->IsChecked;
}
先ほど述べたように、モバイル デバイスを動かすと、TLocationSensor で OnLocationChanged イベントが発生します。イベント ハンドラでパラメータを使用して現在の位置(緯度と経度)を表示することができます。
- フォーム デザイナで TLocationSensor を選択します。
- [オブジェクト インスペクタ]で[イベント]タブの OnLocationChange イベントをダブルクリックします。
- OnLocationChange イベント ハンドラに以下のコードを追加します。
procedure TForm1.LocationSensor1LocationChanged(Sender: TObject;
const OldLocation, NewLocation: TLocationCoord2D);
var
LDecSeparator: String;
begin
LDecSeparator := FormatSettings.DecimalSeparator;
FormatSettings.DecimalSeparator := '.';
// Show current location
ListBoxItemLatitude.ItemData.Detail := Format('%2.6f', [NewLocation.Latitude]);
ListBoxItemLongitude.ItemData.Detail := Format('%2.6f', [NewLocation.Longitude]);
end;
void __fastcall TForm1::LocationSensor1LocationChanged(TObject *Sender, const TLocationCoord2D &OldLocation,
const TLocationCoord2D &NewLocation)
{
char LDecSeparator = FormatSettings.DecimalSeparator;
FormatSettings.DecimalSeparator = '.';
// Show current location
ListBoxItemLatitude->ItemData->Detail = ListBoxItemLatitude->ItemData->Detail.sprintf(L"%2.6f", NewLocation.Latitude);
ListBoxItemLongitude->ItemData->Detail = ListBoxItemLongitude->ItemData->Detail.sprintf(L"%2.6f", NewLocation.Longitude);
}
TWebBrowser コンポーネントで Google マップを使用した現在位置の表示
「モバイル チュートリアル:Web ブラウザ コンポーネントを使用する(iOS および Android)」で説明しているように、TWebBrowser コンポーネントにはモバイル プラットフォーム用の Web ブラウザがラップされています。
次の URL パラメータを使用すると、TWebBrowser コンポーネントから Google マップを呼び出すことができます。
https://maps.google.com/maps?q=(Latitude-value),(Longitude-value)
そのため、この URL を先ほど作成したイベント ハンドラ OnLocationChanged に追加します。コードは次のようになります。
procedure TForm1.LocationSensor1LocationChanged(Sender: TObject;
const OldLocation, NewLocation: TLocationCoord2D);
var
URLString: String;
begin
// code for previous step goes here
// Show Map using Google Maps
URLString := Format(
'https://maps.google.com/maps?q=%s,%s',
[Format('%2.6f', [NewLocation.Latitude]), Format('%2.6f', [NewLocation.Longitude])]);
WebBrowser1.Navigate(URLString);
end;
void __fastcall TForm1::LocationSensor1LocationChanged(TObject *Sender, const TLocationCoord2D &OldLocation,
const TLocationCoord2D &NewLocation)
{
// code for previous step goes here
// Show Map using Google Maps
String LLongitude = FloatToStr(NewLocation.Longitude, FormatSettings);
String URLString = "";
URLString = URLString.sprintf(L"https://maps.google.com/maps?q=%2.6f,%2.6f",
NewLocation.Latitude, NewLocation.Longitude);
FormatSettings.DecimalSeparator = LDecSeparator;
WebBrowser1->Navigate(URLString);
}
逆ジオコーディングの使用
TGeocoder は、ジオコーディング(または逆ジオコーディング)サービスをラップするオブジェクトです。
ジオコーディングとは、住所や郵便番号などの地理データを地理座標に変換する処理です。逆ジオコーディングとは、地理座標をそれ以外の住所などの地理データに変換する処理です。
ここでは、TGeocoder を使用して、位置(緯度と経度)を "逆ジオコーディング" し、人が読み取れる住所情報にします。
TGeocoder を使った作業の基本的な手順は次のとおりです。
- TGeocoder のインスタンスを作成します。
- イベント OnGeocodeReverse を定義して、後でイベントを受け取れるようにします。
- "逆ジオコーディング" を実行するためのデータを設定します。
- TGeocoder accesses the service on the network to resolve the address information.
- TGeocoder で OnGeocodeReverse イベントが発生します。
- iOS アプリケーションで、OnGeocodeReverse イベントのパラメータから住所情報を受け取り、ユーザー インターフェイスを更新します。
- メモ: TGeocoder はコンポーネントではないため(ただのクラスです)、これらの手順をコードで定義する必要があります(コンポーネントをドロップしたり[オブジェクト インスペクタ]でイベント ハンドラを割り当てることはできません)。
まず、フォームの private セクションに新しいフィールド "FGeocoder" を定義します。また、"OnGeocodeReverseEvent 手続き" も定義します。コードは次のとおりです。
type
TForm1 = class(TForm)
// IDE defines visible (or non-visual) components here automatically
private
{ Private declarations }
FGeocoder: TGeocoder;
procedure OnGeocodeReverseEvent(const Address: TCivicAddress);
public
{ Public declarations }
end;
C++ の場合:
- メモ: このコード スニペットをヘッダー ファイル (.h) に入れます。
class TForm1 : public TForm
{
// IDE defines visible (or non-visual) components here automatically
private: // User declarations
TGeocoder *FGeocoder;
void __fastcall OnGeocodeReverseEvent(TCivicAddress* const Address);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
これで、Delphi または C++ のコード(後に示します)で TGeocoder のインスタンスを作成し、データをセットアップすることができます。
TGeocoder.Current からは、ジオコーディング サービスを実際に実装しているクラスの型が返されます。"TGeocoder.Current.Create
" のコードでは、指定された型のコンストラクタ(Create)を呼び出し、FGeocoder フィールドに保存しています。また、TGeocoder の逆ジオコーディングが完了したときに発生するイベント ハンドラを指定する必要もあります。OnGeocodeReverseEvent(前のステップで定義したもの)を FGeocoder.OnGeocodeReverse に代入します。
最後に、TGeocoder のインスタンスの作成が成功していて、かつ TGeocoder が動作中でなければ、位置情報を渡して TGeocoder.GeocodeReverse を呼び出します。TGeocoder がデータを受け取ると、OnGeocodeReverseEvent イベントが発生します。
procedure TForm1.LocationSensor1LocationChanged(Sender: TObject;
const OldLocation, NewLocation: TLocationCoord2D);
begin
// code for previous steps goes here
try
// Setup an instance of TGeocoder
if not Assigned(FGeocoder) then
begin
if Assigned(TGeocoder.Current) then
FGeocoder := TGeocoder.Current.Create;
if Assigned(FGeocoder) then
FGeocoder.OnGeocodeReverse := OnGeocodeReverseEvent;
end;
// Translate location to address
if Assigned(FGeocoder) and not FGeocoder.Geocoding then
FGeocoder.GeocodeReverse(NewLocation);
except
ListBoxGroupHeader1.Text := 'Geocoder service error';
end;
end;
C++ の場合:
void __fastcall TForm1::LocationSensor1LocationChanged(TObject *Sender, const TLocationCoord2D &OldLocation,
const TLocationCoord2D &NewLocation)
{
// code for previous steps goes here
// Setup an instance of TGeocoder
try {
if (FGeocoder == NULL) {
if (TGeocoder::Current != NULL) {
FGeocoder = (TGeocoder*)new TGeocoderClass(TGeocoder::Current);
}
if (FGeocoder != NULL) {
FGeocoder->OnGeocodeReverse = OnGeocodeReverseEvent;
}
}
// Translate location to address
if ((FGeocoder != NULL) && (!(FGeocoder->Geocoding()))) {
FGeocoder->GeocodeReverse(NewLocation);
}
}
catch (...) {
ListBoxGroupHeader1->Text = "Geocoder service error";
}
}
リスト ボックス コンポーネントでの人が読み取れる住所の表示
先ほど述べたように、逆ジオコーディングが完了すると、OnGeocodeReverseEvent が発生します。
次に、住所パラメータ TCivicAddress に含まれるプロパティを代入して、人が読み取れる住所情報をリスト ボックス フィールドに表示します。
procedure TForm1.OnGeocodeReverseEvent(const Address: TCivicAddress);
begin
ListBoxItemAdminArea.ItemData.Detail := Address.AdminArea;
ListBoxItemCountryCode.ItemData.Detail := Address.CountryCode;
ListBoxItemCountryName.ItemData.Detail := Address.CountryName;
ListBoxItemFeatureName.ItemData.Detail := Address.FeatureName;
ListBoxItemLocality.ItemData.Detail := Address.Locality;
ListBoxItemPostalCode.ItemData.Detail := Address.PostalCode;
ListBoxItemSubAdminArea.ItemData.Detail := Address.SubAdminArea;
ListBoxItemSubLocality.ItemData.Detail := Address.SubLocality;
ListBoxItemSubThoroughfare.ItemData.Detail := Address.SubThoroughfare;
ListBoxItemThoroughfare.ItemData.Detail := Address.Thoroughfare;
end;
C++ の場合:
void __fastcall TForm1::OnGeocodeReverseEvent(TCivicAddress* const Address)
{
if (Address != NULL){
ListBoxItemAdminArea->ItemData->Detail = Address->AdminArea;
ListBoxItemCountryCode->ItemData->Detail = Address->CountryCode;
ListBoxItemCountryName->ItemData->Detail = Address->CountryName;
ListBoxItemFeatureName->ItemData->Detail = Address->FeatureName;
ListBoxItemLocality->ItemData->Detail = Address->Locality;
ListBoxItemPostalCode->ItemData->Detail = Address->PostalCode;
ListBoxItemSubAdminArea->ItemData->Detail = Address->SubAdminArea;
ListBoxItemSubLocality->ItemData->Detail = Address->SubLocality;
ListBoxItemSubThoroughfare->ItemData->Detail = Address->SubThoroughfare;
ListBoxItemThoroughfare->ItemData->Detail = Address->Thoroughfare;
}
}
アプリケーションでユーザー位置が必要な理由の記述
最終的なアプリケーションをデプロイする前に、[プロジェクト|オプション...|バージョン情報]を、iOS デバイスをターゲットとして、共に選択し、NSLocationAlwaysUsageDescription
および NSLocationWhenInUseUsageDescription
の値を、なぜアプリケーションがユーザーの場所を尋ねているかを説明するメッセージと共に、更新します。iOS デバイスの位置をアプリケーションに提供する権限を iOS に付与するように、ユーザーがアプリケーションから求められるときに、このメッセージが表示されます。
関連項目
- モバイル チュートリアル:レイアウトを使用してフォームのさまざまなサイズや向きを調整する(iOS および Android)
- モバイル チュートリアル:通知を使用する(iOS および Android)
- モバイル チュートリアル:リモート通知を使用する(iOS および Android)
- System.Sensors.TGeocoder
- System.Sensors.Components.TLocationSensor
- モバイル サンプル コード: Notifications
サンプル
- Location サンプル
- VCL Sensors サンプル