Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Creating an Android Epoch HTML/JavaScript Calendar

Author: Wagied Davids
Published? true
FormatLanguage: WikiFormat

Problem:

You require a custom calendar using Javascript. This recipe also shows how to interact between Javascript and Java.

Solution:

Use a WebView component to load an HTML file containing the third-party Epoch calendar javascript component. Steps involved:

TestCalendar/assets/

  • Code your main HTML file for referencing Epoch calendar
  • Create an Android Activity for launching the Epoch calendar.

Note that files placed in Android assets directory are referenced like this: file:///android_asset/ (NOTE: triple leading slash and singular spelled asset )

Discussion:

The solution - to make use of the WebView component for loading an HTML file containing the Epoch calendar javascript component. To enable interaction between the Javascript based view layer and the Java-based logic layer, a Java--Javascript bridge interface is required, MyJavaScriptInterface inner class. The onDayClick() function shows how to to call a javascript function from an Android actiivity eg. webview.loadUrl("javascript: popup();");

File: calendarview.html

<html>
	<head>
		<title>My Epoch DHTML Javascript Calendar</title>
		<style type="text/css">
			dateheader {
				-background-color: #3399FF;
				-webkit-border-radius: 10px;
				-moz-border-radius: 10px;
				-border-radius: 10px;
				-padding: 5px;
			}
		</style>
		
		<style type="text/css">
		html {height:100%;}
		body {height:100%; margin:0; padding:0;}
		#bg {position:fixed; top:0; left:0; width:100%; height:100%;}
		#content {position:relative; z-index:1;}
        </style>
        <!--[if IE 6]>
		<style type="text/css">
		html {overflow-y:hidden;}
		body {overflow-y:auto;}
		#page-background {position:absolute; z-index:-1;}
		#content {position:static;padding:10px;}
		</style>
		<![endif]-->
		
		<link rel="stylesheet" type="text/css" href="epoch_v106/epoch_styles.css" />
		<script type="text/javascript" src="epoch_v106/epoch_classes.js"></script>

		<script type="text/javascript">
			/*You can also place this code in a separate file and link to it like epoch_classes.js*/
			var my_cal;
			      
    		window.onload = function () {
				my_cal = new Epoch('epoch_basic','flat',document.getElementById('basic_container'));		
			};
			
			function popup()
				{
					var weekday=new Array("Sun","Mon","Tue","Wed","Thur","Fri","Sat");
					var monthname=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
					var date = my_cal.selectedDates.length > 0 ? my_cal.selectedDates[0] : null;
					if ( date != null )
						{
    						var day = date.getDate();
    						var dayOfWeek= date.getDay();
							var month = date.getMonth();
							var yy = date.getYear();
							var year = (yy < 1000) ? yy + 1900 : yy;
    						
    						/* Set the User selected date in HTML form*/
    						var dateStr= weekday[dayOfWeek]  + ", " + day + " " + monthname[month] + " " + year;
    						document.getElementById("selected_date").value= dateStr;
    						
    						/* IMPORTANT: Call Android Javascript->Java bridge setting a Java-field variable */
    						window.android.setSelectedDate( date );
    						window.android.setCalendarButton( date );
						}
				}
		</script>
	</head>
	<body>
	<div id="bg"><img src="bg.png" width="100%" height="100%" alt=""></div>
		<div id="content">
			<div class="dateheader" align="center">
				<form name="form_selected_date">
						<span style="color:white">Selected day:</span>
						<input id="selected_date" name="selected_date" type="text" readonly="true">
				</form>
			</div>
			<div id="basic_container" onClick="popup()"></div>
		</div>
	</body>
</head>>

File: CalendarView.java


import java.util.Date;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.pfizer.android.R;
import com.pfizer.android.utils.DateUtils;
import com.pfizer.android.view.screens.journal.CreateEntryScreen;

