| Oracle® Mobile Application Framework Oracle Mobile Application Frameworkでのモバイル・アプリケーションの開発 2.3.2 E79300-01 |
|
![]() 前 |
![]() 次 |
この章の内容は次のとおりです。
モバイル・アプリケーション・フレームワークによって、ユーザー・インタフェース(UI)・テクノロジとビジネス・サービス実装の分離を可能にする2つの概念(データ・コントロールと宣言的バインディング)が実装されています。データ・コントロールでは、関連するプロパティ、メソッド、タイプの情報を含め、サービスの操作とデータ・コレクションを表す標準のメタデータ・インタフェースを使用してビジネス・サービスの実装技術を抽象化します。JDeveloperを使用すると、その情報をアイコンとして表示し、ページ上にドラッグ・アンド・ドロップできます。宣言的なバインディングによって、データ・コントロール内のデータ・コレクションからのデータ・アクセスとその操作の実行の詳細が抽象化されます。実行時に、モデル・レイヤーによって、適切なXMLファイルからデータ・コントロールおよびバインディングを記述した情報が読み取られ、ユーザー・インタフェースとビジネス・サービスの双方向の結合が実装されます。
ページのユーザー・インタフェース・コンポーネントをサポートするバインディングのグループは、ページ定義ファイルというページ固有のXMLファイルに記述されます。モデル・レイヤーでは実行時にこのファイルが使用され、ページのバインディングがインスタンス化されます。これらのバインディングは、バインディング・コンテナと呼ばれるリクエスト・スコープ・マップに保持され、EL式#{bindings}を使用して各ページ・リクエスト中にアクセスできます。この式により、現在のページのバインディング・コンテナが常に評価されます。「データ・コントロール」パネルから項目をドラッグし、それを特定のUIコンポーネントとしてページ上にドロップすることで、データバインドされたユーザー・インタフェースを設計できます。データ・コントロールを使用してUIコンポーネントを作成すると、そのコンポーネントを選択したデータ・コントロールにバインドするために必要なコードおよびオブジェクトがJDeveloperによって自動的に作成されます。
モバイル・アプリケーション・フレームワークには、即時利用可能な2つのデータ・コントロール(DeviceFeaturesデータ・コントロールとApplicationFeaturesデータ・コントロール)が付属しています。JDeveloperの「データ・コントロール」パネル内に表示されるDeviceFeaturesデータ・コントロールを使用すると、データ・コントロールの主なデータ属性を(テキスト)フィールドとして、またデータ・コントロールの操作をコマンド・オブジェクト(ボタン)として、アプリケーションにドラッグ・アンド・ドロップできます。これらのドラッグ・アンド・ドロップ・アクションによって、アプリケーション内のELバインディングおよび作成されるコントロールに適したプロパティが生成されます。バインディングは、データ・コントロール・ソースを指すために、DataControls.dcxファイルによって表され、ページ・バインディングによって、特定のページの参照がデータ・コントロールにリンクされます。ApplicationFeaturesデータ・コントロールの詳細は、「MAF AMXコンテンツによるカスタムSpringboardアプリケーション機能に関する必知事項」を参照してください。
データ・コントロールおよびバインディングの詳細は、次を参照してください。
実行時、ページがデータにアクセスできるオブジェクト・スコープに必要なデータを格納することで、データをページに渡します。スコープによってオブジェクトの存続期間が決まります。オブジェクトをスコープに置くと、EL式を使用してスコープからアクセスできます。たとえば、fooという名前のマネージドBeanを作成し、Beanをビュー・スコープに存続させるよう定義するとします。このBeanにアクセスするには、#{viewScope.foo}という式を使用します。
モバイル・アプリケーション・フレームワーク変数とマネージドBean参照は、変数の存続期間と可視性を決定する様々なオブジェクト・スコープ内で定義されます。MAFは、次のスコープ(可視性が高い順に表示)をサポートしています。
アプリケーション・スコープ: オブジェクトは、アプリケーションが存続するかぎり(複数の機能にまたがって)使用可能です。
ページ・フロー・スコープ: オブジェクトは、ページ・フロー・スコープのマネージドBeanがどこに定義されているかによって、機能(単一の機能の境界)またはタスク・フローが存続するかぎり使用できます。Beanがバインドなしタスク・フローに定義されている場合、そのスコープは機能です。Beanがバインド・タスク・フローに定義されている場合、そのスコープはタスク・フローに限定されます。
ビュー・スコープ: オブジェクトは、ビューが存続するかぎり(機能の単一ページ内で)使用可能です。
オブジェクト・スコープは、プログラミング言語のグローバル変数およびローカル変数のスコープに相当します。スコープが広いほど、オブジェクトの可用性が高くなります。存続期間の間、これらのオブジェクトで特定のインタフェースの公開、情報の保持および他のオブジェクトへの変数とパラメータの受渡しを行うことができます。たとえば、アプリケーション・スコープに定義されているマネージドBeanは、アプリケーションが存続するかぎり、複数のページ・リクエストの間使用できます。ただし、ビュー・スコープに定義されているマネージドBeanは、1つの機能で1つのページ・リクエストの間のみ使用できます。
アプリケーション・スコープの名前空間で定義されたEL式は、アプリケーションが存続するかぎり、複数の機能にまたがって使用できます。アプリケーションの一方のビューでアプリケーション・スコープを定義し、そのスコープをもう一方のビューで参照できます。ページ・フロー・スコープの名前空間で定義されたEL式は、機能が存続するかぎり、単一の機能の境界内で使用できます。ビュー・スコープの名前空間で定義されたEL式は、ビューが存続するかぎり、機能の単一ページの境界内で使用できます。スコープを含むこのような変数に加えて、MAFでは、デバイス・プロパティとアプリケーション・プリファレンスに関する情報を公開できるスコープが定義されています。これらのスコープによって、アプリケーション・レベルの存続期間と可視性が決まります。詳細は、「マネージドBeanカテゴリについて」および「モバイル・アプリケーション・フレームワーク・オブジェクト・カテゴリについて」を参照してください。
マネージドBeanを登録するスコープまたは値を格納するスコープを決める場合、可能なかぎり狭いスコープを常に使用するようにします。アプリケーション・スコープは、ユーザー情報やコンテキスト情報などのアプリケーション全体に関係する情報にのみ使用します。アプリケーション・スコープは、ページ間での値の受渡しには使用しないでください。
注意:
メモリー・スコープに配置するすべてのオブジェクトは、JSON DataChangeEventにシリアライズされ、このオブジェクト内のgetterメソッドによって返されるオブジェクトもシリアライズされます。これは、ネストが深いシリアライズされたオブジェクト・ツリーにつながることがあり、パフォーマンスが低下します。一連のネストされたオブジェクトのシリアライズを避けるには、それらを一時オブジェクトとして定義する必要があります。詳細は、「Beanクラス変数のシリアライズに関する必知事項」を参照してください。
タスク・フロー内の変数にどのスコープを使用するかを決定するときは、ビュー・スコープまたはページ・フロー・スコープのみを使用する必要があります。アプリケーション・スコープは、タスク・フローの存続期間を超えてオブジェクトをメモリーに保存するため、タスク・フローのカプセル化および再利用で障害が発生します。さらに、アプリケーション・スコープでは、オブジェクトがメモリーに必要以上に長い時間保持されるため、不要なオーバーヘッドが発生します。
タスク・フロー内のアクティビティ間でデータ値を渡す必要がある場合は、ページ・フロー・スコープを使用する必要があります。現在のビュー・アクティビティ内でのみ必要とされ、ビュー・アクティビティ間にまたがっていない変数の場合、ビュー・スコープを使用する必要があります。
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の作成と使用の詳細は、「マネージド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;
}
「データ・コントロール」パネルを使用してコンポーネントを作成すると、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バインディング・プロパティに関する必知事項」を参照してください。
JDeveloperの式ビルダーを使用してEL式を宣言的に作成できます。「プロパティ」ウィンドウから「式ビルダー」にアクセスできます。
始める前に:
EL式に関する知識が役立つ場合があります。詳細は、「EL式の作成」を参照してください。
式ビルダーの使用手順:
表16-2は、「プロパティ」ウィンドウで「式ビルダー」オプションではなく「メソッド式ビルダー」オプションが提供されるプロパティを示しています。これらの唯一の違いは、メソッド式ビルダーが、選択されたプロパティに応じてマネージドBeanをフィルタして除外することです。
表16-2 メソッド式ビルダーのプロパティ
| プロパティ | 要素 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
表16-3は、ELに対応していないため「プロパティ」ウィンドウでEL式ビルダー・オプションが提供されないプロパティを示しています。
表16-3 非ELプロパティ
| プロパティ | 要素 |
|---|---|
|
すべての要素 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
式ビルダーを使用してデータバインド・コンポーネントを作成すると、EL式によって、特定のMAFバインディング・プロパティが参照される場合があります。実行時には、これらのバインディング・プロパティによって、データバインドUIコンポーネントのデフォルトの表示方法や、イテレータ・バインディング固有のパラメータなどが定義されます。バインディング・プロパティは、Oracle APIによって定義されます。各バインディング・タイプで使用可能なプロパティの完全なリストは、表16-4を参照してください
特定のプロパティに割り当てられる値は、ページ定義ファイルで定義されます。たとえば、イテレータ・バインディングには、イテレータが一度に表示する行数を指定する、RangeSizeというプロパティがあります。RangeSizeに割り当てられた値は、次の例に示すようにページ定義ファイルで指定されます。
<iterator Binds="ItemsForOrder" RangeSize="25"
DataControl="BackOfficeAppModuleDataControl"
id="ItemsForOrderIterator" ChangeEventPolicy="ppr"/>
同じデータ・コントロールに対してデータ・プロバイダの複数のインスタンスを作成できます。特定のイテレータで使用するデータ・プロバイダ・インスタンスを定義します。デフォルトのデータ・プロバイダ・インスタンスと同様に、新規データ・プロバイダ・インスタンスはデータ・コントロールのスコープに対して存在します。これにより、ページのメイン・リストをフィルタすると同時にフィルタされていないリストを含む別のコレクションを持つなどの操作を実行できます。
この機能を使用するには、同じデータ・コレクション・インスタンスにアクセスする各ページの最上位レベル・イテレータ(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" />
ルートEL式#{bindings}で、アクティブな画面のバインディング・コンテナを参照できます。式#{data.PageDefName}で、別の画面のバインディング・コンテナを参照できます。MAF AMXバインディング・オブジェクトは、バインディング・コンテナ#{bindings.Name}から名前で参照されます。
表16-4は、実行時に、EL式でMAF AMXバインディング・オブジェクトの値にアクセスするために使用できるプロパティのリストの一部を示しています。プロパティは、アルファベット順に並んでいます。
表16-4 MAFバインディングのランタイムELプロパティ
| 実行時プロパティ | 説明 | イテレータ | アクション | 属性値 | ツリー |
|---|---|---|---|---|---|
|
実行時バインディング用のJavaクラス・オブジェクトを戻します。 |
はい |
はい |
はい |
はい |
|
データのコレクションを公開します。 |
いいえ |
いいえ |
いいえ |
はい |
|
このバインディングのイテレータ内で、選択した行を現在の行にします。 |
いいえ |
いいえ |
いいえ |
はい |
|
選択した行への参照を戻します。 |
いいえ |
いいえ |
いいえ |
はい |
|
イテレータが指している現在の行またはデータ・オブジェクト(組込みナビゲーション・アクションなど)への参照を戻します。 |
はい |
いいえ |
いいえ |
いいえ |
|
イテレータが指している現在の行またはデータ・オブジェクトへの参照を戻します。(これは |
はい |
いいえ |
いいえ |
いいえ |
|
アクション・バインディングの状態に応じて、 |
いいえ |
はい |
いいえ |
いいえ |
|
解決されたときに、名前付きアクションまたは |
いいえ |
はい |
いいえ |
いいえ |
|
これは |
いいえ |
いいえ |
はい |
はい |
|
バインディングが関連付けられているすべての表示属性について、UIヒントの名前/値ペアのリストを戻します。 |
いいえ |
いいえ |
はい |
はい |
|
バインディングが関連付けられている最初の属性の値を戻します。 |
いいえ |
いいえ |
はい |
いいえ |
|
現在のリストの有効な属性に関連付けられた値のリストを戻します。 |
いいえ |
いいえ |
はい |
いいえ |
|
|
いいえ |
いいえ |
はい |
はい |
|
|
はい |
はい |
はい |
はい |
|
イテレータ・バインディングの行セットの範囲サイズを戻します。これにより、データソースからバインドされるデータ・オブジェクトの数を確認できます。 |
はい |
いいえ |
いいえ |
はい |
|
メソッド・アクション・バインディングによりバインドおよび起動されるメソッドの結果を戻します。 |
いいえ |
はい |
いいえ |
いいえ |
|
|
いいえ |
いいえ |
はい |
はい |
|
|
いいえ |
いいえ |
いいえ |
はい |
脚注1
EL語句のrowは、コレクション・コンポーネントのコンテキスト内で使用されます。rowは単に、コレクションをレンダリングするときに、MAF AMXバインディング・オブジェクトからアクセスできる属性を含むコレクションの各要素に対する反復変数として機能します。属性とリスト・バインディングには、row変数を使用してアクセスできます。そのような式の構文は、コレクションに含まれないバインディング・オブジェクトへのアクセスに使用される構文と同じで、#{row.bindings.Name.property}のようにrow変数を先頭の語句として追加します。
MAF AMXページの式ビルダーでは、次のカテゴリを使用できます。
この項では、バインディング・カテゴリで使用できるオプションを示します。bindingsノードとdataノードは、同じ一連のサポートされているバインディングとプロパティを表示します。表16-5に、使用できるバインディング・タイプと、各バインディング・タイプでサポートされるプロパティをリストします。securityContextノードは次のプロパティをサポートしています。
authenticated
userGrantedPrivilege
userInRole
userName
次に例を示します。
#{securityContext.authenticated}#{securityContext.userGrantedPrivilege['submit_privilege']}#{securityContext.userInRole[‘manager_role']}#{securityContext.userName}
表16-5 サポートされるバインディング・タイプ
| バインディング・タイプ | プロパティ |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
この項では、「マネージドBean」カテゴリで使用できるオプションを表示します。
applicationScope: 「マネージドBean」のapplicationScopeノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーション・スコープのマネージドBeanなど)。
pageFlowScope: 「マネージドBean」のpageFlowScopeノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロー・スコープのマネージドBeanなど)。
viewScope: 「マネージドBean」のviewScopeノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュー・スコープのマネージドBeanなど)。
MAFランタイムでは、自身をマネージドBeanプロパティの変更通知のリスナーとして登録することによって、Beanプロパティを参照するUIコンポーネントにバインドされたEL式が、プロパティの値が変更されたときに自動的に更新されるようにします。これらの通知をソースとして参照するには、Beanのプロパティ・アクセッサにコードを追加する必要があります。Beanのプロパティ・アクセッサから、通知をソースとして参照するために必要なコードを自動的に生成するには、「アクセッサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェック・ボックスを選択します(図16-2を参照)。
図16-2 プロパティの変更時にリスナーに通知

