15 MAF AMXでのバインディングの使用とデータ・コントロールの作成
この章の内容は次のとおりです。
バインディングおよびデータ・コントロールの概要
データ・コントロールは、標準のメタデータ・インタフェースを使用して、ビジネス・サービスの操作とデータ・コレクションを記述します。その一方で、宣言的バインディングはデータ・コントロールからのデータへのアクセスに関する情報を格納します。モデル・レイヤーは、データ・コントロールとバインディングに関する情報について関連XMLファイルを読み取って、ユーザー・インタフェースをビジネス・サービスに接続します。
モバイル・アプリケーション・フレームワークによって、ユーザー・インタフェース(UI)・テクノロジとビジネス・サービス実装の分離を可能にする2つの概念(データ・コントロールと宣言的バインディング)が実装されています。データ・コントロールでは、関連するプロパティ、メソッド、タイプの情報を含め、サービスの操作とデータ・コレクションを表す標準のメタデータ・インタフェースを使用してビジネス・サービスの実装技術を抽象化します。JDeveloperを使用すると、その情報をアイコンとして表示し、ページ上にドラッグ・アンド・ドロップできます。宣言的なバインディングによって、データ・コントロール内のデータ・コレクションからのデータ・アクセスとその操作の実行の詳細が抽象化されます。実行時に、モデル・レイヤーによって、適切なXMLファイルからデータ・コントロールおよびバインディングを記述した情報が読み取られ、ユーザー・インタフェースとビジネス・サービスの双方向の結合が実装されます。
ページのユーザー・インタフェース・コンポーネントをサポートするバインディングのグループは、ページ定義ファイルというページ固有のXMLファイルに記述されます。モデル・レイヤーは、このファイルを実行時に使用して、ページのバインディングをインスタンス化します。これらのバインディングは、バインディング・コンテナと呼ばれるリクエスト・スコープ・マップに保持され、EL式#{bindings}
を使用して各ページ・リクエスト中にアクセスできます。この式により、現在のページのバインディング・コンテナが常に評価されます。「データ・コントロール」パネルから項目をドラッグし、それを特定のUIコンポーネントとしてページ上にドロップすることで、データバインドされたユーザー・インタフェースを設計できます。データ・コントロールを使用してUIコンポーネントを作成すると、そのコンポーネントを選択したデータ・コントロールにバインドするために必要なコードおよびオブジェクトがJDeveloperによって自動的に作成されます。
モバイル・アプリケーション・フレームワークには、即時利用可能な2つのデータ・コントロール(DeviceFeaturesデータ・コントロールとApplicationFeaturesデータ・コントロール)が付属しています。JDeveloperの「データ・コントロール」パネル内に表示されるDeviceFeaturesデータ・コントロールを使用すると、データ・コントロールの主なデータ属性を(テキスト)フィールドとして、またデータ・コントロールの操作をコマンド・オブジェクト(ボタン)として、アプリケーションにドラッグ・アンド・ドロップできます。これらのドラッグ・アンド・ドロップ・アクションによって、アプリケーション内のELバインディングおよび作成されるコントロールに適したプロパティが生成されます。バインディングはDataControls.dcx
ファイルで表され、データ・コントロール・ソースを指しています。また、ページ・バインディングは特定のページの参照をデータ・コントロールにリンクします。ApplicationFeaturesデータ・コントロールの詳細は、「MAF AMXコンテンツによるカスタムSpringboardアプリケーション機能に関する必知事項」を参照してください。
データ・コントロールおよびバインディングの詳細は、次を参照してください。
オブジェクト・スコープ・ライフサイクルについて
スコープは、実行時にEL式を使用してアプリケーションがアクセスできるオブジェクトをメモリー内の永続化します。スコープによって、オブジェクト(アプリケーションやタスク・フローなど)の存続期間と可用性が決定されます。
実行時、ページがデータにアクセスできるオブジェクト・スコープに必要なデータを格納することで、データをページに渡します。スコープによってオブジェクトの存続期間が決まります。オブジェクトをスコープに置くと、EL式を使用してスコープからアクセスできます。たとえば、foo
という名前のマネージドBeanを作成し、Beanをビュー・スコープに存続させるよう定義するとします。このBeanにアクセスするには、#{viewScope.foo}
という式を使用します。
モバイル・アプリケーション・フレームワークの変数とマネージドBeanの参照は、変数の存続期間と可視性を決定する様々なオブジェクト・スコープ内で定義されます。MAFは、次のスコープ(可視性が高い順に表示)をサポートしています。
-
アプリケーション・スコープ: オブジェクトは、アプリケーションが存続するかぎり(複数の機能にまたがって)使用可能です。
-
ページ・フロー・スコープ: オブジェクトは、ページ・フロー・スコープのマネージドBeanがどこに定義されているかによって、機能(単一の機能の境界)またはタスク・フローが存続するかぎり使用できます。Beanがバインドなしタスク・フローに定義されている場合、そのスコープは機能です。Beanがバインド・タスク・フローに定義されている場合、そのスコープはタスク・フローに限定されます。
-
ビュー・スコープ: オブジェクトは、ビューが存続するかぎり(機能の単一ページ内で)使用可能です。
オブジェクト・スコープは、プログラミング言語のグローバル変数およびローカル変数のスコープに相当します。スコープが広いほど、オブジェクトの可用性が高くなります。存続期間の間、これらのオブジェクトで特定のインタフェースの公開、情報の保持および他のオブジェクトへの変数とパラメータの受渡しを行うことができます。たとえば、アプリケーション・スコープに定義されているマネージドBeanは、アプリケーションが存続するかぎり、複数のページ・リクエストの間使用できます。ただし、ビュー・スコープに定義されているマネージドBeanは、1つの機能で1つのページ・リクエストの間のみ使用できます。
アプリケーション・スコープの名前空間で定義されたEL式は、アプリケーションが存続するかぎり、複数の機能にまたがって使用できます。アプリケーションの一方のビューでアプリケーション・スコープを定義し、そのスコープをもう一方のビューで参照できます。ページ・フロー・スコープの名前空間で定義されたEL式は、機能が存続するかぎり、単一の機能の境界内で使用できます。ビュー・スコープの名前空間で定義されたEL式は、ビューが存続するかぎり、機能の単一ページの境界内で使用できます。スコープを含むこのような変数に加えて、MAFでは、デバイス・プロパティとアプリケーション・プリファレンスに関する情報を公開できるスコープが定義されています。これらのスコープによって、アプリケーション・レベルの存続期間と可視性が決まります。「マネージドBeanカテゴリについて」および「モバイル・アプリケーション・フレームワーク・オブジェクト・カテゴリについて」を参照してください。
マネージドBeanを登録するスコープまたは値を格納するスコープを決める場合、可能なかぎり狭いスコープを常に使用するようにします。アプリケーション・スコープは、ユーザー情報やコンテキスト情報などのアプリケーション全体に関係する情報にのみ使用します。アプリケーション・スコープは、ページ間での値の受渡しには使用しないでください。
注意:
メモリー・スコープに入れる各オブジェクトはJSON DataChangeEvent
に対してシリアライズされ、このオブジェクト内のゲッター・メソッドによって戻されるオブジェクトもシリアライズされます。これは、ネストが深いシリアライズされたオブジェクト・ツリーにつながることがあり、パフォーマンスが低下します。一連のネストされたオブジェクトのシリアライズを避けるには、それらを一時オブジェクトとして定義する必要があります。「Beanクラス変数のシリアライズに関する必知事項」を参照してください。
オブジェクト・スコープとタスク・フローに関する必知事項
ページ・フロー・スコープは、タスク・フロー内のアクティビティ間でデータ値を受け渡しするために使用します。また、変数のビュー・スコープは現在のビュー・アクティビティ内でのみ必要になります。
タスク・フロー内の変数にどのスコープを使用するかを決定するときは、ビュー・スコープまたはページ・フロー・スコープのみを使用する必要があります。アプリケーション・スコープは、タスク・フローの存続期間を超えてオブジェクトをメモリーに保持するため、タスク・フローのカプセル化および再利用で障害が発生します。さらに、アプリケーション・スコープでは、オブジェクトがメモリーに必要以上に長い時間保持されるため、不要なオーバーヘッドが発生します。
タスク・フロー内のアクティビティ間でデータ値を渡す必要がある場合は、ページ・フロー・スコープを使用する必要があります。現在のビュー・アクティビティ内でのみ必要とされ、ビュー・アクティビティ間にまたがっていない変数の場合、ビュー・スコープを使用する必要があります。
EL式の作成
EL式は、実行時に決定されるオブジェクト値に属性をバインドするために、MAFアプリケーションで使用されます。EL式は、コードを使用することなく、個別のオブジェクトとそのプロパティへのアクセスを自動化するために、ページ定義ファイルを使用して構築します。
MAFアプリケーションのEL式を使用して、属性と実行時に決まるオブジェクト値とをバインドします。たとえば、#{UserList.selectedUsers}
は選択したユーザーのセットを参照でき、#{user.name}
は特定のユーザー名を参照でき、#{user.role == 'manager'}
はユーザーがマネージャかどうかを判断します。実行時、汎用式エバリュエータによって、これらの式に対してそれぞれList
、String
およびboolean
の値が返され、コードなしで自動的に各オブジェクトとそのプロパティにアクセスします。
値の表示に必要になるまで式は評価されません。MAF AMXでは遅延評価のみがサポートされるため、即時構成式(${}
)を使用する式は解析を行いますが、その動作は遅延式(#{}
)と同じになります。実行時、特定のUIコンポーネント(inputText
コンポーネント、outputText
コンポーネントなど)の値は、そのvalue
属性によって決まります。コンポーネントにはその値として静的テキストを割り当てることができますが、通常、value
属性には、表示データを決定するために実行時インフラストラクチャにより評価されるEL式が含まれます。たとえば、現在ログイン中のユーザーの名前を表示するoutputText
コンポーネントには、value
属性に#{UserInfo.name}
という式を設定できます。コンポーネントの任意の属性(value
属性だけでなく)にEL式を使用して値を割り当てることができるため、動的、かつデータ駆動型のユーザー・インタフェースの作成が容易になります。たとえば、UIコンポーネントのrendered
属性に#{not empty UserList.selectedUsers}
などのブール値の式を使用すると、表示するオブジェクト・セットが空のときにはそのコンポーネントを非表示にできます。UserList
というオブジェクトの選択ユーザーのリストが空の場合、rendered
属性はfalse
と評価されるため、コンポーネントはページに表示されません。
通常のアプリケーションでは、UserList
のようなオブジェクトはマネージドBeanとして作成します。ランタイムでは、EL式でBeanを最初に参照した際に、Beanのオンデマンドのインスタンス化が管理されます。値を表示する場合、ページを表示する際にランタイムでEL式が評価され、マネージドBeanから値を得て、コンポーネントにデータが移入されます。ユーザーがUIコンポーネントのデータを更新すると、同じEL式に基づいて、ランタイムによって対応するマネージドBeanに値が戻されます。「マネージドBeanの作成および使用」を参照してください。EL式の詳細は、http://www.oracle.com/technetwork/java/index.html
にあるJava EEチュートリアルを参照してください。
注意:
EL式を編集可能コンポーネントのvalue
属性に使用している場合は、そのコンポーネントに対応するset
メソッドが必要です。そうでないと、EL式は読取り専用と評価され、値の更新は許可されません。
たとえば、ページにinputText
コンポーネント(IDはit1
)があり、その値が#{myBean.inputValue}
に設定されているとします。inputText
値を更新するには、myBean
マネージドBeanに次のようなget
およびset
メソッドが必要です。
public void setIt1(RichInputText it1) { this.it1 = it1; } public RichInputText getIt1() { return it1; }
データ・バインディングEL式について
データ・バインディング式は、「データ・コントロール」パネルを使用してUIコントロールを作成するときに、MAFによって作成されます。また、MAFデータ・バインディング式は、手動で追加または編集することもできます。
「データ・コントロール」パネルを使用してコンポーネントを作成すると、MAFデータ・バインディング式が自動的に作成されます。この式は、バインディング・オブジェクトのデータを表示するか、バインディング・オブジェクトのプロパティを参照する、すべてのコンポーネント属性に追加されます。事前作成済のそれぞれの式は、ページ定義ファイルで定義された、適切なバインディング・オブジェクトを参照します。これらのバインディング式は編集可能ですが、MAFバインディング式の基本構文に従っていれば、独自に作成することもできます。MAFデータ・バインディング式は、属性がELをサポートする場合、バインディング・オブジェクトからのデータを移入する任意のコンポーネント属性に追加できます。
一般的なMAFデータ・バインディングEL式は、次の構文を使用して、バインディング・コンテナ内のタイプの異なるバインディング・オブジェクトを参照します。
#{bindings.BindingObject.propertyName}
各要素の説明は次のとおりです。
-
bindings
は、式によって参照されているバインディング・オブジェクトが現在のページのバインディング・コンテナにあることを識別する変数です。すべてのMAFデータ・バインディングEL式は、bindings
変数で始まる必要があります。 -
BindingObject
は、ページ定義ファイルで定義される、バインディング・オブジェクトのID、または属性については名前です。バインディングobjectID
または名前は、そのページ定義ファイル内で一意なものです。EL式は、パラメータ・バインディング、実行可能バインディングまたは値バインディングなど、ページ定義ファイル内のどのバインディング・オブジェクトでも参照できます。 -
propertyName
は、各データバインドUIコンポーネントのデフォルトの表示方法を決定し、実行時のバインディング・オブジェクトのプロパティを設定する変数です。各タイプのバインディング・オブジェクトに対して、異なるバインディング・プロパティがあります。「MAFバインディング・プロパティに関する必知事項」を参照してください。
たとえば、次の式を例にしてみます。
#{bindings.ProductName.inputValue}
bindings
変数は、現在のページのバインディング・コンテナでバインドされた値を参照します。参照されているバインディング・オブジェクトはProductName
であり、これは属性バインディング・オブジェクトです。バインディング・プロパティはinputValue
で、最初のProductName
属性の値を戻します。
ヒント:
ページ定義ファイルのバインディング式ではドル記号($
)またはハッシュ記号(#
)の接頭辞を使用できますが、MAFページのEL式で使用できるのは、ハッシュ記号(#
)の接頭辞のみです。
前述のように、「データ・コントロール」パネルを使用してUIコンポーネントを作成する場合、これらの式が組み込まれます。ただし、必要に応じて手動で式を作成することもできます。JDeveloperの式ビルダーは、UIコンポーネントがバインドされるその他の有効なオブジェクトに加え、ページ定義ファイルに定義されたバインディング・オブジェクトのリストを提供することにより、EL式の構築を支援するダイアログです。また、MAFバインディング・オブジェクトの階層リストやMAFバインディング・オブジェクトの最も一般的に使用されるプロパティが提供されるため、MAFデータバインド式の作成や編集に特に便利です。「MAFバインディング・プロパティに関する必知事項」を参照してください。
EL式の作成方法
JDeveloperの式ビルダーを使用してEL式を宣言的に作成できます。「プロパティ」ウィンドウから「式ビルダー」にアクセスできます。
メソッド式ビルダーについて
「プロパティ」ウィンドウの「メソッド式ビルダー」は、「式ビルダー」と似ていますが、「メソッド式ビルダー」は選択したプロパティに応じてマネージドBeanにフィルタを適用します。
表15-2は、「プロパティ」ウィンドウで「式ビルダー」オプションではなく「メソッド式ビルダー」オプションが提供されるプロパティを示しています。これらの唯一の違いは、メソッド式ビルダーが、選択されたプロパティに応じてマネージドBeanをフィルタして除外することです。
表15-2 メソッド式ビルダーのプロパティ
プロパティ | 要素 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
非ELプロパティについて
ELに対応していないプロパティには、「プロパティ」ウィンドウで選択可能なEL式ビルダー・オプションオプションがありません。
表15-3は、ELに対応していないため「プロパティ」ウィンドウでEL式ビルダー・オプションが提供されないプロパティを示しています。
表15-3 非ELプロパティ
プロパティ | 要素 |
---|---|
|
すべての要素 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MAFバインディング・プロパティに関する必知事項
式ビルダーを使用してデータバインドされたコンポーネントを作成すると、EL式は、Oracle APIで定義された特定のMAFバインディング・プロパティを参照することがあります。
式ビルダーを使用してデータバインド・コンポーネントを作成すると、EL式によって、特定のMAFバインディング・プロパティが参照される場合があります。実行時には、これらのバインディング・プロパティによって、データバインドUIコンポーネントのデフォルトの表示方法や、イテレータ・バインディング固有のパラメータなどが定義されます。バインディング・プロパティは、Oracle APIによって定義されます。各バインディング・タイプで使用可能なプロパティの完全なリストは、表15-4を参照してください
特定のプロパティに割り当てられる値は、ページ定義ファイルで定義されます。たとえば、イテレータ・バインディングには、イテレータが一度に表示する行数を指定する、RangeSize
というプロパティがあります。RangeSize
に割り当てられた値は、次の例に示すようにページ定義ファイルで指定されます。
<iterator Binds="ItemsForOrder" RangeSize="25" DataControl="BackOfficeAppModuleDataControl" id="ItemsForOrderIterator" ChangeEventPolicy="ppr"/>
イテレータ間でデータ・プロバイダの状態の保持を有効にする方法
データ・コレクション・インスタンスにアクセスする各ページの最上位レベルのイテレータに、同じRSIName
属性を指定することで、データ・コントロールは、そのコントロール用に作成された複数のデータ・プロバイダのインスタンスを持てるようになります。
この機能を使用するには、同じデータ・コレクション・インスタンスにアクセスする各ページの最上位レベル・イテレータ(iterator
)に同じRSIName
属性を指定します。
次の例は、pageDef
ファイルのイテレータの階層を示しています。最後の2つのアクセサ・イテレータでは、第2コレクションの従業員オブジェクトとそれらの従業員の電話番号を反復できます。
<iterator Binds="root" RangeSize="25" DataControl="BusinessManager" id="BusinessManagerIterator" RSIName="secondCollection" /> <accessorIterator id="companyIterator"/ MasterBinding="BusinessManagerIterator" Binds="company" RangeSize="25" DataControl="BusinessManager" BeanClass="mobile.Company"/> <accessorIterator id="employeesIterator" MasterBinding="companyIterator" Binds="employees" RangeSize="25" DataControl="BusinessManager" BeanClass="mobile.Employee"/> <accessorIterator id="phoneNumbersIterator" MasterBinding="employeesIterator" Binds="phoneNumbers" RangeSize="25" DataControl="BusinessManager" BeanClass="mobile.PhoneNumber"/> <accessorIterator id="employeesIterator2" MasterBinding="companyIterator" Binds="employees" RangeSize="25" DataControl="BusinessManager" BeanClass="mobile.Employee" RSIName="secondCollection" /> <accessorIterator id="phoneNumbersIterator2" MasterBinding="employeesIterator2" Binds="phoneNumbers" RangeSize="25" DataControl="BusinessManager" BeanClass="mobile.PhoneNumber" />
バインディング・コンテナを参照する方法
MAFは、アクティブな画面と非アクティブな画面のバインディング・コンテナを参照するために、異なるルートEL式を使用します。MAF AMXバインディング・オブジェクトにアクセスするために、EL式で使用できるプロパティのリストを確認してください。
ルートEL式#{bindings}
で、アクティブな画面のバインディング・コンテナを参照できます。式#{data.PageDefName}
で、別の画面のバインディング・コンテナを参照できます。MAF AMXバインディング・オブジェクトは、バインディング・コンテナ#{bindings.Name}
から名前で参照されます。
表15-4は、実行時に、EL式でMAF AMXバインディング・オブジェクトの値にアクセスするために使用できるプロパティのリストの一部を示しています。プロパティは、アルファベット順に並んでいます。
表15-4 MAFバインディングのランタイムELプロパティ
実行時プロパティ | 説明 | イテレータ | アクション | 属性値 | ツリー |
---|---|---|---|---|---|
|
実行時バインディング用のJavaクラス・オブジェクトを戻します。 |
○ |
○ |
○ |
○ |
|
データのコレクションを公開します。 |
× |
× |
× |
○ |
|
このバインディングのイテレータ内で、選択した行を現在の行にします。 |
× |
× |
× |
○ |
|
選択した行への参照を戻します。 |
× |
× |
× |
○ |
|
イテレータが指している現在の行またはデータ・オブジェクト(組込みナビゲーション・アクションなど)への参照を戻します。 |
○ |
× |
× |
× |
|
イテレータが指している現在の行またはデータ・オブジェクトへの参照を戻します。(これは |
○ |
× |
× |
× |
|
アクション・バインディングの状態に応じて、 |
× |
○ |
× |
× |
|
解決されたときに、名前付きアクションまたは |
× |
○ |
× |
× |
|
これは |
× |
× |
○ |
○ |
|
バインディングが関連付けられているすべての表示属性について、UIヒントの名前/値ペアのリストを戻します。 |
× |
× |
○ |
○ |
|
バインディングが関連付けられている最初の属性の値を戻します。 |
× |
× |
○ |
× |
|
現在のリストの有効な属性に関連付けられた値のリストを戻します。 |
× |
× |
○ |
× |
|
|
× |
× |
○ |
○ |
|
|
○ |
○ |
○ |
○ |
|
イテレータ・バインディングの行セットの範囲サイズを戻します。これにより、データソースからバインドされるデータ・オブジェクトの数を確認できます。 |
○ |
× |
× |
○ |
|
メソッド・アクション・バインディングによりバインドおよび起動されるメソッドの結果を戻します。 |
× |
○ |
× |
× |
|
|
× |
× |
○ |
○ |
|
|
× |
× |
× |
○ |
脚注1
EL語句のrow
は、コレクション・コンポーネントのコンテキスト内で使用されます。row
は単に、コレクションをレンダリングするときに、MAF AMXバインディング・オブジェクトからアクセスできる属性を含むコレクションの各要素に対する反復変数として機能します。属性とリスト・バインディングには、row
変数を使用してアクセスできます。そのような式の構文は、コレクションに含まれないバインディング・オブジェクトへのアクセスに使用される構文と同じで、#{row.bindings.Name.property}
のようにrow
変数を先頭の語句として追加します。
式ビルダーのカテゴリについて
MAF AMXページの式ビルダーでは、次のカテゴリを使用できます。
バインディング・カテゴリについて
様々なバインディング・タイプでサポートされているプロパティを構成できます。「バインディング」カテゴリでサポートされているバインディングとプロパティを確認してください。
この項では、バインディング・カテゴリで使用できるオプションを示します。bindings
ノードとdata
ノードは、サポートされているバインディングとプロパティの同じセットを表示します。表15-5に、使用できるバインディング・タイプと、各バインディング・タイプでサポートされるプロパティをリストします。securityContext
ノードは、次のプロパティをサポートしています。
-
authenticated
-
userGrantedPrivilege
-
userInRole
-
userName
次にその例を示します。
#{securityContext.authenticated}
#{securityContext.userGrantedPrivilege['submit_privilege']}
#{securityContext.userInRole[‘manager_role']}
#{securityContext.userName}
表15-5 サポートされるバインディング・タイプ
バインディング・タイプ | プロパティ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
マネージドBeanカテゴリについて
この項では、「マネージドBean」カテゴリで使用できるオプションを表示します。
-
applicationScope
: 「マネージドBean」のapplicationScope
ノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーションスコープのマネージドBeanなど)。 -
pageFlowScope
: 「マネージドBean」のpageFlowScope
ノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロースコープのマネージドBeanなど)。 -
viewScope
: 「マネージドBean」のviewScope
ノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュースコープのマネージドBeanなど)。
MAFランタイムでは、自身をマネージドBeanプロパティの変更通知のリスナーとして登録することによって、Beanプロパティを参照するUIコンポーネントにバインドされたEL式が、プロパティの値が変更されたときに自動的に更新されるようにします。これらの通知をソースとして参照するには、Beanのプロパティ・アクセッサにコードを追加する必要があります。Beanのプロパティ・アクセッサから、通知をソースとして参照するために必要なコードを自動的に生成するには、「アクセッサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェック・ボックスを選択します(図を参照)。
ELを通じて単にBeanメソッドまたはプロパティを参照する場合、このコードを追加する必要はありませんが、Beanに格納された値が変化する場合や、特にその変更が、1つ以上のプロパティ値を変更するBeanメソッドの実行による二次的な影響など、間接的なものである場合、それらの値に依存するEL式のアクティブ・フォームへのレンダリングを最新の状態に保つ必要があります。プロパティの変更とPropertyChangeSupport
クラスについては、「データ変更イベントについて」を参照してください。
次の例は、プログラムで別のマネージドBean属性にバインドされた値を取得する方法を示しています。
public void someMethod() { Object value = AdfmfJavaUtilities.getELValue( "#{applicationScope.MyManagedBean.someProperty}"); ... }
Oracle Mobile Application Framework Java APIリファレンスで説明されているAdfmfJavaUtilities
クラスには、EL式の管理に役立つ他のメソッドが用意されています。例としては、isEvaluationExpression
とsetELValue
があります。
注意:
機能のapplicationScope
内でマネージドBeanを宣言し、デザインタイムで別の機能のELを通じてそのBeanを参照しようとすると、そのデザインタイムで無効なELに関する警告が表示されます。この警告は、デザインタイムがそのBeanの現在のプロジェクトで参照を検出できないことが原因で表示されます。そのBeanを実行時に参照できるのは、Beanが宣言されている最初の機能に初めてアクセスし、さらに別の機能のELを通じてアクセスする前にそのBeanをインスタンス化した場合のみです。これは、Name
属性の値をノード・ラベルとして使用するPreferenceValue
要素には当てはまりません。
モバイル・アプリケーション・フレームワークのオブジェクト・カテゴリについて
「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリには、MAFで定義されたオブジェクト、ELを使用して参照できるオブジェクトが含まれます。
「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリには、オブジェクト・スコープなどのELを使用して参照できるMAFに定義されている様々なオブジェクトが一覧表示されます。
MAFの変数とマネージドBeanの参照は、変数の存続期間と可視性を決定する様々なオブジェクト・スコープ内で定義されます。これらのスコープには、可視性が高い順に、アプリケーション・スコープ、ページ・フロー・スコープおよびビュー・スコープがあります。「オブジェクト・スコープ・ライフサイクルについて」を参照してください。
スコープを含むこのような変数に加えて、MAFでは、デバイス・プロパティとアプリケーション・プリファレンスに関する情報を公開できるスコープが定義されています。これらのスコープによって、アプリケーション・レベルの存続期間と可視性が決まります。
「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリで使用できるものは、次のとおりです。
-
applicationScope
:applicationScope
ノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーション・スコープのマネージドBeanなど)。アプリケーション・スコープで定義されたEL変数は、アプリケーションが存続するかぎり、機能の境界にまたがって使用できます。 -
deviceScope
:deviceScope
ノードは、デバイスのプロパティに関する情報を公開します。deviceScope
は、アプリケーション・レベルの存続期間および可視性を持ちます。 -
feature
:feature
ノードは、機能レベルのデータを公開します。featureオブジェクトは、dataControlContextDepth
およびmaximumDataControlContextDepth
プロパティを公開します。#{feature.dataControlContextDepth}
および#{feature.maximumDataControlContextDepth}
を使用して、これらのプロパティの値を取得できます。これらの2つのプロパティは読取り専用です。 -
pageFlowScope
:pageFlowScope
ノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロー・スコープのマネージドBeanなど)。ページ・フロー・スコープで定義されたEL変数は、機能が存続するかぎり、単一の機能の境界内で使用できます。 -
preferenceScope
:preferenceScope
ノードには、アプリケーションと機能のすべてのプリファレンスが含まれます。プリファレンス要素では、
PreferenceValue
要素を除き、Id
属性の値を式ビルダーのノード・ラベルとして使用します。PreferenceValue
要素では、Name
属性の値を式ビルダーのノード・ラベルとして使用します。注意:
EL式の文字列トークンにドット(.)や特殊文字または
default
などの予約語が含まれている場合、式ビルダーではそのような文字列トークンを一重引用符と大カッコで囲みます。機能IDやプリファレンス・コンポーネントIDにドットが含まれている場合、式ビルダーでは、ドットによって区切られたIDの各部分を別のプロパティとしてpreferenceScope
階層に表示します。生成された式でも、ドットによって区切られたIDの各部分を別のプロパティとして認識します。preferenceScope
のいくつかのサンプルEL式を次に示します。"#{preferenceScope.feature.oracle.hello.SampleGroup1.label}"
"#{preferenceScope.application.OracleMobileApp.Edition['default']}"
-
viewScope
: このノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュー・スコープのマネージドBeanなど)。ビュー・スコープの名前空間で定義されたEL変数は、ビューが存続するかぎり、機能の単一ページの境界内で使用できます。 -
row
:row
オブジェクトは、collectionModel
に含まれる単一のプロバイダへのショートカットである中間変数です。その名前は、親コンポーネントのvar
属性の値です(List ViewやCarouselなど)。注意:
AdfmfJavaUtilities.evaluateELExpression
を使用して、#{row}
、またはrow
のプロパティを評価することはできません。これらの式はnull値を戻します。 -
viewControllerBundle
これは、プロジェクト・レベルで定義されているリソース・バンドルを指すリソース・バンドル変数の名前です。このノードが表示されるのは、
amx:loadBundle
要素が削除され、リソース・バンドルが作成された後のみです。このノードの名前は、amx:loadBundle
の変数名によって異なります。このノードには、バンドル内で宣言されたすべての文字列が表示されます。次の例は、
viewControllerBundle
のAMXコードの例を示しています。<amx:loadBundle basename="mobile.ViewControllerBundle" var="viewcontrollerBundle"/>
ELイベントについて
ELイベントにより、MAF AMX UIの動作が決まります。これは、このイベントが共通語句を含む式の更新を同期するためです。基礎となる式の値が変化すると、その値のすべてのリスナーに向けたイベントが生成されます。
ELイベントは、共通語句を含む式が相互に同期して更新できるようにするため、MAF AMX UIの動作において重要な役割を果たします。
EL式は、様々なコンテキストで値を参照できます。次の例は、各コンポーネントがapplicationScope
値に関連付けられた2つの入力数値スライダ・コンポーネントの作成方法を示しています。出力テキストでは、ELを使用して単純な追加式を計算結果とともに表示します。フレームワークでは、出力テキスト・ラベル内のEL式を解析するときに、その式に2つの値への参照が含まれていることを確認し、それら2つの値に基づく出力テキストのイベント・リスナー(「イベント・リスナーの使用方法」を参照)を作成します。基礎となる式の値が変化すると、イベントがその値のすべてのリスナーに対して生成されます。
注意:
(スコープ・オブジェクトではなく)マネージドBeanのプロパティを参照している場合、リスナーを追加する必要があります。「マネージドBeanカテゴリについて」を参照してください。
<amx:inputNumberSlider id="slider1" label="X" value="#{applicationScope.X}"/> <amx:inputNumberSlider id="slider2" label="Y" value="#{applicationScope.Y}"/> <amx:outputText id="ot1" value="#{applicationScope.X} + #{applicationScope.Y} = #{applicationScope.X + applicationScope.Y}"/>
前述の例では、2つのコンポーネントがそれぞれ1つの値を更新し、1つのコンポーネントが両方の値を使用します。次の例は、いずれかの既存の値を参照する3つ目の入力数値スライダ・コンポーネントが追加された場合、動作は同じになることを示しています。
<amx:inputNumberSlider id="slider1" label="X" value="#{applicationScope.X}"/> <amx:inputNumberSlider id="slider2" label="Y" value="#{applicationScope.Y}"/> <amx:outputText id="ot1" value="#{applicationScope.X} + #{applicationScope.Y} = #{applicationScope.X + applicationScope.Y}"/> <amx:inputNumberSlider id="slider3" label="X" value="#{applicationScope.X}"/>
前述の例では、いずれかの入力数値スライダ・コンポーネントが#{applicationScope.X}
を更新すると、もう一方が出力テキストとともに自動的に更新されます。
EL式のマネージドBean内での使用方法
JDeveloperが提供するEL式を使用します。新しいEL式を作成して、マネージドBean内でEL式のアクセス、設定、または呼び出しを実行します。
必要なEL式はJDeveloperで作成され、作成されない式は式ビルダーを使用して作成できますが、マネージドBean内でEL式にアクセスしたり、EL式を設定または起動する必要がある場合もあります。
次の例に、EL式への参照を取得し、適合するオブジェクトを返す(または作成する)方法を示します。
public static Object resolveExpression(String expression) { return AdfmfJavaUtilities.evaluateELExpression(expression); }
次の例に、メソッド式を解決する方法を示します。
public static Object resloveMethodExpression(String expression, Class returnType, Class[] argTypes, Object[] argValues) { MethodExpression methodExpression = AdfmfJavaUtilities.getMethodExpression(expression, returnType, argTypes); return methodExpression.invoke(AdfmfJavaUtilities.getAdfELContext(), argValues); }
次の例に、マネージドBeanに新規オブジェクトを設定する方法を示します。
public static void setObject(String expression, Object newValue) { AdfmfJavaUtilities.setELValue(expression, newValue); }
マネージドBeanの作成および使用
マネージドBeanは、構成ファイルによってアプリケーションに登録されたJavaクラスです。これが解析されると、Beanのプロパティとメソッドへのアクセスを提供します。
マネージドBeanは、様々な構成ファイルを使用してアプリケーションに登録するJavaクラスです。MAFアプリケーションを起動すると、これらの構成ファイルが解析されてBeanが使用可能になり、EL式で参照できるため、Beanのプロパティとメソッドにアクセスできます。マネージドBeanが初めて参照されたときにまだ存在していない場合、マネージドBean作成機能によりBeanのデフォルトのコンストラクタ・メソッドがコールされて、Beanがインスタンス化されます。また、プロパティが宣言されると、宣言されたデフォルトの値が移入されます。
多くの場合、マネージドBeanは、フロント・エンドで処理することが最適なイベントやデータ操作を処理します。マネージドBeanの使用方法の詳細は、http://www.oracle.com/technetwork/java/index.html
のJava EEチュートリアルを参照してください。
ベスト・プラクティス:
マネージドBeanを使用して、現在のユーザーなどのブックキーピング情報のみを格納します。すべてのアプリケーション・データおよび処理データは、アプリケーションのビジネス・レイヤーのロジックによって処理される必要があります。
注意:
EL式は、Beanを参照するために明示的にスコープを含める必要があります。たとえば、pageFlowScope
スコープからMyBean
マネージドBeanを参照するには、#{pageFlowScope.MyBean}
という式になります。
JDeveloperでのマネージドBeanの作成方法
マネージドBeanを作成して、MAFアプリケーションに登録する手順を使用してください。
adfc-mobile-config.xml
ファイルに「概要」エディタを使用して、マネージドBeanの作成とMAFアプリケーションへの登録を同時に行うことができます。
始める前に:
マネージドBeanに関する知識が役立つ場合があります。「マネージドBeanの作成および使用」を参照してください。
マネージドBeanの作成および登録手順:
JDeveloperを使用してマネージドBeanを作成する場合の処理
JDeveloperでマネージドBeanを作成してJavaファイルを生成すると、IDEによってスタブ・クラスが作成されます。EL式が特定のスタブ・クラス名を使用して参照できるように、ページにロジックを追加します。
マネージドBeanを作成する際、Javaファイルを生成するよう選択すると、指定された名前とデフォルト・コンストラクタを使用してスタブ・クラスが自動的に作成されます。次の例に、ビュー・パッケージに格納されたMyBean
クラスに追加されるコードを示します。
package view; public class MyBean { public MyBean() { } }
ここでページに必要なロジックを追加する必要があります。このロジックは、マネージドBeanのmanaged-bean-name
を参照するEL式を使用して参照できます。たとえば、my_bean
マネージドBeanのmyInfo
プロパティにアクセスする場合、EL式は次のようになります。
#{my_bean.myInfo}
JDeveloperでは、managed-bean
要素もadfc-mobile-config.xml
ファイル(または編集されるタスク・フロー・ファイル)に追加されます。次の例に、MyBean
クラスに対して作成されたmanaged-bean
要素を示します。
<managed-bean> <managed-bean-name>my_bean</managed-bean-name> <managed-bean-class>view.MyBean</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean>
データ・コントロールを使用したビジネス・サービスの公開
データ・コントロールは、ビジネス・サービスにUIコンポーネントを宣言的にバインドするために作成します。「データ・コントロールの作成」メニュー・オプションを使用してデータ・コントロールを生成します。
アプリケーションのサービスの準備ができたら、JDeveloperを使用して、UIコンポーネントとサービスとの宣言的バインドに必要な情報を提供するデータ・コントロールを作成できます。
データ・コントロールの生成には、「データ・コントロールの作成」メニュー・アイテムを使用します。データ・コントロールは、1つ以上のXMLメタデータ・ファイルで構成され、これらのファイルでは、実行時にバインディングと連動するサービスの機能が定義されます。データ・コントロールは、基礎となるサービスと連動します。
データ・コントロールの作成方法
アプリケーション・ワークスペースを作成して、ビジネス・サービスを追加してから、データ・コントロールの作成手順を使用してください。また、データ・コントロールの基になるクラスまたはオブジェクトのコンテキスト・メニューを使用してデータ・コントロールを作成することもできます。
アダプタ・ベースのデータ・コントロールは、JDeveloperの「アプリケーション」ウィンドウ内で作成します。
始める前に:
データ・コントロール使用の一般的な知識があると役立ちます。「データ・コントロールを使用したビジネス・サービスの公開」を参照してください。
次のタスクを完了する必要があります。
- アプリケーション・ワークスペースを作成し、データ・コントロールの基礎にするビジネス・サービスを追加します。アプリケーション・ワークスペースの作成の詳細は、「MAFアプリケーションの作成」を参照してください。
データ・コントロールを作成する手順は、次のとおりです。
- アプリケーション・ワークスペース内でデータ・モデル・プロジェクトの最上位ノードを右クリックして、「新規」を選択し、「ギャラリから」を選択します。
- 「新規ギャラリ」で、「ビジネス層」を展開し、「データ・コントロール」を選択して、作成するデータ・コントロールのタイプを選択し、「OK」をクリックします。
- ウィザードの残りのステップを完了します。
注意:
場合によっては、データ・コントロールの基礎にするクラスまたはオブジェクトを右クリックし、「データ・コントロールの作成」を選択することによってデータ・コントロールを作成できます。
データ・コントロール作成時のプロジェクト内の処理
JDeveloperは、概要エディタで開いているデータ・コントロールの定義ファイルを作成して、「データ・コントロール」パネルにファイルの階層を表示します。
データ・コントロールを作成すると、JDeveloperによってデータ・コントロール定義ファイル(DataControls.dcx
)が作成され、概要エディタでファイルが開き、ファイルの階層が「データ・コントロール」パネルに表示されます。このファイルにより、データ・コントロールがサービスおよびバインディングと直接連動して動作することが可能になります。
エディタ・ウィンドウの「ソース」タブをクリックすることによって、対応するXMLファイルからのコードを表示できます。
DataControls.dcx概要エディタ
データ・コントロール・オブジェクトの階層とデータ・モデルの公開メソッドは、DataControls.dcx
ファイルの概要エディタに表示されます。このエディタを使用して、データ・コントロール・オブジェクトの設定を編集します。
DataControls.dcx
ファイルの概要エディタは、データ・コントロール・オブジェクトの階層と、データ・モデルの公開メソッドを表示します。
概要エディタおよび「データ・コントロール」パネルで使用されるアイコンの説明は、表15-6を参照してください。
データ・コントロール・オブジェクトの設定を変更するには、オブジェクトを選択し、「編集」アイコンをクリックします。「データ・コントロールの編集方法」を参照してください。
概要エディタでのDataControls.dcx
ファイルを図に示します。
データ・コントロール・パネル
「アプリケーション」ウィンドウに、「データ・コントロール」パネルが表示されます(データ・コントロールの作成後)。「データ・コントロール」パネルからノードをドラッグして、データバインドされたUIコンポーネントをページに作成します。
「データ・コントロール」パネルはパレットとして機能し、ノードを「データ・コントロール」パネルからページのデザイン・エディタにドラッグすることにより、データバインドされたUIコンポーネントを作成できます。データ・コントロールを作成した後、「データ・コントロール」パネルが「アプリケーション」ウィンドウに表示されます。サンプル・アプリケーションの「データ・コントロール」パネルを図に示します。
データ・コントロールの組込み操作
データ・コントロール・フレームワークは、ビジネス・サービスによって実装されるデータ・コントロールの標準操作のセットを定義します。データ・コントロールのタイプとビジネス・サービスの機能により、使用可能な操作が異なります。
データ・コントロール・フレームワークは、データ・コントロールの標準操作のセットを定義します。これらの操作は、基礎となるビジネス・サービスの機能を使用して実装されます。実行時に、これらのデータ・コレクション操作の1つがデータ・バインディング・レイヤーによって名前を指定して起動されると、データ・コントロールは、組込み機能を処理する適切なサービス・メソッドにそのコールを委譲します。たとえば、Beanデータ・コントロールでは、Next
操作はBeanコレクションのイテレータに依存します。
ほとんどの組込み操作は、現在の行に作用します。ただし、execute
操作が、データ・コントロール自体をリフレッシュします。
使用可能な操作は、データ・コントロールのタイプと、基礎となるビジネス・サービスの機能によって異なります。次に、組込み操作すべてのリストを示します。
-
Create
: 現在の行になる新規行を作成。新しい行も行セットに追加されます。 -
CreateInsert
: 現在の行となる新規行を作成し、その行を行セットに挿入。 -
Create With Parameters
: 名前付きパラメータを使用して現在の行になる新規行を作成し、その行を行セットに挿入。 -
Delete
: 現在の行を削除。 -
Execute
: アクセッサ・メソッドを実行または再実行することによって、データ・コレクションをリフレッシュします。ExecuteWithParams
: パラメータとして渡された変数に新しい値を割り当てた後で、関連した問合せを実行または再実行することにより、データ・コレクションをリフレッシュ。この操作は、パラメータ化された問合せに基づくデータ・コントロール・コレクション・オブジェクトに対してのみ使用できます。 -
First
: 行セット内の最初の行を現在の行に設定します。 -
Last
: 行セット内の最後の行を現在の行に設定します。 -
Next
: 行セット内の次の行を現在の行に設定します。 -
Next Set
: 1つ後の行のセットに移動します。 -
Previous
: 行セット内の前の行を現在の行に設定します。 -
Previous Set
: 1つ前の行のセットに移動します。 -
removeRowWithKey
: パラメータとして渡された行キーのシリアライズされた文字列表現を使用して行の検索を試行します。検出されると、その行が削除されます。 -
setCurrentRowWithKey
: パラメータとして渡された行キーのシリアライズされた文字列表現を使用して行の検索を試行します。検出されると、その行が現在の行になります。 -
setCurrentRowWithKeyValue
: パラメータとして渡された主キーの属性値を使用して行の検索を試行します。検出されると、その行が現在の行になります。
データ・コントロールのaddXXXおよびremoveXXXメソッド
ほとんどの組込み操作は自動的に動作しますが、addXXX
メソッドとremoveXXX
メソッドを使用するCreate
やDelete
などの組込み操作が動作するには、いくつかのメソッド・ハンドラの追加が必要になります。addXXX
メソッドとremoveXXX
メソッドは、自動的にコレクションをリフレッシュして、データ変更イベントをトリガーします。
組込み操作のほとんどは、コレクションに対して自動的に実行されます。操作の中には、実行するために、開発者がメソッド・ハンドラを作成する必要があるものがあります。Create
操作を使用するには、開発者がaddXXX
のメソッド・ハンドラを作成する必要があります。Create
操作は、現在のコレクションにレコードを挿入するため、CreateInsert
の操作も実行します。MAFコレクションにはCreateInsert
操作は使用されません。同様に、Delete
操作を実行するには、開発者がremoveXXX
のメソッド・ハンドラを作成する必要があります。
addXXX
およびremoveXXX
メソッドは、自動的にコレクションをリフレッシュし、データ変更イベントを起動するため、開発者はプロバイダを排他的にリフレッシュする必要はありません。データ・オブジェクトは、組込み操作のCreate
およびDelete
で使用されるaddXXX
メソッドとremoveXXX
メソッドなどの、データ・コントロールの組込み操作で使用されます。
-
addXXX
: このメソッドは、データ・コントロール・フレームワークに一意のIDを返します。たとえば、次のようになります。
ここで、public void addDeptBean(DeptBean dept) { deptCollection.add(dept); }
DeptBean
はクラス名、dept
はオブジェクトです。 -
removeXXX
: このメソッドはオブジェクトを削除します。たとえば、次のようになります。
ここで、public void removeDeptBean(DeptBean dept) { deptCollection.remove(dept); }
dept
はDeptBean
クラスのオブジェクトです。
CRUDDemo
サンプル・アプリケーションは、開発コンピュータ上のjdev_install/jdeveloper/jdev/extensions/oracle.maf/Samples
ディレクトリ内のPublicSamples.zip
ファイルにあります。
「データ・コントロール」パネルでのデータバインドされたUIコンポーネントの作成
「データ・コントロール」パネルからデータ・コントロール・オブジェクトをドラッグして、特定のUIコンポーネントを作成するページのエディタにドロップします。JDeveloperは、選択したデータ・コントロールにコンポーネントをバインドするために必要なコードとオブジェクトを自動的に作成します。
「データ・コントロール」パネルでは、各データ・コントロール・オブジェクトが特定のアイコンで表されます。表15-6は、各アイコンが表すデータ・コントロール・オブジェクト、「データ・コントロール」パネルの階層内で表示される場所、そのアイコンを使用して作成できるコンポーネントを示しています。
表15-6 「データ・コントロール」パネルのアイコンおよびオブジェクト階層
アイコン | 名前 | 説明 | 作成できるコンポーネント |
---|---|---|---|
![]() |
データ・コントロール |
データ・コントロールを表します。 |
他のオブジェクトのコンテナとして機能し、作成には使用されません。 |
![]() |
コレクション |
アクセッサ・メソッドまたは操作から返される名前付きデータ・コレクションを表します。 |
フォーム、表、グラフ、ツリー、レンジ・ナビゲーションの各コンポーネント、マスター/ディテール・コンポーネントおよび選択リストの各コンポーネント。 |
![]() |
構造化された属性 |
Javaプリミティブ・タイプ(属性として示される)または任意のタイプのコレクションのいずれでもない、戻りオブジェクトを示します。 |
フォーム、ラベル、テキスト・フィールド、日付、値リストおよび選択リストの各コンポーネント。 |
![]() |
属性 |
オブジェクト内の個別のデータ要素(行の属性など)を表します。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。 |
![]() |
キー属性 |
データ・コントロール構造ファイル、またはビジネス・サービス自体で、主キー属性として宣言されたオブジェクト属性を表します。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。 |
![]() |
メソッド |
データ・コントロールのメソッドまたは操作、またはその公開された構造のいずれかを表し、パラメータの受入れや、ビジネス・ロジックの実行を行ったり、オプションで単一の値、構造、またはコレクションを戻したりすることができます。 |
コマンド・コンポーネント。 パラメータを受け入れるメソッドの場合: コマンド・コンポーネントおよびパラメータ付きフォーム。 |
![]() |
メソッド戻り値 |
メソッドまたはその他の操作から返されたオブジェクトを表します。戻されたオブジェクトは、単一の値またはコレクションです。 メソッド戻りは、これを戻すメソッドの下に、子として表示されます。メソッド戻りの下に子として表示されるオブジェクトは、コレクションの属性、親コレクションに関連するアクションを実行する他のメソッド、または親コレクションで実行できる操作などです。 |
単一の値の場合: テキスト・フィールドおよび選択リスト。 コレクションの場合: フォーム、表、ツリー、レンジ・ナビゲーションの各コンポーネント。 単一値のメソッド戻り値がドロップされると、メソッドはフレームワークにより自動的に起動されなくなります。メソッドを起動するために、対応するメソッドをボタンとしてドロップできます。フォームがタスク・フローの一部の場合、メソッドを起動するためのメソッド・アクティビティを作成できます。 |
![]() |
操作 |
親オブジェクトに対してアクションを実行する、組込みデータ・コントロール操作を表します。 |
ボタンおよびリンクなどのUIコマンド・コンポーネント。 |
![]() |
パラメータ |
メソッドまたはその下に表示される操作によって宣言されたパラメータ値を表します。 |
ラベル、テキストおよび選択リストの各コンポーネント。 |
「データ・コントロール」パネルの使用方法
「データ・コントロール」パネルには、アプリケーションを構築するための事前定義済のUIコンポーネントのセットが用意されています。コンテキスト・メニューを使用してUIコンポーネントを作成する手順を使用してください。コンテキスト・メニューは、このパネルからデータ・コレクションを選択すると表示されます。
JDeveloperは、ドロップするデータ・コントロール項目に対してそれぞれ選択できるUIコンポーネントの事前定義済セットを備えています。
始める前に:
「データ・コントロール」パネルの各種オブジェクトに関する知識があると役立つ場合があります。「データ・コントロール」パネルでのデータバインドされたUIコンポーネントの作成を参照してください。
次のタスクを完了する必要があります。
-
「データ・コントロールの作成方法」の説明に従ってデータ・コントロールを作成します。
-
「MAF AMXページの作成」の説明に従ってMAF AMXページを作成します。
「データ・コントロール」パネルを使用してUIコンポーネントを作成するには:
「データ・コントロール」パネルの使用時の処理
「データ・コントロール」パネルを使用してアプリケーションを構築すると、JDeveloperによって次の処理が行われます。
-
DataBindings.cpx
ファイルがプロジェクトのデフォルト・パッケージに作成されます(このファイルが存在しない場合のみ)。また、そのページ用にエントリが追加されます。DataBindings.cpx
ファイルは、アプリケーションのバインディング・コンテキストを定義します。バインディング・コンテキストはコンテナ・オブジェクトの1つで、使用可能なデータ・コントロールおよびデータ・バインディング・オブジェクトのリストを含みます。DataBindings.cpx
ファイルによって、個々のページがページ定義ファイルに含まれるバインディング定義にマップされ、これらのページが使用するデータ・コントロールが登録されます。「生成されるドラッグ・アンド・ドロップ・アーティファクトに関する必知事項」を参照してください。 -
META-INFディレクトリに
adfm.xml
ファイルが作成されます。このファイルにより、DataBindings.cpx
ファイルのレジストリが作成され、バインディング・コンテキストを作成できるように、実行時にアプリケーションで特定できます。 -
パッケージ定義ファイルがページ定義サブパッケージに追加されます(ページに対してファイルが存在しない場合)。デフォルトのサブパッケージは、
adfmsrc
ディレクトリにあるmobile.pageDefs
です。ヒント:
「プロジェクト・プロパティ」ダイアログ(プロジェクト・ノードをダブルクリックするとアクセスできる)のADFモデル設定ページで、パッケージ構成(名前と場所など)を設定できます。
ページ定義ファイル(
pageName
PageDef.xml
)は、アプリケーションのビュー・レイヤーにある各ページのバインディング・コンテナを定義します。バインディング・コンテナでは、ページのすべてのバインディング・オブジェクトへのランタイム・アクセスが行われます。ページ定義ファイルの詳細は、「生成されるドラッグ・アンド・ドロップ・アーティファクトに関する必知事項」を参照してください。ヒント:
現在のバインディング・コンテナは、プログラム的なアクセス用の
AdfContext
からも入手できます。 -
ページ定義ファイルが構成されます。この処理では、ページによって参照されるバインディング・オブジェクトの定義も追加されます。
-
ページに指定のコンポーネントを追加します。
これらの事前作成済コンポーネントには、ページ定義ファイルのバインディング・オブジェクトを参照するデータ・バインディング式言語(EL)式が含まれます。「データ・バインディングEL式について」を参照してください。
-
UIコンポーネントが必要とするすべてのライブラリ、ファイル、および構成要素が追加されます。データバインドされたコンポーネントに必要なアーティファクトの詳細は、「MAFアプリケーションの作成時に行われる処理」を参照してください。
実行時に行われる処理: バインディング・コンテキストの動作方法
ページにMAFバインディングが含まれている場合、実行時には、クライアントまたはコントローラから起動されたビジネス・サービスとのやり取りが、バインディング・コンテキストと呼ばれる単一オブジェクトを介して、アプリケーションによって管理されます。
バインディング・コンテキストは、アプリケーション内のすべてのデータ・コントロールおよびページ定義のランタイム・マップ(名前付きdataでEL式#{data}
を使用してアクセス可能)です。
次の図に示すように、MAFでは、アプリケーション、DataBindings.cpx
およびページ定義ファイルからバインディング・コンテキストが作成されます。設計時に使用可能なデータ・コントロールは、すべてのDataControls.dcx
ファイルとワークスペース内のすべてのアプリケーション・モジュールの集合体によって定義されますが、実行時にアプリケーションで使用可能なデータ・コントロールは、DataBindings.cpx
ファイルで定義されます。DataBindings.cpx
ファイルは、アプリケーションのページで使用されているデータ・コントロールをすべて一覧表示し、ページ定義ファイルに定義されたバインディング・オブジェクトが格納されているバインディング・コンテナをWebページのURLにマップします。ページ定義ファイルは、アプリケーション・ページで使用するバインディング・オブジェクトを定義します。各ページにページ定義ファイルが1つあります。
バインディング・コンテキストには、これらのオブジェクトの実際のインスタンスは含まれていません。かわりに、マップには必要に応じてデータ・コントロールまたはバインディング・コンテナ・オブジェクトになる参照が含まれます。たとえば、オブジェクト(ページ定義など)がアプリケーションから解放されるか、タスク・フローが終了するか、リクエストの終了時にバンディング・コンテナまたはデータ・コントロールが解放されると、データ・コントロールおよびバンディング・コンテナは参照オブジェクトに戻ります。DataBindings.cpx
ファイルの詳細は、「生成されるドラッグ・アンド・ドロップ・アーティファクトに関する必知事項」を参照してください。
注意:
コンポーネントを構成するときは、使用するバインディング・スタイルを十分に考慮してください。より具体的に言うと、標準的なバインディングをマネージドBeanバインディングと組み合せると、解釈を誤った動作が発生することがよくあります。これは、バインディング・インフラストラクチャとマネージドBeanインフラストラクチャとの間でクラス・インスタンスが一致する可能性が低いためです。バインディングが混在すると、UIに直接リンクされていないインスタンスの動作がコールされる場合があります。
MAFでのバインディングの使用の詳細は、次を参照してください。
データ・コントロールの構成
データ・コントロールを作成してから、そのコントロールの要素を格納するデータ・コントロール構造ファイルを作成して変更します。.dcx
ファイルの概要エディタを使用して、データ・コントロール構造ファイルを生成します。
データ・コントロールを作成すると、データ・コントロールについて、値と動作の標準的なセットが設定されます。たとえば、属性のラベルのクライアントでの表示方法がデータ・コントロールによって決定されます。データ・コントロールの要素に対応するデータ・コントロール構造ファイルを作成および変更することによって、これらの値と動作を構成できます。まず、.dcx
ファイルの概要エディタを使用して、データ・コントロール構造ファイルを生成します。
データ・コントロールの編集方法
データ・コントロールを作成してから、データ・コントロールを編集する手順を使用してください。
データ・コントロールを構成可能にするには、DataControls.dcx
ファイルの概要エディタを使用し、データ・コントロールに含まれるオブジェクトに対応するデータ・コントロール構造ファイルを作成します。個別のデータ・コントロール構造ファイルを編集できるようになります。
始める前に:
データ・コントロール構成の一般的な知識があると役立ちます。「データ・コントロールの構成」を参照してください。
次のタスクを完了する必要があります。
- 「データ・コントロールの作成方法」の説明に従ってデータ・コントロールを作成します。
データ・コントロールを編集するには:
データ・コントロール編集時の処理
データ・コントロールを編集すると、JDeveloperにより、影響を受けたコレクションのメタデータが含まれているデータ・コントロール構造ファイルが作成され、そのファイルが概要エディタで開かれます。
このファイルには、そのコレクション固有のデータ・コントロールの構成データ(データ・オブジェクトに対して指定したUIヒントまたはバリデータなど)が保存されています。
データ・コントロール構造ファイルのベース名は、対応するデータ・オブジェクトのものと同じです。たとえば、Customer.java
エンティティBeanに対応するコレクション・ノードが選択されている状態で「編集」アイコンをクリックすると、データ・コントロール構造ファイルの名前はCustomer.xml
となります。データ・コントロール構成ファイルはBeanクラスのパッケージに対応するパッケージに生成され、パッケージ名にpersdef
が付加されます。たとえば、Customer.java
Beanがmodel
パッケージ内にある場合、Customer.xml
データ・コントロール定義ファイルはpersdef.model
パッケージ内に生成されます。データ・コントロール構成ファイルが生成された後、概要エディタを使用してそのファイルをさらに構成できます。
データ・コントロール構造ファイルには、次の情報が含まれます。
-
属性: サービスのすべての属性を表します。たとえば、エンティティBeanの場合は、データベース列にマップされたBeanプロパティごとに属性が存在します。また、一時属性も追加できます。これらの属性のUIでの表示方法を定義するUIヒントを設定できます。属性値が必須か、一意である必要があるか、表示可能かどうかなどの他のプロパティを設定することもできます。詳細は、「属性の操作」を参照してください。
「属性の検証」で説明しているように、属性の検証を設定したり、カスタム・プロパティを作成することもできます。
-
アクセッサ: 結果セットを返すデータ・コントロール要素を表します。
-
操作: データ・コントロールの組込み操作で使用されるデータ・オブジェクト上のメソッドを表します。たとえば、それぞれ「作成」および「削除」組込み操作で使用される
add
およびremove
メソッドなどです。
Item
Beanのデータ・コントロール構造ファイルを図に示します。
注意:
データ・コントロール構造ファイルの概要エディタには、データ・オブジェクトに関連付けられているすべての属性、アクセッサおよび操作が表示されます。ただし、データ・コントロール構造ファイルのXMLソースには、編集した要素の定義のみが含まれます。基本要素は、データ・オブジェクトからイントロスペクションされます。また、基礎となるデータ・オブジェクトに変更を加えると、データ・コントロールはそれらの変更を継承します。
データ・コントロールのMDSカスタマイズに関する必知事項
データ・コントロール構造ファイルは、データ・コントロール内のオブジェクトをOracle Metadata Servicesのカスタマイズに使用できるようにする場合に、そのオブジェクトに対して必要になります。データ・コントロール・オブジェクトごとにメタデータを編集および追加して、そのオブジェクト用のデータ・コントロール構造ファイルが生成されるようにします。
データ・コントロールに含まれるすべてのオブジェクトをOracle Metadata Services (MDS)カスタマイズ可能にする必要がある場合は、パッケージされたアプリケーションにこれらのオブジェクトのデータ・コントロール構造ファイルが含まれている必要があります。
アダプタ・フレームワークに基づくデータ・コントロールを作成する際には、データ・コントロール構造ファイルはデフォルトでは生成されません。これは、特定のオブジェクトにメタデータを追加しない場合、データ・コントロールにこれらのファイルは必要ないからです。「データ・コントロールの編集方法」で説明されているように、通常、データ・コントロール構造ファイルは、宣言型のメタデータ(UIヒントやバリデータなど)をそのオブジェクトに追加するためにデータ・コントロールを編集するときにのみ、データ・コントロール・オブジェクト用に生成されます。各データ・コントロール・オブジェクト用のデータ・コントロール構造ファイルを作成するには、データ・コントロール・オブジェクトごとにその手順を繰り返す必要があります。
「MDSを使用したMAFアプリケーションのアーティファクトのカスタマイズ」を参照してください。
属性の使用
データ・コントロールが作成されていて、オブジェクトのデータ・コントロール構造ファイルが生成されていると、データ・オブジェクトの持続属性の機能を構成できます。データ・コントロール構造ファイルの概要エディタの「属性」ページを使用して、プロパティを構成します。
ビジネス・サービスのデータ・コントロールを作成する際、個々のデータ・オブジェクトに作成するデータ・コントロール構造ファイルで宣言的にデータ・オブジェクトの永続属性の機能を拡張できます。たとえば、UIコンポーネントの属性のデフォルト表示を制御する検証ルールを作成し、UIヒントを設定できます。
これらのプロパティはデータ・コントロール構造ファイルの概要エディタの「属性」ページで設定します。データ・コントロール構造ファイルの作成の詳細は、「データ・コントロールの編集方法」を参照してください。
属性を主キーとして指定する方法
データ・オブジェクトのデータ・コントロール構造ファイルでは、そのデータ・オブジェクトの主キーとして属性を指定できます。設定された主キーが継承されていないデータ・オブジェクトに、主キーとして属性を設定する手順を使用してください。
データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタでは、そのデータ・オブジェクトの主キーとして属性を指定できます(そのデータ・オブジェクトの基礎クラスでまだ指定していない場合)。
始める前に:
属性プロパティの設定方法の知識があると役立ちます。属性の使用を参照してください
次のタスクを完了する必要があります。
- 「データ・コントロールの編集方法」の説明に従って、必要なデータ・コントロール構造ファイルを作成します。
属性を主キーとして設定する手順は次のとおりです。
- 「アプリケーション」ウィンドウで、使用するデータ・コントロール構造ファイルをダブルクリックします。
- 概要エディタで、「属性」ナビゲーション・タブをクリックします。
- 「属性」ページで、主キーとして指定する属性を選択して、「詳細」タブをクリックします。
- 「詳細」ページで、「キー属性」プロパティを設定します。
注意:
属性がクラス内ですでに主キーとして指定されている場合、データ・コントロールはその設定を継承し、「キー属性」チェックボックスが選択されます。ただし、この場合は、「キー属性」オプションを選択解除することはできません。
属性の静的なデフォルト値を定義する方法
データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタでは、属性の静的なデフォルト値を指定できます。値タイプを「リテラル」に設定して、属性の静的なデフォルト値を定義する手順を使用してください。
値のタイプが「リテラル」に設定されている場合、「詳細」セクションの「値」フィールドには、属性のデフォルト値を静的に指定できます。たとえば、ServiceRequest
エンティティBeanのStatus
属性のデフォルト値をOpen
に設定することや、User
BeanのUserRole
属性のデフォルト値をuser
に設定できます。
始める前に:
属性プロパティの設定方法の知識があると役立ちます。属性の使用を参照してください
属性の静的なデフォルト値を定義する手順:
- 「アプリケーション」ウィンドウで、使用するデータ・コントロール構造ファイルをダブルクリックします。
- 概要エディタで、「属性」ナビゲーション・タブをクリックします。
- 「属性」ページで編集する属性を選択し、「詳細」タブをクリックします。
- 「詳細」ページで、「リテラル」オプションを選択します。
- 「リテラル」オプションの下のテキスト・フィールドに、属性のデフォルト値を入力します。
属性へのUIヒントの設定方法
属性にUIヒントを設定することで、そのヒントを一貫して表示およびラベル付けして、その属性を使用するUIコンポーネントでの属性の利便性とローカライズ可能性を向上します。「アプリケーション」ウィンドウの「属性」オプションを使用して、UIヒントを設定する手順を使用してください。
属性のUIヒントを設定し、それらの属性を使用するすべてのUIコンポーネントでそれらの属性が一貫したローカライズ可能な方法で表示およびラベル付けされるように設定できます。UIヒントにより、属性、ラベル、ツールチップ、フィールドを自動的に送信する必要があるかどうかを表示するために使用するUIコンポーネントのタイプなどが決定されます。特定の属性を表示するか非表示にするかも決定できます。属性のUIヒントを作成するには、「アプリケーション」ウィンドウからアクセスできる、データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタを使用します。
始める前に:
属性プロパティの設定方法の知識があると役立ちます。属性の使用を参照してください
次のタスクを完了する必要があります。
- 「データ・コントロールの編集方法」の説明に従って、必要なデータ・コントロール構造ファイルを作成します。
UIヒントを設定する手順:
- 「アプリケーション」ウィンドウで、使用するデータ・コントロール構造ファイルをダブルクリックします。
- 概要エディタで、「属性」ナビゲーション・タブをクリックします。
- 「属性」ページで編集する属性を選択し、「UIヒント」タブをクリックします。
- 「UIヒント」セクションで、目的のUIヒントを設定します。
属性へのUIヒントの設定時の処理
属性のUIヒントは、タグが追加されるプロパティとして保存されます。プロパティの値は、リソース・バンドル・ファイルに保存されますが、このファイルが見つからない場合は生成されます。
属性に対してUIヒントを設定すると、それらのヒントはプロパティとして格納されます。プロパティのタグはデータ・オブジェクトのデータ・コントロール構造ファイルに追加され、プロパティの値はリソース・バンドル・ファイルに保存されます。リソース・バンドル・ファイルが存在していない場合は、データ・コントロールのパッケージに生成され、初めてUIヒントを設定した際のプロジェクト名に従って名前が設定されます。
次の例に、Item.xml
データ・コントロール構造ファイルにおけるprice
属性のコードを示します。属性に対して設定されているラベルおよびフォーマット・タイプ・ヒントのタグも含まれます。
<PDefAttribute Name="price"> <Properties> <SchemaBasedProperties> <LABEL ResId="${adfBundle['model.ModelBundle']['model.Item.price_LABEL']}"/> <FMT_FORMATTER ResId="${adfBundle['model.ModelBundle'] ['model.Item.price_FMT_FORMATTER']}"/> </SchemaBasedProperties> </Properties> </PDefAttribute>
次の例に、ModelBundle.properties
リソース・バンドル・ファイルにおけるラベルおよびフォーマット・タイプ・ヒントの対応するエントリを示します。これらにはプロジェクトのローカライズ可能なプロパティのすべての値も含まれています。
model.Item.price_LABEL=Price . . . model.Item.price_FMT_FORMATTER=oracle.jbo.format.DefaultCurrencyFormatter
EL式を使用してUIヒントにアクセスする方法
EL式を使用して、ヒントの値をデータとしてページに表示し、UIヒントにアクセスできるようにします。データバインドされたコンポーネントをページにドラッグして、UIヒントへのアクセスを提供するバインディング・インスタンスを作成します。
EL式を使用してUIヒントにアクセスし、ページにデータとしてヒント値を表示できます。UIヒントには、データバインドされたコンポーネントをページにドロップした後に作成するバインディング・インスタンスを通じてアクセスできます。
次の例は、DeviceFeaturesデータ・コントロールを使用して生成されました。この例は、MAFフォームとして接続をドラッグ・アンド・ドロップし、displayName
フィールドとnickname
フィールドのみを保持することによって生成されるEL式を示しています。太字で表示されるラベルは、ELを使用したUIヒント取得の例です。
<amx:panelFormLayout id="pfl2"> <amx:inputText value="#{row.bindings.displayName.inputValue}"label="#{bindings.Contact.hints.displayName.label}"
id="it9"/> <amx:inputText value="#{row.bindings.nickname.inputValue}"label="#{bindings.Contact.hints.nickname.label}"
id="it10"/> </amx:panelFormLayout>af:panelHeader id="ph1"
Beanデータ・コントロールの作成と使用
Beanデータ・コントロールは、Beanクラスのメタデータ・ラッパーとして機能し、コード要素をUIコンポーネントにバインドするために使用するデータ・コントロール・オブジェクトとしてBeanのコード要素を公開します。Java Beanのデータ・コントロールは、「アプリケーション」ウィンドウの「データ・コントロールの作成」オプションを使用して作成します。
Beanデータ・コントロールは、Beanクラスのメタデータ・ラッパーとして機能し、データ・コントロール・オブジェクトとしてBeanのコード要素を公開します。このオブジェクトを使用して、これらのコード要素をUIコンポーネントにバインドできます。Java Beanデータ・コントロールでは、POJO (Plain Old Java Object)から自身のデータ構造を取得します。Java Beanデータ・コントロールを作成するには、Javaクラス・ファイルを右クリックし(「アプリケーション」ウィンドウ内)、「データ・コントロールの作成」を選択します。Java Beanのデータ・コントロールは、JDeveloperの「アプリケーション」ウィンドウ内で作成します。
始める前に:
データ・コントロールの一般的な知識があると役立ちます。「データ・コントロールの作成方法」を参照してください。
注意:
Java Beanがバックグラウンド・スレッドを使用してUI内のデータを更新する場合、手動でoracle.adfmf.framework.api.AdfmfJavaUtilities.flushDataChangeEvent
をコールする必要があります。flushDataChangeEvent
メソッドの詳細は、「データ変更イベントについて」を参照してください。
ローカルSQLiteデータベースおよびJava Beanデータ・コントロールを使用してCRUD操作を構築するサンプルは、開発コンピュータのjdev_install
/jdeveloper/jdev/extensions/oracle.maf/Samples
ディレクトリにあるPublicSamples.zip
ファイル内のCRUDDemoというMAFサンプル・アプリケーションを参照してください。
Beanクラス変数のシリアライズに関する必知事項
ネストされたオブジェクトのチェーンはtransientとして定義することでシリアライズを防止し、オブジェクトのネストによる循環オブジェクトの作成を回避します。JSONBeanSerializationHelper
クラスを使用すると、JavaオブジェクトをJSONオブジェクトにシリアライズおよびシリアライズ解除できます。
MAFでは、一時変数として宣言されたJavaScript Object Notation (JSON)データBeanクラス変数にはシリアライズしません。一連のネストされたオブジェクトのシリアライズを避けるには、それらを一時オブジェクトとして定義する必要があります。この方法を使用すると、オブジェクトのネストが原因で循環オブジェクトが作成されるのを防ぐこともできます。
次のシナリオを考えてみましょう。Employee
オブジェクトが、その子として従業員の上司を表すEmployee
オブジェクトを保持しているとします。その子を一時オブジェクトとして宣言しなかった場合、実行時に子のEmployee
オブジェクトを計算しようとすると、一連のネストされたシリアライズ・オブジェクトが作成されます。
JavaオブジェクトをJSONオブジェクトにシリアライズおよびシリアライズ解除するには、JSONBeanSerializationHelper
クラスを使用します。JSONBeanSerializationHelper
クラスを使用すると、独自のカスタムJSONシリアライズおよびシリアライズ解除を実装できます。また、このクラスでは、JSONシリアライズ(およびシリアライズ解除)処理後にJSONオブジェクトを変更するためのフックが提供されます。Oracle Mobile Application Framework Java APIリファレンスのoracle.adfmf.framework.api.JSONBeanSerializationHelper
クラスに関する項を参照してください。
MAFでは、GregorianCalendar
クラスのオブジェクトのシリアライズはサポートされません。JSONBeanSerializationHelper
クラスでは、GregorianCalendar
クラスのオブジェクトをシリアライズできません。これは、GregorianCalendar
クラスに循環参照が含まれるためです。かわりに、java.util.Dateまたはjava.sql.Date
をデータ操作に使用します。次の例は、java.util.Date
を使用してGregorianCalendar
オブジェクトを変換する方法を示しています。
Calendar calDate = new GregorianCalendar(); calDate.set(1985, 12, 1); // "January 1, 1986" Date date = calDate.getTime();
アプリケーション機能間のデータ・コントロールのインスタンスの共有
共有インスタンスにアクセスするすべてのアプリケーション機能について、複数のアプリケーション機能がアクセスするデータ・コントロールがメモリーに一度ロードされるように、アプリケーション機能間でデータ・コントロールのインスタンスを共有できます。
これを行うことにより、MAFアプリケーションのパフォーマンスは大幅に向上します。共有インスタンス・データ・コントロールは、データ・コントロールにアクセスするアプリケーション機能ごとではなく、メモリーに一度ロードされます。
MAFは、共有インスタンス・データ・コントロールを使用するアプリケーション機能でエンド・ユーザーが行うデータの変更を共有インスタンス・データ・コントロールを使用する他のアプリケーション機能に伝播します。
デフォルトでは、データ・コントロールはMAFアプリケーションのアプリケーション機能間で共有されません。maf-application.xml
ファイルの概要エディタの「共有インスタンスDC」ページに共有する各データ・コントロールを追加する必要があります。次の図は、HRService
データ・コントロールが共有インスタンス・データ・コントロールとして指定されている「共有インスタンスDC」ページを示しています。
デフォルトでは、MAFは、セキュリティが有効化されたアプリケーション機能からの共有インスタンス・データ・コントロールへのアクセスのみ許可します。Enable Securityプロパティをfalse
に設定して、この制限を無効化し、認証されていないユーザーが使用するアプリケーション機能が共有インスタンス・データ・コントロールにアクセスできるようにすることができます。
図15-10 maf-application.xmlの概要エディタの「共有インスタンス・データ・コントロール」ページ

