Quick Start Android Development

Google Android is one of the leading mobile operating systems in use today and open source. Android developers are in great demand now, applications like Flipboard, WhatsApp Messagner & Instragram are changing the way we use information or communicate using our smart phones or tablets.

And not to forget the games like Angry Birds and Subway Surfers. There is lot of potential to make money once we get into Android development.

This is a quick start article for those who want to start development in Android. The focus of the article is application development and not game development.

Who can do Android Development

Developers who know how to use XML and programming using object oriented language like C++ or Microsoft C# and Java developers can feel at home.

What you need to start developing for Android

Android being open source, all development tools are available for free. Download and install the following tools to start development in Android.

1. Android Development Tools (ADT)

Download link: http://developer.android.com/tools/sdk/eclipse-adt.html

ADT is a plugin for Eclipse IDE, Eclipse is again open source and free to download. You don’t need to download Eclipse separately. ADT comes bundle with Eclipse, just download ADT and follow the instructions to install.

2. Genymotion – The faster Android Emulator

Download link: http://www.genymotion.com/

ADT provides a simulator for testing Android applications. While development we’ve two options for testing our applications:

1. Have the target Android device (smart phone or tablet) connected to the PC using a USB cable (enable debugging option on in your device).

2. Use Android Emulator

Android default emulator is painfully slow, so it’s highly recommended to setup Genymotion emulator.

3. SQLiteStudio

Download link: http://sqlitestudio.pl/

All applications need a database to store and retrieve information. Sooner or later you are going to need a database for your app. Android supports SQLite, an open source embedded database system. SQLiteStudio is a Database Manager where you can create and manage database artefacts like tables & views.

Let’s start development

We’re going to create an Expense Tracker app for Android. It’s a simple application that lets the user manage their expense list with details like Expense title, Amount & Paid.

Create SQLite database

We are going to create SQLite database file to be used in our application. Fire up SQLiteStudio and do the following steps:

Select Databases -> Add database from the menu and create a database file called etdata.db3

Create a table called expenses in etdata.db3 with ID, Title, Amount & Paid columns like the following image:

Double click on expenses table and use the Data tab to enter some sample data.

Save and close the database, we’ll use the data file soon in our application.

Creating Android Project

Open Eclipse and select File \ New \ Android Application Project

Type ExtenseTracker in Application Name leave the other options as it is (refer image below) and Click Next

Keep Clicking Next (keeping the default values) until you reach Finish, click Finish to create the project.

Once project is created, you will see the project opened in Eclipse.

Take a close look at Package Explorer (you can open multiple projects at the same time)

The project folder ExpenseTracker consists of several sub folders including:

src – Stores all .java source code files

res – Stores all project resources like images, layout etc.

assets – Stores project assets like text, database etc.

In Android, a project is made up of Activities . An Activity is similar to web page, form or window. We create the layout of the activity using XML and create the Activity class using java.

Be default, the project has created an activity (MainActivity.java) for us with a layout (activity_main.xml).

Right Click on the project and select Run As \ Android Application to run the project in emulator or the connected device.

Copy the database file etdata.db3 we created earlier into the assets folder

Open activity_main.xml file from res\layouts folder and select activity_main.xml tab to view the XML

Remove TextView tag completely and add the below XML:

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="vertical" >

<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content" >

<Button

android:id="@+id/btnNew"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="New Expense" />

</LinearLayout>

<ListView

android:id="@+id/lvExpenses"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

</ListView>

</LinearLayout>

Select Graphical Layout tab, your screen should match the below image:

We’ve created two UI elements in this activity, Button for ‘New Expense’ and ListView for displaying list of expenses.

Create a new .java file in Src folder under com.example.expensestracker and add the following code:

package com.example.expensestracker;

import android.content.ContentValues;

import android.content.Context;

import android.database.Cursor;

