tutorial

create mobile (Android) clients [since 4.1]

 

The version 4.0 of OBEROn platform introduced the Androd Extension Library (AEL): it is a single java package (jar) that you can include inside the Android applications you are developing. It allows to connect your mobile device to the company server and provides all java SDK classes to retrieve, manage and save business object instances without caring about the connection protocols or the security issues. In this way, you can reuse all the business logic at the server side and limit the development only to the high level user interfaces (note that also the user interface logic, like user input data checks, selection values and the input masks are also computed inside the OBEROn http server).

Like for desktop clients, there are two main classes that allows you to develop a desktop client:

- Application: is the basic class for mobile apps. It is included inside the Android Extension Library; it extends the Android Activity class and provides connection methods and other utility functions.

- OberonClient: is a primal Android mobile client; custom Android apps should extend this Activity class or they should have a similar logic.

Mobile clients require an HTTP server for connecting to the OBEROn database and performing actions on object instances. You can setup a light OBEROn HTTP server with a minimal configuration, just download it from the "Downloads" page and edit the oberon.properties file (case D) like we have seen for web-applications.



A simple example of the usage of Android Extension Library is the OOQL console for Android. You can dowload the OOQL Client - Eclipse Project , compile it with Eclipse and upload the apk file to the mobile device or you may download the already compiled version from the Google Play app-store. This app allows to execute OOQL commands and queries on the OBEROn server through Android mobile devices.





The OberonClient class is a part of Android Client - Eclipse Project and contains basic functionalities for developing a standard Android application based on the AEL; you can compile it with Eclipse and upload the apk file to the mobile device or you may also download a compiled version from the Google Play app - store.

OBEROn client https://play.google.com/store/apps/details?id=com.oberon.client
OOQL client https://play.google.com/store/apps/details?id=com.oberon


The configuration parameters for Android can be store into the activity Shared Preferences; in particular you have to define the server URL and the application parameter. The first is absolutely required for contacting the server and exchanging data; the second is also required for creating the application menu and accessing the user interface functionalities. The application value may also be hard coded into the java source when the client is specialized for a single application (or portfolio).


 

To define the possible actions that each user can execute inside the application you must create a set of commands organized into menus and submenus. Menus created for a web/desktop applications can be used also in mobile clients. The first "page" the client shows after the login is the welcome page.

The mechanism that is used inside the mobile app to pass from a page to another is the same of that described for the desktop clients. The classes "ApplicationRequest" and "ApplicationSession" represent the page request and the current session respectively.

The most important method of in the OberonClient is:

handleRequest(ApplicationRequest request)

This method redirects the input request to another specific method according to the requested page (or URL) declared inside the ApplicationRequest itself. It means that for each web URL associated with menu commands there should be a method that represents the equivalent web-page in Android format, like in the following example:



The "TAGS.PAGE_<PageName>" constant values correspond to the web page names (for example "edit.jsp" / "files.jsp" / "lifecycle.jsp" ..... )

Note: page URLs inside the command Href parameter may start with the webapp relative path; for this reason you should use the "endsWith" or "indexOf" comparison operators instead of "equals".


The window manager in a desktop client is implemented by two methods:

createPagePanel : prepares the page layout adding the title bar with title / subtitle, object contextual menu (when required) and manages error messages.

addPageToContainer: add the page panel to the proper page container accordind to the ApplicationRequest target; if target is:
- "" (empty) uses the same container of input request referer
- "_blank" opens a new tab folder
- "<Window Name>" replace the content of popup dialog with corresponding name

The first page opened after the login is the TAGS.PAGE_Home (equals to "home.jsp") renderized by the doHome method.

The following examples show how basic functionalities are implemented with Android controls.


TAGS.PAGE_Edit = edit.jsp -> doEdit

The following method can perform both the object creation and the object data update (if the input ID is passed as input parameter). It also manages both the user interface for data input (createForm) and the database update process (saveFormData). These two methods are defined into the Forms class. The Forms class represents the Android implementation for the form administrative objects: in other words it generates the java code based on the form parameters and on the form-item parameters, included all the code needed to load/refresh the field ranges and to validate the field-item values.

