Sunday, June 3, 2012

SAWACE - SAWINFO Monitor - My First Android Application


INTRODUCTION
Mobile app development is not a new fad. But with growing popularity of android mobile operating system mobile app development is reaching to more and more developers. Earlier in one of my blog I had developed a mobile application for Windows based mobiles [ iMateBuddy ]. Though professionally I'm working on Microsoft Technologies, but I wanted to try my hand at android application development using java. So as soon as I bought my first android mobile I was very eager to develop my own android app. 

SAWACE Android App  powered by sawinfotech.com

App settings page to set url to hit. Start button starts the service.
Website UP notification. Notification detail page.
click the images to enlarge +

The Idea Behind
Nowadays android app for almost everything is available on Play Store. So what new could I create that was not there already and was very personalized. After giving some thought to what android app I should build I decided on creating a Website Monitor for my site. Why? I'm hosting my website www.sawinfotech.com from a VM hosted on my home desktop. And although its protected against occasional power failure by a UPS, intermittently the fail-over to UPS is delayed sometimes and due to which desktop power downs, in turn shutting down the VM and in turn the site goes down. I would not come to know of this down time until I access the site next time which could sometimes be more than a day or two. So I though of building a mobile app which would run as a service and would periodically hit my site to check if it is up or not and give the notification accordingly.

Application Details
So with this idea in mind I created a app which is quite simple. Basically it hits a URL of sawinfotech.com periodically (every 8 hrs)  and gives a notification if the site is Up or Down. The URL is configurable and can always be changed through Settings screen. To change the URL we just have to stop the service, change the URL and start the service again. Short and simple. Following are some code snippets.

Home Class

































Above class handles the initial loading of the Settings page and the event handlers for Starting and Stopping the service.

Service Class


































This class is the heart of the app which runs as a service which is invoked periodically. The function of the service is to hit the configured URL of my site sawinfotech.com to check if the site is up.


Notification Class



















The Notification class is used to generate the notification to show the user if the service return of success message in case the website is up or a failure message if the site is down.

AndroidManifest.xml














Manifest file is configuration file similar to web.config of asp.net. Here we list all the Activity classes (screens), Service classes, user permission etc. For this app I have used permission for internet access. One more thing we can configure is here is to set which Activity/Screen is the loaded at startup of app.

Code is quite self explanatory. If any queries please add comments and I'll try to answer to best of my knowledge.

Just FYI, my blog is not sponsored by Samsung :)

s.a.w

Sunday, January 23, 2011

Nested GridView within Repeater with Paging, Sorting, GridSave, List Sort using IComparable


There are many different implementations of this functionality available on net in parts. I just thought it would be good thing to put all the different functionalities in a single example. Below is the list of functionalities I have included in the following example :


  • Nested GridView in Repeater.

  • Paging in child GridView.

  • Sorting in child GridView.

  • Hide\Unhide child GridView using javascript.

  • Sort List object using IComparable interface.

  • Save nested child grids data on single click.

Download Code - 30 KB
In the example I'm showing Locations in a Repeater and their SubLocations data in nested GridView. To start with, I'm using a List of Locations and SubLocations custom objects to bind to the data controls.

public class Location
{
public int LocationId { get; set; }
public string LocationName { get; set; }
public List SubLocations { get; set; }
}
public class SubLocation :IComparable
{
public int SubLocationId { get; set; }
public string SubLocationName { get; set; }
public int Count { get; set; }
public string Owner { get; set; }
public bool IsOpen { get; set; }
public int CompareTo(SubLocation other)
{
return other.SubLocationName.CompareTo(this.SubLocationName);
}
public static Comparison CountComparisonASC = delegate(SubLocation s1, SubLocation s2)
{
return s1.Count.CompareTo(s2.Count);
};
public static Comparison CountComparisonDESC = delegate(SubLocation s1, SubLocation s2)
{
return s1.Count.CompareTo(s2.Count) * -1 ;
};
public static int SaveSubLocations(List objSubLocationList)
{
//Save method to save data in database.
return 0;
}
}
}


IComparable interface is implemented in SubLocation class inorder to support generic comparision delegates for Sorting in GridView. I'm generating the list of data in the code itselft, using the methode GetData(), to avoid database interaction as this is just a demo. SaveSubLocations method returns 0, in place of actually database update for the same reason.

Heres the markup for the nested GridView within Repeater control:



GridView's PageIndexChanging event:protected void gvSubLocations_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView gv = (GridView)sender;
gv.PageIndex = e.NewPageIndex;
List SubLocationsList = new List();
Label lb = (Label)gv.NamingContainer.FindControl("lblLocation");
Hashtable SubLocationDetails = (Hashtable)Session["SubLocationDetails"];
SubLocationsList = (List)SubLocationDetails[lb.Text];
gv.DataSource = SubLocationsList;
gv.DataBind();
}


