This probably has been blogged more than a few times in the blog sphere, but it doesn't hurt to add another entry about it.

In java 1.6, the specs for @Override annotation was changed to allow @Override annotation on implementation methods that 'override' interface methods. That syntax was not allowed in 1.5.

interface Foo{ void foo(); }
class Bar implements Foo{
@Override //this line is valid in 1.6, but gives compilation error in 1.5
public void foo() {}
}

So, if you are switching back and forth with jdk 1.5 and jdk 1.6 thinking the syntax are compatible, you may run into compilation problems if you have @Override on your implementation class methods. IDEs like Eclipse, trying to be helpful, will automatically add @Override to methods when generating implementation classes, which makes your source codes non-portable to 1.5.

http://blogs.sun.com/ahe/entry/override

 

Mercurial = Good

By Jay Liang

good eclipse support
good integration on both Linux & Windows
distributed repository, you carry the repository everywhere you go (awesome!)
easy to setup, easy to use
many tools support (I think ...)

 

Here is another thing in android that kept me scratching my head for a day before i finally figure out how to do it properly because of the lack of documentations and books for Android development at this time.

The android app that I am currently working on has a search feature which will fire a http request and shows the result in a list view. The search can be slow depending on the network speed so I wanted to put a loading dialog on the screen to indicate that the app is processing.

There's a ProgressDialog class in Android's SDK, so the idea is to just first build and show a progress dialog before the search starts, and then cancel the dialog on search completion:

ProgressDialog pd = ProgressDialog.show(this,
"Title",
"Message",
true, false);

makeHttpRequest();
pd.dismiss();
The above snippet will not work because the makeHttpRequest() method is being executed on the UI thread (Android has a similar threading model as Swing) therefore the dialog will not show on the screen until makeHttpRequest() returns.

That's understandable, so how about putting the method in a background thread like this:
final ProgressDialog pd = ProgressDialog.show(this,
"Title",
"Message",
true, false);

new Thread(new Runnable(){
public void run(){
makeHttpRequest();
pd.dimiss();
}
}).start();
This works as we would expect, the progress dialog is shown and then it will disappear when makeHttpRequest() is finished.

However, here's the difficult bit. The above code will cause your application to crash if the user change the phone's orientation while the progress dialog is not yet dismissed.

W/dalvikvm( 292): threadid=3: thread exiting with uncaught exception
(group=0x40010e28)
E/AndroidRuntime( 292): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 292): java.lang.IllegalArgumentException: View not attached to window manager
E/AndroidRuntime( 292): at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java: 331)
E/AndroidRuntime( 292): at
android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200)
E/AndroidRuntime( 292): at android.view.Window$LocalWindowManager.removeView(Window.java:401)
E/AndroidRuntime( 292): at
android.app.Dialog.dismissDialog(Dialog.java:249)
E/AndroidRuntime( 292): at android.app.Dialog.access$000(Dialog.java:59)
E/AndroidRuntime( 292): at android.app.Dialog$1.run(Dialog.java:93)
E/AndroidRuntime( 292): at
android.app.Dialog.dismiss(Dialog.java:233)
E/AndroidRuntime( 292): at android.app.Dialog.cancel(Dialog.java:838)
E/AndroidRuntime( 292): at com.yellowbook.android2.SearchHelper$3.handleMessage(SearchHelper.java:97)
E/AndroidRuntime( 292): at android.os.Handler.dispatchMessage(Handler.java:88)
E/AndroidRuntime( 292): at android.os.Looper.loop(Looper.java:
123)
E/AndroidRuntime( 292): at android.app.ActivityThread.main(ActivityThread.java:3742)
E/AndroidRuntime( 292): at
java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 292): at
java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime( 292): at com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:739)
E/AndroidRuntime( 292): at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
E/AndroidRuntime( 292): at
dalvik.system.NativeStart.main(Native Method)

That is because by default, activities in Android will be destroyed and recreated on orientation change. Since the progress dialog is no longer 'attached' to the view after the activity is re-created, it blows up once the activity was destroyed. The problem has to do with the internal UI managements of android which i won't attempt to explain here.

Long story short, I figured out a working solution to the above problem. Rather than creating and showing the dialog manually, you will need to override the onCreateDialog() method in your activity to let Android management the dialogs for you.

