15 MAF AMXでのバインディングの使用とデータ・コントロールの作成

この章では、MAF AMXアプリケーション機能内でデータ・バインディング、データ・コントロールおよびデータ・バインディング式言語(EL)を使用する方法について説明します。また、オブジェクト・スコープ・ライフサイクル、マネージドBean、UIヒント、検証およびデータ変更イベントについても説明します。

この章の内容は次のとおりです。

バインディングおよびデータ・コントロールの概要

データ・コントロールは、標準のメタデータ・インタフェースを使用して、ビジネス・サービスの操作とデータ・コレクションを記述します。その一方で、宣言的バインディングはデータ・コントロールからのデータへのアクセスに関する情報を格納します。モデル・レイヤーは、データ・コントロールとバインディングに関する情報について関連XMLファイルを読み取って、ユーザー・インタフェースをビジネス・サービスに接続します。

モバイル・アプリケーション・フレームワークによって、ユーザー・インタフェース(UI)・テクノロジとビジネス・サービス実装の分離を可能にする2つの概念(データ・コントロール宣言的バインディング)が実装されています。データ・コントロールでは、関連するプロパティ、メソッド、タイプの情報を含め、サービスの操作とデータ・コレクションを表す標準のメタデータ・インタフェースを使用してビジネス・サービスの実装技術を抽象化します。JDeveloperを使用すると、その情報をアイコンとして表示し、ページ上にドラッグ・アンド・ドロップできます。宣言的なバインディングによって、データ・コントロール内のデータ・コレクションからのデータ・アクセスとその操作の実行の詳細が抽象化されます。実行時に、モデル・レイヤーによって、適切なXMLファイルからデータ・コントロールおよびバインディングを記述した情報が読み取られ、ユーザー・インタフェースとビジネス・サービスの双方向の結合が実装されます。

ページのユーザー・インタフェース・コンポーネントをサポートするバインディングのグループは、ページ定義ファイルというページ固有のXMLファイルに記述されます。モデル・レイヤーは、このファイルを実行時に使用して、ページのバインディングをインスタンス化します。これらのバインディングは、バインディング・コンテナと呼ばれるリクエスト・スコープ・マップに保持され、EL式#{bindings}を使用して各ページ・リクエスト中にアクセスできます。この式により、現在のページのバインディング・コンテナが常に評価されます。「データ・コントロール」パネルから項目をドラッグし、それを特定のUIコンポーネントとしてページ上にドロップすることで、データバインドされたユーザー・インタフェースを設計できます。データ・コントロールを使用してUIコンポーネントを作成すると、そのコンポーネントを選択したデータ・コントロールにバインドするために必要なコードおよびオブジェクトがJDeveloperによって自動的に作成されます。

モバイル・アプリケーション・フレームワークには、即時利用可能な2つのデータ・コントロール(DeviceFeaturesデータ・コントロールとApplicationFeaturesデータ・コントロール)が付属しています。JDeveloperの「データ・コントロール」パネル内に表示されるDeviceFeaturesデータ・コントロールを使用すると、データ・コントロールの主なデータ属性を(テキスト)フィールドとして、またデータ・コントロールの操作をコマンド・オブジェクト(ボタン)として、アプリケーションにドラッグ・アンド・ドロップできます。これらのドラッグ・アンド・ドロップ・アクションによって、アプリケーション内のELバインディングおよび作成されるコントロールに適したプロパティが生成されます。バインディングはDataControls.dcxファイルで表され、データ・コントロール・ソースを指しています。また、ページ・バインディングは特定のページの参照をデータ・コントロールにリンクします。ApplicationFeaturesデータ・コントロールの詳細は、「MAF AMXコンテンツによるカスタムSpringboardアプリケーション機能に関する必知事項」を参照してください。

データ・コントロールおよびバインディングの詳細は、次を参照してください。

オブジェクト・スコープ・ライフサイクルについて

スコープは、実行時にEL式を使用してアプリケーションがアクセスできるオブジェクトをメモリー内の永続化します。スコープによって、オブジェクト(アプリケーションやタスク・フローなど)の存続期間と可用性が決定されます。

実行時、ページがデータにアクセスできるオブジェクト・スコープに必要なデータを格納することで、データをページに渡します。スコープによってオブジェクトの存続期間が決まります。オブジェクトをスコープに置くと、EL式を使用してスコープからアクセスできます。たとえば、fooという名前のマネージドBeanを作成し、Beanをビュー・スコープに存続させるよう定義するとします。このBeanにアクセスするには、#{viewScope.foo}という式を使用します。

モバイル・アプリケーション・フレームワークの変数とマネージドBeanの参照は、変数の存続期間と可視性を決定する様々なオブジェクト・スコープ内で定義されます。MAFは、次のスコープ(可視性が高い順に表示)をサポートしています。

  • アプリケーション・スコープ: オブジェクトは、アプリケーションが存続するかぎり(複数の機能にまたがって)使用可能です。

  • ページ・フロー・スコープ: オブジェクトは、ページ・フロー・スコープのマネージドBeanがどこに定義されているかによって、機能(単一の機能の境界)またはタスク・フローが存続するかぎり使用できます。Beanがバインドなしタスク・フローに定義されている場合、そのスコープは機能です。Beanがバインド・タスク・フローに定義されている場合、そのスコープはタスク・フローに限定されます。

  • ビュー・スコープ: オブジェクトは、ビューが存続するかぎり(機能の単一ページ内で)使用可能です。

オブジェクト・スコープは、プログラミング言語のグローバル変数およびローカル変数のスコープに相当します。スコープが広いほど、オブジェクトの可用性が高くなります。存続期間の間、これらのオブジェクトで特定のインタフェースの公開、情報の保持および他のオブジェクトへの変数とパラメータの受渡しを行うことができます。たとえば、アプリケーション・スコープに定義されているマネージドBeanは、アプリケーションが存続するかぎり、複数のページ・リクエストの間使用できます。ただし、ビュー・スコープに定義されているマネージドBeanは、1つの機能で1つのページ・リクエストの間のみ使用できます。

アプリケーション・スコープの名前空間で定義されたEL式は、アプリケーションが存続するかぎり、複数の機能にまたがって使用できます。アプリケーションの一方のビューでアプリケーション・スコープを定義し、そのスコープをもう一方のビューで参照できます。ページ・フロー・スコープの名前空間で定義されたEL式は、機能が存続するかぎり、単一の機能の境界内で使用できます。ビュー・スコープの名前空間で定義されたEL式は、ビューが存続するかぎり、機能の単一ページの境界内で使用できます。スコープを含むこのような変数に加えて、MAFでは、デバイス・プロパティとアプリケーション・プリファレンスに関する情報を公開できるスコープが定義されています。これらのスコープによって、アプリケーション・レベルの存続期間と可視性が決まります。「マネージドBeanカテゴリについて」および「モバイル・アプリケーション・フレームワーク・オブジェクト・カテゴリについて」を参照してください。

マネージドBeanを登録するスコープまたは値を格納するスコープを決める場合、可能なかぎり狭いスコープを常に使用するようにします。アプリケーション・スコープは、ユーザー情報やコンテキスト情報などのアプリケーション全体に関係する情報にのみ使用します。アプリケーション・スコープは、ページ間での値の受渡しには使用しないでください。

注意:

メモリー・スコープに入れる各オブジェクトはJSON DataChangeEventに対してシリアライズされ、このオブジェクト内のゲッター・メソッドによって戻されるオブジェクトもシリアライズされます。これは、ネストが深いシリアライズされたオブジェクト・ツリーにつながることがあり、パフォーマンスが低下します。一連のネストされたオブジェクトのシリアライズを避けるには、それらを一時オブジェクトとして定義する必要があります。「Beanクラス変数のシリアライズに関する必知事項」を参照してください。

オブジェクト・スコープとタスク・フローに関する必知事項

ページ・フロー・スコープは、タスク・フロー内のアクティビティ間でデータ値を受け渡しするために使用します。また、変数のビュー・スコープは現在のビュー・アクティビティ内でのみ必要になります。

タスク・フロー内の変数にどのスコープを使用するかを決定するときは、ビュー・スコープまたはページ・フロー・スコープのみを使用する必要があります。アプリケーション・スコープは、タスク・フローの存続期間を超えてオブジェクトをメモリーに保持するため、タスク・フローのカプセル化および再利用で障害が発生します。さらに、アプリケーション・スコープでは、オブジェクトがメモリーに必要以上に長い時間保持されるため、不要なオーバーヘッドが発生します。

タスク・フロー内のアクティビティ間でデータ値を渡す必要がある場合は、ページ・フロー・スコープを使用する必要があります。現在のビュー・アクティビティ内でのみ必要とされ、ビュー・アクティビティ間にまたがっていない変数の場合、ビュー・スコープを使用する必要があります。

EL式の作成

EL式は、実行時に決定されるオブジェクト値に属性をバインドするために、MAFアプリケーションで使用されます。EL式は、コードを使用することなく、個別のオブジェクトとそのプロパティへのアクセスを自動化するために、ページ定義ファイルを使用して構築します。

MAFアプリケーションのEL式を使用して、属性と実行時に決まるオブジェクト値とをバインドします。たとえば、#{UserList.selectedUsers}は選択したユーザーのセットを参照でき、#{user.name}は特定のユーザー名を参照でき、#{user.role == 'manager'}はユーザーがマネージャかどうかを判断します。実行時、汎用式エバリュエータによって、これらの式に対してそれぞれListStringおよびbooleanの値が返され、コードなしで自動的に各オブジェクトとそのプロパティにアクセスします。

値の表示に必要になるまで式は評価されません。MAF AMXでは遅延評価のみがサポートされるため、即時構成式(${})を使用する式は解析を行いますが、その動作は遅延式(#{})と同じになります。実行時、特定のUIコンポーネント(inputTextコンポーネント、outputTextコンポーネントなど)の値は、そのvalue属性によって決まります。コンポーネントにはその値として静的テキストを割り当てることができますが、通常、value属性には、表示データを決定するために実行時インフラストラクチャにより評価されるEL式が含まれます。たとえば、現在ログイン中のユーザーの名前を表示するoutputTextコンポーネントには、value属性に#{UserInfo.name}という式を設定できます。コンポーネントの任意の属性(value属性だけでなく)にEL式を使用して値を割り当てることができるため、動的、かつデータ駆動型のユーザー・インタフェースの作成が容易になります。たとえば、UIコンポーネントのrendered属性に#{not empty UserList.selectedUsers}などのブール値の式を使用すると、表示するオブジェクト・セットが空のときにはそのコンポーネントを非表示にできます。UserListというオブジェクトの選択ユーザーのリストが空の場合、rendered属性はfalseと評価されるため、コンポーネントはページに表示されません。

通常のアプリケーションでは、UserListのようなオブジェクトはマネージドBeanとして作成します。ランタイムでは、EL式でBeanを最初に参照した際に、Beanのオンデマンドのインスタンス化が管理されます。値を表示する場合、ページを表示する際にランタイムでEL式が評価され、マネージドBeanから値を得て、コンポーネントにデータが移入されます。ユーザーがUIコンポーネントのデータを更新すると、同じEL式に基づいて、ランタイムによって対応するマネージドBeanに値が戻されます。「マネージドBeanの作成および使用」を参照してください。EL式の詳細は、http://www.oracle.com/technetwork/java/index.htmlにあるJava EEチュートリアルを参照してください。

注意:

EL式を編集可能コンポーネントのvalue属性に使用している場合は、そのコンポーネントに対応するsetメソッドが必要です。そうでないと、EL式は読取り専用と評価され、値の更新は許可されません。

たとえば、ページにinputTextコンポーネント(IDはit1)があり、その値が#{myBean.inputValue}に設定されているとします。inputText値を更新するには、myBeanマネージドBeanに次のようなgetおよびsetメソッドが必要です。

    public void setIt1(RichInputText it1) {
        this.it1 = it1;
    }
 
    public RichInputText getIt1() {
        return it1;
    }

データ・バインディングEL式について

データ・バインディング式は、「データ・コントロール」パネルを使用してUIコントロールを作成するときに、MAFによって作成されます。また、MAFデータ・バインディング式は、手動で追加または編集することもできます。

「データ・コントロール」パネルを使用してコンポーネントを作成すると、MAFデータ・バインディング式が自動的に作成されます。この式は、バインディング・オブジェクトのデータを表示するか、バインディング・オブジェクトのプロパティを参照する、すべてのコンポーネント属性に追加されます。事前作成済のそれぞれの式は、ページ定義ファイルで定義された、適切なバインディング・オブジェクトを参照します。これらのバインディング式は編集可能ですが、MAFバインディング式の基本構文に従っていれば、独自に作成することもできます。MAFデータ・バインディング式は、属性がELをサポートする場合、バインディング・オブジェクトからのデータを移入する任意のコンポーネント属性に追加できます。

一般的なMAFデータ・バインディングEL式は、次の構文を使用して、バインディング・コンテナ内のタイプの異なるバインディング・オブジェクトを参照します。

#{bindings.BindingObject.propertyName}

各要素の説明は次のとおりです。

  • bindingsは、式によって参照されているバインディング・オブジェクトが現在のページのバインディング・コンテナにあることを識別する変数です。すべてのMAFデータ・バインディングEL式は、bindings変数で始まる必要があります。

  • BindingObjectは、ページ定義ファイルで定義される、バインディング・オブジェクトのID、または属性については名前です。バインディングobjectIDまたは名前は、そのページ定義ファイル内で一意なものです。EL式は、パラメータ・バインディング、実行可能バインディングまたは値バインディングなど、ページ定義ファイル内のどのバインディング・オブジェクトでも参照できます。

  • propertyNameは、各データバインドUIコンポーネントのデフォルトの表示方法を決定し、実行時のバインディング・オブジェクトのプロパティを設定する変数です。各タイプのバインディング・オブジェクトに対して、異なるバインディング・プロパティがあります。「MAFバインディング・プロパティに関する必知事項」を参照してください。

たとえば、次の式を例にしてみます。

#{bindings.ProductName.inputValue}

bindings変数は、現在のページのバインディング・コンテナでバインドされた値を参照します。参照されているバインディング・オブジェクトはProductNameであり、これは属性バインディング・オブジェクトです。バインディング・プロパティはinputValueで、最初のProductName属性の値を戻します。

ヒント:

ページ定義ファイルのバインディング式ではドル記号($)またはハッシュ記号(#)の接頭辞を使用できますが、MAFページのEL式で使用できるのは、ハッシュ記号(#)の接頭辞のみです。

前述のように、「データ・コントロール」パネルを使用してUIコンポーネントを作成する場合、これらの式が組み込まれます。ただし、必要に応じて手動で式を作成することもできます。JDeveloperの式ビルダーは、UIコンポーネントがバインドされるその他の有効なオブジェクトに加え、ページ定義ファイルに定義されたバインディング・オブジェクトのリストを提供することにより、EL式の構築を支援するダイアログです。また、MAFバインディング・オブジェクトの階層リストやMAFバインディング・オブジェクトの最も一般的に使用されるプロパティが提供されるため、MAFデータバインド式の作成や編集に特に便利です。「MAFバインディング・プロパティに関する必知事項」を参照してください。

EL式の作成方法

JDeveloperの式ビルダーを使用してEL式を宣言的に作成できます。「プロパティ」ウィンドウから「式ビルダー」にアクセスできます。

始める前に:

EL式に関する知識が役立つ場合があります。「EL式の作成」を参照してください。

式ビルダーの使用手順:

  1. 「プロパティ」ウィンドウで、変更する属性を見つけて、右端のドロップダウン・メニューを使用して「式ビルダー」を選択します。
  2. 次の機能を使用して式を作成します。
    • 「変数」ドロップダウンを使用して、式に含める項目を選択します。これらの項目は、階層形式のバインディング・オブジェクトであるツリーに表示されます。ツリーの各アイコンは、式で使用できる各種タイプのバインディング・オブジェクトを表します。

      ツリーの絞り込みには、ドロップダウン・フィルタを使用するか、検索フィールドに検索条件を入力します。MAFで公開されているELでアクセス可能なオブジェクトは、「ADFマネージドBean」ノードの「モバイル・アプリケーション・フレームワーク・オブジェクト」ノードにあります。

      ツリーで項目を選択すると、その項目がEL式内の「式」ボックスに移動されます。「式」ボックスに式を直接入力することもできます。

    • 演算子ボタンを使用して、式に論理演算子または算術演算子を追加します。

    「ADFマネージドBean」カテゴリからEL式を作成する方法の例を図に示します。ただし、EL式は、「式ビルダーのカテゴリについて」で説明されているどのカテゴリからも作成できます。

    図15-1 「式ビルダー」ダイアログ

    図15-1の説明が続きます
    「図15-1 「式ビルダー」ダイアログ」の説明

    ヒント:

    EL式を作成する正しい構文の使用の詳細は、http://www.oracle.com/technetwork/java/index.htmlのJava EEチュートリアルを参照してください。

    表15-1 式ビルダーのバインディング・ノードの下にあるアイコン

    アイコン 説明
    このイメージはバインディングのアイコンを示しています。

    現在のページのバインディング・コンテナを参照する、bindingsコンテナ変数を示します。bindingsノードを開くと、現在のページのすべてのバインディング・オブジェクトが公開されます。

    このイメージはデータのアイコンを示しています。

    バインディング・コンテキスト全体を参照する、dataバインディング変数を示します(アプリケーション内の.cpxファイルから作成)。dataノードを開くと、アプリケーション内のページ定義ファイルが公開されます。

    このイメージはアクション・バインディング・オブジェクトのアイコンを示しています。

    アクション・バインディング・オブジェクトを表します。このアイコンを使用するノードを開くと、有効なアクション・バインディング・プロパティのリストが公開されます。

    このイメージはイテレータ・バインディング・オブジェクトのアイコンを示しています。

    イテレータ・バインディング・オブジェクトを表します。このアイコンを使用するノードを開くと、有効なイテレータ・バインディング・プロパティのリストが公開されます。

    このイメージは属性バインディング・オブジェクトのアイコンを示しています。

    属性バインディング・オブジェクトを表します。このアイコンを使用するノードを開くと、有効な属性バインディング・プロパティのリストが公開されます。

    このイメージはリスト・バインディング・オブジェクトのアイコンを示しています。

    リスト・バインディング・オブジェクトを表します。このアイコンを使用するノードを開くと、有効なリスト・バインディング・プロパティのリストが公開されます。

    このイメージはテーブルまたはツリー・バインディング・オブジェクトのアイコンを示しています。

    表バインディング・オブジェクトまたはツリー・バインディング・オブジェクトを表します。このアイコンを使用するノードを開くと、有効な表バインディング・プロパティおよびツリー・バインディング・プロパティのリストが公開されます。

    このイメージはMAFバインディング・オブジェクト・プロパティのアイコンを示しています。

    MAFバインディング・オブジェクト・プロパティを表します。「MAFバインディング・プロパティに関する必知事項」を参照してください。

    このイメージはパラメータ・バインディングのアイコンを示しています。

    パラメータ・バインディング・オブジェクトを表します。

    このイメージはBeanクラスのアイコンを示しています。

    Beanクラスを表します。

    このイメージはメソッドのアイコンを示しています。

    メソッドを表します。

メソッド式ビルダーについて

「プロパティ」ウィンドウの「メソッド式ビルダー」は、「式ビルダー」と似ていますが、「メソッド式ビルダー」は選択したプロパティに応じてマネージドBeanにフィルタを適用します。

表15-2は、「プロパティ」ウィンドウで「式ビルダー」オプションではなく「メソッド式ビルダー」オプションが提供されるプロパティを示しています。これらの唯一の違いは、メソッド式ビルダーが、選択されたプロパティに応じてマネージドBeanをフィルタして除外することです。

表15-2 メソッド式ビルダーのプロパティ

プロパティ 要素

action

amx:commandButton

action

amx:commandLink

action

amx:listItem

action

amx:navigationDragBehavior

action

dvtm:chartDataItem

action

dvtm:ieDataItem

action

dvtm:timelineItem

action

dvtm:area

action

dvtm:marker

actionListener

amx:listItem

actionListener

amx:commandButton

actionListener

amx:commandLink

binding

amx:actionListener

mapBoundsChangeListener

dvtm:geographicMap

mapInputListener

dvtm:geographicMap

moveListener

amx:listView

rangeChangeListener

amx:listView

selectionListener

amx:listView

selectionListener

amx:filmStrip

selectionListener

dvtm:areaDataLayer

selectionListener

dvtm:pointDataLayer

selectionListener

dvtm:treemap

selectionListener

dvtm:sunburst

selectionListener

dvtm:timelineSeries

selectionListener

dvtm:nBox

selectionListener

dvtm:areaChart

selectionListener

dvtm:barChart

selectionListener

dvtm:bubbleChart

selectionListener

dvtm:comboChart

selectionListener

dvtm:horizontalBarChart

selectionListener

dvtm:lineChart

selectionListener

dvtm:funnelChart

selectionListener

dvtm:pieChart

selectionListener

dvtm:scatterChart

valueChangeListener

amx:inputNumberSlider

valueChangeListener

amx:inputText

valueChangeListener

amx:selectBooleanCheckbox

valueChangeListener

amx:selectBooleanSwitch

valueChangeListener

amx:selectManyCheckbox

valueChangeListener

amx:selectManyChoice

valueChangeListener

amx:selectOneButton

valueChangeListener

amx:selectOneChoice

valueChangeListener

amx:selectOneRadio

valueChangeListener

dvtm:statusMeterGauge

valueChangeListener

dvtm:dialGauge

valueChangeListener

dvtm:ratingGauge

viewportChangeListener

dvtm:areaChart

viewportChangeListener

dvtm:barChart

viewportChangeListener

dvtm:comboChart

viewportChangeListener

dvtm:horizontalBarChart

viewportChangeListener

dvtm:lineChart

非ELプロパティについて

ELに対応していないプロパティには、「プロパティ」ウィンドウで選択可能なEL式ビルダー・オプションオプションがありません。

表15-3は、ELに対応していないため「プロパティ」ウィンドウでEL式ビルダー・オプションが提供されないプロパティを示しています。

表15-3 非ELプロパティ

プロパティ 要素

id

すべての要素

facetName

amx:facetRef

failSafeClientHandler

amx:loadingIndicatorBehavior

failSafeDuration

amx:loadingIndicatorBehavior

group

amx:validationBehavior

name

amx:attribute

name

amx:attributeList

name

amx:attributeListIterator

name

amx:facet

ref

amx:attributeList

type

dvtm:attributeGroups

var

amx:carousel

var

amx:filmStrip

var

amx:iterator

var

amx:listView

var

amx:loadBundle

var

dvtm:areaChart

var

dvtm:barChart

var

dvtm:bubbleChart

var

dvtm:comboChart

var

dvtm:funnelChart

var

dvtm:horizontalBarChart

var

dvtm:lineChart

var

dvtm:pieChart

var

dvtm:scatterChart

var

dvtm:sparkChart

var

dvtm:geographicMap

varStatus

amx:attributeListIterator

MAFバインディング・プロパティに関する必知事項

式ビルダーを使用してデータバインドされたコンポーネントを作成すると、EL式は、Oracle APIで定義された特定のMAFバインディング・プロパティを参照することがあります。

式ビルダーを使用してデータバインド・コンポーネントを作成すると、EL式によって、特定のMAFバインディング・プロパティが参照される場合があります。実行時には、これらのバインディング・プロパティによって、データバインドUIコンポーネントのデフォルトの表示方法や、イテレータ・バインディング固有のパラメータなどが定義されます。バインディング・プロパティは、Oracle APIによって定義されます。各バインディング・タイプで使用可能なプロパティの完全なリストは、表15-4を参照してください

特定のプロパティに割り当てられる値は、ページ定義ファイルで定義されます。たとえば、イテレータ・バインディングには、イテレータが一度に表示する行数を指定する、RangeSizeというプロパティがあります。RangeSizeに割り当てられた値は、次の例に示すようにページ定義ファイルで指定されます。

<iterator Binds="ItemsForOrder" RangeSize="25" 
              DataControl="BackOfficeAppModuleDataControl" 
              id="ItemsForOrderIterator" ChangeEventPolicy="ppr"/>

イテレータ間でデータ・プロバイダの状態の保持を有効にする方法

データ・コレクション・インスタンスにアクセスする各ページの最上位レベルのイテレータに、同じRSIName属性を指定することで、データ・コントロールは、そのコントロール用に作成された複数のデータ・プロバイダのインスタンスを持てるようになります。

この機能を使用するには、同じデータ・コレクション・インスタンスにアクセスする各ページの最上位レベル・イテレータ(iterator)に同じRSIName属性を指定します。

次の例は、pageDefファイルのイテレータの階層を示しています。最後の2つのアクセサ・イテレータでは、第2コレクションの従業員オブジェクトとそれらの従業員の電話番号を反復できます。

<iterator Binds="root"
          RangeSize="25"
          DataControl="BusinessManager"
          id="BusinessManagerIterator"
          RSIName="secondCollection" />
<accessorIterator id="companyIterator"/
                  MasterBinding="BusinessManagerIterator"
                  Binds="company"
                  RangeSize="25"
                  DataControl="BusinessManager"
                  BeanClass="mobile.Company"/>
<accessorIterator id="employeesIterator"
                  MasterBinding="companyIterator"
                  Binds="employees"
                  RangeSize="25"
                  DataControl="BusinessManager"
                  BeanClass="mobile.Employee"/>
<accessorIterator id="phoneNumbersIterator"
                  MasterBinding="employeesIterator"
                  Binds="phoneNumbers"
                  RangeSize="25"
                  DataControl="BusinessManager"
                  BeanClass="mobile.PhoneNumber"/>
<accessorIterator id="employeesIterator2"
                  MasterBinding="companyIterator"
                  Binds="employees"
                  RangeSize="25"
                  DataControl="BusinessManager"
                  BeanClass="mobile.Employee"
                  RSIName="secondCollection" />
<accessorIterator id="phoneNumbersIterator2"
                  MasterBinding="employeesIterator2"
                  Binds="phoneNumbers"
                  RangeSize="25"
                  DataControl="BusinessManager"
                  BeanClass="mobile.PhoneNumber" />

バインディング・コンテナを参照する方法

MAFは、アクティブな画面と非アクティブな画面のバインディング・コンテナを参照するために、異なるルートEL式を使用します。MAF AMXバインディング・オブジェクトにアクセスするために、EL式で使用できるプロパティのリストを確認してください。

ルートEL式#{bindings}で、アクティブな画面のバインディング・コンテナを参照できます。式#{data.PageDefName}で、別の画面のバインディング・コンテナを参照できます。MAF AMXバインディング・オブジェクトは、バインディング・コンテナ#{bindings.Name}から名前で参照されます。

表15-4は、実行時に、EL式でMAF AMXバインディング・オブジェクトの値にアクセスするために使用できるプロパティのリストの一部を示しています。プロパティは、アルファベット順に並んでいます。

表15-4 MAFバインディングのランタイムELプロパティ

実行時プロパティ 説明 イテレータ アクション 属性値 ツリー

class

実行時バインディング用のJavaクラス・オブジェクトを戻します。

collectionModel

データのコレクションを公開します。collectionModelにバインドされているコンポーネント内で使用するEL式は、コレクションの各要素の式を解決するrow変数脚注 1を使用して参照できます。

×

×

×

collectionModel.makeCurrent

このバインディングのイテレータ内で、選択した行を現在の行にします。

×

×

×

collectionModel.selectedRow

選択した行への参照を戻します。

×

×

×

currentRow

イテレータが指している現在の行またはデータ・オブジェクト(組込みナビゲーション・アクションなど)への参照を戻します。

×

×

×

currentRow.dataprovider

イテレータが指している現在の行またはデータ・オブジェクトへの参照を戻します。(これはcurrentRowから戻されるものと同じオブジェクトで、構文のみが異なります)。

×

×

×

enabled

アクション・バインディングの状態に応じて、trueまたはfalseを戻します。たとえば、アクション・バインディングは、ユーザーが「先頭へ」、「次へ」、「前へ」、「最後へ」などのナビゲーション・ボタンをクリックした場合に決定される現在位置に基づいて、有効化(true)または無効化(false)されます。

×

×

×

execute

解決されたときに、名前付きアクションまたはmethodActionバインディングを起動します。

×

×

×

format

これはhints.formatのショートカットです。

×

×

hints

バインディングが関連付けられているすべての表示属性について、UIヒントの名前/値ペアのリストを戻します。

×

×

inputValue

バインディングが関連付けられている最初の属性の値を戻します。

×

×

×

items

現在のリストの有効な属性に関連付けられた値のリストを戻します。

×

×

×

label

hintsの子または属性の直接の子として使用できます。バインディングの最初の属性のラベルを戻します(コントロールhintsで指定されている場合)。

×

×

name

PageDef.xmlファイル内で宣言されたバインディングのidを戻します。

rangeSize

イテレータ・バインディングの行セットの範囲サイズを戻します。これにより、データソースからバインドされるデータ・オブジェクトの数を確認できます。

×

×

result

メソッド・アクション・バインディングによりバインドおよび起動されるメソッドの結果を戻します。

×

×

×

updateable

hintsの子または属性の直接の子として使用できます。バインディングが関連付けられている最初の属性が更新可能である場合、trueを戻します。それ以外の場合はfalseを返します。

×

×

viewable

Treeの子として使用できます。このバインディングおよび関連コンポーネントをレンダリングするかどうかを実行時に解決します。

×

×

×

脚注1

EL語句のrowは、コレクション・コンポーネントのコンテキスト内で使用されます。rowは単に、コレクションをレンダリングするときに、MAF AMXバインディング・オブジェクトからアクセスできる属性を含むコレクションの各要素に対する反復変数として機能します。属性とリスト・バインディングには、row変数を使用してアクセスできます。そのような式の構文は、コレクションに含まれないバインディング・オブジェクトへのアクセスに使用される構文と同じで、#{row.bindings.Name.property}のようにrow変数を先頭の語句として追加します。

式ビルダーのカテゴリについて

MAF AMXページの式ビルダーでは、次のカテゴリを使用できます。

バインディング・カテゴリについて

様々なバインディング・タイプでサポートされているプロパティを構成できます。「バインディング」カテゴリでサポートされているバインディングとプロパティを確認してください。

この項では、バインディング・カテゴリで使用できるオプションを示します。bindingsノードとdataノードは、サポートされているバインディングとプロパティの同じセットを表示します。表15-5に、使用できるバインディング・タイプと、各バインディング・タイプでサポートされるプロパティをリストします。securityContextノードは、次のプロパティをサポートしています。

  • authenticated

  • userGrantedPrivilege

  • userInRole

  • userName

次にその例を示します。

#{securityContext.authenticated}
#{securityContext.userGrantedPrivilege['submit_privilege']}
#{securityContext.userInRole[‘manager_role']}
#{securityContext.userName}

表15-5 サポートされるバインディング・タイプ

バインディング・タイプ プロパティ

accessorIterator

class

currentRow: dataProvider

name

rangeSize

action

class

enabled

execute

name

attributeValues

autoSubmit

category

class

controlType

displayHeight

displayHint

displayWidth

filedorder

format

hints: allows.read、allows.update、autoSubmit、category、controlType、displayHeight、displayHint、displayWidth、filedorder、format、label、mandatory、precision、tooltip、updateable

inputValue

items

iteratorBinding

label

mandatory

name

precision

tooltip

updateable

button

autoSubmit

category

class

controlType

displayHeight

displayHint

displayWidth

filedorder

format

hints: allows.read、allows.update、autoSubmit、category、controlType、displayHeight、displayHint、displayWidth、filedorder、format、label、mandatory、precision、tooltip、updateable

inputValue

items

iteratorBinding

label

mandatory

name

precision

tooltip

updateable

invokeAction

always

deferred

iterator

class

currentRow: dataProvider

name

rangeSize

list

autoSubmit

category

class

controlType

displayHeight

displayHint

displayWidth

filedorder

format

hints: format、allows.read、allows.update、autoSubmit、category、controlType、displayHeight、displayHint、displayWidth、filedorder、format、label、mandatory、precision、tooltip、updateable

inputValue

items

iteratorBinding

label

mandatory

name

precision

tooltip

updateable

methodAction

class

enabled

execute

name

operationEnabled

operationInfo

paramsMap

result

methodIterator

class

currentRow: dataProvider

name

rangeSize

searchAction

class

enabled

execute

name

operationEnabled

operationInfo

paramsMap

result

tree

category

class

collectionModel: bindings, makeCurrent, selectedRow, <AttrName>

displayHeight

displayHint

displayWidth

filedorder

format

hints: category、displayHeight、displayHint、displayWidth、filedorder、format、label、mandatory、precision、tooltip、updateable、<AttrName>

iteratorBinding

label

mandatory

name

precision

rangeSize

tooltip

updateable

viewable

variable

class

currentRow: dataProvider

name

variableIterator

class

currentRow: dataProvider

name

マネージドBeanカテゴリについて

この項では、「マネージドBean」カテゴリで使用できるオプションを表示します。

  • applicationScope: 「マネージドBean」のapplicationScopeノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーションスコープのマネージドBeanなど)。

  • pageFlowScope: 「マネージドBean」のpageFlowScopeノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロースコープのマネージドBeanなど)。

  • viewScope: 「マネージドBean」のviewScopeノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュースコープのマネージドBeanなど)。

