Wednesday, November 10, 2010

How to customize control

There are some icons and xmls under C:\Android\android-sdk-windows-1.6_r1\platforms\android-1.5(or other version)\data\res\drawable

To use different icons for standard control, we can copy the xml file and icons used in the xml to our own \drawable folder and set it in the layout xml

1) Grab the checkbox_background.xml and checkbox.xml from above folder and copy to the drawable folder in my project

2) Copy all the PNG files for the checkbox to the drawable folder in my project

image

3) Change the layout to use the checkbox (In my case, it is a CheckedTextView)

android:checkMark="@drawable/checkbox"

image

Monday, October 25, 2010

java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap

Recently our two applications on Android Market kept reporting error “java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap…”. If you look at the stack trace, there is no trace of our code. Below is one of the stack trace:

java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4478a900
at android.graphics.Canvas.throwIfRecycled(Canvas.java:955)
at android.graphics.Canvas.drawBitmap(Canvas.java:1044)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:323)
at android.widget.ImageView.onDraw(ImageView.java:842)
at android.view.View.draw(View.java:6740)
at android.view.ViewRoot.draw(ViewRoot.java:1407)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

 

After searching around the Internet, I found some clues. It has something to do with the call of bitmap.recycle(). Some people suggest to remove all the calls to bitmap.recycle() and let the garbage collector to do the job. So I tried this solution and updated the Packing List application. I will give it a day or two to see if it settles the issue.

Thursday, August 19, 2010

Miscellaneous Tips

How to stretch a control?

Set Layout_weight to greater than 0

image

image

 

Issue with Check box in a list view

When I use anything other than textview in a listview, the context menu stop working. Now to have a check box in a list view, I have to use CheckedTextView. But the text in CheckedTextView appears on the left side of the checkbox. I don’t know how to change it, so I use a CheckedTextView with no text and a TextView.

 

Show checkbox in CheckedTextView

<CheckedTextView android:id="@+id/categoryCheckedTextView"
android:layout_width="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:layout_height="wrap_content"
android:clickable="true">
</CheckedTextView>

Display simple MessageBox in Android


AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Packing List");
alertDialog.setMessage("Could not find the file.");
alertDialog.show();

 

Change emulator orientation

Use KEYPAD_7 or KEYPAD_9 on you desktop. You need to turn off your Num Lock.


Dynamically change the background color

To dynamically change the background color, use myView.setBackgroundResource(R.color.my_color) instead myView.setBackgroundColor(R.color.my_color)

 

How to align text in text view?

When trying to align the text to the right in text , set the “layout_gravity” to right doesn’t work. Need to set “gravity” to right.

Monday, August 9, 2010

Re-import Android project issue

After my laptop crashes, I have to re-install everything. After importing the existing projects, I got the following error “The method onClick(DialogInterface, int) of type new DialogInterface.OnClickListener(){} must override superclass method”

image

And this is what I found on google:

Eclipse is defaulting to Java 1.5 and you have classes implementing interface methods (which in Java 1.6 can be annotated with @Override, but in Java 1.5 can only be applied to methods overriding a superclass method).

Go to your project/ide preferences and set the java compiler level to 1.6 and also make sure you select JRE 1.6 to execute your program from eclipse.

image

How to debug on device?

For detail information, go to - http://developer.android.com/guide/developing/device.html. The following is a simplified version for my own reference.

1. Declare your application as "debuggable" in your Android Manifest.

In Eclipse, you can do this from the Application tab when viewing the Manifest (on the right side, set Debuggable to true). Otherwise, in the AndroidManifest.xml file, add android:debuggable="true" to the <application> element.

2. Turn on "USB Debugging" on your device.

On the device, go to the home screen, press MENU, select Applications > Development, then enable USB debugging.

3. Setup your system to detect your device.

If you're developing on Windows, you need to install a USB driver for adb. See the Windows USB Driver documentation.

image

