Thursday, July 14, 2011

Android #11: Working with WebViews

WebView is a view that displays web pages. WebViews can be used to render HTML content within your Android application. Typically a WebView uses the Android web kit browser within, but the difference or benefit we achieve is that we can embed HTML content from within our native application. A WebView uses the same rendering and JavaScript engine as the browser, but it runs under the control of your application. Another main feature in this approach is that we can have Activity-to-JavaScript communication possible. That is, a JavaScript function can invoke an Activity function and vice versa.

Embedding a WebView into an application activity

Android platform provides the API for rendering arbitrary HTML within your app by allowing the built-in web browser as a widget within the app. HTML content can come from anywhere, either from any of the below
  • Local HTML files stored in your assets of your Android app
  • Downloaded from the web
  • HTML strings
Here is an example on dealing with the three WebViews embedding three different sources of HTML content (as above) and also demonstrates on how to bind Java and JavaScript code for activity and web content communication




layout/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="WebViewDemo"
android:padding="4dip" android:textSize="16sp" />

<WebView android:id="@+id/webview1" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="0" />

<WebView android:id="@+id/webview2" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="0" />

<WebView android:id="@+id/webview3" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="0" />

</LinearLayout>

WebViewActivity.java
package in.satworks.android.samples.activity;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

/** * This class demonstrates on how to embed a WebView in your activity. Also
* demonstrates how to have JavaScript in the WebView call into the activity,
* and how the activity can invoke a JavaScript function.
*/

public class WebViewActivity extends Activity { private WebView mWebView1, mWebView2, mWebView3;
private Handler mHandler = new Handler();

/** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// First WebView with HTML Strings
mWebView1 = (WebView) findViewById(R.id.webview1);
mWebView1.loadData("This is plain HTML text string - BOLDED and
COLORED RED
",
"text/html", "utf-8");

// Second WebView with Local HTML file stored under Android Assets
mWebView2 = (WebView) findViewById(R.id.webview2);
mWebView2.setWebChromeClient(new MyWebChromeClient());
mWebView2.loadUrl("file:///android_asset/demo.html");
WebSettings webSettings2 = mWebView2.getSettings();
// By default, the JavaScript support of the WebView object we are
// working with is turned off.
// In order to turn on the web view support for the JavaScript language
// we should call the setJavaScriptEnabled() method.
webSettings2.setJavaScriptEnabled(true);
// register interface class containing methods to be exposed
// to JavaScript. Takes two params namely, java object we need to expose
// and the reference name to use within JavaScript code
mWebView2.addJavascriptInterface(new MyJavaScriptInterface(),
"androidmethodref");

// Third WebView with external HTML reference mWebView3 = (WebView) findViewById(R.id.webview3);
mWebView3.loadUrl("http://www.google.com/");
WebSettings webSettings3 = mWebView3.getSettings();
webSettings3.setJavaScriptEnabled(true);
// Below is required in order to embed the HTML response output within
// the current activity instead of moving out to Android Browser window
mWebView3.setWebViewClient(new MyWebViewClient());

}/**
* WebViewClient provides a way to embed the WebView call of loadUrl within
* the app layout instead of opening a new independent Android browser
* window
*/
final class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}

}/**
* WebChromeClient provides a hook for calling "alert" from JavaScript.
* Useful for debugging JavaScript.
*/
final class MyWebChromeClient extends WebChromeClient {
@Override
public boolean onJsAlert(WebView view, String url, String message,
JsResult result) {
System.out.println("This message is from Javascript alert=>"
+ message);
Toast.makeText(
getApplicationContext(),
"Activity to WebView Communication: \n" + message
+ " from JavaScript function", Toast.LENGTH_SHORT)
.show();
result.confirm();
return true;
}
}

/** * JavaScript interface containing methods that can be invoked by the
* JavaScript within HTML. It also in turn invokes the JavaScript method
*/
final class MyJavaScriptInterface {

MyJavaScriptInterface() { }

/** * This method will be invoked via the JavaScript event from within HTML
* through the registered reference name 'androidmethodref'. This is not
* called on the UI thread. Post a runnable to invoke loadUrl on the UI
* thread.
*/
public void clickOnAndroid() {
System.out.println("Method - clickOnAndroid called from Javascript embedded within HTML (demo.html).");
Toast.makeText(
getApplicationContext(),
"WebView to Activity Communication: \nclickOnAndroid: Called from Javascript Event",
Toast.LENGTH_SHORT).show();
mHandler.post(new Runnable() {
// Call to the HTML JavaScript Method
public void run() {
mWebView2.loadUrl("javascript:greetUser()");
}
});
}
}

}

