MyDroidTemplate
| CPForAndroid
|
This article will explore some of the interesting components I found while producing CPForAndroid which may be useful for those learning to develop Android applications. There is also a template application with some classes that are needed with most applications like database functions and menus which you will not find in the Eclipse New Project wizard.
I am guessing that there are many readers familiar with SQLite. I have not had a chance to work with light-weight embedded SQL database engine library and I am very glad that it is being used in Android development. I decided to make a small SQLite template made of two classes so they may be reused in future projects. After a very short time attempting this, I decided to just combined some of what I made with a Creative Commons licensed class SQLiteDatabaseAdapter by alessandrofranzi (that's what we like to do around here right? re-use code :smile:). SQLite seemed to be an efficient solution to help remember the end user's previously read CPForAndroid RSS items.
I believe there are more in-depth tutorials on Codeproject on how to get setup for Android development, but here is a quick reference guide that I have compiled for this article:
NOTE (2014-11-06): the below steps were created when the article first was drafted, please go by the documentation found here for the latest instructions and for using Android Studio
- Make sure you have the Eclipse IDE for Java.
- Download the Android SDK you may get an error while running the SDK setup OR Go to window->preferences. Then navigate to Install/update - available software sites. Then you can add http://dl-ssl.google.com/android/eclipse/site.xml to the list. Now if you need to download the android developer's tools, you go back to the main eclipse screen and navigate to help->Install New Software. In the space where it says to Work with paste in that same URL: http://dl-ssl.google.com/android/eclipse/site.xml. Then select all the developer tools available. Restart, and you now have the Android dev tools available. More help HERE.
- Follow the Quick Start for setting up Eclipse IDE.
| When you are building an Android project from scratch using the New -> Android Project wizards, it builds the basics for an application but there are a few expected items that are missing. This template is an attempt to have a template that may be trimmed down and customized rather than hunting down code and adding it in. To use this template, extract the MyDroidTemplate.zip to a new location (for example in your Eclipse 'workspace' folder) and then rename the root folder to your new project name. Next, File -> Import -> Existing Projects into Workspace. You will then need to update the project class name and namespace to your new name. |
Here are some things I have added to the Eclipse generated MyDroidTemplate.java file:
import android.util.Log;
public final String TAG = "MyDroidTemplate";
I have read somewhere that most Android users expect a menu to be present in the application, so let's add one in the project template. I created a subfolder 'menu' under '.\MyDroidTemplate\res' (If you are not familiar with Eclipse, remember that you will need to press F5 in your project when you add folders or files outside of the Eclipse IDE.). This will contain the details on how to draw the buttons in the menu. All we need are three buttons for the template: 'Options', 'Quit', and 'About'.
="1.0"="utf-8"
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/options"
android:title="Options"
android:icon="@android:drawable/ic_menu_preferences">
</item>
<item android:id="@+id/quit"
android:title="Quit"
android:icon="@android:drawable/ic_menu_close_clear_cancel">
</item>
<item android:id="@+id/about"
android:title="About"
android:icon="@android:drawable/ic_menu_info_details">
</item>
</menu>
Next, we need some methods to trigger and draw the menus. Eclipse does a good job at auto adding import lines when it sees it needs a class library. Here are the ones needed for this OptionsMenu:
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
And in the MyDroidTemplate
class, we have the following methods to make it work (NOTE: I have commented out the lines we are not ready for yet like AboutDialog, etc).
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.options:
return true;
case R.id.quit:
finish();
return true;
case R.id.about:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Here is how the AboutDialog is added in the template. With all Android views, there must be a corresponding layout XML file. I created one in Eclipse by selecting the folder I want to add the XML to and selecting "New -> Android XML File"; make sure layout is checked and write 'about.xml' in the 'File' textbox and click Finish. Here is the about.xml and notice we are adding mostly TextViews so we can format and send text to it later (NOTE: I added some color values to the \values\strings.xml). [NOTE: PopUpDialog.java and popup.xml are now added to the template which enables you to create a popup message with one line of code.]
="1.0"="utf-8"
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/options"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/app_name"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="@color/white"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="12dip"
android:layout_marginBottom="4dip" />
<TextView
android:id="@+id/author"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/white"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="4dip"
android:layout_marginBottom="4dip" />
<TextView
android:id="@+id/graphics_byline"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/white"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="4dip"
android:layout_marginBottom="4dip" />
<TextView
android:id="@+id/license"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="4dip"
android:layout_marginBottom="8dip" />
<TextView
android:id="@+id/what_is_this"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="8dip"
android:layout_marginBottom="8dip" />
<TextView
android:id="@+id/website"
android:autoLink="web"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/white"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="8dip"
android:layout_marginBottom="4dip" />
<TextView
android:id="@+id/bugs"
android:autoLink="web"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/white"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:layout_marginTop="4dip"
android:layout_marginBottom="12dip" />
</LinearLayout>
</ScrollView>
Now we must have a Java class that will handle the AboutDialog box. We can create this in Eclipse by right-clicking the 'src' folder and 'New -> class'. For 'Package', I browsed to 'com.android.MyDroidTemplate' and the 'Name' field I placed 'AboutDialog' and clicked the Finish button. Below is the AboutDialog.java and Utils.java. I find AboutDialog a good class to copy for created new dialogs. The Utils
class has some reusable code to get the ever changing application details. (NOTE: Once again, I have added to the \values\strings.xml to store the common text for an application.)
package com.android.MyDroidTemplate;
import android.app.AlertDialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
public class AboutDialog {
@SuppressWarnings("unused")
private static final String TAG = "AboutDialog";
private final Context mCtx;
public AboutDialog(Context ctx) {
super();
this.mCtx = ctx;
}
public void show() {
final LayoutInflater factory = LayoutInflater.from(mCtx);
View dialogView = factory.inflate(R.layout.about, null);
innerUpdate(dialogView);
AlertDialog.Builder adBuilder = new AlertDialog.Builder(mCtx).setTitle(
R.string.about).setIcon(android.R.drawable.ic_dialog_info)
.setView(dialogView);
adBuilder.show();
}
private void innerUpdate(View dialogView) {
TextView appName = (TextView) dialogView.findViewById(R.id.app_name);
TextView author = (TextView) dialogView.findViewById(R.id.author);
TextView graphics_byline = (TextView) dialogView.findViewById(R.id.graphics_byline);
TextView license = (TextView) dialogView.findViewById(R.id.license);
TextView whatIsThis = (TextView) dialogView.findViewById(R.id.what_is_this);
TextView website = (TextView) dialogView.findViewById(R.id.website);
TextView bugs = (TextView) dialogView.findViewById(R.id.bugs);
String appText = Utils.getAppName(mCtx, mCtx.getPackageName()) + " v"
+ Utils.getAppVersionName(mCtx, mCtx.getPackageName());
appName.setText(appText);
author.setText(R.string.author);
license.setText(R.string.license);
whatIsThis.setText(R.string.about_text);
website.setText(mCtx.getString(R.string.website) + ":\n\n"
+ mCtx.getString(R.string.website_url));
bugs.setText("Suggestions or Bugs:\n\n"
+ mCtx.getString(R.string.issues));
}
}
And the Utils.java:
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
public class Utils {
public static boolean checkForInstalledApp(Context ctx, String pkgName) {
try {
PackageManager pm = ctx.getPackageManager();
pm.getPackageInfo(pkgName, 0);
return true;
} catch (NameNotFoundException e) {
}
return false;
}
public static String getAppName(Context ctx, String pkgName) {
try {
PackageManager pm = ctx.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(pkgName, 0);
String label = pm.getApplicationLabel(appInfo).toString();
return label;
} catch (NameNotFoundException e) {
return "";
}
}
public static String getAppVersionName(Context ctx, String pkgName) {
try {
PackageManager pm = ctx.getPackageManager();
PackageInfo pkgInfo = pm.getPackageInfo(pkgName, 0);
String ver = pkgInfo.versionName;
return ver;
} catch (NameNotFoundException e) {
return "0";
}
}
public static int getAppVersionCode(Context ctx, String pkgName) {
try {
PackageManager pm = ctx.getPackageManager();
PackageInfo pkgInfo = pm.getPackageInfo(pkgName, 0);
return pkgInfo.versionCode;
} catch (NameNotFoundException e) {
return 0;
}
}
}
SQLiteDatabaseAdapter.java (Class that delivers methods to manage a SQLite database) and DbDataLayer.java (Partner class to manage database version management opening, creating, and upgrading) has been added for SQLite database support. Instead of posting the entire class, I will explain the important methods that create and get information in the database. For the most part, the only class you will need to customize is DbDataLayer
(if you will need to perform upgrades later modify the OnUpgrade
method in SQLiteDatabaseAdapter). DbDataLayer
needs your name of the database and its tablename. It also needs your table data structure in the standard SQL 'create table
' statement. Finially, you will need to modify the AddRecord
method so it can properly add records to the table schema.
private static final String DATABASE_NAME = "mydbname.db";
private static final String TABLE_NAME = "mytablename";
Also, you will need to customize the table creation to fit your needs (see below). You will notice that the template is defaulted to create a table 'mytablename
' and it has columns 'ID', 'Link', 'Title', and 'Pubdate' in the database 'mydbname.db
'
public DbDataLayer(Context c)
{
String sql = "create table "+ TABLE_NAME + " " +
"("+ BaseColumns._ID + " integer primary key autoincrement, " +
"Link text not null, " +
"Title text not null, " +
"Pubdate text not null); ";
_dbHelper = new SQLiteDatabaseAdapter(c, DATABASE_NAME, null , 1, sql);
}
Now here is how to initialize the database before you can perform any reads or writes:
public DbDataLayer d ;
public class MyDroidTemplate extends Activity {
public DbDataLayer db ;
...
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
db = new DbDataLayer(getBaseContext());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
Call the following method to write to the database:
public void AddRecord(String title, String link, String pubdate) {
SQLiteDatabase db = _dbHelper.getWritableDatabase();
try {
ContentValues values = new ContentValues();
values.put("Link", link);
values.put("Title", title);
values.put("Pubdate", pubdate);
db.insert(TABLE_NAME, "", values);
}catch (Exception e)
{
Log.e(tag,"AddRecord Exception [" + e.getMessage() + "]");
} finally {
if (db != null)
db.close();
}
}
This, by far, was one of the challenging features to implement and I still am not happy with it. So any suggestions and feedback would be great. However, I needed a Progressbar
feature in my template so this is what I have for version 1. Calling showDialog
triggers the onCreateDialog
which displays the requested ProgressDialog
.
import android.app.ProgressDialog;
public class MyDroidTemplate extends Activity {
...
static final int PROGRESS_DIALOG = 0;
DownloaderThread progressThread;
ProgressDialog progressDialog;
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dismissDialog(PROGRESS_DIALOG);
progressThread.setState(DownloaderThread.STATE_DONE);
}
};
protected Dialog onCreateDialog(int id) {
switch(id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressThread = new DownloaderThread(handler);
progressThread.start();
return progressDialog;
default:
return null;
}
}
private class DownloaderThread extends Thread {
Handler mHandler;
final static int STATE_DONE = 0;
final static int STATE_RUNNING = 1;
int mState;
int total;
DownloaderThread(Handler h) {
mHandler = h;
}
public void run() {
mState = STATE_RUNNING;
while (mState == STATE_RUNNING)
{
Message msg = mHandler.obtainMessage();
try {
Thread.sleep(10000);
} catch (Exception e) {
Log.e("ERROR", "Thread Interrupted Exception [" + e.getMessage() + "]");
}
mHandler.sendMessage(msg);
}}
public void setState(int state) {
mState = state;
}
}
A set of classes are included in the template if you need tabbed viewing support. MyTabView.java and mytabview.xml handle the main display of the 2 tabs (you may add more) which are created with MyTabActivity.java and MyTabActivity2.java. MyTabActivity.java populates the ListView
with a simple String
array and MyTabActivity2.java populates with a custom adapter (MyLVAdapter.java [My List View Adapter]).
The Android Debug Bridge (adb.exe) allows you direct access to an emulator instance or Android-powered device for debugging. For example, for this template app I could use it to look at the database after making some entries (NOTE: adb.exe resides in the 'android-sdk-windows\tools' folder). Start the emulator, and then the Android application. Below are commands I have in a textfile so I can easily copy and paste (NOTE: Some of the commands will need modification to access the correct database and table names).
C:\android-sdk-windows\tools>adb shell
cd data
cd data
cd com.android.MyDroidTemplate
cd databases
sqlite3 mydbname.db
cd data
cd data
cd com.android.MyDroidTemplate
cd databases
#ls
ls
mydbname.db
# sqlite3 mydbname.db
sqlite3 mydbname.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> select * from mytablename;
select * from mytablename;
1|http://msn.com|MSN|Mon Aug 30 08:00
2|http://codeproject.com|Codeproject|Mon Aug 30 09:00
3|http://cpforandroid.googlecode.com|CPForAndroid|Mon Aug 30 10:00
sqlite>
Get CPForAndroid now on your Android Phone at the market. Please rate after you try it out!!
| CPForAndroid
App for Interacting with CodeProject.com! Follow the buzzing activity at your favorite programming community. Easy on your eyes and fun.
Current Features include:
- View Latest Article RSS feed
- View Lounge RSS feed
- Removes read items
- View details on each item with optional jump url
- Facebook, Google, Twitter, Windows Live, CP Email link sharing
|
https://market.android.com/details?id=org.android.CPForAndroidPlusPlus
If you are interested in help to develop or provide feedback, visit the development and support site.
- Be certain you have declared the '
android:minSdkVersion
' attribute in your manifest (http://developer.android.com/guide/appendix/api-levels.html), then Export your app to .apk file [File -> Export]. This will also generate the Certificate that is needed for your .apk. (BACKUP YOUR KEYSTORE ASAP!!! You will thank me later.) - $25.00 to publish your applications to the Android Market. http://market.android.com/publish
- Complete the registration process.
- Upload your files according to the publishing instructions.
These are just some items that I had to search for along the way. You may find them useful as you are typing along.
Browsing Codeproject.com on my mobile was motivation enough to learn how to develop using the Android SDK and its emulator. Documenting everything here will help 6 to 12 months from now when I have another idea for an Android app. Hopefully, others will find this article helpful and the MyDroidTemplate
a useful starting point for an Android Project skeleton. Along with the template, I provided some useful links to help as you develop your app and a quick reference to uploading your application to the Android Market. I plan on posting a video shortly for readers who don't own an Android phone nor have the Eclipse IDE to see what this article is about.
This template was a by-product of CPForAndroid. CPForAndroid
is an Android application to help keep up with Codeproject.com. It is an open source project and open to all. Just visit the development and support website for more info. Come help out; the more the merrier!
- Developer.Android.com [^]
- Eclipse Development [^]
- CPForAndroid Open Source Project Support and Development website [^]
- SQLite.org [^]
Updates
- 8/30/2010
- Uploaded
MyDroidTemplate
v1.0.0.0 (tested in Eclipse 3.4)
- 9/1/2010
- Tested in Eclipse 3.6
MyDroidTemplate
v1.0.0.0 (So verified in 3.4 and 3.6)
- 9/5/2010
- Added PopUpDialog.java and popup.xml to
MyDroidTemplate
- Uploaded
MyDroidTemplate.zip
version 1.1 - Updated template_files208x421.png
- Updated cpforandroid_main.png
- Updated MyDroidTemplateIDE478x260.png
CPForAndroid
now at version 1.17 and available on the Android Market
- 9/8/2010
- Added cur.deactivate() in class
DbDataLayer
method DoesExist()
to avoid any errors - Added sample Toast line
- Uploaded
MyDroidTemplate
versionName="1.2" versionCode="3"
- 9/13/2010
- Uploaded
MyDroidTemplate.zip
version 1.3 - Added
ToastMsg
to Utils
class - Added MyTabView.java and mytabview.xml
- Added MyTabActivity.java and mytabact.xml
- Added MyTabActivity2.java (Uses
MyLVAdapter
) - Added 'Show TabView' button in main.xml layout
- Added listview_row.xml for MyLVView.java
- Added MyLVView.java
- Added MyLVAdapter.java
- Added
e.printStackTrace();
to exception catch
statements for better debugging
- 2/11/2011
CPForAndroid
is now CPForAndroid++ - Updated qcode and Market Publishing section
- 11/06/2014
- MyDroidTemplate.java tested succesfully with Android Studio (beta) 0.8.14 and Android 4.4.2 (converts project)
- CPForAndroid++ doesn't compile due to some string.xml errors which I haven't had time to investigate
- Updated "The Android SDK and Eclipse Integrated Development Environment (IDE)" section