モバイル チュートリアル:FireDAC と SQLite を使用する(iOS および Android)
モバイル チュートリアル:モバイル アプリケーション開発(iOS および Android) への移動
目次
- 1 FireDAC を使用してデータベースに接続する
- 2 FireDAC フレームワークを使用してデータベースを作成する
- 3 ユーザー インターフェイスの設計とセットアップ
- 4 [LiveBinding ウィザード]を使用する
- 5 ユーザーがリストの項目を選択したときに削除ボタンを表示するためのイベント ハンドラを作成する
- 6 リストにエントリを追加するための追加ボタン用のイベント ハンドラを作成する
- 7 リストからエントリを削除するための削除ボタン用のイベント ハンドラを作成する
- 8 実行時用にアプリケーションを準備する
- 9 モバイル用にデータベースの配置をセットアップする
- 10 モバイル デバイス上のローカル データベース ファイルに接続するようコードを変更する
- 11 シミュレータまたはモバイル デバイス上でアプリケーションを実行する
- 12 関連項目
このチュートリアルを開始する前に、次のチュートリアルを読んで実行してください。
このチュートリアルでは、FireDAC フレームワークによりモバイル デバイス上のローカル データ ストレージとして SQLite を使用する基本手順を説明します。
iOS | Android |
---|---|
FireDAC を使用してデータベースに接続する
FireDAC は、Delphi および C++Builder でクロスプラットフォーム データベース アプリケーションを開発するための、他に類を見ない汎用データ アクセス コンポーネントです。 FireDAC を使用すると、その強力な共通アーキテクチャのため、Delphi から InterBase、SQLite、MySQL、SQL Server、Oracle、PostgreSQL、IBM DB2、SQL Anywhere、Access、Firebird、Informix などに高速かつ直接にネイティブ アクセスすることができます。
- モバイル プラットフォームの場合、FireDAC では InterBase ToGo および SQLite をサポートしています。これらのデータベース製品は iOS および Android デバイス上で動かすことができます。
- それ以外の Oracle などのデータベースでは、少なくともクライアント ライブラリが必要です。Windows プラットフォームでは、クライアント ライブラリは DLL として提供されていて、それに対して接続します。そのため、モバイル デバイスからこれらのデータベース製品に接続するには、DataSnap REST などの中間層技術を使ってアプリケーションを開発する必要があります。
FireDAC フレームワークを使用してデータベースを作成する
まず、開発用の Windows プラットフォームで SQLite データベース ファイルを作成します。フォーム デザイナを使ってモバイル アプリケーションのユーザー インターフェイスを設計できるよう、以下の手順を実施します。
- メモ: フォーム デザイナで、このチュートリアルの Master ビューを有効にします。
- マルチデバイス アプリケーションを作成するには、以下を選択します。
- Delphi の場合: [ファイル|新規作成|マルチデバイス アプリケーション - Delphi|空のアプリケーション]
- C++ の場合: [ファイル|新規作成|マルチデバイス アプリケーション - C++Builder|空のアプリケーション]
- [ツール パレット]で TFDConnection コンポーネントをダブルクリックします。
- TFDConnection コンポーネントを右クリックし、[接続エディタ...]を選択します。
- [FireDAC 接続エディタ]で、TFDConnection のパラメータを次のように設定します。
- [ドライバ ID]プロパティを SQLite に設定します。
- [Database]パラメータを次のように設定します。
C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\Data\shoplist.s3db
(データベースの場所)- [開く]ダイアログ ボックスで目的のフォルダに移動し、[開く]をクリックします。
- メモ: たとえ shoplist.s3db が存在しない場合でも RAD Studio が自動的に作成するため、上記のように[Database]パラメータを設定することができます ([開く]ダイアログに Employees.s3db または他の *.s3db ファイルを表示するには、[All Files (*.*)]オプションを選択します)。
- [LockingMode]パラメータを normal に設定します。
- [テスト]ボタンをクリックして、接続をテストします。
- [OK]をクリックして、[FireDAC 接続エディタ]を閉じます。
- [オブジェクト インスペクタ]で、TFDConnection のプロパティを次のように設定します。
- LoginPrompt プロパティを False に設定して、ユーザーにログインを求めるプロンプトを表示しないようにします。
- Connected プロパティを True に設定します。
- [ツール パレット]で TFDQuery コンポーネントをダブルクリックします。
- [オブジェクト インスペクタ]で、TFDQuery のプロパティを次のように設定します。
- Name プロパティを FDQueryCreateTable に設定します。
- SQL プロパティを次のように設定します。
CREATE TABLE IF NOT EXISTS Item (ShopItem TEXT NOT NULL)
- FDQueryCreateTable を右クリックして、[実行]を選択します。
ユーザー インターフェイスの設計とセットアップ
このチュートリアルでは、1 つの TListView コンポーネントを UI 要素として使用します。
以下の手順でリスト ビュー コンポーネントなどの UI 要素をセットアップします。
- フォームに TToolBar をドロップします。
- ツールバー コンポーネント上に TButton をドロップし、[オブジェクト インスペクタ]で次のプロパティを設定します。
- Name プロパティを ButtonAdd に設定します。
- StyleLookup を addtoolbutton に設定します。
- Align を Right に設定します。
- ツールバー コンポーネント上に TButton をドロップし、[オブジェクト インスペクタ]で次のプロパティを設定します。
- Name プロパティを ButtonDelete に設定します。
- StyleLookup を deletetoolbutton に設定します。
- Align を Left に設定します。
- Text を「Delete」に設定します。
- Visible プロパティを False に設定します。
- ツールバー コンポーネント上に TLabel をドロップし、[オブジェクト インスペクタ]で次のプロパティを設定します。
- Align を Client に設定します。
- StyleLookup を toollabel に設定します。
- Text を「Shopping List」に設定します。
- TTextSettings ノードを展開し、HorzAlign プロパティを Center に設定します。
- TListView コンポーネントをフォームにドロップし、[オブジェクト インスペクタ]で次のプロパティを設定します。
- Align プロパティを Client に設定して、リスト ビュー コンポーネントがフォーム全体を占めるようにします。
[LiveBinding ウィザード]を使用する
このチュートリアルでは[LiveBinding ウィザード]を使用して、LiveBinding コンポーネント(TBindSourceDB、TBindingsList)や TFDQuery コンポーネントを追加します。
LiveBinding コンポーネントを追加する
- [表示|LiveBinding デザイナ]を選択して[LiveBinding デザイナ]を開きます。
- [LiveBinding ウィザード...]を選択します。
- [データ ソースの作成]バインディング タスクを選択します。
- [次へ >>]ボタンをクリックします。
- クラス名に[FireDAC]を選択します。
- [次へ >>]ボタンをクリックします。
- [コマンド タイプ]を Query に変更します。
- [コマンド テキスト]プロパティを
select ShopItem from Item
に設定します。 - [コマンドのテスト]ボタンをクリックします。
- [次へ >>]ボタンをクリックします。
- [完了]ボタンをクリックします。
この時点で、TBindSourceDB コンポーネントと TFDQuery コンポーネントがフォームに追加されています。
データに接続する
- [LiveBinding ウィザード]をもう一度開きます。
- [コントロールをフィールドとリンク]バインディング タスクを選択します。
- [次へ >>]ボタンをクリックします。
- [既存コントロール]タブを選択します。
- ListView1 コンポーネントを選択します。
- [次へ >>]ボタンをクリックします。
- BindSourceDB1 を選択します。
- [次へ >>]ボタンをクリックします。
- フィールド名に ShopItem を選択します。
- [次へ >>]ボタンをクリックします。
- [完了]ボタンをクリックしてウィザードを閉じます。
メモ: BindSourceDB1 に 1 つのフィールドしかないため、このチュートリアルでは、これら最後のステップは必須ではありません。これらのステップは、データベースの複数のフィールドを管理する場合、選択した値とリンクするうえでも役に立ちます。
ListView で ShopItem を表示する
次のステップでは、TListView コンポーネントで ShopItem のテキストを表示します。
- [LiveBinding デザイナ]おいて、BindSourceDB1 コンポーネントの ShopItem を選択し、ShopItem を、ListView1 の Item.Text にドラッグします。
この手順を実施すると、アプリケーションのユーザー インターフェイスが SQLite データベースのデータに接続されます。データが既に含まれたテーブルをこのチュートリアルで使用している場合には、これでフォーム デザイナに実際のデータが表示されるはずです。
ユーザーがリストの項目を選択したときに削除ボタンを表示するためのイベント ハンドラを作成する
[Delete]ボタンの Visible プロパティは False に設定されています。そのため、このボタンはデフォルトでエンド ユーザーから見えなくなっています。次のようにすると、ユーザーがリストの項目を選択したときにこのボタンを表示することができます。
- ListView1 を選択し、OnItemClick イベント用に次のイベント ハンドラを定義します。
Delphi の場合:
procedure TForm1.ListView1ItemClick(const Sender: TObject;
const AItem: TListViewItem);
begin
ButtonDelete.Visible := ListView1.Selected <> nil;
end;
- C++ の場合:
void __fastcall TForm1::ListView1ItemClick(const TObject *Sender,
const TListViewItem *AItem) {
ButtonDelete->Visible = (ListView1->Selected != NULL);
}
リストにエントリを追加するための追加ボタン用のイベント ハンドラを作成する
次のステップでは、項目をショッピング リストに追加する機能をアプリケーションに追加します。
- TFDQuery コンポーネントをフォームにドロップします。
- [オブジェクト インスペクタ]で次のプロパティを設定します。
- [構造]ビューで ButtonAdd コンポーネントを右クリックし、[コントロール|前面に移動]を選択します。これにより、ボタンがアクティブ フォームの表示の前面に移動します。
- Delphi の場合:
- private セクションで次の手続きを宣言します。
private
procedure OnInputQuery_Close(const AResult: TModalResult; const AValues: array of string);
- 次のプロシージャを追加します :
procedure TForm1.OnInputQuery_Close(const AResult: TModalResult; const AValues: array of string);
var
TaskName: String;
begin
TaskName := string.Empty;
if AResult <> mrOk then
Exit;
TaskName := AValues[0];
try
if (TaskName.Trim <> '')
then
begin
FDQueryInsert.ParamByName('ShopItem').AsString := TaskName;
FDQueryInsert.ExecSQL();
FDQuery1.Close();
FDQuery1.Open;
ButtonDelete.Visible := ListView1.Selected <> nil;
end;
except
on e: Exception do
begin
ShowMessage(e.Message);
end;
end;
end;
- フォーム デザイナで ButtonAdd コンポーネントをダブルクリックします。このイベント ハンドラに次のコードを追加します。
procedure TForm1.ButtonAddClick(Sender: TObject);
begin
TDialogServiceAsync.InputQuery('Enter New Item', ['Name'], [''], Self.OnInputQuery_Close)
end;
- C++ の場合:
C++ で同じ機能を複製するには、追加手順が必要です。
- (ユニットの .h ファイルで)TForm1 定義の後に次の定義を追加します。
typedef void __fastcall(__closure * TInputCloseQueryProcEvent)
(const System::Uitypes::TModalResult AResult,
System::UnicodeString const *AValues, const int AValues_High);
- (お使いのユニットの .h ファイルで上記の型定義の後に)次のクラス定義を追加します。
class InputQueryMethod : public TCppInterfacedObject<TInputCloseQueryProc>
{
private:
TInputCloseQueryProcEvent Event;
public:
InputQueryMethod(TInputCloseQueryProcEvent _Event) {
Event = _Event;
}
void __fastcall Invoke(const System::Uitypes::TModalResult AResult,
System::UnicodeString const *AValues, const int AValues_High) {
Event(AResult, AValues, AValues_High);
}
};
- (お使いのユニットの .h ファイルで)フォームの private セクション下に次の宣言を追加します。
private: //User declarations
void __fastcall OnInputQuery_Close
(const System::Uitypes::TModalResult AResult,
System::UnicodeString const *AValues, const int AValues_High);
- (お使いのユニットの .cpp ファイルに)次のコードを追加します。
void __fastcall TForm1::OnInputQuery_Close(const System::Uitypes::TModalResult AResult,
System::UnicodeString const *AValues, const int AValues_High) {
String TaskName;
TaskName = "";
if (AResult != mrOk)
return;
TaskName = AValues[0];
try {
if (!(Trim(TaskName) == "")) {
FDQueryInsert->ParamByName("ShopItem")->AsString = TaskName;
FDQueryInsert->ExecSQL();
FDQuery1->Close();
FDQuery1->Open();
ButtonDelete->Visible = (ListView1->Selected != NULL);
}
}
catch (Exception &e) {
ShowMessage(e.Message);
}
}
- フォーム デザイナで ButtonAdd コンポーネントをダブルクリックします。このイベント ハンドラに次のコードを追加します。
void __fastcall TForm1::ButtonAddClick(TObject *Sender) {
String caption = "Enter New Item";
String Prompts[1];
Prompts[0] = "Name:";
String Defaults[1];
Defaults[0] = "";
_di_TInputCloseQueryProc Met = new InputQueryMethod(&OnInputQuery_Close);
TDialogServiceAsync::InputQuery(
caption, Prompts, 0, Defaults, 0, (TInputCloseQueryProc *)Met);
}
InputQuery 関数は、エンド ユーザーにテキストの入力を求めるダイアログ ボックスを表示します。 この関数は、ユーザーが OK を選択した際に True を返すため、データベースでデータを追加できるのは、ユーザーが OK を選択し、かつテキストにデータが含まれているときのみです。
iOS | Android |
---|---|
リストからエントリを削除するための削除ボタン用のイベント ハンドラを作成する
次のステップでは、項目をショッピング リストから削除する機能をアプリケーションに追加します。
- TFDQuery コンポーネントをフォームにドロップします。
- [オブジェクト インスペクタ]で次のプロパティを設定します。
- [構造]ビューで ButtonDelete コンポーネントを右クリックし、[コントロール|前面に移動]を選択します。これにより、ボタンがアクティブ フォームの表示の前面に移動します。
- フォーム デザイナで ButtonDelete コンポーネントをダブルクリックします。このイベント ハンドラに次のコードを追加します。
- Delphi の場合:
procedure TForm1.ButtonDeleteClick(Sender: TObject);
var
TaskName: String;
begin
TaskName := TListViewItem(ListView1.Selected).Text;
try
FDQueryDelete.ParamByName('ShopItem').AsString := TaskName;
FDQueryDelete.ExecSQL();
FDQuery1.Close;
FDQuery1.Open;
ButtonDelete.Visible := ListView1.Selected <> nil;
except
on e: Exception do
begin
SHowMessage(e.Message);
end;
end;
end;
- C++ の場合:
void __fastcall TForm1::ButtonDeleteClick(TObject *Sender) {
String TaskName = ((TListViewItem*)(ListView1->Selected))->Text;
try {
FDQueryDelete->ParamByName("ShopItem")->AsString = TaskName;
FDQueryDelete->ExecSQL();
FDQuery1->Close();
FDQuery1->Open();
ButtonDelete->Visible = (ListView1->Selected != NULL);
}
catch (Exception &e) {
ShowMessage(e.Message);
}
}
実行時用にアプリケーションを準備する
FireDAC は疎結合の多層アーキテクチャを備えており、各レイヤでサービスが提供されます。それぞれのサービス API は、他のレイヤからインターフェイス ファクトリを使って要求できる COM インターフェイスとして定義されています。
FireDAC を適切に動作させるには、IFDGUIxWaitCursor インターフェイスと IFDPhysDriver インターフェイスの実装をアプリケーションにリンクする必要があります。
そのために、TFDGUIxWaitCursor コンポーネントと TFDPhysSQLiteDriverLink コンポーネントをフォームにドロップします。
モバイル用にデータベースの配置をセットアップする
ここまでは、デスクトップで SQLite を使用してきました。 つまり、実際のデータベースは、ローカルのハード ディスク ドライブ上(C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\Data\shoplist.s3db など)にあります。 モバイル デバイスでは、アプリケーションはサンドボックス化されるため、通常はアプリケーション フォルダ下の Documents フォルダ(iOS デバイスの場合)および internal 記憶域(Android デバイスの場合)にあるデータしか読み書きできません。
モバイル上でローカル データベースに接続するには、以下の作業を実施する必要があります。
- データベースをモバイル デバイスに配置する。
- (データベース ファイルに接続するための)構成を、Documents フォルダ(iOS デバイスの場合)または internal 記憶域(Android デバイスの場合)のローカル ファイルにチェックする。
データベース ファイルを配置マネージャに追加し構成する
モバイル上でアプリケーションを実行するには、データベース ファイル(shoplist.s3db)の配置情報をセットアップする必要があります。
- データベースは、次の 2 つの方法のいずれかでプロジェクトに追加することができます。
- プロジェクト マネージャ でプロジェクト名を右クリックし、そのコンテキスト メニューから[追加...]を選択して(または[プロジェクト|プロジェクトに追加...])、[プロジェクトに追加]ダイアログ ボックスに表示させます。データベースの場所
C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\Data
まで移動し、データベースのshoplist.s3db
を選択し、[開く]をクリックします。 - データベースの場所
C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\Data
まで移動し、データベースのshoplist.s3db
をプロジェクト マネージャ内のプロジェクトまでドラック&ドロップします。[はい]をクリックして、プロジェクトへのファイル追加を確定します。
- プロジェクト マネージャ でプロジェクト名を右クリックし、そのコンテキスト メニューから[追加...]を選択して(または[プロジェクト|プロジェクトに追加...])、[プロジェクトに追加]ダイアログ ボックスに表示させます。データベースの場所
- データベース ファイルを追加したら、[機能ファイル]ウィンドウが表示されるので、[キャンセル]をクリックして閉じます。
- 配置マネージャを、[プロジェクト|配置]を選択して開きます。
- 配置マネージャ上部のターゲット プラットフォームのドロップダウン リストで、[Debug 構成 - iOS デバイス - 32 ビット プラットフォーム]、[Debug 構成 - iOS デバイス - 64 ビット プラットフォーム]、または、[Debug 構成 - Android プラットフォーム]を選択し、データベース
shoplist.s3db
がプラットフォームに追加されていることを確認します。 shoplist.s3db
のリモート パスが、iOS プラットフォームおよび Android プラットフォーム用にどのように設定されたか確認してください。- iOS デバイス プラットフォームの[リモート パス]:
StartUp\Documents\
- Android プラットフォームの[リモート パス]:
assets\internal\
- iOS デバイス プラットフォームの[リモート パス]:
このように構成すると、モバイル デバイス上でアプリケーションを実行したときに、マルチデバイス アプリケーションのサンドボックス領域の Documents フォルダ(iOS プラットフォームの場合)または internal 記憶域(Android プラットフォームの場合)にデータベース ファイル(shoplist.s3db)を配置するよう、設定されます。
モバイル デバイス上のローカル データベース ファイルに接続するようコードを変更する
このアプリケーションの基本的な機能の実装はこれで終わりです。 このチュートリアルで示す手順に従って、Windows 上にデータベース ファイルを作成しました。 このデータベース ファイルは、モバイル デバイスにコピーするかその場で作成しなければ、モバイル デバイス上で使用できません。
SQLite のデータベースおよびテーブルは次の手順で作成することができます。
モバイル デバイス上での SQLite データベースの場所を指定する
- フォーム デザイナで FDConnection1 コンポーネントを選択します。
- [オブジェクト インスペクタ]で BeforeConnect イベントをダブルクリックします。
- このイベント ハンドラに次のコードを追加します。
- Delphi の場合:
procedure TForm1.FDConnection1BeforeConnect(Sender: TObject);
begin
{$IF DEFINED(iOS) or DEFINED(ANDROID)}
FDConnection1.Params.Values['Database'] :=
TPath.Combine(TPath.GetDocumentsPath, 'shoplist.s3db');
{$ENDIF}
end;
TPath レコードは System.IOUtils ユニットで宣言されているため、ユニットの uses 句に System.IOUtils を追加する必要があります。
implementation
{$R *.fmx}
uses System.IOUtils;
- C++ の場合:
void __fastcall TForm1::FDConnection1BeforeConnect(TObject *Sender) {
#if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)
FDConnection1->Params->Values["Database"] =
System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath
(), "shoplist.s3db");
#endif
}
#include <System.IOUtils.hpp> を追加する必要があります。
テーブルが存在しなければ作成する
SQLite では、CREATE TABLE IF NOT EXISTS
文を使用すると、テーブルが存在しない場合に作成することができます。テーブルの作成は、TFDConnection コンポーネントがデータベースに接続した後、TFDQuery コンポーネントがテーブルに接続する前に行うことができます。手順は以下のとおりです。
- フォーム デザイナで FDConnection1 コンポーネントを選択します。
- [オブジェクト インスペクタ]で AfterConnect イベントをダブルクリックします。
- このイベント ハンドラに次のコードを追加します。
- Delphi の場合:
procedure TForm1.FDConnection1AfterConnect(Sender: TObject);
begin
FDConnection1.ExecSQL('CREATE TABLE IF NOT EXISTS Item (ShopItem TEXT NOT NULL)');
end;
- C++ の場合:
void __fastcall TForm1::FDConnection1AfterConnect(TObject *Sender) {
FDConnection1->ExecSQL("CREATE TABLE IF NOT EXISTS Item (ShopItem TEXT NOT NULL)");
}
シミュレータまたはモバイル デバイス上でアプリケーションを実行する
これで、シミュレータまたは接続したモバイル デバイスの上でアプリケーションを実行する準備ができました。
アプリケーションを実行するには:
- [プロジェクト マネージャ]でターゲット プラットフォームを選択します。
- 次のいずれかのコマンドを選択します。
- [実行|実行]
- [実行|デバッガを使わずに実行]
iOS | Android |
---|---|
メモ: アプリケーションの実行時に問題が発生した場合には、「トラブルシューティング」で説明している手順を行ってください。