assets/demo.html
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
// This function is invoked by the Android Activity
function greetUser()
{
alert("Welcome! "+document.forms[0].nameVal.value);
}
</script>
</head>
<form>
<body bgcolor="lavender">
<input type="text" name="nameVal" value="Sat"/>
<!-- Calls into the JavaScript interface for the activity //-->
<input type="button" value="Greet User" onClick="window.androidmethodref.clickOnAndroid()"/>
</body>
</form>
</html>

values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WebViewApp</string>
</resources>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="in.satworks.android.samples.activity" android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".WebViewActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />

<uses-permission android:name="android.permission.INTERNET"></uses-permission></manifest>

Reference:

Android #10: Working with Android Services

Activities and Content Providers are short lived components and can be shut down any time whereas Services are designed to keep running if required as an independent Activity. For example, they can check for any updates on RSS feed or playing background music even if the controlling Activity is no longer operating. So in order to create a application that runs on background of other current activities, one need to create a service.

Services are of two categories

  1. Unbound Services – They are services that run in background indefinitely. That is, unbound service is one which gets initiated when an activity is started and continues to run even when that activity is closed.

  2. Bound Services – They are services that run in background at the lifespan of a calling activity. That is, bound service is one which gets initiated when an activity is started and destroys or its life span ends when that activity is closed.
Working with Unbound Services:

Here is an example of unbound service that will be initiated by an application activity and even after that activity is closed, will find the service to be running in background.







layout/main.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" android:gravity="center">

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="Activity UnBound Services Demo"

android:textSize="20sp" android:padding="10dp" />

<Button android:layout_width="fill_parent"

android:layout_height="wrap_content" android:id="@+id/buttonStart"

android:text="Create/Start UnBound Service"></Button>

<Button android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="Stop UnBound Service" android:id="@+id/buttonStop">
</Button>

</LinearLayout>

SimpleActivityUnBoundService.java
package in.satworks.android.samples.service;import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.widget.Toast;

public class SimpleActivityUnBoundService extends Service {
 @Override

public IBinder onBind(Intent arg0) { return null;

}

@Override
// Service Created - Called only one time when when the service is first created

public void onCreate() {super.onCreate();

Toast.makeText(this, "Service onCreate called: Service Created", 3).show();}

@Override
// Service Stopped - Called when the service is destroyed

public void onDestroy() {super.onDestroy();

Toast.makeText(this, "Service onDestroy called: Service Stopped", 3).show();}

@Override
// Service Started - Called every time when user tries to start the same service

public void onStart(Intent intent, int startId) {super.onStart(intent, startId);

Toast.makeText(this, "Service onStart called: Service Started", 3).show();}

}

ServiceDemoActivity.java
package in.satworks.android.samples.activity;
import in.satworks.android.samples.R;
import in.satworks.android.samples.service.SimpleActivityUnBoundService;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

public class ServiceDemoActivity extends Activity implements OnClickListener{

Button buttonStart, buttonStop;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

buttonStart = (Button) findViewById(R.id.buttonStart);

buttonStop = (Button) findViewById(R.id.buttonStop);

buttonStart.setOnClickListener(this);

buttonStop.setOnClickListener(this);

}

@Override
public void onClick(View v) {

switch (v.getId()) {

case R.id.buttonStart:

startService(new Intent(this, SimpleActivityUnBoundService.class));

break;

case R.id.buttonStop:

stopService(new Intent(this, SimpleActivityUnBoundService.class));

break;

}

}

@Override protected void onDestroy() {

super.onDestroy();

Toast.makeText(this, "Calling Activity Destoyed", 3).show();

}

}

values/strings.xml
<?xml version="1.0" encoding="utf-8"?>

<resources>

<string name="app_name">ServiceDemoApp</string>

</resources>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="in.satworks.android.samples" android:versionCode="1"

android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".activity.ServiceDemoActivity" android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<service android:enabled="true" android:name=".service.SimpleActivityUnBoundService" />

</application>

<uses-sdk android:minSdkVersion="8" />

</manifest>

Working with Bound Services:

Here is an example of bound service that will be initiated by an application activity and its lifecycle ends when the activity is closed.




layout/main.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="fill_parent"

android:layout_height="fill_parent" android:gravity="center">

<TextView android:layout_width="fill_parent"

android:layout_height="wrap_content" android:text="Activity Bound Services Demo"

android:textSize="20sp" android:padding="10dp" />

<Button android:layout_width="fill_parent"

android:layout_height="wrap_content" android:id="@+id/buttonStart"