MAFランタイムでは、自身をマネージドBeanプロパティの変更通知のリスナーとして登録することによって、Beanプロパティを参照するUIコンポーネントにバインドされたEL式が、プロパティの値が変更されたときに自動的に更新されるようにします。これらの通知をソースとして参照するには、Beanのプロパティ・アクセッサにコードを追加する必要があります。Beanのプロパティ・アクセッサから、通知をソースとして参照するために必要なコードを自動的に生成するには、「アクセッサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェック・ボックスを選択します(図を参照)。

図15-2 プロパティの変更時にリスナーに通知

図15-2の説明が続きます
「図15-2 プロパティの変更時にリスナーに通知」の説明

ELを通じて単にBeanメソッドまたはプロパティを参照する場合、このコードを追加する必要はありませんが、Beanに格納された値が変化する場合や、特にその変更が、1つ以上のプロパティ値を変更するBeanメソッドの実行による二次的な影響など、間接的なものである場合、それらの値に依存するEL式のアクティブ・フォームへのレンダリングを最新の状態に保つ必要があります。プロパティの変更とPropertyChangeSupportクラスについては、「データ変更イベントについて」を参照してください。

次の例は、プログラムで別のマネージドBean属性にバインドされた値を取得する方法を示しています。

public void someMethod() {
   Object value = AdfmfJavaUtilities.getELValue(
                       "#{applicationScope.MyManagedBean.someProperty}");
   ...
}

Oracle Mobile Application Framework Java APIリファレンスで説明されているAdfmfJavaUtilitiesクラスには、EL式の管理に役立つ他のメソッドが用意されています。例としては、isEvaluationExpressionsetELValueがあります。

注意:

機能のapplicationScope内でマネージドBeanを宣言し、デザインタイムで別の機能のELを通じてそのBeanを参照しようとすると、そのデザインタイムで無効なELに関する警告が表示されます。この警告は、デザインタイムがそのBeanの現在のプロジェクトで参照を検出できないことが原因で表示されます。そのBeanを実行時に参照できるのは、Beanが宣言されている最初の機能に初めてアクセスし、さらに別の機能のELを通じてアクセスする前にそのBeanをインスタンス化した場合のみです。これは、Name属性の値をノード・ラベルとして使用するPreferenceValue要素には当てはまりません。

モバイル・アプリケーション・フレームワークのオブジェクト・カテゴリについて

「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリには、MAFで定義されたオブジェクト、ELを使用して参照できるオブジェクトが含まれます。

「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリには、オブジェクト・スコープなどのELを使用して参照できるMAFに定義されている様々なオブジェクトが一覧表示されます。

MAFの変数とマネージドBeanの参照は、変数の存続期間と可視性を決定する様々なオブジェクト・スコープ内で定義されます。これらのスコープには、可視性が高い順に、アプリケーション・スコープ、ページ・フロー・スコープおよびビュー・スコープがあります。「オブジェクト・スコープ・ライフサイクルについて」を参照してください。

スコープを含むこのような変数に加えて、MAFでは、デバイス・プロパティとアプリケーション・プリファレンスに関する情報を公開できるスコープが定義されています。これらのスコープによって、アプリケーション・レベルの存続期間と可視性が決まります。

「モバイル・アプリケーション・フレームワーク・オブジェクト」カテゴリで使用できるものは、次のとおりです。

  • applicationScope: applicationScopeノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーション・スコープのマネージドBeanなど)。アプリケーション・スコープで定義されたEL変数は、アプリケーションが存続するかぎり、機能の境界にまたがって使用できます。

  • deviceScope: deviceScopeノードは、デバイスのプロパティに関する情報を公開します。deviceScopeは、アプリケーション・レベルの存続期間および可視性を持ちます。

  • feature: featureノードは、機能レベルのデータを公開します。featureオブジェクトは、dataControlContextDepthおよびmaximumDataControlContextDepthプロパティを公開します。#{feature.dataControlContextDepth}および#{feature.maximumDataControlContextDepth}を使用して、これらのプロパティの値を取得できます。これらの2つのプロパティは読取り専用です。

  • pageFlowScope: pageFlowScopeノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロー・スコープのマネージドBeanなど)。ページ・フロー・スコープで定義されたEL変数は、機能が存続するかぎり、単一の機能の境界内で使用できます。

  • preferenceScope: preferenceScopeノードには、アプリケーションと機能のすべてのプリファレンスが含まれます。

    プリファレンス要素では、PreferenceValue要素を除き、Id属性の値を式ビルダーのノード・ラベルとして使用します。PreferenceValue要素では、Name属性の値を式ビルダーのノード・ラベルとして使用します。

    注意:

    EL式の文字列トークンにドット(.)や特殊文字またはdefaultなどの予約語が含まれている場合、式ビルダーではそのような文字列トークンを一重引用符と大カッコで囲みます。機能IDやプリファレンス・コンポーネントIDにドットが含まれている場合、式ビルダーでは、ドットによって区切られたIDの各部分を別のプロパティとしてpreferenceScope階層に表示します。生成された式でも、ドットによって区切られたIDの各部分を別のプロパティとして認識します。

    preferenceScopeのいくつかのサンプルEL式を次に示します。

    "#{preferenceScope.feature.oracle.hello.SampleGroup1.label}"
    "#{preferenceScope.application.OracleMobileApp.Edition['default']}"
    
  • viewScope: このノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュー・スコープのマネージドBeanなど)。ビュー・スコープの名前空間で定義されたEL変数は、ビューが存続するかぎり、機能の単一ページの境界内で使用できます。

  • row: rowオブジェクトは、collectionModelに含まれる単一のプロバイダへのショートカットである中間変数です。その名前は、親コンポーネントのvar属性の値です(List ViewやCarouselなど)。

    注意:

    AdfmfJavaUtilities.evaluateELExpressionを使用して、#{row}、またはrowのプロパティを評価することはできません。これらの式はnull値を戻します。

  • viewControllerBundle

    これは、プロジェクト・レベルで定義されているリソース・バンドルを指すリソース・バンドル変数の名前です。このノードが表示されるのは、amx:loadBundle要素が削除され、リソース・バンドルが作成された後のみです。このノードの名前は、amx:loadBundleの変数名によって異なります。このノードには、バンドル内で宣言されたすべての文字列が表示されます。

    次の例は、viewControllerBundleのAMXコードの例を示しています。

    <amx:loadBundle basename="mobile.ViewControllerBundle" var="viewcontrollerBundle"/>

ELイベントについて

ELイベントにより、MAF AMX UIの動作が決まります。これは、このイベントが共通語句を含む式の更新を同期するためです。基礎となる式の値が変化すると、その値のすべてのリスナーに向けたイベントが生成されます。

ELイベントは、共通語句を含む式が相互に同期して更新できるようにするため、MAF AMX UIの動作において重要な役割を果たします。

EL式は、様々なコンテキストで値を参照できます。次の例は、各コンポーネントがapplicationScope値に関連付けられた2つの入力数値スライダ・コンポーネントの作成方法を示しています。出力テキストでは、ELを使用して単純な追加式を計算結果とともに表示します。フレームワークでは、出力テキスト・ラベル内のEL式を解析するときに、その式に2つの値への参照が含まれていることを確認し、それら2つの値に基づく出力テキストのイベント・リスナー(「イベント・リスナーの使用方法」を参照)を作成します。基礎となる式の値が変化すると、イベントがその値のすべてのリスナーに対して生成されます。

注意:

(スコープ・オブジェクトではなく)マネージドBeanのプロパティを参照している場合、リスナーを追加する必要があります。「マネージドBeanカテゴリについて」を参照してください。

<amx:inputNumberSlider id="slider1" label="X" value="#{applicationScope.X}"/>
<amx:inputNumberSlider id="slider2" label="Y" value="#{applicationScope.Y}"/>
<amx:outputText id="ot1" value="#{applicationScope.X} + 
       #{applicationScope.Y} = #{applicationScope.X + applicationScope.Y}"/>

前述の例では、2つのコンポーネントがそれぞれ1つの値を更新し、1つのコンポーネントが両方の値を使用します。次の例は、いずれかの既存の値を参照する3つ目の入力数値スライダ・コンポーネントが追加された場合、動作は同じになることを示しています。

<amx:inputNumberSlider id="slider1" label="X" value="#{applicationScope.X}"/>
<amx:inputNumberSlider id="slider2" label="Y" value="#{applicationScope.Y}"/>
<amx:outputText id="ot1" value="#{applicationScope.X} + 
       #{applicationScope.Y} = #{applicationScope.X + applicationScope.Y}"/>
<amx:inputNumberSlider id="slider3" label="X" value="#{applicationScope.X}"/>

前述の例では、いずれかの入力数値スライダ・コンポーネントが#{applicationScope.X}を更新すると、もう一方が出力テキストとともに自動的に更新されます。

EL式のマネージドBean内での使用方法

JDeveloperが提供するEL式を使用します。新しいEL式を作成して、マネージドBean内でEL式のアクセス、設定、または呼び出しを実行します。

必要なEL式はJDeveloperで作成され、作成されない式は式ビルダーを使用して作成できますが、マネージドBean内でEL式にアクセスしたり、EL式を設定または起動する必要がある場合もあります。

次の例に、EL式への参照を取得し、適合するオブジェクトを返す(または作成する)方法を示します。

public static Object resolveExpression(String expression) {
  return AdfmfJavaUtilities.evaluateELExpression(expression);
}

次の例に、メソッド式を解決する方法を示します。

public static Object resloveMethodExpression(String expression,
                                             Class returnType,
                                             Class[] argTypes,
                                             Object[] argValues) {
  MethodExpression methodExpression = AdfmfJavaUtilities.getMethodExpression(expression,
                                                                             returnType,
                                                                             argTypes);
  return methodExpression.invoke(AdfmfJavaUtilities.getAdfELContext(), argValues);
}

次の例に、マネージドBeanに新規オブジェクトを設定する方法を示します。

public static void setObject(String expression, Object newValue) {
  AdfmfJavaUtilities.setELValue(expression, newValue);
}

マネージドBeanの作成および使用

マネージドBeanは、構成ファイルによってアプリケーションに登録されたJavaクラスです。これが解析されると、Beanのプロパティとメソッドへのアクセスを提供します。

マネージドBeanは、様々な構成ファイルを使用してアプリケーションに登録するJavaクラスです。MAFアプリケーションを起動すると、これらの構成ファイルが解析されてBeanが使用可能になり、EL式で参照できるため、Beanのプロパティとメソッドにアクセスできます。マネージドBeanが初めて参照されたときにまだ存在していない場合、マネージドBean作成機能によりBeanのデフォルトのコンストラクタ・メソッドがコールされて、Beanがインスタンス化されます。また、プロパティが宣言されると、宣言されたデフォルトの値が移入されます。

多くの場合、マネージドBeanは、フロント・エンドで処理することが最適なイベントやデータ操作を処理します。マネージドBeanの使用方法の詳細は、http://www.oracle.com/technetwork/java/index.htmlのJava EEチュートリアルを参照してください。

ベスト・プラクティス:

マネージドBeanを使用して、現在のユーザーなどのブックキーピング情報のみを格納します。すべてのアプリケーション・データおよび処理データは、アプリケーションのビジネス・レイヤーのロジックによって処理される必要があります。

注意:

EL式は、Beanを参照するために明示的にスコープを含める必要があります。たとえば、pageFlowScopeスコープからMyBeanマネージドBeanを参照するには、#{pageFlowScope.MyBean}という式になります。

JDeveloperでのマネージドBeanの作成方法