ClassNotFound exception when unmarshalling

The following code is the serialization part of the Category class in PackingList project. Since the category has an arraylist of items, I have to put it in Bundle. To de-serialize it, I need to retrieve items from the Bundle. To do that, I was using Bundle d = in.readBundle(). However, I received “ClassNotFound exception when unmarshalling”. I have to pass in the ClassLoader so it knows it’s for the Item.

 

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(category);
Bundle b = new Bundle();
b.putParcelableArrayList("items", items);
dest.writeBundle(b);

}

public static final Parcelable.Creator<Category> CREATOR =
new Parcelable.Creator<Category>() {
public Category createFromParcel(Parcel in) {
Category category = new Category();
category.category = in.readString();
Bundle b = in.readBundle(Item.class.getClassLoader());
category.items = b.getParcelableArrayList("items");

return category;
}

@Override
public Category[] newArray(int size) {
return new Category[size];
}
};

How to display progress dialog?

private ProgressDialog dialog;
public void onCreate(Bundle savedInstanceState) {
……

dialog = ProgressDialog.show(this, "",
"Loading Calendar and Tasks. Please wait...", true);

……
CalendarThread calendarThread = new CalendarThread();
calendarThread.start();

}

private class CalendarThread extends Thread {

@Override
public void run() {
//Long running process
……

handler.sendEmptyMessage(0);
}

private Handler handler = new Handler() {

@Override
public void handleMessage(Message msg) {
//Process after the long running process
……
dialog.dismiss();
}
};
}

Wednesday, April 21, 2010

Android Emulator Issue

Yesterday I resumed the work on improving the Packing List 1.5. However, the Emulator didn’t corporate. It kept crashing. I was so frustrated. I deleted and re-created the image several times. It still didn’t work. The error I received was something like "sad result from adb". What does “sad result” mean? They really should give it better description. Some times I received “the user data image is used by another emulator” while there was only one emulator and one user. I googled and no help. Finally, this morning I tried again, the emulator was so slow to start. So I checked the power mode on my laptop. It turned out I accidently set the power mode to “Power Saver” a couple of days ago. I changed it back. Now everything worked just fine!

Monday, February 8, 2010

Creating custom dialog in Android

This blog shows you an example on how to create custom dialog. For more information on creating different kind of dialogs, please visit http://developer.android.com/guide/topics/ui/dialogs.html
1. Create layout for the dialog
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10sp">
<EditText android:text=""
android:id="@+id/categoryEditText"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:singleLine="true">
</EditText>
</LinearLayout>



2. Override onCreateDialog in the Activity
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case CATEGORY_DETAIL:
LayoutInflater li = LayoutInflater.from(this);
View categoryDetailView = li.inflate(R.layout.category_detail, null);

AlertDialog.Builder categoryDetailBuilder = new AlertDialog.Builder(this);
categoryDetailBuilder.setTitle("Edit Category");
categoryDetailBuilder.setView(categoryDetailView);
AlertDialog categoryDetail = categoryDetailBuilder.create();

categoryDetail.setButton("OK", new OnClickListener(){

@Override
public void onClick(DialogInterface dialog, int which) {
AlertDialog categoryDetail = (AlertDialog)dialog;
EditText et = (EditText)categoryDetail.findViewById(R.id.categoryEditText);
if (categories.get(selectedIndex)!=null){
//... some code
}
});

categoryDetail.setButton2("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}});

return categoryDetail;
default:
break;
}
return null;
}


3. Override onPrepareDialog to dynamically set default value before the dialog is open
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
switch (id) {
case CATEGORY_DETAIL:
AlertDialog categoryDetail = (AlertDialog)dialog;
EditText et = (EditText)categoryDetail.findViewById(R.id.categoryEditText);
et.setText(defaultValue);
break;
default:
break;
}
}


4. Call showDialog to display the dialog
static final private int CATEGORY_DETAIL = 1;
//... some code
showDialog(CATEGORY_DETAIL);


