SlideShare a Scribd company logo
Reaching out from ADF Mobile 
ODTUG Kscope 14, Seattle, June 2014
Who Am I 
• Luc Bors 
• Principal Consultant 
• AMIS, Netherlands 
• 3 times Oracle Fusion Middleware Partner 
of the year (2011, 2013, 2014)
3 Types of Applications 
• Native Solution 
– Higher barrier to entry 
– Tight integration to device 
features 
• Browser-based Solution 
– Easiest to provide 
– Limited integration to device 
features 
• Hybrid Solution 
Image from http://wiki.developerforce.com (salesforce) 
– Combines ease of web development with the power of native 
applications 
– Good integration to device features
Oracle ADF Mobile 
• Build Once, Run on Multiple-Platforms – Phones, Tablets, iOS, Android, 
… 
• Java for business logic 
• HTML5/JavaScript user interface 
• Consistent business logic & data model 
• Disconnected: SQLite with encryption 
• Full access to native device features 
• Modular, reusable application components 
• JDeveloper and soon Eclipse
Native Mobile User Experience 
• Device native user experience 
• Spring board and tab bar for feature navigation 
• Advanced HTML5-based UI 
• Full animation, gesture, and touch interaction support 
• Interactive Data Visualization Components 
• Device Interaction using Cordova
ADF Mobile Overview
The Big Bad Mobile World
Todays Topics 
• Embedding remote content 
• Displaying remote files 
• Using GPS and Google APIs’ 
• Embedding Social Media 
• Inter App Communication 
• Notifications
Remote URLs 
• For embedding existing web pages in your ADF Mobile app. 
• For instance: 
– News Website 
– Existing enterprise app Mobile Browser Pages 
• Note: 
– Best use Optimized Mobile Browser Pages 
– Apache Trinidad components 
– Oracle recommends using ADF Mobile browser
Feature as Remote URL 
• Create New Feature as 
Remote URL 
• Create URL Connection
Disable Device Access 
• Device Access can be disabled
Browser Navigation 
• You can Enable Browser Navigation Buttons
Whitelisting 
• Why do we need to do this ? 
• Again; Why do we need to do this ?
Reaching out from ADF Mobile (ODTUG KScope 2014)
FileContent Display 
• Integration with Device Native Viewers 
• Exposed as displayFile on DataControl 
• On Android: Use FileType to start appropriate 
viewer 
• On iOS QuickLook Preview is used
The File Processing 
• displayFile method is only able to display files that are local to the device. 
– This means that remote files first have to be downloaded. 
public void remotePreview(ActionEvent e){ 
URL remoteFileUrl; 
InputStream is; 
FileOutputStream fos; 
try{ 
// open connection to remote PDF file 
remoteFileUrl = new URL( 
"http://ilabs.uw.edu/sites/default/files/sample_0.pdf"); 
URLConnection connection = remoteFileUrl.openConnection(); 
is = connection.getInputStream(); 
// we write the file to the application directory 
File localFile = new File( 
AdfmfJavaUtilities.getDirectoryPathRoot( 
AdfmfJavaUtilities.ApplicationDirectory) + 
"/downloadedPDF.pdf"); 
fos = new FileOutputStream(localFile);
The Actual Display 
// displayFile takes a URL string which has to be encoded. 
// Call method in a utility class to do the encoding of the String 
String encodedString = MyUtils.EncodeUrlString(localFile); 
// create URL and invoke displayFile with its String representation 
URL localURL = new URL("file", "localhost", encodedString); 
DeviceManager dm = DeviceManagerFactory.getDeviceManager(); 
dm.displayFile(localURL.toString(), “Preview Header”);
Reaching out from ADF Mobile (ODTUG KScope 2014)
Google Places
Enable API Acces 
• Enable Google Places API Access
The Places URL 
https://maps.googleapis.com/maps/api/place/nearbysearch/JSON?parameters
Parameters 
• location=52.35985,4.88510 (will be derived from the GPS location of 
your device) 
• radius=1000 
• types 
– food 
– leisure (this is actually a set of types that can be combined by using a pipe symbol) 
• museum 
• art_gallery 
• zoo 
• movie_theater 
• sensor=false 
• key=<your google API key> 
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=5 
2.35985,4.88510&radius=1000&types=art_gallery&sensor=false&key=<you 
r google API key>
Result 
"results" : [ 
{ 
"geometry" : { 
"location" : { 
"lat" : 52.363850, 
"lng" : 4.880790 
} 
}, 
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png", 
"id" : "7e7aa85e3e8fb7436bf77647cecbc6ce80db0b4a”, 
"name" : "American Hotel", 
"rating" : 3.60, 
"types" : [ "cafe", "lodging", "food", "establishment" ], 
"vicinity" : "Leidsekade 97, Amsterdam” 
}, 
… next results……
Two important classes 
• To handle a JSON response you need two classes 
– RestServiceAdapter 
– JSONBeanSerializationHelper 
• In this Example these are used in one method that does the search and 
processes the result 
public void searchAction(String mapType) { 
…. 
…
Connection 
• RestServiceAdapter interface in your ADF Mobile application, it needs a 
valid connection to the URL where the service is hosted. Make sure that 
there is a valid connection in the connections.xml or simply create a new 
connection.
RestServiceAdapter 
RestServiceAdapter restServiceAdapter =Model.createRestServiceAdapter(); 
// Clear previously request properties 
restServiceAdapter.clearRequestProperties(); 
// Set the connection 
restServiceAdapter.setConnectionName("GooglePlacesUrlConn"); 
// Specify the type 
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET); 
restServiceAdapter.addRequestProperty("Content-Type”,"application/json"); 
restServiceAdapter.addRequestProperty("Accept”,"application/json; charset=UTF-8"); 
// Specify the number of retries 
restServiceAdapter.setRetryLimit(0); 
// Set the URI 
restServiceAdapter.setRequestURI("?location=52.35985,4.88510&radius=1000&types=" + 
mapType + "&sensor=false&key=<yourKey>"); 
String response = "error"; 
try { 
response = restServiceAdapter.send("");
JSONBeanSerializationHelper 
• For JSON deserialization 
JSONBeanSerializationHelper jsonHelper = 
new JSONBeanSerializationHelper(); 
try { 
response = restServiceAdapter.send(""); 
ServiceResult responseObject = 
(ServiceResult)jsonHelper.fromJSON(ServiceResult.class, response); 
if ( "OK".equalsIgnoreCase( responseObject.getStatus()) ) { 
placesResult = 
PlacesHelper.transformObject(responseObject).getResults(); 
} 
this.result = responseObject.getStatus(); 
} catch (Exception e) { 
e.printStackTrace(); 
this.result = "error"; 
}
Search and Result 
public class PlacesResult { 
private String vicinity; 
private Double rating; 
private String name; 
private String types; 
private String icon; 
private PlacesGeometry geometry;
The ADF DVT Map Component 
<dvtm:geographicMap id="map1" zoomLevel="4" centerX="52.37323" centerY="4.89166"> 
<dvtm:pointDataLayer value="#{bindings.placesResults.collectionModel}" 
id="pdl2" var="row"> 
<dvtm:pointLocation id="ptl1" type="address" 
pointName="#{row.name}" address="#{row.vicinity}"> 
<dvtm:marker id="mrk1" source="#{row.icon}"/> 
</dvtm:pointLocation> 
</dvtm:pointDataLayer> 
</dvtm:geographicMap>
Reaching out from ADF Mobile (ODTUG KScope 2014)
Embedding Twitter 
• Two options: 
– Exactly like the previous sample using the Twitter REST API v1.1 
https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=<name> 
– Using twitter Widgets (only on Android)
Twitter Widgets
The code for the Widget 
<a class="twitter-timeline” 
href="https://twitter.com/TamcappConf" 
data-widget-id="yourData-Widget-Id"> Tweets by @TamcappConf</a> 
<script type="text/javascript"> 
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/ 
^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d 
.createElement(s);js.id=id;js.src=p+"http://platform.twitter.com/widge 
ts.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitt 
er-wjs"); 
</script>
Whitelisting
Reaching out from ADF Mobile (ODTUG KScope 2014)
Layout Components
Using Layout Components
Gesture Support 
• You can configure Button, Link, and List Item components to react to the 
following gestures: 
• Swipe to the right 
• Swipe to the left 
• Swipe up 
• Swipe down 
• Tap-and-hold
Use case example
Inter App Communication 
• Communicate between apps using URL Scheme 
– Call One ADF Mobile app from other ADF Mobile App 
– Call Skype from within ADF Mobile App 
– Call Barcode Scanner App form ADF Mobile App 
– Call any App from ADF Mobile App
Barcode Scanning
URL Scheme 
•
URL Scheme Listener 
public class UrlSchemeCalledListener implements EventListener { 
public UrlSchemeCalledListener() { 
super(); 
} 
public void onMessage(Event event){ 
} 
public void onError(AdfException adfException){ 
} 
public void onOpen(String string){ 
} 
}
URL Scheme Listener 
public void start(){ 
EventSource openUrl = EventSourceFactory.getEventSource( 
EventSourceFactory.OPEN_URL_EVENT_SOURCE_NAME); 
openUrl.addListener(new UrlSchemeCalledListener());
Interact with other App 
<amx:goLink url="zxing://scan/?ret=tamcapp://scan?scannedCode={CODE}" 
id="gl2"> 
<amx:image inlineStyle="height:102px;width:102px;margin-top:4px" 
source="/images/Barcode.png"/> 
</amx:goLink>
Work with the response 
public void onMessage(Event event){ 
AdfELContext elctx = AdfmfJavaUtilities.getAdfELContext(); 
String url = event.getPayload(); 
// Isolate the action. We do this because if there are more URL-Scheme 
// callbacks, we are able to respond to this in this one single method 
String action = url.substring(url.indexOf("//") + 2, url.indexOf("?")); 
if (action.equalsIgnoreCase("scan")) { 
String codeScanned = 
url.substring(url.indexOf("?scannedCode=")+ 13, url.length()); 
ValueExpression val2 = AdfmfJavaUtilities.getValueExpression( 
"#{applicationScope.scannedCode}", Object.class); 
try{ 
val2.setValue(elctx, codeScanned); 
} 
catch {………..} 
AdfmfContainerUtilities.gotoFeature("com.blogspot.lucbors.scan.Scanner"); 
} 
}
Demo
Push Notifications
Push Notifications 
•
Push Notifications 
• Subscribe to Messaging Service 
• Receive token 
• Register with Enterprise app 
• Enterprise app Pushes message 
to Messaging Service 
• Messaging Service delegates 
message to device(s)
Push Notification
Start GCM 
• ApplicationLifeCycleListener 
– Start() 
– getNotificationStyle() 
– getSourceAuthorizationId() 
public void start() { 
// Add code here... 
EventSource evtSource = 
EventSourceFactory.getEventSource( 
NativePushNotificationEventSource. 
NATIVE_PUSH_NOTIFICATION_REMOTE_EVENT_SOURCE_NAME); 
evtSource.addListener(new PushNotificationListener()); 
} 
public long getNotificationStyle() { 
return PushNotificationConfig.NOTIFICATION_STYLE_ALERT | 
PushNotificationConfig.NOTIFICATION_STYLE_BADGE | 
PushNotificationConfig.NOTIFICATION_STYLE_BADGE;}
Open the application 
• PushNotificationListener 
– OnMessage 
– OnError 
– OnOpen 
public void onOpen(String token) { 
// Invoked during the Push Notification registration process. 
// The parameter "token" contains the token received from APNs or GCMs 
// that uniquely identifies a specific device-application combination. 
ValueExpression ve = AdfmfJavaUtilities.getValueExpression( 
"#{applicationScope.deviceToken}", String.class); 
if (token != null){ 
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), token); 
} 
else{ 
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), "dummy Token"); 
} 
}
Example 
• Select device 
• Send message • Get notified
GCM Demo
Summary 
• Remote URL 
– Simple for (re-) using existing mobile websites 
• Display File 
– To download files and display them in the App in the device native viewer. 
• REST Services (such as Google Places) 
– Embed external data into your ADF Mobile APP 
• Twitter via Local HTML 
– To use twitter timeline via Twitter Widgets 
• URL Scheme 
– For inter app communication 
• Push Notifications 
– Rather complex setup but after that very powerful 
– Keep in mind that there is no guaranteed delivery
Luc Bors, AMIS, The Netherlands 
Luc.Bors@amis.nl 
LucBors@gmail.com 
Follow me on : @lucb_

More Related Content

Reaching out from ADF Mobile (ODTUG KScope 2014)

  • 1. Reaching out from ADF Mobile ODTUG Kscope 14, Seattle, June 2014
  • 2. Who Am I • Luc Bors • Principal Consultant • AMIS, Netherlands • 3 times Oracle Fusion Middleware Partner of the year (2011, 2013, 2014)
  • 3. 3 Types of Applications • Native Solution – Higher barrier to entry – Tight integration to device features • Browser-based Solution – Easiest to provide – Limited integration to device features • Hybrid Solution Image from http://wiki.developerforce.com (salesforce) – Combines ease of web development with the power of native applications – Good integration to device features
  • 4. Oracle ADF Mobile • Build Once, Run on Multiple-Platforms – Phones, Tablets, iOS, Android, … • Java for business logic • HTML5/JavaScript user interface • Consistent business logic & data model • Disconnected: SQLite with encryption • Full access to native device features • Modular, reusable application components • JDeveloper and soon Eclipse
  • 5. Native Mobile User Experience • Device native user experience • Spring board and tab bar for feature navigation • Advanced HTML5-based UI • Full animation, gesture, and touch interaction support • Interactive Data Visualization Components • Device Interaction using Cordova
  • 7. The Big Bad Mobile World
  • 8. Todays Topics • Embedding remote content • Displaying remote files • Using GPS and Google APIs’ • Embedding Social Media • Inter App Communication • Notifications
  • 9. Remote URLs • For embedding existing web pages in your ADF Mobile app. • For instance: – News Website – Existing enterprise app Mobile Browser Pages • Note: – Best use Optimized Mobile Browser Pages – Apache Trinidad components – Oracle recommends using ADF Mobile browser
  • 10. Feature as Remote URL • Create New Feature as Remote URL • Create URL Connection
  • 11. Disable Device Access • Device Access can be disabled
  • 12. Browser Navigation • You can Enable Browser Navigation Buttons
  • 13. Whitelisting • Why do we need to do this ? • Again; Why do we need to do this ?
  • 15. FileContent Display • Integration with Device Native Viewers • Exposed as displayFile on DataControl • On Android: Use FileType to start appropriate viewer • On iOS QuickLook Preview is used
  • 16. The File Processing • displayFile method is only able to display files that are local to the device. – This means that remote files first have to be downloaded. public void remotePreview(ActionEvent e){ URL remoteFileUrl; InputStream is; FileOutputStream fos; try{ // open connection to remote PDF file remoteFileUrl = new URL( "http://ilabs.uw.edu/sites/default/files/sample_0.pdf"); URLConnection connection = remoteFileUrl.openConnection(); is = connection.getInputStream(); // we write the file to the application directory File localFile = new File( AdfmfJavaUtilities.getDirectoryPathRoot( AdfmfJavaUtilities.ApplicationDirectory) + "/downloadedPDF.pdf"); fos = new FileOutputStream(localFile);
  • 17. The Actual Display // displayFile takes a URL string which has to be encoded. // Call method in a utility class to do the encoding of the String String encodedString = MyUtils.EncodeUrlString(localFile); // create URL and invoke displayFile with its String representation URL localURL = new URL("file", "localhost", encodedString); DeviceManager dm = DeviceManagerFactory.getDeviceManager(); dm.displayFile(localURL.toString(), “Preview Header”);
  • 20. Enable API Acces • Enable Google Places API Access
  • 21. The Places URL https://maps.googleapis.com/maps/api/place/nearbysearch/JSON?parameters
  • 22. Parameters • location=52.35985,4.88510 (will be derived from the GPS location of your device) • radius=1000 • types – food – leisure (this is actually a set of types that can be combined by using a pipe symbol) • museum • art_gallery • zoo • movie_theater • sensor=false • key=<your google API key> https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=5 2.35985,4.88510&radius=1000&types=art_gallery&sensor=false&key=<you r google API key>
  • 23. Result "results" : [ { "geometry" : { "location" : { "lat" : 52.363850, "lng" : 4.880790 } }, "icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png", "id" : "7e7aa85e3e8fb7436bf77647cecbc6ce80db0b4a”, "name" : "American Hotel", "rating" : 3.60, "types" : [ "cafe", "lodging", "food", "establishment" ], "vicinity" : "Leidsekade 97, Amsterdam” }, … next results……
  • 24. Two important classes • To handle a JSON response you need two classes – RestServiceAdapter – JSONBeanSerializationHelper • In this Example these are used in one method that does the search and processes the result public void searchAction(String mapType) { …. …
  • 25. Connection • RestServiceAdapter interface in your ADF Mobile application, it needs a valid connection to the URL where the service is hosted. Make sure that there is a valid connection in the connections.xml or simply create a new connection.
  • 26. RestServiceAdapter RestServiceAdapter restServiceAdapter =Model.createRestServiceAdapter(); // Clear previously request properties restServiceAdapter.clearRequestProperties(); // Set the connection restServiceAdapter.setConnectionName("GooglePlacesUrlConn"); // Specify the type restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET); restServiceAdapter.addRequestProperty("Content-Type”,"application/json"); restServiceAdapter.addRequestProperty("Accept”,"application/json; charset=UTF-8"); // Specify the number of retries restServiceAdapter.setRetryLimit(0); // Set the URI restServiceAdapter.setRequestURI("?location=52.35985,4.88510&radius=1000&types=" + mapType + "&sensor=false&key=<yourKey>"); String response = "error"; try { response = restServiceAdapter.send("");
  • 27. JSONBeanSerializationHelper • For JSON deserialization JSONBeanSerializationHelper jsonHelper = new JSONBeanSerializationHelper(); try { response = restServiceAdapter.send(""); ServiceResult responseObject = (ServiceResult)jsonHelper.fromJSON(ServiceResult.class, response); if ( "OK".equalsIgnoreCase( responseObject.getStatus()) ) { placesResult = PlacesHelper.transformObject(responseObject).getResults(); } this.result = responseObject.getStatus(); } catch (Exception e) { e.printStackTrace(); this.result = "error"; }
  • 28. Search and Result public class PlacesResult { private String vicinity; private Double rating; private String name; private String types; private String icon; private PlacesGeometry geometry;
  • 29. The ADF DVT Map Component <dvtm:geographicMap id="map1" zoomLevel="4" centerX="52.37323" centerY="4.89166"> <dvtm:pointDataLayer value="#{bindings.placesResults.collectionModel}" id="pdl2" var="row"> <dvtm:pointLocation id="ptl1" type="address" pointName="#{row.name}" address="#{row.vicinity}"> <dvtm:marker id="mrk1" source="#{row.icon}"/> </dvtm:pointLocation> </dvtm:pointDataLayer> </dvtm:geographicMap>
  • 31. Embedding Twitter • Two options: – Exactly like the previous sample using the Twitter REST API v1.1 https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=<name> – Using twitter Widgets (only on Android)
  • 33. The code for the Widget <a class="twitter-timeline” href="https://twitter.com/TamcappConf" data-widget-id="yourData-Widget-Id"> Tweets by @TamcappConf</a> <script type="text/javascript"> !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/ ^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d .createElement(s);js.id=id;js.src=p+"http://platform.twitter.com/widge ts.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitt er-wjs"); </script>
  • 38. Gesture Support • You can configure Button, Link, and List Item components to react to the following gestures: • Swipe to the right • Swipe to the left • Swipe up • Swipe down • Tap-and-hold
  • 40. Inter App Communication • Communicate between apps using URL Scheme – Call One ADF Mobile app from other ADF Mobile App – Call Skype from within ADF Mobile App – Call Barcode Scanner App form ADF Mobile App – Call any App from ADF Mobile App
  • 43. URL Scheme Listener public class UrlSchemeCalledListener implements EventListener { public UrlSchemeCalledListener() { super(); } public void onMessage(Event event){ } public void onError(AdfException adfException){ } public void onOpen(String string){ } }
  • 44. URL Scheme Listener public void start(){ EventSource openUrl = EventSourceFactory.getEventSource( EventSourceFactory.OPEN_URL_EVENT_SOURCE_NAME); openUrl.addListener(new UrlSchemeCalledListener());
  • 45. Interact with other App <amx:goLink url="zxing://scan/?ret=tamcapp://scan?scannedCode={CODE}" id="gl2"> <amx:image inlineStyle="height:102px;width:102px;margin-top:4px" source="/images/Barcode.png"/> </amx:goLink>
  • 46. Work with the response public void onMessage(Event event){ AdfELContext elctx = AdfmfJavaUtilities.getAdfELContext(); String url = event.getPayload(); // Isolate the action. We do this because if there are more URL-Scheme // callbacks, we are able to respond to this in this one single method String action = url.substring(url.indexOf("//") + 2, url.indexOf("?")); if (action.equalsIgnoreCase("scan")) { String codeScanned = url.substring(url.indexOf("?scannedCode=")+ 13, url.length()); ValueExpression val2 = AdfmfJavaUtilities.getValueExpression( "#{applicationScope.scannedCode}", Object.class); try{ val2.setValue(elctx, codeScanned); } catch {………..} AdfmfContainerUtilities.gotoFeature("com.blogspot.lucbors.scan.Scanner"); } }
  • 47. Demo
  • 50. Push Notifications • Subscribe to Messaging Service • Receive token • Register with Enterprise app • Enterprise app Pushes message to Messaging Service • Messaging Service delegates message to device(s)
  • 52. Start GCM • ApplicationLifeCycleListener – Start() – getNotificationStyle() – getSourceAuthorizationId() public void start() { // Add code here... EventSource evtSource = EventSourceFactory.getEventSource( NativePushNotificationEventSource. NATIVE_PUSH_NOTIFICATION_REMOTE_EVENT_SOURCE_NAME); evtSource.addListener(new PushNotificationListener()); } public long getNotificationStyle() { return PushNotificationConfig.NOTIFICATION_STYLE_ALERT | PushNotificationConfig.NOTIFICATION_STYLE_BADGE | PushNotificationConfig.NOTIFICATION_STYLE_BADGE;}
  • 53. Open the application • PushNotificationListener – OnMessage – OnError – OnOpen public void onOpen(String token) { // Invoked during the Push Notification registration process. // The parameter "token" contains the token received from APNs or GCMs // that uniquely identifies a specific device-application combination. ValueExpression ve = AdfmfJavaUtilities.getValueExpression( "#{applicationScope.deviceToken}", String.class); if (token != null){ ve.setValue(AdfmfJavaUtilities.getAdfELContext(), token); } else{ ve.setValue(AdfmfJavaUtilities.getAdfELContext(), "dummy Token"); } }
  • 54. Example • Select device • Send message • Get notified
  • 56. Summary • Remote URL – Simple for (re-) using existing mobile websites • Display File – To download files and display them in the App in the device native viewer. • REST Services (such as Google Places) – Embed external data into your ADF Mobile APP • Twitter via Local HTML – To use twitter timeline via Twitter Widgets • URL Scheme – For inter app communication • Push Notifications – Rather complex setup but after that very powerful – Keep in mind that there is no guaranteed delivery
  • 57. Luc Bors, AMIS, The Netherlands Luc.Bors@amis.nl LucBors@gmail.com Follow me on : @lucb_