マネージドBeanを作成して、MAFアプリケーションに登録する手順を使用してください。

adfc-mobile-config.xmlファイルに「概要」エディタを使用して、マネージドBeanの作成とMAFアプリケーションへの登録を同時に行うことができます。

始める前に:

マネージドBeanに関する知識が役立つ場合があります。「マネージドBeanの作成および使用」を参照してください。

マネージドBeanの作成および登録手順:

  1. 「アプリケーション」ウィンドウで、adfc-mobile-config.xmlをダブルクリックします。
  2. 「エディタ」ウィンドウで、「概要」タブをクリックします。
  3. 「概要」エディタで、「マネージドBean」ナビゲーション・タブをクリックします。

    adfc-mobile-config.xmlファイル用のエディタを図に示します。

    図15-3 adfc-mobile-config.xmlファイルのマネージドBean

    図15-3の説明が続きます
    「図15-3 adfc-mobile-config.xmlファイルのマネージドBean」の説明
  4. 「追加」アイコンをクリックして「マネージドBean」表に行を追加します。
  5. 「マネージドBeanの作成」ダイアログで値を入力します。ダイアログの使用の詳細が必要な場合は、「ヘルプ」をクリックします。JDeveloperでクラス・ファイルを作成する場合は、「クラスが存在しない場合は生成」オプションを選択します。リスナー・プロパティのいずれかを選択して「編集」ボタンをクリックすることで、「プロパティ」ウィンドウから「マネージドBeanの作成」ダイアログを開くこともできます。そこから、新しいマネージドBeanと対応するメソッドを作成できます。

    注意:

    マネージドBeanを登録するスコープまたは値を格納するスコープを決める場合、可能なかぎり狭いスコープを常に使用するようにします。「オブジェクト・スコープ・ライフサイクルについて」を参照してください。

  6. オプションでBeanに管理プロパティを追加できます。Beanがインスタンス化される際、指定した値が管理プロパティに設定されます。「マネージドBean」表でBeanを選択した状態で「新規」アイコンをクリックし、「管理プロパティ」表に行を追加します。「プロパティ」ウィンドウで、プロパティ名を入力します(他のフィールドはオプションです)。

    注意:

    このエディタを使用して管理プロパティを宣言することはできますが、対応するコードはJavaクラスで生成されません。適切なタイプのプライベート・メンバー・フィールドを作成し、コード・エディタのポップアップ・メニューの「アクセッサの生成」メニュー項目を選択して、これらのBeanプロパティに対応するgetおよびsetメソッドを生成することにより、コードを追加する必要があります。

JDeveloperを使用してマネージドBeanを作成する場合の処理

JDeveloperでマネージドBeanを作成してJavaファイルを生成すると、IDEによってスタブ・クラスが作成されます。EL式が特定のスタブ・クラス名を使用して参照できるように、ページにロジックを追加します。

マネージドBeanを作成する際、Javaファイルを生成するよう選択すると、指定された名前とデフォルト・コンストラクタを使用してスタブ・クラスが自動的に作成されます。次の例に、ビュー・パッケージに格納されたMyBeanクラスに追加されるコードを示します。

package view;
 
public class MyBean {
    public MyBean() {
    }
}

ここでページに必要なロジックを追加する必要があります。このロジックは、マネージドBeanのmanaged-bean-nameを参照するEL式を使用して参照できます。たとえば、my_beanマネージドBeanのmyInfoプロパティにアクセスする場合、EL式は次のようになります。

#{my_bean.myInfo}

JDeveloperでは、managed-bean要素もadfc-mobile-config.xmlファイル(または編集されるタスク・フロー・ファイル)に追加されます。次の例に、MyBeanクラスに対して作成されたmanaged-bean要素を示します。

<managed-bean>
  <managed-bean-name>my_bean</managed-bean-name>
  <managed-bean-class>view.MyBean</managed-bean-class>
  <managed-bean-scope>application</managed-bean-scope>
</managed-bean>

データ・コントロールを使用したビジネス・サービスの公開

データ・コントロールは、ビジネス・サービスにUIコンポーネントを宣言的にバインドするために作成します。「データ・コントロールの作成」メニュー・オプションを使用してデータ・コントロールを生成します。

アプリケーションのサービスの準備ができたら、JDeveloperを使用して、UIコンポーネントとサービスとの宣言的バインドに必要な情報を提供するデータ・コントロールを作成できます。

データ・コントロールの生成には、「データ・コントロールの作成」メニュー・アイテムを使用します。データ・コントロールは、1つ以上のXMLメタデータ・ファイルで構成され、これらのファイルでは、実行時にバインディングと連動するサービスの機能が定義されます。データ・コントロールは、基礎となるサービスと連動します。

データ・コントロールの作成方法

アプリケーション・ワークスペースを作成して、ビジネス・サービスを追加してから、データ・コントロールの作成手順を使用してください。また、データ・コントロールの基になるクラスまたはオブジェクトのコンテキスト・メニューを使用してデータ・コントロールを作成することもできます。

アダプタ・ベースのデータ・コントロールは、JDeveloperの「アプリケーション」ウィンドウ内で作成します。

始める前に:

データ・コントロール使用の一般的な知識があると役立ちます。「データ・コントロールを使用したビジネス・サービスの公開」を参照してください。

次のタスクを完了する必要があります。

  • アプリケーション・ワークスペースを作成し、データ・コントロールの基礎にするビジネス・サービスを追加します。アプリケーション・ワークスペースの作成の詳細は、「MAFアプリケーションの作成」を参照してください。

データ・コントロールを作成する手順は、次のとおりです。

  1. アプリケーション・ワークスペース内でデータ・モデル・プロジェクトの最上位ノードを右クリックして、「新規」を選択し、「ギャラリから」を選択します。
  2. 「新規ギャラリ」で、「ビジネス層」を展開し、「データ・コントロール」を選択して、作成するデータ・コントロールのタイプを選択し、「OK」をクリックします。
  3. ウィザードの残りのステップを完了します。

注意:

場合によっては、データ・コントロールの基礎にするクラスまたはオブジェクトを右クリックし、「データ・コントロールの作成」を選択することによってデータ・コントロールを作成できます。

データ・コントロール作成時のプロジェクト内の処理

JDeveloperは、概要エディタで開いているデータ・コントロールの定義ファイルを作成して、「データ・コントロール」パネルにファイルの階層を表示します。

データ・コントロールを作成すると、JDeveloperによってデータ・コントロール定義ファイル(DataControls.dcx)が作成され、概要エディタでファイルが開き、ファイルの階層が「データ・コントロール」パネルに表示されます。このファイルにより、データ・コントロールがサービスおよびバインディングと直接連動して動作することが可能になります。

エディタ・ウィンドウの「ソース」タブをクリックすることによって、対応するXMLファイルからのコードを表示できます。

DataControls.dcx概要エディタ

データ・コントロール・オブジェクトの階層とデータ・モデルの公開メソッドは、DataControls.dcxファイルの概要エディタに表示されます。このエディタを使用して、データ・コントロール・オブジェクトの設定を編集します。

DataControls.dcxファイルの概要エディタは、データ・コントロール・オブジェクトの階層と、データ・モデルの公開メソッドを表示します。

概要エディタおよび「データ・コントロール」パネルで使用されるアイコンの説明は、表15-6を参照してください。

データ・コントロール・オブジェクトの設定を変更するには、オブジェクトを選択し、「編集」アイコンをクリックします。「データ・コントロールの編集方法」を参照してください。

概要エディタでのDataControls.dcxファイルを図に示します。

図15-4 概要エディタでのDataControls.dcxファイル

図15-4の説明が続きます
「図15-4 概要エディタでのDataControls.dcxファイル」の説明
データ・コントロール・パネル

「アプリケーション」ウィンドウに、「データ・コントロール」パネルが表示されます(データ・コントロールの作成後)。「データ・コントロール」パネルからノードをドラッグして、データバインドされたUIコンポーネントをページに作成します。

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

図15-5 「データ・コントロール」パネル

図15-5の説明が続きます
「図15-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: パラメータとして渡された主キーの属性値を使用して行の検索を試行します。検出されると、その行が現在の行になります。

データ・コントロールのaddXXXおよびremoveXXXメソッド

ほとんどの組込み操作は自動的に動作しますが、addXXXメソッドとremoveXXXメソッドを使用するCreateDeleteなどの組込み操作が動作するには、いくつかのメソッド・ハンドラの追加が必要になります。addXXXメソッドとremoveXXXメソッドは、自動的にコレクションをリフレッシュして、データ変更イベントをトリガーします。

組込み操作のほとんどは、コレクションに対して自動的に実行されます。操作の中には、実行するために、開発者がメソッド・ハンドラを作成する必要があるものがあります。Create操作を使用するには、開発者がaddXXXのメソッド・ハンドラを作成する必要があります。Create操作は、現在のコレクションにレコードを挿入するため、CreateInsertの操作も実行します。MAFコレクションにはCreateInsert操作は使用されません。同様に、Delete操作を実行するには、開発者がremoveXXXのメソッド・ハンドラを作成する必要があります。

addXXXおよびremoveXXXメソッドは、自動的にコレクションをリフレッシュし、データ変更イベントを起動するため、開発者はプロバイダを排他的にリフレッシュする必要はありません。データ・オブジェクトは、組込み操作のCreateおよびDeleteで使用されるaddXXXメソッドとremoveXXXメソッドなどの、データ・コントロールの組込み操作で使用されます。

  • addXXX: このメソッドは、データ・コントロール・フレームワークに一意のIDを返します。たとえば、次のようになります。
    public void addDeptBean(DeptBean dept)
    {
    deptCollection.add(dept);
    }
    ここで、DeptBeanはクラス名、deptはオブジェクトです。
  • removeXXX: このメソッドはオブジェクトを削除します。たとえば、次のようになります。
    public void removeDeptBean(DeptBean dept)
    {
    deptCollection.remove(dept);
    }
    ここで、deptDeptBeanクラスのオブジェクトです。

CRUDDemoサンプル・アプリケーションは、開発コンピュータ上のjdev_install/jdeveloper/jdev/extensions/oracle.maf/Samplesディレクトリ内のPublicSamples.zipファイルにあります。

「データ・コントロール」パネルでのデータバインドされたUIコンポーネントの作成

「データ・コントロール」パネルからデータ・コントロール・オブジェクトをドラッグして、特定のUIコンポーネントを作成するページのエディタにドロップします。JDeveloperは、選択したデータ・コントロールにコンポーネントをバインドするために必要なコードとオブジェクトを自動的に作成します。

「データ・コントロール」パネルでは、各データ・コントロール・オブジェクトが特定のアイコンで表されます。表15-6は、各アイコンが表すデータ・コントロール・オブジェクト、「データ・コントロール」パネルの階層内で表示される場所、そのアイコンを使用して作成できるコンポーネントを示しています。

表15-6 「データ・コントロール」パネルのアイコンおよびオブジェクト階層

アイコン 名前 説明 作成できるコンポーネント
このイメージは「データ・コントロール」のアイコンを示しています。

データ・コントロール

データ・コントロールを表します。

他のオブジェクトのコンテナとして機能し、作成には使用されません。

このイメージは「コレクション」のアイコンを示しています。

コレクション

アクセッサ・メソッドまたは操作から返される名前付きデータ・コレクションを表します。

フォーム、表、グラフ、ツリー、レンジ・ナビゲーションの各コンポーネント、マスター/ディテール・コンポーネントおよび選択リストの各コンポーネント。

このイメージは「構造化された属性」のアイコンを示しています。

構造化された属性

Javaプリミティブ・タイプ(属性として示される)または任意のタイプのコレクションのいずれでもない、戻りオブジェクトを示します。

フォーム、ラベル、テキスト・フィールド、日付、値リストおよび選択リストの各コンポーネント。

このイメージは「属性」のアイコンを示しています。

属性

オブジェクト内の個別のデータ要素(行の属性など)を表します。

ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。

このイメージは「キー属性」のアイコンを示しています。

キー属性

データ・コントロール構造ファイル、またはビジネス・サービス自体で、主キー属性として宣言されたオブジェクト属性を表します。

ラベル、テキスト・フィールド、日付、値リスト、および選択リストの各コンポーネント。

このイメージは「メソッド」のアイコンを示しています。

メソッド

データ・コントロールのメソッドまたは操作、またはその公開された構造のいずれかを表し、パラメータの受入れや、ビジネス・ロジックの実行を行ったり、オプションで単一の値、構造、またはコレクションを戻したりすることができます。

コマンド・コンポーネント。

パラメータを受け入れるメソッドの場合: コマンド・コンポーネントおよびパラメータ付きフォーム。

このイメージは「メソッド戻り値」のアイコンを示しています。

メソッド戻り値

メソッドまたはその他の操作から返されたオブジェクトを表します。戻されたオブジェクトは、単一の値またはコレクションです。

メソッド戻りは、これを戻すメソッドの下に、子として表示されます。メソッド戻りの下に子として表示されるオブジェクトは、コレクションの属性、親コレクションに関連するアクションを実行する他のメソッド、または親コレクションで実行できる操作などです。

単一の値の場合: テキスト・フィールドおよび選択リスト。

コレクションの場合: フォーム、表、ツリー、レンジ・ナビゲーションの各コンポーネント。

単一値のメソッド戻り値がドロップされると、メソッドはフレームワークにより自動的に起動されなくなります。メソッドを起動するために、対応するメソッドをボタンとしてドロップできます。フォームがタスク・フローの一部の場合、メソッドを起動するためのメソッド・アクティビティを作成できます。

このイメージは「操作」のアイコンを示しています。

操作

親オブジェクトに対してアクションを実行する、組込みデータ・コントロール操作を表します。

ボタンおよびリンクなどのUIコマンド・コンポーネント。

このイメージは「パラメータ」のアイコンを示しています。

パラメータ

メソッドまたはその下に表示される操作によって宣言されたパラメータ値を表します。

ラベル、テキストおよび選択リストの各コンポーネント。

「データ・コントロール」パネルの使用方法

「データ・コントロール」パネルには、アプリケーションを構築するための事前定義済のUIコンポーネントのセットが用意されています。コンテキスト・メニューを使用してUIコンポーネントを作成する手順を使用してください。コンテキスト・メニューは、このパネルからデータ・コレクションを選択すると表示されます。

JDeveloperは、ドロップするデータ・コントロール項目に対してそれぞれ選択できるUIコンポーネントの事前定義済セットを備えています。

始める前に:

「データ・コントロール」パネルの各種オブジェクトに関する知識があると役立つ場合があります。「データ・コントロール」パネルでのデータバインドされたUIコンポーネントの作成を参照してください。

次のタスクを完了する必要があります。

「データ・コントロール」パネルを使用してUIコンポーネントを作成するには:

  1. 「データ・コントロール」パネルで項目を選択し、ページのビジュアル・エディタにその項目をドラッグします。パネルの各項目の定義は、表15-6を参照してください。
  2. ポップアップ・メニューから、UIコンポーネントを選択します。

    「データ・コントロール」パネルから項目をドラッグしてページにドロップすると、ドロップした項目に使用できるすべてのデフォルトUIコンポーネントのポップアップ・メニューが表示されます。表示されるコンポーネントは、プロジェクト内のライブラリに基づきます。

    「データ・コントロール」パネルのデータ・コレクションがページにドロップされる際に表示されるポップアップ・メニューを図に示します。

    図15-6 「データ・コントロール」パネルからのコンポーネントのドロップ

    図15-6の説明が続きます
    「図15-6 「データ・コントロール」パネルからのコンポーネントのドロップ」の説明

    ポップアップ・メニューから選択したコンポーネントに応じて、そのコンポーネントの外観を定義するためのダイアログが自動的に表示されます。たとえば、ポップアップ・メニューから 「フォーム」を選択すると、「フォーム・フィールドの編集」ダイアログが開きます。コンポーネントを選択すると、JDeveloperではビジュアル・エディタのページにそのUIコンポーネントが挿入されます。

    デフォルトで選択されたUIコンポーネントはまず、対応するビジネス・オブジェクト上で設定されているUIヒントで決定されます。UIヒントが設定されていない場合、JDeveloperでは標準のフォームおよび表の入力コンポーネントと読取り専用のフォームおよび表の出力コンポーネントが使用されます。リストのコンポーネントは、データ・コントロール・オブジェクトをドロップするときに選択するリストの型に基づいて決定されます。

    デフォルトでは、データ・コントロールの使用時に作成されるUIコンポーネントは、MAFデータ・コントロール内の属性にバインドされ、次のような組込み機能を装備できます。

    • データバインド・ラベル

    • ツールチップ

    • 書式設定

    • 基本的なナビゲーション・ボタン

    • 検証(検証規則が特定の属性にアタッチされている場合。)

    デフォルトのコンポーネントは、そのまま使用しても十分機能します。ただし、特定のニーズに合せて変更することができます。

    ヒント:

    ページで使用するMAFデータバインド・コンポーネントのタイプを変更する場合は、ビジュアル・エディタまたは構造ウィンドウを使用してそのコンポーネントを削除し、「データ・コントロール」パネルから新しいコンポーネントをドラッグ・アンド・ドロップする方法が最も簡単です。データバインドされたコンポーネントをページから削除するときにビジュアル・エディタまたは構造ウィンドウを使用する場合、ページ定義ファイルの関連するバインディング・オブジェクトが他のどのコンポーネントからも参照されていなければ、これらのバインディング・オブジェクトはJDeveloperによって自動的に削除されます(ソース・エディタを使用する場合は、バインディング・オブジェクトの自動削除は行われません)。

「データ・コントロール」パネルの使用時の処理

「データ・コントロール」パネルを使用してアプリケーションを構築すると、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}を使用してアクセス可能)です。

次の図に示すように、MAFでは、アプリケーション、DataBindings.cpxおよびページ定義ファイルからバインディング・コンテキストが作成されます。設計時に使用可能なデータ・コントロールは、すべてのDataControls.dcxファイルとワークスペース内のすべてのアプリケーション・モジュールの集合体によって定義されますが、実行時にアプリケーションで使用可能なデータ・コントロールは、DataBindings.cpxファイルで定義されます。DataBindings.cpxファイルは、アプリケーションのページで使用されているデータ・コントロールをすべて一覧表示し、ページ定義ファイルに定義されたバインディング・オブジェクトが格納されているバインディング・コンテナをWebページのURLにマップします。ページ定義ファイルは、アプリケーション・ページで使用するバインディング・オブジェクトを定義します。各ページにページ定義ファイルが1つあります。

バインディング・コンテキストには、これらのオブジェクトの実際のインスタンスは含まれていません。かわりに、マップには必要に応じてデータ・コントロールまたはバインディング・コンテナ・オブジェクトになる参照が含まれます。たとえば、オブジェクト(ページ定義など)がアプリケーションから解放されるか、タスク・フローが終了するか、リクエストの終了時にバンディング・コンテナまたはデータ・コントロールが解放されると、データ・コントロールおよびバンディング・コンテナは参照オブジェクトに戻ります。DataBindings.cpxファイルの詳細は、「生成されるドラッグ・アンド・ドロップ・アーティファクトに関する必知事項」を参照してください。

図15-7 ファイル・バインディング・コンテキストの実行時の使用

図15-7の説明が続きます
「図15-7 ファイル・バインディング・コンテキストの実行時の使用」の説明

注意:

コンポーネントを構成するときは、使用するバインディング・スタイルを十分に考慮してください。より具体的に言うと、標準的なバインディングをマネージドBeanバインディングと組み合せると、解釈を誤った動作が発生することがよくあります。これは、バインディング・インフラストラクチャとマネージドBeanインフラストラクチャとの間でクラス・インスタンスが一致する可能性が低いためです。バインディングが混在すると、UIに直接リンクされていないインスタンスの動作がコールされる場合があります。

MAFでのバインディングの使用の詳細は、次を参照してください。

データ・コントロールの構成

データ・コントロールを作成してから、そのコントロールの要素を格納するデータ・コントロール構造ファイルを作成して変更します。.dcxファイルの概要エディタを使用して、データ・コントロール構造ファイルを生成します。

データ・コントロールを作成すると、データ・コントロールについて、値と動作の標準的なセットが設定されます。たとえば、属性のラベルのクライアントでの表示方法がデータ・コントロールによって決定されます。データ・コントロールの要素に対応するデータ・コントロール構造ファイルを作成および変更することによって、これらの値と動作を構成できます。まず、.dcxファイルの概要エディタを使用して、データ・コントロール構造ファイルを生成します。

データ・コントロールの編集方法

データ・コントロールを作成してから、データ・コントロールを編集する手順を使用してください。

データ・コントロールを構成可能にするには、DataControls.dcxファイルの概要エディタを使用し、データ・コントロールに含まれるオブジェクトに対応するデータ・コントロール構造ファイルを作成します。個別のデータ・コントロール構造ファイルを編集できるようになります。

始める前に:

データ・コントロール構成の一般的な知識があると役立ちます。「データ・コントロールの構成」を参照してください。

次のタスクを完了する必要があります。

データ・コントロールを編集するには:

  1. 「アプリケーション」ウィンドウで、DataControls.dcxをダブルクリックします。
  2. 概要エディタで、構成するオブジェクトを選択し、「編集」アイコンをクリックしてデータ・コントロール構造ファイルを生成します。

    図15-8 データ・コントロール・レジストリの「編集」ボタン

    図15-8の説明が続きます
    「図15-8 データ・コントロール・レジストリの「編集」ボタン」の説明
  3. データ・コントロール構造ファイルの概要エディタで、必要な変更を加えます。

データ・コントロール編集時の処理

データ・コントロールを編集すると、JDeveloperにより、影響を受けたコレクションのメタデータが含まれているデータ・コントロール構造ファイルが作成され、そのファイルが概要エディタで開かれます。

このファイルには、そのコレクション固有のデータ・コントロールの構成データ(データ・オブジェクトに対して指定したUIヒントまたはバリデータなど)が保存されています。

データ・コントロール構造ファイルのベース名は、対応するデータ・オブジェクトのものと同じです。たとえば、Customer.javaエンティティBeanに対応するコレクション・ノードが選択されている状態で「編集」アイコンをクリックすると、データ・コントロール構造ファイルの名前はCustomer.xmlとなります。データ・コントロール構成ファイルはBeanクラスのパッケージに対応するパッケージに生成され、パッケージ名にpersdefが付加されます。たとえば、Customer.java Beanがmodelパッケージ内にある場合、Customer.xmlデータ・コントロール定義ファイルはpersdef.modelパッケージ内に生成されます。データ・コントロール構成ファイルが生成された後、概要エディタを使用してそのファイルをさらに構成できます。