public class CalendarViewActivity extends Activity
	{
		private static final String tag = "CalendarViewActivity";
		private ImageView calendarToJournalButton;
		private Button calendarDateButton;
		private WebView webview;
		private Date selectedCalDate;

		private final Handler jsHandler = new Handler();

		/** Called when the activity is first created. */
		@Override
		public void onCreate(Bundle savedInstanceState)
			{
				Log.d(tag, "Creating View ...");
				super.onCreate(savedInstanceState);

				// Set the View Layer
				Log.d(tag, "Setting-up the View Layer");
				setContentView(R.layout.calendar_view);

				// Go to CreateJournalEntry
				calendarToJournalButton = (ImageView) this.findViewById(R.id.calendarToJournalButton);
				calendarToJournalButton.setOnClickListener(new OnClickListener()
					{
						@Override
						public void onClick(View v)
							{
								Log.d(tag, "Re-directing -> CreateEntryScreen ...");
								Intent intent = intent = new Intent(getApplicationContext(), CreateEntryScreen.class);
								startActivity(intent);
							}
					});

				// User-Selected Calendar Date
				calendarDateButton = (Button) this.findViewById(R.id.calendarDateButton);

				// Get access to the WebView holder
				webview = (WebView) this.findViewById(R.id.webview);

				// Get the settings
				WebSettings settings = webview.getSettings();

				// Enable Javascript
				settings.setJavaScriptEnabled(true);

				// Enable ZoomControls visibility
				settings.setSupportZoom(true);

				// Add Javascript Interface
				webview.addJavascriptInterface(new MyJavaScriptInterface(), "android");

				// Set the Chrome Client
				webview.setWebChromeClient(new MyWebChromeClient());

				// Load the URL of the HTML file
				webview.loadUrl("file:///android_asset/calendarview.html");

			}

		public void setCalendarButton(Date selectedCalDate)
			{
				Log.d(tag, jsHandler.obtainMessage().toString());
				calendarDateButton.setText(DateUtils.convertDateToSectionHeaderFormat(selectedCalDate.getTime()));
			}

		/**
		 * 
		 * @param selectedCalDate
		 */
		public void setSelectedCalDate(Date selectedCalDate)
			{
				this.selectedCalDate = selectedCalDate;
			}

		/**
		 * 
		 * @return
		 */
		public Date getSelectedCalDate()
			{
				return selectedCalDate;
			}

		/**
		 * JAVA->JAVASCRIPT INTERFACE
		 * 
		 * @author wagied
		 * 
		 */
		final class MyJavaScriptInterface
			{
				private Date jsSelectedDate;
				MyJavaScriptInterface()
					{
						// EMPTY;
					}

				public void onDayClick()
					{
						jsHandler.post(new Runnable()
							{
								public void run()
									{
										// Java telling Javascript to do things
										webview.loadUrl("javascript: popup();");
									}
							});
					}

				/**
				 * NOTE: THIS FUNCTION IS BEING SET IN JAVASCRIPT User-selected Date in
				 * WebView
				 * 
				 * @param dateStr
				 */
				public void setSelectedDate(String dateStr)
					{
						Toast.makeText(getApplicationContext(), dateStr, Toast.LENGTH_SHORT).show();
						Log.d(tag, "User Selected Date: Javascript -> Java : " + dateStr);

						// Set the User Selected Calendar date
						setJsSelectedDate(new Date(Date.parse(dateStr)));
						Log.d(tag, "java.util.Date Object: " + Date.parse(dateStr).toString());
					}
				private void setJsSelectedDate(Date userSelectedDate)
					{
						jsSelectedDate = userSelectedDate;
					}
				public Date getJsSelectedDate()
					{
						return jsSelectedDate;
					}
			}

		/**
		 * Alert pop-up for debugging purposes
		 * 
		 * @author wdavid01
		 * 
		 */
		final class MyWebChromeClient extends WebChromeClient
			{
				@Override
				public boolean onJsAlert(WebView view, String url, String message, JsResult result)
					{
						Log.d(tag, message);
						result.confirm();
						return true;
					}
			}

		@Override
		public void onDestroy()
			{
				Log.d(tag, "Destroying View!");
				super.onDestroy();
			}
	}

For debugging purposes, a MyWebChromeClient is created and the onJsAlert() method is overriden.

Download:

The source code for this project is in the Android Cookbook repository at http://github.com/IanDarwin/Android-Cookbook-Examples, in the subdirectory EpochJSCalendar.
No records found.