Asynchrony Solutions Blog

How to Reuse UI Components Using XML Layouts and the Inflater Service

by on February 28th, 2011 at 3:46 pm

Creating UI components for Android apps programmatically is difficult.  So, the Android framework provides a way to create UI components via XML.  The Eclipse Android SDK actually provides a tool for creating these XML UIs via drag-and-drop/WYSIWYG.  Now developers must manage XML documents along with their Java code, which can also be difficult.  To help alleviate some of these difficulties, the Android framework allows for reusing the XML views via the Inflater Service.

First, let’s define some UI components in XML.

The first XML layout will be the main layout that will be the base of the UI shown to the user. This could also be reused for all the screens as it is just an empty LinearLayout.

res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/main_layout" android:orientation="vertical"
          android:layout_width="fill_parent" android:layout_height="fill_parent">
     <TextView android:text="@string/title" android:layout_width="fill_parent"
               android:layout_height="wrap_content" />
</LinearLayout>

The second XML layout will be used for some text fields for a simple form.

res/layout/personnel_form.xml

<?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="wrap_content">
     <LinearLayout android:orientation="horizontal"
               android:layout_width="fill_parent"
               android:layout_height="wrap_content">
          <TextView android:text="@string/firstname_label"
               android:layout_height="wrap_content"
               android:layout_width="wrap_content" />
          <EditText android:id="@+id/firstname"
               android:layout_height="wrap_content"
               android:layout_width="fill_parent" />
     </LinearLayout>
     <LinearLayout android:orientation="horizontal"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content">
          <TextView android:text="@string/lastname_label"
               android:layout_height="wrap_content"
               android:layout_width="wrap_content" />
          <EditText android:id="@+id/lastname"
               android:layout_height="wrap_content"
               android:layout_width="fill_parent" />
     </LinearLayout>
</LinearLayout>

The final XML layout will be an OK and Cancel button that could be reused for a number of other screens.

res/layout/buttons.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_height="wrap_content" android:orientation="horizontal"
          android:layout_width="fill_parent">
     <Button android:id="@+id/ok_button" android:text="@string/ok"
               android:layout_height="wrap_content"
               android:layout_width="fill_parent" android:layout_weight="1" />
     <Button android:id="@+id/cancel_button" android:text="@string/cancel"
               android:layout_height="wrap_content"
               android:layout_width="fill_parent" android:layout_weight="1" />
</LinearLayout>

Now we get down to obtaining and using an instance of the Inflater Service in the Activity.  To do this, we simply use the getSystemService() method giving it the name of the Inflater Service.

LayoutInflater inflater = (LayoutInflater) context.
     getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Once you have an instance of the Inflator Service, you can call the inflate method giving it the XML layout that you want to use and the root view that you want to append it to.

LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);
inflater.inflate(R.layout.personnel_form, mainLayout)

And finally putting it all together, here’s the Activity…

public class MyTestActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);

          LayoutInflater inflater = (LayoutInflater)
               getSystemService(LAYOUT_INFLATER_SERVICE);

          LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);
          inflater.inflate(R.layout.personnel_form, mainLayout);
          inflater.inflate(R.layout.buttons, mainLayout);

          Button okButton = (Button) findViewById(R.id.ok_button);
          okButton.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                    EditText firstNameText = (EditText) findViewById(R.id.firstname);
                    EditText lastNameText = (EditText) findViewById(R.id.lastname);

                    String message = "Hello, " + firstNameText.getText() + " " +
                         lastNameText.getText() + "!";
                    Toast.makeText(MyTestActivity.this, message, Toast.LENGTH_LONG).
                         show();
               }
          });

          Button cancelButton = (Button) findViewById(R.id.cancel_button);
          cancelButton.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                    MyTestActivity.this.finish();
               }
          });
     }
}

Using this technique, you will be able to reuse portions of UI components for various screens in your Android application.

Tags: , , , ,

Getting started with Google Maps on Android

by on February 3rd, 2011 at 10:59 am

Tutorial: Getting started with Google Maps on Android

If you’re looking to get started with Google Maps on Android, you’ve come to the right place.  The goal of this tutorial is to have a working Google Map on your emulator in 30 minutes or less.

Here’s what you will need for this tutorial:
1. Eclipse with Android SDK/AVD manager installed
2. Google APIs library downloaded using the SDK/AVD manager

These are the steps we will be covering:
1. creating a Google APIs Android project
2. setting permissions in the manifest
3. obtaining a Google Maps API key
4. using a MapView and a MapActivity
5. look at your Google Map

Step 1: creating a Google APIs Android project

First, if you haven’t done this already, download a Google APIs library using the SDK/AVD manager and create an AVD (an Android emulator instance) that uses this library.