データ・コントロール構造ファイルには、次の情報が含まれます。

  • 属性: サービスのすべての属性を表します。たとえば、エンティティBeanの場合は、データベース列にマップされたBeanプロパティごとに属性が存在します。また、一時属性も追加できます。これらの属性のUIでの表示方法を定義するUIヒントを設定できます。属性値が必須か、一意である必要があるか、表示可能かどうかなどの他のプロパティを設定することもできます。詳細は、「属性の操作」を参照してください。

    「属性の検証」で説明しているように、属性の検証を設定したり、カスタム・プロパティを作成することもできます。

  • アクセッサ: 結果セットを返すデータ・コントロール要素を表します。

  • 操作: データ・コントロールの組込み操作で使用されるデータ・オブジェクト上のメソッドを表します。たとえば、それぞれ「作成」および「削除」組込み操作で使用されるaddおよびremoveメソッドなどです。

Item Beanのデータ・コントロール構造ファイルを図に示します。

図15-9 概要エディタでのデータ・コントロール構造ファイル

図15-9の説明が続きます
「図15-9 概要エディタでのデータ・コントロール構造ファイル」の説明

注意:

データ・コントロール構造ファイルの概要エディタには、データ・オブジェクトに関連付けられているすべての属性、アクセッサおよび操作が表示されます。ただし、データ・コントロール構造ファイルのXMLソースには、編集した要素の定義のみが含まれます。基本要素は、データ・オブジェクトからイントロスペクションされます。また、基礎となるデータ・オブジェクトに変更を加えると、データ・コントロールはそれらの変更を継承します。

データ・コントロールのMDSカスタマイズに関する必知事項

データ・コントロール構造ファイルは、データ・コントロール内のオブジェクトをOracle Metadata Servicesのカスタマイズに使用できるようにする場合に、そのオブジェクトに対して必要になります。データ・コントロール・オブジェクトごとにメタデータを編集および追加して、そのオブジェクト用のデータ・コントロール構造ファイルが生成されるようにします。

データ・コントロールに含まれるすべてのオブジェクトをOracle Metadata Services (MDS)カスタマイズ可能にする必要がある場合は、パッケージされたアプリケーションにこれらのオブジェクトのデータ・コントロール構造ファイルが含まれている必要があります。

アダプタ・フレームワークに基づくデータ・コントロールを作成する際には、データ・コントロール構造ファイルはデフォルトでは生成されません。これは、特定のオブジェクトにメタデータを追加しない場合、データ・コントロールにこれらのファイルは必要ないからです。「データ・コントロールの編集方法」で説明されているように、通常、データ・コントロール構造ファイルは、宣言型のメタデータ(UIヒントやバリデータなど)をそのオブジェクトに追加するためにデータ・コントロールを編集するときにのみ、データ・コントロール・オブジェクト用に生成されます。各データ・コントロール・オブジェクト用のデータ・コントロール構造ファイルを作成するには、データ・コントロール・オブジェクトごとにその手順を繰り返す必要があります。

「MDSを使用したMAFアプリケーションのアーティファクトのカスタマイズ」を参照してください。

属性の使用

データ・コントロールが作成されていて、オブジェクトのデータ・コントロール構造ファイルが生成されていると、データ・オブジェクトの持続属性の機能を構成できます。データ・コントロール構造ファイルの概要エディタの「属性」ページを使用して、プロパティを構成します。

ビジネス・サービスのデータ・コントロールを作成する際、個々のデータ・オブジェクトに作成するデータ・コントロール構造ファイルで宣言的にデータ・オブジェクトの永続属性の機能を拡張できます。たとえば、UIコンポーネントの属性のデフォルト表示を制御する検証ルールを作成し、UIヒントを設定できます。

これらのプロパティはデータ・コントロール構造ファイルの概要エディタの「属性」ページで設定します。データ・コントロール構造ファイルの作成の詳細は、「データ・コントロールの編集方法」を参照してください。

属性を主キーとして指定する方法

データ・オブジェクトのデータ・コントロール構造ファイルでは、そのデータ・オブジェクトの主キーとして属性を指定できます。設定された主キーが継承されていないデータ・オブジェクトに、主キーとして属性を設定する手順を使用してください。

データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタでは、そのデータ・オブジェクトの主キーとして属性を指定できます(そのデータ・オブジェクトの基礎クラスでまだ指定していない場合)。

始める前に:

属性プロパティの設定方法の知識があると役立ちます。属性の使用を参照してください

次のタスクを完了する必要があります。

属性を主キーとして設定する手順は次のとおりです。

  1. 「アプリケーション」ウィンドウで、使用するデータ・コントロール構造ファイルをダブルクリックします。
  2. 概要エディタで、「属性」ナビゲーション・タブをクリックします。
  3. 「属性」ページで、主キーとして指定する属性を選択して、「詳細」タブをクリックします。
  4. 「詳細」ページで、「キー属性」プロパティを設定します。

注意:

属性がクラス内ですでに主キーとして指定されている場合、データ・コントロールはその設定を継承し、「キー属性」チェックボックスが選択されます。ただし、この場合は、「キー属性」オプションを選択解除することはできません。

属性の静的なデフォルト値を定義する方法

データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタでは、属性の静的なデフォルト値を指定できます。値タイプを「リテラル」に設定して、属性の静的なデフォルト値を定義する手順を使用してください。

値のタイプが「リテラル」に設定されている場合、「詳細」セクションの「値」フィールドには、属性のデフォルト値を静的に指定できます。たとえば、ServiceRequestエンティティBeanのStatus属性のデフォルト値をOpenに設定することや、User BeanのUserRole属性のデフォルト値をuserに設定できます。

始める前に:

属性プロパティの設定方法の知識があると役立ちます。属性の使用を参照してください

属性の静的なデフォルト値を定義する手順:

  1. 「アプリケーション」ウィンドウで、使用するデータ・コントロール構造ファイルをダブルクリックします。
  2. 概要エディタで、「属性」ナビゲーション・タブをクリックします。
  3. 「属性」ページで編集する属性を選択し、「詳細」タブをクリックします。
  4. 「詳細」ページで、「リテラル」オプションを選択します。
  5. 「リテラル」オプションの下のテキスト・フィールドに、属性のデフォルト値を入力します。

属性へのUIヒントの設定方法

属性にUIヒントを設定することで、そのヒントを一貫して表示およびラベル付けして、その属性を使用するUIコンポーネントでの属性の利便性とローカライズ可能性を向上します。「アプリケーション」ウィンドウの「属性」オプションを使用して、UIヒントを設定する手順を使用してください。

属性のUIヒントを設定し、それらの属性を使用するすべてのUIコンポーネントでそれらの属性が一貫したローカライズ可能な方法で表示およびラベル付けされるように設定できます。UIヒントにより、属性、ラベル、ツールチップ、フィールドを自動的に送信する必要があるかどうかを表示するために使用するUIコンポーネントのタイプなどが決定されます。特定の属性を表示するか非表示にするかも決定できます。属性のUIヒントを作成するには、「アプリケーション」ウィンドウからアクセスできる、データ・オブジェクトのデータ・コントロール構造ファイルの概要エディタを使用します。

始める前に:

属性プロパティの設定方法の知識があると役立ちます。属性の使用を参照してください

次のタスクを完了する必要があります。

UIヒントを設定する手順:

  1. 「アプリケーション」ウィンドウで、使用するデータ・コントロール構造ファイルをダブルクリックします。
  2. 概要エディタで、「属性」ナビゲーション・タブをクリックします。
  3. 「属性」ページで編集する属性を選択し、「UIヒント」タブをクリックします。
  4. 「UIヒント」セクションで、目的のUIヒントを設定します。

属性へのUIヒントの設定時の処理

属性のUIヒントは、タグが追加されるプロパティとして保存されます。プロパティの値は、リソース・バンドル・ファイルに保存されますが、このファイルが見つからない場合は生成されます。

属性に対してUIヒントを設定すると、それらのヒントはプロパティとして格納されます。プロパティのタグはデータ・オブジェクトのデータ・コントロール構造ファイルに追加され、プロパティの値はリソース・バンドル・ファイルに保存されます。リソース・バンドル・ファイルが存在していない場合は、データ・コントロールのパッケージに生成され、初めてUIヒントを設定した際のプロジェクト名に従って名前が設定されます。

次の例に、Item.xmlデータ・コントロール構造ファイルにおけるprice属性のコードを示します。属性に対して設定されているラベルおよびフォーマット・タイプ・ヒントのタグも含まれます。

<PDefAttribute
  Name="price">
  <Properties>
    <SchemaBasedProperties>
      <LABEL
        ResId="${adfBundle['model.ModelBundle']['model.Item.price_LABEL']}"/>
      <FMT_FORMATTER ResId="${adfBundle['model.ModelBundle']
                                       ['model.Item.price_FMT_FORMATTER']}"/>
    </SchemaBasedProperties>
  </Properties>
</PDefAttribute>

次の例に、ModelBundle.propertiesリソース・バンドル・ファイルにおけるラベルおよびフォーマット・タイプ・ヒントの対応するエントリを示します。これらにはプロジェクトのローカライズ可能なプロパティのすべての値も含まれています。

model.Item.price_LABEL=Price
. . .
model.Item.price_FMT_FORMATTER=oracle.jbo.format.DefaultCurrencyFormatter

EL式を使用してUIヒントにアクセスする方法

EL式を使用して、ヒントの値をデータとしてページに表示し、UIヒントにアクセスできるようにします。データバインドされたコンポーネントをページにドラッグして、UIヒントへのアクセスを提供するバインディング・インスタンスを作成します。

EL式を使用してUIヒントにアクセスし、ページにデータとしてヒント値を表示できます。UIヒントには、データバインドされたコンポーネントをページにドロップした後に作成するバインディング・インスタンスを通じてアクセスできます。

次の例は、DeviceFeaturesデータ・コントロールを使用して生成されました。この例は、MAFフォームとして接続をドラッグ・アンド・ドロップし、displayNameフィールドとnicknameフィールドのみを保持することによって生成されるEL式を示しています。太字で表示されるラベルは、ELを使用したUIヒント取得の例です。

<amx:panelFormLayout id="pfl2">
      <amx:inputText value="#{row.bindings.displayName.inputValue}"
                     label="#{bindings.Contact.hints.displayName.label}" id="it9"/>
      <amx:inputText value="#{row.bindings.nickname.inputValue}"
                     label="#{bindings.Contact.hints.nickname.label}"
                     id="it10"/>
</amx:panelFormLayout>af:panelHeader id="ph1"

Beanデータ・コントロールの作成と使用

Beanデータ・コントロールは、Beanクラスのメタデータ・ラッパーとして機能し、コード要素をUIコンポーネントにバインドするために使用するデータ・コントロール・オブジェクトとしてBeanのコード要素を公開します。Java Beanのデータ・コントロールは、「アプリケーション」ウィンドウの「データ・コントロールの作成」オプションを使用して作成します。

Beanデータ・コントロールは、Beanクラスのメタデータ・ラッパーとして機能し、データ・コントロール・オブジェクトとしてBeanのコード要素を公開します。このオブジェクトを使用して、これらのコード要素をUIコンポーネントにバインドできます。Java Beanデータ・コントロールでは、POJO (Plain Old Java Object)から自身のデータ構造を取得します。Java Beanデータ・コントロールを作成するには、Javaクラス・ファイルを右クリックし(「アプリケーション」ウィンドウ内)、「データ・コントロールの作成」を選択します。Java Beanのデータ・コントロールは、JDeveloperの「アプリケーション」ウィンドウ内で作成します。

始める前に:

データ・コントロールの一般的な知識があると役立ちます。「データ・コントロールの作成方法」を参照してください。

注意:

Java Beanがバックグラウンド・スレッドを使用してUI内のデータを更新する場合、手動でoracle.adfmf.framework.api.AdfmfJavaUtilities.flushDataChangeEventをコールする必要があります。flushDataChangeEventメソッドの詳細は、「データ変更イベントについて」を参照してください。

ローカルSQLiteデータベースおよびJava Beanデータ・コントロールを使用してCRUD操作を構築するサンプルは、開発コンピュータのjdev_install/jdeveloper/jdev/extensions/oracle.maf/SamplesディレクトリにあるPublicSamples.zipファイル内のCRUDDemoというMAFサンプル・アプリケーションを参照してください。

Beanクラス変数のシリアライズに関する必知事項

ネストされたオブジェクトのチェーンはtransientとして定義することでシリアライズを防止し、オブジェクトのネストによる循環オブジェクトの作成を回避します。JSONBeanSerializationHelperクラスを使用すると、JavaオブジェクトをJSONオブジェクトにシリアライズおよびシリアライズ解除できます。

MAFでは、一時変数として宣言されたJavaScript Object Notation (JSON)データBeanクラス変数にはシリアライズしません。一連のネストされたオブジェクトのシリアライズを避けるには、それらを一時オブジェクトとして定義する必要があります。この方法を使用すると、オブジェクトのネストが原因で循環オブジェクトが作成されるのを防ぐこともできます。

次のシナリオを考えてみましょう。Employeeオブジェクトが、その子として従業員の上司を表すEmployeeオブジェクトを保持しているとします。その子を一時オブジェクトとして宣言しなかった場合、実行時に子のEmployeeオブジェクトを計算しようとすると、一連のネストされたシリアライズ・オブジェクトが作成されます。

JavaオブジェクトをJSONオブジェクトにシリアライズおよびシリアライズ解除するには、JSONBeanSerializationHelperクラスを使用します。JSONBeanSerializationHelperクラスを使用すると、独自のカスタムJSONシリアライズおよびシリアライズ解除を実装できます。また、このクラスでは、JSONシリアライズ(およびシリアライズ解除)処理後にJSONオブジェクトを変更するためのフックが提供されます。Oracle Mobile Application Framework Java APIリファレンスoracle.adfmf.framework.api.JSONBeanSerializationHelperクラスに関する項を参照してください。

MAFでは、GregorianCalendarクラスのオブジェクトのシリアライズはサポートされません。JSONBeanSerializationHelperクラスでは、GregorianCalendarクラスのオブジェクトをシリアライズできません。これは、GregorianCalendarクラスに循環参照が含まれるためです。かわりに、java.util.Dateまたはjava.sql.Dateをデータ操作に使用します。次の例は、java.util.Dateを使用してGregorianCalendarオブジェクトを変換する方法を示しています。

Calendar calDate = new GregorianCalendar();
calDate.set(1985, 12, 1); // "January 1, 1986"
Date date = calDate.getTime();

アプリケーション機能間のデータ・コントロールのインスタンスの共有

共有インスタンスにアクセスするすべてのアプリケーション機能について、複数のアプリケーション機能がアクセスするデータ・コントロールがメモリーに一度ロードされるように、アプリケーション機能間でデータ・コントロールのインスタンスを共有できます。

これを行うことにより、MAFアプリケーションのパフォーマンスは大幅に向上します。共有インスタンス・データ・コントロールは、データ・コントロールにアクセスするアプリケーション機能ごとではなく、メモリーに一度ロードされます。

MAFは、共有インスタンス・データ・コントロールを使用するアプリケーション機能でエンド・ユーザーが行うデータの変更を共有インスタンス・データ・コントロールを使用する他のアプリケーション機能に伝播します。

デフォルトでは、データ・コントロールはMAFアプリケーションのアプリケーション機能間で共有されません。maf-application.xmlファイルの概要エディタの「共有インスタンスDC」ページに共有する各データ・コントロールを追加する必要があります。次の図は、HRServiceデータ・コントロールが共有インスタンス・データ・コントロールとして指定されている「共有インスタンスDC」ページを示しています。

デフォルトでは、MAFは、セキュリティが有効化されたアプリケーション機能からの共有インスタンス・データ・コントロールへのアクセスのみ許可します。Enable Securityプロパティをfalseに設定して、この制限を無効化し、認証されていないユーザーが使用するアプリケーション機能が共有インスタンス・データ・コントロールにアクセスできるようにすることができます。

図15-10 maf-application.xmlの概要エディタの「共有インスタンス・データ・コントロール」ページ

図15-10の説明が続きます
「図15-10 maf-application.xmlの概要エディタの「共有インスタンス・データ・コントロール」ページ」の説明

データ・コントロールを共有インスタンス・データ・コントロールとして指定した場合でも、MAFアプリケーションがdata-control-contextの値がisolatedのタスク・フローからアクセスするデータ・コントロールは共有されません。

アプリケーション機能間のデータ・コントロールのインスタンスの共有方法

maf-application.xmlファイルの概要エディタの「共有インスタンスDC」ページに共有する各データ・コントロールを追加して、データ・コントロールのインスタンスを共有します。

アプリケーション機能間でデータ・コントロールのインスタンスを共有する手順:
  1. 「アプリケーション」ウィンドウで、「アプリケーション・リソース」パネルを展開します。
  2. 「アプリケーション・リソース」パネルでDescriptorsを展開し、ADF META-INFを展開します。
  3. maf-application.xmlファイルをダブルクリックし、表示される概要エディタで「共有インスタンスDC」ナビゲーション・タブをクリックします。
  4. 「共有インスタンスDC」ページで「追加」アイコンをクリックします。
  5. sharedInstanceDataControlの挿入ダイアログで、ドロップダウン・リストからデータ・コントロールのIDを選択します。
  6. 「OK」をクリックします。

アプリケーション機能間でデータ・コントロールのインスタンスを共有する際の処理内容

実行時、共有インスタンス・データ・コントロールとして指定したデータ・コントロールに対して、1つのデータ・コントロールのインスタンスが作成されます。これは、たとえば、関連付けられた共有インスタンス・データ・コントロールが最初に機能によって参照されたときに一度だけ、Javaクラスがインスタンス化されるということです。

共有インスタンス・データ・コントロールを参照するすべてのアプリケーション機能は、このJavaクラスのインスタンスを共有します。セキュリティ設定で許可されている場合、共有インスタンス・データ・コントロールの更新はすべてのアプリケーション機能に配信されます。たとえば、共有インスタンス・データ・コントロールが保護されたアプリケーション機能でのみ利用可能な場合(デフォルトの設定)、データ変更またはデータ・プロバイダのイベントの形での更新が保護されたアプリケーション機能に送信され、保護されていないアプリケーション機能が共有インスタンス・データ・コントロールにアクセスしようとすると、MAFはエラーをスローします。

ここで説明した動作の1つの例外は、MAFアプリケーションが、data-control-contextの値がisolatedのタスク・フローから共有インスタンス・データ・コントロールにアクセスする場合です。このシナリオでは、複数のデータ・プロバイダのインスタンスが作成されます。

JDeveloperは、共有として指定した各データ・コントロールを識別するmaf-application.xmlファイルにエントリを追加します。次の例は、2つの共有インスタンス・データ・コントロールのエントリを示しています。最初の共有インスタンス・データ・コントロール(HRService)は、セキュリティが有効化されたアプリケーション機能でのみアクセスできます(デフォルトの設定)。一方、2番目(CustomerService)は、保護されていないアプリケーション機能からアクセスできます。

例15-1 maf-application.xmlファイルで定義された共有インスタンス・データ・コントロール

<adfmf:application ...>
  ...
  <adfmf:sharedInstanceDataControls>
    <adfmf:sharedInstanceDataControl dataControlId="HRService" id="sidc1"/>
    <adfmf:sharedInstanceDataControl dataControlId="CustomerService" id="sidc2" securityEnabled="false"/>
  </adfmf:sharedInstanceDataControls>
</adfmf:application>

DeviceFeaturesデータ・コントロールの使用方法

新しいMAFアプリケーションを作成すると、MAFは「データ・コントロール」パネルに DeviceFeaturesデータ・コントロールを表示します。MAF AMXページ上のデータ・コントロールで使用可能な操作を使用して、デバイス上のユーザー連絡先の管理、電子メール・メッセージとSMSテキスト・メッセージの使用、デバイスの場所の確認、デバイスのカメラの使用、デバイスに保管しているイメージの取得を実行します。

MAFでは、アプリケーション内でDeviceFeaturesデータ・コントロールを通じて使用できるデバイス固有の機能が公開されます。DeviceFeaturesデータ・コントロールは、新しいMAFアプリケーションを作成するときに「データ・コントロール」パネルに表示されるコンポーネントです(次の図を参照)。Cordova Java APIは、このデータ・コントロールを通じて抽象化されます。これにより、MAF AMXとして実装されたアプリケーション機能から、デバイスに埋め込まれた様々なサービスにアクセスできるようになります。DeviceFeaturesデータ・コントロールから提供される操作をMAF AMXページ内にドラッグ・アンド・ドロップすることで、デバイスに格納されたユーザーの連絡先を管理する機能の追加、電子メール・メッセージとSMSテキスト・メッセージの両方の作成と送信、デバイスの位置の確認、デバイスのカメラの使用およびデバイスのファイル・システムに格納されたイメージの取得を実行できます。次の項では、これらの操作を宣言的に使用する方法や、JavaコードとJavaScriptを使用して実装する方法など、各操作について詳しく説明します。

図15-11 概要エディタでのMAFのDeviceFeaturesデータ・コントロール

図15-11の説明が続きます
「図15-11 概要エディタでのMAFのDeviceFeaturesデータ・コントロール」の説明

MAFアプリケーション・テンプレートを使用してアプリケーションを作成すると、自動的にDeviceFeaturesデータ・コントロールが「データ・コントロール」パネルに表示されます。図15-11は、「概要」エディタ内のDeviceFeaturesデータ・コントロールを示しています。次のメソッドを使用できます。

  • addLocalNotification

  • cancelLocalNotification

  • createContact

  • displayFile

  • findContacts

  • getPicture

  • removeContact

  • sendEmail

  • sendSMS

  • startLocationMonitor

  • updateContact

ページを作成したら、DeviceFeaturesデータ・コントロールのメソッド(またはそれらのメソッド内にネストされたその他のオブジェクト)を「データ・コントロール」パネルからMAF AMXビューにドラッグして、関連する機能にバインドされたコマンド・ボタンやその他のコンポーネントを作成できます。デフォルトのバインディングを受け入れるか、ELを使用してそれらのバインディングを変更できます。また、JavaScriptやJavaを使用して、機能を実装または構成することもできます。「MAF AMXページへのデータ・コントロールの追加方法」を参照してください。