Example codes:
@Override
protected Dialog onCreateDialog(int id) {
if(id == ID_DIALOG_SEARCHING){
ProgressDialog loadingDialog = new ProgressDialog(this);
loadingDialog.setMessage("searching...");
loadingDialog.setIndeterminate(true);
loadingDialog.setCancelable(true);
return loadingDialog;
}

return super.onCreateDialog(id);
}

private void Search(){
showDialog(ID_DIALOG_SEARCHING);
new Thread(new Runnable(){
public void run(){
makeHttpRequest();
dismissDialog(AndroidSearch.ID_DIALOG_SEARCHING);
}
}).start();
}

In addition to the aboive, my app's makeHttpRequest() forwards the UI to another screen using startActivityForResult() method like so:
makeHttpRequest(){
Result res = search();
Intent i = new Intent(activity, ResultActivity.class);
i.putExtra("result", res);
activity.startActivityForResult(i, 1);
}
If you have similar code, then you will find that the progress dialog is still being shown when you click on the back button to go back to the search activity screen. After a few more hours of trial and errors, I found that if I override the onSaveInstanceState() as followed, the progress dialog will be gone when I go back to the previous screen using the phone's back button.

//Do this at your own risk because I don't know whether that's the correct way of handling this.
@Override
protected void onSaveInstanceState(Bundle outState) {
try {
dismissDialog(ID_DIALOG_SEARCHING);
} catch (Exception e) {
//ignore error
}
super.onSaveInstanceState(outState);
}

 

By Jay Liang















Posted via Pixelpipe.

 

Update (2008-10-29):


I just saw this on android-developers mailing list. Looks like it's a easier way to achieve this effect. (I haven't have time to test it myself).

from:

http://groups.google.com/group/android-developers/tree/browse_frm/thread/1906f24707594f67/17322a04f7af1a5b


In res/drawable, create a file called for instance mybutton_background.xml
and put something like this inside:

<?xml version="1.0" encoding="utf-8"?>
<selector android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false"
android:drawable="@drawable/button_background_focus" />
<item android:state_focused="true" android:state_pressed="true"
android:drawable="@drawable/button_background_pressed" />
<item android:state_focused="false" android:state_pressed="true"
android:drawable="@drawable/button_background_pressed" />
<item drawable="@drawable/button_background_normal">
</selector>
Then set this drawable as the background of your button with
android:background="@drawable/mybutton_background"

This is not documented anywhere in the android site.
==============================================================

The standard Button widget in Android has an onpress effect which will paint the button with orangish color when the button is pressed. However, if you change the background of the button widget to create your own custom button, the onpressed effect will be lost.

To create the same effect with your custom button image, you need to extend the Button class and override its onDraw() methd as followed:

public class OnPressButton extends Button{

public OnPressButton(Context context) {
super(context);
}

public OnPressButton(Context context, AttributeSet attrs){
super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas) {
//sets the button image based on whether the button in its pressed state
setBackgroundDrawable(getResources().getDrawable(isPressed()?R.drawable.btn_on : R.drawable.btn_off));
super.onDraw(canvas);
}

}
Then instead of using the Button widget, use the above implementation of Button in your layout xml file.
<view
class="com.mycompany.android.ui.OnPressButton"
android:background="@android:color/transparent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="My Button" />

Observe that the background is set to "color/transparent".

That's all you need to do to implement the onpress effect. For more details about implementing custom widget, see also http://code.google.com/android/toolbox/custom-components.html

 

(Scraping google map may be in violations of their term & services)

Google map provides a set of ajax API that allows systems to query its data programatically. However the search results from this API does not include the business url information. So what if your application needs this url information? Well, you have no choices but to bring back the good old screen scraping technique.

Rather than using the ajax API link, the easiest way is to just use the 'maps' link directly as shown below and scrape the returned html page for the business url.

http://maps.google.com/maps?q=Little+Sicily+Pizza+loc:26+Crooked+Ln,++King+Of+Prussia,+PA+19406&mrt=yp&view=text

This method can only be used in toy problems of course (as oppose to use in production systems).

 

Lucene Spell Checker

By Jay Liang