public void doEdit(ApplicationRequest request) {
   try {
  ApplicationSession session = (ApplicationSession) request.getSession();
// Get the object id as input parameter
String sID = request.getParameter(TAGS.id);
ObjectObj object;
boolean bCreateNew;
boolean bClone = false;
if ( sID==null || sID.length()==0
    || HTMLUtil.getInputParameter(TAGS.create,request).equals("true") ) {
// Create a new object

bCreateNew=true;
object = new ObjectObj();
  } else {
    // Open the object and read its properties
sID=sID.trim();
bCreateNew=false;
if (HTMLUtil.getInputParameter(TAGS.clone,request).equals("true") ) {
     bClone = true;
}
object = ObjectObj.open(sID,true,framework);
  }

// Get the create/edit Form name as input parameter
String sFormName = HTMLUtil.getInputParameter(TAGS.form , framework);
if ( sFormName.length()==0) {
    // When the form is not passed as input parameter try to get it from the object class
sFormName = object.getClass(framework).getDefaultForm(true);
  }
Form form = Form.open(sFormName , framework , null ); 

// Save the object data or create it
String sForwardPage=Forms.saveFormData(bCreateNew?TAGS.PAGE_Edit:"",object,form,request);

if ( sForwardPage.length()>0 ) {
    // A new object is succesfully created - go forward to the object detail page
ApplicationRequest fwrequest = new ApplicationRequest  
                                                                     (sForwardPage,request.getForwardTarget(),session);
fwrequest.setLocale(request.getLocale());
fwrequest.setReferer(request.getReferer());
handleRequest(fwrequest);
return;
  }
// Define title and subtitle for the menu bar
String sTitle = Dictionary.getKey(dictionary_Section,sFormName,framework);
String sSubTitle = "";
if ( sID!=null && sID.length()>0 ) {
    if (bCreateNew) {
  // Clone an existing object

  object = ObjectObj.open(sID,true,framework);
  object.resetID();
}
sSubTitle=sTitle;
sTitle= getClassNameRevision(object,session);
  }
//
Creates the page container (includes the menu bar with title and subtitle)
LinearLayout globalpanel = createPagePanel(this, sTitle, sSubTitle, !bCreateNew, request);
if (globalpanel!=null) {
    // Generate the Android form compiled with object field values
ScrollView
panel=Forms.createForm(globalpanel,TAGS.PAGE_Edit,object,form,request);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout          .LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
globalpanel.addView(panel,params);
// Add the page container to the application window (tab widget or alert dialog)
String sPrefix = sSubTitle.length()>0?"("+sSubTitle.substring(0,1)+") ":"";
addPageToContainer(globalpanel,sPrefix+sTitle,request);
  }
   } catch (Exception ex) { log(ex.getMessage()); }
}






TAGS.PAGE_Search = search.jsp -> doSearch

The doSearch method is similar to the doEdit: it manages the user interface for the query input filters (createSearchForm); this method is also defined into the Forms class. It requires the search form name as input value and generates the Android code based on this form parameters and on its item parameters.

public void doSearch(ApplicationRequest request) {
   try {
  ApplicationSession session = (ApplicationSession) request.getSession();
// Get the search Form name as input parameter
String sFormName = HTMLUtil.getInputParameter(TAGS.form , request);
if ( sFormName.length()==0) {
    log("NO INPUT FORM");
return;
  }
Form form = Form.open(sFormName , framework , null ); 
String sTitle = Dictionary.getKey(dictionary_Section,sFormName,framework);
 
//
Creates the page container (includes the menu bar with title and subtitle)
LinearLayout globalpanel = createPagePanel(this, sTitle, "",false, request);
if (globalpanel!=null) {
    // Generate the SWT form compiled with object field values
ScrollView
panel = Forms.createSearchForm(globalpanel,TAGS.PAGE_SearchResults,form,request);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout          .LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
globalpanel.addView(panel,params);
// Add the page container to the application window (tab widget or alert dialog)
addPageToContainer(globalpanel,sTitle,request);
  }
   } catch (Exception ex) { log(ex.getMessage()); }
}