import android.database.SQLException;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class DBAdapter {

static final String TAG = "DBAdapter";

static final String DATABASE_NAME = "etdata.db3";

static final int DATABASE_VERSION = 1;

final Context context;

DatabaseHelper DBHelper;

SQLiteDatabase db;

public DBAdapter(Context ctx)

{

this.context = ctx;

DBHelper = new DatabaseHelper(context);

}

private static class DatabaseHelper extends SQLiteOpenHelper

{

DatabaseHelper(Context context)

{

super(context, DATABASE_NAME, null, DATABASE_VERSION);

}

@Override

public void onCreate(SQLiteDatabase db)

{

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

{

}

}

public DBAdapter open() throws SQLException

{

db = DBHelper.getWritableDatabase();

return this;

}

public void close()

{

DBHelper.close();

}

public Cursor getExpenses() throws SQLException

{

return getTableRows("SELECT * FROM expenses");

}

public Cursor getExpense(int id) throws SQLException

{

return getTableRows("SELECT * FROM expenses WHERE ID=" + id);

}

public Cursor getTableRows(String strQuery)

{

return db.rawQuery(strQuery, new String[] {});

}

public long insertExpense(String title, Integer amount, boolean paid)

{

ContentValues initialValues = new ContentValues();

initialValues.put("Title", title);

initialValues.put("Amount", amount);

initialValues.put("Paid", String.valueOf(paid));

db.beginTransaction();

long newId = db.insert("expenses", null, initialValues);

db.setTransactionSuccessful();

db.endTransaction();

return newId;

}

public boolean updateExpense(long rowId, String title, Integer amount, Boolean paid)

{

ContentValues updateValues = new ContentValues();

updateValues.put("Title", title);

updateValues.put("Amount", amount);

updateValues.put("Paid", paid);

db.beginTransaction();

boolean updated = db.update("expenses", updateValues, "ID=" + rowId, null) > 0;

db.setTransactionSuccessful();

db.endTransaction();

return updated;

}

public boolean deleteExpense(long rowId)

{

boolean res = false;

res = db.delete("expenses", "ID=" + rowId, null) > 0;

return res;

}

}

This file contains all database operations and provides user friendly methods to interact with the database like selectExpenses, insertExpense etc.

Open MainActivity.java from Src folder and replace the code with the below following:

package com.example.expensestracker;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.ArrayList;

import java.util.List;

import android.os.Bundle;

import android.app.Activity;

import android.content.Intent;

import android.database.Cursor;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.Menu;

import android.view.View;

import android.view.ViewGroup;

import android.view.View.OnClickListener;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.CheckBox;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.TextView;

public class MainActivity extends Activity {

List<ExpenseType> lstExpense = new ArrayList<ExpenseType>();

ListView lvExpense;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//copy pre-populated sqlite db file to the app data folder

String destDir = "/data/data/" + getPackageName() + "/databases/";

String destPath = destDir + "etdata.db3";

File f = new File(destPath);

if (!f.exists()) {

//---make sure directory exists---

File directory = new File(destDir);

directory.mkdirs();

//---copy the db from the assets folder into the databases folder---

try {

CopyDB(getBaseContext().getAssets().open("etdata.db3"), new FileOutputStream(destPath));

}

catch (FileNotFoundException e) {

Log.i("ExpenseTracker", e.getMessage() + "-in openDataBase method");

}

catch (IOException e) {

Log.i("ExpenseTracker", e.getMessage() + "-in openDataBase method");

}

}

Button btnNew = (Button) findViewById(R.id.btnNew);

btnNew.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Intent i = new Intent("com.example.expensestracker.ExpenseAddActivity");

startActivity(i);

}

});

lvExpense = (ListView)findViewById(R.id.lvExpenses);

fillExpenses();

}

private void fillExpenses()

{

DBAdapter db = new DBAdapter(this);

Cursor cExpense = null;

db.open();

cExpense = db.getExpenses();

lstExpense.clear();

if (cExpense.moveToFirst())

{

do {

lstExpense.add(new ExpenseType(cExpense.getInt(0), cExpense.getString(1), cExpense.getInt(2), Boolean.valueOf(cExpense.getString(3))));

}

while (cExpense.moveToNext());

}

db.close();

lvExpense = (ListView) findViewById(R.id.lvExpenses);

lvExpense.setAdapter(mExpenseAdapter);

}