android:text="Start"></Button>

</LinearLayout>

SimpleActivityBoundService.java
package in.satworks.android.samples.service;import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.widget.Toast;

public class SimpleActivityBoundService extends Service { @Override

public IBinder onBind(Intent arg0) {

return null;

}

@Override // Service Created - Called only one time when when the service is first created

public void onCreate() {

super.onCreate();

Toast.makeText(this, "Service onCreate called: Service Created", 3).show();

}

@Override // Service Stopped - Called when the service is destroyed

public void onDestroy() {

super.onDestroy();

Toast.makeText(this, "Service onDestroy called: Service Stopped", 3).show();

}

}

ServiceDemoActivity.java
package in.satworks.android.samples.activity;import in.satworks.android.samples.R;

import in.satworks.android.samples.service.SimpleActivityBoundService;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

public class ServiceDemoActivity extends Activity implements OnClickListener{
Button buttonStart;

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

buttonStart = (Button) findViewById(R.id.buttonStart);

buttonStart.setOnClickListener(this);

}

@Override public void onClick(View v) {

switch (v.getId()) {

case R.id.buttonStart:

bindService(new Intent(this, SimpleActivityBoundService.class), null, BIND_AUTO_CREATE);

break;

}

}

@Override protected void onDestroy() {

super.onDestroy();

Toast.makeText(this, "Calling Activity Destroyed", 3).show();

}

}

values/strings.xml
<?xml version="1.0" encoding="utf-8"?>

<resources>

<string name="app_name">ServiceDemoApp</string>

</resources>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="in.satworks.android.samples" android:versionCode="1"

android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".activity.ServiceDemoActivity" android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<service android:enabled="true" android:name=".service.SimpleActivityBoundService" />

</application>

<uses-sdk android:minSdkVersion="8" />

</manifest>

Best Practices: Cross-Context Dispatching and Session Handling

It’s been quite some time since I blogged. Thought of blogging this topic as recently we had faced a similar kind of problem that was faced earlier in another project. Just before going on to the problem and solution, let us first understand few basics and then move forward.

Understanding Session Tracking and JSESSIONID:

Basically a web container can use several methods to associate a session with a user, all of which involve passing an identifier between the client and the server. The identifier can be maintained on the client as a cookie, or the web component can include the identifier in every URL that is returned to the client.

JSESSIONID is a unique identifier of the HTTP session generated by the web container, stored within the cookie and is also the default cookie name. JSESSIONID cookie is created/sent when session is created. If cookies are turned off, the identifier is encoded in the URL link and if the cookies are turned on, the URL is simply empty and the identifier is available in the cookie itself.

Another misconception is that session gets created during first request which is not actually the case and totally up to the code to determine on when it should be created. To better understand this behavior,

  • In Java Servlet, new session is created when your code calls request.getSession() or request.getSession(true) for the first time. If you just want to get session if exists and do not want to create it if it doesn't exists, use request.getSession(false) that will return you a session if exists or null if it doesn’t. In this case, new session is not created and JSESSIONID cookie is not sent to the client browser that also means the session is not necessarily created on first request.

  • In JSP, new session is created whenever a call is made to the JSP page for the first time and uses the already available session for other subsequent requests. If we need to turn off this feature in a particular JSP page, use session=”false” page directive in which case session variable is not available on that JSP page at all.


Problem Description:

In case there are two or more different web application contexts accessed by the same user from the same domain, each request from the same user will generate cookie with its own session id that will get overridden and loose the session it had already set up.

By default all popular browser has the parent (main) window and the child (pop-up) window sharing the same cookie whenever the session is tracked using cookies. Assume the scenario where there are two different web applications deployed under the same server domain and each are accessed via their own context roots, the parent window accesses the first application and child window with the second application. In this case, as parent window and child window accesses two different applications from the same domain, session information gets overridden because the cookie name is same and the new Identifier (JSESSIONID) named cookie gets overridden due to which parent window looses it session data.