GridView's Sorting :
protected void gvSubLocations_Sorting(object sender, GridViewSortEventArgs e)
{
if (ViewState[_VWSORTDIRECTION].ToString() == SORT_ASCENDING)
ViewState[_VWSORTDIRECTION] = SORT_DESCENDING;
else
ViewState[_VWSORTDIRECTION] = SORT_ASCENDING;
ViewState[_VWSORTCOLUMN] = e.SortExpression;
GridView gv = (GridView)sender;
List ListSubLocations = new List();
Label lb = (Label)gv.NamingContainer.FindControl("lblLocation");
Hashtable SubLocationDetails = (Hashtable)Session["SubLocationDetails"];
ListSubLocations = (List)SubLocationDetails[lb.Text];
SortAndBind(ListSubLocations, ViewState[_VWSORTDIRECTION].ToString(), e.SortExpression, gv);
}


Repeater's Databound event: Here we bind the child gridview controls.

protected void rptLocations_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item e.Item.ItemType == ListItemType.AlternatingItem)
{
GridView gvSubLoc = (GridView)e.Item.FindControl("gvSubLocations");
Location objLoc = (Location)e.Item.DataItem;
gvSubLoc.DataSource = objLoc.SubLocations;
gvSubLoc.DataBind();
}
}

Thursday, July 29, 2010

Resolving relative URL's in javascript

In ASP.Net we have Page.ResolveUrl() method to resolve any relative URLs like "~/images/logo.gif". This at runtime renders the complete hosted path of the image e.g. http://Hostname/VirtualDirectory/images/logo.gif. This makes our applications safely deployable to virtual directories within IIS applications without messing up the URL's.

However, with javascript we don't have such an straight forward solution. One scenario where you might face such an problem of incorrect URL resolution is while using a single Master page for Web Content pages in different directories(root and sub directories).
So here's a little tweak that can be used with javascript to resolve the URL's at runtime:

Put below javascript in either the site's Master page or if you are not using Master page, put it in the first js file thats included in the page or in the first script section of the page:

Url = function() { }
Url.prototype =
{
_relativeRoot: '<%= ResolveUrl("~/") %>',
resolve: function(relative) {
var resolved = relative;
if (relative[0] == '~') resolved = this._relativeRoot + relative.substring(2);
return resolved;
}
}
$Url = new Url();


Now, this function can be use on any page that has reference of above script to resolve a relative url as show below:

var logoUrl = $Url.resolve("~/images/logo.gif");

Although, this solution is ASP.Net specific, but it can be used in any scripting language like php, jsp, etc by simply replacing the part "ResolveUrl("~/")" from above script to respective language's equivalent code.





Saturday, May 1, 2010

Bar chart, Trend line, Tree view and Grouped columns in Flex AdvancedDataGrid



Download Code - 2 MB

Introduction

Altough I'm a ASP.Net developer, I recently had to use Adobe Flex Builder 3.0 in one of my projects. I think this is a really cool technology with very rich controls. And its integration with ASP.Net is so seamless which compeled me to like it instantly. I generated some really cool UI using data from .Net webservice and AdvancedDataGrid control of Flex. So I though I should publish this as an article so that newbies to Flex can explorer these cool features of Flex.



Description

Example I have taken is that of a Sales History of a categories of some products.Features of Flex used in this article are:

  • Tree mode of AdvancedDataGrid using Hierarchical datasource
  • BarChart within a column of the grid using Itemrenderer(using degrafa library)
  • LineChart withing a column of the grid to show trend of sales in previous years(using degrafa library)
  • Grouped columns for Sales History of last 5 years

Article consist of two parts. One is the .Net webservice which acts as the data access layer to fetch data. And other is the Flex application which consumes the webservice, fetches data and displays it in the AdvancedDataGrid control. In addition to just binding the data to columns of the grid, I have taken a example where I can use many features of the AdvancedDataGrid and Flex as a whole. Here the data returned by webservice is in XML format (as shown below) which is parsed by action script code and converted to a Hierarchical data object in order to display the data in a Tree struchture.


Check out demo link here.

The below action script parses the XML data returned by the webservice call and converts it into a Hierarchical data object of flex