DeviceManagerは、デバイスの機能へのアクセスを可能にするオブジェクトです。このオブジェクトのハンドルは、DeviceManagerFactory.getDeviceManagerをコールすることによって取得できます。次の項では、DeviceManagerオブジェクトを使用してgetPicturecreateContactなどのメソッドを起動する方法について説明します。

ネットワーク・アクセスを除き、すべてのApache Cordova対応デバイス機能へのアクセスは、MAFアプリケーションの場合デフォルトでは有効になっていません。DeviceFeaturesデータ・コントロールによって公開されている操作が実行時に正常に機能するには、関連するプラグインがMAFアプリケーションで有効になっている必要があります。たとえば、DeviceFeaturesデータ・コントロールのsendSMS操作を使用する場合は、MAFアプリケーションでSMSプラグインを有効にする必要があります。プラグインは手動で有効にするか、MAFアプリケーションで関連するプラグインが有効になっていない操作をドラッグ・アンド・ドロップしたときにJDeveloperによって表示されるダイアログで該当するオプションを選択して有効にします。たとえば、まだSMSプラグインが有効になっていないMAFアプリケーションのMAF AMXページにsendSMS操作をドラッグ・アンド・ドロップすると、JDeveloperによって図のようにダイアログが表示されます。

図15-12 DeviceFeaturesデータ・コントロールの操作用プラグインの有効化

図15-12の説明が続きます
「図15-12 DeviceFeaturesデータ・コントロールの操作用プラグインの有効化」の説明

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

図15-13 DeviceFeaturesデータ・コントロールの操作に必要なプラグイン

図15-13の説明が続きます
「図15-13 DeviceFeaturesデータ・コントロールの操作に必要なプラグイン」の説明

撮影を有効にするためのgetPictureメソッドの使用方法

DeviceFeaturesデータ・コントロールには、デバイスのカメラでの写真撮影や既存の画像の取得のためのgetPictureメソッドがあります。getPicture操作をカスタマイズする手順を使用してください。カスタマイズには、sourceTypedestinationTypequalityallowEditなどのパラメータを使用します。

DeviceFeaturesデータ・コントロールに含まれるgetPictureメソッドをMAFアプリケーションで使用すると、エンド・ユーザーはデバイスのカメラとフォト・ライブラリを利用して、写真を撮影や既存のイメージの取得ができるようになります。この項の終わりに、次のことを示す例があります。

  • デバイスのカメラでエンド・ユーザーが写真撮影できるようにするJavaScriptコード。デバイスのカメラでユーザーが写真撮影できるようにするJavaコード。

  • ユーザーが保存済イメージを取得することを可能にするJavaコード。

getPictureメソッドについては、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。

次のパラメータによって、イメージの取得元と、そのイメージを戻す方法が制御されます。

注意:

撮影する写真にtargetWidthtargetHeightおよびqualityを指定しない場合、使用されるデフォルト値は最大値になり、メモリーに障害が発生することがあります。

  • quality: 保存済イメージの質を設定します。範囲は1から100 (100を含む)です。大きい数値を指定すると質は高くなりますが、ファイル・サイズも増大します。JPEGイメージ(encodingTypeで指定します)にのみ適用されます。

  • destinationType: 戻り値の形式を次から選択します。

    • DeviceManager.CAMERA_DESTINATIONTYPE_DATA_URL (0): Base64でエンコードされた文字列としてイメージを戻します。プログラムで使用する場合、この値は、DeviceManager.CAMERA_DESTINATION_DATA_URLを使用してenumとしても指定されます。イメージをイメージ・コンポーネント内に表示するには、戻された値の前にdata:image/gif;base64を付ける必要があります。

    • DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI (1): イメージ・ファイルのパスを戻します。この値は、プログラムで使用される場合、DeviceManager.CAMERA_DESTINATION_FILE_URIを使用する列挙としても指定されます。

    注意:

    ファイルのURIがgetPictureメソッドによって戻された場合、ファイルのサイズを求めるために使用する前に、問合せパラメータを削除する必要があります。次にその例を示します。

    String fileURI = ...getPicture(...);

    fileURI = fileURI.substring(0, result.lastIndexOf("?"));

  • sourceType: 写真のソースを次から選択して設定します。

    • DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARY (0): ユーザーは保存済のイメージから選択できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARYを使用する列挙としても指定されます。

    • DeviceManager.CAMERA_SOURCETYPE_CAMERA (1): ユーザーはデバイスのカメラで写真撮影できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_CAMERAを使用する列挙としても指定されます。

    • DeviceManager.CAMERA_SOURCETYPE_SAVEDPHOTOALBUM (2): ユーザーは既存のフォト・アルバムから選択できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_SAVEDPHOTOALBUMを使用する列挙としても指定されます。

  • allowEdit: 選択する前にイメージの単純な編集を許可するかどうかを選択します(ブール)。

  • encodingType: 戻されるイメージ・ファイルのエンコーディングを次から選択します。

    • DeviceManager.CAMERA_ENCODINGTYPE_JPEG (0): 戻されるイメージをJPEGファイルとしてエンコードします。この値は、プログラムで使用される場合、DeviceManager.CAMERA_ENCODINGTYPE_JPEGを使用する列挙としても指定されます。

    • DeviceManager.CAMERA_ENCODINGTYPE_PNG (1): 戻されるイメージをPNGファイルとしてエンコードします。この値は、プログラムで使用される場合、DeviceManager.CAMERA_ENCODINGTYPE_PNGを使用する列挙としても指定されます。

  • targetWidth: 幅をピクセル単位で設定してイメージのスケールを変更します。アスペクト比は維持されます。負の値または0の場合、イメージの元のディメンションが使用されます。

  • targetHeight: 高さをピクセル単位で設定してイメージのスケールを変更します。アスペクト比は維持されます。負の値または0の場合、イメージの元のディメンションが使用されます。

DeviceFeaturesデータ・コントロールを使用してgetPicture操作をカスタマイズするには:

  1. 「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからgetPicture操作をドラッグし、ボタンとしてページにドロップします。

    ユーザーがよりきめ細かく制御できるようにするには、getPicture操作をパラメータ・フォームとしてドロップします。これにより、エンド・ユーザーは写真を撮影したり既存のイメージを選択する前に、設定を指定できるようになります。

  2. 「アクションの編集」ダイアログで、前述のすべてのパラメータの値を設定します。イメージがファイル名として戻されるように、destinationType = 1を指定するようにします。

  3. getPictureの戻り値をドラッグし、それを出力テキストとしてページ上にドロップします。

  4. 「共通コンポーネント」パネルで、「コンポーネント・パレット」から「イメージ」をドラッグし、ページ上にドロップします。

  5. 「イメージ」source属性を、getPicture操作の戻り値に設定します。バインディングの式は、#{bindings.Return.inputValue}である必要があります。

ユーザーのフォト・ライブラリからのイメージを表示するバインディングを図に示します。

図15-14 デザインタイムでフォト・ライブラリからイメージを表示するためのバインディング

図15-14の説明が続きます
「図15-14 デザインタイムでフォト・ライブラリからイメージを表示するためのバインディング」の説明

このアプリケーションを実行すると、イメージ・チューザが自動的に表示され、エンド・ユーザーは表示するイメージを選択できます。イメージ・チューザが自動的に表示される理由は、イメージ・コントロールがgetPicture操作の戻り値にバインドされており、それによってgetPicture操作が起動するためです。

注意:

getPictureメソッドのタイムアウト値は、5分に設定されます。デバイス操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。

次に示すプラットフォーム固有の問題に留意してください。

  • iOS

    • いくつかのデバイスでメモリー・エラーが発生しないようにするには、qualityを50未満に設定します。

    • destinationType FILE_URIを使用すると、写真はアプリケーションの一時ディレクトリに保存されます。

    • アプリケーションの一時ディレクトリの内容は、アプリケーションの終了時に削除されます。記憶域の空き領域が問題になる場合は、navigator.fileMgr APIを使用してこのディレクトリの内容を削除することもできます。

    • targetWidthtargetHeightを使用するには、これらを両方とも指定する必要があります。一方または両方の値が負の値または0の場合、イメージの元のディメンションが使用されます。

  • Android

    • allowEditパラメータを無視します。

    • Camera.PictureSourceType.PHOTOLIBRARYCamera.PictureSourceType.SAVEDPHOTOALBUMでは、どちらも同じフォト・アルバムが表示されます。

    • Camera.EncodingTypeはサポートされていません。パラメータは無視され、常にJPEGイメージが生成されます。

    • targetWidthtargetHeightは、個別に指定できます。一方のパラメータが正の値で、もう一方が負の値またはゼロを使用して元のサイズを表す場合、正の値がそのディメンションに使用され、もう一方のディメンションは元のアスペクト比を維持するようにスケール変更されます。

    • destinationType DATA_URLを使用すると、イメージが大きい場合は使用可能なメモリーがすべて使用され、メモリー不足のエラーが発生する場合があります。通常は、デフォルトのイメージ・サイズを使用すると、この動作が発生します。targetWidthtargetHeightを設定してイメージ・サイズを制限します。

次の例は、デバイスのカメラでユーザーが写真撮影できるようにするJavaScriptコードを示しています。結果は、保存済イメージへのフルパスになります。

// The camera, like many other device-specific features, is accessed 
// from the global 'navigator' object in JavaScript.
// Note that in the Cordova JavaScript APIs, the parameters are passed
// in as a dictionary, so it is only necessary to provide key-value pairs
// for the parameters you want to specify.

navigator.camera.getPicture(onSuccess, onFail, { quality: 50 });

function onSuccess(imageURI) { 
    var image = document.getElementById('myImage');
    image.src = imageURI;
}

function onFail(message) {
    alert('Failed because: ' + message);
}

次の例は、デバイスのカメラでユーザーが写真撮影できるようにするJavaコードを示しています。結果は、保存済イメージへのフルパスになります。

import oracle.adf.model.datacontrols.device; 

// Access device features in Java code by acquiring an instance of the  
// DeviceManager from the DeviceManagerFactory.
// Take a picture with the device's camera.  
// The result will be the full path to the saved PNG image.
String imageFilename = DeviceManagerFactory.getDeviceManager().getPicture(100,
                               DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI,
                               DeviceManager.CAMERA_SOURCETYPE_CAMERA, false,
                               DeviceManager.CAMERA_ENCODINGTYPE_PNG, 0, 0);

次の例は、ユーザーが保存済イメージを取得することを可能にするJavaコードを示しています。結果は、Base64でエンコードされたJPEGになります。

import oracle.adf.model.datacontrols.device; 

// Retrieve a previously-saved image. The result will be a base64-encoded JPEG.
String imageData = DeviceManagerFactory.getDeviceManager().getPicture(100, 
  DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URL,
  DeviceManager.CAMERA_SOURCETYPE__PHOTOLIBRARY, false,
  DeviceManager.CAMERA_ENCODINGTYPE_JPEG, 0, 0);

テキスト・メッセージを有効にするためのSendSMSメソッドの使用方法

DeviceFeaturesデータ・コントロールのsendSMSを使用して、デバイスのショート・メッセージ・サービス(SMS)テキスト・メッセージング・インターフェイスでSMSメッセージを送受信します。sendSMS操作はカスタマイズできます。

DeviceFeaturesデータ・コントロールに含まれるsendSMSメソッドをMAFアプリケーションで使用すると、デバイスのショート・メッセージ・サービス(SMS)テキスト・メッセージング・インタフェースを利用して、ユーザーがSMSメッセージを送受信できるようになります。MAFでは、デバイスのSMSインタフェースを表示して、必要に応じて次のフィールドにデータを事前移入できます。

  • to: 受信者をリストします(カンマ区切り)。

  • body: メッセージの本文を追加します。

SMSテキスト・メッセージング・インタフェースが表示されると、ユーザーはSMSを送信することも、それを取り消すこともできます。デバイスとキャリアの制限により、SMSは自動的に送信できません。実際にSMSを送信できるのはユーザーのみです。

sendSMSメソッドのタイムアウト値は、5分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかった場合は、タイムアウト・エラーが表示されます。

Androidでは、ユーザーがSMSメッセージの編集中にアプリケーションを切り替えて、その後戻すと、SMS編集画面は表示されなくなります。かわりに、そのメッセージは下書きとして保存され、手動で選択して編集を続けることができます。

ユニバーサルWindowsプラットフォーム上のMAFアプリケーションは、SMSテキスト・メッセージを現在サポートしていません。

DeviceFeaturesデータ・コントロールを使用してsendSMS操作をカスタマイズするには:

SMSの送信のためページに対話型フォームを表示するには、sendSMS操作を「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからドラッグし、ページ・デザイナ上にパラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスのSMSインタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに値が事前移入されいる送信準備が整ったSMSが表示されます。

ページ上の編集可能なフォームを使用してSMSを送信するためのバインディングを図に示します。

図15-15 デザインタイムで編集可能なフォームを使用してSMSを送信するためのバインディング

図15-15の説明が続きます
「図15-15 デザインタイムで編集可能なフォームを使用してSMSを送信するためのバインディング」の説明

次の例は、ユーザーがデバイスのテキスト・メッセージング・インタフェースを使用してSMSメッセージを送信できるようにするコード例を示しています。

sendSMSメソッドについては、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。

次の例は、ユーザーがSMSメッセージを送信できるようにするJavaScriptコードを示しています。

adf.mf.api.sendSMS({to: "5551234567", body: "This is a test message"}); 

次の例は、ユーザーがSMSメッセージを送信できるようにするJavaコードを示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

// Access device features in Java code by acquiring an instance of the  
// DeviceManager from the DeviceManagerFactory.
// Send an SMS to the phone number "5551234567"
DeviceManagerFactory.getDeviceManager().sendSMS("5551234567", "This is a test message");

電子メールを有効にするためのsendEmailメソッドの使用方法

DeviceFeaturesデータ・コントロールには、構成済の電子メール・アカウントの電子メール・メッセージをデバイスの電子メール・メッセージング・インタフェースで送受信するためのsendEmailメソッドがあります。sendEmail操作はカスタマイズできます。

DeviceFeaturesデータ・コントロールに含まれるsendEmailメソッドをMAFアプリケーションで使用すると、デバイスの電子メール・メッセージング・インタフェースを利用して、ユーザーが電子メール・メッセージを送受信できるようになります。MAFでは、デバイスの電子メール・インタフェースを表示して、必要に応じて次のフィールドにデータを事前移入できます。

  • to: 受信者をリストします(カンマ区切り)。

  • cc: CC受信者をリストします(カンマ区切り)。

  • subject: メッセージの件名を追加します。

  • body: メッセージの本文を追加します。

  • bcc: BCC受信者をリストします(カンマ区切り)。

  • attachments: 電子メールに添付するファイルの名前をリストします(カンマ区切り)。

  • mimeTypes: 添付ファイルに使用するMIMEタイプをリストします(カンマ区切り)。MAFで自動的にMIMEタイプを決定するには、nullを指定します。この項の最後にある例に示すように、選択した添付ファイルのMIMEタイプのみを指定することもできます。

デバイスの電子メール・インタフェースが表示されると、ユーザーは電子メールを送信することも、それを取り消すこともできます。デバイスとキャリアの制限により、電子メールは自動的に送信できません。実際に電子メールを送信できるのは、ユーザーのみです。また、電子メールを送信するには、1つ以上の電子メール・アカウントを構成する必要があります。アカウントが構成されていない場合、電子メール・アカウントが見つからないことを示すエラーが表示されます。

注意:

sendEmailメソッドのタイムアウト値は5分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。

注意:

Androidでは、ユーザーが電子メールの編集中にアプリケーションを切り替えて、その後戻すと、電子メールの編集画面は表示されなくなります。かわりに、そのメッセージは下書きとして保存され、手動で選択して編集を続けることができます。

DeviceFeaturesデータ・コントロールを使用してsendEmail操作をカスタマイズするには:

JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからsendEmail操作をページ・デザイナ上にドラッグし、パラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスの電子メール・インタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに値が事前移入され、送信準備が整った電子メールが表示されます。

ページ上の編集可能なフォームを使用して電子メールを送信するためのバインディングを図に示します。

図15-16 デザインタイムで編集可能なフォームを使用して電子メールを送信するためのバインディング

図15-16の説明が続きます
「図15-16 デザインタイムで編集可能なフォームを使用して電子メールを送信するためのバインディング」の説明

次に、ユーザーがデバイスの電子メール・インタフェースを使用して電子メール・メッセージを送信できるようにするコード例を示します。

sendEmailメソッドについては、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。

次の例は、ユーザーが電子メール・メッセージを送信できるようにするJavaScriptコードを示しています。

// Populate an email to 'ann.li@example.com',  
// copy 'joe.jones@example.com', with the 
// subject 'Test message', and the body 'This is a test message'
// No BCC recipients or attachments
adf.mf.api.sendEmail({to: "ann.li@example.com",
                           cc: "joe.jones@example.com",
                           subject: "Test message",
                           body: "This is a test message"});

// Populate the same email as before, but this time, also BCC 
// 'john.smith@example.com' & 'jane.smith@example.com' and attach two files.
// By not specifying a value for the mimeTypes parameter, you are telling 
// ADFMobile to automatically determine the MIME type for each of the attachments.
adf.mf.api.sendEmail({to: "ann.li@example.com",
                           cc: "joe.jones@example.com",
                           subject: "Test message",
                           body: "This is a test message"});
                           bcc: "john.smith@example.com,jane.smith@example.com",
                           attachments: "path/to/file1.txt,path/to/file2.png"});

// For iOS only: Same as previous email, but this time, explicitly specify
// all the MIME types.
adf.mf.api.sendEmail({to: "ann.li@example.com",
                           cc: "joe.jones@example.com",
                           subject: "Test message",
                           body: "This is a test message"});
                           bcc: "john.smith@example.com,jane.smith@example.com",
                           attachments: "path/to/file1.txt,path/to/file2.png"});
                           mimeTypes: "text/plain,image/png"});

// For iOS only: Same as previous email, but this time, only specify  
// the MIME type for the second attachment and let the system determine
// the MIME type for the first one.
adf.mf.api.sendEmail({to: "ann.li@example.com",
                           cc: "joe.jones@example.com",
                           subject: "Test message",
                           body: "This is a test message"});
                           bcc: "john.smith@example.com,jane.smith@example.com",
                           attachments: "path/to/file1.txt,path/to/file2.png"});
                           mimeTypes: ",image/png"});

// For Android only: Same as previous e-mail, but this time, explicitly specify 
// the MIME type.
adf.mf.api.sendEmail({to: "ann.li@example.com",
                           cc: "joe.jones@example.com",
                           subject: "Test message",
                           body: "This is a test message"});
                           bcc: "john.smith@example.com,jane.smith@example.com",
                           attachments: "path/to/file1.txt,path/to/file2.png"});
                           mimeTypes: "image/*"}); 
// You can also use "plain/text" as the MIME type as it just determines the type
// of applications to be filtered in the application chooser dialog.

次の例は、ユーザーが電子メール・メッセージを送信できるようにするJavaコードを示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

// Access device features in Java code by acquiring an instance of the  
// DeviceManager from the DeviceManagerFactory.
// Populate an email to 'ann.li@example.com', copy 'joe.jones@example.com', with the 
// subject 'Test message', and the body 'This is a test message'.
// No BCC recipients or attachments.
DeviceManagerFactory.getDeviceManager().sendEmail(
                                        "ann.li@example.com",
                                        "joe.jones@example.com",
                                        "Test message",
                                        "This is a test message",
                                        null,
                                        null,
                                        null);

// Populate the same email as before, but this time, also BCC 
// 'john.smith@example.com' & 'jane.smith@example.com' and attach two files.
// By specifying null for the mimeTypes parameter, you are telling 
// ADFMobile to automatically determine the MIME type for each of the attachments.
DeviceManagerFactory.getDeviceManager().sendEmail(
                                        "ann.li@example.com",
                                        "joe.jones@example.com",
                                        "Test message",
                                        "This is a test message",
                                        "john.smith@example.com,jane.smith@example.com",
                                        "path/to/file1.txt,path/to/file2.png",
                                        null);

// Same as previous email, but this time, explicitly specify all the MIME types.
DeviceManagerFactory.getDeviceManager().sendEmail(
                                        "ann.li@example.com",
                                        "joe.jones@example.com",
                                        "Test message",
                                        "This is a test message",
                                        "john.smith@example.com,jane.smith@example.com",
                                        "path/to/file1.txt,path/to/file2.png",
                                        "text/plain,image/png");


// Same as previous email, but this time, only specify the MIME type for the 
// second attachment and let the system determine the MIME type for the first one.
DeviceManagerFactory.getDeviceManager().sendEmail(
                                        "ann.li@example.com",
                                        "joe.jones@example.com",
                                        "Test message",
                                        "This is a test message",
                                        "john.smith@example.com,jane.smith@example.com",
                                        "path/to/file1.txt,path/to/file2.png",
                                        ",image/png");

連絡先の作成を有効にするためのcreateContactメソッドの使用方法

DeviceFeaturesデータ・コントロールに含まれるcreateContactメソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーが新しい連絡先を作成してデバイスのアドレス帳に保存できるようになります。

MAFでは、デバイスのインタフェースを表示して、必要に応じてContactフィールドにデータを事前移入できます。この項の最後の例に示すように、createContactメソッドはContactオブジェクトをパラメータとして使用し、作成されたContactオブジェクトを戻します。

createContactメソッドおよびContactオブジェクトの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。Contactのプロパティについては、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」も参照してください。

注意:

createContactメソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。

注意:

null Contactオブジェクトがメソッドに渡された場合、例外がスローされます。

DeviceFeaturesデータ・コントロールを使用してcreateContact操作をカスタマイズするには:

  1. JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからcreateContact操作をドラッグし、リンクまたはボタンとしてページ・デザイナ上にドロップします。

    リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、createContact操作に対するContactオブジェクトのパラメータを入力するよう求められます。このパラメータは、Java BeanクラスからContactを戻すために使用されるマネージドBeanのプロパティを参照するEL式である必要があります。マネージドBeanにContactオブジェクトのゲッターがすでに含まれている場合は、EL式ビルダーを使用して、パラメータの値を設定できます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してcreateContact操作を実行できます。次のコード例は、Contactオブジェクトを作成するマネージドBeanコードの例を示しています。

  2. 操作から戻されるオブジェクトのContactを、「データ・コントロール」パネルにあるcreateContact操作の下からドラッグし、フォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。createContact操作を実行すると、結果がこのフォームに表示されます。
private Contact contactToBeCreated;
 