For instance, we had two different applications (say for example /app1 and /app2) running under the same domain (say for example http://www.samedomain.com/), parent window accesses the first application (http://www.samedomain.com/app1/) and through it, opens a child window with the second application (http://www.samedomain.com/app2) . When the parent window opens, it creates a cookie named with JSESSIONID and stores client session related information. As soon as the child window is opened, the existing session gets overridden by the app2 session as cookie names are same resulting in loss of session data in parent screen. Post this, whenever user navigates within parent screen for anything session specific will not fetch them the required data.

Solution Description:

Any of the below two approaches can be employed to prevent the session override problem

  1. Changing the cookie name from default value.

  2. Changing the cookie path (in case certain application server doesn’t allow to change the cookie name, we can create the same JSESSIONID named cookie into two different paths thus a work around way to prevent the override issue)


As each web container implementation differs even though they follow the same specification, above approaches can be employed using their proprietary configurations. Below are two different examples through which the above problem can be solved.

Illustration by Examples:

In Weblogic Application Server, changing the cookie name from default value. Suppose we have two applications deployed on Weblogic Application server, we can change the cookie name from its default JSESSIONID named cookie. This way, we can create application-specific cookies to avoid cookie override that in turn avoids the HTTP session override issue. Modify the weblogic.xml configuration specific to each application as below

<session-descriptor>
<session-param>
<param-name>CookieName</param-name>
<param-value>App1Cookie</param-value>
</session-param>
</session-descriptor>

By changing the cookie name, we ensure two different cookies created for each applications, thus ensuring that app1 and app2 sessions doesn't get overridden.

In Tomcat Web Server or JBoss Application server, changing the cookie path. We have the property named emptySessionPath used by the Apache connector’s configuration that states whether all cookie should be stored in the root folder “/” or not (otherwise) . This way, we can have cookies placed in two different location to avoid cookie override that in turn avoids HTTP session override issue. If emptySessionPath is enabled and set as “true” in Tomcat or JBoss, the JSESSIONID cookie is written to the root "/" path. If emptySessionPath is set to “false”, there are multiple cookies in the browser, one for each web app (none at the root), so different web apps are not re-writing each other's cookie. Modify the server.xml configuration specific to each application as below


<Connector port="8080" address="${jboss.bind.address}"maxThreads="5" maxHttpHeaderSize="8192"
emptySessionPath="false" protocol="HTTP/1.1" enableLookups="false" redirectPort="8443"
acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" />
<Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3"
maxThreads="200" emptySessionPath="false" enableLookups="false" redirectPort="8443" />

By changing the emptySessionPath to "false", we ensure that the session cookies of app1 gets created at “/app1” instead of the default path of “/”, thus ensuring that app1 and app2 sessions doesn't get overridden.

Wednesday, April 27, 2011

Dynamic views of my blog

Just got to know that my blog can be viewed with different look and feel. Blogger currently offers five dynamic views for its public blogs. These views are only accessible if allowed for by the blog author.

  • Flipcard: http://satworks.blogspot.com/view/flipcard
  • Mosaic: http://satworks.blogspot.com/view/mosaic
  • Sidebar: http://satworks.blogspot.com/view/sidebar
  • Snapshot: http://satworks.blogspot.com/view/snapshot
  • Timeslide: http://satworks.blogspot.com/view/timeslide
  • Monday, January 3, 2011

    Mobilizing Existing Application Architecture

    When we say mobilizing existing enterprise applications, we just don’t talk about creating a mobile client that connects or communicates with the back-end enterprise systems for data. But often requires modifying and/or extending the existing enterprise application architecture with many components working together to support multiple platform devices.

    Following high level architecture represents the logical view and can be used as reference architecture in extending the design of the existing architecture to a mobile based application for the enterprise world.




    Enterprise System Tier:

    Enterprise System Tier may constitutes the existing enterprise applications. Many flavors of enterprise applications such as Content Management Systems (CMS), Customer Relation Management (CRM), Enterprise Resource Planning (ERP), Business Intelligence (BI), Web Enterprise Architectures exists today that can be extended to mobile devices.

    Web enterprise applications within itself may follow a three or N tier architecture (presentation tier, application tier, database tier) with one or more layers (presentation layer, business layer, data access layer) within each tier.

    Middle Tier:

    Middle Tier constitutes the middleware that integrates the client application to the EIS tier. As most of the enterprise application architecture does not directly work with or run on devices, there comes the need for a middleware (mobile middleware) that makes the enterprise application data to be accessed by the mobile devices. They serve as an abstraction layer between the mobile device and the enterprise application.

    They are typically services/web services (may be restful web services) or can have its own service oriented architecture (SOA) and also contain mobile templates that can be used to extend the enterprise applications like CMS, CRM, BI, and ERP with the data transformed/rendered into the mobile interface. They contain the content adapters, framework wrappers, content processor/transformers that connects the enterprise data and the mobile application.

    For Web based enterprise applications, we can actually enhance the existing architecture within its abstraction layer to support data sharing to mobile devices instead of this separate middle tier.

    Client Tier:

    Client Tier constitutes the actual mobile client applications and the run times. They are typically the software or programs that run on the mobile devices. The client tier itself may have either no layers or one to three layers of application code based on the platform needs of the mobile application.
    There are three client application architecture options that can be chosen based on requirements and other factors.

    There are three client application architecture options that can be chosen based on requirements and other factors.

    Thin Client Application Architecture:

    This architecture can be chosen when we have to do deal with developing online applications. It is useful in situation where connectivity is guaranteed. Here the client software/program is normally the browser and has no custom application code and relies completely on the enterprise systems for data.
    • Typically has no custom application code

    • Cannot operate independently from server as it completely relies on server for functionality

    • No dependency on the mobile OS and typically use web/wap browser to display HTML, XML and WML contents
    Pros:
    • Easy to maintain/support since there are no application code or data on client side

    • No distribution mechanism or application code release needed for any kind of enhancements as the application business logic resides on the server
    Cons:
    • Always should be in online mode wherein to have constant communication with the server. So mobile application will not work without connectivity.
    Thick/Fat Client Application Architecture:

    This architecture can be chosen when we have to deal with developing offline applications. It is useful in situation where connectivity is not guaranteed. Here the client software/program is installed locally to the device that holds all required data either completely independent of any servers or for most duration and synchronizes data with server at a pre-configured time period or at the end of day whenever connectivity resumes.
    • Typically have one to three layers of custom application code. So native application has to be developed that depends on the mobile OS.
    • Can operate independently from server either completely or for certain period of time
    Pros:
    • Application will work even there is limited connectivity or no connectivity
    Cons:
    • Distribution mechanism or application code release can be difficult as it heavily depends on the mobile OS
    • If we have multi-versions of the application, it would be difficult to maintain or provide support for all versions
    Interactive/Smart Client Application Architecture:

    This architecture can be chosen when we have to deal with developing occasionally connected application. It is useful in situations where connectivity bandwidth is not used all times but whenever required. Here the client software/program is installed locally to the device like fat client, but the application can update or refresh data anytime as against any pre-configured time even though the connectivity is on. That is, synchronizes data with server on need basis only when required.
    • Typically have one to three layers of custom application code. So native application has to be developed that depends on the mobile OS
    Pros:
    • Application will work even there is limited connectivity or no connectivity but the difference here as compared with fat client architecture is that data synchronization happens on need basis when required or whenever there is a update on data is available
    Cons:
    • Distribution mechanism or application code release can be difficult as it heavily depends on the mobile OS but comparatively easier as against fat client models as we can control on what needs to be coded on server and what on client.
    • If we have multi-versions of the application, it would be difficult to maintain or provide support for all versions
    Design Considerations:

    As most of the enterprise web architectures currently available were implemented long before even mobile applications existed or were considered, the need to accommodate the extension of enterprise application to the mobile has the following considerations while design an architecture
    • Connectivity Type: Mobile devices can operate on three connection modes namely 1: Always Connected, 2: Partially Connected & 3: Never Connected. This will play a key role in defining the architecture as only based on this factor; we will have to decide on how the mobile client application would be out of the three thin, fat and smart client models. This affects the way in which data is synchronized between the enterprise app and the mobile client.

    • Data Synchronization: As described above, data synchronization between the mobile client app and the enterprise app plays a key role as well in defining the architecture. It is achieved in either of two ways.
    1. Continuous Synchronous/Asynchronous Communication: Data synchronization between the mobile client and server is continuous where in case of synchronous communication, all data is completely stored before server acknowledges the receipt of data and in case of asynchronous communication, all data need not be completely stored before the server acknowledges the client (ie., server acknowledges immediately when the request comes to it and later carries the store request)
    2. Store-and-Forward Communication: Whenever there is no connectivity, data gets stored within the mobile client local data store and then upon connectivity, data synchronization takes place between mobile client and server. In case of the data retrieval from server, the server uses push-to-messaging to push notifications/messages from the server to the client whenever client is online and rest of the time uses the local data during offline.
    • Abstraction Level: Level of Abstraction of existing application should be considered before an architecture solution is achieved. If there is a clear separation of presentation, business, and data access logic, then it would be easier to mobilize the application as reuse of the existing business and data access components is possible as compared against the writing lot of code/work if the existing application is not well-abstracted.
    • Application Version: Modified version of the application or new application should also be considered while defining a mobile architecture. If we go with a fat/smart client based architecture, then the mobile application we develop will be a scale-down version of the actual server application as some part of the server logic will be developed within the mobile application.

    • Location Based Content: Location based content delivery provides targeted content such as advertisements, information, maps, news to devices based on current physical location. So while defining a architecture, gather information on or clearly separate the different contents that are generic and location based.