If you are creating a new project, then select  File -> New -> Project -> Android -> Android Project.  Choose a Google APIs build target and finish creating your new project.  Run your new project as an Android Application and you should see the familiar “Hello World, <project name>” display on your emulator.

If you are adding the map to an existing project, click on the project and select
Properties -> Android -> then select a Google APIs as your build target

Step 2: setting permissions in the manifest

We are now ready to add two important settings to the project manifest: a usage setting for the Google APIs library and an internet access permission.

The first setting will allow your application to use the Google APIs library.  To edit the manifest, you can either use the built in GUI editor, or manually edit the raw xml.
To add this setting using the GUI editor, go to the Application tab, click add.., Uses Library, and select com.google.android.maps in the name drop down.
To add this setting manually, add
<uses-library android:name=”com.google.android.maps”/>
under the application tag.

The second setting will give your application permission to access the internet.
To add this setting using the GUI editor, go to the Permissions tab, click add.., Uses Permission, and select android.permission.INTERNET.
To add this setting manually, add
<uses-permission android:name=”android.permission.INTERNET” />
under the manifest tag.

Here is an illustration of how your manifest should look when you are done:

<manifest>
<application>
<some other stuff/>
<uses-library android:name=”com.google.android.maps”/>
</application>
<some other stuff/>
<uses-permission android:name=”android.permission.INTERNET” />
</manifest>

Step 3: obtaining a Google Maps API key

This is the most difficult step, and will take a little bit of time.  First, you should understand that when you compile an APK (Android package) and push it to an Android device (even your emulator) it is signed with a certificate.  You will need to retrieve the MD5 fingerprint from this certificate to sign up for an API key.  If you google for “android google maps api key sign up” you should be able to find the Google’s Map API Key sign up page without too much trouble. Their page will provide a brief explanation of this entire process.

To get started, you will need to find the certificate you are using to sign your application.  If you have not added your own keystore, you are likely using a debug keystore.  To see where this keystore is located, go to Eclipse -> Preferences -> Android -> Build -> and you will see the location under Default debug keystore.
Once you have this information, in Linux simply run

keytool -list -keystore <your keystore location>
any names and passwords it asks for will be: android

In Windows, you will probably want to use the keytool.exe provided with Java.  You may get an error if keytool is not in your Windows path. Either add it to your path or run keytool directly from the bin directory in your Java folder.

If done correctly, you should see something like:
Certificate fingerprint (MD5): 94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98

Now, copy 94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98 or whatever your MD5 fingerprint is (should be different) and paste it into google’s sign up box.  You will need a google account to get your key.  Google will give you a success screen with your key and a code snippet that look like this-

Your key is:
0AuNnVn-pYluVNgxpSs6ZD_Cy9KZXMA-qdhbTzA

Here is an example xml layout:
<com.google.android.maps.MapView
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:apiKey=”0AuNnVn-pYluVNgxpSs6ZD_Cy9KZXMA-qdhbTzA”
/>

Step 4: using a MapView and a MapActivity

Now, the final step.  If you created a new project for this tutorial, you can add the MapView code snippet above to the Linear Layout in your main.xml.  Make sure to replace the API Key in the above snippet with your own API Key.  It should look something like this:

<?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”
>
<com.google.android.maps.MapView
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:apiKey=”YOUR API KEY GOES HERE”
/>
</LinearLayout>

Otherwise, simply add this MapView to any other layout like normal.

Last but not least, update the Activity displaying your MapView layout.  Instead of extending Activity, your class should now extend MapActivity. That’s it. You’re done.

Step 5: look at your Google Map

Launch your application.  You should see a map of the United States zoomed out really far.  If instead you get a force close error, make sure you correctly added the Google APIs library setting in Step 2.  If you only see a white grid it could be one of many things.  You could be having an internet outage, you incorrectly added the internet permissions from Step 2, you have an incorrect API Key, or you forgot to use your API Key.  A lot of things can go wrong here.  If things didn’t work out you aren’t the first. Keep trying and don’t give up.

If everything is working, then congratulations and have fun playing with your new Google Map on Android. There are a plethora of other tutorials online to help you take it from here!

Tags:

Thoughts After a Week with the iPhone 4

by on July 14th, 2010 at 11:14 am

Differences from a 3GS
The first noticeable difference about the iPhone 4 is the construction. Gone is the plastic back construction of the previous two iPhone models, replaced by strengthened glass sheets on the front and back with a stainless-steel band around the edge. The screen of the iPhone 4, like that of the 3GS, should be very resistant to scratches, but early reports indicate that the latest model may be more susceptible to cracked glass when dropped, so get a case if you are worried about dropping your phone (that goes for just about any smartphone). The volume buttons and ringer on/off switch feel much more solid than those of the iPhone 3GS, which felt fairly cheap.

Read More of This Post

Tags: , , , , , ,