public void setContactToBeCreated(Contact contactToBeCreated) {
   this.contactToBeCreated = contactToBeCreated;
}
 
public Contact getContactToBeCreated() {
   String givenName = "Mary";
   String familyName = "Jones";
   String note = "Just a Note";
   String phoneNumberType = "mobile";
   String phoneNumberValue = "650-555-0111";
   String phoneNumberNewValue = "650-555-0199";
   String emailType = "home";
   String emailTypeNew = "work";
   String emailValue = "Mary.Jones@example.com";
   String addressType = "home";
   String addressStreet = "500 Barnacle Pkwy";
   String addressLocality = "Redwood Shores";
   String addressCountry = "USA";
   String addressPostalCode = "94065";
   ContactField[] phoneNumbers = null;
   ContactField[] emails = null;
   ContactAddresses[] addresses = null;
 
   /*
    * Create contact
    */
   this.contactToBeCreated = new Contact();
 
   ContactName name = new ContactName();
   name.setFamilyName(familyName);
   name.setGivenName(givenName);
   this.contactToBeCreated.setName(name);
 
   ContactField phoneNumber = new ContactField();
   phoneNumber.setType(phoneNumberType);
   phoneNumber.setValue(phoneNumberValue);
 
   phoneNumbers = new ContactField[] { phoneNumber };
 
   ContactField email = new ContactField();
   email.setType(emailType);
   email.setValue(emailValue);
 
   emails = new ContactField[] { email };
 
   ContactAddresses address = new ContactAddresses();
   address.setType(addressType);
   address.setStreetAddress(addressStreet);
   address.setLocality(addressLocality);
   address.setCountry(addressCountry);
 
   addresses = new ContactAddresses[] { address };
 
   this.contactToBeCreated.setNote(note);
   this.contactToBeCreated.setPhoneNumbers(phoneNumbers);
   this.contactToBeCreated.setEmails(emails);
   this.contactToBeCreated.setAddresses(addresses);
 
   return this.contactToBeCreated;
}

次の例は、ユーザーがデバイスで連絡先を作成できるようにするコード例を示しています。

次の例は、createContactのJavaScriptコードを示しています。

// Contacts, like many other device-specific features, 
// are accessed from the global 'navigator' object in JavaScript
var contact = navigator.contacts.create();
 
var name = new ContactName();
name.givenName = "Mary";
name.familyName = "Jones";
 
contact.name = name;
 
// Store contact phone numbers in ContactField[]
var phoneNumbers = [1];
phoneNumbers[0] = new ContactField('home', '650-555-0123', true);
 
contact.phoneNumbers = phoneNumbers;
 
// Store contact email addresses in ContactField[]
var emails = [1];
emails[0] = new ContactField('work', 'Mary.Jones@example.com');
 
contact.emails = emails;
 
// Save
contact.save(onSuccess, onFailure);
 
function onSuccess()
{
  alert("Create Contact successful.");
}
 
function onFailure(Error)
{
  alert("Create Contact failed: " + Error.code);
}
     

次の例は、createContactのJavaコードを示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory; 

import oracle.adf.model.datacontrols.device.ContactAddresses;
import oracle.adf.model.datacontrols.device.ContactField;
import oracle.adf.model.datacontrols.device.ContactName;

String givenName = "Mary";
String familyName = "Jones";
String note = "Just a Note";
String phoneNumberType = "mobile";
String phoneNumberValue = "650-555-0111";
String phoneNumberNewValue = "650-555-0199";
String emailType = "home";
String emailTypeNew = "work";
String emailValue = "Mary.Jones@example.com";
String addressType = "home";
String addressStreet = "500 Barnacle Pkwy";
String addressLocality = "Redwood Shores";
String addressCountry = "USA";
String addressPostalCode = "91234";
ContactField[] phoneNumbers = null;
ContactField[] emails = null;
ContactAddresses[] addresses = null;
ContactField[] emails = null;
    
/*
* Create contact
*/
Contact aContact = new Contact();
     
ContactName name = new ContactName();
name.setFamilyName(familyName);
name.setGivenName(givenName);
aContact.setName(name);
     
ContactField phoneNumber = new ContactField();
phoneNumber.setType(phoneNumberType);
phoneNumber.setValue(phoneNumberValue);
     
phoneNumbers = new ContactField[] { phoneNumber };
     
ContactField email = new ContactField();
email.setType(emailType);
email.setValue(emailValue);
     
emails = new ContactField[] { email };
     
ContactAddresses address = new ContactAddresses();
address.setType(addressType);
address.setStreetAddress(addressStreet);
address.setLocality(addressLocality);
address.setCountry(addressCountry);
     
addresses = new ContactAddresses[] { address };
     
aContact.setNote(note);
aContact.setPhoneNumbers(phoneNumbers);
aContact.setEmails(emails);
aContact.setAddresses(addresses);
     
// Access device features in Java code by acquiring an instance of the  
// DeviceManager from the DeviceManagerFactory.
// Invoking the createContact method, using the DeviceDataControl object.
Contact createdContact = DeviceManagerFactory.getDeviceManager()
    .findContacts.createContact(aContact);

連絡先の検索を有効にするためのfindContactsメソッドの使用方法

DeviceFeaturesデータ・コントロールに含まれるfindContactsメソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーがデバイスのアドレス帳から1つ以上の連絡先を検索できるようになります。

MAFでは、デバイスのインタフェースを表示して、必要に応じてfindContactsフィールドにデータを事前移入できます。findContactsメソッドでは、フィルタ文字列と検索する(そして、見つかったコンタクト先の一部として戻す)フィールド名のリストを使用します。フィルタ文字列には、コンタクト先内の検索する任意の項目を指定できます。findContactsメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。

findContacts操作では、次の引数を使用します。

  • contactFields: 必須パラメータ。このパラメータは、findContacts操作によって生成されるContactオブジェクトに含めるフィールドを指定するために使用します。フィールドはカンマで区切ります(スペースの有無は関係ありません)。

  • filter: コンタクト先をフィルタするために使用する検索文字列。(文字列) (デフォルト: "")

  • multiple: findContacts操作から複数のコンタクト先を戻すかどうかを決定します。(ブール) (デフォルト: false)

注意:

次のリストに含まれていないフィールド名を渡すと、findContacts操作の戻り値がnullになる場合があります。また、Contactのフィールドの引数に指定したフィールドのみが、Contactオブジェクトの一部として戻されます。

次のリストに示すContactのプロパティを渡して、検索に使用し、見つかったコンタクト先の一部として戻すことができます。

  • id: グローバルに一意な識別子

  • displayName: エンド・ユーザーへの表示に適した、このコンタクト先の名前

  • name: 人物名のすべてのコンポーネントを含むオブジェクト

  • nickname: コンタクト先のカジュアルな名前。このフィールドをnullに設定すると、空の文字列として保存されます。

  • phoneNumbers: コンタクト先のすべての電話番号の配列

  • emails: コンタクト先のすべての電子メール・アドレスの配列

  • addresses: コンタクト先のすべての住所の配列

  • ims: コンタクト先のすべてのインスタント・メッセージング(IM)・アドレスの配列(imsプロパティは、このリリースではサポートされていません。)

    注意:

    このリリースでは、MAFはContactプロパティのimsをサポートしていません。imsプロパティのあるコンタクト先を作成する場合、MAFはimsプロパティなしでコンタクト先を保存します。その結果、ユーザーがimsに基づいて検索を実行しようとすると、コンタクト先を検索できなくなります。また、ユーザーが「検索」フィールドにimsを入力しようとすると、imsnullとして戻されます。

  • organizations: コンタクト先のすべての組織の配列

  • birthday: コンタクト先の誕生日。プログラムで連絡先の誕生日フィールドを設定することや、アドレス帳に連絡先を永続化することはできませんが、オペレーティング・システムのアドレス帳アプリケーションを使用してこのフィールドを手動で設定できます。

  • note: コンタクト先に関するメモ。このフィールドをnullに設定すると、空の文字列として保存されます。

  • photos: コンタクト先の写真の配列

  • categories: コンタクト先のすべてのユーザー定義カテゴリの配列。

  • urls: コンタクト先に関連付けられたWebページの配列

注意:

findContactsメソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。

DeviceFeaturesデータ・コントロールを使用してfindContacts操作をカスタマイズするには:

  1. JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからfindContacts操作をドラッグし、リンクボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。

    リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、findContacts操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してfindContacts操作を実行できます。

    パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが前述のContactの様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してfindContacts操作を実行できます。

  2. 操作から戻されるオブジェクトのContactを、「データ・コントロール」パネルにあるfindContacts操作の下からドラッグし、フォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。findContacts操作を実行すると、結果がこのフォームに表示されます。

次の例は、findContactsメソッドに指定できる引数値を示しています。

// This will return just one contact with only the ID field:
Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("", "", false);

// This will return all contacts with only ID fields:
Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("", "", true);

// This will return just one contact with all fields:
Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("*", "", false);

// This will return all contacts with all fields:
Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("*", "", true);

// These will throw an exception as contactFields is a required argument and cannot be null:
DeviceManagerFactory.getDeviceManager().findContacts(null, "", false);
DeviceManagerFactory.getDeviceManager().findContacts(null, "", true);

// These will throw an exception as the filter argument cannot be null:
DeviceManagerFactory.getDeviceManager().findContacts("", null, false);
DeviceManagerFactory.getDeviceManager().findContacts("", null, true);

注意:

渡されるContactのフィールドは、文字列(カンマで区切られたフィールドを含む)です。いずれかの引数がnullとしてメソッドに渡された場合、例外がスローされます。

次のJavaScript例は、姓でコンタクト先を検索し、コンタクト先の名前、電話番号、電子メール、住所およびメモを取得する方法を示しています。

var filter = ["name", "phoneNumbers", "emails", "addresses", "note"];
 
var options = new ContactFindOptions();
options.filter="FamilyName";
 
// Contacts, like many other device-specific features, are accessed from 
// the global 'navigator' object in JavaScript.
navigator.contacts.find(filter, onSuccess, onFail, options);
 
function onSuccess(contacts)
{
  alert ("Find Contact call succeeded! Number of contacts found = " + contacts.length);
}
 
function onFail(Error)
{
  alert("Find Contact failed: " + Error.code);
}

次のJava例は、姓でコンタクト先を検索し、コンタクト先の名前、電話番号、電子メール、住所およびメモを取得する方法を示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

/*
 * Find Contact - Find contact by family name.
 *
 * See if we can find the contact that we just created.
 */

String familyName = "FamilyName"

// Access device features in Java code by acquiring an instance of the  
// DeviceManager from the DeviceManagerFactory.
Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts(
    "name,phoneNumbers,emails,addresses,note", familyName, true); 

連絡先の更新を有効にするためのupdateContactメソッドの使用方法

DeviceFeaturesデータ・コントロールに含まれるupdateContactメソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーがデバイスのアドレス帳に含まれる連絡先を更新できるようになります。

MAFでは、デバイスのインタフェースを表示して、必要に応じてupdateContactフィールドにデータを事前移入できます。この項の最後の例に示すように、updateContactメソッドはContactオブジェクトをパラメータとして使用し、更新されたupdateContactオブジェクトを戻します。

updateContactメソッドおよびContactオブジェクトの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。Contactのプロパティについては、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」も参照してください。

注意:

入力パラメータとして必要なContactオブジェクトは、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」の説明に従って、findContactsメソッドを使用することによって検索できます。nullのContactオブジェクトがメソッドに渡された場合、例外がスローされます。

DeviceFeaturesデータ・コントロールを使用してupdateContact操作をカスタマイズするには:

  1. JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからupdateContact操作をドラッグし、リンクまたはボタンとしてページ・デザイナ上にドロップします。

    リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、updateContact操作に対するContactオブジェクトのパラメータを入力するよう求められます。このパラメータは、Java BeanクラスからContactを戻すために使用されるマネージドBeanのプロパティを参照するEL式である必要があります。マネージドBeanにContactオブジェクトのゲッターがすでに含まれている場合は、EL式ビルダーを使用して、パラメータの値を設定できます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してupdateContact操作を実行できます。「連絡先の作成を有効にするためのcreateContactメソッドの使用方法」に、Contactオブジェクトを作成するマネージドBeanコードの例を示しています。

  2. 戻されたContactオブジェクトを「データ・コントロール」パネルにあるupdateContact操作の下からドラッグし、フォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。updateContact操作を実行すると、結果がこのフォームに表示されます。

次の例は、コンタクト先の電話番号を更新および追加する方法を示しています。

次のJavaScript例は、updateContactの使用方法を示しています。

function updateContact(contact)
{
  try
  {
    if (null != contact.phoneNumbers)
    {
      alert("Number of phone numbers = " + contact.phoneNumbers.length);
      var numPhoneNumbers = contact.phoneNumbers.length;
      for (var j = 0; j < numPhoneNumbers; j++)
      {
        alert("Type: " + contact.phoneNumbers[j].type + "\n" +
              "Value: "  + contact.phoneNumbers[j].value + "\n" +
              "Preferred: "  + contact.phoneNumbers[j].pref);
 
        contact.phoneNumbers[j].type = "mobile";
        contact.phoneNumbers[j].value = "408-555-0100";
      }
 
      // save
      contact.save(onSuccess, onFailure);
    }
    else
    {
      //alert ("No phone numbers found in the contact.");
    }
  }
  catch(e)
  {
    alert("updateContact - ERROR: " + e.description);
  }
}
 
function onSuccess()
{
  alert("Update Contact successful.");
}
 
function onFailure(Error)
{
  alert("Update Contact failed: " + Error.code);
}

次のJavaScript例は、updateContactを使用して既存の電話番号に電話番号を追加する方法を示しています。

function updateContact(contact)
{
  try
  {
    var phoneNumbers = [1];
    phoneNumbers[0] = new ContactField('home', '650-555-0123', true);
    contact.phoneNumbers = phoneNumbers;
 
    // save
    contact.save(onSuccess, onFailure);
  }
  catch(e)
  {
    alert("updateContact - ERROR: " + e.description);
  }
}
 
function onSuccess()
{
  alert("Update Contact successful.");
}
 
function onFailure(Error)
{
  alert("Update Contact failed: " + Error.code);
}

次のJavaコード例は、updateContactを使用してコンタクト先の電話番号、電子メール・タイプおよび郵便番号を更新する方法を示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

/*
 * Update Contact - Updating phone number, email type, and adding address postal code
 */
String familyName = "FamilyName";
String phoneNumberNewValue = "650-555-0123";
String emailTypeNew = "work";
String addressPostalCode = "91234";

Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts(
    "name,phoneNumbers,emails,addresses,note", familyName, true); 

// Assuming there was only one contact returned, we can use the first contact in the array.
// If more than one contact is returned then we have to filter more to find the exact contact 
// we need to update.

foundContacts[0].getPhoneNumbers()[0].setValue(phoneNumberNewValue);
foundContacts[0].getEmails()[0].setType(emailTypeNew);
foundContacts[0].getAddresses()[0].setPostalCode(addressPostalCode);

Contact updatedContact = DeviceManagerFactory.getDeviceManager().updateContact(foundContacts[0]);

次のJava例は、updateContactを使用して既存の電話番号に電話番号を追加する方法を示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

String additionalPhoneNumberValue = "408-555-0123";
String additionalPhoneNumberType = "mobile";
// Create a new phoneNumber that will be appended to the previous one.
ContactField additionalPhoneNumber = new ContactField();
additionalPhoneNumber.setType(additionalPhoneNumberType);
additionalPhoneNumber.setValue(additionalPhoneNumberValue);

foundContacts[0].setPhoneNumbers(new ContactField[] { additionalPhoneNumber });

// Access device features in Java code by acquiring an instance of the DeviceManager 
// from the DeviceManagerFactory.
Contact updatedContact = DeviceManagerFactory.getDeviceManager().updateContact(foundContacts[0]);

注意:

updateContactメソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。

連絡先の削除を有効にするためのremoveContactメソッドの使用方法

DeviceFeaturesデータ・コントロールには、findContactsを使用して検索した連絡先をデバイスのアドレス帳から削除するためのremoveContactメソッドがあります。removeContact操作をカスタマイズする手順を使用してください。

DeviceFeaturesデータ・コントロールに含まれるremoveContactメソッドをMAFアプリケーションで使用すると、連絡先を管理するためのデバイスのインタフェースとファイル・システムを利用して、ユーザーがデバイスのアドレス帳から連絡先を削除できるようになります。MAFでは、デバイスのインタフェースを表示して、必要に応じてremoveContactフィールドにデータを事前移入できます。この項の最後の例に示すように、removeContactメソッドはContactオブジェクトをパラメータとして使用します。

注意:

入力パラメータとして必要なContactオブジェクトは、「連絡先の検索を有効にするためのfindContactsメソッドの使用方法」の説明に従って、findContactsメソッドを使用することによって検索できます。

DeviceFeaturesデータ・コントロールを使用してremoveContact操作をカスタマイズするには:

  1. JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからremoveContact操作をドラッグし、リンクボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。

    リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、removeContact操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してremoveContact操作を実行できます。

    パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが様々なContactのフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してremoveContact操作を実行できます。

  2. 操作から戻されるオブジェクトのContactを、「データ・コントロール」パネルにあるremoveContact操作の下からドラッグし、フォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。removeContact操作を実行すると、結果がこのフォームに表示されます。

