Monday Feb 25, 2013

ADF Mobile on BlackBerry 10: a failed but instructive experiment

With the release of their new handsets and operating system, Blackberry occupied lots of media space recently. This prompted me to have a deeper look at their platform and to experiment a bit in relation to ADF Mobile. You shouldn't read anything in this, by the way; my personal curiosity doesn't foreshadow Oracle's strategy. 

The BlackBerry 10 OS, as you may know, is able to run most Android applications through a runtime which supports about 70% of Android's APIs. Just for the sake of it, I tried to repackage a very simple ADF Mobile application and deploy it on the BlackBerry 10 simulator. Deployment was successful, and I was even able to get past the splash screen. It is only then that the application failed with an error message stating « Network_ERR: XMLHttpRequest Exception 101 ». This application is self-contained and didn't call any web services, by the way. The root cause of the error was obviously something else.

To be truthful, I expected the experiment to fail. The Android toolkit provided by BlackBerry contains an executable that scans APKs (packaged Android applications) for compatibility. When I ran it on my ADF Mobile APK, it flagged various minor problems (since we are using various hardware features) as well as a major issue: the presence of native code. You can see the full output below:

Apk2Bar /Verifier version 1.5.1
Research In Motion Ltd ? 2012 All rights reserved.
[osname.apk]:(res/drawable-xhdpi/adfmf_icon.png) found an alternate icon with better size:impact=1
[osname.apk]:(AndroidManifest.xml) uses-feature: android.hardware.camera:required minimal Tablet OS version=2.1:impact=2
[osname.apk]:(AndroidManifest.xml) uses-feature: android.hardware.telephony:required minimal Tablet OS version=10.0.6:impact=2
[osname.apk]:(AndroidManifest.xml) uses-feature: android.hardware.camera.autofocus:required minimal Tablet OS version=10.0.9:impact=2
[osname.apk]:(AndroidManifest.xml) native-code: armeabi:impact=5
[osname.apk]:(com/phonegap/AudioHandler.java:275) uses method: android.media.AudioManager$setRouting:impact=1
[osname.apk]:(com/phonegap/AudioHandler.java:272) uses method: android.media.AudioManager$setRouting:impact=1
[osname.apk]:(com/phonegap/AudioPlayer.java:193) uses method: android.media.MediaPlayer$setAudioStreamType:impact=1
[osname.apk]:Summary: [5]=1; [4]=0; [3]=0; [2]=3; [1]=4;
Summary: [5]=1; [4]=0; [3]=0; [2]=3; [1]=4;
Impact Legend: [5]=Severe; [4]=High /context; [3]=Medium /context; [2]=Medium-low /context; [1]=Minor;

The offending native code is part of the JVM that we package with the application itself. Therefore, there is nothing we can do to circumvent the issue right now. Further releases of ADF Mobile could replace the current JVM, thus creating more favorable conditions for this to work.

I must say I was impressed by the developer tools provided by BlackBerry (formerly Research in Motion), especially the device simulator. Its boot time is an order of magnitude shorter than the Android Emulator's, and it was a joy to use.

Does your organization plans to get BlackBerry 10 devices? Is this new platform a more interesting target than Windows Phone? Let us know!   

 

Wednesday Feb 13, 2013

Evaluating EL expressions the Java way in ADF Mobile

Expression language (EL) is used all over the place in JSF and ADF Faces, since it enables the presentation layer (JSPX / JSF pages) to communicate with the application logic (managed beans). ADF Mobile uses exactly the same pattern with its AMX technology, which delivers a JSF-like development experience to build an HTML5-based user interface. The key point here is JSF-like, since internal implementation details may vary between the two.

It is sometimes useful to evaluate EL expressions in the managed bean itself rather than delegate the task to the page. Typically, in ADF web applications, this is done like this:

import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;


public static Object resolveExpression(String expression) {
    FacesContext facesContext = getFacesContext();
    Application app = facesContext.getApplication();
    ExpressionFactory elFactory = app.getExpressionFactory();
    ELContext elContext = facesContext.getELContext();
    ValueExpression valueExp = 
        elFactory.createValueExpression(elContext, expression,
                                        Object.class);
    return valueExp.getValue(elContext);
}

This code snippet will not work as is in ADF Mobile, since there are no FacesContext or Application objects.

Sure, you could retrieve the expression factory by doing this:

import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.framework.model.AdfELContext;

AdfELContext ctx = AdfmfJavaUtilities.getAdfELContext();
ExpressionFactory factory = ctx.getExpressionFactory();

But ADF Mobile provides helper methods that will retrieve the context and expression factory behind the scenes for you.  For example, if you want to evaluate in Java an EL expression that retrieves a message (key ERROR_MSG) from a ressource bundle (declared as viewcontrollerBundle):

import oracle.adfmf.framework.api.Model
import oracle.adfmf.framework.contract.adf.NameValuePair;
...
Model mod = new Model();
NameValuePair[] result = null;

result = mod.getValue(new String[] { "#{viewcontrollerBundle.ERROR_MSG}" });
String value = (String)(result[0].getValue());

The code above will work out of the box if the AMX pages referencing the bean declare the bundle. If that's not the case, you must simply add this line of code before calling getValue on the Model object:

mod.loadBundle(<resource_bundle_basename>, <var_attribute>);

How would you use this technique in a real-world scenario? Suppose, for example, that you need to bind a single amx:outputText to several different values in a resource bundle, the specific text string to be displayed being determined at runtime. In ADF web applications, you could use nested EL to achieve your goal:

#{viewcontrollerBundle[<EL_expression_for_bundle_key>]}

This doesn't work in ADF Mobile currently. Thus, you can sidestep the issue by creating a method binding on a bean and reference it in the page. 

Monday Feb 04, 2013

ADF Mobile: Checking the operating system's name

Recently, somebody asked on the OTN forums how to check the name of the operating system from an ADF Mobile application. This is useful in order to provide a user experience better tailored to a specific mobile platform, for example. 

The first idea I had was to query the JVM's built-in properties: 


System.getProperty("os.name")

This, however, returns Linux on an Android device. This is not surprising, as Google's mobile OS uses the Linux kernel as its foundation. On the other hand, this answer lacks specificity. How can we get a better one?

Turns out  the most reliable way to achieve this task is to use the DeviceManager interface, which supports the DeviceFeatures data control. 


DeviceManager device = DeviceManagerFactory.getDeviceManager();
String os = device.getOs();

The code sample above will return Android as expected on my device.

ADF Mobile and resource bundles

In my last post, I described the three bundle types available to ADF Developers. Last week, I learned that the ADF Mobile framework doesn't support all the choices offered by its server-side older brother. Only XLIFF bundles are available in the current version. You can read more about this here.

About

Frédéric Desbiens

The musings of a member of the ADF Product Management team.

I focus here on my favorite development framework but also have a strong interest in Mobile Development, Oracle WebCenter and Oracle SOA Suite.

Attentive readers will even find posts about IT Strategy from time to time, an interest of mine since I completed my MBA in 2006.

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.

Search

Archives
« February 2013 »
SunMonTueWedThuFriSat
     
1
2
3
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
26
27
28
  
       
Today