ELを通じて単にBeanメソッドまたはプロパティを参照する場合、このコードを追加する必要はありませんが、Beanに格納された値が変化する場合や、特にその変更が、1つ以上のプロパティ値を変更するBeanメソッドの実行による二次的な影響など、間接的なものである場合、それらの値に依存するEL式のアクティブ・フォームへのレンダリングを最新の状態に保つ必要があります。プロパティの変更とPropertyChangeSupportクラスについては、「データ変更イベントについて」を参照してください。
次の例は、プログラムで別のマネージドBean属性にバインドされた値を取得する方法を示しています。
public void someMethod() { Object value = AdfmfJavaUtilities.evaluateELExpression( "#{applicationScope.MyManagedBean.someProperty}"); ... }
次の例は、プログラムでマネージドBeanからバインディングを実行する方法を示しています。
public void someMethod() { Object value = AdfmfJavaUtilities.evaluateELExpression( "#{bindings.someDataControlMethod.execute}"); ... }
注意:
機能のapplicationScope内でマネージドBeanを宣言し、デザインタイムで別の機能のELを通じてそのBeanを参照しようとすると、そのデザインタイムで無効なELに関する警告が表示されます。この警告は、デザインタイムがそのBeanの現在のプロジェクトで参照を検出できないことが原因で表示されます。そのBeanを実行時に参照できるのは、Beanが宣言されている最初の機能に初めてアクセスし、さらに別の機能のELを通じてアクセスする前にそのBeanをインスタンス化した場合のみです。これは、Name属性の値をノード・ラベルとして使用するPreferenceValue要素には当てはまりません。
「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリには、オブジェクト・スコープなどの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属性の値です。
注意:
AdfmfJavaUtilities.evaluateELExpressionを使用して#{row}またはrowのプロパティを評価することはできません。これらの式はnull値を戻します。
viewControllerBundle
これは、プロジェクト・レベルで定義されているリソース・バンドルを指すリソース・バンドル変数の名前です。このノードは、amx:loadBundle要素がドロップされ、リソース・バンドルが作成された後にのみ表示されます。このノードの名前は、amx:loadBundleの変数名によって異なります。このノードには、バンドル内で宣言されたすべての文字列が表示されます。
次の例は、viewControllerBundleのAMXコードの例を示しています。
<amx:loadBundle basename="mobile.ViewControllerBundle" var="viewcontrollerBundle"/>
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式は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は、様々な構成ファイルを使用してアプリケーションに登録する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}という式になります。
adfc-mobile-config.xmlファイルに「概要」エディタを使用して、マネージドBeanの作成とMAFアプリケーションへの登録を同時に行うことができます。
始める前に:
マネージドBeanに関する知識が役立つ場合があります。詳細は、「マネージドBeanの作成と使用」を参照してください。
マネージドBeanの作成および登録手順:
マネージド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>
アプリケーションのサービスの準備ができたら、JDeveloperを使用して、UIコンポーネントとサービスとの宣言的バインドに必要な情報を提供するデータ・コントロールを作成できます。
データ・コントロールの生成には、「データ・コントロールの作成」メニュー・アイテムを使用します。データ・コントロールは、1つ以上のXMLメタデータ・ファイルで構成され、これらのファイルでは、実行時にバインディングと連動するサービスの機能が定義されます。データ・コントロールは、基礎となるサービスと連動します。
アダプタ・ベースのデータ・コントロールは、JDeveloperの「アプリケーション」ウィンドウ内で作成します。
始める前に:
データ・コントロール使用の一般的な知識があると役立ちます。詳細は、「データ・コントロールを使用したビジネス・サービスの公開」を参照してください。
次のタスクを完了する必要があります。
データ・コントロールを作成する手順は、次のとおりです。
注意:
場合によっては、データ・コントロールの基礎にするクラスまたはオブジェクトを右クリックし、「データ・コントロールの作成」を選択することによってデータ・コントロールを作成できます。
データ・コントロールを作成する際に、JDeveloperによってデータ・コントロール定義ファイル(DataControls.dcx)が作成され、概要エディタでファイルが開き、ファイルの階層が「データ・コントロール」パネルに表示されます。このファイルにより、データ・コントロールがサービスおよびバインディングと直接連動して動作することが可能になります。
エディタ・ウィンドウの「ソース」タブをクリックすることによって、対応するXMLファイルからのコードを表示できます。
DataControls.dcxファイルの概要エディタは、データ・コントロール・オブジェクトの階層と、データ・モデルの公開メソッドを表示します。
概要エディタおよび「データ・コントロール」パネルで使用されるアイコンの説明は、表16-6を参照してください。
データ・コントロール・オブジェクトの設定を変更するには、オブジェクトを選択し、「編集」アイコンをクリックします。データ・コントロールの編集方法の詳細は、「データ・コントロールの編集方法」を参照してください。
図16-4は、概要エディタでのDataControls.dcxファイルを示しています。
図16-4 概要エディタでのDataControls.dcxファイル