この項の最後にある例は、findContactsを使用して見つかったコンタクト先を削除する方法を示しています。removeContactメソッドとContactオブジェクトについては、MAF JavadocのDeviceDataControlクラスおよびCordovaのドキュメント(http://cordova.apache.org/)を参照してください。

注意:

Androidでは、removeContact操作を実行しても完全にはコンタクト先が削除されません。removeContactメソッドをコールしてコンタクト先を削除すると、「(不明)」の付いた名前がアプリケーション内のコンタクト先リストに表示されます。

次のJavaScriptコード例は、removeContactの使用方法を示しています。

// Remove the contact from the device
contact.remove(onSuccess,onError);
 
function onSuccess()
{
  alert("Removal Success");
}
 
function onError(contactError)'
{
  alert("Error = " + contactError.code);
}

次のJavaコード例は、removeContactの使用方法を示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

/*
 * Remove the contact from the device
 */
Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts(
    "name,phoneNumbers,emails,addresses", familyName, true);

// Assuming there is only one contact returned, we can use the first contact in the array.
// If more than one contact is returned we will have to filter more to find the  
// exact contact we want to remove.

// Access device features in Java code by acquiring an instance of the DeviceManager 
// from the DeviceManagerFactory.
DeviceManagerFactory.getDeviceManager().removeContact(foundContacts[0]);

注意:

removeContactメソッドのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。

地理的位置を有効にするためのstartLocationMonitorメソッドの使用方法

DeviceFeaturesデータ・コントロールに含まれるstartLocationMonitorメソッドをMAFアプリケーションで使用すると、デバイスの地理的位置情報サービスを使用して、デバイスの位置を取得および追跡できます。

MAFで公開されているAPIを使用すると、デバイスの現在位置を取得できるため、特定の時点におけるデバイスの現在位置を取得したり、定期的にその情報をサブスクライブできます。この項の最後にある例は、地理的位置情報を使用してデバイスの位置変化をサブスクライブする方法と、デバイスの位置を取得する方法を示しています。startLocationMonitorメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。

MAFにより公開されるAPIを使用するには、MAFに用意されているGeolocationコア・プラグインも有効化する必要があります。AndroidプラットフォームにデプロイするMAFアプリケーションの場合、Geolocation - Google Play Services (cordova-plugin-geolocation-play-services)というプラグインはMAF APIを介してGoogle Playサービス・ロケーションAPIを起動するため、このプラグインを有効化することをお薦めします。

注意:

Androidでは、APIレベル26 (Android 8.0)以上を使用するデバイスで(MAFアプリケーションでGeolocation - Google Play Servicesコア・プラグインを使用した場合)、altitudeAccuracyプロパティがサポートされています。

DeviceFeaturesデータ・コントロールを使用してデバイスの位置変化をリスニングするには:

JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからstartLocationMonitor操作をページ・デザイナ上にドラッグし、リンクまたはボタンとしてドロップします。「アクションの編集」ダイアログで入力を要求されたら、次のリストを参照するか、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスのstartLocationMonitorメソッドに関する項を参照して、その操作でサポートされるパラメータの値をフィールドに入力します。

  • enableHighAccuracy: trueの場合、位置を最も正確に取得できる方法を使用します。これは単なるヒントであり、オペレーティング・システムでは考慮されない場合があります。多くの場合、デバイスには、携帯電話基地局の三角測量、Wi-Fiホットスポットの参照、実際のGPSなど、位置の修正を取得するためのいくつかの異なるメカニズムがあります。falseを指定すると、正確性の低い位置を受け入れることになりますが、この場合、レスポンスの速度が向上し、消費電力が低下する可能性があります。

  • updateInterval: 更新の受信頻度をミリ秒単位で定義します。位置の更新は、指定した頻度では配信されない場合があります。オペレーティング・システムは、デバイスの位置の大きな変化が検出されるまで待機してから、別の位置の更新をトリガーする場合があります。

  • locationListener: 次のシグネチャを含むBeanメソッドに解決されるEL式。

    void methodName(Location newLocation)
    

    このEL式は、位置の更新を受信するたびに評価されます。たとえば、viewScope.LocationListenerBean.locationUpdated(#{}で囲みません)と入力した後、LocationListenerBeanというBeanをviewScope内に定義し、次のシグネチャを含むメソッドを実装します。

    public void locationUpdated(Location currentLocation) {
      System.out.println(currentLocation);
      // To stop subscribing to location updates, invoke the following:
      // DeviceManagerFactory.getDeviceManager().clearWatchPosition(
      //     currentLocation.getWatchId());
    }
    

    注意:

    EL式の評価結果としてlocationListenerの名前が必要でないかぎり、locationListenerを指定するためにEL構文#{LocationListenerBean.locationUpdate}を使用しないでください。

この項の最後にある例は、DeviceManager.startUpdatingPositionメソッドを使用してデバイスの位置変化をサブスクライブする方法を示しています。

JavaScriptを使用してデバイスの位置変化をサブスクライブする方法の例は、Cordovaのドキュメント(http://cordova.apache.org/)を参照してください。

locationListenerによって指定されたコールバック関数内に戻されるパラメータは、次のとおりです。

  • double getAccuracy: m単位の緯度と経度を示す座標の精度レベル。

  • double getAltitude: m単位の楕円体高度。

  • double getLatitude: 10進度単位の緯度。

  • double getLongitude: 10進度単位の経度。

  • double getAltitudeAccuracy: m単位の高度座標の精度レベル。

  • double getHeading: 真北から時計回りに計測した度単位で示される進行方向

  • double getSpeed: m/秒単位で指定される、デバイスの現在の対地速度

  • long getTimestamp: Unixエポックからのミリ秒単位の経過時間で示されるタイムスタンプの作成

  • String getWatchId: 定期的な位置の更新をサブスクライブするときのみ使用します。後から位置の更新のサブスクライブを停止するために使用できる一意のID

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;
import oracle.adf.model.datacontrols.device.GeolocationCallback;
import oracle.adf.model.datacontrols.device.Location;

// Subscribe to location updates that will be delivered every 20 seconds, with high accuracy.
// As you can have multiple subscribers, let's identify this one as 'MyGPSSubscriptionID'.
// Notice that this call returns the watchID, which is usually the same as the watchID passed in.
// However, it may be different if the specified watchID conflicts with an existing watchID,
// so be sure to always use the returned watchID.
String watchID = DeviceManagerFactory.getDeviceManager().startUpdatingPosition(20000, true, "
       "MyGPSSubscriptionID", new GeolocationCallback() {
    public void locationUpdated(Location position) {
        System.out.println("Location updated to: " + position);
    }
});

// The previous call returns immediately so that you can continue processing. 
// When the device's location changes, the locationUpdated() method specified in  
// the previous call will be invoked in the context of the current feature.

// When you wish to stop being notified of location changes, call the following method:
DeviceManagerFactory().getDeviceManager().clearWatchPosition(watchID);

startLocationMonitorメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。

次の例は、DeviceManager.getCurrentPositionを使用してデバイスの現在位置を(1回)取得する方法を示しています。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;
import oracle.adf.model.datacontrols.device.Location;

// Get the device's current position, with highest accuracy, and accept a cached location that is 
// no older than 60 seconds.
Location currentPosition = DeviceManagerFactory.getDeviceManager().getCurrentPosition(60000, true);
System.out.println("The device's current location is: latitude=" + currentPosition.getLatitude() + 
    ", longitude=" + currentPosition.getLongitude());

ファイルの表示を有効にするためのdisplayFileメソッドの使用方法

DeviceFeaturesデータ・コントロールに含まれるdisplayFileメソッドを使用すると、MAFアプリケーションでデバイスにあるファイルを表示できます。

プラットフォームに応じて、アプリケーション・ユーザーはPDF、イメージ・ファイル、Microsoft Officeドキュメントおよびその他の様々なファイル・タイプを表示できます。iOSでは、アプリケーション・ユーザーは、サポートされているファイルをMAFアプリケーション内でプレビューできます。またユーザーは、それらのファイルをサードパーティ・アプリケーションで開く、電子メールで送信する、プリンタに送信するなどの操作を行うこともできます。

Androidでは、すべてのファイルがサードパーティ・アプリケーション内で開かれます。アプリケーション・ユーザーは、ファイルを表示する間はMAFアプリケーションを離れますが、Androidデバイスの戻るボタンをタップすることによって、MAFアプリケーションに戻ることができます。所定のファイルを開くことができるアプリケーションがデバイス内に存在しない場合は、エラーが表示されます。サードパーティ・アプリケーションに渡して開くファイルは、MAFアプリケーションがアプリケーションのパッケージ・ドメインの外のfile:// URIを渡す場合にAndroidの制限に準拠するように、次の親ディレクトリのいずれかの子である必要があります。
  • AdfmfJavaUtilities.TemporaryDirectory

  • AdfmfJavaUtilities.ApplicationDirectory

  • AdfmfJavaUtilities.DeviceOnlyDirectory

  • AdfmfJavaUtilities.DownloadDirectory

displayFileメソッドの機能は、デバイスのローカル・ファイルを表示することのみです。つまり、リモート・ファイルは最初にダウンロードする必要があります。ダウンロードしたファイルを保存する必要のあるディレクトリ・ルートに戻るには、AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.DownloadDirectory)を使用します。iOSでは、この場所はアプリケーションによって異なりますが、Androidでは、この場所として外部ストレージ・ディレクトリが参照されます。この外部ストレージ・ディレクトリは公的にアクセス可能であるため、サードパーティ・アプリケーションを使用して、そこに格納されているファイルを読み取ることができます。

displayFileメソッドがファイルを開く例の詳細は、サンプルのMAFアプリケーションで説明されているDeviceDemoサンプル・アプリケーションを参照してください。

表15-7 サポートされるファイル・タイプ

iOS Android

サポートされるファイル・タイプの詳細は、Apple iOS開発サイト(http://developer.apple.com/library/ios/navigation/)にある、Quick Lookプレビュー・コントローラに関するドキュメントを参照してください。

特定のMIMEタイプがデバイスにインストールされている場合、このMAFによって、そのタイプに関連付けられたビューアが起動されます。特定のファイル・タイプを表示するためのフレームワークは組み込まれていません。そのファイル・タイプを開くことができるアプリケーションがデバイスにインストールされていない場合は、MAFアプリケーションによってエラーが表示されます。

iWorkドキュメント

Microsoft Officeドキュメント(Office 97以降)

リッチ・テキスト・フォーマット(RTF)ドキュメント

PDFファイル

イメージ

Uniform Type Identifier (UTI)がpublic.text typeに準拠しているテキスト・ファイル

カンマ区切り(csv)ファイル

DeviceFeaturesデータ・コントロールを使用してdisplayFile操作をカスタマイズするには:

  1. JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからdisplayFile操作をドラッグし、リンクボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。

    リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、displayFile操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してdisplayFile操作を実行できます。

    パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してdisplayFile操作を実行できます。

次の例は、displayFileメソッドを使用してファイルを表示する方法を示しています。displayFileメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。

import oracle.adf.model.datacontrols.device.DeviceManagerFactory;

 URL remoteFileUrl;
        InputStream is;
        BufferedOutputStream fos;
        try {
           
            // Open connection to remote file; fileUrl here is a String containing the URL to the remote file.
            remoteFileUrl = new URL(fileUrl);
            URLConnection connection = remoteFileUrl.openConnection();
            is = new BufferedInputStream(connection.getInputStream());
            // Saving the file locally as 'previewTempFile.<extension>'
            String fileExt = fileUrl.substring(fileUrl.lastIndexOf('.'), fileUrl.length());
            String tempFile = "/previewTempFile" + fileExt;
            File localFile = null;
            // Save the file in the DownloadDirectory location
            localFile = new File(AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.DownloadDirectory) + tempFile);
            if (localFile.exists()) {
                localFile.delete();
            }
            // Use buffered streams to download the file.
            fos = new BufferedOutputStream(new FileOutputStream(localFile));
            byte[] data = new byte[1024];
            int read = 0;
            while ((read = is.read(data)) != -1) {
                fos.write(data, 0, read);
            }
            is.close();
            fos.close();
 
            // displayFile takes a URL string which has to be encoded on iOS.
            // iOS does not handle "+" as an encoding for space (" ") but
            // expects "%20" instead.  Also, the leading slash MUST NOT be
            // encoded to "%2F".  We will revert it to a slash after the
            // URLEncoder converts it to "%2F".
            StringBuffer buffer = new StringBuffer();
            String path = URLEncoder.encode(localFile.getPath(), "UTF-8");
            // replace "+" with "%20"
            String replacedString = "+";
            String replacement = "%20";
            int index = 0, previousIndex = 0;
            index = path.indexOf(replacedString, index);
            while (index != -1) {
                buffer.append(path.substring(previousIndex, index)).append(replacement);
                previousIndex = index + 1;
                index = path.indexOf(replacedString, index + replacedString.length());
            }
            buffer.append(path.substring(previousIndex, path.length()));
            // Revert the leading encoded slash ("%2F") to a literal slash ("/").
            if (buffer.indexOf("%2F") == 0) {
                buffer.replace(0, 3, "/");
            }
 
            // Create URL and invoke displayFile with its String representation.
            URL localURL = null;
            if (Utility.getOSFamily() == Utility.OSFAMILY_ANDROID) {
                localURL = new URL("file", "localhost", localFile.getAbsolutePath());
            }
            else if (Utility.getOSFamily() == Utility.OSFAMILY_IOS)
            {
                localURL = new URL("file", "localhost", buffer.toString());
            }
            DeviceManagerFactory.getDeviceManager().displayFile(localURL.toString(), "remote file");
        } catch (Throwable t) {
            System.out.println("Exception caught: " + t.toString());
        }

addLocalNotificationメソッドとcancelLocalNotificationメソッドを使用してローカル通知を管理する方法

DeviceFeaturesデータ・コントロールに含まれるaddLocalNotificationメソッドとcancelLocalNotificationメソッドをMAFアプリケーションで使用すると、通知を管理するためのデバイスのインタフェースを利用できるようになり、ユーザーはローカル通知のスケジュールまたは取消しができるようになります。

DeviceFeaturesデータ・コントロールを使用してaddLocalNotificationまたはcancelLocalNotification操作をカスタマイズするには:

  1. JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからaddLocalNotificationまたはcancelLocalNotification操作をドラッグし、ボタンリンクリスト・アイテムまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。

    ボタン、リンクまたはリスト・アイテム: 「アクション・バインディングの編集」ダイアログが表示され、addLocalNotificationまたはcancelLocalNotification操作の引数の値を入力するよう求められます。このダイアログの詳細は、Oracle JDeveloperのオンライン・ヘルプを参照してください。実行時にページに表示されるボタン、リンクまたはリスト・アイテムをクリックすると、入力した値を使用してaddLocalNotificationまたはcancelLocalNotification操作を実行できます。

    パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。このダイアログの詳細は、Oracle JDeveloperのオンライン・ヘルプを参照してください。実行時に、アプリケーション・ユーザーが様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してaddLocalNotificationまたはcancelLocalNotification操作を実行できます。

選択した操作のパラメータを構成するために使用する「アクション・バインディングの編集」ダイアログを図に示します。この例では、cancelLocalNotification操作のnotificationIDがaddLocalNotification操作の結果にバインドされます。

図15-17 ローカル通知のスケジュール用のバインドの設定

図15-17の説明が続きます
「図15-17 ローカル通知のスケジュール用のバインドの設定」の説明

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

図15-18 addLocalNotificationの結果へのcancelLocalNotificationのバインド

図15-18の説明が続きます
「図15-18 addLocalNotificationの結果へのcancelLocalNotificationのバインド」の説明

addLocalNotificationおよびcancelLocalNotificationメソッドの詳細は、Oracle Mobile Application Framework Java APIリファレンスDeviceDataControlクラスに関する項を参照してください。「ローカル通知の管理」を参照してください。「通知の概要」も参照してください。

デバイス・プロパティに関する必知事項

MAFには、アプリケーションでの動的な動作をサポートするために、Java、JavaScriptおよびELからアクセスできるプロパティがあります。プロパティのリストを確認して、問合せ方法、予期される戻り値およびアプリケーション・ライフサイクル期間のプロパティの変化について理解してください。

アプリケーションには、特定のデバイスの特性や機能に依存する機能が含まれる場合があります。たとえば、デバイスの画面の向きによって異なるユーザー・インタフェースを提示したり、デバイスで地理的位置情報がサポートされる場合のみマッピング機能を有効にすることなどが考えられます。MAFでは、このような動的な動作をサポートするために、Java、JavaScriptおよびELからアクセスできる様々なプロパティが用意されています。表15-8に、これらのプロパティをリストし、問合せ方法、予期される戻り値およびアプリケーションのライフサイクル期間にそのプロパティが変化する可能性があるかどうかに関する情報も提供します。この項の最後にある例は、JavaScriptを使用してこれらのプロパティにアクセスする方法を示しています。

注意:

デバイス・プロパティのタイムアウト値は、1分に設定されます。デバイスの操作に、許可されたタイムアウトよりも長い時間がかかると、タイムアウト・エラーが表示されます。

表15-8 デバイス・プロパティと対応するEL式

プロパティ 静的/動的 EL式 サンプル値 Java API

device.name

静的

#{deviceScope.device.name}

"iPhone Simulator"、"Joe Smith's iPhone"

DeviceManager.getName()

device.platform

静的

#{deviceScope.device.platform}

"iPhone Simulator"、"iPhone"

DeviceManager.getPlatform()

device.version

静的

#{deviceScope.device.version}

"4.3.2"、"5.0.1"

DeviceManager.getVersion()

device.os

静的

#{deviceScope.device.os}

"iOS"

DeviceManager.getOs()

device.model

静的

#{deviceScope.device.model}

"x86_64"、"i386"、"iPhone3,1"

DeviceManager.getModel()

device.phonegap

静的

#{deviceScope.device.phonegap}

"1.0.0"

DeviceManager.getPhonegap()

hardware.hasCamera

静的

#{deviceScope.hardware.hasCamera}

"true"、"false"

DeviceManager.hasCamera()

hardware.hasContacts

静的

#{deviceScope.hardware.hasContacts}

"true"、"false"

DeviceManager.hasContacts()

hardware.hasTouchScreen

静的

#{deviceScope.hardware.hasTouchScreen}

"true"、"false"

DeviceManager.hasTouchScreen()

hardware.hasGeolocation

静的

#{deviceScope.hardware.hasGeolocation}

"true"、"false"

DeviceManager.hasGeolocation()

hardware.hasAccelerometer

静的

#{deviceScope.hardware.hasAccelerometer}

"true"、"false"

DeviceManager.hasAccelerometer()

hardware.hasCompass

静的

#{deviceScope.hardware.hasCompass}

"true"、"false"

DeviceManager.hasCompass()

hardware.hasFileAccess

静的

#{deviceScope.hardware.hasFileAccess}

"true"、"false"

DeviceManager.hasFileAccess()

hardware.hasLocalStorage

静的

#{deviceScope.hardware.hasLocalStorage}

"true"、"false"

DeviceManager.hasLocalStorage()

hardware.hasMediaPlayer

静的

#{deviceScope.hardware.hasMediaPlayer}

"true"、"false"

DeviceManager.hasMediaPlayer()

hardware.hasMediaRecorder

静的

#{deviceScope.hardware.hasMediaRecorder}

"true"、"false"

DeviceManager.hasMediaRecorder()

hardware.networkStatus

動的

#{deviceScope.hardware.networkStatus}

"wifi"、"2g"、"unknown"、"none"脚注 2

DeviceManager.getNetworkStatus()

hardware.screen.width

動的

#{deviceScope.hardware.screen.width}

320、480

DeviceManager.getScreenWidth()

hardware.screen.height

動的

#{deviceScope.hardware.screen.height}

480、320

DeviceManager.getScreenHeight()

hardware.availableWidth

動的

#{deviceScope.hardware.screen.availableWidth}

<= 320、<= 480

DeviceManager.getAvailableScreenWidth()

hardware.availableHeight

動的

#{deviceScope.hardware.screen.availableHeight}

<= 480、<= 320

DeviceManager.getAvailableScreenHeight()

hardware.screen.dpi

静的

#{deviceScope.hardware.screen.dpi}

160、326

DeviceManager.getScreenDpi()

hardware.screen.diagonalSize

静的

#{deviceScope.hardware.screen.diagonalSize}

9.7、6.78

DeviceManager.getScreenDiagonalSize()

hardware.screen.scaleFactor

静的

#{deviceScope.hardware.screen.scaleFactor}

1.0、2.0

DeviceManager.getScreenScaleFactor()

脚注2

wifiおよび2Gの両方が有効になっている場合、wifi2Gよりも優先されるため、ネットワーク・ステータスはwifiになります。

次の例は、JavaScriptを使用してデバイス・プロパティにアクセスする方法を示しています。

<!DOCTYPE html>
<html>
  <head>
    <title>Device Properties Example</title>
 
    <script type="text/javascript" charset="utf-8" src="cordova-2.2.0.js"></script>
    <script type="text/javascript" charset="utf-8">

    // Wait for Cordova to load
    //
    //document.addEventListener("deviceready", onDeviceReady, false);
    document.addEventListener("showpagecomplete",onDeviceReady,false);
 
    // Cordova is ready
    //
    function onDeviceReady() {
        adf.mf.api.getDeviceProperties(properties_success, properties_fail);
    }
    
    function properties_success(response) {
      try {
        var element = document.getElementById('deviceProperties');
        var device = response.device;
        var hardware = response.hardware;
        element.innerHTML = 'Device Name:              ' + device.name            + '<br />' +
                            'Device Platform:          ' + device.platform        + '<br />' +
                            'Device Version:           ' + device.version         + '<br />' +
                            'Device OS:                ' + device.os              + '<br />' +
                            'Device Model:             ' + device.model           + '<br />' +
                            'Hardware Screen Width:    ' + hardware.screen.width  + '<br />' +
                            'Hardware Screen Height:   ' + hardware.screen.height + '<br />' +
      } catch (e) {alert("Exception: " + e);}
    }
    
    function properties_fail(error) {
        alert("getDeviceProperties failed");
    }

    </script>
  </head>
  <body>
    <p id="deviceProperties">Loading device properties...</p>
  </body>
</html>

注意:

JavaScript関数をshowpagecompleteイベントに宣言的にバインドするには、次の例のように、amx:clientListenerタグを<amx:view>の直接の子として追加します。

<amx:clientListener type="showpagecomplete" method="myShowPageCompleteHandler"/>

クライアント・リスナー(clientListener)コンポーネントの詳細は、「クライアント・リスナーの使用方法」を参照してください。

属性の検証

MAFでは、検証ルールがバインディング属性に設定され、データ・コントロール・レイヤーで検証が行われます。データ・コントロールによって公開される属性に対するバリデータと、属性の検証メッセージの両方を構成できます。

モバイル・アプリケーション・フレームワークでは、バインディング属性で検証ルールが設定された状態で、データ・コントロール・レイヤーで検証が実行されます。属性の検証は、バインディングに対するsetValue操作中に、システム内の単一点で実行されます。

データ・コントロールによって公開される属性に対して、次のバリデータを定義できます。

  • 比較バリデータ

  • 長さバリデータ

  • リスト・バリデータ

  • 範囲バリデータ

特定の属性に対してすべてのバリデータが実行され、成功しないすべてのバリデータに対してネストされた例外がスローされます。属性の検証メッセージを定義し、実行時に検証ルールを起動するときに表示できます。「入力の検証」および「検証ルールの追加方法」を参照してください。

注意:

JSONの制限により、BigDecimalが保持できる値はDoubleの範囲内となり、BigIntegerが保持できる値はLongの範囲内となります。許可された値よりも大きい数値を使用するには、toStringBigDecimalまたはBigIntegerでコールし、値をStringとしてシリアライズ(解除)します。

表15-9に、長さバリデータでサポートされる検証の組合せをリストします。

表15-9 長さ検証

比較タイプ バイト 文字

Equals

サポート

サポート

Not Equals

サポート

サポート

Less Than

サポート

サポート

Greater Than

サポート

サポート

次以下

サポート

サポート

次以上

サポート

サポート

Between

サポート

サポート

表15-10表15-11に、範囲バリデータでサポートされる検証の組合せを示します。

表15-10 範囲検証

比較タイプ バイト 文字 倍精度 浮動小数 整数 長整数 短整数

Between

サポート

サポート

サポート

サポート

サポート

サポート

サポート

Not Between

サポート

サポート

サポート

サポート

サポート

サポート

サポート

表15-11 範囲検証: math、sqlおよびutilパッケージ

比較タイプ java.math.BigDecimal java.math.BigInteger java.sql.Date java.sql.Time java.sql.Timestamp java.util.Date

Between

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

Not Between

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

表15-12に、リスト・バリデータでサポートされる検証の組合せをリストします。

表15-12 リスト検証

比較タイプ 文字列

In

サポート

Not In

サポート

表15-13表15-14に、比較バリデータでサポートされる検証の組合せを示します。

表15-13 比較検証

比較タイプ バイト 文字 倍精度 浮動小数 整数 長整数 短整数 文字列

Equals

サポート

サポート

サポート

サポート

サポート

サポート

サポート

サポート

Not Equals

サポート

サポート

サポート

サポート

サポート

サポート

サポート

サポート

Less Than

サポートなし

サポート

サポート

サポート

サポート

サポート

サポート

サポートなし

Greater Than

サポートなし

サポート

サポート

サポート

サポート

サポート

サポート

サポートなし

次以下

サポートなし

サポート

サポート

サポート

サポート

サポート

サポート

サポートなし

次以上

サポートなし

サポート

サポート

サポート

サポート

サポート

サポート

サポートなし

表15-14 比較検証: java.math、java.sqlおよびjava.utilパッケージ

比較タイプ java.math.BigDecimal java.math.BigInteger java.sql.Date java.sql.Time java.sql.Timestamp java.util.Date

Equals

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

Not Equals

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

Less Than

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

Greater Than

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

次以下

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

次以上

サポート

サポート

サポートなし

サポートなし

サポートなし

サポートなし

検証ルールの追加方法

MAFのユーザーは、検証ルールを定義できます。データ・コントロール構造ファイルの概要エディタにある「属性」ページを使用して、データ・コントロール・オブジェクトに検証ルールを追加する手順を使用してください。

検証ルールは、様々なユース・ケースに合わせて定義できます。宣言的検証ルールをエンティティ・オブジェクトに追加するには、データ・コントロール構造ファイルの「概要」エディタにある「属性」ページを使用します。

検証規則を追加するには:

  1. 「データ・コントロール」パネルで、データ・コントロール・オブジェクトを右クリックして、「定義の編集」を選択します。
  2. データ・コントロール構造ファイルの「概要」エディタで、「属性」ページを選択します。

    図15-19 「属性」ページの「検証ルール」タブ

    図15-19の説明が続きます
    「図15-19 「属性」ページの「検証ルール」タブ」の説明
  3. ページの下部にある「検証ルール」タブを選択し、「追加」をクリックします。表示された「検証ルールの追加」ダイアログで、検証ルールと失敗処理を定義します。

    図15-20 検証規則の追加

    図15-20の説明が続きます
    「図15-20 検証規則の追加」の説明

バリデータのメタデータに関する必知事項

データ・コントロール構造のメタデータXMLファイルには、バリデータのメタデータが格納されています。

バリデータのメタデータは、設計時にデータ・コントロール構造のメタデータXMLファイル内に配置されます。次の例は、サンプルの長さバリデータを示しています。

<?xml version="1.0" encoding="windows-1252" ?>
<!DOCTYPE PDefViewObject SYSTEM "jbo_03_01.dtd">
<PDefViewObject
   xmlns="http://xmlns.oracle.com/bc4j"
   Name="Product"
   Version="12.1.1.61.36"
   xmlns:validation="http://xmlns.oracle.com/adfm/validation">
   <DesignTime>
      <Attr Name="_DCName" Value="DataControls.ProductListBean"/>
      <Attr Name="_SDName" Value="mobile.Product"/>
   </DesignTime>
   <PDefAttribute
      Name="name">
      <validation:LengthValidationBean
         Name="nameRule0"
         OnAttribute="name"
         CompareType="GREATERTHAN"
         DataType="BYTE"
         CompareLength="5"
         Inverse="false"/>
   </PDefAttribute>
</PDefViewObject>

バックグラウンド・スレッドの使用方法

バックグラウンドのJavaスレッドを使用してデータ・モデルの値を更新できますが、更新がユーザー・インタフェースと正しく同期されるように注意する必要があります。

バックグラウンド・スレッドは、データをフェッチする場合(たとえば、リモート・サーバーから)、または複雑なアルゴリズムで値を計算する場合に役立ちます。バックグラウンド・スレッドを使用してフェッチやデータ値は計算できますが、アプリケーションのユーザー・インタフェース・スレッドと競合する可能性があるため、直接それを使用してアプリケーションのデータ・モデル・オブジェクトを更新しないでください。

バックグラウンド・スレッドからモデル・オブジェクトを更新するには、MafExecutorService APIを使用して、モデルの更新を実行するJavaのRunnableを発行します。まず、新規または更新されたモデルの値(フェッチ済または計算済)を取得して、次の例に示すようにRunnableを発行してアプリケーションのデータ・モデル・オブジェクトの値を更新します。

        //  First, fetch/compute new data values.
        fetchUpdatedValues();

        //  Next, use a Runnable to update the model objects.
        MafExecutorService.execute(new Runnable()
        {
          public void run()
          {
            doModelUpdates();
            AdfmfJavaUtilities.flushDataChangeEvent();
          }
        });

注意:

アプリケーションが無応答にならないよう、発行されるタスクは短時間のものにする必要があります。タスクを実行する前に機能がロックされる可能性があり、このロックはタスクが完了するまでは解放されません。

oracle.adfmf.framework.api.MafExecutorService.executeクラスの詳細はOracle Mobile Application Framework Java APIリファレンスを参照してください。

MAFアプリケーションのバックグラウンド・スレッド処理の許可

iOSまたはAndroidプラットフォームでのバックグラウンド・スレッド処理を許可するには、oracle.adfmf.framework.api.AdfmfContainerUtilities APIのbeginBackgroundTaskおよびendBackgroundTaskメソッドを使用します。

iOSおよびAndroidプラットフォームでは、アプリケーションがフォアグラウンド・アプリケーションでない場合や、デバイスがロックされている場合、オペレーティング・システムによりそのアプリケーションが一時停止または終了されることがあります。これにより、ネットワーク・ダウンロードなどの、一時停止することが望ましくない進行中のアクティビティが停止する場合があります。通常、アプリケーションが再開されると、ほとんどのアクティビティは簡単にリカバリできます。ただし、デバイスが長い間停止された場合、長時間実行のネットワーク・リクエストなどの一部のアクティビティはリカバリされないことがあります。

注意:

Windowsはフォアグラウンドでないアプリケーションを一時停止することはないため、Windowsプラットフォームではこの問題は発生しません。

実行中のアプリケーションが一時停止されないようにするには、MAFに用意されているoracle.adfmf.framework.api.AdfmfContainerUtilities Java APIを使用してください。バックグラウンド・タスクとして実行する必要がある操作をラップするには、beginBackgroundTaskメソッドおよびendBackgroundTaskメソッドを使用します。このAPIの詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。

次のコードは、この機能を実装する方法を示しています。

...
public class StartBackgroundTask {

  //Start button is enabled. 
  private boolean buttonStatus = true;
  private String buttonString = "Start to download";
  private PropertyChangeSupport _propertyChangeSupport = new PropertyChangeSupport(this);
  private Object taskId = null;

  public StartBackgroundTask() {
  }

  public void startTask(ActionEvent actionEvent) {
    buttonStatus = !buttonStatus;
		
    if (!buttonStatus) {
      this.setButtonString("Downloading");
      taskId = AdfmfContainerUtilities.beginBackgroundTask("Download task description", null);
      ExecutorService cachedThreadPool = ThreadUtil.getInstance().getCachedThreadPool();
      cachedThreadPool.submit(() -> {
        try {
          //Specify the URL for the big file to download
          URL url = new URL("http://...");
          HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
          int responseCode = httpConn.getResponseCode();
          if (responseCode == HttpURLConnection.HTTP_OK) {
            InputStream inputStream = httpConn.getInputStream();
            int bytesRead = -1;
            byte[] buffer = new byte[1024];
            while ((bytesRead = inputStream.read(buffer)) != -1) {
            ;
            }
            inputStream.close();
           }
	      }
	      catch(Exception e) {
	      ;
	      }
      AdfmfContainerUtilities.endBackgroundTask(taskId);
      taskId = null;
      this.setButtonString("Start to download");
      buttonStatus = !buttonStatus;
      });
    }
    else {
      if(taskId != null) {
      AdfmfContainerUtilities.endBackgroundTask(taskId);
      taskId = null;
    }
    this.setButtonString("Start to download");
   }
  }

  public void setButtonString(String buttonString) {
    String oldButtonString = this.buttonString;
    this.buttonString = buttonString;
    _propertyChangeSupport.firePropertyChange("buttonString", oldButtonString, buttonString);
  }

  public String getButtonString() {
    return buttonString;
  }

}

データ変更イベントの使用

JDeveloperでは、データ変更イベントを単純化するために、プロパティ変更リスナー・パターンを使用します。多くの場合、JDeveloperを使用して、Beanのプロパティ・アクセサからの通知を参照するために必要なソース・コードを生成できます。これを行うには、「アクセサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェックボックスを選択します

PropertyChangeSupportオブジェクトが自動的に生成され、新たに生成されたsetterメソッドにfirePropertyChangeへのコールが含まれます。また、addPropertyChangeListenerおよびremovePropertyChangeListenerメソッドが追加されるため、プロパティ変更リスナーは、このオブジェクトを使用して自身を登録および登録解除できます。これを使用してフレームワークはクライアント・キャッシュにプッシュする変更を取得し、データが変更されたことをユーザー・インタフェース・レイヤーに通知します。

注意:

PropertyChangeSupportオブジェクトを手動でクラスに追加する場合は、addPropertyChangeListenerおよびremovePropertyChangeListenerメソッドも(これらの明示的なメソッド名を使用して)含める必要があります。

プロパティ変更のみでは、すべてのデータ変更通知は解決されません。たとえば、データ・コントロールによってラップされたBeanがあり、アイテムのコレクションの公開が必要な場合が考えられます。リストの個々のアイテムが変更されたときはプロパティ変更で十分ですが、カーディナリティが変更されたときは十分ではありません。この場合、コレクション全体のプロパティ変更を起動すると、パフォーマンスが低下する可能性があるため、かわりにコレクションのデルタのみを更新します。これを行うには、ProviderChangeSupportクラスを使用して、単純なプロパティ変更に必要なデータよりも多くのデータを公開する必要があります。プロバイダ変更イベントはプロパティ変更イベントと似ていますが、個別のプロパティのみを対象とするのではなく、プロバイダ全体に適用されます。

注意:

ProviderChangeSupportオブジェクトは、自動的には生成されません。このオブジェクトはaddProviderChangeListenerremoveProviderChangeListenerおよびgetKey()メソッドとともに、(これらの明示的なメソッド名を使用して)手動でクラスに追加する必要があります。getKey()メソッドは、プロバイダに対して一意の値を生成する文字列を返す必要があります。getKey()メソッドをクラスに追加するかわりに、図に示す概要エディタを使用して、データ・コントロール構造ファイルのキー属性として、データ・コントロールで属性を指定します

図15-21 データ・コントロールのデータ・コントロール構造ファイルでのキー属性の選択

図15-21の説明が続きます
「図15-21 データ・コントロールのデータ・コントロール構造ファイルでのキー属性の選択」の説明

プロバイダ変更は、データ・コントロールによってラップされたBeanで公開されている動的なコレクションを保持しているときのみ必要になるため、起動するプロバイダ変更イベントは、次のいくつかのタイプのみになります。

  • fireProviderCreate: 新しい要素をコレクションに追加する場合

  • fireProviderDelete: 要素をコレクションから削除する場合

  • fireProviderChange: コレクション内の1つの要素を変更する場合(リスト全体のリフレッシュを回避するのに必要です)

  • fireProviderRefresh: 同時に複数の変更をコレクションに加え、単純にクライアントにコレクション全体のリフレッシュを要求した方がよいと判断した場合(これは一括操作でのみ使用する必要があります)

ProviderChangeSupportクラスは、コレクション要素に関連する通知を送信するために使用され、これによって、Java Beanデータ・コントロール内で変更が発生したときにコンポーネントを適切に更新できます。このクラスが従うパターンは、自動的に生成されるPropertyChangeSupportクラスと似ていますが、ProviderChangeSupportとともに使用されるイベント・オブジェクトでは、操作のタイプや変更された要素のキーと位置などの詳細情報を送信します。ProviderChangeSupportでは、コレクションに対する要素(プロバイダ)の追加や削除など、コレクションに対する構造的な変更を取得します。PropertyChangeSupportでは、コレクション内の個々のアイテムに対する変更を取得します。

次の例は、ProviderChangeSupportを使用して、コレクションの要素に対する構造的な変更(子を追加または削除する場合など)に関する通知を送信する方法を示しています。ProviderChangeListenerインタフェースおよびProviderChangeEventProviderChangeSupportクラスの詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。

public class NotePad {
   private static List s_notes = null;
 
/* manually adding property change listener as well as provider change listener. */
   protected transient PropertyChangeSupport 
                       propertyChangeSupport = new PropertyChangeSupport(this);
   protected transient ProviderChangeSupport 
                       providerChangeSupport = new ProviderChangeSupport(this);
 
    public NotePad() {
        …
    }
 
    public  mobile.Note[] getNotes() {
        mobile.Note n[] = null;
 
        synchronized (this) {
            if(s_notes.size() > 0) {
                n = (mobile.Note[])
                    s_notes.toArray(new mobile.Note[s_notes.size()]);
            }
            else {
                n = new mobile.Note[0];
            }
        }
 
        return n;
    }
 
    public void addNote() {
        System.out.println("Adding a note ....");
        Note n = new Note();
        int s = 0;
        
        synchronized (this) {
            s_notes.add(n);
            s = s_notes.size();
        }
 
        System.out.println("firing the events");
        providerChangeSupport.fireProviderCreate("notes", n.getUid(), n);
    }
    
    public void removeNote() {
        System.out.println("Removng a note ....");
        if(s_notes.size() > 0) {
            int end = -1;
            Note n = null;
 
            synchronized (this) {
                end = s_notes.size() - 1;
                n = (Note)s_notes.remove(end);
            }
            
            System.out.println("firing the events");
            providerChangeSupport.fireProviderDelete("notes", n.getUid());
        }
    }
    
    public void RefreshNotes() {
        System.out.println("Refreshing the notes ....");
 
        providerChangeSupport.fireProviderRefresh("notes");
    }
    
    public void addProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.addProviderChangeListener(l);
    }
 
    public void removeProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.removeProviderChangeListener(l);
    }
 
    protected String   status;    
    
    /* --- JDeveloper generated accessors --- */
 
    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }
 
    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }
 
    public void setStatus(String status) {
        String oldStatus = this.status;
        this.status = status;
        propertyChangeSupport.firePropertyChange("status", oldStatus, status);
    }
 
    public String getStatus() {
        return status;
    }
}