var arrCollection:ArrayCollection = new ArrayCollection();
for each(var prop:XML in dataXML.children())
{
var o:CatInfo = new CatInfo();
if(prop.@Rank != null)
o.Rank = prop.@Rank;
if(prop.@Category != null)
o.Category = prop.@Category;
if(prop.@Amount != null)
o.Amount = prop.@Amount;
if(prop.@Percent != null)
o.Percent = prop.@Percent;
if(prop.@Year1 != null)
o.Year1 = prop.@Year1;
if(prop.@Year2 != null)
o.Year2 = prop.@Year2;
if(prop.@Year3 != null)
o.Year3 = prop.@Year3;
if(prop.@Year4 != null)
o.Year4 = prop.@Year4;
if(prop.@Year5 != null)
o.Year5 = prop.@Year5;

var objTrend:ArrayCollection = new ArrayCollection();
objTrend.addItemAt(o.Year1,0);
objTrend.addItemAt(o.Year2,1);
objTrend.addItemAt(o.Year3,2);
objTrend.addItemAt(o.Year4,3);
objTrend.addItemAt(o.Year5,4);
o.Trend = objTrend;
ParseNodes(o,prop);
arrCollection.addItem(o);
}

hdCollection = new HierarchicalData(arrCollection);
hdCollection.childrenField = "ChildNodes";
adg1.dataProvider = hdCollection;
I have used two controls from degrafa libraries for generating the runtime charts in the grid. One for the bar charts and other for the trend line chart. For references on using Degrafa libraries please check out the below links -

Degrafa + Datagrids = Visual Display of Data - InsideRIA
Degrafa + Data Part 2: The Sparkline

The Webservice is consumed using the service reference component as shown below



<mx:WebService
id="service1"
wsdl="http://localhost/FlexService/FlexService/TestService.asmx?WSDL">
<mx:operation name="GetData" resultFormat="object"
fault="mx.controls.Alert.show(event.fault.faultString)"
result="remotingCFCHandler(event)"
/>
</mx:WebService>



Future scope

Further I would be adding a search on grid soon to this application. So look out for the same. Do let me know if you would like some other features to be added to this application.

s.a.w

Friday, January 1, 2010

My First Blog

Hey Folks,

So now I have my own blog too. But don't worry guys, I'm not gonna be blogging about any of the boring topics like politics, global warming, terrorism around the world,... etc.

I plan to keep my blogs strictly technical in nature. To start with let me introduce you to my personal website http://www.sawinfotech.com/. Its not just my personal website having my personal information, pics, etc. Its a collection of web applications viz 'SAWiNFO', 'SAWManager', 'SAWWiki' and 'Waingankars' about which you can learn more on its home page.

It also lists my technical articles, social network links, photo albums and many more. In my first blog I just wanted to introduce me and my website. So moving forward you shall see some technical blogs, info, etc...

So keep watching this space...

s.a.w

Thursday, January 1, 2009

iMateBuddy - Soft Reset and Timer for Windows Mobile 5.0

Introduction


I always wanted to try out the windows mobile programming\ projects that had shipped with the Visual Studio 2003. And some time back I got this opportunity when I bought my first windows mobile, a i-mate PDAL with Windows Mobile 5.0 OS and hence the name "iMateBuddy".

To start with, there were two features that are common in normal mobiles, which I didn't find in Windows Mobile 5.0. One was a Soft Reset for a mobile and second is a Timer application. So I went ahead and created my own windows mobile application using VS 2008 with above two features.

Download Code - 1.5MB



Description



Timer is simple up timer with precision in thousand milliseconds. Its implemented using the Timer class from the System.Windows.Forms namespace.
Reset features resets the mobile which other wise requires to be done by pressing and holding the power button. For this the coredll.dll is imported using [DllImport("coredll.dll")] and its
KernelIoControl() methode is called with IOCTL_HAL_REBOOT code passed as the parameter.

const int FILE_DEVICE_HAL = 0x101;
const int METHOD_BUFFERED = 0;
const int FILE_ANY_ACCESS = 0;
int bytesReturned = 0;
int IOCTL_HAL_REBOOT;
IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS);
return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned);

The solution consists of the main Smart Device project and a Smart Device CAB project. The CAB project generates the .CAB file which is setup file to install the app in the mobile device. On installation, setup copies a shortcut in the 'Programs' and the 'Startup' menu.

Future Scope

Futher I'm planning to add another feature which I find missing in Windows Mobile 5.0, from the normal symbian mobiles, which is "Location Info". For this I have googled around a bit but didn't find a complete solution. One possible solution is to get the cell tower info using api mentioned in the article - http://social.msdn.microsoft.com/Forums/en-US/windowsmobiledev/thread/279ca64f-5768-4c7d-9f44-6794e173fa91. But it doesn't give all the information. I'll keep looking for a better solution and post an update.

Please let me know if anybody has a solution for getting the mobile's "Location Info" or any other suggestions\ comments about this application.

s.a.w