tag:blogger.com,1999:blog-2093372468472166212024-02-19T13:19:50.181+01:00My Small SoftLabThis blog shares posts about general software development, mobile development, good practices in software design, tips & tricks and useful samples.Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-209337246847216621.post-8955524578713457992015-07-05T14:10:00.001+02:002015-07-05T16:10:18.081+02:00Sprint retrospective<div dir="ltr" style="text-align: left;" trbidi="on">
<h3 style="text-align: left;">
Introduction </h3>
<h3 style="text-align: left;">
</h3>
For those who are not familiar with the term <a href="https://en.wikipedia.org/wiki/Scrum_%28software_development%29" target="_blank">Scrum</a>, it is a framework that helps in managing team and project development. It is a part of a larger <a href="https://en.wikipedia.org/wiki/Agile_software_development" target="_blank">Agile </a>methodology which principles it applies. We can certainly say that most of the software companies use Scrum or some other alternative Agile framework for managing their project. This popularity probably rises from its flexibility that allows a team to quickly adjust their process to the current needs of a project, but still not allowing them to divert from the project goal course.<br />
<br />
This flexibility actually creates love-hate relationship towards Scrum methodology. Also, you couldn't find two companies that carry out Scrum in the same way. Most of the teams I've met get irritated when a pattern or event that worked great in the other company doesn't work well for them. One of such patterns/events is a sprint retrospective.<br />
<br />
<h3 style="text-align: left;">
Sprint retrospective </h3>
<h3 style="text-align: left;">
</h3>
Sprint retrospective is a team meeting, usually done in the end of development iteration (i.e. "sprint"), where team discusses about events that happened in the past iteration and solutions they can provide to improve following iterations. These events are usually categorized by the certain way. Here, I'll describe one way of categorizing those events. We'll categorize events in five groups:<br />
<ol style="text-align: left;">
<li>Start - things we didn't do in the past, but it would be beneficial to start doing it.</li>
<li>Stop - things that blocked us to make a progress in our iteration. Usually, things in this category should be handled as a priority.</li>
<li>More - we identified things that helped us become more efficient.</li>
<li>Less - we identified things that made us less efficient.</li>
<li>Stay - things that are proved to be good at the last iteration and we should keep doing them.</li>
</ol>
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIqpy10uDvj3E0am2dYptSbBnB6MIlKIC16ejuNV9T9MgQEYrCZwjIB8yv8khXbrOne9ArYANPaz45g0KJBMJs0rili880AUzgoq0nH8GyFsuJ__LVBi8yckTbSDNQpUEQvKlPxKc-JBs/s1600/sprintretrpspective.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="373" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIqpy10uDvj3E0am2dYptSbBnB6MIlKIC16ejuNV9T9MgQEYrCZwjIB8yv8khXbrOne9ArYANPaz45g0KJBMJs0rili880AUzgoq0nH8GyFsuJ__LVBi8yckTbSDNQpUEQvKlPxKc-JBs/s400/sprintretrpspective.png" width="400" /></a></div>
Picture 01 - Sample of sprint retrospective board</div>
<h3 style="text-align: left;">
Process</h3>
<h3 style="text-align: left;">
</h3>
At the beginning of the iteration we draw a section for each of these categories on the whiteboard (see Picture 01). During iteration, team members are allowed to write their suggestions on the board. Once the iteration completes, Scrum master will review the board and prepare the team for the meeting. Entire team discusses of each suggestion and comes to the conclusion. These discussions should be done in three steps:<br />
<ol style="text-align: left;">
<li>need - identify reasons why this event/suggestion should be beneficial or damaging to the team</li>
<li>decision - entire team needs to come up with the decision whether to accept or decline the suggustion</li>
<li>action - maybe the most important part. As before, the entire team needs to come up with idea of how to carry out the proposed solution in the following iteration.</li>
</ol>
Once the Sprint retrospective is finished, all the meeting points and tasks should be documented and shared between team members. Also, it would be a good practice to briefly review these previous meeting points before new Sprint retrospective in order to determine if we failed in providing identified actions.<br />
<br />
<h3 style="text-align: left;">
Known issues</h3>
<h3 style="text-align: left;">
</h3>
One of the main issues here is carrying out the actions we agreed about. This happens a lot. Most of the time it happens that team members simply forgot about performing them. It even happens to people who suggested them in the first place. And this is perfectly OK (I can't emphasize this enough). The worst thing that can happen is to blame each other in the team for not doing his/her job.<br />
<br />
The reason why this usually happens is that we all get overwhelmed by work, so we don't have much time to develope an action as a habit and therefore we'll probably forget about it.<br />
<br />
I've seen that Scrum masters usually start by introducing new rules for following certain actions. Sometimes they are printed on a sheet of paper and shared between team members in order to remind them to behave a certain way in a certain situations.<br />
This doesn't work in most cases. Due to a fact that humans are usually very defensive when they are forced to do things in a certain way.<br />
Blaming people is also not the way of handling issues, due to a fact that it won't make any grownup person fill better or even perform better.<br />
<br />
<h3 style="text-align: left;">
So what to do? How to make people remember? </h3>
<h3 style="text-align: left;">
</h3>
It is important that all actions we identified as beneficial should become habits and <b>this takes time</b>. It is my personal experience that the best way is to start small by picking 2-3 actions from a list and making a decision within team members that we'll work on these things in the following iteration. Don't force anything. Not all team members will remember to follow them, usually they simply forget or they don't see the benefit yet. But, at the next sprint retrospective you should make sure to recommend team members who followed suggestions and performed the actions. Also, it is important to underline what benefits this had to our project. This way we can attract other team members to become more engaging.<br />
<br />
<h3 style="text-align: left;">
Conclusion</h3>
<h3 style="text-align: left;">
</h3>
There is no easy way to apply a certain process methodology within your company. In most cases we should balance between adjusting methodology frameworks towards team behavior and modifying team habits toward project goal.<br />
It is important that there is no brute force approach to solving this problem. There is only the way where all team members work together on making their work environment the most enjoyable and productive one.<br />
<br /></div>
Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com0tag:blogger.com,1999:blog-209337246847216621.post-57954402890438682332013-12-20T00:29:00.001+01:002013-12-20T00:29:57.420+01:00PhoneGap/Cordova: loading content from URL<p> </p> <h2>Introduction</h2> <p>A colleague of mine and myself struggled recently about strange problem during development of mobile application by using PhoneGap framework.</p> <p>The problem manifested in a strange behavior. Image couldn’t load content from specified URL. This actually manifested only on new versions of Android and was very strange for us since we double checked the image resource URL, which worked correctly within HTML in any browser.</p> <div style="color: black; background-color: white"><pre><span style="color: blue">var</span> email = $.mobile.activePage.find(<span style="color: #a31515">'#txtEmail'</span>).val();<br /><span style="color: blue">var</span> urlGravatar = <span style="color: #a31515">"http://www.gravatar.com/avatar/"</span> + md5Calculator.md5(email);<br />$.mobile.activePage.find(<span style="color: #a31515">'#profileImageSection'</span>).html(<span style="color: #a31515">"<img id='profile_img' src='"</span>+urlGravatar+<span style="color: #a31515">"' />"</span>);<br /></pre></div><br /><p>By using jquery mobile we wrote this code snippet which does the MD5 calculation over the entered email address and generates URL to Gravatar image. Next, we insert an image element inside our HTML page.</p><br /><h2>Solution</h2><br /><p>After spending a lot of time searching for a solution we finally found the source of the problem.</p><br /><p>Inside PhoneGap’s <strong>res/xml/config.xml </strong>there is a special element that allows/disallows retrieving content from remote resources. Changing default value of localhost to allow all (i.e. *) sets the settings to allow retrieving content from any source. </p><br /><p><access origin="*" /></p><br /><p>This way our image loaded successfully. If you want to be more specific, you can allow content on a certain domain as well:</p><br /><p><access origin=”http://google.com” /></p> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com0tag:blogger.com,1999:blog-209337246847216621.post-56047253151153087972013-07-11T19:29:00.001+02:002013-07-11T19:29:17.476+02:00Push Notification Services with Android, GCM and Google App Engine (Part 2)<p> </p> <h2>Introduction</h2> <p>In this part of the tutorial will implement server side implementation of our 3 main components. For this purpose we’ll use Google App Engine (GAE) to implement simple JSP web application as well GAE Datastore that is delivered with application. The entire project can be downloaded from <a href="https://dl.dropboxusercontent.com/u/45556593/Guestapp.zip">here</a>.</p> <p>The GAE web app will have two functionalities:</p> <ul> <li>to send message to the GCM which will then dispatch notification to all targeted devices <li>to store device tokens, once they are received from GCM</li></ul> <p>For messaging sending will have very simple form where we can enter some message and submit for delivery:</p> <p><a href="http://lh6.ggpht.com/-Wq1BEMbLe6w/Ud7rV5YI-EI/AAAAAAAAAXA/BOoD4HfLSAo/s1600-h/GAE4.png"><img title="GAE" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="GAE" src="http://lh6.ggpht.com/-EcKnPBa3RBM/Ud7rWSFeIkI/AAAAAAAAAXE/mlXCIZLNmDY/GAE_thumb2.png?imgmax=800" width="329" height="141"></a></p> <p align="center"><font size="1">Figure01: Web application in Google App Engine</font></p> <h2>Setup</h2> <p>Step01: Visit <a href="https://appengine.google.com/">Google App Engine</a> web site and create a new application.</p> <p><a href="http://lh5.ggpht.com/-ekgE5Oo0NDY/Ud7rWkd4FpI/AAAAAAAAAXQ/xe0-WPbDfWo/s1600-h/GAECreateApp4.png"><img title="GAECreateApp" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="GAECreateApp" src="http://lh4.ggpht.com/-oKuJbj7v1Ag/Ud7rXAGpUaI/AAAAAAAAAXU/frC6Imkd64Y/GAECreateApp_thumb2.png?imgmax=800" width="285" height="324"></a></p> <h2 align="center"><font style="font-weight: normal" size="1">Figure02: Create GAE application</font></h2> <p align="left">Step02: Install GAE plugin within your Eclipse. Visit <a href="https://developers.google.com/appengine/docs/java/tools/eclipse">here</a> for guidelines.</p> <p align="left">Step03: Once you installed the plugin, in Eclipse go to <em>File > New > Other </em>and choose under <em>Google</em> section <em>Web application project.</em></p> <p align="left"><a href="http://lh5.ggpht.com/-KACoAkWAqKs/Ud7rXp2oadI/AAAAAAAAAXc/U02j-cPERy0/s1600-h/GAEEclipse014.png"><img title="GAEEclipse01" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="GAEEclipse01" src="http://lh6.ggpht.com/-Ic1uuZc8aHM/Ud7rYK0viqI/AAAAAAAAAXk/43mOhOhnE78/GAEEclipse01_thumb2.png?imgmax=800" width="334" height="259"></a></p> <h2 align="center"><font style="font-weight: normal" size="1">Figure03: Select GAE project in Eclipse</font></h2> <p align="left">Step04: Name your project and namespace and uncheck the <em>Generate project sample code </em>option.</p> <p align="center"><a href="http://lh5.ggpht.com/-wG_IXBCNsgM/Ud7rYZohPjI/AAAAAAAAAXs/6yq_vrlX_1k/s1600-h/GAEEclipse9.png"><img title="GAEEclipse" style="display: inline" alt="GAEEclipse" src="http://lh3.ggpht.com/-dyimz93NbMU/Ud7rY9YlM_I/AAAAAAAAAX4/XHoYRTZ4rv8/GAEEclipse_thumb5.png?imgmax=800" width="272" height="392"></a></p> <p align="center"><font style="font-weight: normal" size="1">Figure04: Create GAE project in Eclipse</font></p> <h2 align="left">Implementation</h2> <p>Our web application consists of two servlets (<em>MainActivityServlet.java, StoreIdServlet.java</em>) and two JSP pages (<em>main.jsp, storeid.jsp</em>) respectively.</p> <p><a href="http://lh5.ggpht.com/-4pNDDWMUTrg/Ud7rZYU5l8I/AAAAAAAAAX8/lYciFa27xR0/s1600-h/GAEEclipse024.png"><img title="GAEEclipse02" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="GAEEclipse02" src="http://lh4.ggpht.com/-Nrt7ehm1Jj4/Ud7rZ-8-8LI/AAAAAAAAAYE/G4hfkru6WLY/GAEEclipse02_thumb2.png?imgmax=800" width="200" height="258"></a></p> <p align="center"><font style="font-weight: normal" size="1">Figure05: GAE project structure in Eclipse</font></p> <p align="left">The <em>MainActivityServlet.java</em> servlet handles HTTP requests that are coming from the <em>main.jsp</em> form (see Figure01) and is in charge of sending notification messages to the GCM service. The second functionality for storing device tokens is implemented within <em>StoreIdServlet.java </em>servlet and it also handles requests from <em>storeid.jsp </em>to store device tokens manually if necessary.</p> <p align="left">Following code is the implementation of the <em>MainActivityServlet.java</em> servlet:</p> <div style="color: black; background-color: white"><pre><span style="color: blue">package</span> com.guestapp;<br /><span style="color: blue">import</span> java.io.IOException;<br /><span style="color: blue">import</span> java.util.ArrayList;<br /><span style="color: blue">import</span> java.util.List;<br /><span style="color: blue">import</span> java.util.logging.Logger;<br /><br /><span style="color: blue">import</span> javax.servlet.ServletException;<br /><span style="color: blue">import</span> javax.servlet.http.HttpServlet;<br /><span style="color: blue">import</span> javax.servlet.http.HttpServletRequest;<br /><span style="color: blue">import</span> javax.servlet.http.HttpServletResponse;<br /><br /><span style="color: blue">import</span> com.google.android.gcm.server.Message;<br /><span style="color: blue">import</span> com.google.android.gcm.server.MulticastResult;<br /><span style="color: blue">import</span> com.google.android.gcm.server.Sender;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.DatastoreService;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.DatastoreServiceFactory;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.Entity;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.EntityNotFoundException;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.FetchOptions;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.Key;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.KeyFactory;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.PreparedQuery;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.Query;<br /><br /><span style="color: blue">public</span> <span style="color: blue">class</span> MainActivityServlet <span style="color: blue">extends</span> HttpServlet {<br /><br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> <span style="color: blue">long</span> serialVersionUID = 1L;<br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> Logger log = Logger.getLogger(MainActivityServlet.<span style="color: blue">class</span>.getName());<br /> <span style="color: green">// API_KEY is sender_auth_token (server key previously generated in GCM)</span><br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> String API_KEY = <span style="color: #a31515">""</span>;<br /> <span style="color: green">// Datastore is database where all device tokens get stored</span><br /> <span style="color: blue">private</span> <span style="color: blue">static</span> DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();<br /> <br /> <br /> <span style="color: green">// Handles HTTP GET request from the main.jsp </span><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> doGet(HttpServletRequest req,<br /> HttpServletResponse resp) <span style="color: blue">throws</span> ServletException, IOException {<br /> resp.sendRedirect(<span style="color: #a31515">"/main.jsp"</span>); <br /> }<br /> <br /> <span style="color: green">// Handles HTTP POST request - submit message from the main.jsp</span><br /> <span style="color: blue">public</span> <span style="color: blue">void</span> doPost(HttpServletRequest req, HttpServletResponse resp)<br /> <span style="color: blue">throws</span> IOException { <br /> String txtInput = req.getParameter(<span style="color: #a31515">"txtInput"</span>);<br /> <br /> <span style="color: green">// Instantiating sender for dispatching message to GCM</span><br /> Sender sender = <span style="color: blue">new</span> Sender(API_KEY);<br /> <span style="color: green">// Creating a message for GCM</span><br /> Message message = <span style="color: blue">new</span> Message<br /> .Builder()<br /> .addData(<span style="color: #a31515">"message"</span>, txtInput)<br /> .build();<br /> <br /> ArrayList<String> devices = getAllRegIds();<br /> <span style="color: blue">if</span>(!devices.isEmpty()){<br /> <span style="color: green">// Sending multicast message to GCM specifying all targeting devices</span><br /> MulticastResult result = sender.send(message, devices, 5);<br /> log.info(<span style="color: #a31515">"Message posted: "</span> + txtInput);<br /> resp.sendRedirect(<span style="color: #a31515">"/main.jsp?message="</span>+txtInput);<br /> }<span style="color: blue">else</span>{<br /> log.info(<span style="color: #a31515">"No devices registered."</span>);<br /> resp.sendRedirect(<span style="color: #a31515">"/main.jsp?message=warning-no-devices"</span>);<br /> }<br /> }<br /> <br /> <span style="color: green">// Reads all previously stored device tokens from the database</span><br /> <span style="color: blue">private</span> ArrayList<String> getAllRegIds(){<br /> ArrayList<String> regIds = <span style="color: blue">new</span> ArrayList<String>();<br /> Query gaeQuery = <span style="color: blue">new</span> Query(<span style="color: #a31515">"GCMDeviceIds"</span>);<br /> PreparedQuery pq = datastore.prepare(gaeQuery);<br /> <span style="color: blue">for</span> (Entity result : pq.asIterable()){<br /> String id = (String) result.getProperty(<span style="color: #a31515">"regid"</span>);<br /> regIds.add(id);<br /> }<br /> <br /> <span style="color: blue">return</span> regIds;<br /> }<br />}<br /><br /></pre></div><br /><p align="left">The implementation of <em>main.jsp</em> page looks like:</p><br /><div style="color: black; background-color: white"><pre><%@ page contentType="text/html;charset=UTF-8" language="java" %><br /><%@ page import="java.util.List" %><br /><%@ page import="com.google.appengine.api.users.User" %><br /><%@ page import="com.google.appengine.api.users.UserService" %><br /><%@ page import="com.google.appengine.api.users.UserServiceFactory" %><br /><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %><br /><br /><span style="color: blue"><</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">body</span><span style="color: blue">></span><br /> Message:<br /> <% if (request.getParameter("message") != null) { %><br /> <%= request.getParameter("message")%><br /> <% } %><br /> <span style="color: blue"><</span><span style="color: #a31515">form</span> <span style="color: red">action</span><span style="color: blue">=</span><span style="color: blue">"/main"</span> <span style="color: red">method</span><span style="color: blue">=</span><span style="color: blue">"post"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span><span style="color: blue">></span><span style="color: blue"><</span><span style="color: #a31515">textarea</span> <span style="color: red">name</span><span style="color: blue">=</span><span style="color: blue">"txtInput"</span> <span style="color: red">rows</span><span style="color: blue">=</span><span style="color: blue">"3"</span> <span style="color: red">cols</span><span style="color: blue">=</span><span style="color: blue">"60"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">textarea</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span><span style="color: blue">></span><span style="color: blue"><</span><span style="color: #a31515">input</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"submit"</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"Submit"</span> <span style="color: blue">/></span><span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">form</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">body</span><span style="color: blue">></span><br /><span style="color: blue"></</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /><br /></pre></div><br /><p>The implementation of second <em>StoreIdServlet.java</em> servlet is like following:</p><br /><div style="color: black; background-color: white"><pre><span style="color: blue">package</span> com.guestapp;<br /><span style="color: blue">import</span> java.io.IOException;<br /><span style="color: blue">import</span> java.util.logging.Logger;<br /><br /><span style="color: blue">import</span> javax.servlet.ServletException;<br /><span style="color: blue">import</span> javax.servlet.http.HttpServlet;<br /><span style="color: blue">import</span> javax.servlet.http.HttpServletRequest;<br /><span style="color: blue">import</span> javax.servlet.http.HttpServletResponse;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.DatastoreService;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.DatastoreServiceFactory;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.Entity;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.EntityNotFoundException;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.Key;<br /><span style="color: blue">import</span> com.google.appengine.api.datastore.KeyFactory;<br /><br /><span style="color: blue">public</span> <span style="color: blue">class</span> StoreIdServlet <span style="color: blue">extends</span> HttpServlet {<br /><br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> <span style="color: blue">long</span> serialVersionUID = 1L;<br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> Logger log = Logger.getLogger(MainActivityServlet.<span style="color: blue">class</span>.getName());<br /> <span style="color: green">// Datastore is database where all device tokens get stored</span><br /> <span style="color: blue">private</span> <span style="color: blue">static</span> DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();<br /> <br /> <span style="color: green">// Handles HTTP GET request from the storeid.jsp</span><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> doGet(HttpServletRequest req,<br /> HttpServletResponse resp) <span style="color: blue">throws</span> ServletException, IOException {<br /> resp.sendRedirect(<span style="color: #a31515">"/storeid.jsp"</span>); <br /> }<br /> <br /> <span style="color: green">// Handles HTTP POST request - submit message from the storeid.jsp</span><br /> <span style="color: blue">public</span> <span style="color: blue">void</span> doPost(HttpServletRequest req, HttpServletResponse resp)<br /> <span style="color: blue">throws</span> IOException { <br /> String txtRegId = req.getParameter(<span style="color: #a31515">"txtRegId"</span>);<br /> <br /> <span style="color: green">// Creates device token entity and saves it in the database</span><br /> Entity regId = <span style="color: blue">new</span> Entity(<span style="color: #a31515">"GCMDeviceIds"</span>,txtRegId);<br /> regId.setProperty(<span style="color: #a31515">"regid"</span>, txtRegId);<br /> <span style="color: blue">if</span>(!isReqIdExist(txtRegId)){<br /> saveToDB(regId);<br /> log.info(<span style="color: #a31515">"RegId inserted into DB: "</span> + txtRegId);<br /> }<br /> }<br /> <br /> <span style="color: green">// Save device token in the database</span><br /> <span style="color: blue">private</span> <span style="color: blue">void</span> saveToDB(Entity regId){<br /> datastore.put(regId);<br /> }<br /> <br /> <span style="color: green">// Checks if the device token already exist in the database</span><br /> <span style="color: blue">private</span> <span style="color: blue">boolean</span> isReqIdExist(String regId){<br /> Key keyRegId = KeyFactory.createKey(<span style="color: #a31515">"GCMDeviceIds"</span>, regId);<br /> Entity entity = <span style="color: blue">null</span>;<br /> <span style="color: blue">try</span> {<br /> entity = datastore.get(keyRegId);<br /> } <span style="color: blue">catch</span> (EntityNotFoundException e) {<br /> <span style="color: green">// TODO Auto-generated catch block</span><br /> e.printStackTrace();<br /> }<br /> <span style="color: blue">if</span>(entity!=<span style="color: blue">null</span>){<br /> <span style="color: blue">return</span> <span style="color: blue">true</span>;<br /> }<br /> <span style="color: blue">return</span> <span style="color: blue">false</span>;<br /> }<br />}<br /><em><font color="#333333" face="Arial"></font></em><br /></pre></div><br /><p>The corresponding JSP page, <em>storeid.jsp </em>looks like:</p><br /><div style="color: black; background-color: white"><pre><%@ page contentType="text/html;charset=UTF-8" language="java" %><br /><%@ page import="java.util.List" %><br /><%@ page import="com.google.appengine.api.users.User" %><br /><%@ page import="com.google.appengine.api.users.UserService" %><br /><%@ page import="com.google.appengine.api.users.UserServiceFactory" %><br /><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %><br /><br /><span style="color: blue"><</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /><br /> <span style="color: blue"><</span><span style="color: #a31515">body</span><span style="color: blue">></span><br /> Insert device Registration_id:<br /> <span style="color: blue"><</span><span style="color: #a31515">form</span> <span style="color: red">action</span><span style="color: blue">=</span><span style="color: blue">"/storeid"</span> <span style="color: red">method</span><span style="color: blue">=</span><span style="color: blue">"post"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span><span style="color: blue">></span><span style="color: blue"><</span><span style="color: #a31515">textarea</span> <span style="color: red">name</span><span style="color: blue">=</span><span style="color: blue">"txtRegId"</span> <span style="color: red">rows</span><span style="color: blue">=</span><span style="color: blue">"3"</span> <span style="color: red">cols</span><span style="color: blue">=</span><span style="color: blue">"60"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">textarea</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span><span style="color: blue">></span><span style="color: blue"><</span><span style="color: #a31515">input</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"submit"</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"Submit"</span> <span style="color: blue">/></span><span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">form</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">body</span><span style="color: blue">></span><br /><span style="color: blue"></</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /><br /></pre></div><br /><h2>Deployment</h2><br /><p>Right click on the project and go to <em>Google > App Engine Settings… </em>Fill in the <em>application id</em> that goes before “.appspot.com” part.</p><br /><p><a href="http://lh3.ggpht.com/-LKjRZQeqQmE/Ud7raSRrK3I/AAAAAAAAAYQ/xdZcxl-tR1Q/s1600-h/GAEEclipse033.png"><img title="GAEEclipse03" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="GAEEclipse03" src="http://lh4.ggpht.com/-fcDXOq9wcCg/Ud7rbLBxNZI/AAAAAAAAAYU/gMkOBPsTMM0/GAEEclipse03_thumb1.png?imgmax=800" width="386" height="348"></a></p><br /><p align="center"><font style="font-weight: normal" size="1">Figure06: GAE deployment configuration</font></p><br /><p align="justify">Now go right click on the project <em>Google > Deploy to App Engine</em> and then click deploy.</p><br /><p align="justify">Once your deployment is successfully finished you can go back to Google App Engine web site or check your application by visiting <em>appid</em>.appspot.com. Also, on Google App Engine web site you can check <em>Datastore Viewer </em>for preview your database records.</p><br /><p align="justify"> </p><br /><p align="justify">The remaining component of notification system is Android application. Check the implementation in the next blog.</p> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com15tag:blogger.com,1999:blog-209337246847216621.post-46408083276339815472013-07-11T19:27:00.000+02:002013-07-11T19:29:51.157+02:00Push Notification Services with Android, GCM and Google App Engine (Part 3)<p> </p> <p> </p> <h2>Introduction</h2> <p>As the last piece of the 3-piece architecture is implementation of the Android application which will be able to register and receive notification messages from GCM.</p> <p>The complete Android application can be downloaded from <a href="https://dl.dropboxusercontent.com/u/45556593/GCMAndroidDemo.zip">here</a>.</p> <p>The sending of the notification is done in following order:</p> <p> <table cellspacing="0" cellpadding="2" width="723" border="0"> <tbody> <tr> <td valign="top" width="133"> <p align="left">1. Google App engine – submit a message</p></td> <td valign="top" width="343">2. Android application receives a notification</td> <td valign="top" width="245">3. Android notification tray preview</td></tr> <tr> <td valign="top" width="133"><a href="http://lh3.ggpht.com/-uyu-_5H7r7w/Ud7rg7ZJuCI/AAAAAAAAAYg/pg-w4f0O6n8/s1600-h/Send-013.png"><img title="Send 01" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="Send 01" src="http://lh6.ggpht.com/-nPTrVoO6jZs/Ud7rhYouoCI/AAAAAAAAAYo/D1YBAz3E24s/Send-01_thumb1.png?imgmax=800" width="314" height="111"></a></td> <td valign="top" width="343"><a href="http://lh4.ggpht.com/-dISGoyUyu50/Ud7rhr-TXtI/AAAAAAAAAYw/x-_yREJqKTg/s1600-h/Screenshot_2013-07-11-18-46-072.png"><img title="Screenshot_2013-07-11-18-46-07" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="Screenshot_2013-07-11-18-46-07" src="http://lh3.ggpht.com/-7MxcY2IBawI/Ud7ria8P1uI/AAAAAAAAAY4/lPfRrmyDLP4/Screenshot_2013-07-11-18-46-07_thumb.png?imgmax=800" width="148" height="244"></a></td> <td valign="top" width="245"><a href="http://lh6.ggpht.com/-IDkj-J4_hgo/Ud7ri3GgP8I/AAAAAAAAAZA/gXQ_06-47VE/s1600-h/Screenshot_2013-07-11-18-46-282.png"><img title="Screenshot_2013-07-11-18-46-28" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="Screenshot_2013-07-11-18-46-28" src="http://lh6.ggpht.com/-_GyBFetE4ZU/Ud7rjWqOhwI/AAAAAAAAAZE/U4_TrY5ImME/Screenshot_2013-07-11-18-46-28_thumb.png?imgmax=800" width="148" height="244"></a></td></tr></tbody></table></p> <p> </p> <h2>Implementation</h2> <p>The first part of Android application would be the communication to backend server that we developed before by using Google App Engine. This communication is done in asynchronous way and for this reason <em>AsyncTask</em> class has been extended. <em>GAEClient</em> is in charge of handling HTTP requests. There is only single method implementation (<em>storeRegistrationId)</em> that is called once the device token is received and needs to be stored on the server.</p> <div style="color: black; background-color: white"><pre><span style="color: blue">public</span> <span style="color: blue">class</span> GAEClient <span style="color: blue">extends</span> AsyncTask<Object, Void, String> {<br /> <span style="color: green">// TODO: Change URL to Google App Engine application URL</span><br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> String URL = <span style="color: #a31515">"http://<APP_NAME>.appspot.com/"</span>;<br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> String POST_ID_PARAM = <span style="color: #a31515">"txtRegId"</span>;<br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> String POST_MSG_PARAM = <span style="color: #a31515">"txtInput"</span>;<br /> <span style="color: blue">private</span> String res;<br /><br /> @Override<br /> <span style="color: green">// Checks HTTP page requests</span><br /> <span style="color: blue">protected</span> String doInBackground(Object... objects) {<br /> String action = (String)objects[0];<br /> <span style="color: blue">if</span>(action.contains(<span style="color: #a31515">"storeid"</span>))<br /> {<br /> String param = (String) objects[1];<br /> <span style="color: blue">return</span> storeRegistrationId(param);<br /> }<span style="color: blue">else</span>{<br /> <span style="color: blue">return</span> <span style="color: blue">null</span>;<br /> }<br /> }<br /><br /> <span style="color: green">// Stores device token on the backend server</span><br /> <span style="color: blue">public</span> String storeRegistrationId(String id){<br /> String result = <span style="color: blue">null</span>;<br /> <span style="color: blue">try</span>{<br /> DefaultHttpClient client = <span style="color: blue">new</span> DefaultHttpClient();<br /> HttpPost request = <span style="color: blue">new</span> HttpPost(URL+<span style="color: #a31515">"storeid"</span>);<br /> request.setHeader(<span style="color: #a31515">"Content-type"</span>, <span style="color: #a31515">"application/x-www-form-urlencoded"</span>);<br /> List<NameValuePair> nameValuePairs = <span style="color: blue">new</span> ArrayList<NameValuePair>(2);<br /> nameValuePairs.add(<span style="color: blue">new</span> BasicNameValuePair(POST_ID_PARAM, id));<br /> request.setEntity(<span style="color: blue">new</span> UrlEncodedFormEntity(nameValuePairs));<br /> HttpResponse response = client.execute(request);<br /> result = String.valueOf(response.getStatusLine().getStatusCode());<br /> <span style="color: blue">return</span> result;<br /> }<span style="color: blue">catch</span>(Exception e){<br /> e.printStackTrace();<br /> <span style="color: blue">return</span> <span style="color: #a31515">"400"</span>;<br /> }<br /> }<br /><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> onPostExecute(String result) {<br /> res = result;<br /> }<br />}<br /></pre></div><br /><p> </p><br /><p>The second part is <em>GCMIntentService. </em>This class is in charge of receiving a notification from the GCM and dispatching its message via broadcast to all Activities that will receive this message if they have broadcast listener implemented. In this simple demo, with single activity, only <em>MainActivity</em> will receive a message.</p><br /><div style="color: black; background-color: white"><pre><span style="color: blue">public</span> <span style="color: blue">class</span> GCMIntentService <span style="color: blue">extends</span> GCMBaseIntentService {<br /><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> onMessage(Context context, Intent intent) {<br /> String message = intent.getStringExtra(<span style="color: #a31515">"message"</span>);<br /> <span style="color: blue">if</span>(message!=<span style="color: blue">null</span>){<br /> Intent i = <span style="color: blue">new</span> Intent();<br /> i.setAction(<span style="color: #a31515">"GCM_RECEIVED_ACTION"</span>);<br /> i.putExtra(<span style="color: #a31515">"gcm"</span>, message);<br /> context.sendBroadcast(i);<br /> }<br /> }<br /><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">boolean</span> onRecoverableError(Context context, String errorId) {<br /> <span style="color: blue">return</span> <span style="color: blue">super</span>.onRecoverableError(context, errorId); <span style="color: green">//To change body of overridden methods use File | Settings | File Templates.</span><br /> }<br /><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> onError(Context context, String s) {<br /> <span style="color: green">//To change body of implemented methods use File | Settings | File Templates.</span><br /> }<br /><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> onRegistered(Context context, String s) {<br /> <span style="color: green">//To change body of implemented methods use File | Settings | File Templates.</span><br /> }<br /><br /> @Override<br /> <span style="color: blue">protected</span> <span style="color: blue">void</span> onUnregistered(Context context, String s) {<br /> <span style="color: green">//To change body of implemented methods use File | Settings | File Templates.</span><br /> }<br />}<br /></pre></div><br /><p> </p><br /><p>Once the Activity receives a message, the following step is to preview a message. They are few ways to display a notification, but the most common way is to use notification drawer (i.e. notification tray). <em>NotificationDrawerMng </em>builds notification for notification drawer preview.</p><br /><div style="color: black; background-color: white"><pre><span style="color: blue">public</span> <span style="color: blue">class</span> NotificationDrawerMng{<br /><br /> <span style="color: blue">public</span> <span style="color: blue">static</span> Notification createNotification(Context context, String title, String message) {<br /> <span style="color: green">// Prepare intent for notification display in</span><br /> <span style="color: green">// the notification tray</span><br /> Intent intent = <span style="color: blue">new</span> Intent();<br /> intent.putExtra(<span style="color: #a31515">"message"</span>,message);<br /> intent.putExtra(<span style="color: #a31515">"title"</span>,title);<br /> <span style="color: blue">int</span> requestID = (<span style="color: blue">int</span>) System.currentTimeMillis();<br /> PendingIntent pIntent = PendingIntent.getActivity(context, requestID, intent, 0);<br /><br /> <span style="color: green">// Build notification for tray display</span><br /> Notification notification = <span style="color: blue">new</span> Notification.Builder(context)<br /> .setContentTitle(title)<br /> .setContentText(message)<br /> .setSmallIcon(R.drawable.ic_launcher)<br /> .setContentIntent(pIntent)<br /> .build();<br /> <span style="color: blue">return</span> notification;<br /> }<br />}<br /></pre></div><br /><p> </p><br /><p>In the broadcast listener, in the <em>MainActivity,</em> notification will be actually set inside the notification tray.</p><br /><div style="color: black; background-color: white"><pre>BroadcastReceiver gcmReceiver = <span style="color: blue">new</span> BroadcastReceiver() {<br /> <span style="color: green">// Broadcast listener that receives a dispatched notification previously received</span><br /> <span style="color: green">// from GCMIntentService</span><br /> @Override<br /> <span style="color: blue">public</span> <span style="color: blue">void</span> onReceive(Context context, Intent intent) {<br /> broadcastMessage = intent.getExtras().getString(<span style="color: #a31515">"gcm"</span>);<br /><br /> <span style="color: blue">if</span> (broadcastMessage != <span style="color: blue">null</span>) {<br /> Toast.makeText(getApplicationContext(), broadcastMessage, Toast.LENGTH_LONG).show();<br /> Notification notification = NotificationDrawerMng.createNotification(getApplicationContext(), <span style="color: #a31515">"GCMAndroidDemo"</span>, broadcastMessage);<br /> NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);<br /><br /> notification.flags = notification.flags | Notification.FLAG_AUTO_CANCEL;<br /> notificationManager.notify(0, notification);<br /> }<br /> }<br />};<br /></pre></div><br /><p>The last step is to add additional permissions in <em>AndroidManifest </em>for using GCM. Although we are using GCM don’t get confused since C2DM remained a configuration tag.</p><br /><div style="color: black; background-color: white"><pre><span style="color: blue"><?</span><span style="color: #a31515">xml</span> <span style="color: red">version</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">1.0</span><span style="color: black">"</span> <span style="color: red">encoding</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">utf-8</span><span style="color: black">"</span><span style="color: blue">?></span><br /><span style="color: blue"><</span><span style="color: #a31515">manifest</span> <span style="color: red">xmlns:android</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">http://schemas.android.com/apk/res/android</span><span style="color: black">"</span><br /> <span style="color: red">package</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.gcmdemo.GCMAndroidDemo</span><span style="color: black">"</span><br /> <span style="color: red">android:versionCode</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">1</span><span style="color: black">"</span><br /> <span style="color: red">android:versionName</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">1.0</span><span style="color: black">"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-sdk</span> <span style="color: red">android:minSdkVersion</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">14</span><span style="color: black">"</span><span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">android.permission.ACCESS_NETWORK_STATE</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.gcmdemo.GCMAndroidDemo.permission.C2D_MESSAGE</span><span style="color: black">"</span> <span style="color: red">android:protectionLevel</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">signature</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.gcmdemo.GCMAndroidDemo.permission.C2D_MESSAGE</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: green"><!-- App receives GCM messages. --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.google.android.c2dm.permission.RECEIVE</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: green"><!-- GCM connects to Google Services. --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">android.permission.INTERNET</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: green"><!-- GCM requires a Google account. --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">android.permission.GET_ACCOUNTS</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: green"><!-- Keeps the processor from sleeping when a message is received. --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">uses-permission</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">android.permission.WAKE_LOCK</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">application</span> <span style="color: red">android:label</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">@string/app_name</span><span style="color: black">"</span> <span style="color: red">android:icon</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">@drawable/ic_launcher</span><span style="color: black">"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">activity</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">MainActivity</span><span style="color: black">"</span><br /> <span style="color: red">android:label</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">@string/app_name</span><span style="color: black">"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">intent-filter</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">action</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">android.intent.action.MAIN</span><span style="color: black">"</span><span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">category</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">android.intent.category.LAUNCHER</span><span style="color: black">"</span><span style="color: blue">/></span><br /> <span style="color: blue"></</span><span style="color: #a31515">intent-filter</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">activity</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">receiver</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.google.android.gcm.GCMBroadcastReceiver</span><span style="color: black">"</span> <span style="color: red">android:permission</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.google.android.c2dm.permission.SEND</span><span style="color: black">"</span> <span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">intent-filter</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">action</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.google.android.c2dm.intent.RECEIVE</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">action</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.google.android.c2dm.intent.REGISTRATION</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"><</span><span style="color: #a31515">category</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.gcmdemo.GCMAndroidDemo</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"></</span><span style="color: #a31515">intent-filter</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">receiver</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">service</span> <span style="color: red">android:name</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">com.gcmdemo.GCMIntentService</span><span style="color: black">"</span> <span style="color: blue">/></span><br /> <span style="color: blue"></</span><span style="color: #a31515">application</span><span style="color: blue">></span><br /><span style="color: blue"></</span><span style="color: #a31515">manifest</span><span style="color: blue">></span><br /></pre></div> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com3tag:blogger.com,1999:blog-209337246847216621.post-41415902030092557562013-07-03T20:33:00.000+02:002013-07-11T19:28:18.267+02:00Push Notification Services with Android, GCM and Google App Engine (Part 1)<p> </p> <p> </p> <h2>Introduction</h2> <p>In this blog I’ll demonstrate a solution for implementing push notification services for Android applications. It will leverage on the existing technologies that Google provides for the developers: Android platform, Google Cloud Messaging (GCM) and Google App Engine. </p> <p>As you are probably already familiar, GCM is push notification service for Android platform that delivers notifications to your phone. Notifications are commonly used for notifying user about installed application updates or important status updates, for example, the Twitter application that notifies you about re-tweets. It is important to mention that push notification services (PNS) should be used with precaution since there are intended only to notify user about crucial things at the current moment. For example, if a user bids on an auction on the eBay, he/she should be notified if someone places bigger bid. Also, notifications should not be used if the messages will come too frequently. Too frequent notifications will annoy user and he/she will probably uninstall your app. PNSs are also not intended for delivering any confidential content since they don’t support encryption and they should not be used for these purposes. Instead, make sure you meet requirements as frequency, importance and sending it in a relevant time.</p> <h2>Architectural overview</h2> <p>First let’s get familiar with GCM, in order to better understand how our solutions will look like in the very end.<br>GCM system consists of three components:</p> <ul> <li>Client (Android application) <li>Backend server (Google App Engine backend) <li>GCM service</li></ul> <p>GCM provides us services for sending notifications to the Android smart phones. These notifications are messages that are constructed and sent to GCM by <em>backend server</em> who initiates notification sending (in Figure01 step <strong>a</strong>), i.e. <em>backend server</em> behaves as notification trigger. <em>Backend server</em> also stores all <em>registration_ids</em> of every subscriber (phone with installed application) and with these information server knows which group of subscribers it wants to target (in Figure01 step <strong>3</strong>). Mobile app simply asks GCM for <em>registration_id</em> and connects to push service in order to receive notifications (in Figure01 step <strong>1</strong>). It can also send <em>registration_id</em> delivered by GCM to the backend server (in Figure01 step <strong>3</strong>).<br>For using GCM notification system several credentials need to be used:</p> <ul> <li><strong>sender_id</strong> - project number that uniquely identifies the project in Google Application Console, <li><strong>application_id</strong> - identifies the application and it’s necessary to be used for receiving messages, <li><strong>registration_id</strong> - identifies device with the installed app and it’s also necessary to be used for receiving messages. Device receives it from GCM service during connection process. <li><strong>sender_auth_token</strong> - or API_KEY that is used on a server side in order to use GCM services <li><strong>google_user_account</strong> - for Android versions lower than 4.0, Google account needs to be used.</li></ul> <p align="center"><a href="http://lh6.ggpht.com/-5mlBmC5IUNA/Ud7rJTmyumI/AAAAAAAAAWQ/pS59IVCsEWo/s1600-h/GCM19.png"><img title="GCM" style="display: inline" alt="GCM" src="http://lh5.ggpht.com/-45hQvc7ppwc/Ud7rJ93TUuI/AAAAAAAAAWY/AUYS_J0mePE/GCM_thumb15.png?imgmax=800" width="452" height="254"></a></p> <p align="center"><font size="1">Figure01 – GCM notification cycle</font></p> <p>The complete process of notification sending can be explained with the following steps (see Figure01):</p> <ul> <li>enabling GCM: <ol> <li>(1) device is sending a request to the GCM. The request contains sender_id and app_id. <li>(2) GCM sends response containing app_id and registration_id. <li>(3) mobile app sends received registration_id to backend server, which stores the id</li></ol> <li>sending a message: <ol> <li>(‘a’) backend server with defined API_KEY sends a message content with a set of registration_ids of device it wants to target <li>(‘b’) GCM receives the message from server and broadcasts it to the devices </li></ol> <li>receiving a message (on a device) <ol> <li>mobile app receives the notification, extracts it and processes data <li>displays message content<br></li></ol></li></ul> <h2>Generating credentials</h2> <p>Now we’ll go through steps of how to generate mentioned credentials that we’ll later use in our implementation.</p> <p>Step 01: Go to <a href="http://code.google.com/apis/console‎">Google API Console</a> web site and log in with your Gmail account.</p> <p><a href="http://lh3.ggpht.com/-j6hh0PHcn9A/Ud7rKVa_-9I/AAAAAAAAAWg/BgFr4-3wDsw/s1600-h/Google-Api-Console6.png"><img title="Google Api Console" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="Google Api Console" src="http://lh3.ggpht.com/-KgpQdbf7Rgo/Ud7rLO2clLI/AAAAAAAAAWk/kkj7PWRJaKI/Google-Api-Console_thumb2.png?imgmax=800" width="244" height="221"></a></p> <p align="center"><font size="1">Figure02 – Google API Console start page</font></p> <p align="justify">Step 02: Create project…</p> <p align="justify">Step 03: Enter project name and continue</p> <p align="justify">Step 04: In the left navigation menu go to <em>Services </em>and enable <em>Google Cloud Messaging for Android</em></p> <p align="center"><a href="http://lh3.ggpht.com/-dc3Yy0qta-E/Ud7rLS5zuwI/AAAAAAAAAWw/ILC_FhQ1RLc/s1600-h/GCMEnable3.png"><img title="GCMEnable" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="GCMEnable" src="http://lh4.ggpht.com/-aCHdcnWHHL8/Ud7rMLKxzMI/AAAAAAAAAW4/hWE50AXQWy0/GCMEnable_thumb1.png?imgmax=800" width="560" height="90"></a></p> <p align="center"><font size="1">Figure03 – Turn on GCM for Android</font></p> <p align="justify">Step 05: In the same menu go to <em>API Access. </em>Now you need to create a server key. Click on <em>Create New Server Key… </em>and for this case leave IPs field empty and follow with <em>create</em> (no IP address needs to be specified if you want to be in public domain).</p> <p align="justify">Step 06: In the same menu go to <em>Overview.</em></p> <p align="justify">So far we generated following credentials:</p> <ul> <li> <div align="justify"><strong>sender_id: </strong>in the <em>Overview </em>you can see <em>Project Number </em>and that is your sender_id <u>(will be used in Android application)</u></div> <li> <div align="justify"><strong>application_id:</strong> as explained before will be received from the GCM when the mobile connects to the GCM</div> <li> <div align="justify"><strong>registration_id: </strong>as explained before will be received from the GCM when the mobile connects to the GCM</div> <li> <div align="justify"><strong>sender_auth_token: </strong>in the <em>API Access </em>you can see under <em>Key for server apps (with IP locking) </em>the <em>API key </em>which is your sender authentication token <u>(will be used in Google App Engine web application)</u></div> <li> <div align="justify"><strong>google_user_account:</strong> is not necessary since in this tutorial will develop Android 4.0 application</div></li></ul> <p>Now we are ready to implement our notification system. Follow this next blog.</p> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com4tag:blogger.com,1999:blog-209337246847216621.post-5554588745837445632013-03-05T14:46:00.001+01:002013-04-15T20:30:37.451+02:00Build cross platform mobile application with jQ.Mobi and PhoneGap<blockquote></blockquote> <p> </p> <h2>Introduction</h2> <p>In this blog post we’ll learn how to build a mobile application for multiple platforms by using JavaScript library called <a href="http://www.jqmobi.com/" target="_blank">jQ.Mobi</a> and <a href="http://phonegap.com/" target="_blank">PhoneGap</a> cloud build service.</p> <p>In the first part, there will be shown steps of building a “Hello, world” mobile application in HTML5/JavaScript/CSS3. This will be done by using free jQ.Mobi library that allow us to build application with native look&feel of the specific platforms in very easy way.</p> <p>The second part will describe how to use PhoneGap cloud build service which allow us to build our previous “Hello, world” project for multiple platforms. What this service is providing, is it will build executable install files for each of the platforms: iOS, Android, WP, Blackberry, HP and Symbian.</p> <h2>Part 01 – “Hello, world”</h2> <p>Firstly, download jQ.Mobi library from <a href="https://github.com/01org/appframework/" target="_blank">GitHub link</a> just by clicking ZIP button. After download finishes, extract the archive.</p> <p>Now create a separate folder for your new “Hello, world” project. Inside the directory create another directory named “www”. Copy<em> plugins</em>, <em>kitchensink</em> and <em>ui</em> folders from extracted jQ.Mobi folder. Also, copy <em>jq.mobi.js</em> and <em>jq.mobi.min.js. </em>In the “www” folder, create <em>index.html </em>empty file. Now the current folder structure should look like this:</p> <p><a href="http://lh3.ggpht.com/-gHMFi1xvSZE/UTX3JitvppI/AAAAAAAAAPo/CwV8HpfrxHk/s1600-h/directory%252520structure%25255B3%25255D.jpg"><img title="directory structure" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="directory structure" src="http://lh5.ggpht.com/-IKyUwC6m5v0/UTX3KUxa3jI/AAAAAAAAAPw/zYwhAZXzPZk/directory%252520structure_thumb%25255B1%25255D.jpg?imgmax=800" width="547" height="246"></a></p> <p align="center"><font size="1">Picture 01 – Project directory structure</font></p> <p>Now we’ll edit our <em>index.html </em>file with the following code:</p> <div style="color: black; background-color: white"><pre><span style="color: blue"><!</span><span style="color: #a31515">DOCTYPE</span> <span style="color: red">html</span><span style="color: blue">></span><br /><span style="color: green"><!--HTML5 doctype--></span><br /><span style="color: blue"><</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /> <br /> <span style="color: blue"><</span><span style="color: #a31515">head</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">title</span><span style="color: blue">></span>jqUi Starter<span style="color: blue"></</span><span style="color: #a31515">title</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">meta</span> <span style="color: red">http-equiv</span><span style="color: blue">=</span><span style="color: blue">"Content-type"</span> <span style="color: red">content</span><span style="color: blue">=</span><span style="color: blue">"text/html; charset=utf-8"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">meta</span> <span style="color: red">name</span><span style="color: blue">=</span><span style="color: blue">"viewport"</span> <span style="color: red">content</span><span style="color: blue">=</span><span style="color: blue">"width=device-width, initial-scale=1, maximum-scale=1"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">meta</span> <span style="color: red">name</span><span style="color: blue">=</span><span style="color: blue">"apple-mobile-web-app-capable"</span> <span style="color: red">content</span><span style="color: blue">=</span><span style="color: blue">"yes"</span> <span style="color: blue">/></span><br /> <br /> <span style="color: blue"><</span><span style="color: #a31515">link</span> <span style="color: red">rel</span><span style="color: blue">=</span><span style="color: blue">"stylesheet"</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"text/css"</span> <span style="color: red">href</span><span style="color: blue">=</span><span style="color: blue">"kitchensink/icons.css"</span> <span style="color: blue">/></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">link</span> <span style="color: red">rel</span><span style="color: blue">=</span><span style="color: blue">"stylesheet"</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"text/css"</span> <span style="color: red">href</span><span style="color: blue">=</span><span style="color: blue">"kitchensink/jq.ui.css"</span> <span style="color: red">title</span><span style="color: blue">=</span><span style="color: blue">"volcano"</span><span style="color: blue">/></span><br /> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"text/javascript"</span> <span style="color: red">charset</span><span style="color: blue">=</span><span style="color: blue">"utf-8"</span> <span style="color: red">src</span><span style="color: blue">=</span><span style="color: blue">"ui/jq.ui.min.js"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span><br /><br /> <span style="color: blue"><</span><span style="color: #a31515">script</span><span style="color: blue">></span><br /> <span style="color: blue">if</span> (!((window.DocumentTouch && document <span style="color: blue">instanceof</span> DocumentTouch) || <span style="color: #a31515">'ontouchstart'</span> <span style="color: blue">in</span> window)) {<br /> $.os.android = <span style="color: blue">true</span>; <span style="color: green">//let's make it run like an android device</span><br /> }<br /> <br /> <span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">script</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"text/javascript"</span><span style="color: blue">></span><br /> <br /> <span style="color: blue">var</span> webRoot = <span style="color: #a31515">"./"</span>;<br /> $.ui.backButtonText = <span style="color: #a31515">"Back"</span>;<span style="color: green">// We override the back button text to always say "Back"</span><br /> <span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">head</span><span style="color: blue">></span><br /> <br /> <span style="color: blue"><</span><span style="color: #a31515">body</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"jQUi"</span><span style="color: blue">></span> <span style="color: green"><!-- this is the main container div. This way, you can have only part of your app use jqUi --></span><br /> <span style="color: green"><!-- this is the header div at the top --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"header"</span><span style="color: blue">></span><br /> <br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"content"</span><span style="color: blue">></span><br /> <span style="color: green"><!-- here is where you can add your panels --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">title</span><span style="color: blue">=</span><span style="color: blue">'Welcome'</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"main"</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">"panel"</span><span style="color: blue">></span>This is a "Hello, world" sample.<span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">title</span><span style="color: blue">=</span><span style="color: blue">"Targeting platforms"</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"jqmweb"</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">"panel"</span> <span style="color: red">data-header</span><span style="color: blue">=</span><span style="color: blue">"testheader"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">h2</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">'expanded'</span> <span style="color: red">onclick</span><span style="color: blue">=</span><span style="color: blue">'showHide(this,"jqweb_info");'</span><span style="color: blue">></span>Platforms<span style="color: blue"></</span><span style="color: #a31515">h2</span><span style="color: blue">></span><span style="color: blue"><</span><span style="color: #a31515">p</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">'jqweb_info'</span><span style="color: blue">></span><br /> We wish to support following platforms:<span style="color: blue"></</span><span style="color: #a31515">p</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">ul</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">li</span><span style="color: blue">></span>iOS<span style="color: blue"></</span><span style="color: #a31515">li</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">li</span><span style="color: blue">></span>Android<span style="color: blue"></</span><span style="color: #a31515">li</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">li</span><span style="color: blue">></span>Windows Phone<span style="color: blue"></</span><span style="color: #a31515">li</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">li</span><span style="color: blue">></span>Blackberry<span style="color: blue"></</span><span style="color: #a31515">li</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">li</span><span style="color: blue">></span>HP<span style="color: blue"></</span><span style="color: #a31515">li</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">li</span><span style="color: blue">></span>Symbian<span style="color: blue"></</span><span style="color: #a31515">li</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">ul</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">br</span><span style="color: blue">/></span><span style="color: blue"><</span><span style="color: #a31515">br</span><span style="color: blue">/></span><br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: green"><!-- bottom navbar. Add additional tabs here --></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"navbar"</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">"horzRule"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">a</span> <span style="color: red">href</span><span style="color: blue">=</span><span style="color: blue">"#main"</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">'navbar_home'</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">'icon home'</span><span style="color: blue">></span>home<span style="color: blue"></</span><span style="color: #a31515">a</span><span style="color: blue">></span><br /> <span style="color: blue"><</span><span style="color: #a31515">a</span> <span style="color: red">href</span><span style="color: blue">=</span><span style="color: blue">"#jqmweb"</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">'navbar_target'</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">'icon target'</span><span style="color: blue">></span>target<span style="color: blue"></</span><span style="color: #a31515">a</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">body</span><span style="color: blue">></span><br /><span style="color: blue"></</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /></pre></div><br /><p> </p><br /><p>In the <em>head </em>tag you can see we referenced JavaScript files and CSS from the jQ.Mobi library. There is additional initialization JavaScript that runs first time the app starts. In the <em>body </em>part there are two divs that are loaded depending on button click from the navigation bar (“navbar”). First div with <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"main" </span>is the main page, while other div with <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"jqmweb" </span>represents the second page with list of items.</p><br /><p><strong>TIP</strong>: If you want to use Visual Studio for easy project editing, simply go File>Open>Web Site and browse to your project folder.</p><br /><p>Now you can test <em>index.html</em> page preview in browser. After you navigate with “home” and “target” buttons you should see slide animation.</p><br /><table cellspacing="0" cellpadding="2" width="400" border="0"><br /><tbody><br /><tr><br /><td valign="top" width="200"><br /><p align="center"><a href="http://lh4.ggpht.com/-rIYerji1T8Q/UTX3LA-ShTI/AAAAAAAAAP4/lysWI_JtH30/s1600-h/mainpage%25255B4%25255D.jpg"><img title="mainpage" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="mainpage" src="http://lh5.ggpht.com/-wmU-RKy7jKg/UTX3L7NkM6I/AAAAAAAAAP8/d94ER4_ONK0/mainpage_thumb%25255B2%25255D.jpg?imgmax=800" width="378" height="230"></a></p></td><br /><td valign="top" width="200"><br /><p align="center"><a href="http://lh4.ggpht.com/-p_6IXaQWW6k/UTX3MWBhs1I/AAAAAAAAAQI/YhwSK2qiYwI/s1600-h/targetpage%25255B4%25255D.jpg"><img title="targetpage" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="targetpage" src="http://lh6.ggpht.com/-qm9j4neDaM0/UTX3NOxMlKI/AAAAAAAAAQQ/lcM0HgyhDYg/targetpage_thumb%25255B2%25255D.jpg?imgmax=800" width="383" height="231"></a></p></td></tr><br /><tr><br /><td valign="top" width="200"><br /><p align="center">Picture 02 – Main page</p></td><br /><td valign="top" width="200"><br /><p align="center">Picture 03 – Target page</p></td></tr></tbody></table><br /><p>Now when your “Hello, world” app is done, zip the entire folder to .zip archive.</p><br /><h2>Part 02 – PhoneGap build service</h2><br /><p>With your browser go to <a title="https://build.phonegap.com/" href="https://build.phonegap.com/">https://build.phonegap.com/</a>. Login with your Adobe account or GitHub account. If you don’t have account you can go to the <a href="https://github.com/" target="_blank">GitHub official web site</a> and register for a free account. After you have been logged in: </p><br /><p>1. Click on <em><strong>New App</strong></em> button.</p><br /><p><a href="http://lh3.ggpht.com/-s3C7w0-ymfY/UTX3Nx9CpvI/AAAAAAAAAQY/Be2ynXwpHlI/s1600-h/phonegap-build01%25255B3%25255D.jpg"><img title="phonegap-build01" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="phonegap-build01" src="http://lh6.ggpht.com/-BL7_HUnIXOk/UTX3OsoOm1I/AAAAAAAAAQg/8-A2UQ0rGi8/phonegap-build01_thumb%25255B1%25255D.jpg?imgmax=800" width="536" height="108"></a></p><br /><p>2. Select <strong><em>Private</em></strong> tab, click <strong><em>Upload a .zip file</em></strong>, browse to your zip project archive and click <strong><em>Ready to build</em></strong>.</p><br /><p><a href="http://lh4.ggpht.com/-ufr_gvfwx44/UTX3PXXFJMI/AAAAAAAAAQo/P1ITif-bGvQ/s1600-h/phonegap-build02%25255B3%25255D.jpg"><img title="phonegap-build02" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="phonegap-build02" src="http://lh5.ggpht.com/-xFe_Tlw72AM/UTX3QAivinI/AAAAAAAAAQw/0ivdHS6RRjY/phonegap-build02_thumb%25255B1%25255D.jpg?imgmax=800" width="541" height="232"></a></p><br /><p><strong>TIP: </strong>For a free use you can only upload 1 zip archive, but instead, you could use GitHub repository and build your application directly from there.</p><br /><p>3. After your build is finished you can download executable files for these platforms:</p><br /><p><a href="http://lh3.ggpht.com/-iGMOa9VkHXw/UTX3QoA7qGI/AAAAAAAAAQ4/9pSa-CDOSJw/s1600-h/PGBuildApp%25255B3%25255D.jpg"><img title="PGBuildApp" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="PGBuildApp" src="http://lh6.ggpht.com/-6DKiyAE3Uao/UTX3RUI3-yI/AAAAAAAAAQ8/_a8d7cji87E/PGBuildApp_thumb%25255B1%25255D.jpg?imgmax=800" width="544" height="252"></a></p><br /><p><strong>TIP: </strong>For the iOS case you’ll first need to upload application certificate and build afterwards.</p> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com13tag:blogger.com,1999:blog-209337246847216621.post-82398920021898784072013-02-25T14:56:00.001+01:002013-07-02T14:04:59.577+02:00Android with WCF web services<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<h2>
Introduction</h2>
This post will briefly describe how to implement WCF web service client side in an Android application. For this purpose, simple “ToDo” Android application will be used for demonstration. The complete source code can be downloaded from <a href="https://dl.dropboxusercontent.com/u/45556593/ToDoDemoApplication.zip" target="_blank">here</a>.<br />
The easiest way to do this is by using WCF Rest services that will send information in JSON or XML format. If you would like to use SOAP base services, then you would need to use some 3rd party libraries for Android like <a href="http://ksoap2.sourceforge.net/">kSOAP</a>. <br />
<h2>
Implementing WCF web service</h2>
In this post, we’ll use Azure project approach to implement web service, but any other approach will serve the purpose also. <br />
The first step is to create new Azure Cloud Service project. If you don’t have Azure SDK installed, you can download it from <a href="http://www.windowsazure.com/en-us/downloads/">Azure web site</a>. In .NET section you’ll find installs both for VS2012 and VS2010. <br />
In Visual Studio, go<em> File > New Project</em> and under the <em>Cloud</em> category choose <em>Windows Azure Cloud Service</em> project. Fill in necessary data, hit <em>Ok </em>and afterwards select <em>WCF Service Web Role</em>. <br />
<table border="0" cellpadding="2" cellspacing="0" style="width: 400px;"> <tbody>
<tr> <td valign="top" width="200"><div align="center">
<a href="http://lh3.ggpht.com/-J-tnjT4I-mI/USttdC6jwsI/AAAAAAAAAPA/pcbWvuqOoZM/s1600-h/NewAzureProj3.jpg"><img alt="NewAzureProj" border="0" height="252" src="http://lh6.ggpht.com/-ED4CZcQdnzg/USttdyT_Q_I/AAAAAAAAAPI/5x5aG4Da47I/NewAzureProj_thumb1.jpg?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="NewAzureProj" width="374" /></a><br /><span style="font-size: xx-small;">Step 01: Select Azure project</span></div>
</td> <td valign="top" width="200"><div align="right">
<a href="http://lh4.ggpht.com/-CyyMuJFmY9E/USttgIUMfvI/AAAAAAAAAPQ/cKTLoit_QJg/s1600-h/AzureRole3.jpg"><img alt="AzureRole" border="0" height="253" src="http://lh6.ggpht.com/-Zeaaf9ElG8Y/USttg1xjcTI/AAAAAAAAAPY/773xvsjxUGc/AzureRole_thumb1.jpg?imgmax=800" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="AzureRole" width="382" /></a><span style="font-size: xx-small;">Step 02: Select WCF Service Role </span></div>
</td></tr>
</tbody></table>
After you created your project, add a new WCF service or refactor default WCF service that has been generated within the project. Replace service interface with the following code:<br />
<div style="background-color: white; color: black;">
<pre><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Collections.Generic;
<span style="color: blue;">using</span> System.Linq;
<span style="color: blue;">using</span> System.Runtime.Serialization;
<span style="color: blue;">using</span> System.ServiceModel;
<span style="color: blue;">using</span> System.ServiceModel.Web;
<span style="color: blue;">using</span> System.Text;
<span style="color: blue;">namespace</span> WCFServiceWebRole1
{
<span style="color: green;">// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IToDoService" in both code and config file together.</span>
[ServiceContract]
<span style="color: blue;">public</span> <span style="color: blue;">interface</span> IToDoService
{
[OperationContract]
[WebInvoke(
Method = <span style="color: #a31515;">"POST"</span>,
UriTemplate = <span style="color: #a31515;">"AddToDoItem"</span>,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
<span style="color: blue;">void</span> AddToDoItem(ToDoItem toDoItem);
[OperationContract]
[WebInvoke(
Method = <span style="color: #a31515;">"GET"</span>,
UriTemplate = <span style="color: #a31515;">"GetToDoItemsByDate?date={date}"</span>,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
List<ToDoItem> GetToDoItemsByDate(String date);
[OperationContract]
[WebGet(
UriTemplate = <span style="color: #a31515;">"GetAllToDoItems"</span>,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
List<ToDoItem> GetAllToDoItems();
}
[DataContract]
<span style="color: blue;">public</span> <span style="color: blue;">class</span> ToDoItem
{
[DataMember(Name = <span style="color: #a31515;">"description"</span>)]
<span style="color: blue;">public</span> String Description { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
[DataMember(Name = <span style="color: #a31515;">"scheduleddate"</span>)]
<span style="color: blue;">public</span> DateTime ScheduledDate { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
}
}
</pre>
</div>
<br />
As you can see we have defined three methods:<br />
<br />
<ol><br />
<li><em>AddToDoItem – </em>will be used for adding a new ToDo item. It will receive a ToDo item in JSON format (RequestFormat), through POST request. </li>
<li><em>GetToDoItemsByDate – </em>will be used to retrieve all ToDo items for specific date. Method receives date as an argument in JSON format, through GET request and retrieves list of ToDo items also in JSON format (ResponseFormat). </li>
<li><em>GetAllToDoItems – </em>will be used to retrieve all ToDo items. The list of items in JSON format will be in response body for GET request.</li>
</ol>
<br />
<em>DataContract </em>represents the ToDo item model and defines the model properties.<br />
<br />
In the next step, we need to implement interface methods:<br />
<br />
<div style="background-color: white; color: black;">
<pre><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Collections.Generic;
<span style="color: blue;">using</span> System.Data;
<span style="color: blue;">using</span> System.Data.SqlClient;
<span style="color: blue;">using</span> System.Globalization;
<span style="color: blue;">using</span> System.Linq;
<span style="color: blue;">using</span> System.Runtime.Serialization;
<span style="color: blue;">using</span> System.ServiceModel;
<span style="color: blue;">using</span> System.ServiceModel.Activation;
<span style="color: blue;">using</span> System.Text;
<span style="color: blue;">namespace</span> WCFServiceWebRole1
{
<span style="color: green;">// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ToDoService" in code, svc and config file together.</span>
<span style="color: green;">// NOTE: In order to launch WCF Test Client for testing this service, please select ToDoService.svc or ToDoService.svc.cs at the Solution Explorer and start debugging.</span>
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
<span style="color: blue;">public</span> <span style="color: blue;">class</span> ToDoService : IToDoService
{
<span style="color: blue;">public</span> <span style="color: blue;">void</span> AddToDoItem(ToDoItem toDoItem)
{
<span style="color: blue;">int</span> id = 0;
<span style="color: blue;">try</span>
{
<span style="color: blue;">using</span> (SqlConnection con = DBConnection.GetConnection())
{
SqlCommand cmd = <span style="color: blue;">new</span> SqlCommand(<span style="color: #a31515;">"InsertToDo"</span>, con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(<span style="color: blue;">new</span> SqlParameter(<span style="color: #a31515;">"@ScheduledDate"</span>, toDoItem.ScheduledDate));
cmd.Parameters.Add(<span style="color: blue;">new</span> SqlParameter(<span style="color: #a31515;">"@Description"</span>, toDoItem.Description));
con.Open();
SqlDataAdapter ad = <span style="color: blue;">new</span> SqlDataAdapter(cmd);
DataSet ds = <span style="color: blue;">new</span> DataSet();
ad.Fill(ds);
DataTable result = ds.Tables[0];
<span style="color: blue;">foreach</span> (DataRow row <span style="color: blue;">in</span> result.Rows)
{
id = Int16.Parse(row[0].ToString());
}
con.Close();
}
}
<span style="color: blue;">catch</span> (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
<span style="color: blue;">public</span> List<ToDoItem> GetAllToDoItems()
{
List<ToDoItem> items = <span style="color: blue;">new</span> List<ToDoItem>();
<span style="color: blue;">using</span> (SqlConnection con = DBConnection.GetConnection())
{
SqlCommand cmd = <span style="color: blue;">new</span> SqlCommand(<span style="color: #a31515;">"GetAllToDoItems"</span>, con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
con.Open();
SqlDataAdapter ad = <span style="color: blue;">new</span> SqlDataAdapter(cmd);
DataSet ds = <span style="color: blue;">new</span> DataSet();
ad.Fill(ds);
DataTable result = ds.Tables[0];
<span style="color: blue;">if</span> (result == <span style="color: blue;">null</span>)
{
<span style="color: blue;">return</span> <span style="color: blue;">null</span>;
}
<span style="color: blue;">else</span>
{
<span style="color: blue;">foreach</span> (DataRow row <span style="color: blue;">in</span> result.Rows)
{
ToDoItem todo = <span style="color: blue;">new</span> ToDoItem();
todo.ScheduledDate = DateTime.Parse(row[1].ToString());
todo.Description = row[2].ToString();
items.Add(todo);
}
}
con.Close();
}
<span style="color: blue;">return</span> items;
}
<span style="color: blue;">public</span> List<ToDoItem> GetToDoItemsByDate(String date)
{
List<ToDoItem> items = <span style="color: blue;">new</span> List<ToDoItem>();
<span style="color: blue;">try</span>
{
<span style="color: blue;">using</span> (SqlConnection con = DBConnection.GetConnection())
{
SqlCommand cmd = <span style="color: blue;">new</span> SqlCommand(<span style="color: #a31515;">"GetToDoItemsByDate"</span>, con);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(<span style="color: blue;">new</span> SqlParameter(<span style="color: #a31515;">"@ScheduledDate"</span>, date));
con.Open();
SqlDataAdapter ad = <span style="color: blue;">new</span> SqlDataAdapter(cmd);
DataSet ds = <span style="color: blue;">new</span> DataSet();
ad.Fill(ds);
DataTable result = ds.Tables[0];
<span style="color: blue;">if</span> (result == <span style="color: blue;">null</span>)
{
<span style="color: blue;">return</span> <span style="color: blue;">null</span>;
}
<span style="color: blue;">else</span>
{
<span style="color: blue;">foreach</span> (DataRow row <span style="color: blue;">in</span> result.Rows)
{
ToDoItem todo = <span style="color: blue;">new</span> ToDoItem();
todo.ScheduledDate = DateTime.Parse(row[1].ToString());
todo.Description = row[2].ToString();
items.Add(todo);
}
}
con.Close();
}
}
<span style="color: blue;">catch</span> (Exception e)
{
Console.WriteLine(e.StackTrace);
}
<span style="color: blue;">return</span> items;
}
}
}
</pre>
</div>
<br />
The concrete implementation contains only SQL stored procedure calls. With these stored procedures, data are stored in and retrieved from MSSQL database. Also, <em>DBConnection</em> class defines DB connection and connection string and it looks like this:<br />
<br />
<br />
<br />
<div style="background-color: white; color: black;">
<pre><span style="color: blue;">using</span> System;
<span style="color: blue;">using</span> System.Collections.Generic;
<span style="color: blue;">using</span> System.Data.SqlClient;
<span style="color: blue;">using</span> System.Linq;
<span style="color: blue;">using</span> System.Web;
<span style="color: blue;">namespace</span> WCFServiceWebRole1
{
<span style="color: blue;">public</span> <span style="color: blue;">class</span> DBConnection
{
<span style="color: blue;">private</span> <span style="color: blue;">static</span> String connectionString = <span style="color: #a31515;">"user id=<USERNAME>;"</span> +
<span style="color: #a31515;">@"password=<PASSWORD>;server=<YOUR_HOST>\<MSSQLSERVER>;"</span> +
<span style="color: #a31515;">"Trusted_Connection=yes;"</span> +
<span style="color: #a31515;">"database=ToDoDB; "</span> +
<span style="color: #a31515;">"connection timeout=30"</span>;
<span style="color: blue;">private</span> <span style="color: blue;">static</span> SqlConnection con = <span style="color: blue;">null</span>;
<span style="color: blue;">public</span> <span style="color: blue;">static</span> SqlConnection GetConnection()
{
con = <span style="color: blue;">new</span> SqlConnection(connectionString);
<span style="color: blue;">return</span> con;
}
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> CloseConnection()
{
<span style="color: blue;">if</span> (con != <span style="color: blue;">null</span>)
con.Close();
}
<span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: blue;">void</span> OpenConnection()
{
<span style="color: blue;">if</span> (con != <span style="color: blue;">null</span>)
con.Open();
}
}
}</pre>
</div>
<br />
The last thing concerning WCF service implementation is configuration within <em>WebConfig</em> file in your project. Under <system.serviceModel>, in your config file, you’ll need to make the following changes:<br />
<br />
<div style="background-color: white; color: black;">
<pre> <span style="color: blue;"><</span><span style="color: #a31515;">system.serviceModel</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">behaviors</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">endpointBehaviors</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">behavior</span> <span style="color: red;">name</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">httpBehavior</span><span style="color: black;">"</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">dataContractSerializer</span> <span style="color: red;">maxItemsInObjectGraph</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">10000000</span><span style="color: black;">"</span><span style="color: blue;">/></span>
<span style="color: blue;"><</span><span style="color: #a31515;">webHttp</span><span style="color: blue;">/></span>
<span style="color: blue;"></</span><span style="color: #a31515;">behavior</span><span style="color: blue;">></span>
<span style="color: blue;"></</span><span style="color: #a31515;">endpointBehaviors</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">serviceBehaviors</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">behavior</span><span style="color: blue;">></span>
<span style="color: green;"><!-- To avoid disclosing metadata information, set the value below to false before deployment --></span>
<span style="color: blue;"><</span><span style="color: #a31515;">serviceMetadata</span> <span style="color: red;">httpGetEnabled</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">true</span><span style="color: black;">"</span><span style="color: blue;">/></span>
<span style="color: green;"><!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --></span>
<span style="color: blue;"><</span><span style="color: #a31515;">serviceDebug</span> <span style="color: red;">includeExceptionDetailInFaults</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">false</span><span style="color: black;">"</span><span style="color: blue;">/></span>
<span style="color: blue;"></</span><span style="color: #a31515;">behavior</span><span style="color: blue;">></span>
<span style="color: blue;"></</span><span style="color: #a31515;">serviceBehaviors</span><span style="color: blue;">></span>
<span style="color: blue;"></</span><span style="color: #a31515;">behaviors</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">serviceHostingEnvironment</span> <span style="color: red;">multipleSiteBindingsEnabled</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">true</span><span style="color: black;">"</span> <span style="color: red;">aspNetCompatibilityEnabled</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">true</span><span style="color: black;">"</span> <span style="color: blue;">/></span>
<span style="color: blue;"><</span><span style="color: #a31515;">services</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">service</span> <span style="color: red;">name</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">WCFServiceWebRole1.ToDoService</span><span style="color: black;">"</span><span style="color: blue;">></span>
<span style="color: blue;"><</span><span style="color: #a31515;">endpoint</span> <span style="color: red;">address</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">web</span><span style="color: black;">"</span>
<span style="color: red;">behaviorConfiguration</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">httpBehavior</span><span style="color: black;">"</span>
<span style="color: red;">binding</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">webHttpBinding</span><span style="color: black;">"</span>
<span style="color: red;">contract</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">WCFServiceWebRole1.IToDoService</span><span style="color: black;">"</span> <span style="color: blue;">/></span>
<endpoint address=""
binding="basicHttpBinding"
contract="WCFServiceWebRole1.IToDoService" />
<span style="color: blue;"></</span><span style="color: #a31515;">service</span><span style="color: blue;">></span>
<span style="color: blue;"></</span><span style="color: #a31515;">services</span><span style="color: blue;">></span>
<span style="color: blue;"></</span><span style="color: #a31515;">system.serviceModel</span><span style="color: blue;">></span></pre>
</div>
<br />
<br />
<br />
Notice, that you’ll need to add <span style="color: blue;"><</span><span style="color: #a31515;">behavior</span> <span style="color: red;">name</span><span style="color: blue;">=</span><span style="color: black;">"</span><span style="color: blue;">httpBehavior</span><span style="color: black;">"</span><span style="color: blue;">> </span>and service endpoints under <span style="color: blue;"><span style="color: blue;"><</span><span style="color: #a31515;">services</span><span style="color: blue;">>. </span></span>For purpose of demonstration, you can notice two<em> endpoints </em>with different bindings: basic and web. For current implementation, you can only use webHttpBinding, but in the case you have a legacy WCF service with different binding, you can simply add another endpoint for your new requirement and WCF service will continue to work with the previous and the new binding as well.<br />
<br />
<h2>
Implementing Android WCF client</h2>
<br />
In this section, it will be only presented the code for communication with previously implemented web service. For complete Android application you can refer to complete project from this <a href="http://www.filedropper.com/tododemoapplication" target="_blank">link</a>.<br />
<br />
Since we are using Rest services the client can be implemented by using HttpRequests. The following code represents the implementation of client side in Android application for each web service’s method call:<br />
<br />
<br />
<br />
<div style="background-color: white; color: black;">
<pre><span style="color: blue;">package</span> com.smallsoftlab.ToDoDemo.Services;
<span style="color: blue;">import</span> android.os.AsyncTask;
<span style="color: blue;">import</span> com.smallsoftlab.ToDoDemo.Model.ToDoItemModel;
<span style="color: blue;">import</span> org.apache.http.HttpEntity;
<span style="color: blue;">import</span> org.apache.http.HttpResponse;
<span style="color: blue;">import</span> org.apache.http.client.methods.HttpGet;
<span style="color: blue;">import</span> org.apache.http.client.methods.HttpPost;
<span style="color: blue;">import</span> org.apache.http.entity.StringEntity;
<span style="color: blue;">import</span> org.apache.http.impl.client.DefaultHttpClient;
<span style="color: blue;">import</span> org.json.JSONStringer;
<span style="color: blue;">import</span> java.io.InputStream;
<span style="color: blue;">import</span> java.io.InputStreamReader;
<span style="color: blue;">import</span> java.text.SimpleDateFormat;
<span style="color: blue;">import</span> java.util.Date;
<span style="color: green;">/**
* Created with IntelliJ IDEA.
* User: Vladimir
* Date: 2/20/13
* Time: 2:00 PM
* To change this template use File | Settings | File Templates.
*/</span>
<span style="color: blue;">public</span> <span style="color: blue;">class</span> Services <span style="color: blue;">extends</span> AsyncTask<Object, Void, String> {
<span style="color: blue;">private</span> <span style="color: blue;">static</span> <span style="color: blue;">final</span> String SVC_URL = <span style="color: #a31515;">"http://10.0.2.2:81/ToDoService.svc/web"</span>;
@Override
<span style="color: blue;">protected</span> String doInBackground(Object... params) {
String action = params[0].toString();
<span style="color: blue;">if</span> (action.contains(<span style="color: #a31515;">"AddToDoItem"</span>)) {
ToDoItemModel toDoItem = (ToDoItemModel) params[1];
<span style="color: blue;">return</span> addToDoItem(action, toDoItem);
} <span style="color: blue;">else</span> <span style="color: blue;">if</span> (action.contains(<span style="color: #a31515;">"GetToDoItemsByDate"</span>)) {
Date date = (Date) params[1];
<span style="color: blue;">return</span> getToDoItemsByDate(action, date);
} <span style="color: blue;">else</span> <span style="color: blue;">if</span> (action.contains(<span style="color: #a31515;">"GetAllToDoItems"</span>)) {
<span style="color: blue;">return</span> getAllToDoItems(action);
}
<span style="color: blue;">return</span> <span style="color: blue;">null</span>;
}
<span style="color: blue;">public</span> String addToDoItem(String action, ToDoItemModel toDoItem) {
<span style="color: blue;">int</span> statusCode = 400;
<span style="color: blue;">try</span> {
<span style="color: green;">// POST request to <service>/AddToDoItem</span>
<span style="color: green;">// Adds new ToDoItem</span>
HttpPost request = <span style="color: blue;">new</span> HttpPost(SVC_URL + action);
request.setHeader(<span style="color: #a31515;">"Accept"</span>, <span style="color: #a31515;">"application/json"</span>);
request.setHeader(<span style="color: #a31515;">"Content-type"</span>, <span style="color: #a31515;">"application/json"</span>);
<span style="color: green;">// Build JSON string</span>
JSONStringer item = <span style="color: blue;">new</span> JSONStringer()
.object()
.key(<span style="color: #a31515;">"toDoItem"</span>)
.object()
.key(<span style="color: #a31515;">"description"</span>).value(toDoItem.getDescription())
.key(<span style="color: #a31515;">"scheduleddate"</span>).value(<span style="color: #a31515;">"/Date("</span>+toDoItem.getScheduleDate().getTime()+<span style="color: #a31515;">")/"</span>)
.endObject()
.endObject();
StringEntity entity = <span style="color: blue;">new</span> StringEntity(item.toString());
request.setEntity(entity);
<span style="color: green;">// Send request to WCF service</span>
DefaultHttpClient httpClient = <span style="color: blue;">new</span> DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
statusCode = response.getStatusLine().getStatusCode();
} <span style="color: blue;">catch</span> (Exception e) {
e.printStackTrace();
}
<span style="color: blue;">return</span> String.valueOf(statusCode);
}
<span style="color: blue;">public</span> String getToDoItemsByDate(String action, Date date) {
String result = <span style="color: #a31515;">""</span>;
SimpleDateFormat sdf = <span style="color: blue;">new</span> SimpleDateFormat(<span style="color: #a31515;">"yyyy-MM-dd"</span>);
<span style="color: blue;">try</span> {
<span style="color: green;">// GET request to <service>/GetToDoItemsByDate</span>
<span style="color: green;">// Gets a list of ToDoItems for specific date</span>
HttpGet request = <span style="color: blue;">new</span> HttpGet(SVC_URL + action + <span style="color: #a31515;">"?date="</span> + sdf.format(date));
request.setHeader(<span style="color: #a31515;">"Accept"</span>, <span style="color: #a31515;">"application/json"</span>);
request.setHeader(<span style="color: #a31515;">"Content-type"</span>, <span style="color: #a31515;">"application/json"</span>);
DefaultHttpClient httpClient = <span style="color: blue;">new</span> DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity responseEntity = response.getEntity();
<span style="color: green;">// Read response data into buffer</span>
<span style="color: blue;">char</span>[] buffer = <span style="color: blue;">new</span> <span style="color: blue;">char</span>[(<span style="color: blue;">int</span>) responseEntity.getContentLength()];
InputStream stream = responseEntity.getContent();
InputStreamReader reader = <span style="color: blue;">new</span> InputStreamReader(stream);
reader.read(buffer);
stream.close();
result = <span style="color: blue;">new</span> String(buffer);
} <span style="color: blue;">catch</span> (Exception e) {
e.printStackTrace();
}
<span style="color: blue;">return</span> result;
}
<span style="color: blue;">public</span> String getAllToDoItems(String action) {
String result = <span style="color: #a31515;">""</span>;
<span style="color: blue;">try</span> {
<span style="color: green;">// GET request to <service>/GetAllToDoItems</span>
<span style="color: green;">// Gets all ToDoItems </span>
HttpGet request = <span style="color: blue;">new</span> HttpGet(SVC_URL + action);
request.setHeader(<span style="color: #a31515;">"Accept"</span>, <span style="color: #a31515;">"application/json"</span>);
request.setHeader(<span style="color: #a31515;">"Content-type"</span>, <span style="color: #a31515;">"application/json"</span>);
DefaultHttpClient httpClient = <span style="color: blue;">new</span> DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity responseEntity = response.getEntity();
<span style="color: green;">// Read response data into buffer</span>
<span style="color: blue;">char</span>[] buffer = <span style="color: blue;">new</span> <span style="color: blue;">char</span>[(<span style="color: blue;">int</span>) responseEntity.getContentLength()];
InputStream stream = responseEntity.getContent();
InputStreamReader reader = <span style="color: blue;">new</span> InputStreamReader(stream);
reader.read(buffer);
stream.close();
result = <span style="color: blue;">new</span> String(buffer);
} <span style="color: blue;">catch</span> (Exception e) {
e.printStackTrace();
}
<span style="color: blue;">return</span> result;
}
}
</pre>
</div>
<br />
NOTICE: You can see the service URL is directed to 10.0.2.2, and use this IP address since it is the address of the host that runs the WCF service. Do not use 127.0.0.1 since that would be the address of your Android phone or emulator that runs the application. Also, after you run your Azure project on the emulator, check the port number in your URL. Usually, it is 81, but if it is different you’ll need to change it to the right one.<br />
<br />
For the newest versions of Android SDK you’ll need to use the <em>AsyncTask</em> class for any kind of connection to remote resource. After you extend this class you’ll override the <em>doInBackground</em> method that receives the array of arguments. This method will proxy your request to specific web service call.<br />
<br />
The way you need to use <em>Services</em> class is like this:<br />
<br />
<div style="background-color: white; color: black;">
<pre> <span style="color: green;">//Add ToDoItem</span>
<span style="color: blue;">public</span> String addToDoItem(ToDoItemModel toDoItem) {
String status = <span style="color: blue;">null</span>;
<span style="color: blue;">try</span> {
Services svc = <span style="color: blue;">new</span> Services();
status = svc.execute(<span style="color: #a31515;">"/AddToDoItem"</span>, toDoItem).get();
} <span style="color: blue;">catch</span> (Exception e) {
e.printStackTrace();
}
<span style="color: blue;">return</span> status;
}</pre>
</div>
<br />
where status represents the return value of method. It can also be a JSON result for <em>GetToDoItemsByDate</em> and <em>GetAllToDoItems </em>call.<br />
<br />
<u><strong><span style="color: red;">Do not use this:</span></strong></u><br />
<br />
<div style="background-color: white; color: black;">
<pre>status = svc.addToDoItem(<span style="color: #a31515;">"/AddToDoItem"</span>, toDoItem);</pre>
</div>
<strong><u><span style="color: red;"></span></u></strong><br />
Instead use <em><strong>execute() </strong></em>which calls <em>doInBackground</em> method from <em>Services</em> class.</div>
Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com2tag:blogger.com,1999:blog-209337246847216621.post-88097028421264540672012-10-25T21:50:00.001+02:002012-10-26T14:32:33.358+02:00Clarifying Mediator pattern<div style="text-align: left" dir="ltr" trbidi="on"> </div> <div style="text-align: left" dir="ltr" trbidi="on"><br> </div> <h3 style="text-align: left" dir="ltr" trbidi="on"></h3> <h2 style="text-align: left" dir="ltr" trbidi="on">Introduction</h2> <div style="text-align: left" dir="ltr" trbidi="on">Mediator is design pattern that is primarily used to loose coupling between components in their communication. For instance, if each of components would communicate to each other directly, we could get a complex net of communication lines between these components. Instead of direct communication we are using mediator who will be intermediate component for inside communication between components.<br>Simple scenario for mediator role would be to gather messages from each component (component is in some books referred as Colleague), and than mediator would broadcast that message to all other components.<br>In the next image we can see UML class diagram showing us dependencies between classes in implementation of Mediator pattern. <em>Mediator </em>and <em>Component </em>can be either abstract classes or interfaces, depending of the specific implementation.</div> <div style="text-align: left" dir="ltr" trbidi="on"><br> </div><a href="http://lh5.ggpht.com/-aY7nfroOj8A/UIp9evlosKI/AAAAAAAAAMk/-IKJ8OCHKnE/s1600-h/ClassDiagram%25255B9%25255D.png"><img title="ClassDiagram" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="ClassDiagram" src="http://lh3.ggpht.com/-grbixuak_ao/UIp9ff___FI/AAAAAAAAAMo/-pMd8rRXVa4/ClassDiagram_thumb%25255B4%25255D.png?imgmax=800" width="611" height="380"></a><br> <div align="center"><span style="font-size: xx-small">UML class diagram representing Mediator pattern</span></div> <div align="center"><span style="font-size: xx-small"></span> </div>Now, there is a question, since mediator using broadcast, how each of components would know that the message is intended just for her. Well, in most cases message contains a key value that would be known to the receiver and sender, and it will be used to determine the originator and receiver of the message. There is also possibility to send sender and recipient information within the message. So, when the message is received by some component, component can determine if the message is intended for her or some other component, in that way message can be processed or ignored.<br>From the security side, this is not very safe way to distribute all messages as a broadcast, but if implementation is not restricted with security rules (for example, UI classes) than it can have a good purpose to decouple communication between components.<br><br> <h2>Implementation</h2> <p>In this blog I’ll demonstrate simple chat application written in Java. Application will contain three tabs (three components, i.e. Colleague), and each of the tabs will be able to communicate with other tabs over the Mediator. For the message representation I’ll implement Intent class which instances will be able to contain string messages. Of course, current implementation of Intent can be extended and used to wrap other object types in a message as well.<br></p><a href="http://lh3.ggpht.com/-gcOI9gidCcg/UIp_08B9A2I/AAAAAAAAANE/Od4xwEY3cl4/s1600-h/Mediator%252520demo%252520app%25255B4%25255D.png"><img title="Mediator demo app" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="Mediator demo app" src="http://lh5.ggpht.com/-jP1mkZ4kEag/UIp_1iRwiUI/AAAAAAAAANI/UFyi-F4J79U/Mediator%252520demo%252520app_thumb%25255B2%25255D.png?imgmax=800" width="468" height="328"></a><br> <blockquote> <div align="center"><span style="font-size: xx-small">Screenshot of the Mediator demo application</span></div></blockquote> <p>Current implementation of demo project is demonstrated in the next picture:<br></p><a href="http://lh6.ggpht.com/-OF8xFvcnk0s/UIp9gAz_W2I/AAAAAAAAAM0/ZUt0xpOtdU0/s1600-h/NewDiagram%25255B9%25255D.png"><img title="NewDiagram" style="float: none; margin-left: auto; display: block; margin-right: auto" alt="NewDiagram" src="http://lh5.ggpht.com/-RwfvJ08uRQk/UIp9hNU-1oI/AAAAAAAAAM8/0Xb9_FwUZDw/NewDiagram_thumb%25255B5%25255D.png?imgmax=800" width="653" height="445"></a><br> <div align="center"><span style="font-size: xx-small">UML class diagram representing implementation of Mediator pattern</span></div> <div align="center"><span style="font-size: xx-small"></span> </div> <p>Source code from demo project can be downloaded from <a href="https://dl.dropbox.com/u/45556593/TestMediator.zip">here</a>.</p> <p><br>Now, let’s take a look at the code.<br>This is simple Mediator interface that will be implemented in the Mediator class.<br></p><pre style="overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; border-bottom: #cecece 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; min-height: 40px; border-left: #cecece 1px solid; padding-right: 5px; width: 650px; background-color: #fbfbfb"><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">package com.testmediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"><span style="color: blue">public</span> <span style="color: blue">interface</span> IMediator {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void addComponent(IComponent _component);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void send(Intent _message, IComponent _sender);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">}</pre></pre><br>Class Mediator implements previous interface with two methods. Method <em>addComponent </em>is used for registering components, since the Mediator needs to know all actors of communication. Second method, <em>send</em>, simply broadcasts message to all of the components, except sender component.<br><pre style="overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; border-bottom: #cecece 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; min-height: 40px; border-left: #cecece 1px solid; padding-right: 5px; width: 650px; background-color: #fbfbfb"><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">package com.testmediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import java.util.ArrayList;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"><span style="color: blue">public</span> <span style="color: blue">class</span> Mediator <span style="color: blue">implements</span> IMediator{</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> ArrayList<IComponent> components = <span style="color: blue">new</span> ArrayList<IComponent>();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> @Override</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void addComponent(IComponent _component) {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> components.add(_component);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> @Override</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void send(Intent _message, IComponent _sender) {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">for</span>(IComponent component : components){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">if</span>(!component.equals(_sender)){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> component.receive(_message);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">}</pre></pre><br>In the next code preview you can see Component interface that will be implemented in Component classes.<br><pre style="overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; border-bottom: #cecece 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; min-height: 40px; border-left: #cecece 1px solid; padding-right: 5px; width: 650px; background-color: #fbfbfb"><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">package com.testmediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"><span style="color: blue">public</span> interface IComponent {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void receive(Intent _message);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void send(Intent _message, IComponent _sender);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> IMediator getMediator();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">}</pre></pre><br>As you can see in the Component implementation, each Component contains the reference to the same Mediator that is set up in the constructor. Other important methods are <em>send </em>and <em>receive</em> which implements sending message via Mediator instance and receiving message from Mediator broadcast, respectively. On the click of the send button message will be send to another component depending of selected recipient from the combo box.<br><pre style="overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; border-bottom: #cecece 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; min-height: 40px; border-left: #cecece 1px solid; padding-right: 5px; width: 650px; background-color: #fbfbfb"><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">package com.testmediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import java.awt.event.ActionEvent;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import java.awt.event.ActionListener;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import java.awt.event.WindowAdapter;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import javax.swing.JButton;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import javax.swing.JComboBox;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import javax.swing.JLabel;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import javax.swing.JPanel;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">import javax.swing.JTextField;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"><span style="color: blue">public</span> <span style="color: blue">class</span> ComponentOne extends WindowAdapter implements IComponent, ActionListener{</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> IMediator m_mediator = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> JPanel m_panel = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> JComboBox<<span style="color: blue">String</span>> m_tabSelect = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> JLabel m_label = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> JTextField m_text = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> JButton m_button = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> JLabel m_receivedMsg = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> Intent m_message = null;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> ComponentOne(IMediator mediator){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_mediator = mediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> initGui();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> @Override</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void receive(Intent _message) {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_message = _message;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">if</span>(m_message.getStringMsg("<span style="color: darkred">ToTab01</span>")!="<span style="color: darkred"></span>"){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_receivedMsg.setText(m_receivedMsg.getText() + "<span style="color: darkred"> - </span>" + m_message.getStringMsg("<span style="color: darkred">ToTab01</span>"));</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel.repaint();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> @Override</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void send(Intent _message, IComponent _sender) {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_mediator.send(_message, this);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> @Override</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> IMediator getMediator() {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> return m_mediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">private</span> void initGui(){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel = new JPanel();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_tabSelect = new JComboBox<<span style="color: blue">String</span>>();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_tabSelect.addItem("<span style="color: darkred">tab02</span>");</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_tabSelect.addItem("<span style="color: darkred">tab03</span>");</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_label = new JLabel("<span style="color: darkred">Tab01, enter the message: </span>");</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_text = new JTextField(20);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_button = new JButton("<span style="color: darkred">Send</span>");</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_button.addActionListener(this);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_receivedMsg = new JLabel("<span style="color: darkred">Received: </span>");</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel.<span style="color: blue">add</span>(m_tabSelect);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel.<span style="color: blue">add</span>(m_label);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel.<span style="color: blue">add</span>(m_text);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel.<span style="color: blue">add</span>(m_button);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_panel.<span style="color: blue">add</span>(m_receivedMsg);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> JPanel getPanel(){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> return m_panel;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> Intent getMessage(){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> return m_message;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> @Override</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void actionPerformed(ActionEvent _event) {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> Object source = _event.getSource();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">if</span>(source.equals(m_button)){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> Intent intent = new Intent();</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">if</span>(m_tabSelect.getSelectedItem() == "<span style="color: darkred">tab02</span>"){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> intent.putStringMsg("<span style="color: darkred">ToTab02</span>", m_text.getText());</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }<span style="color: blue">else</span> <span style="color: blue">if</span>(m_tabSelect.getSelectedItem() == "<span style="color: darkred">tab03</span>"){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> intent.putStringMsg("<span style="color: darkred">ToTab03</span>", m_text.getText());</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> send(intent,this);</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">}</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre></pre><br>Simple Intent class represents wrapper for all messages. As you can see for now it contains only methods for putting string message and reading the same message. This class can be extended to wrap all other kinds of objects.<br><pre style="overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; border-bottom: #cecece 1px solid; padding-bottom: 5px; padding-top: 5px; padding-left: 5px; min-height: 40px; border-left: #cecece 1px solid; padding-right: 5px; width: 650px; background-color: #fbfbfb"><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">package com.testmediator;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"><span style="color: blue">public</span> <span style="color: blue">class</span> Intent {</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">String</span> m_stringMsgKey;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">String</span> m_stringMsg = "<span style="color: darkred"></span>";</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> void putStringMsg(<span style="color: blue">String</span> _key, <span style="color: blue">String</span> _value){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_stringMsgKey = _key;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> m_stringMsg = _value;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> </pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">public</span> <span style="color: blue">String</span> getStringMsg(<span style="color: blue">String</span> _messageKey){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">if</span>(_messageKey == m_stringMsgKey){</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">return</span> m_stringMsg;</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">else</span>{</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> <span style="color: blue">return</span> "<span style="color: darkred"></span>";</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"> }</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb">}</pre><pre style="font-size: 12px; font-family: consolas,'Courier New',courier,monospace; margin: 0em; width: 100%; background-color: #fbfbfb"></pre></pre><br>Other classes from <a href="https://dl.dropbox.com/u/45556593/TestMediator.zip">project</a> are excluded from code preview since primary role of this blog was to present Mediator pattern. In a context of the project it is basically a simple desktop app developed using swing library.<br><br><br /><h2>Conclusion </h2><br>Mediator pattern is pretty common to meet in a different solutions. For instance, Android platform is using very similar principle regarding communication between Activities using Intent objects as messages that will be broadcasted to all Activity instances in the app. This way complex peer-to-peer communication is replaced by the Mediator who is in charge of distributing messages, providing loose coupling between components which is in the almost all cases very good practice.<br /> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com1tag:blogger.com,1999:blog-209337246847216621.post-8737015265225063592012-09-24T20:07:00.001+02:002012-09-24T20:08:25.709+02:00Installing Windows Phone SDK on Windows 8 RC1<p> </p> <p>In this blog I’ll tell you about little issue that occurred to me during installation of Windows Phone SDK on Windows 8 RC1. Since it could happen to anyone running Win8 RC I thought it would be a good idea to share this tip.</p> <p>Since I have already had installed Visual Studio on my PC, I went to <a href="http://dev.windowsphone.com/en-us/downloadsdk">Windows Phone Dev Center</a> and downloaded the last version of Windows Phone SDK 7.1.1. After that, I started the installation but than the error message occurred: “<strong>KB2669191 does not apply, or is blocked by another condition on your computer</strong>”.</p> <h2>What is causing the error?</h2> <p>During installation, XNA Game Studio tries to install a version of the Games for Windows - LIVE Redistributable. The system reacts with the previously mentioned error since the install process wants to replace a file with an older version. So, the main reason of this compatibility issue is that the Win8 comes with the newer version of Games for Windows. </p> <h2>Solution</h2> <p>If you preinstall the the new version of Games for Windows before WP SDK, install process will recognize his presence and use the new version instead the old one. So, basic workaround is this:</p> <p>1. Install the new version of Games for Windows from the <a href="http://www.xbox.com/en-US/LIVE/PC/DownloadClient">XBOX site</a></p> <p>2. <a href="http://go.microsoft.com/fwlink/?LinkId=258412">Download</a> and install WP SDK 7.1.1 </p> <p>3. <a href="http://go.microsoft.com/fwlink/?LinkId=258413">Download</a> and install WP SDK 7.1.1 Update (recommended)</p> <p>After you did these steps you are ready to go.</p> <p>Launch your Visual Studio and in File->New->Project you should see the next screen:</p> <p><a href="http://lh3.ggpht.com/-rYAcG0lDHXg/UGChYUgl1bI/AAAAAAAAAL4/h0OJwWeKPnE/s1600-h/WP7%252520projects%25255B8%25255D.png"><img title="WP7 projects" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; display: block; padding-right: 0px; border-top-width: 0px; margin-right: auto" border="0" alt="WP7 projects" src="http://lh3.ggpht.com/--3LADFHMvpY/UGChZGae1DI/AAAAAAAAAMA/27n3NUvMTSE/WP7%252520projects_thumb%25255B4%25255D.png?imgmax=800" width="493" height="339"></a></p> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com0tag:blogger.com,1999:blog-209337246847216621.post-91263256249852535122012-06-21T21:59:00.000+02:002012-06-21T22:02:43.172+02:00Create your resource’s icons for Android app with ease<h2> </h2> <h2>Introduction</h2> <p align="justify"><a href="http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html">Android Asset Studio</a> is a part of <a href="http://code.google.com/p/android-ui-utils/">android-ui-utils</a> project and in essence it is a web site that provides you online tool for generating necessary icons for buttons or menus. This service allows you to automatically and rapidly generate required icons in all sizes you need, and by that you can save a lot of time.</p> <h2>About</h2> <p>If you visit <a href="http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html">Android Asset Studio</a> web site you will notice two parts. <strong>Icon generators</strong> contains several categories that allow you to generate icons for particular purpose.</p> <table border="0" cellspacing="0" cellpadding="2" width="822"> <tbody> <tr> <td valign="top" width="200"><a href="http://lh5.ggpht.com/-xu3dAxw_hYw/T-N8pl7ve7I/AAAAAAAAAIM/uNgx-RjSmZg/s1600-h/ScreenShot01%25255B4%25255D.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ScreenShot01" border="0" alt="ScreenShot01" src="http://lh4.ggpht.com/-sFofpna2xHU/T-N8rBSkp5I/AAAAAAAAAIU/v8vAGX9XHsw/ScreenShot01_thumb%25255B2%25255D.jpg?imgmax=800" width="404" height="442"></a></td> <td valign="top" width="620"><br><br><br><br><br><br><br>Using foreground option you can upload image, use default clipart icons or use text as icon foreground. <br>Also, you can adjust padding by using percentage scroll to determine width of image margins.<br>Besides, you can also adjust background shape and color.<br><br>After you adjusted your icon look, you can download single image in desired dpi or you can download .zip file that will contain “res” folder with photos of all image sizes.</td></tr></tbody></table> <p></p> <p>The second part contains nice online tool called <strong>Device frame generators</strong> for wrapping your previously taken screenshots of mobile screen. You can use it if you just need to create a couple of screen images to assemble screen flow for your mobile app usage scenario. In this case you will be provided better context for your frames which can be pretty handy. It also allows you to use correct screen resolutions for particular devices. Only requirement is that your image is in exact resolution as it is specified for particular device.</p> <table border="0" cellspacing="0" cellpadding="2" width="823"> <tbody> <tr> <td valign="top" width="200"><a href="http://lh4.ggpht.com/-RYxtaAsT-5Q/T-N8tLCgsrI/AAAAAAAAAIc/0H1vBZVnmUU/s1600-h/ScreenShot03%25255B3%25255D.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ScreenShot03" border="0" alt="ScreenShot03" src="http://lh5.ggpht.com/-1oKbGHZ9ywg/T-N8uCIlbGI/AAAAAAAAAIk/cNgk5l21i9w/ScreenShot03_thumb%25255B1%25255D.jpg?imgmax=800" width="404" height="276"></a> </td> <td valign="top" width="621"> <p> </p> <p> </p> <ul> <li>Drag&drop image to area for wanted mobile device. Notice that you will need to use image that has exactly the same size as a mobile device’s screen size.</li></ul></td></tr> <tr> <td valign="top" width="200"><a href="http://lh6.ggpht.com/-CwPwHqC97wI/T-N8wVe93sI/AAAAAAAAAIs/FNa0TPlN3BY/s1600-h/ScreenShot04%25255B3%25255D.jpg"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ScreenShot04" border="0" alt="ScreenShot04" src="http://lh5.ggpht.com/-JMXFS13X45Q/T-N8xntHOsI/AAAAAAAAAI0/MEURX2bntT8/ScreenShot04_thumb%25255B1%25255D.jpg?imgmax=800" width="404" height="231"></a> </td> <td valign="top" width="621"> <p> </p> <p> </p> <ul> <li>After image is loaded you can export it back to your desktop by using drag&drop.</li></ul></td></tr></tbody></table> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com0tag:blogger.com,1999:blog-209337246847216621.post-59584315805298336352012-02-11T17:20:00.000+01:002013-07-02T16:45:10.697+02:00Link Android application with eBay web service<div style="text-align: left" dir="ltr" trbidi="on"><br><br></div> <h3 style="text-align: left" dir="ltr" trbidi="on">Introduction</h3> <div style="text-align: left" dir="ltr" trbidi="on"> </div> <p style="text-align: left" dir="ltr" trbidi="on">In this tutorial I'll demonstrate a way of linking your hybrid Android applications (Android native + HTML) with eBay web services.<br><br>You can download file project source from <a href="https://dl.dropboxusercontent.com/u/45556593/MyEbaySearch.zip">here</a>.<br><i>(Notice that you will need to insert AppID in url string at RestClient.java. Procedure is described in Sign up - ebay Developer Network section and Web service client section.)</i><br><br>We'll create simple Android app with service client for searching eBay items by a keyword. After search is completed, application will list a correct number of items with their hyperlinks to details and images.<br>For developing applications with eBay integration, <a href="https://www.x.com/developers/ebay">Ebay Developer Network</a> gives a good insight in some of the products for developers. From current featured products there are 4 categories:<br>1. Search - offers eBay finding API that enables application to search for eBay items.<br>2. Trading - offers API for authenticated access to private eBay data<br>3. Buying - offers eBay shopping API access to public read-only data<br>4. Go Local - offers Milo Open API that allows developers to access local availability information from 50,000+ stores all across the country<br><br>These APIs give you a powerfull tools for developing e-commerce apps using integration with eBay web services. </p> <p style="text-align: left" dir="ltr" trbidi="on">The same as in <a href="http://smallsoftlab.blogspot.com/2012/01/syntaxhighlighter.html">previous tutorial</a> we'll develope hybrid Android application that is using native Java code for backend logic and HTML with jQuery for UI. </p> <div style="text-align: left" dir="ltr" trbidi="on"> </div> <h3 style="text-align: left" dir="ltr" trbidi="on">Screen flow</h3> <div style="text-align: left" dir="ltr" trbidi="on"><br>In this sample, our application will contain two HTML pages. The first page will be search interface that has search keyword input and number input that represents a number of searched result items that will be displayed in second screen. The second screen will display search results with item titles with hyperlinks and their images.<br></div> <div style="text-align: left" dir="ltr" trbidi="on"> <table> <tbody> <tr> <td> <div class="separator" style="text-align: center; clear: both"><a style="margin-left: 1em; margin-right: 1em" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_9BoUfqQTRfOOfevSydCE1C_ws-bux03Tg_hlJ23Mu9VNb3mQz8tspnP5BN0Cn2QgTUiJM83cZ-fyfIIyXA4H9X9AnpKtbbtkUFzaCfgTKmzmNyk72pi9OWmTXTNMz7VgOVPZmG4XSVQ/s1600/firstscreen.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_9BoUfqQTRfOOfevSydCE1C_ws-bux03Tg_hlJ23Mu9VNb3mQz8tspnP5BN0Cn2QgTUiJM83cZ-fyfIIyXA4H9X9AnpKtbbtkUFzaCfgTKmzmNyk72pi9OWmTXTNMz7VgOVPZmG4XSVQ/s320/firstscreen.png" width="251" height="320"></a></div></td> <td> <div class="separator" style="text-align: center; clear: both"><a style="margin-left: 1em; margin-right: 1em" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzym5q7m8Sa0sQZHHn6q24G5wpHG2VG3lJU4mxe6cpyHG1ZiXrUmAE01VMpSVS01QFNvloRCVL57hzhko9_CcwBSYgQD8_ZqFm1QCuPU-yXPzie6zhGxo3q6qzrjLLZNbj1elppx-2snU/s1600/second+screen.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzym5q7m8Sa0sQZHHn6q24G5wpHG2VG3lJU4mxe6cpyHG1ZiXrUmAE01VMpSVS01QFNvloRCVL57hzhko9_CcwBSYgQD8_ZqFm1QCuPU-yXPzie6zhGxo3q6qzrjLLZNbj1elppx-2snU/s320/second+screen.png" width="198" height="320"></a></div></td></tr> <tr> <td> <div style="text-align: center">First page - (index.html) Search page</div></td> <td> <div style="text-align: center">Second page - (searchitems.html) Search results</div></td></tr></tbody></table></div> <div style="text-align: left" dir="ltr" trbidi="on"> </div> <h3 style="text-align: left" dir="ltr" trbidi="on">Sign up - ebay Developer Network</h3> <div style="text-align: left" dir="ltr" trbidi="on"> </div> <p style="text-align: left" dir="ltr" trbidi="on">In case with developing application that will use eBay services, you'll need to have some application parameters that we'll be provided to you after you sing up on <a href="https://developer.ebay.com/base/membership/signin/">developer.ebay.com </a>web site. In order to do that:<br>1. go on previous URL and click <i>Join now</i> section.<br>2. Fill in required data and register.<br>3. After you confirm your account, go back to web site and sign in.<br>4. Go to <i>My Account</i><br>5. At <i>application keys</i> pane click <i>Generate Keys</i><br> <div class="separator" style="text-align: left; clear: both" dir="ltr" trbidi="on"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsokOT1isv-My8w1iAHTc0rnmnnXKkf-UYMyuLyDSJZgkgr45at8AcAe7vAtxR-hpwPlXJGKHFQVZFgd2O61e7Ebg3UmCG7DyepWDZN-l-vh69UF_6loN3KqZCIQUXfoHlBhWz84mexs/s1600/EBay+account.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAsokOT1isv-My8w1iAHTc0rnmnnXKkf-UYMyuLyDSJZgkgr45at8AcAe7vAtxR-hpwPlXJGKHFQVZFgd2O61e7Ebg3UmCG7DyepWDZN-l-vh69UF_6loN3KqZCIQUXfoHlBhWz84mexs/s320/EBay+account.png" width="320" height="202"></a></div> <div style="text-align: left" dir="ltr" trbidi="on"><br>6. After you generate your keys you should get list of ids that will be used in your app configuration.<br><br></div> <h3 style="text-align: left" dir="ltr" trbidi="on">Setting up Android project</h3> <div style="text-align: left" dir="ltr" trbidi="on"> </div> <p style="text-align: left" dir="ltr" trbidi="on"><u><b>Android Manifest</b></u><br><br>Create new Android project in Eclipse environment - File -> New -> Android project, and choose target platform (in my case I used Android 2.1-update1). <br>1. After you created project enter AndroidManifest.xml and go to <i>Permissions</i> section.<br>2. Click <i>Add...</i> and choose <i>Uses Permission</i><br>3. From <i>Name</i> option set choose <b>android.permission.INTERNET</b><br>4. Save your changes <br><br><u><b>Layout XML</b></u><br><br>In project solution go to <i>res</i> folder and in <i>layouts</i> open main.xml. Go to main.xml section and replace your xml layout with next: <div style="text-align: left" dir="ltr" trbidi="on"><pre class="brush: xml"><div class="csharpcode"><pre><pre><span class="kwrd"></span></pre><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><div style="color: black; background-color: white"><pre><span style="color: green"><!--?xml version="1.0" encoding="utf-8"?--></span><br /><span style="color: blue"><</span><span style="color: #a31515">linearlayout</span> <span style="color: red">xmlns:android</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">http://schemas.android.com/apk/res/android</span><span style="color: black">"</span><br /><span style="color: red">android:orientation</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">vertical</span><span style="color: black">"</span><br /><span style="color: red">android:layout_width</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">fill_parent</span><span style="color: black">"</span> <br /><span style="color: red">android:layout_height</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">fill_parent</span><span style="color: black">"</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">webview</span> <span style="color: red">android:layout_width</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">fill_parent</span><span style="color: black">"</span><br /> <span style="color: red">android:layout_height</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">fill_parent</span><span style="color: black">"</span> <br /> <span style="color: red">android:id</span><span style="color: blue">=</span><span style="color: black">"</span><span style="color: blue">@+id/webview</span><span style="color: black">"</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">webview</span><span style="color: blue">></span><br /><span style="color: blue"></</span><span style="color: #a31515">linearlayout</span><span style="color: blue">></span><br /></pre></div><br></linearlayout><br></pre></div></pre></div><br /><div style="text-align: left" dir="ltr" trbidi="on">In this step we added <i>webView</i> component which will be used to display HTML pages and execute JavaScript. <br><br><u><b>Assets folder</b></u><br><br>The same as in <a href="http://smallsoftlab.blogspot.com/2012/01/syntaxhighlighter.html">previous tutorial</a> we'll use <a href="http://jqmobi.com/">jQMobi</a> library for jQuery development. Follow next steps to set up necessary resources for UI development:<br>1. Create directories in <i>assets</i> folder with following paths - <i>assets/www/css-js</i> and <i>assets/www/img</i><br>2. Download jQMobi and extract js libraries in <i>assets/www/css-js/</i><br>3. Store some PNG in img folder that we'll be used in search screen<br>4. Create two empty HTML files in www directory and name them as <i>index.html</i> and <i>searchitems.html</i><br>Now your <i>assets</i> folder should look like this<br></div><br /><div class="separator" style="text-align: left; clear: both" dir="ltr" trbidi="on"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuQ8sOFWo1iFNumFywdXgYuigax_GHbQVWexPHtphb_qUB9nA15Z-iNb2As-gWqyYcTXt6KJj7z9jIxOwlDr5HDoOycUFea_v8VegP6Evihow0coCSjt39h8ymX0S-FMsyqPy7J8o-RVI/s1600/assets+folder.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuQ8sOFWo1iFNumFywdXgYuigax_GHbQVWexPHtphb_qUB9nA15Z-iNb2As-gWqyYcTXt6KJj7z9jIxOwlDr5HDoOycUFea_v8VegP6Evihow0coCSjt39h8ymX0S-FMsyqPy7J8o-RVI/s320/assets+folder.png" width="204" height="184"></a></div><br /><div style="text-align: left" dir="ltr" trbidi="on"><br><br></div><br /><h3 style="text-align: left" dir="ltr" trbidi="on">Web service client</h3><br /><div style="text-align: left" dir="ltr" trbidi="on"> </div><br /><p style="text-align: left" dir="ltr" trbidi="on">To establish link to eBay web service we'll need to write a client side class that is going to access eBay <i>Finding</i> service. In this case, we'll use <a href="http://www.ibm.com/developerworks/webservices/library/ws-restful/">REST-full</a> eBay service and since these services are based on HTTP methods, we'll implement HTTP client to send HTTP requests to eBay service. In response, web service will send JSON object with items data as a search result.<br><i>Remark: You're not limited on using REST-full services, their is also a way of using SOAP based eBay web services. In that case you'll need to use <a href="http://ksoap2.sourceforge.net/">kSOAP2 project</a>. SOAP services won't be covered in this tutorial.</i></p><br /><p style="text-align: left" dir="ltr" trbidi="on">First step is to create new class in your package called <i>RestClient</i>. Then enter this code in your class: <br /><div style="color: black; background-color: white"><br /><div style="color: black; background-color: white"><pre> <span style="color: blue">import</span> java.io.IOException; <br /> <span style="color: blue">import</span> org.apache.http.client.ClientProtocolException; <br /> <span style="color: blue">import</span> org.apache.http.client.HttpClient; <br /> <span style="color: blue">import</span> org.apache.http.client.ResponseHandler; <br /> <span style="color: blue">import</span> org.apache.http.client.methods.HttpGet; <br /> <span style="color: blue">import</span> org.apache.http.impl.client.BasicResponseHandler; <br /> <span style="color: blue">import</span> org.apache.http.impl.client.DefaultHttpClient; <br /> <br /> <span style="color: blue">public</span> <span style="color: blue">class</span> RestClient { <br /> <br /> <span style="color: blue">public</span> <span style="color: blue">static</span> String getEbayItems(String term, String number){ <br /> <br /> String json = <span style="color: blue">null</span>; <br /> <br /> String url = <span style="color: #a31515">"http://svcs.ebay.com/services/search/FindingService/v1?OPERATION-"</span>+<br /> <span style="color: #a31515">"NAME=findItemsByKeywords"</span>+<br /> <span style="color: #a31515">"&SERVICE-VERSION=1.0.0"</span>+<br /> <span style="color: #a31515">"&SECURITY-APPNAME=000000000-0000-0000-0000-00000000000"</span>+<br /> <span style="color: #a31515">"&RESPONSE-DATA-FORMAT=JSON"</span>+<br /> <span style="color: #a31515">"&REST-PAYLOAD"</span>+<br /> <span style="color: #a31515">"&keywords="</span>+term+<br /> <span style="color: #a31515">"&paginationInput.entriesPerPage="</span>+Integer.parseInt(number);<br /> <br /> HttpClient httpClient = <span style="color: blue">new</span> DefaultHttpClient();<br /> HttpGet httpGet = <span style="color: blue">new</span> HttpGet(url);<br /> ResponseHandler<String> responseHandler = <span style="color: blue">new</span> BasicResponseHandler();<br /> String response;<br /> <span style="color: blue">try</span> {<br /> response = httpClient.execute(httpGet,responseHandler);<br /> json = response.toString();<br /> }<span style="color: blue">catch</span> (ClientProtocolException e) { <br /> e.printStackTrace();<br /> }<span style="color: blue">catch</span> (IOException e) {<br /> e.printStackTrace();<br /> }<br /> <span style="color: blue">return</span> json;<br /> }<br />}<br /></pre></div></div><br /><div style="color: black; background-color: white"><font face="Courier New"></font> </div><br /><div style="text-align: left" dir="ltr" trbidi="on">As we can see, this class contains single method <i>getEbayItems</i> that will retrieve search results. Notice in <i>url</i> string HTTP POST arguments. These arguments represents our web service call parameters.<br>- In <i>SECURITY-APPNAME</i> you will enter your generated <i>AppID</i> key from Production keys section under your account at developer.ebay.com.<br>- <i>RESPONSE-DATA-FORMAT</i> represents data type that web service will return in response (JSON or XML).<br>- <i>keywords</i> is a search term.<br>- and <i>paginationInput.entriesPerPage</i> represents item number in search result.<br>If you set your parameters correctly, you will be able to see your JSON result when you enter this <i>url</i> in your web browser. In continue, we'll create simple HTTP client that will send HTTP GET request to eBay web service. In response it returns JSON result. </div><br /><div style="text-align: left" dir="ltr" trbidi="on"> </div><br /><h3 style="text-align: left" dir="ltr" trbidi="on">Main Activity class</h3><br /><p style="text-align: left" dir="ltr" trbidi="on">In source of project, we'll edit Activity class that was generate when project was created. Modify your code: <br /><div style="text-align: left" dir="ltr" trbidi="on"><pre class="brush: java"><div class="csharpcode"><div style="color: black; background-color: white"><pre><span style="color: blue">import</span> java.util.ArrayList; <br /><span style="color: blue">import</span> org.json.JSONArray;<br /><span style="color: blue">import</span> org.json.JSONException; <br /><span style="color: blue">import</span> org.json.JSONObject; <br /><span style="color: blue">import</span> android.app.Activity; <br /><span style="color: blue">import</span> android.os.Bundle; <br /><span style="color: blue">import</span> android.os.Handler; <br /><span style="color: blue">import</span> android.view.KeyEvent;<br /><span style="color: blue">import</span> android.webkit.WebView; <br /><br /><span style="color: blue">public</span> <span style="color: blue">class</span> MainActivity <span style="color: blue">extends</span> Activity {<br /> WebView webView; <br /> String json;<br /> String callback; <br /><br /> <span style="color: green">//Searched item data </span><br /> ArrayList<String> titles = <span style="color: blue">new</span> ArrayList<String>(); <br /> ArrayList<String> imageUrl = <span style="color: blue">new</span> ArrayList<String>(); <br /> ArrayList<String> viewItemUrl = <span style="color: blue">new</span> ArrayList<String>(); <br /> <br /> <span style="color: blue">private</span> Handler handler; <br /> <span style="color: blue">private</span> <span style="color: blue">static</span> <span style="color: blue">final</span> String HTML_ROOT = <span style="color: #a31515">"file:///android_asset/www/"</span>; <br /> <br /> @Override <br /> <span style="color: blue">public</span> <span style="color: blue">void</span> onCreate(Bundle savedInstanceState) { <br /> <span style="color: blue">super</span>.onCreate(savedInstanceState);<br /> setContentView(R.layout.main); <br /> webView = (WebView)findViewById(R.id.webview); <br /> webView.getSettings().setJavaScriptEnabled(<span style="color: blue">true</span>); <br /> webView.addJavascriptInterface(<span style="color: blue">this</span>, <span style="color: #a31515">"jsInterface"</span>); <br /> handler = <span style="color: blue">new</span> Handler(); <br /> loadPage(<span style="color: #a31515">"index.html"</span>); <br /> } <br /> <br /> <span style="color: blue">public</span> <span style="color: blue">void</span> loadPage(String page){ <br /> <span style="color: blue">final</span> String url = HTML_ROOT + page; <br /> loadURL(url); <br /> } <br /> <br /> <span style="color: blue">private</span> <span style="color: blue">void</span> loadURL(<span style="color: blue">final</span> String url){ <br /> handler.post(<span style="color: blue">new</span> Runnable(){ <br /> <span style="color: blue">public</span> <span style="color: blue">void</span> run(){ <br /> webView.loadUrl(url); <br /> } <br /> }); <br /> } <br /> <br /> <span style="color: blue">public</span> <span style="color: blue">void</span> callSearchService(String term, String number, String callback){ <br /> <span style="color: blue">try</span> { <br /> json = RestClient.getEbayItems(term,number); <br /> <span style="color: blue">this</span>.callback = callback; <br /> <span style="color: green">//Parsing JSON result </span><br /> JSONObject jObjectMain = <span style="color: blue">new</span> JSONObject(json); <br /> JSONArray jArrayMain = jObjectMain.getJSONArray(<span style="color: #a31515">"findItemsByKeywordsResponse"</span>); <br /> JSONObject jObjectResult = jArrayMain.getJSONObject(0); <br /> JSONArray jArrayResult = jObjectResult.getJSONArray(<span style="color: #a31515">"searchResult"</span>); <br /> JSONObject jObjectSearch = jArrayResult.getJSONObject(0); <br /> JSONArray jArraySearch = jObjectSearch.getJSONArray(<span style="color: #a31515">"item"</span>); <br /> <br /> JSONObject jObjectItems = <span style="color: blue">new</span> JSONObject(); <br /> titles = <span style="color: blue">new</span> ArrayList<String>(); <br /> imageUrl = <span style="color: blue">new</span> ArrayList<String>(); <br /> viewItemUrl = <span style="color: blue">new</span> ArrayList<String>(); <br /> <span style="color: blue">for</span>(<span style="color: blue">int</span> i=0; i<jarraysearch.length(); i++){ <br /> jObjectItems = jArraySearch.getJSONObject(i); <br /> titles.add(jObjectItems.getString(<span style="color: #a31515">"title"</span>).replaceAll(<span style="color: #a31515">"[\"]|[\\[]|[\\]]"</span>, <span style="color: #a31515">""</span>)); <br /> imageUrl.add(jObjectItems.getString(<span style="color: #a31515">"galleryURL"</span>).replaceAll(<span style="color: #a31515">"[\"]|[\\[]|[\\]]"</span>, <span style="color: #a31515">""</span>)); <br /> viewItemUrl.add(jObjectItems.getString(<span style="color: #a31515">"viewItemURL"</span>).replaceAll(<span style="color: #a31515">"[\"]|[\\[]|[\\]]"</span>, <span style="color: #a31515">""</span>)); <br /> } <br /> loadPage(<span style="color: #a31515">"searchitems.html"</span>); <br /> } <span style="color: blue">catch</span> (JSONException e) { <br /> e.printStackTrace(); <br /> } <br /> } <br /> <br /> <span style="color: blue">public</span> <span style="color: blue">void</span> getSearchedItems(){ <br /> String innerHtml = <span style="color: #a31515">""</span>; <br /> <span style="color: blue">for</span>(<span style="color: blue">int</span> i=0; i<titles.size(); i++){<br /> innerHtml += <span style="color: #a31515">"<div class="</span>resultItem<span style="color: #a31515">">"</span> + <br /> <span style="color: #a31515">"<a href="</span><span style="color: #a31515">"+viewItemUrl.get(i)+"</span><span style="color: #a31515">">"</span>+titles.get(i)+<span style="color: #a31515">"</a>"</span> +<br /> <span style="color: #a31515">"<img src="</span><span style="color: #a31515">"+imageUrl.get(i)+"</span><span style="color: #a31515">">"</span> + <br /> <span style="color: #a31515">"</div>"</span>; <br /> } <br /> <span style="color: blue">final</span> String callbackMethod = <span style="color: #a31515">"javascript:"</span>+callback+<span style="color: #a31515">"(\""</span>+innerHtml+<span style="color: #a31515">"\")"</span>; <br /> loadURL(callbackMethod); <br /> } <br /> <br /> @Override <br /> <span style="color: blue">public</span> <span style="color: blue">boolean</span> onKeyDown(<span style="color: blue">int</span> keyCode, KeyEvent event){ <br /> <span style="color: blue">if</span>((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()){ <br /> webView.goBack(); <br /> <span style="color: blue">return</span> <span style="color: blue">true</span>; <br /> } <br /><br /> <span style="color: blue">return</span> <span style="color: blue">super</span>.onKeyDown(keyCode, event); <br /> } <br /> }<br /></pre></div><pre><font color="#606060"></font> </pre></div><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style></pre></div><br /><div style="text-align: left" dir="ltr" trbidi="on">1. <i>onCreate</i> method - This method is called at creating activity state. In this part, we'll set our layout that was previously edited (main.xml) and in WebView component will enable JavaScript execution and register JavaScript interface. Using this interface we'll be able to call JavaScript from our Java code and vice versa (see <a href="http://smallsoftlab.blogspot.com/2012/01/syntaxhighlighter.html">previous tutorial</a>). In the end of this method we'll load our first page (index.html).<br>2. <i>loadPage</i> method is used to load page in WebView component using page URL and <i>loadURL</i> is used for running HTML page and jQUery in WebView.<br>3. <i>callSearchService</i> method - this method gets three arguments: term (search keyword), number (item number in search result) and callback (name of JavaScript method to be called back). All of these arguments represent input data that will be forwarded from HTML page to Java by JavaScript method that will make <i>callSearchService</i> method call using <i>jsInterface</i>. In the first part, method gets search results by calling <i>getEbaysItems</i> from RestClient class. After that we parse our JSON result.<br>Basically, it re-encapsulates JSON arrays in result to get to item data. After we get our specific JSON Array with items data, we'll read their titles, image urls and url to details page. Don't get confused by <i>replaceAll("[\"]|[\\[]|[\\]]", "")</i> method. It is using Regex to remove redundant JSON characters - <i>["</i> and <i>"]</i>.<br>After we store JSON parsed results in class attributes, we load second page (searchitems.html) that is going to display search results.<br>4. <i>getSearchedItems</i> method - will send inner HTML with JSON prased results as an argument in callback JavaScript method in <i>searchitems.html</i> page.<br>5. <i>onKeyDown</i> method - overrides button "Back" functionality to go to previous HTML page. <br> </div><br /><h3 style="text-align: left" dir="ltr" trbidi="on">HTML pages</h3><br /><p style="text-align: left" dir="ltr" trbidi="on">Replace your index.html with following HTML: <span class="lnum"><span class="lnum"></span><br /><div style="text-align: left" dir="ltr" trbidi="on"><pre class="brush: html"><div class="csharpcode"><pre><div class="csharpcode"><pre><span class="lnum"></span><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style></span><div style="color: black; background-color: white"><pre><span style="color: red"><div style="color: black; background-color: white"><pre><span style="color: blue"><!</span><span style="color: #a31515">DOCTYPE</span> <span style="color: red">html</span><span style="color: blue">></span><br /><span style="color: blue"><</span><span style="color: #a31515">html</span><span style="color: blue">></span> <br /><span style="color: blue"><</span><span style="color: #a31515">head</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">meta</span> <span style="color: red">charset</span><span style="color: blue">=</span><span style="color: blue">"ISO-8859-1"</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span> <span style="color: red">src</span><span style="color: blue">=</span><span style="color: blue">"css-js/ui/jq.ui.js"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span> <span style="color: red">src</span><span style="color: blue">=</span><span style="color: blue">"css-js/jq.mobi.js"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue">function</span> sendSearchTerm(){ <br /> <span style="color: blue">var</span> inputString = $(<span style="color: #a31515">"#term"</span>).val(); <br /> <span style="color: blue">var</span> dropdown = document.getElementById(<span style="color: #a31515">"itemNum"</span>); <br /> <span style="color: blue">var</span> index = dropdown.selectedIndex; <br /> <span style="color: blue">var</span> inputNumber = dropdown.options[index].value; <br /> <br /> <span style="color: blue">if</span>(inputString == <span style="color: #a31515">""</span>) <br /> { <br /> alert(<span style="color: #a31515">"Please enter search term."</span>); <br /> } <br /> <span style="color: blue">else</span> <br /> { <br /> jsInterface.callSearchService(inputString, inputNumber, <span style="color: #a31515">"getResult"</span>); <br /> } <br /> } <br /> <span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">style</span><span style="color: blue">></span> <br /> .info{ <br /> display: block; <br /> line-height: 22px; <br /> padding: 0 5px 5px 0; <br /> color: #36558e; <br /> } <br /> #finding{ <br /> height: 152px; <br /> padding: 80px 0 0 30px; <br /> background: url('img/search.png') transparent no-repeat 0 0;<br /> margin: 30px auto; <br /> } <br /> <span style="color: blue"></</span><span style="color: #a31515">style</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">head</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">body</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"search"</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"finding"</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">label</span> <span style="color: red">for</span><span style="color: blue">=</span><span style="color: blue">"input"</span> <span style="color: red">class</span><span style="color: blue">=</span><span style="color: blue">"info"</span><span style="color: blue">></span>Search <br /> <span style="color: blue"><</span><span style="color: #a31515">strong</span> <span style="color: red">style</span><span style="color: blue">=</span><span style="color: blue">"color:red"</span><span style="color: blue">></span>e<span style="color: blue"></</span><span style="color: #a31515">strong</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">strong</span> <span style="color: red">style</span><span style="color: blue">=</span><span style="color: blue">"color:blue"</span><span style="color: blue">></span>b<span style="color: blue"></</span><span style="color: #a31515">strong</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">strong</span> <span style="color: red">style</span><span style="color: blue">=</span><span style="color: blue">"color:#ffcc00"</span><span style="color: blue">></span>a<span style="color: blue"></</span><span style="color: #a31515">strong</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">strong</span> <span style="color: red">style</span><span style="color: blue">=</span><span style="color: blue">"color:green"</span><span style="color: blue">></span>y<span style="color: blue"></</span><span style="color: #a31515">strong</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">label</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">input</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"text"</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"term"</span> <span style="color: red">name</span><span style="color: blue">=</span><span style="color: blue">"term"</span><span style="color: blue">></span> <br /> number of items: <br /> <span style="color: blue"><</span><span style="color: #a31515">select</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"itemNum"</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"1"</span><span style="color: blue">></span>1<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"2"</span><span style="color: blue">></span>2<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"3"</span><span style="color: blue">></span>3<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"4"</span><span style="color: blue">></span>4<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"5"</span><span style="color: blue">></span>5<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"6"</span><span style="color: blue">></span>6<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"7"</span><span style="color: blue">></span>7<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"8"</span><span style="color: blue">></span>8<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"9"</span><span style="color: blue">></span>9<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">option</span> <span style="color: red">value</span><span style="color: blue">=</span><span style="color: blue">"10"</span><span style="color: blue">></span>10<span style="color: blue"></</span><span style="color: #a31515">option</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">select</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">button</span> <span style="color: red">onclick</span><span style="color: blue">=</span><span style="color: blue">"sendSearchTerm()"</span><span style="color: blue">></span>Search<span style="color: blue"></</span><span style="color: #a31515">button</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">body</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">html</span><span style="color: blue">></span></span></pre></div></pre></div></pre></div></pre></div></pre></div><br /><div style="text-align: left" dir="ltr" trbidi="on">This HTML contains two input elements for input search term and select list for number of search items. JScript function <i>sendSearchTerm</i> reads values from input fields and sends that to Java <i>callSearchService</i> method. </div><br /><p style="text-align: left" dir="ltr" trbidi="on">Second page will display search results: </p><br /><div style="color: black; background-color: white"><pre><span style="color: blue"><!</span><span style="color: #a31515">DOCTYPE</span> <span style="color: red">html</span><span style="color: blue">></span> <br /><span style="color: blue"><</span><span style="color: #a31515">html</span><span style="color: blue">></span> <br /><span style="color: blue"><</span><span style="color: #a31515">head</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">meta</span> <span style="color: red">charset</span><span style="color: blue">=</span><span style="color: blue">"ISO-8859-1"</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span> <span style="color: red">src</span><span style="color: blue">=</span><span style="color: blue">"css-js/ui/jq.ui.js"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span> <span style="color: red">src</span><span style="color: blue">=</span><span style="color: blue">"css-js/jq.mobi.js"</span><span style="color: blue">></span><span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> $(document).ready(<span style="color: blue">function</span> () { <br /> jsInterface.getSearchedItems(); <br /> }); <br /> <span style="color: blue">function</span> getResult(innerHtml){ <br /> $(<span style="color: #a31515">"#result"</span>).html(innerHtml); <br /> } <br /> <span style="color: blue"></</span><span style="color: #a31515">script</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">style</span> <span style="color: red">type</span><span style="color: blue">=</span><span style="color: blue">"text/css"</span><span style="color: blue">></span> <br /> .resultItem{ <br /> border: 1px solid #60672B; <br /> } <br /> <span style="color: blue"></</span><span style="color: #a31515">style</span><span style="color: blue">></span> <br /><span style="color: blue"></</span><span style="color: #a31515">head</span><span style="color: blue">></span> <br /><span style="color: blue"><</span><span style="color: #a31515">body</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">div</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">label</span><span style="color: blue">></span>Searched items:<span style="color: blue"></</span><span style="color: #a31515">label</span><span style="color: blue">></span> <br /> <span style="color: blue"><</span><span style="color: #a31515">div</span> <span style="color: red">id</span><span style="color: blue">=</span><span style="color: blue">"result"</span><span style="color: blue">></span><br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span> <br /> <span style="color: blue"></</span><span style="color: #a31515">div</span><span style="color: blue">></span> <br /><span style="color: blue"></</span><span style="color: #a31515">body</span><span style="color: blue">></span> <br /><span style="color: blue"></</span><span style="color: #a31515">html</span><span style="color: blue">></span><br /></pre></div><br /><div style="text-align: left" dir="ltr" trbidi="on">At a page load, <i>$(document).ready</i> function is called and Java <i>getSearchedItems</i> method gets executed. From this execution <i>getResult</i> function is called in callback and it will load results as innerHtml to "result" <i>div</i> element. <br></div><br /><h3 style="text-align: left" dir="ltr" trbidi="on"> </h3><br /><h3 style="text-align: left" dir="ltr" trbidi="on">Conclusion</h3><br /><div style="text-align: left" dir="ltr" trbidi="on"><br>Voila! You just created Android hybrid application with connection to eBay service.<br>Through this tutorial I showed how to work with Android hybrid application using HTML and jQuery and how to expand Android functionality using web service clients. The purpose of this tutorial was to give some insights of working with web service clients and make your mobile apps a little more advanced. </div> Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com12tag:blogger.com,1999:blog-209337246847216621.post-38476298624957017342012-01-29T15:54:00.000+01:002012-01-29T17:12:18.448+01:00Development of Android application using native Android, jQ.Mobi and HTML<link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css"></link>
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css"></link>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js" type="text/javascript">
</script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js" type="text/javascript">
</script>
<script language="javascript">
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
</script>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br/><br/>
<h3>Introduction</h3><br/>
<p>In this tutorial we'll develope a simple Andorid application using combination of native Android development, <a href="http://jqmobi.com/">jQ.Mobi</a> framework
and HTML. Application sample can be downloaded from this <a href="https://rapidshare.com/files/3657420456/FruitApp.zip">link</a>.</p>
<p>The main point of this tutorial is too use adventages of HTML and JavaScript for UI design, and native Android development
and Java language for business logic development.
For UI development, we'll use jQ.Mobi framework and HTML. JQ.Mobi is an <a href="http://www.w3schools.com/html5/">HTML5</a> optimized rewriting JQuery JavaScript library, which offers
way much faster execution than some other JS frameworks (JQuery Mobile, Zepto...). It is compatible for Andorid and iPhone platforms.
</p>
<p>The basic concept of this sample lies in integration of HTML/JavaScript based UI with Android Java backend.
Andorid provides a generic way of exposiong Android Java objects in JavaScript code through interface that is registered using WebView class.
This interface provide us a set of abilities:</p>
1. accessing Java methods from JavaScript<br/>
2. accessing HTML/JavaScript from Java code<br/>
3. parameter data types in method calls between Java-JavaScript
<br/>
<br/>
<h3>Screen flow</h3><br/>
<p>This very simple aplication will contain two HTML pages. First page will be used for saving fruit data in Andorid SQLite database and the
second page will show all fruits from database table.</p>
<table>
<tr><td><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk-hEOP7mt6yhXfxqEy5E6wXH3mRNa36ZAmD0GpLrklYWzaeA3C9PZPh1CAQL_VKws2IHMqsyUNrEYGuOYsDwiuRWWDbMYR2GlINKRCPgwFgj2ExFnF83U4XswCe6vZ3VeO8IUhGVdrX0/s1600/FruitApp01.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"><img border="0" height="320" width="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk-hEOP7mt6yhXfxqEy5E6wXH3mRNa36ZAmD0GpLrklYWzaeA3C9PZPh1CAQL_VKws2IHMqsyUNrEYGuOYsDwiuRWWDbMYR2GlINKRCPgwFgj2ExFnF83U4XswCe6vZ3VeO8IUhGVdrX0/s320/FruitApp01.png" /></a></div>
</td>
<td>First page (index.html) - Add new fruit</td></tr>
<tr><td><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42h5YccyDiMz4xQAL2DXc1fETttTrW3tscOcY3rDQA5RNLsRmk0HU9Lj0P2V6JXMqxNksrYI8tlLvXDJfvr-zP5t_3kzau5xQQ2h_XANBBiPx8QRSPYYMQLv_2tIMI8ENwLOaViGncRE/s1600/FruitApp02.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"><img border="0" height="259" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi42h5YccyDiMz4xQAL2DXc1fETttTrW3tscOcY3rDQA5RNLsRmk0HU9Lj0P2V6JXMqxNksrYI8tlLvXDJfvr-zP5t_3kzau5xQQ2h_XANBBiPx8QRSPYYMQLv_2tIMI8ENwLOaViGncRE/s320/FruitApp02.png" /></a></div>
</td>
<td>Second page (viewall.html) - View all added fruits</td></tr>
</table>
<br/>
<h3>Database access</h3><br/>
<p>First, create a new Andorid project in <a href="http://www.eclipse.org/">Eclipse</a>. After that, create a new package where we'll add some classes for database access.
Create a new class named <i>DataSQLHelper</i> that will extend <i><a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html">SQLiteOpenHelper</a></i> class.</p>
<pre class="brush: java">
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
import android.util.Log;
public class DataSQLHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "fruitapp.db";
public static final int DB_VERSION = 1;
public static final String TABLE_FRUIT = "fruit";
//columns
public static final String FRUIT_NAME = "fruit_name";
public static final String FRUIT_NUMBER = "fruit_number";
public DataSQLHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE " + TABLE_FRUIT +" ( "
+BaseColumns._ID+" integer primary key autoincrement, "+
FRUIT_NAME+" text, "+
FRUIT_NUMBER+" int)";
Log.d("FruitData","onCreate: "+sql);
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
}
</pre>
<p>After creating first instance of this class, <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html">SQLite </a>will create new database called "fruitapp.db".
Method <i>onCreate(SQLiteDatabase db)</i> will add table "fruit" to previosly created database.</p>
<p>FruitEntity class is used as a representation of database table.</p>
<pre class="brush: java">
public class FruitEntity {
private long id;
private String name;
private int number;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
</pre>
<p>Another class called <i>DBRepository</i> contains methods for inserting fruit data in "fruit" database table - <i>insertFruit(String dbtable, Context context, FruitEntity fruit)</i>. It also contains method
<i>getFruits(String dbtable, Context context)</i> which returns <a href="http://www.json.org/">JSON </a>String representation with all records from "fruit" table. For purpose of parsing JSON objects in this sample was used
<a href="http://jackson.codehaus.org/">Jackson JSON processor</a>.</p>
<pre class="brush: java">
import java.io.StringWriter;
import java.util.ArrayList;
import org.codehaus.jackson.map.ObjectMapper;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import org.fruit.db.FruitEntity;
import org.fruit.db.DataSQLHelper;
public class DBRepository{
DataSQLHelper sqlHelper;
public DBRepository(Context context){
this.sqlHelper = new DataSQLHelper(context);
}
//returns Cursor for reading reocrds from database table
public Cursor getCursor(String dbtable, Context context){
SQLiteDatabase db = sqlHelper.getReadableDatabase();
Cursor cursor = db.query(dbtable,null,null,null,null,null, null);
return cursor;
}
public String getFruits(String dbtable, Context context){
Cursor cursor = getCursor(dbtable, context);
StringWriter ret = new StringWriter();
ArrayList<FruitEntity> fruits = new ArrayList<FruitEntity>();
while(cursor.moveToNext()){
FruitEntity t = new FruitEntity();
t.setId(cursor.getLong(0));
t.setName(cursor.getString(1));
t.setNumber(cursor.getInt(2));
fruits.add(t);
}
try{
//using jackson mapper for generating JSON object
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(ret, fruits);
}catch(Exception e){
e.printStackTrace();
}
closeDB();
return ret.toString();
}
public void insertFruit(String dbtable, Context context, FruitEntity fruit){
SQLiteDatabase db = sqlHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DataSQLHelper.FRUIT_NAME, fruit.getName());
values.put(DataSQLHelper.FRUIT_NUMBER, fruit.getNumber());
db.insert(DataSQLHelper.TABLE_FRUIT, null, values);
closeDB();
}
public void closeDB(){
sqlHelper.close();
}
}
</pre>
<br/><br/>
<h3>Main Activity class</h3><br/>
After creating new Project in Eclipse, go to your main <a href="http://developer.android.com/guide/topics/fundamentals/activities.html">Activity </a>class and add this code:
<pre class="brush: java">
import org.fruit.db.DBRepository;
import org.fruit.db.DataSQLHelper;
import org.fruit.db.FruitEntity;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.webkit.WebView;
public class FruitAppActivity extends Activity {
WebView webView;
DBRepository dbRepository;
private Handler handler = null;
private static final String HTML_ROOT = "file:///android_asset/www/";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webView = new WebView(this);
setContentView(webView);
webView.getSettings().setJavaScriptEnabled(true);
dbRepository = new DBRepository(this);
handler = new Handler(); //creates handler instance for page loading
webView.addJavascriptInterface(this, "fruitInterface");
loadPage("index.html");
}
public void loadPage(String in){
final String url = HTML_ROOT + in;
loadURL(url);
}
//Loads pages and executes JavaScript.
private void loadURL(final String in){
handler.post(new Runnable() {
public void run() {
webView.loadUrl(in);
}
});
}
}
</pre>
<p>In <i>onCreate</i> method we create new <a href="http://developer.android.com/guide/webapps/webview.html">WebView </a>component that will be used for HTML preview and JavaScript execution. We'll also need to enable JavaScript for WebView component.
In the next step, we'll create an instance of BDRepository class. Creating this instance, it will be created fruitapp.db database with "fruit" table. After that, we'll register "fruitInterface" for current context. This JavaScript interface represents the interface
that will be used for calling Java methods from JavaScript, and vice versa. In the end, we'll load index page.</p>
<p>
Add additonal methods to main Activity class:
<pre class="brush: java">
public void addNewFruit(String fruit_name, String fruit_num){
FruitEntity fruit = new FruitEntity();
fruit.setName(fruit_name);
fruit.setNumber(Integer.parseInt(fruit_num));
dbRepository.insertFruit(DataSQLHelper.TABLE_FRUIT, this, fruit);
}
public void sendResultToJavaScript(String callback){
String result = dbRepository.getFruits(DataSQLHelper.TABLE_FRUIT,this);
final String callbackFunction = "javascript:" + callback + "('" + result + "')";
loadURL(callbackFunction);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()){
webView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
</pre>
<p>
Method <i>addNewFruit</i> is used to insert data from HTML form into database table. On the other hand, method <i>sendResultToJavaScript</i> is used to read all the records from
"fruit" table in form of JSON representation and send JSON string to HTML by sending it like argument of javascript function.
Both of these methods will be called from JavaScript using JavaScript interface.
</p>
Override method <i>onKeyDown</i> to define event on click of back button. In our case, default behavior is to go to previuos page.
<br/><br/>
<h3>Adding HTML pages and JavaScript</h3><br/>
<p>
In <i>assets</i> create folders <i>www</i> and <i>css-js</i>:
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHMGp_eLdl4_5Jb5XQeNoGy5cOH-mLOMK21JtObQVaLZQIZRCviihJ6AcCzwdN7x0WPT9kQ3AN3O7agzeJtbEzxdzPTLyn_P6cn8Yp0onhc8WeGaAcG-guSV1BqUaDMNuDG4U7_6nOMC8/s1600/assets+folder.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"><img border="0" height="184" width="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHMGp_eLdl4_5Jb5XQeNoGy5cOH-mLOMK21JtObQVaLZQIZRCviihJ6AcCzwdN7x0WPT9kQ3AN3O7agzeJtbEzxdzPTLyn_P6cn8Yp0onhc8WeGaAcG-guSV1BqUaDMNuDG4U7_6nOMC8/s320/assets+folder.png" /></a></div>
In folder <i>css-js</i> add exported files from downloaded jQ.Mobi archive.
</p>
<p>
In folder <i>www</i> create new "index.html" page. In this case, it was used HTML 5, but you can use any version of HTML.
</p>
<pre class="brush: html">
<!--<!DOCTYPE html>
<html>
<head>-->
<meta charset="ISO-8859-1">
<link rel="stylesheet" href="css-js/kitchensink/jq.ui.css" />
<script src="css-js/ui/jq.ui.js"></script>
<script src="css-js/jq.mobi.js"></script>
<!--</head>
<body>-->
<div id="header"><h1>Add fruit</h1></div>
<div id="content">
<form id="form">
<table>
<tr>
<td><label id="lbl_name">Fruit Name: </label></td>
<td><input type="text" id="fruit_name"/></td>
</tr>
<tr>
<td><label id="lbl_number">Fruit Number: </label></td>
<td><input type="number" id="fruit_num" min="0"/></td>
</tr>
<tr>
<td><button id="btn_viewall" onClick="goToAllRecordsPage()">View all</button></td>
<td><button id="btn_save" onClick="saveFruit()">Save</button></td>
</tr>
</table>
</form>
</div>
<!--</body>-->
<script>
function saveFruit(){
var fruit_name = $("#fruit_name").val();
var fruit_num = $("#fruit_num").val();
if(fruit_name!="" && fruit_num!=""){
fruitInterface.addNewFruit(fruit_name,fruit_num);
}else{
alert("Please fill all the fields.");
}
clearFields();
}
function goToAllRecordsPage(){
fruitInterface.loadPage('viewall.html');
}
function clearFields(){
var fruit_name = $("#fruit_name");
var fruit_num = $("#fruit_num");
fruit_name.text("");
fruit_num.text("");
}
</script>
<!--</html>-->
</pre>
<p>
In "head" tag we add css and jQ.Mobi libraries. After that, create simple form with basic input fields and buttons.
In the end, add JavaScript functions.
</p>
<p>
<ul>
<li><i>saveFruit</i> function reads values from input fields and use it as arguments in Java method <i>addNewFruit</i> call.
Notice that for Java method calls, we use interface that we added before in our Activity class.</li>
<li><i>goToAllRecordsPage</i> function redirects to next page.</li>
<li><i>clearFields</i> function clears values from input fields.</li>
</ul>
</p>
In folder <i>www</i> create another HTML page called "viewall.html".
<pre class="brush: html">
<!--<!DOCTYPE html>
<html>
<head>-->
<meta charset="ISO-8859-1">
<link rel="stylesheet" href="css-js/kitchensink/jq.ui.css" />
<script src="css-js/ui/jq.ui.js"></script>
<script src="css-js/jq.mobi.js"></script>
<!--</head>
<body>-->
<div id="header"><h1>All fruits</h1></div>
<div id="content">
<label>Records:</label>
<br/>
<ul id="fruits">
<!-- <li> elements will be added using java script method getRecords-->
</ul>
</div>
<!--</body>-->
<script>
$(document).ready(function () {
fruitInterface.sendResultToJavaScript('getRecords');
});
function getRecords(resultText){
var fruitList = $("#fruits");
var tmpJson = $.parseJSON(resultText);
if(tmpJson!=null){
for(var i=0; i<tmpJson.length; i++){
var fruit_name = (tmpJson[i]).name;
var fruit_number = (tmpJson[i]).number;
var listItem = '<li data-role="list-divider">'+fruit_name+" - "+fruit_number+'</li>';
fruitList.append(listItem);
}
}
fruitList.listview('refresh');
}
</script>
<!--</html>-->
</pre>
<p>
Again, in the "head" tag we add css and jQ.Mobi libraries. In body part, add an unordered list element that will be used to display fruit data.
</p>
<p>
After page loads, Java <i>sendResultToJavaScript</i> method will be called. As argument of this method we use name of JavaScript method that we'll be invoked.
JavaScript function <i>getRecords</i> we'll parse JSON result set and add records data to list items.
</p>
<br /></div>Anonymoushttp://www.blogger.com/profile/16041111446838284611noreply@blogger.com2