Monday, February 1, 2010

Passing a list of objects between Activities

In Android, you can use Bundle to pass data between activities. There are many functions to pass Integer, String, etc. To pass an object, you will need to implement Parcelable interface and override some functions to serialize/de-serialize the object. Here is an example:
public class Category implements Parcelable {
private String category;
private ArrayList<Item> items;

public String getCategory() {
return category;
}

public void setCategory(String category) {
this.category = category;
}

public ArrayList<Item> getItems() {
return items;
}

public void setItems(ArrayList<Item> items) {
this.items = items;
}

public Category(){

}

public Category(String _category){
category = _category;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(category);
Bundle b = new Bundle();
b.putParcelableArrayList("items", items);
dest.writeBundle(b);

}

public static final Parcelable.Creator<Category> CREATOR = 
new Parcelable.Creator<Category>() { 
public Category createFromParcel(Parcel in) { 
Category category = new Category();
category.category = in.readString();
Bundle b = in.readBundle(Item.class.getClassLoader());        
category.items = b.getParcelableArrayList("items");

return category;
}

@Override
public Category[] newArray(int size) {
return new Category[size];
}
};
}


To pass an arraylist  of Category to another activity,
intent i = new Intent(_av.getContext(), ItemList.class);
Bundle b = new Bundle();
b.putParcelableArrayList("categories", categories);
b.putInt("index", _index);
i.putExtras(b);
startActivityForResult(i, ITEM_LIST);

To retrieve the data,
Bundle b = this.getIntent().getExtras();

ArrayList<Category> cats = b.getParcelableArrayList("categories");
int index = b.getInt("index");

How to add MessageBox in Android?

Simple message box with no buttons
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Packing List");
alertDialog.setMessage("Could not find the file.");
alertDialog.show();

Message box with buttons
AlertDialog deleteAlert = new AlertDialog.Builder(this).create();
deleteAlert.setTitle("Delete List");
deleteAlert.setMessage("Are you sure you want to delete this list?");
deleteAlert.setButton("Yes", new OnClickListener(){

@Override
public void onClick(DialogInterface dialog, int which) {               
//...
}
});
deleteAlert.setButton2("No", new OnClickListener(){

@Override
public void onClick(DialogInterface dialog, int which) {
//...
}
});
deleteAlert.show();

Thursday, January 14, 2010

How to deploy Android application?

1. Create icon for your application and add it to the project
 image
image
2. Export unsigned application
Right click on the project. Click on “Android Tools->Export Unsigned Application Package…”
image
2. Generate personal certificate by using keytool in java’s jre\bin directory
image
3. Sign Android application by using jarsigner in jre\bin direcotry
image
4. Installation
a) Install application on emulator
image 
b) Install application on device
I downloaded ASTRO File Manager and copied the apk file to device. Use File Manager to find the file and tap on it. It prompted me a couple of questions. I have to change my device setting to allow unknown source apps to be installed on my device.

How to obtain Google Map Key for Android Application?

This link will give detailed information on how to get Google Map Key for Android Application. I don’t need to repeat it. Here I just want to give simplified steps for future reference:
1. Get MD5 Fingerprint of the Certificate
a) SDK Debug Certificate
image
b) Your Signing Certificate
image
2. Go to this link to sign up for an Android Maps API key
3. Add the key to your application’s AndroidManifest.xml
<com.google.android.maps.MapView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="[your key]"
/>

MapActivity cannot be resolved to a type

When I first working on with MapActivity, I got above error. I kept press Ctrl+Shift+O. However, the type just wouldn’t resolve. Finally I found the answer on the Internet. You need to change the build target to “Google API”
Right click on the project. Go to “Properties”. Change the “Build Target” from “Android 1.x to Google APIs 1.x”
image

Read, Write and Parse XML file in Android

1. Read and Parse Xml file
The sample XML file looks like the following:
<packingList>
<category name="test">
</category>
<packingList>


