Shopper App, Hello Android #6

Welcome,

to the 6th posting.
The serverside implementation isn’t really finished at all but now it’s time to begin with the android client :) I will finish those things which are missing on the serverside when it is needed.

ANDROID

I will develop and test my application on a Samsung Galaxy S. If needed one could also use the eclipse build-in Emulator for android devices. But to get a better feeling of the “look&feel” it is better to develop and test your application on a real device.
I think it’s not neccessary to explain what it is, what it makes cause everybody knows it, but there still a few things that are interesting:

Android is based on a Linux kernel and provides a comfortable Java programming interface. To adept which java packages are supported on android one can take a look at the developer website where the entire Android API is listed. One special thing to mention is that the Android platform has its own Java Virtual Machine (DVM – Dalvik Virtual Machine), so it is not possible to run standard Java bytecode on Android. Instead of it one have to use the special Android compiler to create bytecode for the DVM. Fortunally there exists, like for many purposes, a wonderful Android Eclipse Plugin (ADT – Android Development Tools) which makes it very easy to dive into the development process on android :) GREAT!
The Android fundamentals consist of some central features and components which are Activities, Services, Broadcast Receivers, Content Providers and Intents. To understand the operating principle of android i will give a short overview of these components:

Activities - You can imagine an activity as a single screen on the android device, which contains the User Interface. An application can consist of just one or several activities which contain some visual User Interface Elements called Views.

Services - Different from Activities a so called Service does not have any User Interface and is not visual to the user. It performs  ”longtime-tasks” in the background. All components are instantiated in the main thread and calls to some events and callback functions also run in the main thread of the process. Therefore, long-task-operations like networking operations or computation loops, should not be performed in an Activity but in a Service, otherwise it would could block the comonents for a non acceptable timeperiod which causes the application to be nasty to use. Android provides some classes for managing thread for this purpose. Looper, Handler and HandlerThreads.

Broadcast ReceiversBroadcast Receivers do also not have any UI, but they are here to accept announcements form the system, like “the timezone has changed”, “the battery status is low” or whatever. It is also possible to initiate your own Broadcast Receivers in your own application to let other applications know that something is happen.

Content Providers – They make some sort of information data available for other applications. This data can be stored in a SQLite database or in the file system or wherever.

Intents - Intents are a very interesting concept, which causes your application to be very uncoupled and maintainable. They are like asynchronous messages which are used for activating activities, services and broadcast receivers. An intent is, so to say, an “intention” that is used to tell the system what to do. For example the intention to read a specific contact out from the contacts application. Applications can register themeselves through an intent-filter so the platform itself can decide which component is the most suitable for the requested intention. It does so by comparing the Intent object to the intent filters of potential targets. On the other hand it is also possible to make the Intent explicitly so Android just have to search the requested component and activate it.

So by understanding what these concepts means (in term of android) let’s begin with coding on Android :)

I decided that i will first implement a main entry point, a main menu for the shopper application, like in many other apps where the user can tip on a icon to do something.
User Interface layouts and views can be declared in xml files in the folder res/layout. Alternatively there exists a grafical editor for editing the xml layout but many things don’t work correctly and for better understanding i edit my xml layout file manually :) So, let’s take a first look at the main xml layout file of our shopper main menu:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ImageView
    android:id="@+id/headline"
   	android:src="@drawable/headline"
   	android:layout_width="wrap_content"
   	android:layout_height="wrap_content" />

<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/gridview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:numColumns="2"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:gravity="center"
/>
</LinearLayout>

The Main Menu activity contains a vertical LinearLayout to place the header and the menuicons. As you can see the icons are placed in a socalled GridView which is able to situate views in a grid order via an Adapter. Every Xml element has a bunch of attributes  for setting up the component. Icons are stored in the res/drawable folder and can be referenced via the xml file or programmatically. Here is the result of the above xml file and the Adapter :

As said, this is the Main Screen of the Shopper App. Icons design and some other details could (and may will) change in future, but this is the basic layout. Different from iphone apps, android apps have to run on a lot of different devices, with different hardware especially with different screen resolutions. For this case there exists guidelines for creating the graphical user interface elements to help you out so that your app would look good on all devices. For example I have to store the menu icons in three different sizes. One single icon has to be stored for low density screens (ldpi), which should have a size of 36×36, for the medium density screens (mdpi) with a size of 48×48 and finally for high density screens (hdpi) like the samsung galaxy s with a icon size of 72×72. This guarantee that no icon has to be streched or clinched too much to look good and to have the right size on the device.