public void CopyDB(InputStream inputStream, OutputStream outputStream) throws IOException {

//---copy 1K bytes at a time---

byte[] buffer = new byte[1024];

int length;

while ((length = inputStream.read(buffer)) > 0) {

outputStream.write(buffer, 0, length);

}

inputStream.close();

outputStream.close();

}

private BaseAdapter mExpenseAdapter = new BaseAdapter() {

@Override

public int getCount() {

return lstExpense.size();

}

@Override

public Object getItem(int position) {

return null;

}

@Override

public long getItemId(int position) {

return 0;

}

@Override

public View getView(final int position, View convertView, ViewGroup parent) {

View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.expense_item_layout, null);

TextView txtID = (TextView) retval.findViewById(R.id.txtID);

TextView txtTitle = (TextView) retval.findViewById(R.id.txtTitle);

TextView txtAmount = (TextView) retval.findViewById(R.id.txtAmount);

CheckBox chkPaid = (CheckBox) retval.findViewById(R.id.chkPaid);

ImageView imgRemove = (ImageView) retval.findViewById(R.id.imgRemove);

imgRemove.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

removeExpense (position);

}

});

txtID.setText(lstExpense.get(position).ID.toString());

txtTitle.setText(lstExpense.get(position).Title);

txtAmount.setText("$" + lstExpense.get(position).Amount.toString());

chkPaid.setChecked(lstExpense.get(position).Paid);

return retval;

}

};

private void removeExpense(int position)

{

DBAdapter db = new DBAdapter(this);

db.open();

if (db.deleteExpense(lstExpense.get(position).ID))

fillExpenses();

db.close();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.main, menu);

return true;

}

}

In OnCreate event of the activity we are doing the following:

1. Copy the database file to the data folder

2. Add Click event to ‘New Expense’ button and call ExpenseAddActivity activity that consists of layout (expense_add.xml) to add new expense items. We’ll create the activity and layout files soon.

3. Call and create fillExpenses() function that interacts with the database and iterate expenses table to fill the List with expense items, we’ll create ExpenseType class to map with the expenses table records, and finally we connect the ListView lvExpense to the adapter mExpenseAdapter that we will create later.

4. Create CopyDB function that copy the database file

5. Create mExpenseAdapter based in BaseAdapter that is one way of connecting to the ListView control with collection or array objects.

Create ExpenseType.java file in Src folder with the following code:

package com.example.expensestracker;

public final class ExpenseType

{

public Integer ID;

public String Title;

public Integer Amount;

public Boolean Paid;

public ExpenseType(int id, String title, int amount, Boolean paid)

{

ID = id;

Title = title;

Amount = amount;

Paid = paid;

}

}

Create ExpenseAddActivity.java with the following code:

package com.example.expensestracker;

import android.os.Bundle;

import android.app.Activity;

import android.content.Intent;

import android.view.Menu;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.CheckBox;

import android.widget.EditText;

import android.widget.Toast;

public class ExpenseAddActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.expense_add);

Button btnSave = (Button) findViewById(R.id.btnSave);

Button btnCancel = (Button) findViewById(R.id.btnCancel);

btnSave.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

EditText txtTitle = (EditText) findViewById(R.id.txtTitle);

EditText txtAmount = (EditText) findViewById(R.id.txtAmount);

CheckBox chkPaid = (CheckBox) findViewById(R.id.chkPaid);

if (txtTitle.getText().toString().trim().length() == 0) {

Toast.makeText(getApplicationContext(), "EXPENSE TITLE is missing.", Toast.LENGTH_SHORT).show();

return;

}

if (txtAmount.getText().toString().trim().length() == 0) {

Toast.makeText(getApplicationContext(), "AMOUNT is missing.", Toast.LENGTH_SHORT).show();

return;

}

DBAdapter db = new DBAdapter(getApplicationContext());

db.open();

db.insertExpense(txtTitle.getText().toString(), Integer.valueOf(txtAmount.getText().toString()), chkPaid.isChecked());