「図15-10 maf-application.xmlの概要エディタの「共有インスタンス・データ・コントロール」ページ」の説明
データ・コントロールを共有インスタンス・データ・コントロールとして指定した場合でも、MAFアプリケーションがdata-control-context
の値がisolated
のタスク・フローからアクセスするデータ・コントロールは共有されません。
アプリケーション機能間のデータ・コントロールのインスタンスの共有方法
maf-application.xml
ファイルの概要エディタの「共有インスタンスDC」ページに共有する各データ・コントロールを追加して、データ・コントロールのインスタンスを共有します。
- 「アプリケーション」ウィンドウで、「アプリケーション・リソース」パネルを展開します。
- 「アプリケーション・リソース」パネルでDescriptorsを展開し、ADF META-INFを展開します。
maf-application.xml
ファイルをダブルクリックし、表示される概要エディタで「共有インスタンスDC」ナビゲーション・タブをクリックします。- 「共有インスタンスDC」ページで「追加」アイコンをクリックします。
- sharedInstanceDataControlの挿入ダイアログで、ドロップダウン・リストからデータ・コントロールのIDを選択します。
- 「OK」をクリックします。
アプリケーション機能間でデータ・コントロールのインスタンスを共有する際の処理内容
実行時、共有インスタンス・データ・コントロールとして指定したデータ・コントロールに対して、1つのデータ・コントロールのインスタンスが作成されます。これは、たとえば、関連付けられた共有インスタンス・データ・コントロールが最初に機能によって参照されたときに一度だけ、Javaクラスがインスタンス化されるということです。
共有インスタンス・データ・コントロールを参照するすべてのアプリケーション機能は、このJavaクラスのインスタンスを共有します。セキュリティ設定で許可されている場合、共有インスタンス・データ・コントロールの更新はすべてのアプリケーション機能に配信されます。たとえば、共有インスタンス・データ・コントロールが保護されたアプリケーション機能でのみ利用可能な場合(デフォルトの設定)、データ変更またはデータ・プロバイダのイベントの形での更新が保護されたアプリケーション機能に送信され、保護されていないアプリケーション機能が共有インスタンス・データ・コントロールにアクセスしようとすると、MAFはエラーをスローします。
ここで説明した動作の1つの例外は、MAFアプリケーションが、data-control-context
の値がisolated
のタスク・フローから共有インスタンス・データ・コントロールにアクセスする場合です。このシナリオでは、複数のデータ・プロバイダのインスタンスが作成されます。
JDeveloperは、共有として指定した各データ・コントロールを識別するmaf-application.xml
ファイルにエントリを追加します。次の例は、2つの共有インスタンス・データ・コントロールのエントリを示しています。最初の共有インスタンス・データ・コントロール(HRService
)は、セキュリティが有効化されたアプリケーション機能でのみアクセスできます(デフォルトの設定)。一方、2番目(CustomerService
)は、保護されていないアプリケーション機能からアクセスできます。
例15-1 maf-application.xmlファイルで定義された共有インスタンス・データ・コントロール
<adfmf:application ...>
...
<adfmf:sharedInstanceDataControls>
<adfmf:sharedInstanceDataControl dataControlId="HRService" id="sidc1"/>
<adfmf:sharedInstanceDataControl dataControlId="CustomerService" id="sidc2" securityEnabled="false"/>
</adfmf:sharedInstanceDataControls>
</adfmf:application>
DeviceFeaturesデータ・コントロールの使用方法
新しいMAFアプリケーションを作成すると、MAFは「データ・コントロール」パネルに DeviceFeatures
データ・コントロールを表示します。MAF AMXページ上のデータ・コントロールで使用可能な操作を使用して、デバイス上のユーザー連絡先の管理、電子メール・メッセージとSMSテキスト・メッセージの使用、デバイスの場所の確認、デバイスのカメラの使用、デバイスに保管しているイメージの取得を実行します。
MAFでは、アプリケーション内でDeviceFeaturesデータ・コントロールを通じて使用できるデバイス固有の機能が公開されます。DeviceFeaturesデータ・コントロールは、新しいMAFアプリケーションを作成するときに「データ・コントロール」パネルに表示されるコンポーネントです(次の図を参照)。Cordova Java APIは、このデータ・コントロールを通じて抽象化されます。これにより、MAF AMXとして実装されたアプリケーション機能から、デバイスに埋め込まれた様々なサービスにアクセスできるようになります。DeviceFeaturesデータ・コントロールから提供される操作をMAF AMXページ内にドラッグ・アンド・ドロップすることで、デバイスに格納されたユーザーの連絡先を管理する機能の追加、電子メール・メッセージとSMSテキスト・メッセージの両方の作成と送信、デバイスの位置の確認、デバイスのカメラの使用およびデバイスのファイル・システムに格納されたイメージの取得を実行できます。次の項では、これらの操作を宣言的に使用する方法や、JavaコードとJavaScriptを使用して実装する方法など、各操作について詳しく説明します。
MAFアプリケーション・テンプレートを使用してアプリケーションを作成すると、自動的にDeviceFeaturesデータ・コントロールが「データ・コントロール」パネルに表示されます。図15-11は、「概要」エディタ内のDeviceFeaturesデータ・コントロールを示しています。次のメソッドを使用できます。
-
addLocalNotification
-
cancelLocalNotification
-
createContact
-
displayFile
-
findContacts
-
getPicture
-
removeContact
-
sendEmail
-
sendSMS
-
startLocationMonitor
-
updateContact
ページを作成したら、DeviceFeaturesデータ・コントロールのメソッド(またはそれらのメソッド内にネストされたその他のオブジェクト)を「データ・コントロール」パネルからMAF AMXビューにドラッグして、関連する機能にバインドされたコマンド・ボタンやその他のコンポーネントを作成できます。デフォルトのバインディングを受け入れるか、ELを使用してそれらのバインディングを変更できます。また、JavaScriptやJavaを使用して、機能を実装または構成することもできます。「MAF AMXページへのデータ・コントロールの追加方法」を参照してください。
DeviceManager
は、デバイスの機能へのアクセスを可能にするオブジェクトです。このオブジェクトのハンドルは、DeviceManagerFactory.getDeviceManager
をコールすることによって取得できます。次の項では、DeviceManager
オブジェクトを使用してgetPicture
やcreateContact
などのメソッドを起動する方法について説明します。
ネットワーク・アクセスを除き、すべてのApache Cordova対応デバイス機能へのアクセスは、MAFアプリケーションの場合デフォルトでは有効になっていません。DeviceFeaturesデータ・コントロールによって公開されている操作が実行時に正常に機能するには、関連するプラグインがMAFアプリケーションで有効になっている必要があります。たとえば、DeviceFeaturesデータ・コントロールのsendSMS
操作を使用する場合は、MAFアプリケーションでSMSプラグインを有効にする必要があります。プラグインは手動で有効にするか、MAFアプリケーションで関連するプラグインが有効になっていない操作をドラッグ・アンド・ドロップしたときにJDeveloperによって表示されるダイアログで該当するオプションを選択して有効にします。たとえば、まだSMSプラグインが有効になっていないMAFアプリケーションのMAF AMXページにsendSMS
操作をドラッグ・アンド・ドロップすると、JDeveloperによって図のようにダイアログが表示されます。
操作に必要なプラグインが有効になっていない場合、MAF AMXページのソース・ファイル内に警告メッセージが表示されます。たとえば、MAFアプリケーションでSMSプラグインが有効になっていないと仮定しましょう。MAF AMXページの、アプリケーションがsendSMS
操作を起動する箇所に、図のような警告メッセージが表示されます。この問題を解決するには、「MAFアプリケーションでのプラグインの使用方法」の説明に従って、プラグインを手動で有効にします。
撮影を有効にするためのgetPictureメソッドの使用方法
DeviceFeatures
データ・コントロールには、デバイスのカメラでの写真撮影や既存の画像の取得のためのgetPicture
メソッドがあります。getPicture
操作をカスタマイズする手順を使用してください。カスタマイズには、sourceType
、destinationType
、quality
、allowEdit
などのパラメータを使用します。
DeviceFeaturesデータ・コントロールに含まれるgetPicture
メソッドをMAFアプリケーションで使用すると、エンド・ユーザーはデバイスのカメラとフォト・ライブラリを利用して、写真を撮影や既存のイメージの取得ができるようになります。この項の終わりに、次のことを示す例があります。
-
デバイスのカメラでエンド・ユーザーが写真撮影できるようにするJavaScriptコード。デバイスのカメラでユーザーが写真撮影できるようにするJavaコード。
-
ユーザーが保存済イメージを取得することを可能にするJavaコード。
getPicture
メソッドについては、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/
)を参照してください。
次のパラメータによって、イメージの取得元と、そのイメージを戻す方法が制御されます。
注意:
撮影する写真にtargetWidth
、targetHeight
およびquality
を指定しない場合、使用されるデフォルト値は最大値になり、メモリーに障害が発生することがあります。
-
quality:
保存済イメージの質を設定します。範囲は1から100 (100を含む)です。大きい数値を指定すると質は高くなりますが、ファイル・サイズも増大します。JPEGイメージ(encodingType
で指定します)にのみ適用されます。 -
destinationType:
戻り値の形式を次から選択します。-
DeviceManager.CAMERA_DESTINATIONTYPE_DATA_URL (0)
: Base64でエンコードされた文字列としてイメージを戻します。プログラムで使用する場合、この値は、DeviceManager
.CAMERA_DESTINATION_DATA_URL
を使用してenum
としても指定されます。イメージをイメージ・コンポーネント内に表示するには、戻された値の前にdata:image/gif;base64
を付ける必要があります。 -
DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI
(1)
: イメージ・ファイルのパスを戻します。この値は、プログラムで使用される場合、DeviceManager.CAMERA_DESTINATION_FILE_URI
を使用する列挙としても指定されます。
注意:
ファイルのURIが
getPicture
メソッドによって戻された場合、ファイルのサイズを求めるために使用する前に、問合せパラメータを削除する必要があります。次にその例を示します。String fileURI = ...getPicture(...);
fileURI = fileURI.substring(0, result.lastIndexOf("?"));
-
-
sourceType:
写真のソースを次から選択して設定します。-
DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARY (0)
: ユーザーは保存済のイメージから選択できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARY
を使用する列挙としても指定されます。 -
DeviceManager.CAMERA_SOURCETYPE_CAMERA (1)
: ユーザーはデバイスのカメラで写真撮影できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_CAMERA
を使用する列挙としても指定されます。 -
DeviceManager.CAMERA_SOURCETYPE_SAVEDPHOTOALBUM
(2)
: ユーザーは既存のフォト・アルバムから選択できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_SAVEDPHOTOALBUM
を使用する列挙としても指定されます。
-
-
allowEdit:
選択する前にイメージの単純な編集を許可するかどうかを選択します(ブール)。 -
encodingType:
戻されるイメージ・ファイルのエンコーディングを次から選択します。-
DeviceManager.CAMERA_ENCODINGTYPE_JPEG
(0): 戻されるイメージをJPEGファイルとしてエンコードします。この値は、プログラムで使用される場合、DeviceManager.CAMERA_ENCODINGTYPE_JPEG
を使用する列挙としても指定されます。 -
DeviceManager.CAMERA_ENCODINGTYPE_PNG
(1): 戻されるイメージをPNGファイルとしてエンコードします。この値は、プログラムで使用される場合、DeviceManager.CAMERA_ENCODINGTYPE_PNG
を使用する列挙としても指定されます。
-
-
targetWidth:
幅をピクセル単位で設定してイメージのスケールを変更します。アスペクト比は維持されます。負の値または0の場合、イメージの元のディメンションが使用されます。 -
targetHeight:
高さをピクセル単位で設定してイメージのスケールを変更します。アスペクト比は維持されます。負の値または0の場合、イメージの元のディメンションが使用されます。
DeviceFeaturesデータ・コントロールを使用してgetPicture操作をカスタマイズするには:
-
「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからgetPicture操作をドラッグし、ボタンとしてページにドロップします。
ユーザーがよりきめ細かく制御できるようにするには、getPicture操作をパラメータ・フォームとしてドロップします。これにより、エンド・ユーザーは写真を撮影したり既存のイメージを選択する前に、設定を指定できるようになります。
-
「アクションの編集」ダイアログで、前述のすべてのパラメータの値を設定します。イメージがファイル名として戻されるように、
destinationType
= 1
を指定するようにします。 -
getPictureの戻り値をドラッグし、それを出力テキストとしてページ上にドロップします。
-
「共通コンポーネント」パネルで、「コンポーネント・パレット」から「イメージ」をドラッグし、ページ上にドロップします。
-
「イメージ」の
source
属性を、getPicture
操作の戻り値に設定します。バインディングの式は、#{bindings.Return.inputValue}
である必要があります。
ユーザーのフォト・ライブラリからのイメージを表示するバインディングを図に示します。
このアプリケーションを実行すると、イメージ・チューザが自動的に表示され、エンド・ユーザーは表示するイメージを選択できます。イメージ・チューザが自動的に表示される理由は、イメージ・コントロールがgetPicture
操作の戻り値にバインドされており、それによってgetPicture
操作が起動するためです。
注意:
getPicture
メソッドのタイムアウト値は、5分に設定されます。デバイス操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。
次に示すプラットフォーム固有の問題に留意してください。
-
iOS
-
いくつかのデバイスでメモリー・エラーが発生しないようにするには、qualityを50未満に設定します。
-
destinationType
FILE_URI
を使用すると、写真はアプリケーションの一時ディレクトリに保存されます。 -
アプリケーションの一時ディレクトリの内容は、アプリケーションの終了時に削除されます。記憶域の空き領域が問題になる場合は、
navigator.fileMgr
APIを使用してこのディレクトリの内容を削除することもできます。 -
targetWidth
とtargetHeight
を使用するには、これらを両方とも指定する必要があります。一方または両方の値が負の値または0の場合、イメージの元のディメンションが使用されます。
-
-
Android
-
allowEdit
パラメータを無視します。 -
Camera.PictureSourceType.PHOTOLIBRARY
とCamera.PictureSourceType.SAVEDPHOTOALBUM
では、どちらも同じフォト・アルバムが表示されます。 -
Camera.EncodingType
はサポートされていません。パラメータは無視され、常にJPEGイメージが生成されます。 -
targetWidth
とtargetHeight
は、個別に指定できます。一方のパラメータが正の値で、もう一方が負の値またはゼロを使用して元のサイズを表す場合、正の値がそのディメンションに使用され、もう一方のディメンションは元のアスペクト比を維持するようにスケール変更されます。 -
destinationType
DATA_URL
を使用すると、イメージが大きい場合は使用可能なメモリーがすべて使用され、メモリー不足のエラーが発生する場合があります。通常は、デフォルトのイメージ・サイズを使用すると、この動作が発生します。targetWidth
とtargetHeight
を設定してイメージ・サイズを制限します。
-
次の例は、デバイスのカメラでユーザーが写真撮影できるようにするJavaScriptコードを示しています。結果は、保存済イメージへのフルパスになります。
// The camera, like many other device-specific features, is accessed // from the global 'navigator' object in JavaScript. // Note that in the Cordova JavaScript APIs, the parameters are passed // in as a dictionary, so it is only necessary to provide key-value pairs // for the parameters you want to specify. navigator.camera.getPicture(onSuccess, onFail, { quality: 50 }); function onSuccess(imageURI) { var image = document.getElementById('myImage'); image.src = imageURI; } function onFail(message) { alert('Failed because: ' + message); }
次の例は、デバイスのカメラでユーザーが写真撮影できるようにするJavaコードを示しています。結果は、保存済イメージへのフルパスになります。
import oracle.adf.model.datacontrols.device; // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. // Take a picture with the device's camera. // The result will be the full path to the saved PNG image. String imageFilename = DeviceManagerFactory.getDeviceManager().getPicture(100, DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI, DeviceManager.CAMERA_SOURCETYPE_CAMERA, false, DeviceManager.CAMERA_ENCODINGTYPE_PNG, 0, 0);
次の例は、ユーザーが保存済イメージを取得することを可能にするJavaコードを示しています。結果は、Base64でエンコードされたJPEGになります。
import oracle.adf.model.datacontrols.device; // Retrieve a previously-saved image. The result will be a base64-encoded JPEG. String imageData = DeviceManagerFactory.getDeviceManager().getPicture(100, DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URL, DeviceManager.CAMERA_SOURCETYPE__PHOTOLIBRARY, false, DeviceManager.CAMERA_ENCODINGTYPE_JPEG, 0, 0);
テキスト・メッセージを有効にするためのSendSMSメソッドの使用方法
DeviceFeatures
データ・コントロールのsendSMS
を使用して、デバイスのショート・メッセージ・サービス(SMS)テキスト・メッセージング・インターフェイスでSMSメッセージを送受信します。sendSMS
操作はカスタマイズできます。
DeviceFeaturesデータ・コントロールに含まれるsendSMS
メソッドをMAFアプリケーションで使用すると、デバイスのショート・メッセージ・サービス(SMS)テキスト・メッセージング・インタフェースを利用して、ユーザーがSMSメッセージを送受信できるようになります。MAFでは、デバイスのSMSインタフェースを表示して、必要に応じて次のフィールドにデータを事前移入できます。
-
to:
受信者をリストします(カンマ区切り)。 -
body:
メッセージの本文を追加します。
SMSテキスト・メッセージング・インタフェースが表示されると、ユーザーはSMSを送信することも、それを取り消すこともできます。デバイスとキャリアの制限により、SMSは自動的に送信できません。実際にSMSを送信できるのはユーザーのみです。
sendSMS
メソッドのタイムアウト値は、5分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。
Androidでは、ユーザーがSMSメッセージの編集中にアプリケーションを切り替えて、その後戻すと、SMS編集画面は表示されなくなります。かわりに、そのメッセージは下書きとして保存され、手動で選択して編集を続けることができます。
ユニバーサルWindowsプラットフォーム上のMAFアプリケーションは、SMSテキスト・メッセージを現在サポートしていません。
DeviceFeaturesデータ・コントロールを使用してsendSMS操作をカスタマイズするには:
SMSの送信のためページに対話型フォームを表示するには、sendSMS
操作を「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからドラッグし、ページ・デザイナ上にパラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスのSMSインタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに値が事前移入されいる送信準備が整ったSMSが表示されます。
ページ上の編集可能なフォームを使用してSMSを送信するためのバインディングを図に示します。
次の例は、ユーザーがデバイスのテキスト・メッセージング・インタフェースを使用してSMSメッセージを送信できるようにするコード例を示しています。
sendSMS
メソッドについては、MAF JavadocのDeviceDataControl
クラスおよびCordovaのドキュメント(http://cordova.apache.org/
)を参照してください。
次の例は、ユーザーがSMSメッセージを送信できるようにするJavaScriptコードを示しています。
adf.mf.api.sendSMS({to: "5551234567", body: "This is a test message"});
次の例は、ユーザーがSMSメッセージを送信できるようにするJavaコードを示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. // Send an SMS to the phone number "5551234567" DeviceManagerFactory.getDeviceManager().sendSMS("5551234567", "This is a test message");
電子メールを有効にするためのsendEmailメソッドの使用方法
DeviceFeatures
データ・コントロールには、構成済の電子メール・アカウントの電子メール・メッセージをデバイスの電子メール・メッセージング・インタフェースで送受信するためのsendEmail
メソッドがあります。sendEmail
操作はカスタマイズできます。
DeviceFeaturesデータ・コントロールに含まれるsendEmail
メソッドをMAFアプリケーションで使用すると、デバイスの電子メール・メッセージング・インタフェースを利用して、ユーザーが電子メール・メッセージを送受信できるようになります。MAFでは、デバイスの電子メール・インタフェースを表示して、必要に応じて次のフィールドにデータを事前移入できます。
-
to:
受信者をリストします(カンマ区切り)。 -
cc:
CC受信者をリストします(カンマ区切り)。 -
subject:
メッセージの件名を追加します。 -
body:
メッセージの本文を追加します。 -
bcc:
BCC受信者をリストします(カンマ区切り)。 -
attachments:
電子メールに添付するファイルの名前をリストします(カンマ区切り)。 -
mimeTypes:
添付ファイルに使用するMIMEタイプをリストします(カンマ区切り)。MAFで自動的にMIMEタイプを決定するには、nullを指定します。この項の最後にある例に示すように、選択した添付ファイルのMIMEタイプのみを指定することもできます。
デバイスの電子メール・インタフェースが表示されると、ユーザーは電子メールを送信することも、それを取り消すこともできます。デバイスとキャリアの制限により、電子メールは自動的に送信できません。実際に電子メールを送信できるのは、ユーザーのみです。また、電子メールを送信するには、1つ以上の電子メール・アカウントを構成する必要があります。アカウントが構成されていない場合、電子メール・アカウントが見つからないことを示すエラーが表示されます。
注意:
sendEmail
メソッドのタイムアウト値は5分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。
注意:
Androidでは、ユーザーが電子メールの編集中にアプリケーションを切り替えて、その後戻すと、電子メールの編集画面は表示されなくなります。かわりに、そのメッセージは下書きとして保存され、手動で選択して編集を続けることができます。
DeviceFeaturesデータ・コントロールを使用してsendEmail操作をカスタマイズするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからsendEmail
操作をページ・デザイナ上にドラッグし、パラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスの電子メール・インタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに値が事前移入され、送信準備が整った電子メールが表示されます。
ページ上の編集可能なフォームを使用して電子メールを送信するためのバインディングを図に示します。
図15-16 デザインタイムで編集可能なフォームを使用して電子メールを送信するためのバインディング