「データ・コントロール」パネルはパレットとして機能し、ノードを「データ・コントロール」パネルからページのデザイン・エディタにドラッグすることにより、データバインドされたUIコンポーネントを作成できます。データ・コントロールを作成した後、「データ・コントロール」パネルが「アプリケーション」ウィンドウに表示されます。図16-5は、サンプル・アプリケーションの「データ・コントロール」パネルを示しています。
図16-5 「データ・コントロール」パネル

データ・コントロール・フレームワークは、データ・コントロールの標準操作のセットを定義します。これらの操作は、基礎となるビジネス・サービスの機能を使用して実装されます。実行時に、これらのデータ・コレクション操作の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: パラメータとして渡された主キーの属性値を使用して行の検索を試行します。検出されると、その行が現在の行になります。
組込み操作のほとんどは、コレクションに対して自動的に実行されます。操作の中には、実行するために、開発者がメソッド・ハンドラを作成する必要があるものがあります。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によって自動的に作成されます。
「データ・コントロール」パネルでは、各データ・コントロール・オブジェクトが特定のアイコンで表されます。表16-6は、各アイコンが表すデータ・コントロール・オブジェクト、「データ・コントロール」パネルの階層内で表示される場所、そのアイコンを使用して作成できるコンポーネントを示しています。
表16-6 「データ・コントロール」パネルのアイコンおよびオブジェクト階層
| アイコン | 名前 | 説明 | 作成できるコンポーネント |
|---|---|---|---|
![]() |
データ・コントロール |
データ・コントロールを表します。 |
他のオブジェクトのコンテナとして機能し、作成には使用されません。 |
![]() |
コレクション |
アクセッサ・メソッドまたは操作から返される名前付きデータ・コレクションを表します。 |
フォーム、表、グラフ、ツリー、レンジ・ナビゲーションの各コンポーネント、マスター/ディテール・コンポーネントおよび選択リストの各コンポーネント。 |
![]() |
構造化された属性 |
Javaプリミティブ・タイプ(属性として示される)または任意のタイプのコレクションのいずれでもない、戻りオブジェクトを示します。 |
フォーム、ラベル、テキスト・フィールド、日付、値リストおよび選択リストの各コンポーネント。 |
![]() |
属性 |
オブジェクト内の個別のデータ要素(行の属性など)を表します。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。 |
![]() |
キー属性 |
データ・コントロール構造ファイル、またはビジネス・サービス自体で、主キー属性として宣言されたオブジェクト属性を表します。 |
ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。 |
![]() |
メソッド |
データ・コントロールのメソッドまたは操作、またはその公開された構造のいずれかを表し、パラメータの受入れや、ビジネス・ロジックの実行を行ったり、オプションで単一の値、構造、またはコレクションを戻したりすることができます。 |
コマンド・コンポーネント。 パラメータを受け入れるメソッドの場合: コマンド・コンポーネントおよびパラメータ付きフォーム。 |
![]() |
メソッド戻り値 |
メソッドまたはその他の操作から返されたオブジェクトを表します。戻されたオブジェクトは、単一の値またはコレクションです。 メソッド戻りは、これを戻すメソッドの下に、子として表示されます。メソッド戻りの下に子として表示されるオブジェクトは、コレクションの属性、親コレクションに関連するアクションを実行する他のメソッド、または親コレクションで実行できる操作などです。 |
単一の値の場合: テキスト・フィールドおよび選択リスト。 コレクションの場合: フォーム、表、ツリー、レンジ・ナビゲーションの各コンポーネント。 単一値のメソッド戻り値がドロップされると、メソッドはフレームワークにより自動的に起動されなくなります。メソッドを起動するために、対応するメソッドをボタンとしてドロップできます。フォームがタスク・フローの一部の場合、メソッドを起動するためのメソッド・アクティビティを作成できます。 |
![]() |
操作 |
親オブジェクトに対してアクションを実行する、組込みデータ・コントロール操作を表します。 |
ボタンおよびリンクなどの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モデル設定ページで、パッケージ構成(名前と場所など)を設定できます。
ページ定義ファイル(pageNamePageDef.xml)は、アプリケーションのビュー・レイヤーにある各ページのバインディング・コンテナを定義します。バインディング・コンテナでは、ページのすべてのバインディング・オブジェクトへのランタイム・アクセスが行われます。ページ定義ファイルの詳細は、「生成されるドラッグ・アンド・ドロップ・アーティファクトに関する必知事項」を参照してください。
ヒント:
現在のバインディング・コンテナは、プログラム的なアクセス用のAdfContextからも入手できます。
ページ定義ファイルが構成されます。この処理では、ページによって参照されるバインディング・オブジェクトの定義も追加されます。
ページに指定のコンポーネントを追加します。
これらの事前作成済コンポーネントには、ページ定義ファイルのバインディング・オブジェクトを参照するデータ・バインディング式言語(EL)式が含まれます。詳細は、「データ・バインディングEL式について」を参照してください。
UIコンポーネントが必要とするすべてのライブラリ、ファイル、および構成要素が追加されます。データバインドされたコンポーネントに必要なアーティファクトの詳細は、「MAFアプリケーションの作成時に行われる処理」を参照してください。
ページにMAFバインディングが含まれている場合、実行時には、クライアントまたはコントローラから起動されたビジネス・サービスとのやり取りが、バインディング・コンテキストと呼ばれる単一オブジェクトを介して、アプリケーションによって管理されます。バインディング・コンテキストは、アプリケーション内のすべてのデータ・コントロールおよびページ定義のランタイム・マップ(名前付きdataでEL式#{data}を使用してアクセス可能)です。
図16-7に示すように、MAFでは、アプリケーション、DataBindings.cpxおよびページ定義ファイルからバインディング・コンテキストが作成されます。設計時に使用可能なデータ・コントロールは、すべてのDataControls.dcxファイルとワークスペース内のすべてのアプリケーション・モジュールの集合体によって定義されますが、実行時にアプリケーションで使用可能なデータ・コントロールは、DataBindings.cpxファイルで定義されます。DataBindings.cpxファイルは、アプリケーションのページで使用されているすべてのデータ・コントロールを一覧表示し、ページ定義ファイルに定義したバインディング・オブジェクトが格納されているバインディング・コンテナをWebページのURLにマップします。ページ定義ファイルは、アプリケーション・ページで使用するバインディング・オブジェクトを定義します。各ページにページ定義ファイルが1つあります。
バインディング・コンテキストには、これらのオブジェクトの実際のインスタンスは含まれていません。かわりに、マップには必要に応じてデータ・コントロールまたはバインディング・コンテナ・オブジェクトになる参照が含まれます。たとえば、オブジェクト(ページ定義など)がアプリケーションから解放されるか、タスク・フローが終了するか、リクエストの終了時にバンディング・コンテナまたはデータ・コントロールが解放されると、データ・コントロールおよびバンディング・コンテナは参照オブジェクトに戻ります。DataBindings.cpxファイルの詳細は、「生成されるドラッグ・アンド・ドロップ・アーティファクトに関する必知事項」を参照してください。
図16-7 ファイル・バインディング・コンテキストの実行時の使用

注意:
コンポーネントを構成するときは、使用するバインディング・スタイルを十分に考慮してください。より具体的に言うと、標準的なバインディングをマネージドBeanバインディングと組み合せると、解釈を誤った動作が発生することがよくあります。これは、バインディング・インフラストラクチャとマネージドBeanインフラストラクチャとの間でクラス・インスタンスが一致する可能性が低いためです。バインディングが混在すると、UIに直接リンクされていないインスタンスの動作がコールされる場合があります。
MAFでのバインディングの使用の詳細は、次の項を参照してください。
データ・コントロールを作成すると、データ・コントロールについて、値と動作の標準的なセットが設定されます。たとえば、属性のラベルのクライアントでの表示方法がデータ・コントロールによって決定されます。データ・コントロールの要素に対応するデータ・コントロール構造ファイルを作成および変更することによって、これらの値と動作を構成できます。まず、.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メソッドなどです。
図16-9に、Item Beanのデータ・コントロール構造ファイルを示します。
図16-9 概要エディタでのデータ・コントロール構造ファイル

注意:
データ・コントロール構造ファイルの概要エディタには、データ・オブジェクトに関連付けられているすべての属性、アクセッサおよび操作が表示されます。ただし、データ・コントロール構造ファイルのXMLソースには、編集した要素の定義のみが含まれます。基本要素は、データ・オブジェクトからイントロスペクションされます。また、基礎となるデータ・オブジェクトに変更を加えると、データ・コントロールはそれらの変更を継承します。
データ・コントロールに含まれるすべてのオブジェクトをOracle Metadata Services (MDS)カスタマイズ可能にする必要がある場合は、パッケージされたアプリケーションにこれらのオブジェクトのデータ・コントロール構造ファイルが含まれている必要があります。
アダプタ・フレームワークに基づくデータ・コントロールを作成する際には、データ・コントロール構造ファイルはデフォルトでは生成されません。これは、特定のオブジェクトにメタデータを追加しない場合、データ・コントロールにこれらのファイルは必要ないからです。「データ・コントロールの編集方法」で説明されているように、通常、データ・コントロール構造ファイルは、宣言型のメタデータ(UIヒントやバリデータなど)をそのオブジェクトに追加するためにデータ・コントロールを編集するときにのみ、データ・コントロール・オブジェクト用に生成されます。各データ・コントロール・オブジェクト用のデータ・コントロール構造ファイルを作成するには、データ・コントロール・オブジェクトごとにその手順を繰り返す必要があります。
MDSの詳細は、「MDSを使用したMAFアプリケーションのアーティファクトのカスタマイズ」を参照してください。
ビジネス・サービスのデータ・コントロールを作成する際、個々のデータ・オブジェクトについて作成するデータ・コントロール構造ファイルで宣言的にデータ・オブジェクトの永続属性の機能を拡張できます。たとえば、UIコンポーネントの属性のデフォルト表示を制御する検証ルールを作成し、UIヒントを設定できます。
これらのプロパティはデータ・コントロール構造ファイルの概要エディタの「属性」ページで設定します。データ・コントロール構造ファイルの作成の詳細は、「データ・コントロールの編集方法」を参照してください。
データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタで、そのデータ・オブジェクトの主キーとして属性を指定できます(データ・オブジェクトの基礎クラスでまだ指定していない場合)。
始める前に:
属性プロパティの設定方法の知識があると役立ちます。詳細は、「属性の操作」を参照してください。
次のタスクを完了する必要があります。
属性を主キーとして設定する手順は次のとおりです。
注意:
属性がクラス内ですでに主キーとして指定されている場合、データ・コントロールはその設定を継承し、「キー属性」チェックボックスが選択されます。ただし、この場合は、「キー属性」オプションを選択解除することはできません。
値のタイプが「リテラル」に設定されている場合、「詳細」セクションの「値」フィールドには、属性のデフォルト値を静的に指定できます。たとえば、ServiceRequestエンティティBeanのStatus属性のデフォルト値をOpenに設定したり、User BeanのUserRole属性のデフォルト値をuserに設定できます。
始める前に:
属性プロパティの設定方法の知識があると役立ちます。詳細は、「属性の操作」を参照してください。
属性の静的なデフォルト値を定義する手順:
属性の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ヒントにアクセスし、ページにデータとしてヒント値を表示できます。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コンポーネントにバインドできます。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サンプル・アプリケーションを参照してください。
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では、アプリケーション内でDeviceFeaturesデータ・コントロールを通じて使用できるデバイス固有の機能が公開されます。DeviceFeaturesデータ・コントロールは、新しいMAFアプリケーションを作成するときに「データ・コントロール」パネルに表示されるコンポーネントです。Cordova Java APIは、このデータ・コントロールを通じて抽象化されます。これにより、MAF AMXとして実装されたアプリケーション機能から、デバイスに埋め込まれた様々なサービスにアクセスできるようになります。DeviceFeaturesデータ・コントロールから提供される操作をMAF AMXページ内にドラッグ・アンド・ドロップすることによって、デバイスに格納されたユーザーのコンタクト先を管理する機能の追加、電子メール・メッセージとSMSテキスト・メッセージの両方の作成と送信、デバイスの位置の確認、デバイスのカメラの使用およびデバイスのファイル・システムに格納されたイメージの取得を行うことができます。次の項では、これらの操作を宣言的に使用する方法や、JavaコードとJavaScriptを使用して実装する方法など、各操作について詳しく説明します。
図16-10 概要エディタでのMAFのDeviceFeaturesデータ・コントロール

MAFアプリケーション・テンプレートを使用してアプリケーションを作成すると、自動的にDeviceFeaturesデータ・コントロールが「データ・コントロール」パネルに表示されます。図16-10は、「概要」エディタ内のDeviceFeaturesデータ・コントロールを示しています。次のメソッドを使用できます。
addLocalNotification
cancelLocalNotification
createContact
displayFile
findContacts
getPicture
removeContact
sendEmail
sendSMS
startLocationMonitor
updateContact
ページを作成したら、DeviceFeaturesデータ・コントロールのメソッド(またはそれらのメソッド内にネストされたその他のオブジェクト)を「データ・コントロール」パネルからMAF AMXビューにドラッグして、関連する機能にバインドされたコマンド・ボタンやその他のコンポーネントを作成できます。デフォルトのバインディングを受け入れるか、ELを使用してそれらのバインディングを変更できます。また、JavaScriptやJavaを使用して、機能を実装または構成することもできます。データ・コントロールをMAFアプリケーションに含める方法については、「MAF AMXページへのデータ・コントロールの追加方法」を参照してください。
DeviceManagerは、デバイスの機能へのアクセスを可能にするオブジェクトです。このオブジェクトのハンドルは、DeviceManagerFactory.getDeviceManagerをコールすることによって取得できます。次の項では、DeviceManagerオブジェクトを使用してgetPictureやcreateContactなどのメソッドを起動する方法について説明します。
[[ dev ER 19938192は後述]]
ネットワーク・アクセスを除き、すべてのApache Cordova対応デバイス機能へのアクセスは、MAFアプリケーションの場合デフォルトでは有効になっていません。DeviceFeaturesデータ・コントロールによって公開されている操作が実行時に正常に機能するには、関連するプラグインがMAFアプリケーションで有効になっている必要があります。たとえば、DeviceFeaturesデータ・コントロールのsendSMS操作を使用する場合は、MAFアプリケーションでSMSプラグインを有効にする必要があります。プラグインは手動で有効にするか、MAFアプリケーションで関連するプラグインが有効になっていない操作をドラッグ・アンド・ドロップしたときにJDeveloperによって表示されるダイアログで該当するオプションを選択して有効にすることができます。たとえば、まだSMSプラグインが有効になっていないMAFアプリケーションのMAF AMXページにsendSMS操作をドラッグ・アンド・ドロップすると、JDeveloperによって図16-11のダイアログが表示されます。
図16-11 DeviceFeaturesデータ・コントロールの操作用プラグインの有効化

操作に必要なプラグインが有効になっていない場合、MAF AMXページのソース・ファイル内に警告メッセージが表示されます。たとえば、MAFアプリケーションでSMSプラグインが有効になっていないと仮定しましょう。MAF AMXページの、アプリケーションがsendSMS操作を起動する箇所に、図16-12に示した警告メッセージが表示されます。この問題を解決するには、「MAFアプリケーションでのプラグインの使用方法」の説明に従って、プラグインを手動で有効にします。
図16-12 DeviceFeaturesデータ・コントロールの操作に必要なプラグイン

DeviceFeaturesデータ・コントロールに含まれるgetPictureメソッドをMAFアプリケーションで使用すると、デバイスのカメラとフォト・ライブラリを活用し、エンド・ユーザーが写真を撮影したり、既存のイメージを取得できるようにすることが可能です。この項の終わりに、次のことを示す例があります。
ユーザーがデバイスのカメラで写真を撮影することを可能にするデバイスのcamera.Javaコードでエンド・ユーザーが写真を撮影できるようにするJavaScriptコード。
ユーザーが保存済イメージを取得することを可能にする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メソッドによって戻される場合、ファイルのサイズを決定するために使用する前にファイルURIから問合せパラメータを削除する必要があります。次に例を示します。
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}である必要があります。
図16-13は、エンド・ユーザーのフォト・ライブラリからイメージを表示するためのバインディングを示しています。
図16-13 デザインタイムでフォト・ライブラリからイメージを表示するためのバインディング

