Oracle® Fusion Middleware Oracle Application Development Frameworkモバイル開発者ガイド 11g リリース2 (11.1.2.3.0) B70750-01 |
|
![]() 前 |
![]() 次 |
この章では、ADFモバイル・アプリケーションでデータ・バインディング、データ・コントロールおよびADFデータ・バインディング式言語(EL)を使用する方法について説明します。またこの章では、検証およびデータ変更イベントについても説明します。
この章では、次の項目について説明します。
ADFモデルによって、ユーザー・インタフェース・テクノロジとビジネス・サービス実装の分離を可能にする2つの概念(データ・コントロールと宣言的バインディング)が実装されています。データ・コントロールでは、関連するプロパティ、メソッド、タイプの情報を含め、サービスの操作とデータ・コレクションを表す標準のメタデータ・インタフェースを使用してビジネス・サービスの実装技術を抽象化します。JDeveloperを使用すると、その情報をアイコンとして表示し、ページ上にドラッグ・アンド・ドロップできます。宣言的なバインディングによって、データ・コントロール内のデータ・コレクションからのデータ・アクセスとその操作の実行の詳細が抽象化されます。実行時に、ADFモデル・レイヤーによって、適切なXMLファイルからデータ・コントロールおよびバインディングを記述した情報が読み取られ、ユーザー・インタフェースとビジネス・サービスの双方向の結合が実装されます。
ページのUIコンポーネントをサポートするバインディングのグループは、ページ定義ファイルというページ固有のXMLファイルに記述されます。ADF Modelレイヤーでは実行時にこのファイルが使用され、ページのバインディングがインスタンス化されます。これらのバインディングは、バインディング・コンテナと呼ばれるリクエスト・スコープ・マップに保持され、EL式#{bindings}
を使用して各ページ・リクエスト中にアクセスできます。この式により、現在のページのバインディング・コンテナが常に評価されます。「データ・コントロール」パネルから項目をドラッグし、それを特定のUIコンポーネントとしてページ上にドロップすることで、データバインドされたユーザー・インタフェースを設計できます。データ・コントロールを使用してUIコンポーネントを作成すると、そのコンポーネントを選択したデータ・コントロールにバインドするために必要なコードおよびオブジェクトがJDeveloperによって自動的に作成されます。
ADFモバイルにおけるデータ・コントロールの動作は、Oracle ADFにおける動作と似ています。JDeveloperの「データ・コントロール」パネル内に表示されるDeviceFeaturesデータ・コントロールを使用すると、データ・コントロールの主なデータ属性を(テキスト)フィールドとしてまたデータ・コントロールの操作をコマンド・オブジェクト(ボタン)として、アプリケーションにドラッグ・アンド・ドロップできます。これらのドラッグ・アンド・ドロップ・アクションによって、アプリケーション内のELバインディングが、作成されるコントロールに適したプロパティ内に生成されます。そのようなアクションに対応する通常のADFバインディング(データ・コントロール・ソースを指す汎用的なDataControls.dcx
ファイルや特定のページの参照をデータ・コントロールにリンクするページ・バインディングによって表されます)が提供され、ランタイムはアプリケーションの実行時にそれらのバインディングを処理できます。
データ・バインディングとデータ・コントロールの詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』と『Oracle Fusion Middleware Oracle Application Development Framework Java EE開発者ガイド』を参照してください。
ADFモバイルでは、そのADFモバイルAMXアプリケーション機能での式言語(EL)の使用がサポートされます。
ELは、データ・バインディングを有効化するために使用します。ELとOracle ADFの併用の概要については、次の資料を参照してください。
『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のFusion WebアプリケーションでのADFモデルの使用方法に関する項
『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のADFデータ・バインディングのEL式の作成に関する項
ADFオブジェクトは、アプリケーション・スコープ、セッション・スコープ、ページ・フロー・スコープなど、様々なスコープ内に存在します(『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のオブジェクト・スコープのライフサイクルに関する項を参照)。一方、ADFモバイルでは、次のスコープがサポートされます。
アプリケーション・スコープ
ページ・フロー・スコープ
プリファレンス・スコープ
ビュー・スコープ
デバイス・スコープ
アプリケーション・スコープの名前空間で定義されたEL式は、アプリケーションが存続するかぎり使用できます。ADFモバイルを使用すると、アプリケーションの一方のビューでアプリケーション・スコープを定義し、そのスコープをもう一方のビューで参照できます。
ADFモバイルAMX ELの実装は、Java Unified Expression Language (JUEL)プロジェクトに基づき、Expression Language Specification Version 2.1 (http://juel.sourceforge.net/
にあるJUELプロジェクトのページで確認できます。今後これを「仕様」と呼びます)に従って行いますが、次のような例外があります。
仕様の「1.2.1: Eval-expression」に記載されているとおり、式は即時に評価される場合と遅れて評価される場合があります。ADFモバイルAMX ELの実装では、ページのメタデータをロードするときに式を解析し、ここで解析されたオブジェクトへの参照を所有コンポーネントが保持します。式の評価は、実際にはコンポーネントで値のレンダリングのために式が必要になるまで行われません。ADFモバイルAMXでは遅延セマンティクのみがサポートされるため、即時構成式(${}
)を使用する式は解析を行いますが、その動作は遅延式(#{}
)と同じになります。
仕様の「1.17: Enums」に記載されているとおり、リテラル文字列を使用して列挙型の値に強制することはできません。その理由は、基礎となる必要な列挙操作がJ2MEでサポートされないためです。
アクティブな画面のバインディング・コンテナは、ルートEL式#{bindings}
から参照できます。別の画面のバインディング・コンテナは、式#{data.PageDefName}
から参照できます。ADFモバイルAMXバインディング・オブジェクトは、バインディング・コンテナ#{bindings.Name}
から名前で参照されます。
表9-1は、実行時にADFモバイルAMXバインディング・オブジェクトの値にアクセスするためのEL式で使用できるプロパティをリストしています。表では、これらのプロパティをアルファベット順にリストしています。
表9-1 実行時プロパティ
実行時プロパティ | 説明 | イテレータ | アクション | 属性 | ツリー |
---|---|---|---|---|---|
|
実行時バインディング用のJavaクラス・オブジェクトを戻します。 |
あり |
あり |
あり |
あり |
|
データのコレクションを公開します。 |
なし |
なし |
なし |
あり |
|
イテレータが指している現在の行へのアクセスを提供します。 |
あり |
なし |
なし |
なし |
|
イテレータの関連データ・プロバイダを戻します。 |
あり |
なし |
なし |
なし |
|
|
あり |
なし |
なし |
なし |
|
アクション・バインディングの状態に応じて、 |
なし |
あり |
なし |
なし |
|
解決されたときに、名前付きアクションまたは |
なし |
あり |
なし |
なし |
|
バインディングが関連付けられているすべての表示属性について、UIヒントの名前/値ペアのリストを戻します。次の名前の付いた値がサポートされています。
|
なし |
なし |
あり |
あり |
|
現在の属性の値を戻すか設定します。 |
なし |
なし |
あり |
なし |
|
現在のリストの有効な属性に関連付けられた値のリストを戻します。 |
あり |
なし |
なし |
なし |
|
|
なし |
なし |
あり |
あり |
|
イテレータ・バインディングの行セットの範囲サイズを戻します。 |
あり |
なし |
なし |
あり |
|
レンジに含まれる最初の行のコレクションの絶対索引を戻します。 |
あり |
なし |
なし |
なし |
|
コレクションに含まれる行の合計数を戻します。 |
あり |
なし |
なし |
なし |
|
|
なし |
なし |
あり |
あり |
|
ツリーの子として使用できます。このバインディングおよび関連コンポーネントをレンダリングするかどうかを実行時に解決します。 |
なし |
なし |
なし |
あり |
脚注 1 EL語句のrow
は、コレクション・コンポーネントのコンテキスト内で使用されます。row
は単に、コレクションをレンダリングするときに、ADFモバイルAMXバインディング・オブジェクトからアクセスできる属性を含むコレクションの各要素に対する反復変数として機能します。属性とリスト・バインディングには、row
変数を使用してアクセスできます。そのような式の構文は、コレクションに含まれないバインディング・オブジェクトへのアクセスに使用される構文と同じで、#{row.bindings.Name.property}
のようにrow
変数を先頭の語句として追加します。
ELイベントは、共通語句を含む式が相互に同期して更新できるようにするため、ADFモバイルAMX UIの動作において重要な役割を果たします。
EL式は、様々なコンテキストで値を参照できます。例9-1は、2つの入力数値スライダ・コンポーネントの作成を示しており、各コンポーネントがapplicationScope
の値に関連付けられています。出力テキストでは、ELを使用して単純な追加式を計算結果とともに表示します。フレームワークでは、出力テキスト・ラベル内のEL式を解析するときに、その式に2つの値への参照が含まれていることを確認し、それら2つの値に基づく出力テキストのイベント・リスナー(第8.10項「イベント・リスナーの使用方法」を参照)を作成します。基礎となる式の値が変化すると、イベントがその値のすべてのリスナーに対して生成されます。
注意: (スコープ・オブジェクトではなく)マネージドBeanのプロパティを参照している場合、リスナーを追加する必要があります。詳細は、第9.2.4.2項「ADFマネージドBean」を参照してください。 |
例9-1 2つのコンポーネントを含むELイベントの生成
<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}"/>
例9-1では、2つのコンポーネントがそれぞれ1つの値を更新し、1つのコンポーネントが両方の値を使用します。例9-2は、いずれかの既存の値を参照する3つ目の入力数値スライダ・コンポーネントが追加された場合、動作は同じになることを示しています。
例9-2 3つのコンポーネントを含むELイベントの生成
<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}"/>
例9-2では、いずれかの入力数値スライダ・コンポーネントが#{applicationScope.X}
を更新すると、もう一方が出力テキストとともに自動的に更新されます。
アプリケーションのadf-config.xml
ファイル内にあるすべての<adf-property>
要素は、ELを通じて#{applicationScope.configuration}
ノードの子として公開されます。このため、たとえばadf-config.xml
が次の例のようになっている場合、#{applicationScope.configuration.key1}
の評価によってvalue1
が生成され、#{applicationScope.configuration.key2}
の評価によってvaue2
が生成されます。
<?xml version="1.0" encoding="windows-1252" ?> <adf-config xmlns="http://xmlns.oracle.com/adf/config" xmlns:config="http://xmlns.oracle.com/bc4j/configuration" xmlns:sec="http://xmlns.oracle.com/adf/security/config"> <adf-properties-child xmlns="http://xmlns.oracle.com/adf/config/properties"> <adf-property name="key1" value="value1"/> <adf-property name="key2" value="value2"/> </adf-properties-child> </adf-config>
また、デバイスでアクセシビリティ・モードが有効になっている場合、#{applicationScope.configuration.accessibilityEnabled}
はtrue
と評価されます。iOSデバイスでは、これはVoiceOver
がアクティブ化されることを意味します。Androidデバイスでは、これはTalkBack
がアクティブ化されることを意味します。
EL式は、JDeveloper式ビルダーで変数と演算子から値を選択することによって作成できます。この式ビルダーは、ELに対応した任意のプロパティの「プロパティ・インスペクタ」から起動できます。式ビルダーの使用の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のADFデータ・バインディングEL式の作成方法に関する項を参照してください。
Oracle ADFには、次の2つのELタイプがあります。
動的EL: ${EL expression}
遅延EL: #{EL expression}
ADFモバイルでは動的ELタイプがサポートされず、${EL expression}
が#{EL expression}
として処理されるため、式を定義するときにハッシュ記号( # )接頭辞を使用する必要があります。詳細は、第9.2.1.1項「即時および遅延評価」を参照してください。
ADFモバイルAMXページの式ビルダーでは、次のカテゴリを使用できます。
この項では、「ADFバインディング」カテゴリで使用できるオプションをリストします。バインディングとデータ・ノードは、同じ一連のサポートされているバインディングとプロパティを表示します。表9-2に、使用できるバインディング・タイプと、各バインディング・タイプでサポートされるプロパティをリストします。
bindings
表9-2に、使用できるバインディング・タイプと、各バインディング・タイプでサポートされるプロパティをリストします。
data
表9-2に、使用できるバインディング・タイプと、各バインディング・タイプでサポートされるプロパティをリストします。
securityContext
サポートされるプロパティは、次のとおりです。
authenticated
userGrantedPrivilege
userInRole
userName
表9-2 サポートされるバインディング・タイプ
バインディング・タイプ | プロパティ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ADFモバイル・アプリケーションでマネージドBeanを作成および使用し、追加のデータを格納したり、カスタム・コードを実行できます。ADFモバイル・アプリケーションへのマネージドBeanの追加は、Fusion WebアプリケーションにマネージドBeanを追加する場合と同じ方法で行います。
詳細は、次の項を参照してください。
『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のFusion WebアプリケーションでのマネージドBeanの使用方法に関する項。
JavaDemo。これはjdev_install
/jdeveloper/jdev/extensions/oracle.adf.mobile/Samples
ディレクトリ内のADFモバイルのサンプル・アプリケーションです。このサンプル・アプリケーションでは、Java Beanの使用方法とコンテナ・ユーティリティ・メソッドの起動方法を示します。詳細は、付録E「サンプルのADFモバイル・アプリケーション」を参照してください。
注意: コンポーネントを構成するときは、使用するバインディング・スタイルを十分に考慮してください。より具体的に言うと、標準的なバインディングをマネージドBeanバインディングと組み合せると、解釈を誤った動作が発生することがよくあります。これは、バインディング・インフラストラクチャとマネージドBeanインフラストラクチャとの間でクラス・インスタンスが一致する可能性が低いためです。バインディングが混在すると、UIに直接リンクされていないインスタンスの動作がコールされる場合があります。 |
サポートされるADFモバイル・マネージドBeanのスコープは、次のとおりです。
applicationScope
: 「ADFマネージドBean」のapplicationScope
ノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーション・スコープのマネージドBeanなど)。
pageFlowScope
: 「ADFマネージドBean」のpageFlowScope
ノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロー・スコープのマネージドBeanなど)。
viewScope
: 「ADFマネージドBean」のviewScope
ノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュー・スコープのマネージドBeanなど)。
式ビルダーで「ADFマネージドBean」カテゴリを選択すると、「マネージドBeanの作成」ボタンが表示されます。式ビルダーから直接マネージドBeanを作成するには、このボタンをクリックします。
図9-1は、ADFモバイル・マネージドBeanの内容と「マネージドBeanの作成」ボタンの例を示しています。
ADFモバイル・ランタイムでは、自身をマネージドBeanプロパティの変更通知のリスナーとして登録することによって、Beanプロパティを参照するUIコンポーネントにバインドされたEL式が、プロパティの値が変更されたときに自動的に更新されるようにします。これらの通知をソースとして参照するには、Beanのプロパティ・アクセッサにコードを追加する必要があります。Beanのプロパティ・アクセッサから、通知をソースとして参照するために必要なコードを自動的に生成するには、「アクセッサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェック・ボックスを選択します(図9-2を参照)。
ELを通じて単にBeanメソッドまたはプロパティを参照する場合、このコードを追加する必要はありませんが、Beanに格納された値が変化する場合や、特にその変更が、1つ以上のプロパティ値を変更するBeanメソッドの実行による二次的な影響など、間接的なものである場合、それらの値に依存するEL式のアクティブ・フォームへのレンダリングを最新の状態に保つ必要があります。プロパティの変更とPropertyChangeSupport
クラスについては、第9.7項「データ変更イベント」を参照してください。
注意: 機能の |
「ADFモバイル・オブジェクト」カテゴリでは、次のオプションを使用できます。
applicationScope
: applicationScope
ノードには、アプリケーション・レベルで定義されたものがすべて含まれます(アプリケーション・スコープのマネージドBeanなど)。
deviceScope
: deviceScope
ノードには、デバイス・レベルで定義されたものがすべて含まれます(デバイス・スコープのマネージドBeanなど)。ADFモバイルでは、次のdeviceScope
プロパティがサポートされます。
device
model
name
os
phonegap
platform
version
hardware
hasAccelerometer
hasCamera
hasCompass
hasContacts
hasFileAccess
hasGeolocation
hasLocalStorage
hasMediaPlayer
hasMediaRecorder
hasTouchScreen
networkStatus
screen
(availableHeight
、availableWidth
、height
、width
)
pageFlowScope
: pageFlowScope
ノードには、ページ・フロー・レベルで定義されたものがすべて含まれます(ページ・フロー・スコープのマネージドBeanなど)。
preferenceScope
: preferenceScope
ノードには、アプリケーションと機能のすべてのプリファレンスが含まれます。
アプリケーションのプリファレンスは、「ADFモバイル・オブジェクト」→「preferenceScope」→「application」
で提供されます。
機能のプリファレンスは、「ADFモバイル・オブジェクト」→「preferenceScope」→「feature」→
「featureId」
で提供されます。
図9-3は、preferenceScope
ノードにあるプリファレンス要素の例を示しています。
プリファレンス要素では、PreferenceValue
要素を除き、Id
属性の値を式ビルダーのノード・ラベルとして使用します。PreferenceValue
要素では、Name
属性の値を式ビルダーのノード・ラベルとして使用します。
注意: EL式の文字列トークンにドット(.)や特殊文字または |
preferenceScope
のいくつかのサンプルEL式を次に示します。
viewScope
: このノードには、ビュー・レベルで定義されたものがすべて含まれます(ビュー・スコープのマネージドBeanなど)。
row
: row
変数ノードは、collectionModel
へのショートカットです。その名前は、親のイテレータ、リスト・ビューまたはカルーセル・コンポーネントのvar
属性の値です。このノードでは、次のディレクトリ構造がサポートされます。
バインディング
AttrName
class
format
hints
inputValue
items
iteratorBinding
label
name
updateable
AttrName
class
format
hints
inputValue
items
iteratorBinding
label
name
updateable
rowKey
図9-4は、row
変数ノードの内容の例を示しています。
viewControllerBundle
これはプロジェクト・レベルで定義されたリソース・バンドルを指すリソース・バンドル変数の名前です。このノードは、amx:loadBundle
要素がドロップされ、リソース・バンドルが作成された後にのみ表示されます。このノードの名前は、amx:loadBundleの変数名によって異なります。このノードには、バンドル内で宣言されたすべての文字列が表示されます。
図9-5は、viewControllerBundle
ノードの内容の例を示しています。例9-5は、viewControllerBundle
のAMXコードの例を示しています。
表9-3は、「プロパティ・インスペクタ」で「式ビルダー」オプションではなく「メソッド式ビルダー」オプションが提供されるプロパティを示しています。これらの唯一の違いは、メソッド式ビルダーが、選択されたプロパティに応じてマネージドBeanをフィルタして除外することです。
表9-3 編集可能な属性
プロパティ | 要素 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ADFモバイル・ランタイムでは、default
動作(例9-6を参照)を使用して特定の操作のアクションを起動します。これは、ページがロードされた後(最初のロードのみではありません)、そのページを繰り返し表示するときに、アクションをコールする必要があるためです。
例9-6 ADFモバイルAMXのinvokeAction
<invokeAction id="callSetCurrentRowWithKeyValue" Binds="setCurrentRowWithKeyValue" Refresh="default" RefreshCondition="#{requestScope.partyId != null}"/>
認識されるRefresh
属性の値とそれらの意味については、表9-5「Refreshの値と対応する起動条件」を参照してください。
ADFモバイル・ランタイムでは、実行可能ファイルを起動するための通知の発行に関する次の条件を検出できます。
A: 毎回のページの表示
B: モデルの状態を変更するアクションの発生(属性値の設定や新しい行へのナビゲートなど)
ランタイムでは、invokeAction
を、前述の条件に基づき、そのRefresh
およびRefreshCondition
属性の値(表9-5「Refreshの値と対応する起動条件」にリストされています)に従って実行します。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のRefreshプロパティの正しい使用方法に関する項を参照してください。
表9-5 Refreshの値と対応する起動条件
Refreshの値 | 起動条件 |
---|---|
|
AおよびB |
|
A |
|
A |
RefreshCondition
式が提供された場合、その式はinvokeAction
が実行される可能性が生じるたびに評価されます。false
と評価された場合、その発生に対する実行はスキップされます。
注意: イテレータ実行可能ファイルの場合は、 |
ADFモバイルにおけるバインディングの使用の詳細は、次の項を参照してください。
デフォルトで、同じRefresh
の値を使用して宣言されたinvokeAction
は、pagedef
で宣言された順序で実行されます。
注意: 先行者が実行されるかどうかは、それぞれの |
ADFモバイルで、ADFモバイルAMXページのELバインディングの検証は、Oracle ADFと同じように動作するJSFページのELの検証と同じメカニズムを使用します。ELの構成はページ・バインディングに対して検証され、メソッドの参照はマネージドBeanに対して検証されます。
検証の詳細は、第9.6項「検証の実行」を参照してください。
Java Beanデータ・コントロールでは、POJO (Plain Old Java Object)から自身のデータ構造を取得します。Java Beanデータ・コントロールを作成するには、(「アプリケーション」ウィンドウで)Javaクラス・ファイルを右クリックし、「データ・コントロールの作成」を選択します。Beanデータ・コントロールの作成は、EJBデータ・コントロールの作成と非常によく似ています。
注意: Java Beanがバックグラウンド・スレッドを使用してUI内のデータを更新する場合、手動で |
詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のFusion Webアプリケーションのデータ・コントロールに関する項と『Oracle Fusion Middleware Oracle Application Development Framework Java EE開発者ガイド』のADFデータ・コントロールを使用したビジネス・サービスの公開に関する項を参照してください。
ADFモバイルでは、一時変数として宣言されたJavaScript Object Notation (JSON)データBeanクラス変数にはシリアライズしません。一連のネストされたオブジェクトをシリアライズしないようにするには、それらを一時オブジェクトとして定義する必要があります。この方法を使用すると、オブジェクトのネストが原因で循環オブジェクトが作成されるのを防ぐこともできます。
次のシナリオを考えてみましょう。Employee
オブジェクトが、その子として従業員の上司を表すEmployee
オブジェクトを保持しているとします。その子を一時オブジェクトとして宣言しなかった場合、実行時に子のEmployee
オブジェクトを計算しようとすると、一連のネストされたシリアライズ・オブジェクトが作成されます。
ADFモバイルでは、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();
ADFモバイルでは、アプリケーション内でDeviceFeaturersデータ・コントロールを通じて使用できるデバイス固有の機能が公開されます。DeviceFeaturersデータ・コントロールは、新しいADFモバイル・アプリケーションを作成するときに「データ・コントロール」パネルに表示されるコンポーネントです。PhoneGap Java APIは、このデータ・コントロールを通じて抽象化されます。これにより、ADFモバイルAMXとして実装されたアプリケーション機能から、デバイスに埋め込まれた様々なサービスにアクセスできるようになります。DeviceFeaturesデータ・コントロールから提供される操作をADFモバイルAMXページ内にドラッグ・アンド・ドロップすることによって、デバイスに格納されたユーザーのコンタクト先を管理する機能の追加、電子メール・メッセージとSMSテキスト・メッセージの両方の作成と送信、デバイスの位置の確認、デバイスのカメラの使用およびデバイスのファイル・システムに格納されたイメージの取得を行うことができます。次の項では、これらの操作を宣言的に使用する方法や、JavaコードとJavaScriptを使用して実装する方法など、各操作について詳しく説明します。
ADFモバイル・アプリケーション・テンプレートを使用してアプリケーションを作成すると、自動的にDeviceFeaturesデータ・コントロールが「データ・コントロール」パネルに表示されます。図9-6は、「概要」エディタに表示されたDeviceFeaturesデータ・コントロールを示しています。次のメソッドを使用できます。
createContact
findContacts
getPicture
removeContact
sendEmail
sendSMS
startLocationMonitor
updateContact
ページを作成したら、DeviceFeaturesデータ・コントロールのメソッド(またはそれらのメソッド内にネストされたその他のオブジェクト)を「データ・コントロール」パネルから「ADFモバイルAMX」ビューにドラッグして、関連する機能にバインドされたコマンド・ボタンやその他のコンポーネントを作成できます。デフォルトのバインディングを受け入れるか、ELを使用してそれらのバインディングを変更できます。また、JavaScriptやJavaを使用して、機能を実装または構成することもできます。
DeviceManager
は、デバイスの機能へのアクセスを可能にするオブジェクトです。このオブジェクトのハンドルは、DeviceManagerFactory.getDeviceManager
をコールすることによって取得できます。次の項では、DeviceManager
オブジェクトを使用してgetPicture
やcreateContact
などのメソッドを起動する方法について説明します。
データ・コントロールをADFモバイル・アプリケーションに含める方法については、第7.3.2.4項「データ・コントロールのビューへの追加」を参照してください。
DeviceFeaturesデータ・コントロールに含まれるgetPicture
メソッドをADFモバイル・アプリケーションで使用すると、デバイスのカメラとフォト・ライブラリを活用し、エンド・ユーザーが写真を撮影したり、既存のイメージを取得できるようにすることが可能です。例9-7は、エンド・ユーザーがデバイスのカメラを使用して写真を撮影することを可能にするJavaScriptコードを示しています。例9-8と例9-9は、エンド・ユーザーが写真を撮影したり、保存済イメージを取得することを可能にするJavaコードを示しています。getPicture
メソッドについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
次のパラメータによって、イメージの取得元と、そのイメージを戻す方法が制御されます。
quality:
保存済イメージの質を設定します。範囲は1から100(100を含む)です。大きい数値を指定すると質は高くなりますが、ファイル・サイズも増大します。JPEGイメージ(encodingType
で指定します)にのみ適用されます。
destinationType:
戻り値の形式を次から選択します。
DeviceManager.CAMERA_DESTINATIONTYPE_DATA_URL (0)
: Base64でエンコードされた文字列としてイメージを戻します。この値は、プログラムで使用される場合、DeviceManager
.CAMERA_DESTINATION_DATA_URL
を使用する列挙としても指定されます。
DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI
(1)
: イメージ・ファイルのパスを戻します。この値は、プログラムで使用される場合、DeviceManager.CAMERA_DESTINATION_FILE_URI
を使用する列挙としても指定されます。
sourceType:
写真のソースを次から選択して設定します。
DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARY (0)
: ユーザーは保存済のイメージから選択できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_PHOTOLIBRARY
を使用する列挙としても指定されます。
DeviceManager.CAMERA_SOURCETYPE_CAMERA (1)
: ユーザーはデバイスのカメラを使用して写真を撮影できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_CAMERA
を使用する列挙としても指定されます。
DeviceManager.CAMERA_SOURCETYPE_SAVEDPHOTOALBUM
(2)
: ユーザーは既存のフォト・アルバムから選択できます。この値は、プログラムで使用される場合、DeviceManager.CAMERA_SOURCETYPE_SAVEDPHOTOALBUM
を使用する列挙としても指定されます。
allowEdit:
選択する前にイメージの単純な編集を許可するかどうかを選択します(ブール)。
encodingType:
戻されるイメージ・ファイルのエンコーディングを次から選択します。
DeviceManager.CAMERA_ENCODINGTYPE_JPEG
(0): 戻されるイメージをJPEGファイルとしてエンコードします。この値は、プログラムで使用される場合、DeviceManager.CAMERA_ENCODINGTYPE_JPEG
を使用する列挙としても指定されます。
DeviceManager.CAMERA_ENCODINGTYPE_PNG
(1): 戻されるイメージをPNGファイルとしてエンコードします。この値は、プログラムで使用される場合、DeviceManager.CAMERA_ENCODINGTYPE_PNG
を使用する列挙としても指定されます。
targetWidth:
幅をピクセル単位で設定してイメージのスケールを変更します。アスペクト比は維持されます。負の値または0の場合、イメージの元のディメンションが使用されます。
targetHeight:
高さをピクセル単位で設定してイメージのスケールを変更します。アスペクト比は維持されます。負の値または0の場合、イメージの元のディメンションが使用されます。
DeviceFeaturesデータ・コントロールを使用してgetPicture操作をカスタマイズするには:
「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからgetPicture
操作をドラッグし、ADFモバイルのボタンとしてページにドロップします。
ユーザーがよりきめ細かく制御できるようにするには、getPicture
操作をADFモバイルのパラメータ・フォームとしてドロップします。これにより、エンド・ユーザーは写真を撮影したり既存のイメージを選択する前に、設定を指定できるようになります。
アクションの編集ダイアログで、前述のすべてのパラメータの値を設定します。イメージがファイル名として戻されるように、destinationType
= 1
を指定するようにします。
getPicture
の戻り値をドラッグし、それを出力テキストとしてページ上にドロップします。
「共通コンポーネント」パネルで、「コンポーネント・パレット」から「イメージ」をドラッグし、ページ上にドロップします。
イメージのsource
属性を、getPicture
操作の戻り値に設定します。バインディングの式は、#{bindings.Return.inputValue}
である必要があります。
図9-7は、エンド・ユーザーのフォト・ライブラリからイメージを表示するためのバインディングを示しています。
このアプリケーションを実行すると、イメージ・チューザが自動的に表示され、エンド・ユーザーは表示するイメージを選択できます。イメージ・チューザが自動的に表示される理由は、イメージ・コントロールがgetPicture
操作の戻り値にバインドされており、それによってgetPicture
操作が起動するためです。
次に示すプラットフォーム固有の問題に留意してください。
iOS
いくつかのデバイスでメモリー・エラーが発生しないようにするには、qualityを50未満に設定します。
destinationType
FILE_URI
を使用すると、写真はアプリケーションの一時ディレクトリに保存されます。
アプリケーションの一時ディレクトリの内容は、アプリケーションの終了時に削除されます。記憶域の空き領域が問題になる場合は、navigator.fileMgr
APIを使用してこのディレクトリの内容を削除することもできます。
targetWidth
とtargetHeight
を使用するには、これらを両方とも指定する必要があります。一方または両方の値が負の値または0の場合、イメージの元のディメンションが使用されます。
Android
allowEdit
パラメータを無視します。
Camera.PictureSourceType.PHOTOLIBRARY
とCamera.PictureSourceType.SAVEDPHOTOALBUM
では、どちらも同じフォト・アルバムが表示されます。
Camera.EncodingType
はサポートされていません。パラメータは無視され、常にJPEGイメージが生成されます。
targetWidth
とtargetHeight
は、個別に指定できます。一方のパラメータが正の値で、もう一方が負の値またはゼロを使用して元のサイズを表す場合、正の値がそのディメンションに使用され、もう一方のディメンションは元のアスペクト比を維持するようにスケール変更されます。
destinationType
DATA_URL
を使用すると、イメージが大きい場合は使用可能なメモリーがすべて使用され、メモリー不足のエラーが発生する場合があります。通常は、デフォルトのイメージ・サイズを使用すると、この動作が発生します。targetWidth
とtargetHeight
を設定してイメージ・サイズを制限します。
例9-7は、ユーザーがデバイスのカメラを使用して写真を撮影することを可能にするJavaScriptコードを示しています。結果は、保存済イメージへのフルパスになります。
例9-7 getPictureのJavaScriptコード例
// The camera, like many other device-specific features, is accessed // from the global 'navigator' object in JavaScript. // Note that in the PhoneGap 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); }
例9-8は、ユーザーがデバイスのカメラを使用して写真を撮影することを可能にするJavaコードを示しています。結果は、保存済イメージへのフルパスになります。
例9-8 getPictureを使用して写真を撮影するための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);
例9-9は、ユーザーが保存済イメージを取得することを可能にするJavaコードを示しています。結果は、Base64でエンコードされたJPEGになります。
例9-9 getPictureを使用してイメージを取得するためのJavaコード例
import oracle.adf.model.datacontrols.device; // Retrieve a previously-saved image. The result will be a base64-encoded JPEG. String imageData = DeviceManagerFactory.getDeviceManager().getPicture(100, DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URL, DeviceManager.CAMERA_SOURCETYPE__PHOTOLIBRARY, false, DeviceManager.CAMERA_ENCODINGTYPE_JPEG, 0, 0);
DeviceFeaturesデータ・コントロールに含まれるsendSMS
メソッドをADFモバイル・アプリケーションで使用すると、デバイスのショート・メッセージ・サービス(SMS)テキスト・メッセージング・インタフェースを活用し、エンド・ユーザーがSMSメッセージを送受信できるようにすることが可能です。ADFモバイルでは、デバイスのSMSインタフェースを表示し、必要に応じて次のフィールドに事前にデータを移入できます。
to:
受信者をリストします(カンマ区切り)。
body:
メッセージの本文を追加します。
SMSテキスト・メッセージング・インタフェースが表示されたら、エンド・ユーザーはSMSを送信するか、それを取り消すことができます。デバイスとキャリアの制限により、SMSは自動的に送信できません。実際にSMSを送信できるのは、エンド・ユーザーのみです。
DeviceFeaturesデータ・コントロールを使用してsendSMS操作をカスタマイズするには:
SMSの送信のためページに対話型フォームを表示するには、sendSMS
操作を「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからドラッグし、ページ・デザイナ上にADFモバイルのパラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスのSMSインタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに事前に値が移入され、送信準備が整ったSMSが表示されます。
図9-8は、ページ上の編集可能なフォームを使用してSMSを送信するためのバインディングを示しています。
例9-10と例9-11は、エンド・ユーザーがデバイスのテキスト・メッセージング・インタフェースを使用してSMSメッセージを送信することを可能にするコード例を示しています。
sendSMS
メソッドについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
例9-10 sendSMSのJavaScriptコード例
adf.mf.api.sendSMS({to: "5551234567", body: "This is a test message"});
例9-11 sendSMSのJavaコード例
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. // Send an SMS to the phone number "5551234567" DeviceManagerFactory.getDeviceManager().sendSMS("5551234567", "This is a test message");
DeviceFeaturesデータ・コントロールに含まれるsendEmail
メソッドをADFモバイル・アプリケーションで使用すると、デバイスの電子メール・メッセージング・インタフェースを活用し、エンド・ユーザーが電子メール・メッセージを送受信できるようにすることが可能です。ADFモバイルでは、デバイスの電子メール・インタフェースを表示し、必要に応じて次のフィールドに事前にデータを移入できます。
to:
受信者をリストします(カンマ区切り)。
cc:
CC受信者をリストします(カンマ区切り)。
subject:
メッセージの件名を追加します。
body:
メッセージの本文を追加します。
bcc:
BCC受信者をリストします(カンマ区切り)。
attachments:
電子メールに添付するファイルの名前をリストします(カンマ区切り)。
mimeTypes:
添付ファイルに使用するMIMEタイプをリストします(カンマ区切り)。ADFモバイルで自動的にMIMEタイプを決定するには、nullを指定します。例9-12と例9-13のように、選択した添付ファイルのMIMEタイプのみを指定することもできます。
デバイスの電子メール・インタフェースが表示されたら、ユーザーは電子メールを送信するか、それを取り消すことができます。デバイスとキャリアの制限により、電子メールは自動的に送信できません。実際に電子メールを送信できるのは、エンド・ユーザーのみです。また、電子メールを送信するには、1つ以上の電子メール・アカウントを構成する必要があります。アカウントが構成されていない場合、電子メール・アカウントが見つからないことを示すエラーが表示されます。
DeviceFeaturesデータ・コントロールを使用してsendEmail操作をカスタマイズするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからsendEmail
操作をページ・デザイナ上にドラッグし、ADFモバイルのパラメータ・フォームとしてドロップします。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。実行時に、アプリケーション・ユーザーが前述の様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンを使用すると、デバイスの電子メール・インタフェースを表示できます。このインタフェースには、指定したすべてのフィールドに事前に値が移入され、送信準備が整った電子メールが表示されます。
図9-9は、ページ上の編集可能なフォームを使用して電子メールを送信するためのバインディングを示しています。
例9-12と例9-13は、エンド・ユーザーがデバイスの電子メール・インタフェースを使用して電子メール・メッセージを送信することを可能にするコード例を示しています。
sendEmail
メソッドについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
例9-12 sendEmailのJavaScriptコード例
// Populate an email to 'ann.li@corp.example.com', // copy 'joe.jones@corp.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@corp.example.com", cc: "joe.jones@corp.example.com", subject: "Test message", body: "This is a test message"}); // Populate the same email as before, but this time, also BCC // 'john.smith@corp.example.com' & 'jane.smith@corp.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@corp.example.com", cc: "joe.jones@corp.example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@corp.example.com,jane.smith@corp.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@corp.example.com", cc: "joe.jones@corp.example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@corp.example.com,jane.smith@corp.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@corp.example.com", cc: "joe.jones@corp.example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@corp.example.com,jane.smith@corp.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@corp.example.com", cc: "joe.jones@corp.example.com", subject: "Test message", body: "This is a test message"}); bcc: "john.smith@corp.example.com,jane.smith@corp.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.
例9-13 sendEmailの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@corp.example.com', copy 'joe.jones@corp.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@corp.example.com", "joe.jones@corp.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@corp.example.com' & 'jane.smith@corp.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@corp.example.com", "joe.jones@corp.example.com", "Test message", "This is a test message", "john.smith@corp.example.com,jane.smith@corp.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@corp.example.com", "joe.jones@corp.example.com", "Test message", "This is a test message", "john.smith@corp.example.com,jane.smith@corp.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@corp.example.com", "joe.jones@corp.example.com", "Test message", "This is a test message", "john.smith@corp.example.com,jane.smith@corp.example.com", "path/to/file1.txt,path/to/file2.png", ",image/png");
DeviceFeaturesデータ・コントロールに含まれるcreateContact
メソッドをADFモバイル・アプリケーションで使用すると、デバイスのコンタクト先を管理するためのインタフェースとファイル・システムを活用し、エンド・ユーザーが新しいコンタクト先を作成してデバイスのアドレス帳に保存できるようにすることが可能です。ADFモバイルでは、デバイスのインタフェースを表示し、必要に応じてContact
のフィールドに事前にデータを移入できます。例9-14のように、createContact
メソッドはContact
オブジェクトをパラメータとして使用し、作成されたContact
オブジェクトを戻します。createContact
メソッドとContact
オブジェクトについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。Contact
のフィールドについては、第9.5.5項「findContactsメソッドの使用方法」も参照してください。
DeviceFeaturesデータ・コントロールを使用してcreateContact操作をカスタマイズするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからcreateContact
操作をドラッグし、ADFモバイルのリンク、ボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。
リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、createContact
操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してcreateContact
操作を実行できます。
パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが様々なContactのフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してcreateContact
操作を実行できます。
戻されたContact
オブジェクトを「データ・コントロール」パネルにあるcreateContact
操作の下からドラッグし、ADFフォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。createContact
操作を実行すると、結果がこのフォームに表示されます。
例9-14と例9-15は、エンド・ユーザーがデバイスにコンタクト先を作成することを可能にするコード例を示しています。
例9-14 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 = "GivenName"; name.familyName = "FamilyName"; contact.name = name; // Store contact phone numbers in ContactField[] var phoneNumbers = [1]; phoneNumbers[0] = new ContactField('home', '650-111-2222', true); contact.phoneNumbers = phoneNumbers; // Store contact phone numbers in ContactField[] var emails = [1]; emails[0] = new ContactField('work', 'first.given@oracle.com'); contact.emails = emails; // Save contact.save(onSuccess, onFailure); function onSuccess() { alert("Create Contact successful."); } function onFailure(Error) { alert("Create Contact failed: " + Error.code); }
例9-15 createContactのJavaコード例
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; import oracle.adfmf.framework.contract.adf.ContactAddresses; import oracle.adfmf.framework.contract.adf.ContactField; import oracle.adfmf.framework.contract.adf.ContactName; String givenName = "GivenName"; String familyName = "FamilyName"; String note = "Just a Note"; String phoneNumberType = "mobile"; String phoneNumberValue = "650-000-1234"; String phoneNumberNewValue = "650-111-1234"; String emailType = "home"; String emailTypeNew = "work"; String emailValue = "first.given@oracle.com"; String addressType = "home"; String addressStreet = "500 Oracle Pkwy"; String addressLocality = "Redwood Shores"; String addressCountry = "USA"; String addressPostalCode = "94065"; ContactField[] phoneNumbers = null; ContactField[] emails = null; ContactAddresses[] addresses = null; ContactField[] emails = null; /* * Create contact */ Contact aContact = new Contact(); ContactName name = new ContactName(); name.setFamilyName(familyName); name.setGivenName(givenName); aContact.setName(name); ContactField phoneNumber = new ContactField(); phoneNumber.setType(phoneNumberType); phoneNumber.setValue(phoneNumberValue); phoneNumbers = new ContactField[] { phoneNumber }; ContactField email = new ContactField(); email.setType(emailType); email.setValue(emailValue); emails = new ContactField[] { email }; ContactAddresses address = new ContactAddresses(); address.setType(addressType); address.setStreetAddress(addressStreet); address.setLocality(addressLocality); address.setCountry(addressCountry); addresses = new ContactAddresses[] { address }; aContact.setNote(note); aContact.setPhoneNumbers(phoneNumbers); aContact.setEmails(emails); aContact.setAddresses(addresses); // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. // Invoking the createContact method, using the DeviceDataControl object. Contact createdContact = DeviceManagerFactory.getDeviceManager() .findContacts.createContact(aContact);
DeviceFeaturesデータ・コントロールに含まれるfindContacts
メソッドをADFモバイル・アプリケーションで使用すると、デバイスのコンタクト先を管理するためのインタフェースとファイル・システムを活用し、エンド・ユーザーがデバイスのアドレス帳から1つ以上のコンタクト先を検索できるようにすることが可能です。ADFモバイルでは、デバイスのインタフェースを表示し、必要に応じてfindContacts
のフィールドに事前にデータを移入できます。findContacts
メソッドでは、フィルタ文字列と検索する(そして、見つかったコンタクト先の一部として戻す)フィールド名のリストを使用します。フィルタ文字列には、コンタクト先内の検索する任意の項目を指定できます。findContacts
メソッドの詳細は、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
findContacts
操作では、次の引数を使用します。
contactFields:
必須パラメータ。このパラメータは、findContacts
操作によって生成されるContact
オブジェクトに含めるフィールドを指定するために使用します。フィールドはカンマで区切ります(スペースの有無は関係ありません)。
filter:
コンタクト先をフィルタするために使用する検索文字列。(文字列) (デフォルト: ""
)
multiple:
findContacts
操作から複数のコンタクト先を戻すかどうかを決定します。(ブール) (デフォルト: false
)
注意: 次のリストに含まれていないフィールド名を渡すと、 |
次のリストに示すContact
のフィールドを渡して、検索に使用し、見つかったコンタクト先の一部として戻すことができます。
id:
グローバルに一意な識別子
displayName:
エンド・ユーザーへの表示に適した、このコンタクト先の名前
name:
人物名のすべてのコンポーネントを含むオブジェクト
nickname:
コンタクト先のカジュアルな名前
phoneNumbers:
コンタクト先のすべての電話番号の配列
emails:
コンタクト先のすべての電子メール・アドレスの配列
addresses:
コンタクト先のすべての住所の配列
ims:
すべてのインスタント・メッセージング(IM)アドレスの配列
organizations:
コンタクト先のすべての組織の配列
revision:
コンタクト先が最後に訂正された日付
birthday:
コンタクト先の誕生日
gender:
コンタクト先の性別
note:
コンタクト先に関するメモ
photos:
コンタクト先の写真の配列
urls:
コンタクト先に関連付けられたWebページの配列
DeviceFeaturesデータ・コントロールを使用してfindContacts操作をカスタマイズするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからfindContacts
操作をドラッグし、ADFモバイルのリンク、ボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。
リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、findContacts
操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してfindContacts
操作を実行できます。
パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが前述のContactの様々なフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してfindContacts
操作を実行できます。
戻されたContact
オブジェクトを「データ・コントロール」パネルにあるfindContacts
操作の下からドラッグし、ADFフォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。findContacts
操作を実行すると、結果がこのフォームに表示されます。
例9-16は、findContacts
メソッドに指定できる引数値を示しています。例9-17と例9-18は、姓でコンタクト先を検索し、コンタクト先の名前、電話番号、電子メール、住所およびメモを取得する方法を示しています。
例9-16 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);
注意: 渡される |
例9-17 findContactsの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); }
例9-18 findContactsのJavaコード例
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; /* * Find Contact - Find contact by family name. * * See if we can find the contact that we just created. */ String familyName = "FamilyName" // Access device features in Java code by acquiring an instance of the // DeviceManager from the DeviceManagerFactory. Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts( "name,phoneNumbers,emails,addresses,note", familyName, true);
DeviceFeaturesデータ・コントロールに含まれるupdateContact
メソッドをADFモバイル・アプリケーションで使用すると、コンタクト先を管理するためにデバイスのインタフェースとファイル・システムを活用し、エンド・ユーザーがデバイスのアドレス帳に含まれるコンタクト先を更新できるようにすることが可能です。ADFモバイルでは、デバイスのインタフェースを表示し、必要に応じてupdateContact
のフィールドに事前にデータを移入できます。例9-19のように、updateContact
メソッドはContact
オブジェクトをパラメータとして使用し、更新されたContact
オブジェクトを戻します。
注意: 入力パラメータとして必要な |
DeviceFeaturesデータ・コントロールを使用してupdateContact操作をカスタマイズするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからupdateContact
操作をドラッグし、ADFモバイルのリンク、ボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。
リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、updateContact
操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してupdateContact
操作を実行できます。
パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが様々なContactのフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してupdateContact
操作を実行できます。
戻されたContact
オブジェクトを「データ・コントロール」パネルにあるupdateContact
操作の下からドラッグし、ADFフォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。updateContact
操作を実行すると、結果がこのフォームに表示されます。
例9-19と例9-21は、コンタクト先の電話番号を更新する方法を示しています。例9-20と例9-22は、コンタクト先に別の電話番号を追加する方法を示しています。
updateContact
メソッドとContact
オブジェクトについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。Contact
のフィールドについては、第9.5.5項「findContactsメソッドの使用方法」も参照してください。
例9-19 updateContactのJavaScriptコード例
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-123-4567"; } // 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);
例9-20は、既存の電話番号に別の電話番号を追加する方法を示しています。
例9-20 updateContactを使用して電話番号を追加するためのJavaScriptコード例
function updateContact(contact) { try { var phoneNumbers = [1]; phoneNumbers[0] = new ContactField('home', '650-111-2222', 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); }
例9-21は、コンタクト先の電話番号、電子メール・タイプおよび郵便番号を更新する方法を示しています。
例9-21 updateContactのJavaコード例
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-111-1234"; String emailTypeNew = "work"; String addressPostalCode = "94065"; 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]);
例9-22は、既存の電話番号に別の電話番号を追加する方法を示しています。
例9-22 updateContactを使用して電話番号を追加するためのJavaコード例
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; String additionalPhoneNumberValue = "999-888-0000"; 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]);
DeviceFeaturesデータ・コントロールに含まれるremoveContact
メソッドをADFモバイル・アプリケーションで使用すると、コンタクト先を管理するためのデバイスの・インタフェースとファイル・システムを活用し、エンド・ユーザーがデバイスのアドレス帳からコンタクト先を削除できるようにすることが可能です。ADFモバイルでは、デバイスのインタフェースを表示し、必要に応じてremoveContact
のフィールドに事前にデータを移入できます。例9-23のように、removeContact
メソッドはContact
オブジェクトをパラメータとして使用します。
注意: 入力パラメータとして必要な |
DeviceFeaturesデータ・コントロールを使用してremoveContact操作をカスタマイズするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからremoveContact
操作をドラッグし、ADFモバイルのリンク、ボタンまたはパラメータ・フォームとしてページ・デザイナ上にドロップします。
リンクまたはボタン: 「アクション・バインディングの編集」ダイアログが表示され、removeContact
操作の引数の値を入力するよう求められます。実行時にページに表示されるボタンまたはリンクをクリックすると、入力した値を使用してremoveContact
操作を実行できます。
パラメータ・フォーム: 「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズします。実行時に、アプリケーション・ユーザーが様々なContactのフィールドの値を入力できる、編集可能なフォームがページに表示されます。このフォームの下にあるボタンをクリックすると、入力した値を使用してremoveContact
操作を実行できます。
戻されたContact
オブジェクトを「データ・コントロール」パネルにあるremoveContact
操作の下からドラッグし、ADFフォームとしてページ上にドロップすることもできます。その後、「フォーム・フィールドの編集」ダイアログでフォームをカスタマイズできます。removeContact
操作を実行すると、結果がこのフォームに表示されます。
例9-23と例9-24は、findContacts
を使用して検索したコンタクト先を削除する方法を示しています。removeContact
メソッドとContactオブジェクトについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
例9-23 removeContactのJavaScriptコード例
// Remove the contact from the device contact.remove(onSuccess,onError); function onSuccess() { alert("Removal Success"); } function onError(contactError)' { alert("Error = " + contactError.code); }
例9-24 removeContactのJavaコード例
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]);
DeviceFeaturesデータ・コントロールに含まれるstartLocationMonitor
メソッドをADFモバイル・アプリケーションで使用すると、地理的位置機能を提供し、エンド・ユーザーがデバイスの場所を取得できるようにすることが可能です。ADFモバイルでは、デバイスのインタフェースを表示し、必要に応じてstartLocationMonitor
のフィールドに事前にデータを移入できます。
ADFモバイルで公開されているAPIを使用すると、デバイスの現在の位置を取得できるため、特定の時点におけるデバイスの現在の位置を取得したり、定期的にその情報をサブスクライブできます。例9-25と例9-26は、アプリケーションでデバイスの位置の取得を可能にするコード例を示しています。startLocationMonitor
メソッドについては、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
DeviceFeaturesデータ・コントロールを使用してデバイスの位置の変更をリスニングするには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからstartLocationMonitor
操作をページ・デザイナ上にドラッグし、ADFモバイルのリンクまたはボタンとしてドロップします。アクションの編集ダイアログによって要求されたら、次のようにフィールドに値を移入します。
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式の評価結果として |
例9-25は、デバイスの位置の変更を定期的にサブスクライブする方法を示しています。この例で使用するDeviceManager.startUpdatingPosition
メソッドのパラメータは、次のとおりです。
int updateInterval:
位置の更新の配信頻度をミリ秒単位で定義します。位置の更新は、指定した頻度では配信されない場合があります。オペレーティング・システムでは、デバイスの位置の大きな変更が検出されるまで待機してから、別の位置の更新をトリガーする場合があります。逆に言えば、位置の更新は指定した頻度で配信されることもありますが、デバイスの位置が大きく変更されるまで、配信される位置が変化しない場合があります。
boolean enableHighAccuracy
: true
に設定された場合、位置の修正を最も正確に取得できるメソッドを使用します。
String watchID:
後から位置の更新のサブスクライブを停止するために使用できる一意のIDを定義します。
GeolocationCallback:
GeolocationCallbackインタフェースの実装。例9-25のように、この実装のlocationUpdated
メソッドは、位置が更新されるたびに起動されます。
JavaScriptを使用してデバイスの位置の変更をサブスクライブする方法の例は、PhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
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
startLocationMonitor
およびstartHeadingMonitor
メソッドの詳細は、ADFモバイルJavadocのDeviceDataControl
クラスおよびPhoneGapのドキュメント(http://www.phonegap.com/home
)を参照してください。
例9-25 地理的位置を使用したデバイスの位置の変更のサブスクライブ
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; import oracle.adf.model.datacontrols.device.GeolocationCallback; import oracle.adfmf.framework.contract.adf.Location; // Subscribe to location updates that will be delivered every 20 seconds, with high accuracy. // As we 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);
DeviceFeaturesデータ・コントロールを使用してデバイスの位置を取得するには:
JDeveloperで、「データ・コントロール」パネルのDeviceFeaturesデータ・コントロールからstartLocationMonitor
操作をページ・デザイナ上にドラッグし、ADFモバイルのリンクまたはボタンとしてドロップします。例9-25に従いますが、最初の位置の変更を受信した後、リスニングを停止します。
例9-26は、デバイスの位置を1回取得する方法を示しています。この例で使用するDeviceManager.getCurrentPosition
メソッドのパラメータは、次のとおりです。
int maximumAge:
ミリ秒単位で指定したこの値より古くないキャッシュ値を受け入れます。位置の修正をこの時間内に取得した場合、その情報がすぐに戻されますが、それ以外の場合、コールは新しい位置の修正が確定するまでブロックされます。
boolean: enableHighAccuracy
trueに設定された場合、位置の修正を最も正確に取得できるメソッドを使用します。
例9-26 地理的位置を使用したデバイスの現在位置の取得(1回)
import oracle.adf.model.datacontrols.device.DeviceManagerFactory; import oracle.adfmf.framework.contract.adf.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());
アプリケーションには、特定のデバイスの特性や機能に依存する機能が含まれる場合があります。たとえば、デバイスの画面の向きによって異なるユーザー・インタフェースを提示したり、デバイスで地理的位置がサポートされる場合のみマッピング機能を有効にすることなどが考えられます。ADFモバイルでは、このような動的な動作をサポートするためにJavaとELからアクセスできる、様々なプロパティが提供されます。表9-6に、これらのプロパティをリストし、問合せ方法、予期される戻り値およびアプリケーションのライフサイクル中にそのプロパティが変更される可能性があるかどうかに関する情報も提供します。
表9-6 デバイス・プロパティと対応するEL式
プロパティ | 静的/ 動的 |
EL式 | サンプル値 | Java API |
---|---|---|---|---|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
動的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
|
静的 |
|
|
|
脚注 1 wifi
と2G
の両方が有効になっている場合、wifi
が2G
よりも優先されるため、ネットワーク・ステータスはwifi
になります。
ADFモバイルでは、データ・コントロール・レイヤーで検証を実行し、Oracle ADFの場合と同様に動作するバインディング属性に設定された検証ルールを使用します。属性の検証は、バインディングに対するsetValue
操作中に、システム内の単一点で実行されます。
データ・コントロールによって公開される属性に対して、次のバリデータを定義できます。
比較バリデータ
長さバリデータ
リスト・バリデータ
範囲バリデータ
特定の属性に対してすべてのバリデータが実行され、成功しないすべてのバリデータに対してネストされた例外がスローされます。属性の検証メッセージを定義し、実行時に検証ルールを起動するときに表示できます。詳細は、第8.9項「入力の検証」と第9.6.1項「検証ルールの追加方法」を参照してください。
注意: JSONの制限により、 |
表9-7に、長さバリデータでサポートされる検証の組合せをリストします。
表9-7 長さの検証
比較タイプ | Byte | Character |
---|---|---|
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
|
サポート |
サポート |
表9-8と表9-9に、範囲バリデータでサポートされる検証の組合せをリストします。
表9-8 範囲検証
比較タイプ | Byte | Char | Double | Float | Integer | Long | Short |
---|---|---|---|---|---|---|---|
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
表9-9 範囲検証: math、sqlおよびutilパッケージ
比較タイプ | java.math.BigDecimal | java.math.BigInteger | java.sql.Date | java.sql.Time | java.sql.Timestamp | java.util.Date |
---|---|---|---|---|---|---|
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
表9-10に、リスト・バリデータでサポートされる検証の組合せをリストします。
表9-11と表9-12に、比較バリデータでサポートされる検証の組合せをリストします。
表9-11 比較検証
比較タイプ | Byte | Char | Double | Float | Integer | Long | Short | String |
---|---|---|---|---|---|---|---|---|
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
|
未サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
サポート |
未サポート |
表9-12 比較検証: java.math、java.sqlおよびjava.utilパッケージ
比較タイプ | java.math.BigDecimal | java.math.BigInteger | java.sql.Date | java.sql.Time | java.sql.Timestamp | java.util.Date |
---|---|---|---|---|---|---|
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
|
サポート |
サポート |
未サポート |
未サポート |
未サポート |
未サポート |
検証ルールは、様々なユース・ケースに合わせて定義できます。宣言的検証ルールをエンティティ・オブジェクトに追加するには、データ・コントロール構造ファイルの「概要」エディタにある「属性」ページを使用します。
検証ルールの追加の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のエンティティ・オブジェクトおよび属性への検証ルールの追加に関する項を参照してください。
検証規則を追加する手順:
「データ・コントロール」パネルで、データ・コントロール・オブジェクトを右クリックして「定義の編集」を選択します。
データ・コントロール構造ファイルの「概要」エディタで、「属性」ページを選択します。
ページの下部にある「検証ルール」タブを選択し、「追加」をクリックします。表示された「検証ルールの追加」ダイアログで、検証ルールと失敗処理を定義します。
詳細は、次の項を参照してください。
『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の組込みの宣言的検証ルールの使用方法に関する項
バリデータのメタデータは、設計時にデータ・コントロール構造のメタデータXMLファイル内に配置されます。例9-27は、サンプルの長さバリデータを示しています。
例9-27 メタデータ・ファイル内で宣言された長さバリデータ
<?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>
JDeveloperでは、データ変更イベントを単純化するために、プロパティ変更リスナー・パターンを使用します。多くの場合、JDeveloperを使用して、Beanのプロパティ・アクセッサから通知をソースとして参照するために必要なコードを生成できます。これを行うには、「アクセッサの生成」ダイアログの「プロパティの変更時にリスナーに通知」チェック・ボックスを選択します(詳細は第9.2.4.2項「ADFマネージドBean」を参照)。PropertyChangeSupport
オブジェクトが自動的に生成され、新たに生成されたsetterメソッドにfirePropertyChange
へのコールが含まれます。また、addPropertyChangeListener
およびremovePropertyChangeListener
メソッドが追加されるため、プロパティ変更リスナーは、このオブジェクトを使用して自身を登録および登録解除できます。これを使用してフレームワークはクライアント・キャッシュにプッシュする変更を取得し、データが変更されたことをユーザー・インタフェース・レイヤーに通知します。
プロパティ変更のみでは、すべてのデータ変更通知は解決されません。たとえば、データ・コントロールによってラップされたBeanがあり、アイテムのコレクションの公開が必要な場合が考えられます。リストの個々のアイテムを変更するにはプロパティ変更で十分ですが、カーディナリティを変更するには十分ではありません。この場合、コレクション全体のプロパティ変更を起動すると、パフォーマンスが低下する可能性があるため、かわりにコレクションのデルタのみを更新します。これを行うには、ProviderChangeSupport
クラスを使用して、単純なプロパティ変更に必要なデータよりも多くのデータを公開する必要があります。
プロバイダ変更は、データ・コントロールによってラップされたBeanで公開されている動的なコレクションを保持しているときのみ必要になるため、起動するプロバイダ変更イベントは、次のいくつかのタイプのみになります。
fireProviderCreate
: 新しい要素をコレクションに追加する場合
fireProviderDelete
: 要素をコレクションから削除する場合
fireProviderRefresh
: 同時に複数の変更をコレクションに加え、単純にクライアントにコレクション全体のリフレッシュを要求した方がよいと判断した場合(これは一括操作でのみ使用する必要があります)
ProviderChangeSupport
クラスは、コレクション要素に関連する通知を送信するために使用され、これによって、Java Beanデータ・コントロール内で変更が発生したときにコンポーネントを適切に更新できます。このクラスが従うパターンは、自動的に生成されるPropertyChangeSupport
クラスと似ていますが、ProviderChangeSupport
とともに使用されるイベント・オブジェクトでは、操作のタイプや変更された要素のキーと位置などの詳細情報を送信します。ProviderChangeSupport
では、コレクションに対する要素(プロバイダ)の追加や削除など、コレクションに対する構造的な変更を取得します。PropertyChangeSupport
では、コレクション内の個々のアイテムに対する変更を取得します。
例9-28は、ProviderChangeSupport
を使用して、コレクションの要素に対する構造的な変更(子を追加または削除する場合など)に関する通知を送信する方法を示しています。ProviderChangeListener
インタフェースとProviderChangeEvent
クラスの詳細は、ADFモバイルJavadocを参照してください。
例9-28 ProviderChangeSupportのコード例
public class NotePad { private static List s_notes = null; 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ページ全体のリロードによるパフォーマンスの低下を回避できます。
注意:
|
例9-29は、flushDataChangeEvent
メソッドを使用して保留中のデータ変更をクライアントに強制する方法を示しています。oracle.adfmf.framework.api.AdfmfJavaUtilities.flushDataChangeEvent
の詳細は、Oracle Fusion Middleware Oracle ADFモバイルJava APIリファレンスを参照してください。
例9-29 データ変更イベントの例
/* 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 jdev 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) { // TODO Auto-generated catch block ex.printStackTrace(); } } } }; backgroundThread.start(); } protected String uid; protected String title; protected String note; protected int version; protected int iterations = 10; protected int delay = 500; /* --- jdev 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) { // TODO Auto-generated catch block setStatus("inturrpted " + ex); ex.printStackTrace(); } } } }; backgroundThread.start(); } protected int iterations = 100; protected int delay = 750; protected String status; /* --- jdev 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を使用してデータ変更をユーザー・インタフェースに反映する方法の例を示します。このサンプル・アプリケーションは、開発用コンピュータのJDeveloperインストール・ディレクトリ内にある次の場所のPublicSamples.zip
ファイルに含まれています。
jdev_install/jdeveloper/jdev/extensions/oracle.adf.mobile/Samples
サンプル・アプリケーションの詳細は、付録E「サンプルのADFモバイル・アプリケーション」を参照してください。