Create a currency converter application using Yahoo! API
DownloadKeywords: ConnectivityManager HttpGet XmlPullParser SAXParser SimpleCursorAdapter SQLiteDatabase ContentProvider SQLiteQueryBuilder BroadcastReceiver IntentService AChartEngine Search Dialog Animation TableLayout
Contents- Overview
- Create a new Eclipse Android project
- Define the Data model
- The Android Manifest file
- The Application class
- Create a Preferences screen
- Implement the Init Task
- The Yahoo! Finance API
- The XmlPullParser
- The SAX Parser
- Calling RESTful service
- Implement the Data Service
- Create a splash screen
- Create the Main screen
- The Search Dialog
- Create the Info screen
- The AChartEngine library
- ForexWiz
- assets
- hist
- USDHRK.csv
- USDSEK.csv
- USDARS.csv
- USDISK.csv
- USDZAR.csv
- USDUAH.csv
- USDPLN.csv
- USDJPY.csv
- USDSAR.csv
- USDCHF.csv
- USDILS.csv
- USDTHB.csv
- USDNOK.csv
- USDCLP.csv
- USDNZD.csv
- USDDKK.csv
- USDHUF.csv
- USDLKR.csv
- USDGBP.csv
- USDLVL.csv
- USDMYR.csv
- USDRSD.csv
- USDINR.csv
- USDHKD.csv
- USDPKR.csv
- USDBRL.csv
- USDSGD.csv
- USDEGP.csv
- USDAED.csv
- USDEEK.csv
- USDNGN.csv
- USDIDR.csv
- USDEUR.csv
- USDPHP.csv
- USDRUB.csv
- USDTRY.csv
- USDAUD.csv
- USDCAD.csv
- USDQAR.csv
- USDIRR.csv
- USDMXN.csv
- USDTWD.csv
- USDRON.csv
- USDDZD.csv
- USDCNY.csv
- USDKRW.csv
- USDBGN.csv
- USDCZK.csv
- fonts
- Font.ttf
- symbols.xml
- quote.xml
- result.txt
- hist
- res
- drawable-xxhdpi
- thailand.png
- honduras.png
- saudiarabia.png
- unitedkingdom.png
- singapore.png
- afghanistan.png
- norway.png
- zimbabwe.png
- azerbaijan.png
- barbados.png
- serbia.png
- romania.png
- guatemala.png
- kazakhstan.png
- elsalvador.png
- suriname.png
- venezuela.png
- croatia.png
- jamaica.png
- israel.png
- bosnia_and_herzegovina.png
- brazil.png
- liberia.png
- oman.png
- netherlands.png
- nicaragua.png
- seychelles.png
- sweden.png
- russia.png
- mongolia.png
- egypt.png
- unitedstates.png
- latvia.png
- ghana.png
- cuba.png
- qatar.png
- namibia.png
- argentina.png
- turkey.png
- paraguay.png
- bermuda.png
- estonia.png
- mexico.png
- hongkong.png
- nepal.png
- malaysia.png
- india.png
- denmark.png
- chile.png
- sainthelena.png
- southkorea.png
- gibraltar.png
- bulgaria.png
- switzerland.png
- ukraine.png
- uzbekistan.png
- northkorea.png
- kyrgyzstan.png
- poland.png
- yemen.png
- mauritius.png
- trinidadandtobago.png
- somalia.png
- colombia.png
- guyana.png
- isleofman.png
- pakistan.png
- macedonia.png
- cambodia.png
- fiji.png
- australia.png
- albania.png
- costarica.png
- belize.png
- newzealand.png
- philippines.png
- hungary.png
- lebanon.png
- syria.png
- srilanka.png
- japan.png
- panama.png
- bolivia.png
- iceland.png
- guernsey.png
- falklandislands.png
- dominicanrepublic.png
- czechrepublic.png
- taiwan.png
- canada.png
- vietnam.png
- lithuania.png
- bahamas.png
- uruguay.png
- mozambique.png
- nigeria.png
- belarus.png
- botswana.png
- cayman_islands.png
- peru.png
- indonesia.png
- china.png
- brunei.png
- solomonislands.png
- euro.png
- iran.png
- laos.png
- aruba.png
- southafrica.png
- tuvalu.png
- jersey.png
- xml
- settings.xml
- searchable.xml
- settings2.xml
- layout
- row.xml
- splash.xml
- main.xml
- info.xml
- drawable-hdpi
- system.png
- ic_btn_round_more.png
- throbber2.png
- plus.png
- throbber.png
- drawable-xhdpi
- ic_launcher.png
- delete.png
- drawable-mdpi
- ic_menu_refresh.png
- ic_dialog_menu_generic.png
- back_pattern.png
- values-sw720dp-land
- dimens.xml
- anim
- progress.xml
- values
- arrays.xml
- dimens.xml
- strings.xml
- colors.xml
- styles.xml
- drawable
- bg_repeat.xml
- curved2.xml
- curved.xml
- separator.xml
- menu
- context.xml
- options.xml
- values-sw600dp
- dimens.xml
- drawable-xxhdpi
- libs
- android-support-v4.jar
- achartengine-1.0.0.jar
- src
- com
- appsrox
- forexwiz
- data
- QuoteLoader.java
- QuoteUpdater.java
- RateUpdater.java
- SymbolLoader.java
- Downloader.java
- QuoteHandler.java
- RateLoader.java
- common
- Util.java
- Constants.java
- model
- Rate.java
- Quote.java
- DbHelper.java
- Symbol.java
- AbstractModel.java
- DataService.java
- InitTask.java
- Disclaimer.java
- SplashActivity.java
- InfoActivity.java
- SearchableActivity.java
- ForexWiz.java
- MainActivity.java
- SuggestionProvider.java
- SettingsActivity.java
- data
- forexwiz
- appsrox
- com
- AndroidManifest.xml
- assets
1. Overview
In this tutorial we show how to create a currency converter app in Android. If you travel to foreign countries or do forex trading then you already know the utility of such an application. Even if you do neither of these you'd still find it interesting to check the exchange rates of world currencies and how they vary over time.Developing a currency converter app is a good way of learning Android development as it involves a lot of concepts such as making REST calls, parsing the data, storing into a database, as well as updating the data in background. Apart from these we also allow user to check historical exchange rates which involves plotting charts using third party libraries like AChartEngine.
Here is the design of the app.
The main screen is implemented using a ListView with custom layout for the rows. And the details screen uses AChartEngine library to render the chart. There is a search mechanism available in the main screen which allows user to search a currency and add it to the list.
There is also a settings screen which we cover in the tutorial. So let's start coding!
2. Create a new Eclipse Android project
In Eclipse, go to File > New > Project and in the New Project dialog, expand Android folder to select Android Project.In New Android Project dialog enter the project details as follows.
Project name: ForexWiz
Build Target: Android 2.1
Application name: Forex Wiz
Package name: com.appsrox.forexwiz
Create Activity: MainActivity
Click Finish. The project gets created in your workspace.
3. Define the Data model
The data model of the application comprises of two tables. The Symbol table holds basic information about each currency such as its name, country, ISO code, and whether the user is tracking the currency. The Quote table holds the exchange rates between currencies and other useful information which would be updated regularly. Create a package com.appsrox.forexwiz.model to hold the data model classes.The data model classes are simple Java beans with attributes and getters/setters corresponding to the table columns. Additionally, we implement CRUD (create, read, update, delete) functionality in the model class itself. Here is some code to give you an idea.
public class Symbol extends AbstractModel { public static final String TABLE_NAME = "symbol"; public static final String SQL_CREATE = "CREATE TABLE symbol (_id INTEGER PRIMARY KEY AUTOINCREMENT, country TEXT, name TEXT, code TEXT, isTracked INTEGER)"; private String country; private String name; private String code; private boolean isTracked; // constructors // getters and setters public long save(SQLiteDatabase db) { ContentValues cv = new ContentValues(); cv.put("country", country); cv.put("name", name); cv.put("code", code); cv.put("isTracked", 0); return db.insert(TABLE_NAME, null, cv); } public boolean update(SQLiteDatabase db) { ContentValues cv = new ContentValues(); cv.put("isTracked", isTracked ? 1 : 0); return db.update(TABLE_NAME, cv, "_id = ?", new String[]{String.valueOf(id)}) == 1 ? true : false; } public boolean load(SQLiteDatabase db) { Cursor cursor = db.query(TABLE_NAME, null, "code = ?", new String[]{code}, null, null, null); try { if (cursor.moveToFirst()) { id = cursor.getLong(cursor.getColumnIndex("_id")); country = cursor.getString(cursor.getColumnIndex("country")); name = cursor.getString(cursor.getColumnIndex("name")); code = cursor.getString(cursor.getColumnIndex("code")); isTracked = cursor.getInt(cursor.getColumnIndex("isTracked")) == 1 ? true : false; return true; } return false; } finally { cursor.close(); } } // Override equals and hashCode }
Declare the column names as constants as done for table name.
Additionally, create DbHelper class by extending SQLiteOpenHelper for accessing and managing the database.public class DbHelper extends SQLiteOpenHelper { public static final String DB_NAME = "forexwiz"; public static final int DB_VERSION = 1; public DbHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(Symbol.SQL_CREATE); db.execSQL(Quote.SQL_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }The database gets created along with tables when we access it the first time. We will cover this later in the section for Application class.
4. The Android Manifest file
The AndroidManifest.xml file describes the Android application. We need to edit this file to declare various components, features, permissions, etc. used by the application.To start with, we show you just the important elements but we will modify this file as we develop components for the application.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.appsrox.forexwiz" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="8" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:name=".ForexWiz" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > </application> </manifest>Notice that we specified a name attribute for the <application> element which declares that we have implemented a Application class for the application.
5. The Application class
The Application class is a good place to declare all globals in an application although it's not mandatory. To use it we create a class which extends Application and override onCreate() method where the variables are instantiated.public class ForexWiz extends Application { public static DbHelper dbHelper; public static SQLiteDatabase db; public static SharedPreferences sp; public static final String BASE_CURRENCY = "base_currency"; public static final String DEFAULT_CURRENCY = "USD"; @Override public void onCreate() { super.onCreate(); PreferenceManager.setDefaultValues(this, R.xml.settings, false); sp = PreferenceManager.getDefaultSharedPreferences(this); dbHelper = new DbHelper(this); db = dbHelper.getWritableDatabase(); } public static String getBaseCurrency() { return sp.getString(BASE_CURRENCY, DEFAULT_CURRENCY); } public static void setBaseCurrency(String currencyCode) { sp.edit().putString(BASE_CURRENCY, currencyCode).commit(); } }We instantiate DbHelper and invoke getWritableDatabase() to get an instance of the database. When the app is launched the very first time then this is the instant when the database is created and the code in onCreate(SQLiteDatabase db) of DbHelper is executed.
If you execute a lot of SQL inside onCreate(SQLiteDatabase db) method either to create tables or populate data then its better to invoke getWritableDatabase() in a separate (non UI) thread.
In the next section we'll develop a Preference screen and create a settings.xml file which we have already used in the Application class to load default preference values.