「図15-16 デザインタイムで編集可能なフォームを使用して電子メールを送信するためのバインディング」の説明
次に、ユーザーがデバイスの電子メール・インタフェースを使用して電子メール・メッセージを送信できるようにするコード例を示します。
sendEmail
メソッドについては、MAF JavadocのDeviceDataControl
クラスおよびCordovaのドキュメント(http://cordova.apache.org/
)を参照してください。
次の例は、ユーザーが電子メール・メッセージを送信できるようにするJavaScriptコードを示しています。
// Populate an email to 'ann.li@example.com', // copy 'joe.jones@example.com', with the // subject 'Test message', and the body 'This is a test message' // No BCC recipients or attachments adf.mf.api.sendEmail({to: "ann.li@example.com", cc: "joe.jones@example.com", subject: "Test message", body: "This is a test message"}); // Populate the same email as before, but this time, also BCC // 'john.smith@example.com' & 'jane.smith@example.com' and attach two files. // By not specifying a value for the mimeTypes parameter, you are telling // ADFMobile to automatically determine the MIME type for each of the attachments. adf.mf.api.sendEmail({to: "ann.li@example.com", cc: "joe.jones@example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@example.com,jane.smith@example.com", attachments: "path/to/file1.txt,path/to/file2.png"}); // For iOS only: Same as previous email, but this time, explicitly specify // all the MIME types. adf.mf.api.sendEmail({to: "ann.li@example.com", cc: "joe.jones@example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@example.com,jane.smith@example.com", attachments: "path/to/file1.txt,path/to/file2.png"}); mimeTypes: "text/plain,image/png"}); // For iOS only: Same as previous email, but this time, only specify // the MIME type for the second attachment and let the system determine // the MIME type for the first one. adf.mf.api.sendEmail({to: "ann.li@example.com", cc: "joe.jones@example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@example.com,jane.smith@example.com", attachments: "path/to/file1.txt,path/to/file2.png"}); mimeTypes: ",image/png"}); // For Android only: Same as previous e-mail, but this time, explicitly specify // the MIME type. adf.mf.api.sendEmail({to: "ann.li@example.com", cc: "joe.jones@example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@example.com,jane.smith@example.com", attachments: "path/to/file1.txt,path/to/file2.png"}); mimeTypes: "image/*"}); // You can also use "plain/text" as the MIME type as it just determines the type // of applications to be filtered in the application chooser dialog.
次の例は、ユーザーが電子メール・メッセージを送信できるようにするJavaコードを示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. // Populate an email to 'ann.li@example.com', copy 'joe.jones@example.com', with the // subject 'Test message', and the body 'This is a test message'. // No BCC recipients or attachments. DeviceManagerFactory.getDeviceManager().sendEmail( "ann.li@example.com", "joe.jones@example.com", "Test message", "This is a test message", null, null, null); // Populate the same email as before, but this time, also BCC // 'john.smith@example.com' & 'jane.smith@example.com' and attach two files. // By specifying null for the mimeTypes parameter, you are telling // ADFMobile to automatically determine the MIME type for each of the attachments. DeviceManagerFactory.getDeviceManager().sendEmail( "ann.li@example.com", "joe.jones@example.com", "Test message", "This is a test message", "john.smith@example.com,jane.smith@example.com", "path/to/file1.txt,path/to/file2.png", null); // Same as previous email, but this time, explicitly specify all the MIME types. DeviceManagerFactory.getDeviceManager().sendEmail( "ann.li@example.com", "joe.jones@example.com", "Test message", "This is a test message", "john.smith@example.com,jane.smith@example.com", "path/to/file1.txt,path/to/file2.png", "text/plain,image/png"); // Same as previous email, but this time, only specify the MIME type for the // second attachment and let the system determine the MIME type for the first one. DeviceManagerFactory.getDeviceManager().sendEmail( "ann.li@example.com", "joe.jones@example.com", "Test message", "This is a test message", "john.smith@example.com,jane.smith@example.com", "path/to/file1.txt,path/to/file2.png", ",image/png");
連絡先の作成を有効にするためのcreateContactメソッドの使用方法
DeviceFeaturesデータ・コントロールに含まれるcreateContact
メソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーが新しい連絡先を作成してデバイスのアドレス帳に保存できるようになります。
MAFでは、デバイスのインタフェースを表示して、必要に応じてContact
フィールドにデータを事前移入できます。この項の最後の例に示すように、createContact
メソッドはContact
オブジェクトをパラメータとして使用し、作成されたContact
オブジェクトを戻します。
createContact
メソッドおよびContact
オブジェクトの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。Contact
のプロパティについては、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」も参照してください。
注意:
createContact
メソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。
注意:
null Contact
オブジェクトがメソッドに渡された場合、例外がスローされます。
DeviceFeaturesデータ・コントロールを使用してcreateContact操作をカスタマイズするには:
private Contact contactToBeCreated; public void setContactToBeCreated(Contact contactToBeCreated) { this.contactToBeCreated = contactToBeCreated; } public Contact getContactToBeCreated() { String givenName = "Mary"; String familyName = "Jones"; String note = "Just a Note"; String phoneNumberType = "mobile"; String phoneNumberValue = "650-555-0111"; String phoneNumberNewValue = "650-555-0199"; String emailType = "home"; String emailTypeNew = "work"; String emailValue = "Mary.Jones@example.com"; String addressType = "home"; String addressStreet = "500 Barnacle Pkwy"; String addressLocality = "Redwood Shores"; String addressCountry = "USA"; String addressPostalCode = "94065"; ContactField[] phoneNumbers = null; ContactField[] emails = null; ContactAddresses[] addresses = null; /* * Create contact */ this.contactToBeCreated = new Contact(); ContactName name = new ContactName(); name.setFamilyName(familyName); name.setGivenName(givenName); this.contactToBeCreated.setName(name); ContactField phoneNumber = new ContactField(); phoneNumber.setType(phoneNumberType); phoneNumber.setValue(phoneNumberValue); phoneNumbers = new ContactField[] { phoneNumber }; ContactField email = new ContactField(); email.setType(emailType); email.setValue(emailValue); emails = new ContactField[] { email }; ContactAddresses address = new ContactAddresses(); address.setType(addressType); address.setStreetAddress(addressStreet); address.setLocality(addressLocality); address.setCountry(addressCountry); addresses = new ContactAddresses[] { address }; this.contactToBeCreated.setNote(note); this.contactToBeCreated.setPhoneNumbers(phoneNumbers); this.contactToBeCreated.setEmails(emails); this.contactToBeCreated.setAddresses(addresses); return this.contactToBeCreated; }
次の例は、ユーザーがデバイスで連絡先を作成できるようにするコード例を示しています。
次の例は、createContact
のJavaScriptコードを示しています。
// Contacts, like many other device-specific features, // are accessed from the global 'navigator' object in JavaScript var contact = navigator.contacts.create(); var name = new ContactName(); name.givenName = "Mary"; name.familyName = "Jones"; contact.name = name; // Store contact phone numbers in ContactField[] var phoneNumbers = [1]; phoneNumbers[0] = new ContactField('home', '650-555-0123', true); contact.phoneNumbers = phoneNumbers; // Store contact email addresses in ContactField[] var emails = [1]; emails[0] = new ContactField('work', 'Mary.Jones@example.com'); contact.emails = emails; // Save contact.save(onSuccess, onFailure); function onSuccess() { alert("Create Contact successful."); } function onFailure(Error) { alert("Create Contact failed: " + Error.code); }
次の例は、createContact
のJavaコードを示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; import oracle.adf.model.datacontrols.device.ContactAddresses; import oracle.adf.model.datacontrols.device.ContactField; import oracle.adf.model.datacontrols.device.ContactName; String givenName = "Mary"; String familyName = "Jones"; String note = "Just a Note"; String phoneNumberType = "mobile"; String phoneNumberValue = "650-555-0111"; String phoneNumberNewValue = "650-555-0199"; String emailType = "home"; String emailTypeNew = "work"; String emailValue = "Mary.Jones@example.com"; String addressType = "home"; String addressStreet = "500 Barnacle Pkwy"; String addressLocality = "Redwood Shores"; String addressCountry = "USA"; String addressPostalCode = "91234"; ContactField[] phoneNumbers = null; ContactField[] emails = null; ContactAddresses[] addresses = null; ContactField[] emails = null; /* * Create contact */ Contact aContact = new Contact(); ContactName name = new ContactName(); name.setFamilyName(familyName); name.setGivenName(givenName); aContact.setName(name); ContactField phoneNumber = new ContactField(); phoneNumber.setType(phoneNumberType); phoneNumber.setValue(phoneNumberValue); phoneNumbers = new ContactField[] { phoneNumber }; ContactField email = new ContactField(); email.setType(emailType); email.setValue(emailValue); emails = new ContactField[] { email }; ContactAddresses address = new ContactAddresses(); address.setType(addressType); address.setStreetAddress(addressStreet); address.setLocality(addressLocality); address.setCountry(addressCountry); addresses = new ContactAddresses[] { address }; aContact.setNote(note); aContact.setPhoneNumbers(phoneNumbers); aContact.setEmails(emails); aContact.setAddresses(addresses); // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. // Invoking the createContact method, using the DeviceDataControl object. Contact createdContact = DeviceManagerFactory.getDeviceManager() .findContacts.createContact(aContact);
連絡先の検索を有効にするためのfindContactsメソッドの使用方法
DeviceFeaturesデータ・コントロールに含まれるfindContacts
メソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーがデバイスのアドレス帳から1つ以上の連絡先を検索できるようになります。
MAFでは、デバイスのインタフェースを表示して、必要に応じてfindContacts
フィールドにデータを事前移入できます。findContacts
メソッドでは、フィルタ文字列と検索する(そして、見つかったコンタクト先の一部として戻す)フィールド名のリストを使用します。フィルタ文字列には、コンタクト先内の検索する任意の項目を指定できます。findContacts
メソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。
findContacts
操作では、次の引数を使用します。
-
contactFields:
必須パラメータ。このパラメータは、findContacts
操作によって生成されるContact
オブジェクトに含めるフィールドを指定するために使用します。フィールドはカンマで区切ります(スペースの有無は関係ありません)。 -
filter:
コンタクト先をフィルタするために使用する検索文字列。(文字列) (デフォルト:""
) -
multiple:
findContacts
操作から複数のコンタクト先を戻すかどうかを決定します。(ブール) (デフォルト:false
)
注意:
次のリストに含まれていないフィールド名を渡すと、findContacts
操作の戻り値がnull
になる場合があります。また、Contact
のフィールドの引数に指定したフィールドのみが、Contact
オブジェクトの一部として戻されます。
次のリストに示すContact
のプロパティを渡して、検索に使用し、見つかったコンタクト先の一部として戻すことができます。
-
id:
グローバルに一意な識別子 -
displayName:
エンド・ユーザーへの表示に適した、このコンタクト先の名前 -
name:
人物名のすべてのコンポーネントを含むオブジェクト -
nickname:
コンタクト先のカジュアルな名前。このフィールドをnullに設定すると、空の文字列として保存されます。 -
phoneNumbers:
コンタクト先のすべての電話番号の配列 -
emails:
コンタクト先のすべての電子メール・アドレスの配列 -
addresses:
コンタクト先のすべての住所の配列 -
ims:
コンタクト先のすべてのインスタント・メッセージング(IM)・アドレスの配列(ims
プロパティは、このリリースではサポートされていません。)注意:
このリリースでは、MAFは
Contact
プロパティのims
をサポートしていません。ims
プロパティのあるコンタクト先を作成する場合、MAFはims
プロパティなしでコンタクト先を保存します。その結果、ユーザーがims
に基づいて検索を実行しようとすると、コンタクト先を検索できなくなります。また、ユーザーが「検索」フィールドにims
を入力しようとすると、ims
はnull
として戻されます。 -
organizations:
コンタクト先のすべての組織の配列 -
birthday:
コンタクト先の誕生日。プログラムで連絡先の誕生日フィールドを設定することや、アドレス帳に連絡先を永続化することはできませんが、オペレーティング・システムのアドレス帳アプリケーションを使用してこのフィールドを手動で設定できます。 -
note:
コンタクト先に関するメモ。このフィールドをnullに設定すると、空の文字列として保存されます。 -
photos:
コンタクト先の写真の配列 -
categories:
コンタクト先のすべてのユーザー定義カテゴリの配列。 -
urls:
コンタクト先に関連付けられたWebページの配列
注意:
findContacts
メソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。
DeviceFeaturesデータ・コントロールを使用してfindContacts操作をカスタマイズするには:
-
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールから
findContacts
操作をドラッグし、リンク、ボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、
findContacts
操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してfindContacts
操作を実行できます。パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが前述のContactの様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用して
findContacts
操作を実行できます。 -
操作から戻されるオブジェクトの
Contact
を、「データ・コントロール」パネルにあるfindContacts
操作の下からドラッグし、フォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。findContacts
操作を実行すると、結果がこのフォームに表示されます。
次の例は、findContacts
メソッドに指定できる引数値を示しています。
// This will return just one contact with only the ID field: Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("", "", false); // This will return all contacts with only ID fields: Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("", "", true); // This will return just one contact with all fields: Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("*", "", false); // This will return all contacts with all fields: Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("*", "", true); // These will throw an exception as contactFields is a required argument and cannot be null: DeviceManagerFactory.getDeviceManager().findContacts(null, "", false); DeviceManagerFactory.getDeviceManager().findContacts(null, "", true); // These will throw an exception as the filter argument cannot be null: DeviceManagerFactory.getDeviceManager().findContacts("", null, false); DeviceManagerFactory.getDeviceManager().findContacts("", null, true);
注意:
渡されるContact
のフィールドは、文字列(カンマで区切られたフィールドを含む)です。いずれかの引数がnull
としてメソッドに渡された場合、例外がスローされます。
次のJavaScript例は、姓でコンタクト先を検索し、コンタクト先の名前、電話番号、電子メール、住所およびメモを取得する方法を示しています。
var filter = ["name", "phoneNumbers", "emails", "addresses", "note"]; var options = new ContactFindOptions(); options.filter="FamilyName"; // Contacts, like many other device-specific features, are accessed from // the global 'navigator' object in JavaScript. navigator.contacts.find(filter, onSuccess, onFail, options); function onSuccess(contacts) { alert ("Find Contact call succeeded! Number of contacts found = " + contacts.length); } function onFail(Error) { alert("Find Contact failed: " + Error.code); }
次のJava例は、姓でコンタクト先を検索し、コンタクト先の名前、電話番号、電子メール、住所およびメモを取得する方法を示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; /* * Find Contact - Find contact by family name. * * See if we can find the contact that we just created. */ String familyName = "FamilyName" // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts( "name,phoneNumbers,emails,addresses,note", familyName, true);
連絡先の更新を有効にするためのupdateContactメソッドの使用方法
DeviceFeaturesデータ・コントロールに含まれるupdateContact
メソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーがデバイスのアドレス帳に含まれる連絡先を更新できるようになります。
MAFでは、デバイスのインタフェースを表示して、必要に応じてupdateContact
フィールドにデータを事前移入できます。この項の最後の例に示すように、updateContact
メソッドはContact
オブジェクトをパラメータとして使用し、更新されたupdateContact
オブジェクトを戻します。
updateContact
メソッドおよびContact
オブジェクトの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。Contact
のプロパティについては、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」も参照してください。
注意:
入力パラメータとして必要なContact
オブジェクトは、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」の説明に従って、findContacts
メソッドを使用することによって検索できます。nullのContact
オブジェクトがメソッドに渡された場合、例外がスローされます。
DeviceFeaturesデータ・コントロールを使用してupdateContact操作をカスタマイズするには:
次の例は、コンタクト先の電話番号を更新および追加する方法を示しています。
次のJavaScript例は、updateContact
の使用方法を示しています。
function updateContact(contact) { try { if (null != contact.phoneNumbers) { alert("Number of phone numbers = " + contact.phoneNumbers.length); var numPhoneNumbers = contact.phoneNumbers.length; for (var j = 0; j < numPhoneNumbers; j++) { alert("Type: " + contact.phoneNumbers[j].type + "\n" + "Value: " + contact.phoneNumbers[j].value + "\n" + "Preferred: " + contact.phoneNumbers[j].pref); contact.phoneNumbers[j].type = "mobile"; contact.phoneNumbers[j].value = "408-555-0100"; } // save contact.save(onSuccess, onFailure); } else { //alert ("No phone numbers found in the contact."); } } catch(e) { alert("updateContact - ERROR: " + e.description); } } function onSuccess() { alert("Update Contact successful."); } function onFailure(Error) { alert("Update Contact failed: " + Error.code); }
次のJavaScript例は、updateContact
を使用して既存の電話番号に電話番号を追加する方法を示しています。
function updateContact(contact) { try { var phoneNumbers = [1]; phoneNumbers[0] = new ContactField('home', '650-555-0123', true); contact.phoneNumbers = phoneNumbers; // save contact.save(onSuccess, onFailure); } catch(e) { alert("updateContact - ERROR: " + e.description); } } function onSuccess() { alert("Update Contact successful."); } function onFailure(Error) { alert("Update Contact failed: " + Error.code); }
次のJavaコード例は、updateContact
を使用してコンタクト先の電話番号、電子メール・タイプおよび郵便番号を更新する方法を示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; /* * Update Contact - Updating phone number, email type, and adding address postal code */ String familyName = "FamilyName"; String phoneNumberNewValue = "650-555-0123"; String emailTypeNew = "work"; String addressPostalCode = "91234"; Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts( "name,phoneNumbers,emails,addresses,note", familyName, true); // Assuming there was only one contact returned, we can use the first contact in the array. // If more than one contact is returned then we have to filter more to find the exact contact // we need to update. foundContacts[0].getPhoneNumbers()[0].setValue(phoneNumberNewValue); foundContacts[0].getEmails()[0].setType(emailTypeNew); foundContacts[0].getAddresses()[0].setPostalCode(addressPostalCode); Contact updatedContact = DeviceManagerFactory.getDeviceManager().updateContact(foundContacts[0]);
次のJava例は、updateContact
を使用して既存の電話番号に電話番号を追加する方法を示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; String additionalPhoneNumberValue = "408-555-0123"; String additionalPhoneNumberType = "mobile"; // Create a new phoneNumber that will be appended to the previous one. ContactField additionalPhoneNumber = new ContactField(); additionalPhoneNumber.setType(additionalPhoneNumberType); additionalPhoneNumber.setValue(additionalPhoneNumberValue); foundContacts[0].setPhoneNumbers(new ContactField[] { additionalPhoneNumber }); // Access device features in Java code by acquiring an instance of the DeviceManager // from the DeviceManagerFactory. Contact updatedContact = DeviceManagerFactory.getDeviceManager().updateContact(foundContacts[0]);
注意:
updateContact
メソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。
連絡先の削除を有効にするためのremoveContactメソッドの使用方法
DeviceFeatures
データ・コントロールには、findContacts
を使用して検索した連絡先をデバイスのアドレス帳から削除するためのremoveContact
メソッドがあります。removeContact
操作をカスタマイズする手順を使用してください。
DeviceFeaturesデータ・コントロールに含まれるremoveContact
メソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーがデバイスのアドレス帳から連絡先を削除できるようになります。MAFでは、デバイスのインタフェースを表示して、必要に応じてremoveContact
フィールドにデータを事前移入できます。この項の最後の例に示すように、removeContact
メソッドはContact
オブジェクトをパラメータとして使用します。
注意:
入力パラメータとして必要なContact
オブジェクトは、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」の説明に従って、findContacts
メソッドを使用することによって検索できます。
DeviceFeaturesデータ・コントロールを使用してremoveContact操作をカスタマイズするには:
この項の最後にある例は、findContacts
を使用して見つかったコンタクト先を削除する方法を示しています。removeContact
メソッドとContactオブジェクトについては、MAF JavadocのDeviceDataControl
クラスおよびCordovaのドキュメント(http://cordova.apache.org/
)を参照してください。
注意:
Androidでは、removeContact
操作を実行しても完全にはコンタクト先が削除されません。removeContact
メソッドをコールしてコンタクト先を削除すると、「(不明)」の付いた名前がアプリケーション内のコンタクト先リストに表示されます。
次のJavaScriptコード例は、removeContact
の使用方法を示しています。
// Remove the contact from the device contact.remove(onSuccess,onError); function onSuccess() { alert("Removal Success"); } function onError(contactError)' { alert("Error = " + contactError.code); }
次のJavaコード例は、removeContact
の使用方法を示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; /* * Remove the contact from the device */ Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts( "name,phoneNumbers,emails,addresses", familyName, true); // Assuming there is only one contact returned, we can use the first contact in the array. // If more than one contact is returned we will have to filter more to find the // exact contact we want to remove. // Access device features in Java code by acquiring an instance of the DeviceManager // from the DeviceManagerFactory. DeviceManagerFactory.getDeviceManager().removeContact(foundContacts[0]);
注意:
removeContact
メソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。
地理的位置を有効にするためのstartLocationMonitorメソッドの使用方法
DeviceFeaturesデータ・コントロールに含まれるstartLocationMonitor
メソッドをMAFアプリケーションで使用すると、デバイスの地理的位置情報サービスを使用して、デバイスの位置を取得および追跡できます。
MAFで公開されているAPIを使用すると、デバイスの現在位置を取得できるため、特定の時点におけるデバイスの現在位置を取得したり、定期的にその情報をサブスクライブできます。この項の最後にある例は、地理的位置情報を使用してデバイスの位置変化をサブスクライブする方法と、デバイスの位置を取得する方法を示しています。startLocationMonitor
メソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。
MAFにより公開されるAPIを使用するには、MAFに用意されているGeolocationコア・プラグインも有効化する必要があります。AndroidプラットフォームにデプロイするMAFアプリケーションの場合、Geolocation - Google Play Services (cordova-plugin-geolocation-play-services
)というプラグインはMAF APIを介してGoogle Playサービス・ロケーションAPIを起動するため、このプラグインを有効化することをお薦めします。
注意:
Androidでは、APIレベル26 (Android 8.0)以上を使用するデバイスで(MAFアプリケーションでGeolocation - Google Play Servicesコア・プラグインを使用した場合)、altitudeAccuracy
プロパティがサポートされています。
DeviceFeaturesデータ・コントロールを使用してデバイスの位置変化をリスニングするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからstartLocationMonitor
操作をページ・デザイナ上にドラッグし、リンクまたはボタンとしてドロップします。「アクションの編集」ダイアログで入力を要求されたら、次のリストを参照するか、Oracle Mobile Application Framework Java APIリファレンスでDeviceDataControl
クラスのstartLocationMonitor
メソッドに関する項を参照して、その操作でサポートされるパラメータの値をフィールドに入力します。
-
enableHighAccuracy:
true
の場合、位置を最も正確に取得できる方法を使用します。これは単なるヒントであり、オペレーティング・システムでは考慮されない場合があります。多くの場合、デバイスには、携帯電話基地局の三角測量、Wi-Fiホットスポットの参照、実際のGPSなど、位置の修正を取得するためのいくつかの異なるメカニズムがあります。false
を指定すると、正確性の低い位置を受け入れることになりますが、この場合、レスポンスの速度が向上し、消費電力が低下する可能性があります。 -
updateInterval:
更新の受信頻度をミリ秒単位で定義します。位置の更新は、指定した頻度では配信されない場合があります。オペレーティング・システムは、デバイスの位置の大きな変化が検出されるまで待機してから、別の位置の更新をトリガーする場合があります。 -
locationListener:
次のシグネチャを含むBeanメソッドに解決されるEL式。void methodName(Location newLocation)
このEL式は、位置の更新を受信するたびに評価されます。たとえば、
viewScope.LocationListenerBean.locationUpdated
(#{}
で囲みません)と入力した後、LocationListenerBean
というBeanをviewScope
内に定義し、次のシグネチャを含むメソッドを実装します。public void locationUpdated(Location currentLocation) { System.out.println(currentLocation); // To stop subscribing to location updates, invoke the following: // DeviceManagerFactory.getDeviceManager().clearWatchPosition( // currentLocation.getWatchId()); }
注意:
EL式の評価結果として
locationListener
の名前が必要でないかぎり、locationListener
を指定するためにEL構文#{LocationListenerBean.locationUpdate}
を使用しないでください。
この項の最後にある例は、DeviceManager.startUpdatingPosition
メソッドを使用してデバイスの位置変化をサブスクライブする方法を示しています。
JavaScriptを使用してデバイスの位置変化をサブスクライブする方法の例は、Cordovaのドキュメント(http://cordova.apache.org/
)を参照してください。
locationListener
によって指定されたコールバック関数内に戻されるパラメータは、次のとおりです。
-
double getAccuracy
: m単位の緯度と経度を示す座標の精度レベル。 -
double getAltitude
: m単位の楕円体高度。 -
double getLatitude
: 10進度単位の緯度。 -
double getLongitude
: 10進度単位の経度。 -
double getAltitudeAccuracy
: m単位の高度座標の精度レベル。 -
double getHeading
: 真北から時計回りに計測した度単位で示される進行方向 -
double getSpeed
: m/秒単位で指定される、デバイスの現在の対地速度 -
long getTimestamp
: Unixエポックからのミリ秒単位の経過時間で示されるタイムスタンプの作成 -
String getWatchId
: 定期的な位置の更新をサブスクライブするときのみ使用します。後から位置の更新のサブスクライブを停止するために使用できる一意のID
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; import oracle.adf.model.datacontrols.device.GeolocationCallback; import oracle.adf.model.datacontrols.device.Location; // Subscribe to location updates that will be delivered every 20 seconds, with high accuracy. // As you can have multiple subscribers, let's identify this one as 'MyGPSSubscriptionID'. // Notice that this call returns the watchID, which is usually the same as the watchID passed in. // However, it may be different if the specified watchID conflicts with an existing watchID, // so be sure to always use the returned watchID. String watchID = DeviceManagerFactory.getDeviceManager().startUpdatingPosition(20000, true, " "MyGPSSubscriptionID", new GeolocationCallback() { public void locationUpdated(Location position) { System.out.println("Location updated to: " + position); } }); // The previous call returns immediately so that you can continue processing. // When the device's location changes, the locationUpdated() method specified in // the previous call will be invoked in the context of the current feature. // When you wish to stop being notified of location changes, call the following method: DeviceManagerFactory().getDeviceManager().clearWatchPosition(watchID);
startLocationMonitor
メソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。
次の例は、DeviceManager.getCurrentPosition
を使用してデバイスの現在位置を(1回)取得する方法を示しています。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; import oracle.adf.model.datacontrols.device.Location; // Get the device's current position, with highest accuracy, and accept a cached location that is // no older than 60 seconds. Location currentPosition = DeviceManagerFactory.getDeviceManager().getCurrentPosition(60000, true); System.out.println("The device's current location is: latitude=" + currentPosition.getLatitude() + ", longitude=" + currentPosition.getLongitude());
ファイルの表示を有効にするためのdisplayFileメソッドの使用方法
DeviceFeaturesデータ・コントロールに含まれるdisplayFile
メソッドを使用すると、MAFアプリケーションでデバイスにあるファイルを表示できます。
プラットフォームに応じて、アプリケーション・ユーザーはPDF、イメージ・ファイル、Microsoft Officeドキュメントおよびその他の様々なファイル・タイプを表示できます。iOSでは、アプリケーション・ユーザーは、サポートされているファイルをMAFアプリケーション内でプレビューできます。またユーザーは、それらのファイルをサードパーティ・アプリケーションで開く、電子メールで送信する、プリンタに送信するなどの操作を行うこともできます。
file://
URIを渡す場合にAndroidの制限に準拠するように、次の親ディレクトリのいずれかの子である必要があります。
-
AdfmfJavaUtilities.TemporaryDirectory
-
AdfmfJavaUtilities.ApplicationDirectory
-
AdfmfJavaUtilities.DeviceOnlyDirectory
-
AdfmfJavaUtilities.DownloadDirectory
displayFile
メソッドの機能は、デバイスのローカル・ファイルを表示することのみです。つまり、リモート・ファイルは最初にダウンロードする必要があります。ダウンロードしたファイルを保存する必要のあるディレクトリ・ルートに戻るには、AdfmfJavaUtilities.getDirectoryPathRoot
(AdfmfJavaUtilities.
DownloadDirectory
)を使用します。iOSでは、この場所はアプリケーションによって異なりますが、Androidでは、この場所として外部ストレージ・ディレクトリが参照されます。この外部ストレージ・ディレクトリは公的にアクセス可能であるため、サードパーティ・アプリケーションを使用して、そこに格納されているファイルを読み取ることができます。
displayFile
メソッドがファイルを開く例の詳細は、サンプルのMAFアプリケーションで説明されているDeviceDemoサンプル・アプリケーションを参照してください。
表15-7 サポートされるファイル・タイプ
iOS | Android |
---|---|
サポートされるファイル・タイプの詳細は、Apple iOS開発サイト( |
特定のMIMEタイプがデバイスにインストールされている場合、このMAFによって、そのタイプに関連付けられたビューアが起動されます。特定のファイル・タイプを表示するためのフレームワークは組み込まれていません。そのファイル・タイプを開くことができるアプリケーションがデバイスにインストールされていない場合は、MAFアプリケーションによってエラーが表示されます。 |
iWorkドキュメント |
|
Microsoft Officeドキュメント(Office 97以降) |
|
リッチ・テキスト・フォーマット(RTF)ドキュメント |
|
PDFファイル |
|
イメージ |
|
Uniform Type Identifier (UTI)がpublic.text typeに準拠しているテキスト・ファイル |
|
カンマ区切り(csv)ファイル |
DeviceFeaturesデータ・コントロールを使用してdisplayFile操作をカスタマイズするには:
次の例は、displayFile
メソッドを使用してファイルを表示する方法を示しています。displayFile
メソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; URL remoteFileUrl; InputStream is; BufferedOutputStream fos; try { // Open connection to remote file; fileUrl here is a String containing the URL to the remote file. remoteFileUrl = new URL(fileUrl); URLConnection connection = remoteFileUrl.openConnection(); is = new BufferedInputStream(connection.getInputStream()); // Saving the file locally as 'previewTempFile.<extension>' String fileExt = fileUrl.substring(fileUrl.lastIndexOf('.'), fileUrl.length()); String tempFile = "/previewTempFile" + fileExt; File localFile = null; // Save the file in the DownloadDirectory location localFile = new File(AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.DownloadDirectory) + tempFile); if (localFile.exists()) { localFile.delete(); } // Use buffered streams to download the file. fos = new BufferedOutputStream(new FileOutputStream(localFile)); byte[] data = new byte[1024]; int read = 0; while ((read = is.read(data)) != -1) { fos.write(data, 0, read); } is.close(); fos.close(); // displayFile takes a URL string which has to be encoded on iOS. // iOS does not handle "+" as an encoding for space (" ") but // expects "%20" instead. Also, the leading slash MUST NOT be // encoded to "%2F". We will revert it to a slash after the // URLEncoder converts it to "%2F". StringBuffer buffer = new StringBuffer(); String path = URLEncoder.encode(localFile.getPath(), "UTF-8"); // replace "+" with "%20" String replacedString = "+"; String replacement = "%20"; int index = 0, previousIndex = 0; index = path.indexOf(replacedString, index); while (index != -1) { buffer.append(path.substring(previousIndex, index)).append(replacement); previousIndex = index + 1; index = path.indexOf(replacedString, index + replacedString.length()); } buffer.append(path.substring(previousIndex, path.length())); // Revert the leading encoded slash ("%2F") to a literal slash ("/"). if (buffer.indexOf("%2F") == 0) { buffer.replace(0, 3, "/"); } // Create URL and invoke displayFile with its String representation. URL localURL = null; if (Utility.getOSFamily() == Utility.OSFAMILY_ANDROID) { localURL = new URL("file", "localhost", localFile.getAbsolutePath()); } else if (Utility.getOSFamily() == Utility.OSFAMILY_IOS) { localURL = new URL("file", "localhost", buffer.toString()); } DeviceManagerFactory.getDeviceManager().displayFile(localURL.toString(), "remote file"); } catch (Throwable t) { System.out.println("Exception caught: " + t.toString()); }
addLocalNotificationメソッドとcancelLocalNotificationメソッドを使用してローカル通知を管理する方法
DeviceFeaturesデータ・コントロールに含まれるaddLocalNotification
メソッドとcancelLocalNotification
メソッドをMAFアプリケーションで使用すると、通知を管理するためのデバイスのインタフェースを利用できるようになり、ユーザーはローカル通知のスケジュールまたは取消しができるようになります。
DeviceFeaturesデータ・コントロールを使用してaddLocalNotificationまたはcancelLocalNotification操作をカスタマイズするには:
選択した操作のパラメータを構成するために使用する「アクション・バインディングの編集」ダイアログを図に示します。この例では、cancelLocalNotification
操作のnotificationIDがaddLocalNotification
操作の結果にバインドされます。
式ビルダーを使用してaddLocalNotification
操作の結果をcancelLocalNotification
操作にバインドする方法を図に示します。
図15-18 addLocalNotificationの結果へのcancelLocalNotificationのバインド

「図15-18 addLocalNotificationの結果へのcancelLocalNotificationのバインド」の説明
addLocalNotification
およびcancelLocalNotification
メソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControl
クラスに関する項を参照してください。「ローカル通知の管理」を参照してください。「通知の概要」も参照してください。
デバイス・プロパティに関する必知事項
MAFには、アプリケーションでの動的な動作をサポートするために、Java、JavaScriptおよびELからアクセスできるプロパティがあります。プロパティのリストを確認して、問合せ方法、予期される戻り値およびアプリケーション・ライフサイクル期間のプロパティの変化について理解してください。
アプリケーションには、特定のデバイスの特性や機能に依存する機能が含まれる場合があります。たとえば、デバイスの画面の向きによって異なるユーザー・インタフェースを提示したり、デバイスで地理的位置情報がサポートされる場合のみマッピング機能を有効にすることなどが考えられます。MAFでは、このような動的な動作をサポートするために、Java、JavaScriptおよびELからアクセスできる様々なプロパティが用意されています。表15-8に、これらのプロパティをリストし、問合せ方法、予期される戻り値およびアプリケーションのライフサイクル期間にそのプロパティが変化する可能性があるかどうかに関する情報も提供します。この項の最後にある例は、JavaScriptを使用してこれらのプロパティにアクセスする方法を示しています。
注意:
デバイス・プロパティのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。
表15-8 デバイス・プロパティと対応するEL式
プロパティ | 静的/動的 | EL式 | サンプル値 | Java API |
---|---|---|---|---|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
脚注2
wifi
および2G
の両方が有効になっている場合、wifi
が2G
よりも優先されるため、ネットワーク・ステータスはwifi
になります。
次の例は、JavaScriptを使用してデバイス・プロパティにアクセスする方法を示しています。
<!DOCTYPE html> <html> <head> <title>Device Properties Example</title> <script type="text/javascript" charset="utf-8" src="cordova-2.2.0.js"></script> <script type="text/javascript" charset="utf-8"> // Wait for Cordova to load // //document.addEventListener("deviceready", onDeviceReady, false); document.addEventListener("showpagecomplete",onDeviceReady,false); // Cordova is ready // function onDeviceReady() { adf.mf.api.getDeviceProperties(properties_success, properties_fail); } function properties_success(response) { try { var element = document.getElementById('deviceProperties'); var device = response.device; var hardware = response.hardware; element.innerHTML = 'Device Name: ' + device.name + '<br />' + 'Device Platform: ' + device.platform + '<br />' + 'Device Version: ' + device.version + '<br />' + 'Device OS: ' + device.os + '<br />' + 'Device Model: ' + device.model + '<br />' + 'Hardware Screen Width: ' + hardware.screen.width + '<br />' + 'Hardware Screen Height: ' + hardware.screen.height + '<br />' + } catch (e) {alert("Exception: " + e);} } function properties_fail(error) { alert("getDeviceProperties failed"); } </script> </head> <body> <p id="deviceProperties">Loading device properties...</p> </body> </html>
注意:
JavaScript関数をshowpagecomplete
イベントに宣言的にバインドするには、次の例のように、amx:clientListener
タグを<amx:view>
の直接の子として追加します。
<amx:clientListener type="showpagecomplete" method="myShowPageCompleteHandler"/>
クライアント・リスナー(clientListener
)コンポーネントの詳細は、「クライアント・リスナーの使用方法」を参照してください。
属性の検証
MAFでは、検証ルールがバインディング属性に設定され、データ・コントロール・レイヤーで検証が行われます。データ・コントロールによって公開される属性に対するバリデータと、属性の検証メッセージの両方を構成できます。
モバイル・アプリケーション・フレームワークでは、バインディング属性で検証ルールが設定された状態で、データ・コントロール・レイヤーで検証が実行されます。属性の検証は、バインディングに対するsetValue
操作中に、システム内の単一点で実行されます。
データ・コントロールによって公開される属性に対して、次のバリデータを定義できます。
-
比較バリデータ
-
長さバリデータ
-
リスト・バリデータ
-
範囲バリデータ
特定の属性に対してすべてのバリデータが実行され、成功しないすべてのバリデータに対してネストされた例外がスローされます。属性の検証メッセージを定義し、実行時に検証ルールを起動するときに表示できます。「入力の検証」および「検証ルールの追加方法」を参照してください。
注意:
JSONの制限により、BigDecimal
が保持できる値はDouble
の範囲内となり、BigInteger
が保持できる値はLong
の範囲内となります。許可された値よりも大きい数値を使用するには、toString
をBigDecimal
またはBigInteger
でコールし、値をString
としてシリアライズ(解除)します。
表15-9に、長さバリデータでサポートされる検証の組合せをリストします。
表15-9 長さ検証
比較タイプ | バイト | 文字 |
---|---|---|
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
表15-10と表15-11に、範囲バリデータでサポートされる検証の組合せを示します。
表15-10 範囲検証
比較タイプ | バイト | 文字 | 倍精度 | 浮動小数 | 整数 | 長整数 | 短整数 |
---|---|---|---|---|---|---|---|
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
表15-11 範囲検証: math、sqlおよびutilパッケージ
比較タイプ | java.math.BigDecimal | java.math.BigInteger | java.sql.Date | java.sql.Time | java.sql.Timestamp | java.util.Date |
---|---|---|---|---|---|---|
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
表15-12に、リスト・バリデータでサポートされる検証の組合せをリストします。
表15-12 リスト検証
比較タイプ | 文字列 |
---|---|
|
サポート |
|
サポート |
表15-13と表15-14に、比較バリデータでサポートされる検証の組合せを示します。
表15-13 比較検証
比較タイプ | バイト | 文字 | 倍精度 | 浮動小数 | 整数 | 長整数 | 短整数 | 文字列 |
---|---|---|---|---|---|---|---|---|
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポートなし |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポートなし |
|
サポートなし |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポートなし |
|
サポートなし |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポートなし |
|
サポートなし |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポートなし |
表15-14 比較検証: java.math、java.sqlおよびjava.utilパッケージ
比較タイプ | java.math.BigDecimal | java.math.BigInteger | java.sql.Date | java.sql.Time | java.sql.Timestamp | java.util.Date |
---|---|---|---|---|---|---|
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
|
サポート |
サポート |
サポートなし |
サポートなし |
サポートなし |
サポートなし |
検証ルールの追加方法
MAFのユーザーは、検証ルールを定義できます。データ・コントロール構造ファイルの概要エディタにある「属性」ページを使用して、データ・コントロール・オブジェクトに検証ルールを追加する手順を使用してください。
検証ルールは、様々なユース・ケースに合わせて定義できます。宣言的検証ルールをエンティティ・オブジェクトに追加するには、データ・コントロール構造ファイルの「概要」エディタにある「属性」ページを使用します。
検証規則を追加するには:
バリデータのメタデータに関する必知事項
データ・コントロール構造のメタデータXMLファイルには、バリデータのメタデータが格納されています。
バリデータのメタデータは、設計時にデータ・コントロール構造のメタデータXMLファイル内に配置されます。次の例は、サンプルの長さバリデータを示しています。
<?xml version="1.0" encoding="windows-1252" ?> <!DOCTYPE PDefViewObject SYSTEM "jbo_03_01.dtd"> <PDefViewObject xmlns="http://xmlns.oracle.com/bc4j" Name="Product" Version="12.1.1.61.36" xmlns:validation="http://xmlns.oracle.com/adfm/validation"> <DesignTime> <Attr Name="_DCName" Value="DataControls.ProductListBean"/> <Attr Name="_SDName" Value="mobile.Product"/> </DesignTime> <PDefAttribute Name="name"> <validation:LengthValidationBean Name="nameRule0" OnAttribute="name" CompareType="GREATERTHAN" DataType="BYTE" CompareLength="5" Inverse="false"/> </PDefAttribute> </PDefViewObject>
バックグラウンド・スレッドの使用方法
バックグラウンドのJavaスレッドを使用してデータ・モデルの値を更新できますが、更新がユーザー・インタフェースと正しく同期されるように注意する必要があります。
バックグラウンド・スレッドは、データをフェッチする場合(たとえば、リモート・サーバーから)、または複雑なアルゴリズムで値を計算する場合に役立ちます。バックグラウンド・スレッドを使用してフェッチやデータ値は計算できますが、アプリケーションのユーザー・インタフェース・スレッドと競合する可能性があるため、直接それを使用してアプリケーションのデータ・モデル・オブジェクトを更新しないでください。
バックグラウンド・スレッドからモデル・オブジェクトを更新するには、MafExecutorService
APIを使用して、モデルの更新を実行するJavaのRunnable
を発行します。まず、新規または更新されたモデルの値(フェッチ済または計算済)を取得して、次の例に示すようにRunnable
を発行してアプリケーションのデータ・モデル・オブジェクトの値を更新します。
// First, fetch/compute new data values. fetchUpdatedValues(); // Next, use a Runnable to update the model objects. MafExecutorService.execute(new Runnable() { public void run() { doModelUpdates(); AdfmfJavaUtilities.flushDataChangeEvent(); } });
注意:
アプリケーションが無応答にならないよう、発行されるタスクは短時間のものにする必要があります。タスクを実行する前に機能がロックされる可能性があり、このロックはタスクが完了するまでは解放されません。oracle.adfmf.framework.api.MafExecutorService.execute
クラスの詳細はOracle Mobile Application Framework Java APIリファレンスを参照してください。
MAFアプリケーションのバックグラウンド・スレッド処理の許可
iOSまたはAndroidプラットフォームでのバックグラウンド・スレッド処理を許可するには、oracle.adfmf.framework.api.AdfmfContainerUtilities
APIのbeginBackgroundTask
およびendBackgroundTask
メソッドを使用します。
注意:
Windowsはフォアグラウンドでないアプリケーションを一時停止することはないため、Windowsプラットフォームではこの問題は発生しません。実行中のアプリケーションが一時停止されないようにするには、MAFに用意されているoracle.adfmf.framework.api.AdfmfContainerUtilities
Java APIを使用してください。バックグラウンド・タスクとして実行する必要がある操作をラップするには、beginBackgroundTask
メソッドおよびendBackgroundTask
メソッドを使用します。このAPIの詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。
次のコードは、この機能を実装する方法を示しています。
...
public class StartBackgroundTask {
//Start button is enabled.
private boolean buttonStatus = true;
private String buttonString = "Start to download";
private PropertyChangeSupport _propertyChangeSupport = new PropertyChangeSupport(this);
private Object taskId = null;
public StartBackgroundTask() {
}
public void startTask(ActionEvent actionEvent) {
buttonStatus = !buttonStatus;
if (!buttonStatus) {
this.setButtonString("Downloading");
taskId = AdfmfContainerUtilities.beginBackgroundTask("Download task description", null);
ExecutorService cachedThreadPool = ThreadUtil.getInstance().getCachedThreadPool();
cachedThreadPool.submit(() -> {
try {
//Specify the URL for the big file to download
URL url = new URL("http://...");
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = httpConn.getInputStream();
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = inputStream.read(buffer)) != -1) {
;
}
inputStream.close();
}
}
catch(Exception e) {
;
}
AdfmfContainerUtilities.endBackgroundTask(taskId);
taskId = null;
this.setButtonString("Start to download");
buttonStatus = !buttonStatus;
});
}
else {
if(taskId != null) {
AdfmfContainerUtilities.endBackgroundTask(taskId);
taskId = null;
}
this.setButtonString("Start to download");
}
}
public void setButtonString(String buttonString) {
String oldButtonString = this.buttonString;
this.buttonString = buttonString;
_propertyChangeSupport.firePropertyChange("buttonString", oldButtonString, buttonString);
}
public String getButtonString() {
return buttonString;
}
}
データ変更イベントの使用
JDeveloperでは、データ変更イベントを単純化するために、プロパティ変更リスナー・パターンを使用します。多くの場合、JDeveloperを使用して、Beanのプロパティ・アクセサからの通知を参照するために必要なソース・コードを生成できます。これを行うには、「アクセサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェックボックスを選択します
PropertyChangeSupport
オブジェクトが自動的に生成され、新たに生成されたsetterメソッドにfirePropertyChange
へのコールが含まれます。また、addPropertyChangeListener
およびremovePropertyChangeListener
メソッドが追加されるため、プロパティ変更リスナーは、このオブジェクトを使用して自身を登録および登録解除できます。これを使用してフレームワークはクライアント・キャッシュにプッシュする変更を取得し、データが変更されたことをユーザー・インタフェース・レイヤーに通知します。
注意:
PropertyChangeSupport
オブジェクトを手動でクラスに追加する場合は、addPropertyChangeListener
およびremovePropertyChangeListener
メソッドも(これらの明示的なメソッド名を使用して)含める必要があります。
プロパティ変更のみでは、すべてのデータ変更通知は解決されません。たとえば、データ・コントロールによってラップされたBeanがあり、アイテムのコレクションの公開が必要な場合が考えられます。リストの個々のアイテムが変更されたときはプロパティ変更で十分ですが、カーディナリティが変更されたときは十分ではありません。この場合、コレクション全体のプロパティ変更を起動すると、パフォーマンスが低下する可能性があるため、かわりにコレクションのデルタのみを更新します。これを行うには、ProviderChangeSupport
クラスを使用して、単純なプロパティ変更に必要なデータよりも多くのデータを公開する必要があります。プロバイダ変更イベントはプロパティ変更イベントと似ていますが、個別のプロパティのみを対象とするのではなく、プロバイダ全体に適用されます。
注意:
ProviderChangeSupport
オブジェクトは、自動的には生成されません。このオブジェクトはaddProviderChangeListener
、removeProviderChangeListener
およびgetKey()
メソッドとともに、(これらの明示的なメソッド名を使用して)手動でクラスに追加する必要があります。getKey()
メソッドは、プロバイダに対して一意の値を生成する文字列を返す必要があります。getKey()
メソッドをクラスに追加するかわりに、図に示す概要エディタを使用して、データ・コントロール構造ファイルのキー属性として、データ・コントロールで属性を指定します
プロバイダ変更は、データ・コントロールによってラップされたBeanで公開されている動的なコレクションを保持しているときのみ必要になるため、起動するプロバイダ変更イベントは、次のいくつかのタイプのみになります。
-
fireProviderCreate
: 新しい要素をコレクションに追加する場合 -
fireProviderDelete
: 要素をコレクションから削除する場合 -
fireProviderChange
: コレクション内の1つの要素を変更する場合(リスト全体のリフレッシュを回避するのに必要です) -
fireProviderRefresh
: 同時に複数の変更をコレクションに加え、単純にクライアントにコレクション全体のリフレッシュを要求した方がよいと判断した場合(これは一括操作でのみ使用する必要があります)
ProviderChangeSupport
クラスは、コレクション要素に関連する通知を送信するために使用され、これによって、Java Beanデータ・コントロール内で変更が発生したときにコンポーネントを適切に更新できます。このクラスが従うパターンは、自動的に生成されるPropertyChangeSupport
クラスと似ていますが、ProviderChangeSupport
とともに使用されるイベント・オブジェクトでは、操作のタイプや変更された要素のキーと位置などの詳細情報を送信します。ProviderChangeSupport
では、コレクションに対する要素(プロバイダ)の追加や削除など、コレクションに対する構造的な変更を取得します。PropertyChangeSupport
では、コレクション内の個々のアイテムに対する変更を取得します。
次の例は、ProviderChangeSupport
を使用して、コレクションの要素に対する構造的な変更(子を追加または削除する場合など)に関する通知を送信する方法を示しています。ProviderChangeListener
インタフェースおよびProviderChangeEvent
とProviderChangeSupport
クラスの詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。
public class NotePad { private static List s_notes = null; /* manually adding property change listener as well as provider change listener. */ protected transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); protected transient ProviderChangeSupport providerChangeSupport = new ProviderChangeSupport(this); public NotePad() { … } public mobile.Note[] getNotes() { mobile.Note n[] = null; synchronized (this) { if(s_notes.size() > 0) { n = (mobile.Note[]) s_notes.toArray(new mobile.Note[s_notes.size()]); } else { n = new mobile.Note[0]; } } return n; } public void addNote() { System.out.println("Adding a note ...."); Note n = new Note(); int s = 0; synchronized (this) { s_notes.add(n); s = s_notes.size(); } System.out.println("firing the events"); providerChangeSupport.fireProviderCreate("notes", n.getUid(), n); } public void removeNote() { System.out.println("Removng a note ...."); if(s_notes.size() > 0) { int end = -1; Note n = null; synchronized (this) { end = s_notes.size() - 1; n = (Note)s_notes.remove(end); } System.out.println("firing the events"); providerChangeSupport.fireProviderDelete("notes", n.getUid()); } } public void RefreshNotes() { System.out.println("Refreshing the notes ...."); providerChangeSupport.fireProviderRefresh("notes"); } public void addProviderChangeListener(ProviderChangeListener l) { providerChangeSupport.addProviderChangeListener(l); } public void removeProviderChangeListener(ProviderChangeListener l) { providerChangeSupport.removeProviderChangeListener(l); } protected String status; /* --- JDeveloper generated accessors --- */ public void addPropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.removePropertyChangeListener(l); } public void setStatus(String status) { String oldStatus = this.status; this.status = status; propertyChangeSupport.firePropertyChange("status", oldStatus, status); } public String getStatus() { return status; } }
データ変更は、JVMレイヤーからのレスポンス・メッセージや戻り値とともに、クライアントに(キャッシュするために)戻されます。これにより、JDeveloperではユーザー・インタフェースに対してリフレッシュするイベントと更新の数を縮小し、可能なかぎりフレームワークの効率を上げることができます。
ただし、バックグラウンド・スレッドで実行時間の長い処理(Webサービスの相互作用、データベースの相互作用、コストのかかる計算など)に対処し、ユーザー・アクションに依存しないユーザー・インタフェースへの通知を行うことが必要になる場合もあります。AMXページのデータを更新して、値が変更されたデータ・フィールドの現在の値を反映させる場合、AdfmfJavaUtilities.flushDataChangeEvent
をコールして現在キューに入っているデータ変更をクライアントに強制することによって、AMXページ全体のリロードによるパフォーマンスの低下を回避できます。
注意:
flushDataChangeEvent
メソッドは、バックグラウンド・スレッドからのみ実行できます。
次の例は、flushDataChangeEvent
メソッドを使用してクライアントへの保留中のデータ変更を強制する方法を示しています。oracle.adfmf.framework.api.AdfmfJavaUtilities.flushDataChangeEvent
に関する詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。
/* Note – Simple POJO used by the NotePad managed bean or data control wrapped bean */
package mobile;
import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;
/**
* Simple note object
* uid - unique id - generated and not mutable
* title - title for the note - mutable
* note - note comment - mutable
*/
public class Note {
/* standard JDeveloper generated property change support */
protected transient PropertyChangeSupport
propertyChangeSupport = new PropertyChangeSupport(this);
private static boolean s_backgroundFlushTestRunning = false;
public Note() {
this("" + (System.currentTimeMillis() % 10000));
}
public Note(String id) {
this("UID-"+id, "Title-"+id, "");
}
public Note(String uid, String title, String note) {
this.uid = uid;
this.title = title;
this.note = note;
}
/* update the current note with the values passed in */
public void updateNote(Note n) {
if (this.getUid().compareTo(n.getUid()) == 0) {
this.setTitle(n.getTitle());
this.setNote(n.getNote());
}
else {
throw new IllegalArgumentException("note");
}
}
/* background thread to simulate some background process that make changes */
public void startNodeBackgroundThread(ActionEvent actionEvent) {
Thread backgroundThread = new Thread() {
public void run() {
System.out.println("startBackgroundThread enter - " +
s_backgroundFlushTestRunning);
s_backgroundFlushTestRunning = true;
for(int i = 0; i <= iterations; ++i) {
try {
System.out.println("executing " + i + " of " + iterations + "
" iterations.");
/* update a property value */
if(i == 0) {
setNote("thread starting");
}
else if( i == iterations) {
setNote("thread complete");
s_backgroundFlushTestRunning = false;
}
else {
setNote("executing " + i + " of " + iterations + " iterations.");
}
setVersion(getVersion() + 1);
setTitle("Thread Test v" + getVersion());
AdfmfJavaUtilities.flushDataChangeEvent(); /* key line */
}
catch(Throwable t) {
System.err.println("Error in the background thread: " + t);
}
try {
Thread.sleep(delay); /* sleep for 6 seconds */
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
backgroundThread.start();
}
protected String uid;
protected String title;
protected String note;
protected int version;
protected int iterations = 10;
protected int delay = 500;
/* --- JDeveloper generated accessors --- */
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
public String getUid() {
return uid;
}
public void setTitle(String title) {
String oldTitle = this.title;
this.title = title;
propertyChangeSupport.firePropertyChange("title", oldTitle, title);
}
public String getTitle() {
return title;
}
public void setNote(String note) {
String oldNote = this.note;
this.note = note;
propertyChangeSupport.firePropertyChange("note", oldNote, note);
}
public String getNote() {
return note;
}
public void setVersion(int version) {
int oldVersion = this.version;
this.version = version;
propertyChangeSupport.firePropertyChange("version", oldVersion, version);
}
public int getVersion() {
return version;
}
public void setIterations(int iterations) {
int oldIterations = this.iterations;
this.iterations = iterations;
propertyChangeSupport.
firePropertyChange("iterations", oldIterations, iterations);
}
public int getIterations() {
return iterations;
}
public void setDelay(int delay) {
int oldDelay = this.delay;
this.delay = delay;
propertyChangeSupport.
firePropertyChange("delay", oldDelay, delay);
}
public int getDelay() {
return delay;
}
}
/* NotePad – Can be used as a managed bean or wrapped as a data control */
package mobile;
import java.util.ArrayList;
import java.util.List;
import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;
import oracle.adfmf.java.beans.ProviderChangeListener;
import oracle.adfmf.java.beans.ProviderChangeSupport;
public class NotePad {
private static List s_notes = null;
private static boolean s_backgroundFlushTestRunning = false;
protected transient PropertyChangeSupport propertyChangeSupport =
new PropertyChangeSupport(this);
protected transient ProviderChangeSupport
providerChangeSupport = new ProviderChangeSupport(this);
public NotePad() {
if (s_notes == null) {
s_notes = new ArrayList();
for(int i = 1000; i < 1003; ++i) {
s_notes.add(new Note(""+i));
}
}
}
public mobile.Note[] getNotes() {
mobile.Note n[] = null;
synchronized (this) {
if(s_notes.size() > 0) {
n = (mobile.Note[])s_notes.
toArray(new mobile.Note[s_notes.size()]);
}
else {
n = new mobile.Note[0];
}
}
return n;
}
public void addNote() {
System.out.println("Adding a note ....");
Note n = new Note();
int s = 0;
synchronized (this) {
s_notes.add(n);
s = s_notes.size();
}
System.out.println("firing the events");
/* update the note count property on the screen */
propertyChangeSupport.
firePropertyChange("noteCount", s-1, s);
/* update the notes collection model with the new note */
providerChangeSupport.
fireProviderCreate("notes", n.getUid(), n);
/* to update the client side model layer */
AdfmfJavaUtilities.flushDataChangeEvent();
}
public void removeNote() {
System.out.println("Removing a note ....");
if(s_notes.size() > 0) {
int end = -1;
Note n = null;
synchronized (this) {
end = s_notes.size() - 1;
n = (Note)s_notes.remove(end);
}
System.out.println("firing the events");
/* update the client side model layer */
providerChangeSupport.fireProviderDelete("notes", n.getUid());
/* update the note count property on the screen */
propertyChangeSupport.firePropertyChange("noteCount", -1, end);
}
}
public void RefreshNotes() {
System.out.println("Refreshing the notes ....");
/* update the entire notes collection on the client */
providerChangeSupport.fireProviderRefresh("notes");
}
public int getNoteCount() {
int size = 0;
synchronized (this) {
size = s_notes.size();
}
return size;
}
public void addProviderChangeListener(ProviderChangeListener l) {
providerChangeSupport.addProviderChangeListener(l);
}
public void removeProviderChangeListener(ProviderChangeListener l) {
providerChangeSupport.removeProviderChangeListener(l);
}
public void startListBackgroundThread(ActionEvent actionEvent) {
for(int i = 0; i < 10; ++i) {
_startListBackgroundThread(actionEvent);
try {
Thread.currentThread().sleep(i * 1234);
}
catch (InterruptedException e) {
}
}
}
public void
_startListBackgroundThread(ActionEvent actionEvent) {
Thread backgroundThread = new Thread() {
public void run() {
s_backgroundFlushTestRunning = true;
for(int i = 0; i <= iterations; ++i) {
System.out.println("executing " + i +
" of " + iterations + " iterations.");
try {
/* update a property value */
if(i == 0) {
setStatus("thread starting");
addNote(); // add a note
}
else if( i == iterations) {
setStatus("thread complete");
removeNote(); // remove a note
s_backgroundFlushTestRunning = false;
}
else {
setStatus("executing " + i + " of " +
iterations + " iterations.");
synchronized (this) {
if(s_notes.size() > 0) {
Note n =(Note)s_notes.get(0);
n.setTitle("Updated-" +
n.getUid() + " v" + i);
}
}
}
AdfmfJavaUtilities.flushDataChangeEvent();
}
catch(Throwable t) {
System.err.
println("Error in bg thread - " + t);
}
try {
Thread.sleep(delay);
}
catch (InterruptedException ex) {
setStatus("inturrpted " + ex);
ex.printStackTrace();
}
}
}
};
backgroundThread.start();
}
protected int iterations = 100;
protected int delay = 750;
protected String status;
/* --- JDeveloper generated accessors --- */
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
public void setStatus(String status) {
String oldStatus = this.status;
this.status = status;
propertyChangeSupport.firePropertyChange("status", oldStatus, status);
}
public String getStatus() {
return status;
}
public void setIterations(int iterations) {
int oldIterations = this.iterations;
this.iterations = iterations;
propertyChangeSupport.firePropertyChange("iterations", oldIterations, iterations);
}
public int getIterations() {
return iterations;
}
public void setDelay(int delay) {
int oldDelay = this.delay;
this.delay = delay;
propertyChangeSupport.firePropertyChange("delay", oldDelay, delay);
}
public int getDelay() {
return delay;
}
}
StockTrackerサンプル・アプリケーションでは、データ変更イベントでJavaを使用してデータ変更をユーザー・インタフェースに反映する方法の例を示します。このサンプル・アプリケーションおよびその他のサンプル・アプリケーションの詳細は、「サンプルのMAFアプリケーション」を参照してください。