このアプリケーションを実行すると、イメージ・チューザが自動的に表示され、エンド・ユーザーは表示するイメージを選択できます。イメージ・チューザが自動的に表示される理由は、イメージ・コントロールが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);
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が表示されます。
図16-14は、ページ上の編集可能なフォームを使用してSMSを送信するためのバインディングを示しています。
図16-14 デザインタイムで編集可能なフォームを使用して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");
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操作をページ・デザイナ上にドラッグし、パラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスの電子メール・インタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに事前に値が移入され、送信準備が整った電子メールが表示されます。
図16-15は、ページ上の編集可能なフォームを使用して電子メールを送信するためのバインディングを示しています。
図16-15 デザインタイムで編集可能なフォームを使用して電子メールを送信するためのバインディング

次に、エンド・ユーザーがデバイスの電子メール・インタフェースを使用して電子メール・メッセージを送信することを可能にするコード例を示します。
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");
DeviceFeaturesデータ・コントロールに含まれるcreateContactメソッドをMAFアプリケーションで使用すると、コンタクト先を管理するためのデバイスのインタフェースとファイル・システムを活用し、エンド・ユーザーが新しいコンタクト先を作成してデバイスのアドレス帳に保存できるようにすることが可能です。MAFでは、デバイスのインタフェースを表示し、必要に応じてContactのフィールドに事前にデータを移入できます。この項の最後の例に示すように、createContactメソッドはContactオブジェクトをパラメータとして使用し、作成されたContactオブジェクトを戻します。
createContactメソッドとContactオブジェクトの詳細は、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。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);
DeviceFeaturesデータ・コントロールに含まれるfindContactsメソッドをMAFアプリケーションで使用すると、コンタクト先を管理するためのデバイスのインタフェースとファイル・システムを活用し、エンド・ユーザーがデバイスのアドレス帳から1つ以上のコンタクト先を検索できるようにすることが可能です。MAFでは、デバイスのインタフェースを表示し、必要に応じてfindContactsのフィールドに事前にデータを移入できます。findContactsメソッドでは、フィルタ文字列と検索する(そして、見つかったコンタクト先の一部として戻す)フィールド名のリストを使用します。フィルタ文字列には、コンタクト先内の検索する任意の項目を指定できます。findContactsメソッドの詳細は、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。
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);
DeviceFeaturesデータ・コントロールに含まれるupdateContactメソッドをMAFアプリケーションで使用すると、コンタクト先を管理するためにデバイスのインタフェースとファイル・システムを活用し、エンド・ユーザーがデバイスのアドレス帳に含まれるコンタクト先を更新できるようにすることが可能です。MAFでは、デバイスのインタフェースを表示し、必要に応じてupdateContactのフィールドに事前にデータを移入できます。この項の最後の例に示すように、updateContactメソッドはContactオブジェクトをパラメータとして使用し、更新されたupdateContactオブジェクトを戻します。
updateContactメソッドとContactオブジェクトの詳細は、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。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分に設定されます。デバイス操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。
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分に設定されます。デバイス操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。
DeviceFeaturesデータ・コントロールに含まれるstartLocationMonitorメソッドをMAFアプリケーションで使用すると、デバイスの地理的位置サービスを使用して、デバイスの場所を取得および追跡できます。MAFでは、デバイスのインタフェースを表示し、必要に応じてstartLocationMonitorのフィールドに事前にデータを移入できます。
MAFで公開されているAPIを使用すると、デバイスの現在の位置を取得できるため、特定の時点におけるデバイスの現在の位置を取得したり、定期的にその情報をサブスクライブできます。この項の最後にある例は、地理的位置を使用してデバイスの位置の変更をサブスクライブする方法と、デバイスの位置を取得する方法を示しています。startLocationMonitorメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。
注意:
altitudeAccuracyプロパティは、Androidデバイスでサポートされていません。
Androidプラットフォームでは、iOSほど頻繁に更新が行われません。
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を使用してデバイスの位置の変更をサブスクライブする方法を示しています。このメソッドが受け取るパラメータの詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。
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およびstartHeadingMonitorメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。
次の例は、DeviceManager.getCurrentPositionを使用してデバイスの現在位置を(1回)取得する方法を示しています。このメソッドが受け取るパラメータの詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。
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());
DeviceFeaturesデータ・コントロールに含まれるdisplayFileメソッドを使用すると、MAFアプリケーションでデバイスのローカル・ファイルを表示できます。プラットフォームに応じて、アプリケーション・ユーザーはPDF、イメージ・ファイル、Microsoft Officeドキュメントおよびその他の様々なファイル・タイプを表示できます。iOSでは、アプリケーション・ユーザーは、サポートされているファイルをMAFアプリケーション内でプレビューできます。またユーザーは、それらのファイルをサードパーティ・アプリケーションで開く、電子メールで送信する、プリンタに送信するなどの操作を行うこともできます。Androidでは、すべてのファイルがサードパーティ・アプリケーション内で開かれます。つまり、アプリケーション・ユーザーは、ファイルを表示しながらMAFアプリケーションから離れることができます。ユーザーは、Androidの戻るボタンを押すことによって、MAFアプリケーションに戻ることができます。所定のファイルを開くことができるアプリケーションがデバイス内に存在しない場合は、エラーが表示されます。displayFileメソッドを使用してiOSデバイスとAndroidデバイスの両方でファイルを開く方法の例は、DeviceDemoサンプル・アプリケーションを参照してください。このアプリケーションは、開発コンピュータのJDeveloperインストール・ディレクトリ内で次の場所にあるPublicSamples.zipファイルから入手できます。
jdev_install/jdeveloper/jdev/extensions/oracle.maf/Samples
displayFileメソッドの機能は、デバイスのローカル・ファイルを表示することのみです。つまり、リモート・ファイルは最初にダウンロードする必要があります。ダウンロードしたファイルを保存する必要のあるディレクトリ・ルートに戻るには、コールAdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.DownloadDirectory)を使用します。iOSでは、この場所はアプリケーションによって異なりますが、Androidでは、この場所として外部ストレージ・ディレクトリが参照されます。この外部ストレージ・ディレクトリは公的にアクセス可能であるため、サードパーティ・アプリケーションを使用して、そこに格納されているファイルを読み取ることができます。
表16-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メソッドの詳細は、MAF Javadocの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());
}
DeviceFeaturesデータ・コントロールには、addLocalNotificationメソッドとcancelLocalNotificationメソッドが含まれており、これらのメソッドによって、MAFアプリケーションは、通知を管理するためにデバイスのインタフェースを利用できるようになり、エンド・ユーザーはローカル通知のスケジュールや取消しを行うことができます。
DeviceFeaturesデータ・コントロールを使用してaddLocalNotificationまたはcancelLocalNotification操作をカスタマイズするには:
図16-16は、選択した操作のパラメータを構成するために使用する「アクション・バインディングの編集」ダイアログを示しています。この例では、cancelLocalNotification操作のnotificationIDがaddLocalNotification操作の結果にバインドされます。
図16-16 ローカル通知のスケジュール用のバインドの設定

