Android Hybrid Application to use JavaScript,CSS,HTML files in Android and pass/share data between Android Native to HTML Files and Vise-Verse.


This Application will cover various mechanisms in Hybrid Applications :
a) Pass the data from one HTML file to other HTML file.
b) Pass the data from HTML file to Android native Application.
c) Pass the data from Android Native Application to HTML file.
c) Navigation/Moving from one HTML to other HTML file in Android Device.
d) Mainly to change the text of label dynamically at Runtime.

MainActivity.java:
package org.traeg.nativejswebview;

import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

WebView webview;
EditText fnameEditText;
EditText lnameEditText;
Button updateWebViewButton;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

fnameEditText = (EditText)this.findViewById(R.id.fnameEditText);
lnameEditText = (EditText)this.findViewById(R.id.lnameEditText);
updateWebViewButton = (Button)this.findViewById(R.id.updateWebViewButton);
webview = (WebView)this.findViewById(R.id.webView);

updateWebViewButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendNamesToWebView();
}
});

}

@SuppressLint("SetJavaScriptEnabled")
@Override
public void onStart() {
    super.onStart();
    WebSettings webSettings = webview.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webview.loadUrl("file:///android_asset/webviewContent.html");
   
       //Here this "Android" name used to send the data from html file to Android Native Application.
    webview.addJavascriptInterface(new WebViewInterface(this), "Android");
   
}

public void sendNamesToWebView() {
JSONObject namesJson = new JSONObject();
try {
namesJson.put("fname", fnameEditText.getText().toString());
namesJson.put("lname", lnameEditText.getText().toString());
webview.loadUrl( "javascript:setNames(" + namesJson.toString() + ")" );
} catch (JSONException e) {
Log.e(getPackageName(), "Failed to create JSON object for web view");
}
}

//This class is the interface between HTML file and Android native to send the data from html to Android Native Code.
public class WebViewInterface {
   Context mContext;

   /** Instantiate the interface and set the context */
   WebViewInterface(Context c) {
       mContext = c;
   }
 
   //This wil receive string from HTML file and display it in Toast...
   @JavascriptInterface
   public void showToast(String toastMsg){
    Toast.makeText(MainActivity.this, toastMsg, Toast.LENGTH_LONG).show();
   }

   /*
    * Uncomment if compiling for Android 4.2
    * @JavascriptInterface
    */
   @JavascriptInterface
   public void updateNames(String namesJsonString) {
    Log.d(getPackageName(), "Sent from webview: " + namesJsonString);
    try {

    JSONObject namesJson = new JSONObject(namesJsonString);
final String firstName = namesJson.getString("fname");
final String lastName = namesJson.getString("lname");

// When invoked from Javascript this is executed on a thread other than the UI thread
// Since we want to update the native UI controls we must create a runnable for the                                       //main UI thread.
    runOnUiThread(new Runnable() {
           public void run() {
            fnameEditText.setText(firstName);
            lnameEditText.setText(lastName);
           }
       });

    } catch (JSONException e) {
Log.e(getPackageName(), "Failed to create JSON object from web view data");
}
   }
}
        //Refer these links for extra stuff....
/*
* http://www.smashingmagazine.com/2013/10/17/best-of-both-worlds-mixing-html5-native-code/
* http://www.caliberdt.com/tips/Dec2006.htm
*/
}



/layout/activity_main.xml   :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:background="#8fbc8f"
    tools:context=".MainActivity" >

    <WebView
        android:id="@+id/webView"
        android:layout_width="fill_parent"
        android:layout_height="230dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" />

    <RelativeLayout
        android:id="@+id/relativeLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/webView"
        android:layout_below="@+id/webView"
        android:layout_marginTop="0dp" >

        <TextView
            android:id="@+id/fnameLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/fnameEditText"
            android:text="First Name:"
            android:textStyle="bold" />

   <EditText
       android:id="@+id/fnameEditText"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
       android:layout_toRightOf="@+id/fnameLabel"
       android:ems="10" />

   <TextView
       android:id="@+id/lnameLabel"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignBottom="@+id/lnameEditText"
       android:layout_toLeftOf="@+id/lnameEditText"
       android:text="Last Name:"
       android:textStyle="bold" />

   <EditText
       android:id="@+id/lnameEditText"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignLeft="@+id/fnameEditText"
       android:layout_below="@+id/fnameEditText"
       android:layout_marginTop="5dp"
       android:ems="10" >

       <requestFocus />
   </EditText>
    
   <Button
       android:id="@+id/updateWebViewButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@+id/lnameEditText"
       android:layout_centerHorizontal="true"
       android:minHeight="40dp"
       android:layout_marginTop="8dip"
       android:text="Send Data to WebView" />     
    </RelativeLayout>
</RelativeLayout>



/assets/webviewContent.html  :
<!DOCTYPE html>
<html>
<head>
    <title>Android WebView Test</title>
    <style>
        body {
            font-family: sans-serif;
            background-color: #efe;
        }

        button {
            height: 40px;
            margin-top: 15px;
        }
    </style>
</head>
<body>
<h2>HTML File Content</h2>

<form name="myform" method="POST" action="">
    <label>First Name To Send:</label>
    <input type="text" id="fname">
    <br/>
    <label>Last Name To Send:</label>
    <input type="text" id="lname">
    <br/>
    <button id='updateNativeBtn'>Send Data To AndroidNative</button>
    <button id='SendToSecndHTML' onclick="SendToSecondBtnClicked()">Send Data To SecondHTML</button>