Intent i = new Intent(getApplicationContext(), MainActivity.class);

startActivity(i);

}

});

btnCancel.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Intent i = new Intent(getApplicationContext(), MainActivity.class);

startActivity(i);

}

});

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.main, menu);

return true;

}

}

This activity uses the expense_add.xml layout file and calls the insertExpense method of DBAdapter and returns to the MainActivity.

Create expense_add.xml in res\layouts folder and add the following tags:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

tools:context=".MainActivity" >

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

<TextView

android:id="@+id/textView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Expense Title" />

<EditText

android:id="@+id/txtTitle"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:ems="10" >

<requestFocus />

</EditText>

<TextView

android:id="@+id/TextView01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Amount" />

<EditText

android:id="@+id/txtAmount"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:ems="10" />

<CheckBox

android:id="@+id/chkPaid"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Paid" />

<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content" >

<Button

android:id="@+id/btnCancel"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Cancel" />

<Button

android:id="@+id/btnSave"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Save" />

</LinearLayout>

</LinearLayout>

</RelativeLayout>

This layout file consists of UI for adding new expense items.

Open AndroidManifest.xml file and add the following content:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.example.expensestracker"

android:versionCode="1"

android:versionName="1.0" >

<uses-sdk

android:minSdkVersion="8"

android:targetSdkVersion="18" />

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

<activity

android:name="com.example.expensestracker.MainActivity"

android:label="@string/app_name" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity

android:name=".ExpenseAddActivity"

android:label="@string/app_name" >

<intent-filter>

<action android:name="com.example.expensestracker.ExpenseAddActivity" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

</application>

</manifest>

We need to add the ExpenseAddActivity activity to AndroidManifest.xml file to be able to call the activity from MainActivity.

Create expense_item_layout.xml in res\layouts folder and add the following tags:

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:clickable="true"

android:focusableInTouchMode="true"

android:longClickable="true"

android:onClick="onClickCaseTypeCard" >

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_margin="4dp"

>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_margin="1dp"

android:background="#fff"

android:orientation="horizontal" >

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_weight="1"

android:orientation="vertical" >

<TextView

android:id="@+id/txtID"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="left"

android:text="1"

android:textSize="15sp"

android:visibility="gone" />

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="4dp"

android:layout_marginTop="4dp"

>

<TextView

android:id="@+id/txtTitle"

android:layout_width="wrap_content"

android:layout_height="fill_parent"

android:layout_margin="1dp"

android:layout_weight="1"

android:background="#ffffff"

android:gravity="left"

android:lines="1"

android:maxLines="1"

android:text="Title"

android:textSize="15sp"

android:textStyle="bold" />

</LinearLayout>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="4dp"

android:layout_marginTop="4dp"

android:gravity="center_horizontal"

android:orientation="horizontal"

android:padding="1dp" >

<TextView

android:id="@+id/txtAmount"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#ffffff"

android:gravity="left"

android:lines="1"

android:maxLines="1"

android:paddingLeft="4dp"

android:paddingRight="4dp"

android:text="Amount"

android:textSize="15sp" />

<CheckBox

android:id="@+id/chkPaid"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:gravity="center_vertical"

android:text="Paid" />

</LinearLayout>

</LinearLayout>

<ImageView

android:id="@+id/imgRemove"

android:layout_width="32dp"

android:layout_height="32dp"

android:src="@drawable/i00cancel" />

</LinearLayout>

</LinearLayout>

</FrameLayout>

This layout file is used to render expense items in ListView.

THAT’S IT…

Run the project in emulator or connected device to see the result. Use ‘New Expense’ to add new expense item.

Press Save to add the new expense to the expense list

Summary

In this article we managed to create a complete app for expense tracking. We have not got deep into each and every step of the code but the code being simple and easy to understand, the same framework can be used to create more complex business applications. It all boils down to layout files with UI widgets (Textbox, Buttons and List controls) and Activities (Java files) that are similar to web pages.

By Shameem Ahmed   Popularity  (4736 Views)