TAGS.PAGE_SearchResults = search_results.jsp -> doSearchResult

This method executes the search query based on the filters defined into the doSearch. It employs the searchObjects method included into the Forms class. In addition, you can apply a view to the query results to extract and show several object properties.


public void doSearchResult(ApplicationRequest request) {
   try {
  ApplicationSession session = (ApplicationSession) request.getSession();
// Get the search Form name as input parameter
String sFormName = HTMLUtil.getInputParameter(TAGS.form , request);
if ( sFormName.length()==0) {
    log("NO INPUT FORM");
return;
  }
Form form = Form.open(sFormName , framework , null ); 
String formHTMLName=Forms.getFormHTMLName(form);

// Execute the search query
try {
    String sMessage = Forms.searchObjects( form , request );
if (sMessage.length()>0) {
  if (sMessage.startsWith(TAGS.FORM_ActionAlert+"(" )) {
    sMessage= StringUtils.getStringPart( sMessage,TAGS.FORM_ActionAlert+"(\"", "\");" );
  }
   showMessage(app,sMessage,"",null);
}
  } catch (Exception e) {
    log(e.getMessage());
  }

// Get user views
Vector vViews = com.oberon.ooql.sdk.View.getUserViews(framework);

// Prepare the view list
String sViews = HTMLUtil.getInputParameter(TAGS.views ,request);
Vector vFormViews = StringUtils.StringTokensToVector(sViews,"|");
for (int i=vViews.size()-1;i>=0;i--) {
     if (vFormViews.indexOf(((String)vViews.elementAt(i)))<0) { vViews.removeElementAt(i);}
  }

String sView = HTMLUtil.getInputParameter(TAGS.view,request);
 
//
Creates the page container (includes the menu bar with title and subtitle)
LinearLayout globalpanel = createPagePanel(this, sTitle, "",false, request);
if (globalpanel!=null) {
    // Generate the Android table for search result
ResultSetPanel
rst = new ResultSetPanel(globalpanel,request);
// Set the listener for showing the object contextual menu when the user click on a table row
rst.getTable().setOnRowLongClickListener( new OnLongClickListener() {
    public boolean onLongClick(View view) {
        try {
            String sID = (String) getData(view,TAGS.ID);
            Forms.fillObjectPopUpMenu(view,sID,null,(ApplicationSession)request.getSession());
        } catch (Exception exx) { }
            return true;
        }
    }
);
// Load the view list in the result set panel
rst.resetViews(sView,vViews);
// Process the search result Vector
rst.process( Forms.getSearchResults( formHTMLName , session ) );
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout          .LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
globalpanel.addView(rst.panel,params);
// Add the page container to the application window (tab widget or alert dialog)
addPageToContainer(globalpanel,sTitle,request);
  }
   } catch (Exception ex) { log(ex.getMessage()); }
}




TAGS.PAGE_Files = files.jsp - doFiles

This method shows the object's attached files and enables the user to perform operations on them (open, extract into a local folder, attach more , remove )





TAGS.PAGE_Lifecycle = lifecycle.jsp -> doLifecycle

This method loads the object's lifecycle and generates its graphical representation. The user will be able to progress or regress the status and to validate/refuse the path validations.



TAGS.PAGE_Navigate = navigate.jsp -> doNavigate

Shows the object's navigation tree: links can be filtered selecting the linktype and the direction.



TAGS.PAGE_Activity = activity.jsp -> doActivityList
TAGS.PAGE_ActivityCompletion=default_step_completion.jsp ->doActivityCompletion

Visualizes the user activity dashboard and opens the default completion popups when Href is not specified in workflow steps.

 

<< extend the client basic functionalities  
© 2008-2015 MS Enterprise Solutions | Website Templates by IceTemplates.com
Please Read: Privacy Policy and Terms of Use