</form>
</body>
<script>

///function that will send the data from this file to -> sendData.html  and opens that html file directly..
function SendToSecondBtnClicked(){
document.myform.action = "sendData.html?" + document.myform.fname.value+"@"+document.myform.lname.value;
//code to display a toast with the string with message sendData.html file loading...
  Android.showToast("sendData.html file loading with input data..");
  
  window.event.returnValue = true;
}

    (function () {
        var nativeBridge = {
            invoke: function (commandName, args) {
                console.log(commandName + ": " + JSON.stringify(args, null, 2));
       window.location = 'js-call:' + commandName + ':' + encodeURIComponent(JSON.stringify(args));
            }
        };
        var updateNativeBtn = document.getElementById('updateNativeBtn');
        var fNameTextField = document.getElementById('fname');
        var lNameTextField = document.getElementById('lname');
        var clickevent = window.ontouchend ? 'touchend' : 'click';
        updateNativeBtn.addEventListener(clickevent, function (evt) {
            evt.preventDefault();
            var nameData = {
                fname: fNameTextField.value,
                lname: lNameTextField.value
            };
            if (window.Android) {
                Android.updateNames(JSON.stringify(nameData));
            } else {
           nativeBridge.invoke('updateNames', nameData);
            }
        });
        window.setNames = function(names) {
            fNameTextField.value = names.fname;
            lNameTextField.value = names.lname;
        }
     })();
</script>
</html>

/assets/sendData.html   :
<html>
<head>
<title>I am the sender</title>
</head>

<body>
<h3>I am the sender</h3>

<form name="myform" method="POST" action="" onsubmit="dosubmit()">

<label>First Name:</label>  
<input type="text" id="frstName" name="frstName"/>
<br/>

<label>Last Name:</label>  
<input type="text" id="lastName" name="lastName"/>
<br/>
<label>City:</label>  
<input type="text" id="city" name="city"/>
<br/>
<label>Pincode:</label>  
<input type="text" id="pinCode" name="pinCode"/>

<br/><br/>
  <input type="submit" value="Send text to receiver"/>
</form>


<script language="JavaScript">

// this script must be after the form else
// the document object is not recognized.
// unescape converts %20 to blanks, etc.

  var string = window.location.href;
  var getit = new Array();
  var finalarray= new Array();
  getit=string.split("?");
  
  //here u can split the string"frstName@lastName" into two parts to show both frstName and lastName differntly..
  finalarray=unescape(getit[1]).split("@");
  
  document.getElementById('frstName').value = unescape(finalarray[0]);
document.getElementById('lastName').value = unescape(finalarray[1]);

//This method will be called when user pressing the Submit button and it will navigate to other HTML page.
function dosubmit()
{
  document.myform.action = "receiveData.html?" + document.myform.frstName.value+"@"+document.myform.lastName.value+"@"+document.myform.city.value+"@"+document.myform.pinCode.value;
  window.event.returnValue = true;
}
</script>
</body>
</html>


/assets/receiveData.html   :
<html>
<head>
<title>I am the receiver</title>
</head>

<body>
<h3>I am the Receiver</h3>

<form name="myform" action="webviewContent.html" >
  Values Received: 
  <br/>
  
  First Name: <label id="firstName"></label>
  <br/>
  Last Name: <label id="lastName" ></label>
  <br/>
  City : <label id="city" ></label>
  <br/>
  PinCode: <label id="picode" ></label>
  <br/>
  <input type="submit" value="GoToHomePage"/>
</form>

<script language="JavaScript">

// this script must be after the form else the document object is not recognized.
// unescape converts %20 to blanks, etc.
//This complete below code will received data from previous html(sendData.html) file and parse it and show in input field..

  var string = window.location.href;

  //code to display a toast with the string it received from sendData.html file...
  Android.showToast(string);
  
  var getit = new Array();
  var finalarray= new Array();
  getit=string.split("?");
  
  //if u want to set text in input field then use this...
  //document.myform.firstName.value = unescape(getit[1]);
  
  //here u can split the string"frstName@lastName" into two parts to show both frstName and lastName differntly..
  finalarray=unescape(getit[1]).split("@");
  
  //if u want to set text in label then use this format with innerHTML..
document.getElementById('firstName').innerHTML =unescape(finalarray[0]);
document.getElementById('lastName').innerHTML =unescape(finalarray[1]);
document.getElementById('city').innerHTML =unescape(finalarray[2]);
document.getElementById('picode').innerHTML =unescape(finalarray[3]);
</script>
</body>
</html>

    a) Initially screen will be displayed like this after executing the application..

    b) Enter FirstName and LastName and click "sendDataToAndroidNative" button to send the text.

 c)After pressing the button text will goes from HTML file to Android Native displayed like this.and press the "sendDataToSecondHTML" button to send text to other HTML File...


d) Then Second HTML file received the text and fill other city,pincode fields and click the button specified.


e)Finally Details screen will receive the data and display the content in HTML Labels like this..after that press the button to return to home page.


Comments

Popular posts from this blog

Custom Dialog with no title and full screen in Android

code to display .pdf,.text,.DOC,.DOCX,.doc extension files exists in SDCard

Best working code to set Date limits on Date Picker Dialog,in Android