Android LogoFor the past two days, I have been showing you how to create your own Android apps. On day one, I showed you how to download and install the Java Development Kit (JDK), Eclipse, and the Android SDK. I even showed you how to create an Android virtual device and how to configure it to mimic your own actual device. On day two, I showed you how to configure Eclipse to work with the Android SDK and the Android virtual device (AVD) you created on day one. Today, I will be showing you how to make your application do something by adding IDs to objects in your layout and how to access those objects in code. As described in yesterday’s article, I am creating an Android application that allows me to test that my servers are online and accessible using a simple UDP client which will talk to my servers where I have a UDP server listening. Also mentioned in that article, I promised I would show you what my layout looks like. So, that is where we will begin today’s article which will be the third article of a multi-article series where I will teach you how to build your own Android apps, how to deploy your apps to physical devices such as cellphones and tablets, how to get your apps listed on Google Play, and even how to make money with your apps by including ads in them. So, let’s begin.

Since my app is extremely simple with only one function, I didn’t need to worry too much about the look of it. Instead, I kept it very basic and only included the pieces I need to make my app useful. As you can see below, I have included fields for adding the IP address of the server I want to test along with the port number my UDP server is listening on. I have also included a text box that allows me to enter a message to send to my UDP server as well as a text box for receiving a reply from the server. There is also one single button that will allow me to send my outgoing UDP message to my server. You will also notice that I have intentionally left a little bit of a gap at the top of my layout. That empty space is where I plan on placing my ads which we will get to on day 5 of this series.

UDP Tester Layout

CLICK TO ENLARGE

Whenever you are working with objects that the user needs to interact with, it is advised to create meaningful IDs that easily identify each object. In my case, I have four text fields and one button. So, I had to create meaningful IDs that I can use later on in my Java code. To setup your IDs, click each field one at a time and modify the auto-generated ID on the Properties panel. For example, when I click on the text box that contains the IP address for the server I want to test, I can go to the Properties panel and change the ID to something like “@+id/txt_dest_ip”.

Even though you can click on any object that accepts text and add the text directly to the object via the Properties panel, Google’s best practices advises that you setup string variables. Not only does this help for when you want to reuse the same text in other locations. But, it also helps for when / if you decide to implement localization. By using string variables throughout your app, you can easily swap text in your app from one language to another. Since I’m only planning on supporting English at this time, I won’t go into how to setup your app for localization. I’ll save that for another article. However, I will still use string variables as opposed to adding labels and text directly to the Properties panel.

One way you can add string variables is by selecting an object on your form such as a label or an edit box and clicking the button next to the Text field in the Properties panel. This will bring up a dialog window that will allow you to pick from currently existing variables. If you need some text that isn’t already in the list, you can click the “New String…” button which will open another dialog window which will assist you with creating new strings. Personally, I don’t like messing with all of that. Instead, I know that all of my string variables are stored in the “strings.xml” file located under the res/values folder. When you first create your new Android application using the new Android Application Wizard, Eclipse will add a couple of string variables for you. To create new variables, you can simply copy one of the existing variables, paste it on a new line, change its name, and change its text. You can also just type out the entire line by hand if you prefer.

strings.xml example

CLICK TO ENLARGE

Even though the name implies one thing, the strings.xml file can also be used for more than just storing text for labels and such. For example, in my example below, I threw in a couple of <color> tags as well to demonstrate how to create colors which can also be swapped out just like your string variables. You can also store other variables in the strings.xml file such as dimensions, images, items, and arrays. To see what all is possible, type “<” (without the quotes) and press and hold the Ctrl key and press the spacebar. This will display an auto-complete window which will show you the different types of things you can store in the strings.xml file and reuse throughout your application.

strings.xml auto complete

CLICK TO ENLARGE

Once you have defined your strings (and other variables) in the strings.xml file, swap back over to your layout. When there, you can assign your newly created variables to each item on your activity by clicking each item one at a time and selecting the corresponding field on the Properties panel. For example, since I created a new string called “default_dest_ip” and gave it a value of “127.0.0.1”, I want to assign this variable to my txt_dest_ip edit box I created earlier by clicking the “…” button next to the Text field on my Properties panel and selecting default_dest_ip from the list. Again, since I’ve been doing this for a while, it’s easier for me just to go straight to the layout XML and do everything there. Besides, just like in the strings.xml file, you can leverage Eclipse’s auto-complete feature inside your activity XML file by pressing and holding the Ctrl key and pressing the spacebar anywhere in your XML file. Depending on where you are at in the XML file, you will see options that relate to the area of the XML you are editing.