データ変更は、JVMレイヤーからのレスポンス・メッセージや戻り値とともに、クライアントに(キャッシュするために)戻されます。これにより、JDeveloperではユーザー・インタフェースに対してリフレッシュするイベントと更新の数を縮小し、可能なかぎりフレームワークの効率を上げることができます。

ただし、バックグラウンド・スレッドで実行時間の長い処理(Webサービスの相互作用、データベースの相互作用、コストのかかる計算など)に対処し、ユーザー・アクションに依存しないユーザー・インタフェースへの通知を行うことが必要になる場合もあります。AMXページのデータを更新して、値が変更されたデータ・フィールドの現在の値を反映させる場合、AdfmfJavaUtilities.flushDataChangeEventをコールして現在キューに入っているデータ変更をクライアントに強制することによって、AMXページ全体のリロードによるパフォーマンスの低下を回避できます。

注意:

flushDataChangeEventメソッドは、バックグラウンド・スレッドからのみ実行できます。

次の例は、flushDataChangeEventメソッドを使用してクライアントへの保留中のデータ変更を強制する方法を示しています。oracle.adfmf.framework.api.AdfmfJavaUtilities.flushDataChangeEventに関する詳細は、Oracle Mobile Application Framework Java APIリファレンスを参照してください。

 
/* Note – Simple POJO used by the NotePad managed bean or data control wrapped bean */	 
 
package mobile;
 
import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;
 
 
/**
 * Simple note object
 * uid   - unique id - generated and not mutable
 * title - title for the note - mutable
 * note  - note comment - mutable
 */
public class Note {
    /* standard JDeveloper generated property change support */
    protected transient PropertyChangeSupport 
                       propertyChangeSupport = new PropertyChangeSupport(this);
 
    private static boolean s_backgroundFlushTestRunning = false;
 
 
    public Note() {
        this("" + (System.currentTimeMillis() % 10000));
    }
 
    public Note(String id) {
        this("UID-"+id, "Title-"+id, "");
    }
 
    public Note(String uid, String title, String note) {
        this.uid     = uid;
        this.title   = title;
        this.note    = note;
    }
 
 
    /* update the current note with the values passed in */
    public void updateNote(Note n) {
        if (this.getUid().compareTo(n.getUid()) == 0) {
            this.setTitle(n.getTitle());
            this.setNote(n.getNote());
        } 
        else {
            throw new IllegalArgumentException("note");
        }
    }
 
 
    /* background thread to simulate some background process that make changes */
    public void startNodeBackgroundThread(ActionEvent actionEvent) {
        Thread backgroundThread   = new Thread() {
            public void run() {
                System.out.println("startBackgroundThread enter - " + 
                                                      s_backgroundFlushTestRunning);
                
                s_backgroundFlushTestRunning = true;
                for(int i = 0; i <= iterations; ++i) {
                    try {
                        System.out.println("executing " + i + " of " + iterations + "
                                " iterations.");
                        
                        /* update a property value */                    
                        if(i == 0) {
                            setNote("thread starting");
                        }
                        else if( i == iterations) {
                            setNote("thread complete");
                            s_backgroundFlushTestRunning = false;                        
                        }
                        else {
                            setNote("executing " + i + " of " + iterations + " iterations.");
                        }
                        setVersion(getVersion() + 1);
                        setTitle("Thread Test v" + getVersion());
                        AdfmfJavaUtilities.flushDataChangeEvent();  /* key line */
                    }
                    catch(Throwable t) {
                        System.err.println("Error in the background thread: " + t);
                    }
 
                    try {
                        Thread.sleep(delay);  /* sleep for 6 seconds */
                    } 
                    catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        };
        
        backgroundThread.start();
    }
    
    protected String uid;
    protected String title;
    protected String note;
    protected int    version;
 
    protected int iterations = 10;
    protected int delay = 500;
    
    /* --- JDeveloper generated accessors --- */
 
    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }
 
    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }
 
    public String getUid() {
        return uid;
    }
 
    public void setTitle(String title) {
        String oldTitle = this.title;
        this.title = title;
        propertyChangeSupport.firePropertyChange("title", oldTitle, title);
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setNote(String note) {
        String oldNote = this.note;
        this.note = note;
        propertyChangeSupport.firePropertyChange("note", oldNote, note);
    }
 
    public String getNote() {
        return note;
    }
 
    public void setVersion(int version) {
        int oldVersion = this.version;
        this.version = version;
        propertyChangeSupport.firePropertyChange("version", oldVersion, version);
    }
 
    public int getVersion() {
        return version;
    }
 
    public void setIterations(int iterations) {
        int oldIterations = this.iterations;
        this.iterations = iterations;
        propertyChangeSupport.
                 firePropertyChange("iterations", oldIterations, iterations);
    }
 
    public int getIterations() {
        return iterations;
    }
 
    public void setDelay(int delay) {
        int oldDelay = this.delay;
        this.delay = delay;
        propertyChangeSupport.
                firePropertyChange("delay", oldDelay, delay);
    }
 
    public int getDelay() {
        return delay;
    }
}
	 
  
/* NotePad – Can be used as a managed bean or wrapped as a data control */
	   
package mobile;
 
import java.util.ArrayList;
import java.util.List;
 
import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;
import oracle.adfmf.java.beans.ProviderChangeListener;
import oracle.adfmf.java.beans.ProviderChangeSupport;
 
 
public class NotePad {
    private static List s_notes = null;
    private static boolean s_backgroundFlushTestRunning = false;
    
    protected transient PropertyChangeSupport propertyChangeSupport = 
                                                   new PropertyChangeSupport(this);
 
    protected transient ProviderChangeSupport 
        providerChangeSupport = new ProviderChangeSupport(this);
 
    public NotePad() {
        if (s_notes == null) {
            s_notes = new ArrayList();
            
            for(int i = 1000; i < 1003; ++i) {
                s_notes.add(new Note(""+i));
            }
        }
    }
 
    public  mobile.Note[] getNotes() {
        mobile.Note n[] = null;
 
        synchronized (this) {
            if(s_notes.size() > 0) {
                n = (mobile.Note[])s_notes.
                     toArray(new mobile.Note[s_notes.size()]);
            }
            else {
                n = new mobile.Note[0];
            }
        }
 
        return n;
    }
 
    public void addNote() {
        System.out.println("Adding a note ....");
        Note  n = new Note();
        int   s = 0;
        
        synchronized (this) {
            s_notes.add(n);
            s = s_notes.size();
        }
 
        System.out.println("firing the events");
        
        /* update the note count property on the screen */
        propertyChangeSupport.
             firePropertyChange("noteCount", s-1, s);
 
        /* update the notes collection model with the new note */
        providerChangeSupport.
             fireProviderCreate("notes", n.getUid(), n);
 
        /* to update the client side model layer */
        AdfmfJavaUtilities.flushDataChangeEvent();
    }
    
    public void removeNote() {
        System.out.println("Removing a note ....");
        if(s_notes.size() > 0) {
            int end = -1;
            Note n = null;
 
            synchronized (this) {
                end = s_notes.size() - 1;
                n = (Note)s_notes.remove(end);
            }
            
            System.out.println("firing the events");
            
            /* update the client side model layer */
            providerChangeSupport.fireProviderDelete("notes", n.getUid());
 
           /* update the note count property on the screen */
           propertyChangeSupport.firePropertyChange("noteCount", -1, end);
        }
    }
    
    public void RefreshNotes() {
        System.out.println("Refreshing the notes ....");
 
        /* update the entire notes collection on the client */
        providerChangeSupport.fireProviderRefresh("notes");
    }
    
    public int getNoteCount() {
        int size = 0;
        
        synchronized (this) {
            size = s_notes.size();
        }
       return size;
    }
 
    public void addProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.addProviderChangeListener(l);
    }
 
    public void removeProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.removeProviderChangeListener(l);
    }
 
    public void startListBackgroundThread(ActionEvent actionEvent) {
        for(int i = 0; i < 10; ++i) {
            _startListBackgroundThread(actionEvent);
            try {
                Thread.currentThread().sleep(i * 1234);
            } 
            catch (InterruptedException e) {
            }
        }
    }
    
    public void 
    _startListBackgroundThread(ActionEvent actionEvent) {
        Thread backgroundThread = new Thread() {
            public void run() {
                s_backgroundFlushTestRunning = true;
                
                for(int i = 0; i <= iterations; ++i) {
                    System.out.println("executing " + i + 
                          " of " + iterations + " iterations.");
                    
                    try {
                        /* update a property value */                    
                        if(i == 0) {
                            setStatus("thread starting");
                            addNote();  // add a note
                        }
                        else if( i == iterations) {
                            setStatus("thread complete");
                            removeNote();  // remove a note
                            s_backgroundFlushTestRunning = false;                        
                        }
                        else {
                            setStatus("executing " + i + " of " + 
                                    iterations + " iterations.");
                            
                            synchronized (this) {
                                if(s_notes.size() > 0) {
                                    Note n =(Note)s_notes.get(0);
                                
                                    n.setTitle("Updated-" + 
                                          n.getUid() + " v" + i);
                                }
                            }
                        }
                        AdfmfJavaUtilities.flushDataChangeEvent();
                    }
                    catch(Throwable t) {
                        System.err.
                        println("Error in bg thread - " + t);
                    }
 
                    try {
                         Thread.sleep(delay);
                    } 
                    catch (InterruptedException ex) {
                        setStatus("inturrpted " + ex);
                        ex.printStackTrace();
                    }
                }
            }
        };
        
        backgroundThread.start();
    }
 
    
    protected int iterations = 100;
    protected int delay      = 750;
 
    protected String   status;    
    
    /* --- JDeveloper generated accessors --- */
 
    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }
 
    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }
 
    public void setStatus(String status) {
        String oldStatus = this.status;
        this.status = status;
        propertyChangeSupport.firePropertyChange("status", oldStatus, status);
    }
 
    public String getStatus() {
        return status;
    }
 
    public void setIterations(int iterations) {
        int oldIterations = this.iterations;
        this.iterations = iterations;
        propertyChangeSupport.firePropertyChange("iterations", oldIterations, iterations);
    }
 
    public int getIterations() {
        return iterations;
    }
 
    public void setDelay(int delay) {
        int oldDelay = this.delay;
        this.delay = delay;
        propertyChangeSupport.firePropertyChange("delay", oldDelay, delay);
    }
 
    public int getDelay() {
        return delay;
    }
}
	 

StockTrackerサンプル・アプリケーションでは、データ変更イベントでJavaを使用してデータ変更をユーザー・インタフェースに反映する方法の例を示します。このサンプル・アプリケーションおよびその他のサンプル・アプリケーションの詳細は、「サンプルのMAFアプリケーション」を参照してください。