The following code shows you how to read and parse the file
ArrayList<Category> categories;
XmlPullParser parser = Xml.newPullParser();
try {
FileInputStream fIn = openFileInput(FILE_NAME);
InputStreamReader isr = new InputStreamReader(fIn);

// auto-detect the encoding from the stream
parser.setInput(isr);
int eventType = parser.getEventType();
Category currentCategory = null;
boolean done = false;
while (eventType != XmlPullParser.END_DOCUMENT && !done){
String name = null;
switch (eventType){
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
name = parser.getName();
if (name.equalsIgnoreCase("packingList")){
categories = new ArrayList<Category>();
} else if (categories != null){
if (name.equalsIgnoreCase("category"))
currentCategory = new Category(parser.getAttributeValue(0));
}
break;
case XmlPullParser.END_TAG:
name = parser.getName();
if (name.equalsIgnoreCase("category") &&
currentCategory != null){
categories.add(0, currentCategory);
} else if (name.equalsIgnoreCase("packingList")){
done = true;
}
break;
}
eventType = parser.next();
}
} catch (FileNotFoundException e) {
// TODO
} catch (IOException e) {
// TODO
} catch (Exception e){
// TODO
}


2. Write to file
 
try {
FileOutputStream fOut = openFileOutput(FILE_NAME, MODE_WORLD_READABLE);
OutputStreamWriter osw = new OutputStreamWriter(fOut);
String fileContent = …; //build file content
osw.write(fileContent );
osw.flush();
osw.close();

} catch (FileNotFoundException e) {

}


 

Tuesday, January 12, 2010

How to kill an application running in Android Emulator?

Since I am not a Java programmer, there is a learning curve using Eclipse. I am getting used it. But sometimes I have to search the Internet to find answers for really simple question like this one. And here is how.
image
1. Click on “DDMS”
2. Select the application you want to kill
3. Click on “Stop”

Android 2.0 Update

To get Android SDK 2.0 update, go to “Windows->Android SDK Manager” to download the new update.
After download the update, I got the following message when try to open my existing application
image
I went to “Help->Software Updates…” and installed the developer tools in below screen shot.
image

Issues with running my first “Hello Android” application

Soon after I have the environment setup, I created my first Android application “Hello Android”. The app is sure simple, but I still run into some issues when running it.
The first one is “HelloAndroidConversion to Delvik format failed with error 1” (see screen shot below)
image
I am not a Java programmer and I have no idea what the issue is. After searching the answer on the Internet, I found the solution. That is go to “Project-Clean…” in Eclipse.
Then I received error “Could not find HelloAndroid.apk!”
 image
It turned out to be the path I added to the system variable. I added “C:\Android\GlassFish-Tools-Bundle-For-Eclipse-1.1\jre\bin” to Path in windows system environment variable. I removed “\bin” and do “Project->Clean…” again. The issue is gone.
The emulator kept shutting down even after I passed these two issues. I had to start the emulator first. Even so, it failed to run it the first time. But it worked the second time and after. Strange!

Thursday, January 7, 2010

Android Development Environment Setup

1. Download Android SDK 1.6
2. Download GlassFish tool bundle for Eclipse 1.1
Don’t ask me why GlassFish. That is the first Eclipse tool I found, so I just installed it.
3. Install Android plug-in in Eclipse
If you got the “No repository found at https://dl-ssl.google.com/android/eclipse/” error when using the URL on Andorid web site which is the checked one in the following screen shot, use the second URL on the screen instead.
image
4. Install AVD(Android Virtual Device)
\[Android sdk folder]\tools\android create avd –-target 2 –-name my_avd
Don’t forget to add “[Eclipse folder]\jre” to the PATH in Environment Variables
5. Set up Android SDK location in Eclipse. Go to Windows->Preferences
image

Welcome to Android Ideas!

This is the place I want to share my experience on learning Android programming. Let's start.