図16-17に、式ビルダーを使用してaddLocalNotification操作の結果をcancelLocalNotification操作にバインドする方法を示します。
図16-17 addLocalNotificationの結果へのcancelLocalNotificationのバインド

addLocalNotificationおよびcancelLocalNotificationメソッドの詳細は、MAF JavadocのDeviceDataControlクラスを参照してください。コード例などのローカル通知の管理の詳細は、「ローカル通知の管理」を参照してください。通知に関する一般的な情報については、「通知の概要」を参照してください。
アプリケーションには、特定のデバイスの特性や機能に依存する機能が含まれる場合があります。たとえば、デバイスの画面の向きによって異なるユーザー・インタフェースを提示したり、デバイスで地理的位置がサポートされる場合のみマッピング機能を有効にすることなどが考えられます。MAFでは、このような動的な動作をサポートするために、Java、JavaScriptおよびELからアクセスできる様々なプロパティが用意されています。表16-8に、これらのプロパティをリストし、問合せ方法、予期される戻り値およびアプリケーションのライフサイクル中にそのプロパティが変更される可能性があるかどうかに関する情報も提供します。この項の最後にある例は、JavaScriptを使用してこれらのプロパティにアクセスする方法を示しています。
注意:
デバイス・プロパティのタイムアウト値は、1分に設定されます。デバイス操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。
表16-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)コンポーネントの詳細は、「クライアント・リスナーの使用方法」を参照してください。
モバイル・アプリケーション・フレームワークでは、バインディング属性で検証ルールが設定された状態で、データ・コントロール・レイヤーで検証が実行されます。属性の検証は、バインディングに対するsetValue操作中に、システム内の単一点で実行されます。
データ・コントロールによって公開される属性に対して、次のバリデータを定義できます。
比較バリデータ
長さバリデータ
リスト・バリデータ
範囲バリデータ
特定の属性に対してすべてのバリデータが実行され、成功しないすべてのバリデータに対してネストされた例外がスローされます。属性の検証メッセージを定義し、実行時に検証ルールを起動するときに表示できます。詳細は、「入力の検証」および「検証ルールの追加方法」を参照してください。
注意:
JSONの制限により、BigDecimalが保持できる値はDoubleの範囲内となり、BigIntegerが保持できる値はLongの範囲内となります。許可された値よりも大きい数値を使用するには、toStringをBigDecimalまたはBigIntegerでコールし、値をStringとしてシリアライズ(解除)します。
表16-9に、長さバリデータでサポートされる検証の組合せをリストします。
表16-9 長さ検証
| 比較タイプ | バイト | 文字 |
|---|---|---|
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
表16-10と表16-11に、範囲バリデータでサポートされる検証の組合せを示します。
表16-10 範囲検証
| 比較タイプ | バイト | 文字 | 倍精度 | 浮動小数 | 整数 | 長整数 | 短整数 |
|---|---|---|---|---|---|---|---|
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
表16-11 範囲検証: math、sqlおよびutilパッケージ
| 比較タイプ | java.math.BigDecimal | java.math.BigInteger | java.sql.Date | java.sql.Time | java.sql.Timestamp | java.util.Date |
|---|---|---|---|---|---|---|
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
表16-12に、リスト・バリデータでサポートされる検証の組合せをリストします。
表16-12 リスト検証
| 比較タイプ | 文字列 |
|---|---|
|
サポート |
|
サポート |
表16-13と表16-14に、比較バリデータでサポートされる検証の組合せを示します。
表16-13 比較検証
| 比較タイプ | バイト | 文字 | 倍精度 | 浮動小数 | 整数 | 長整数 | 短整数 | 文字列 |
|---|---|---|---|---|---|---|---|---|
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
表16-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 |
|---|---|---|---|---|---|---|
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
検証ルールは、様々なユース・ケースに合わせて定義できます。宣言的検証ルールをエンティティ・オブジェクトに追加するには、データ・コントロール構造ファイルの「概要」エディタにある「属性」ページを使用します。
検証規則を追加するには:
バリデータのメタデータは、設計時にデータ・コントロール構造のメタデータ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クラスの詳細は、MAFのJavadocを参照してください。
JDeveloperでは、データ変更イベントを単純化するために、プロパティ変更リスナー・パターンを使用します。多くの場合、JDeveloperを使用して、Beanのプロパティ・アクセサからの通知を参照するために必要なソース・コードを生成できます。これを行うには、「アクセサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェック・ボックスを選択します(詳細は「マネージドBeanカテゴリについて」を参照)。PropertyChangeSupportオブジェクトが自動的に生成され、新たに生成されたsetterメソッドにfirePropertyChangeへのコールが含まれます。また、addPropertyChangeListenerおよびremovePropertyChangeListenerメソッドが追加されるため、プロパティ変更リスナーは、このオブジェクトを使用して自身を登録および登録解除できます。これを使用してフレームワークはクライアント・キャッシュにプッシュする変更を取得し、データが変更されたことをユーザー・インタフェース・レイヤーに通知します。
注意:
PropertyChangeSupportオブジェクトを手動でクラスに追加する場合は、addPropertyChangeListenerおよびremovePropertyChangeListenerメソッドも(これらの明示的なメソッド名を使用して)含める必要があります。
プロパティ変更のみでは、すべてのデータ変更通知は解決されません。たとえば、データ・コントロールによってラップされたBeanがあり、アイテムのコレクションの公開が必要な場合が考えられます。リストの個々のアイテムが変更されたときはプロパティ変更で十分ですが、カーディナリティが変更されたときは十分ではありません。この場合、コレクション全体のプロパティ変更を起動すると、パフォーマンスが低下する可能性があるため、かわりにコレクションのデルタのみを更新します。これを行うには、ProviderChangeSupportクラスを使用して、単純なプロパティ変更に必要なデータよりも多くのデータを公開する必要があります。プロバイダ変更イベントはプロパティ変更イベントと似ていますが、個別のプロパティのみを対象とするのではなく、プロバイダ全体に適用されます。
注意:
ProviderChangeSupportオブジェクトは、自動的には生成されません。このオブジェクトはaddProviderChangeListener、removeProviderChangeListenerおよびgetKey()メソッドとともに、(これらの明示的なメソッド名を使用して)手動でクラスに追加する必要があります。getKey()メソッドは、プロバイダに対して一意の値を生成する文字列を返す必要があります。getKey()メソッドをクラスに追加するかわりに、図16-18に示す概要エディタを使用して、データ・コントロール構造ファイルのキー属性として、データ・コントロールで属性を指定します。
図16-18 データ・コントロールのデータ・コントロール構造ファイルでのキー属性の選択