After you are finished laying out your activity the way you want it and have assigned IDs to all of the fields that the user will be interacting with, it is now time to write some code. The first thing we are going to code for will be our menu. When you created your project using the Android Application Wizard, a new menu was auto generated for you under the res/menu folder. By default, it has a menu item for settings. Since my application will not have a settings page, I have decided to change the only menu item in my res/menu/activity_main.xml file to be my exit button instead. So, just like before, I created a new string in my strings.xml file which I named “menu_exit” and gave it a value of “Exit”. Inside my res/menu/activity_main.xml file, I changed the only item in there to have an ID of “@+id/menu_exit” and a title of “@string/menu_exit”. Don’t worry if you misspell any of your variable names at any point in your application. Eclipse will notify you with little red error tags which you can mouseover to reveal the problem. Here is what my res/menu/activity_main.xml file looks like:

activity_main_menu.xml

Next, expand all of the folders under the “src” folder until you see the activity Java file that got created after the new Android Application Wizard finished. When you double-click that file, you will see that a little bit of code has already been generated for you. However, just like everything else, it is up to you to do something with it. Since we are currently working on our menu, I will need to point out the “onCreateOptionsMenu”. If you decided to rename your res/menu/activity_main.xml file at any point, you will also need to change the first line of the onCreateOptionsMenu method to reflect that name change. For example, I typically get res/layout/activity_main.xml confused with res/menu/activity_main.xml. So, to keep from continuously opening the wrong file for editing, I will sometimes rename res/menu/activity_main.xml to something like res/menu/activity_main_menu.xml. Then, I will change the first line of the onCreateOptionsMenu to be “getMenuInflater().inflate(R.menu.activity_main_menu, menu);“. For now I will stick with the default name so that I don’t have to change this too.

Every time your application gets launched, the onCreateOptionsMenu will be triggered which will create your menu. Each activity in your app can have its own menu. Now that you have a menu being created when you launch your app, you will need to tell Android what to do when a user clicks one of your menu items. To do that, you will need to override a function called “onMenuItemSelected”. Inside that method, you will need to add a switch/case statement that checks the ID of the item being clicked and act accordingly. Since my menu only consists of one item, Exit, I will only have one case. That is also where I will call the built-in “finish()” method which will tell Android to close my application and free up the resources that it was using. Here are what my onCreateOptionsMenu and onMenuItemSelected methods look like:

onCreateOptionsMenu & onMenuItemSelected

After I have my Exit menu working, all I have left to do is to add the rest of the code that makes my UDP tester work. Since the remainder of the code is UDP specific, I’m not going to walk you through all of it. However, I have provided all of my code below in case you would like to create a UDP client of your own. That’s all for today. Tomorrow I will show you how to test your application using the Android emulator and the AVD you setup on day one.

package com.prodigy.mobile.android.udptester;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {
	private Thread clientThread;
	
	private EditText txtOutMessage;
	private EditText txtOutIp;
	private EditText txtOutPort;
	private EditText txtInMessage;
	
	private Button btnSend;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		txtOutMessage = (EditText)findViewById(R.id.txt_out_msg);
		txtOutIp = (EditText)findViewById(R.id.txt_dest_ip);
		txtOutPort = (EditText)findViewById(R.id.txt_dest_port);
		txtInMessage = (EditText)findViewById(R.id.txt_recv_msg);
		
		btnSend = (Button)findViewById(R.id.btn_send);
		btnSend.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				clientThread = new Thread(new Client());
				clientThread.start();
			}
		});
	}
	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
	
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId())
		{
			case R.id.menu_exit:
				if (clientThread != null && clientThread.isAlive())
				{
					clientThread.interrupt();
				}
				finish();
				return false;
			default:
				return super.onMenuItemSelected(featureId, item);
		}
	}
	
	class Client implements Runnable
	{
		public Client()
		{
		}
		
		@Override
		public void run() {
			try
			{
				String outMessage = txtOutMessage.getText().toString();
				String outIp = txtOutIp.getText().toString();
				int outPort = Integer.parseInt(txtOutPort.getText().toString());
				
				InetAddress serverAddr = InetAddress.getByName(outIp);
	            DatagramSocket socket = new DatagramSocket();
	            byte[] buf = outMessage.getBytes();
	            DatagramPacket packet = new DatagramPacket(buf, buf.length, serverAddr, outPort);
	            socket.send(packet);
	            
	            byte[] receiveData = new byte[1024];
	            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
	            socket.receive(receivePacket);
	            final String recvMsg = new String(receivePacket.getData()).trim();
	            runOnUiThread(new Runnable()
	            {
					@Override
					public void run() {
						txtInMessage.setText(recvMsg);
					}
	            });
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
	}
}

Create Your Own Android Apps for Fun or Profit
Part 1: Downloading and Installing Java, Eclipse, and the Android SDK
Part 2: Configuring Eclipse and Creating Your First Android App
Part 3: Creating a Layout and Adding Some Code
Part 4: Testing Your App with the Android Emulator
Part 5: Monetizing Your Android App with Google AdMob
Part 6: Running Your Android App on Cellphones and Tablets
Part 7: Publishing Your Android App to the Google Play Store

Grab yourself a copy of my eBook (Android App Development 101) today!

BUY NOW

Related Posts

Tagged with:  

Leave a Reply