Ok, so this is our first and main activity. Now let’s take a look how we can switch to another screen (another activity) by touching one of the icons, for example the “new group” icon, via an Intent. Every icon in the grid has a specific position represented as an Integer value. The “new group” icon has the value 0, “join group” 1 and so on. Note that the “new purchase” icon does not have the value 2, because the textdescription below the icons are just graphics too which lies in the grid. So the “new purchase” icon will have the value 4. Every icon is setup with an ClickListener and when the icon is clicked we can find out which icon was clicked via the position value. Here is the little “onclick” Method which will, for now, react just on position 0, the new group icon and start the specific activity.


public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

	switch (position) {
	   case 0:
	        Intent i = new Intent(MainMenu.this, NewGroupActivity.class);
		startActivityForResult(i, ACTIVITY_NEW_GROUP);
	        break;

	   case 1:
		// TBA
	}
}

Here the “Intent-Concept” comes into play. This is an explicit Intent because it names the Activity class directly instead of letting android take care of the best Activity for the intention (via an intent filter ;) ). You could start the specific Activity either with the startActivity() or the startActivityForResult() method. The first is a fire-and-forget approach while the second lets you inform the caller activity through a callback method called onActivityResult(). ACTIVITY_NEW_GROUP is a constant which is returned from the callee Activity to the onActivityResult()-Method in order to recognize which activity was called. This intent leads us to a new activity where the user can simply insert the groupname and hit the OK button to create the group on the server. (RESTful)

Let’s take a look at the code of the Listener Method of the “OK” button. There are just a few really usefull code examples of how to make Http RestCalls out of the android platform so this code-snippet could be very interesting to you. :)

mOkBtn.setOnClickListener(new View.OnClickListener() {

			public void onClick(View view) {

				String contentToSend = mGroupnameTxt.getText().toString()
						.trim();

				DefaultHttpClient httpClient = new DefaultHttpClient();

				HttpHost targetHost = new HttpHost(TARGET_DOMAIN, 80, "http");

				HttpPost httpPost = new HttpPost(URL_TO_SEND_REQUEST);

				// httpPost.addHeader("Accept", "text/plain");

				String result = "";
				try {
					StringEntity entity = new StringEntity(contentToSend,
							"UTF-8");
					entity.setContentType("text/plain");
					httpPost.setEntity(entity);

					HttpResponse response = httpClient.execute(targetHost,
							httpPost);

					HttpEntity httpentity = response.getEntity();

					InputStream instream = httpentity.getContent();
					BufferedReader reader = new BufferedReader(
							new InputStreamReader(instream));
					StringBuilder sb = new StringBuilder();

					String line = null;

					while ((line = reader.readLine()) != null) {
						sb.append(line + "\n");
					}

					result = sb.toString();
					Toast.makeText(NewGroupActivity.this, result,
							Toast.LENGTH_LONG).show();

					if (response.getStatusLine().getStatusCode() != 500) {
						finish();
					}

				} catch (Exception ex) {
					ex.printStackTrace();
					result += ex.getMessage();
					Toast.makeText(NewGroupActivity.this,
							"Exception " + result, Toast.LENGTH_LONG).show();
				}

			}

		});

Creating a new group is the very simplest case and just consists of making a simple http Rest call to the shopper server with the groupname as text/plain content. First we have to fetch the content from the EditText-View and preventively trim it. Then we instantiate a DefaultHttpClient Object and a HttpHost Object which holds all the variables needed to describe a HTTP connection. This includes remote host name , port and the scheme. We want to make POST call to the server so we need the HttpPost object with the URL to the connection point. (at the moment http://1.latest.pms-server.appspot.com/rest/groups/new). The content which should be sent to the server is wrapped in a StringEntity Object and contains the String content (the groupname) and the encoding. Next we have to set the MiMe type (text/plain in this case) and bin dthe StringEntity to our HttpPost Object. Now it’s time to make the call via the execute() method. Attention! This is a blocking method which makes everything in the same thread stop while the call has not finished. Generally such calls are processed in a Service but this is a very very simple case which should not take a long time so i keep it in the main thread. Other calls, like getting the purchases etc. will be handled in a Service then. When the call is finished its “result” is stored into a HttpResponse Object, especially in the HttpEntity Object. From here we can get a common inputstream and read out the content. At the end we see an if-condition. Say, the groupname just exists the server response a) with the responsemessage “This group already exists” and b) with the Http status code 500 which stands for an internal error.

There is still one tiny but important thing to do to keep the code working. We have to tell the android platform that our application needs the permission to access to the internet. This can be done in the AndroidManifest.xml file with an entry: <uses-permission android:name=”android.permission.INTERNET”></uses-permission>.

In the next post (#7) we will take a look how to construct a menu for preferences (when the user hits the menu button on the phone), how we can easily store information pairs (SharedPreferences) and take a look at the next Activities (joning the group, fetching the purchases, ….)

cheers,

bernd

, , , , ,
  • Delicious
  • Facebook
  • Digg
  • Reddit
  • StumbleUpon
  • Twitter

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>