プロバイダ変更は、データ・コントロールによってラップされたBeanで公開されている動的なコレクションを保持しているときのみ必要になるため、起動するプロバイダ変更イベントは、次のいくつかのタイプのみになります。
fireProviderCreate: 新しい要素をコレクションに追加する場合
fireProviderDelete: 要素をコレクションから削除する場合
fireProviderChange: コレクション内の1つの要素を変更する場合(リスト全体のリフレッシュを回避するのに必要です)
fireProviderRefresh: 同時に複数の変更をコレクションに加え、単純にクライアントにコレクション全体のリフレッシュを要求した方がよいと判断した場合(これは一括操作でのみ使用する必要があります)
ProviderChangeSupportクラスは、コレクション要素に関連する通知を送信するために使用され、これによって、Java Beanデータ・コントロール内で変更が発生したときにコンポーネントを適切に更新できます。このクラスが従うパターンは、自動的に生成されるPropertyChangeSupportクラスと似ていますが、ProviderChangeSupportとともに使用されるイベント・オブジェクトでは、操作のタイプや変更された要素のキーと位置などの詳細情報を送信します。ProviderChangeSupportでは、コレクションに対する要素(プロバイダ)の追加や削除など、コレクションに対する構造的な変更を取得します。PropertyChangeSupportでは、コレクション内の個々のアイテムに対する変更を取得します。
次の例は、ProviderChangeSupportを使用して、コレクションの要素に対する構造的な変更(子を追加または削除する場合など)に関する通知を送信する方法を示しています。ProviderChangeListeneインタフェースとProviderChangeEventクラスおよびProviderChangeSupportクラスの詳細は、MAF Javadocを参照してください。
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アプリケーション」を参照してください。