Thursday, 31 December 2009
Merry Christmas and Happy New Year!
Just wanted to wish everyone a Merry Christmas and a Happy New Year. A little late on the Christmas, but better late than never. :)
TimePicker, a widget that to select the time by hour, minute and AM or PM.
A TimePicker is a widget that allows the user to select the time by hour, minute and AM or PM.
Further extends from the previouse exercise of DatePicker.
Modify main to have one more button to start TimePicker.
Modify the main class.
Download the files.
Further extends from the previouse exercise of DatePicker.
Modify main to have one more button to start TimePicker.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/datepickerbutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="DatePicker"
/>
<Button
android:id="@+id/timepickerbutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="TimePicker"
/>
</LinearLayout>
Modify the main class.
package com.exercise.AndroidDatePicker;
import java.util.Calendar;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TimePicker;
import android.widget.Toast;
public class AndroidDatePicker extends Activity {
private int myYear, myMonth, myDay, myHour, myMinute;
static final int ID_DATEPICKER = 0;
static final int ID_TIMEPICKER = 1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button datePickerButton = (Button)findViewById(R.id.datepickerbutton);
Button timePickerButton = (Button)findViewById(R.id.timepickerbutton);
datePickerButton.setOnClickListener(datePickerButtonOnClickListener);
timePickerButton.setOnClickListener(timePickerButtonOnClickListener);
}
private Button.OnClickListener datePickerButtonOnClickListener
= new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
final Calendar c = Calendar.getInstance();
myYear = c.get(Calendar.YEAR);
myMonth = c.get(Calendar.MONTH);
myDay = c.get(Calendar.DAY_OF_MONTH);
showDialog(ID_DATEPICKER);
}
};
private Button.OnClickListener timePickerButtonOnClickListener
= new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
final Calendar c = Calendar.getInstance();
myHour = c.get(Calendar.HOUR_OF_DAY);
myMinute = c.get(Calendar.MINUTE);
showDialog(ID_TIMEPICKER);
}
};
@Override
protected Dialog onCreateDialog(int id) {
// TODO Auto-generated method stub
switch(id){
case ID_DATEPICKER:
Toast.makeText(AndroidDatePicker.this,
"- onCreateDialog(ID_DATEPICKER) -",
Toast.LENGTH_LONG).show();
return new DatePickerDialog(this,
myDateSetListener,
myYear, myMonth, myDay);
case ID_TIMEPICKER:
Toast.makeText(AndroidDatePicker.this,
"- onCreateDialog(ID_TIMEPICKER) -",
Toast.LENGTH_LONG).show();
return new TimePickerDialog(this,
myTimeSetListener,
myHour, myMinute, false);
default:
return null;
}
}
private DatePickerDialog.OnDateSetListener myDateSetListener
= new DatePickerDialog.OnDateSetListener(){
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
// TODO Auto-generated method stub
String date = "Year: " + String.valueOf(year) + "\n"
+ "Month: " + String.valueOf(monthOfYear+1) + "\n"
+ "Day: " + String.valueOf(dayOfMonth);
Toast.makeText(AndroidDatePicker.this, date,
Toast.LENGTH_LONG).show();
}
};
private TimePickerDialog.OnTimeSetListener myTimeSetListener
= new TimePickerDialog.OnTimeSetListener(){
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
// TODO Auto-generated method stub
String time = "Hour: " + String.valueOf(hourOfDay) + "\n"
+ "Minute: " + String.valueOf(minute);
Toast.makeText(AndroidDatePicker.this, time,
Toast.LENGTH_LONG).show();
}
};
}
Download the files.
Avatar - The Review
Official Avatar Movie
Well now that I have seen Avatar in both 3d and 2d, it is time for me to drop my $0.02 on the subject.
First off, this is a great movie. A class David vs Goliath story that takes place in an amazingly detailed and interesting world. Everything just fits really well together, the plants, the animals, the floating rocks. James Cameron deserves a lot of praise for creating such a rich setting. I especially liked the night scenes with all the glow-in-the-dark plants.
In 3d, the movie works because the focus is on the story and not the 3d effects. Any 3d film I have seen in the past seems to be totally focused on cheesy 3d effects that happen every 10 or 15 minutes. This movie includes some great 3d effects, but it never forgets to tell the story first. In addition, the movie looks great in 3d. The colors and imagery are just as rich in the 2d and 3d versions. The 3d version doesn't feel washed out or blurry at all.
Much has been written about how 3d is gonna save movie theaters, blah blah blah. It still seems like a bit of a gimmick to me. It really doesn't add that much to the experience. Oh sure, it will prevent movie pirates from sending films out on the Net. But is it that much better than watching a movie at home on your own HD set? I am not so sure about that.
In regards to the movie being preachy, I just don't buy that. There might be what, 1 or 2 statements in the entire movie that could be considered in that vein. But to me it is just a movie. The weak fighting back against the strong is as classic as it gets. Go see Avatar, you will be glad you did.
My rating. (5 out of 5)
DatePicker, a widget to select month, day and year.
A DatePicker is a widget that allows the user to select a month, day and year.
Create a new Android Application, AndroidDatePicker.
Modify the layout, main.xml, to add a button to start the DatePicker.
Modify the main program, AndroidDatePicker.java.
A Toast will be displayed in onCreateDialog(), to show that DatePickerDialog() will be created once only (in the first time display the dialog).
Download the files.
Create a new Android Application, AndroidDatePicker.
Modify the layout, main.xml, to add a button to start the DatePicker.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/datepickerbutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="DatePicker"
/>
</LinearLayout>
Modify the main program, AndroidDatePicker.java.
package com.exercise.AndroidDatePicker;
import java.util.Calendar;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.Toast;
public class AndroidDatePicker extends Activity {
private int myYear, myMonth, myDay;
static final int ID_DATEPICKER = 0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button datePickerButton = (Button)findViewById(R.id.datepickerbutton);
datePickerButton.setOnClickListener(datePickerButtonOnClickListener);
}
private Button.OnClickListener datePickerButtonOnClickListener
= new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
final Calendar c = Calendar.getInstance();
myYear = c.get(Calendar.YEAR);
myMonth = c.get(Calendar.MONTH);
myDay = c.get(Calendar.DAY_OF_MONTH);
showDialog(ID_DATEPICKER);
}
};
@Override
protected Dialog onCreateDialog(int id) {
// TODO Auto-generated method stub
switch(id){
case ID_DATEPICKER:
Toast.makeText(AndroidDatePicker.this,
"- onCreateDialog -",
Toast.LENGTH_LONG).show();
return new DatePickerDialog(this,
myDateSetListener,
myYear, myMonth, myDay);
default:
return null;
}
}
private DatePickerDialog.OnDateSetListener myDateSetListener
= new DatePickerDialog.OnDateSetListener(){
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
// TODO Auto-generated method stub
String date = "Year: " + String.valueOf(year) + "\n"
+ "Month: " + String.valueOf(monthOfYear+1) + "\n"
+ "Day: " + String.valueOf(dayOfMonth);
Toast.makeText(AndroidDatePicker.this, date,
Toast.LENGTH_LONG).show();
}
};
}
A Toast will be displayed in onCreateDialog(), to show that DatePickerDialog() will be created once only (in the first time display the dialog).
Download the files.
Wednesday, 30 December 2009
Uses tabs to navigate between different views, TabWidget.
A TabWidget offers the ability to easily draw an interface that uses tabs to navigate between different views.
Start a new Android Application, named AndrodTab extends TabActivity.
To use TabWidget, a TabHost have to be used to contain the entire layout of the Activity. A TabHost requires two descendant elements: a TabWidget and a FrameLayout. In order to properly layout these elements, we've put them inside a vertical LinearLayout. Otherwise, the TabWidget and FrameLayout will overlay each other. The FrameLayout is where we keep the content that will change with each tab. Each child in the FrameLayout will be associated with a different tab.
Modify the main.xml
Finally, modify the method onCreate() in AndroidTab.java
getTabHost() returns a reference to the TabHost. Then call addTab() for each of the tabs to add them into the TabHost. setIndicator() set the text for the tab button, and setContent() define the View associate with the tab. At the end, call setCurrentTab() to define which tab should be opened by default.
Download the files.
Start a new Android Application, named AndrodTab extends TabActivity.
To use TabWidget, a TabHost have to be used to contain the entire layout of the Activity. A TabHost requires two descendant elements: a TabWidget and a FrameLayout. In order to properly layout these elements, we've put them inside a vertical LinearLayout. Otherwise, the TabWidget and FrameLayout will overlay each other. The FrameLayout is where we keep the content that will change with each tab. Each child in the FrameLayout will be associated with a different tab.
Modify the main.xml
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/tabview1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="tabview1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Just put something here" />
/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/tabview2">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="tabview2" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A" />
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B" />
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C" />
/>
</LinearLayout>
<TextView
android:id="@+id/tabview3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="tabview3" />
</FrameLayout>
</LinearLayout>
</TabHost>
Finally, modify the method onCreate() in AndroidTab.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TabHost mTabHost = getTabHost();
mTabHost.addTab(mTabHost.newTabSpec("tab_test1")
.setIndicator("TAB 1")
.setContent(R.id.tabview1));
mTabHost.addTab(mTabHost.newTabSpec("tab_test2")
.setIndicator("TAB 2")
.setContent(R.id.tabview2));
mTabHost.addTab(mTabHost.newTabSpec("tab_test3")
.setIndicator("TAB 3")
.setContent(R.id.tabview3));
mTabHost.setCurrentTab(0);
}
getTabHost() returns a reference to the TabHost. Then call addTab() for each of the tabs to add them into the TabHost. setIndicator() set the text for the tab button, and setContent() define the View associate with the tab. At the end, call setCurrentTab() to define which tab should be opened by default.
Download the files.
Use system wallpaper as application's wallpaper
Just as Android provides other built-in resources, there are several themes that you swap in without having to write one yourself.
To set this theme for all the activites of your application, open the AndroidManifest.xml file and edit the <application> tag to include the android:theme attribute with the theme name.
If you want the theme applied to just one Activity in your application, then add the theme attribute to the <activity> tag, instead.
If you want to use system wallpaper as your own application's wall paper, add android:theme="@android:style/Theme.Wallpaper" in your AndroidManifest.xml.
Example:
To set this theme for all the activites of your application, open the AndroidManifest.xml file and edit the <application> tag to include the android:theme attribute with the theme name.
If you want the theme applied to just one Activity in your application, then add the theme attribute to the <activity> tag, instead.
If you want to use system wallpaper as your own application's wall paper, add android:theme="@android:style/Theme.Wallpaper" in your AndroidManifest.xml.
Example:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidSysTheme"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@android:style/Theme.Wallpaper"
>
<activity android:name=".AndroidSysTheme"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5" />
</manifest>
Sunday, 27 December 2009
Read Exif information in a JPEG file, ExifInterface
ExifInterface is a class for reading and writing Exif tags in a JPEG file. Here is a simple exercise to read Exif tags. To make it simple, it will read a fixed JPG file from SD Card. The name and path of the JPG file is hard coded.
Refer to the article "Create SD Card in Android Emulator and copy files into, in Eclipse, Emulator and DDMS" to copy a JPG file with Exif into SD Card. And also, you have to update the program code with your own path and file name.
Create a Android Application, AndroidExif, with the following setting.
Project Name: AndroidExif
Build Target: Google APIs/Platform 2.0/API Level 5
Application name: AndroidExif
Package name: com.exercise.AndroidExif
Create Activity: AndroidExif
Min SDK Version: 5
Modify the layout file, main.xml, to assign id on the TextView.
Modify the code, AndroidExif.java, to implement our Activity to read Exif.
Download the files.
Refer to the article "Create SD Card in Android Emulator and copy files into, in Eclipse, Emulator and DDMS" to copy a JPG file with Exif into SD Card. And also, you have to update the program code with your own path and file name.
Create a Android Application, AndroidExif, with the following setting.
Project Name: AndroidExif
Build Target: Google APIs/Platform 2.0/API Level 5
Application name: AndroidExif
Package name: com.exercise.AndroidExif
Create Activity: AndroidExif
Min SDK Version: 5
Modify the layout file, main.xml, to assign id on the TextView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>
Modify the code, AndroidExif.java, to implement our Activity to read Exif.
package com.exercise.AndroidExif;
import java.io.IOException;
import android.app.Activity;
import android.media.ExifInterface;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
public class AndroidExif extends Activity {
TextView myTextView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myTextView = (TextView)findViewById(R.id.textview);
//change with the filename & location of your photo file
String filename = "/sdcard/DSC_3509.JPG";
try {
ExifInterface exif = new ExifInterface(filename);
ShowExif(exif);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(this, "Error!",
Toast.LENGTH_LONG).show();
}
}
private void ShowExif(ExifInterface exif)
{
String myAttribute="Exif information ---\n";
myAttribute += getTagString(ExifInterface.TAG_DATETIME, exif);
myAttribute += getTagString(ExifInterface.TAG_FLASH, exif);
myAttribute += getTagString(ExifInterface.TAG_GPS_LATITUDE, exif);
myAttribute += getTagString(ExifInterface.TAG_GPS_LATITUDE_REF, exif);
myAttribute += getTagString(ExifInterface.TAG_GPS_LONGITUDE, exif);
myAttribute += getTagString(ExifInterface.TAG_GPS_LONGITUDE_REF, exif);
myAttribute += getTagString(ExifInterface.TAG_IMAGE_LENGTH, exif);
myAttribute += getTagString(ExifInterface.TAG_IMAGE_WIDTH, exif);
myAttribute += getTagString(ExifInterface.TAG_MAKE, exif);
myAttribute += getTagString(ExifInterface.TAG_MODEL, exif);
myAttribute += getTagString(ExifInterface.TAG_ORIENTATION, exif);
myAttribute += getTagString(ExifInterface.TAG_WHITE_BALANCE, exif);
myTextView.setText(myAttribute);
}
private String getTagString(String tag, ExifInterface exif)
{
return(tag + " : " + exif.getAttribute(tag) + "\n");
}
}
Download the files.
Wednesday, 23 December 2009
Android Scripting Environment, ase_r15.apk, just released.
The Android Scripting Environment (ASE) brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreters directly on the Android device. These scripts have access to many of the APIs available to full-fledged Android applications, but with a greatly simplified interface.
android-scripting Project Home>>
My old article, android-scripting: Android Scripting Environment, described how to install Android Scripting Environment on Android Emulator.
android-scripting Project Home>>
My old article, android-scripting: Android Scripting Environment, described how to install Android Scripting Environment on Android Emulator.
AndroidMapper files list
It's a bug here:
Using onTouchEvent(MotionEvent, MapView) to handle user touching as in the example, it's work fine on Android Emulator, but not working on true phone.
Please refer to another article "Problem of onTouchEvent(MotionEvent, MapView) on MapView" for details.
Android Er@2010-06-22
------------------------------------------------
The the passed articles, I have a series to describe the steps in implementing AndroidMapper, a Android application to get and update location using MapView. Here is a list of the related article:
- Exercise AndroidMapper, Android Application using MapView
- Display a marker on MapView, using Overlays
- Get center location of a map, using MapView.getMapCenter()
- Move the marker on MapView
- Move the marker on MapView with Zoom Control Seekbar
- Implement a Help Dialog, using onCreateOptionsMenu(), onOptionsItemSelected() and AlertDialog.Builder
- Add options menu on MapView
- AndroidMapper: return result in Bundle
Related articles:
- Change GPS location of Android Emulator
- Obtaining a Maps API Key
Download the files.
Using onTouchEvent(MotionEvent, MapView) to handle user touching as in the example, it's work fine on Android Emulator, but not working on true phone.
Please refer to another article "Problem of onTouchEvent(MotionEvent, MapView) on MapView" for details.
Android Er@2010-06-22
------------------------------------------------
The the passed articles, I have a series to describe the steps in implementing AndroidMapper, a Android application to get and update location using MapView. Here is a list of the related article:
- Exercise AndroidMapper, Android Application using MapView
- Display a marker on MapView, using Overlays
- Get center location of a map, using MapView.getMapCenter()
- Move the marker on MapView
- Move the marker on MapView with Zoom Control Seekbar
- Implement a Help Dialog, using onCreateOptionsMenu(), onOptionsItemSelected() and AlertDialog.Builder
- Add options menu on MapView
- AndroidMapper: return result in Bundle
Related articles:
- Change GPS location of Android Emulator
- Obtaining a Maps API Key
Download the files.
AndroidMapper: return result in Bundle.
It's (may be) the last article in the series of AndroidMapper. Here, methods exitOk() and exitCancel() in AndroidMapView were implemented to return or ignore the updated location back to the main activity, AndroidMapper. As you know, a application return nothing after processed is useless!
In exitOk() method in AndroidMapView, the updated location will be packed inside Bundle, and finish() with RESULT_OK.
In exitCancel() method in AndroidMapView, simple finish() with RESULT_CANCELED.
In onActivityResult() in AndroidMapper, resultCode will be checked if it's RESULT_OK. If yes, the data inside Bundle will be used to update mylongitude and mylatitude.
Download the files.
In exitOk() method in AndroidMapView, the updated location will be packed inside Bundle, and finish() with RESULT_OK.
private void exitOk()
{
Bundle bundle = new Bundle();
bundle.putInt("Longitude", updatedGeoPoint.getLongitudeE6());
bundle.putInt("Latitude", updatedGeoPoint.getLatitudeE6());
Intent intent = new Intent();
intent.putExtras(bundle);
setResult(RESULT_OK, intent);
finish();
}
In exitCancel() method in AndroidMapView, simple finish() with RESULT_CANCELED.
private void exitCancel()
{
Intent intent = new Intent();
setResult(RESULT_CANCELED, intent);
finish();
}
In onActivityResult() in AndroidMapper, resultCode will be checked if it's RESULT_OK. If yes, the data inside Bundle will be used to update mylongitude and mylatitude.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if(resultCode==RESULT_OK)
{
Bundle extras = data.getExtras();
String mylongitudeText = String.valueOf((float)extras.getInt("Longitude")/1000000);
String mylatitudeText = String.valueOf((float)extras.getInt("Latitude")/1000000);
mylongitude.setText(mylongitudeText);
mylatitude.setText(mylatitudeText);
validLocation();
}
}
Download the files.
Monday, 21 December 2009
Add options menu on MapView
Further works on the exercise, AndroidMapper. A options menu will be added in AndroidMapView using XML; with options of OK, Cancel, Reload and Help.
Reload: is used to reload the initiate location.
Help: display the help message.
OK and Cancel: not yet implemented. They will be used to return to the last Activity, AndroidMapper, with or ignore the updated location.
To know more about how to add options menu using XML, refer to the article Implement option menu using XML.
Download the files.
Reload: is used to reload the initiate location.
Help: display the help message.
OK and Cancel: not yet implemented. They will be used to return to the last Activity, AndroidMapper, with or ignore the updated location.
To know more about how to add options menu using XML, refer to the article Implement option menu using XML.
Download the files.
Sunday, 20 December 2009
Implement option menu using XML
In my old articles, "Exercise: Menu and Dialog" and "Implement a Help Dialog, using onCreateOptionsMenu(), onOptionsItemSelected() and AlertDialog.Builder", option menu was added using programmatic coding. In this article, another method to implement option menu, using XML, will be introduced.
First of all, create a new Android application AndroidOptionMenu.
Create a folder, "menu", under /res
Create a menu.xml under /res/menu
Modify AndroidOptionMenu.java to implement the methods onCreateOptionsMenu(Menu menu) and onOptionsItemSelected(MenuItem item):
First of all, create a new Android application AndroidOptionMenu.
Create a folder, "menu", under /res
Create a menu.xml under /res/menu
<?xml version="1.0" encoding="UTF-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_help"
android:title="Help" />
<item android:id="@+id/menu_OK"
android:title="OK" />
<item android:id="@+id/menu_Cancel"
android:title="Cancel" />
</menu>
Modify AndroidOptionMenu.java to implement the methods onCreateOptionsMenu(Menu menu) and onOptionsItemSelected(MenuItem item):
package com.exercise.AndroidOptionMenu;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
public class AndroidOptionMenu extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater myMenuInflater = getMenuInflater();
myMenuInflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case(R.id.menu_OK):
Toast.makeText(this, "OK", Toast.LENGTH_LONG).show();
break;
case(R.id.menu_help):
Toast.makeText(this, "Help", Toast.LENGTH_LONG).show();
break;
case(R.id.menu_Cancel):
Toast.makeText(this, "Cancel", Toast.LENGTH_LONG).show();
break;
}
return true;
}
}
Saturday, 19 December 2009
Stack Overflow for Android beginner, a collaboratively edited question and answer site for Android programmers.
Google announced working with Stack Overflow, a collaboratively edited question and answer site for programmers, to improve developer support, especially for developers new to Android. In essence, the Android tag on Stack Overflow will become an official Android app development Q&A medium. Google encourage to post beginner-level technical questions there. It's also important to point out that Google don't plan to change the android-developers group, so intermediate and expert users should still feel free to post there.
Thursday, 17 December 2009
Android device dashboard of Platform Versions
Google just announced the new device dashboard of Platform Versions. It provides information about deployed Android-powered devices that is helpful to developers as they build and update their apps. The dashboard provides the relative distribution of Android platform versions on devices running Android Market.
Data collected during two weeks ending on 12/14/2009
Tuesday, 15 December 2009
More Thoughts on Google OS
After listening to the This week in Google from a few weeks back, I have a better understanding of just what the new Google OS is. It is interesting that Google is targeting the Netbook platform for this OS. With the requirement to essentially have an Internet connection to do anything, this would seem like quite a limitation to me. There are still a lot of places I go with a laptop or netbook where there is no Wifi.
To me a better target might be a really inexpensive desktop replacement. Almost everyone I know now has wifi unless they live in very remote places. The combination of Google Office and OS would meet the needs of about 90% of the folks. Word processing, web surfing, video streaming, social networks, etc.. would all be covered. The only thing I see missing is a replacement for Quicken.
Just think how nice it would be to set up your parents or grandparents on a PC that is always up to date, gets no viruses and is really easy to use. With a low price that would be a very compelling story.
To me a better target might be a really inexpensive desktop replacement. Almost everyone I know now has wifi unless they live in very remote places. The combination of Google Office and OS would meet the needs of about 90% of the folks. Word processing, web surfing, video streaming, social networks, etc.. would all be covered. The only thing I see missing is a replacement for Quicken.
Just think how nice it would be to set up your parents or grandparents on a PC that is always up to date, gets no viruses and is really easy to use. With a low price that would be a very compelling story.
Monday, 14 December 2009
Implement a Help Dialog, using onCreateOptionsMenu(), onOptionsItemSelected() and AlertDialog.Builder.
Follow the code from previouse exercise, Move the marker on MapView with Zoom Control Seekbar.
In this exercise, a OptionsMenu with a single OptionsItem of help will be added.
The option items is added to the option menu in the method onCreateOptionsMenu(), in which initialize the contents of the Activity's standard options menu.
Because it's only one item in the menu, Menu.add(CharSequence title) is used to add item to the menu. Otherwise, Menu.add(int groupId, int itemId, int order, CharSequence title) or Menu.add(int groupId, int itemId, int order, int titleRes) have to be used.
onOptionsItemSelected() will be called whenever an item in options menu is selected. Also, because it's only one item in the menu, so there are no need to check which item have been selected, otherwise, you have to check the itemId.
Add the following three method in the class AndroidMapView:
public boolean onCreateOptionsMenu(Menu menu)
{
menu.add("Help");
return super.onCreateOptionsMenu(menu);
}
private void openOptionsHelpDialog()
{
new AlertDialog.Builder(this)
.setTitle(R.string.help_title).setMessage(R.string.help_message)
.setPositiveButton(R.string.help_ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
}
)
.show();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
super.onOptionsItemSelected(item);
openOptionsHelpDialog();
return true;
}
Implement a file helpmessage.xml in the folder /res/values/, it's used to hold the text used inside the Help Dialog.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="help_title">Help!</string>
<string name="help_message">\n
Pan on the Map: touch the screen and move.\n
Update location: touch on the screen.\n
Zoom: slice on the SeekBar on bottom.\n
</string>
<string name="help_ok">OK</string>
</resources>
Download the files.
Friday, 11 December 2009
Storing Data in Safari for iPhone
Recently I have been thinking of different ways you could store simple text messages and the like on an iPhone. There are a number of note applications out there and you can sync the iPhone note application with some e-mail clients.
Anyway, I ran across this inventive solution, store an entire application in a URL. Its all explained on the Life with Lunchhooks blog. Now that is really cool. Simply put that in a link. Then click the link and save it to your Bookmark list. Whamo-bamo, you have some offline data stored on your iPhone. The only limitation is the data is read only.
But fear not, there are a number of ways you can store applications that can both read and write offline. Apple has this offline application programming guide on their web site. Really neat stuff. I gotta find some time to play with this. :)
Anyway, I ran across this inventive solution, store an entire application in a URL. Its all explained on the Life with Lunchhooks blog. Now that is really cool. Simply put that in a link. Then click the link and save it to your Bookmark list. Whamo-bamo, you have some offline data stored on your iPhone. The only limitation is the data is read only.
But fear not, there are a number of ways you can store applications that can both read and write offline. Apple has this offline application programming guide on their web site. Really neat stuff. I gotta find some time to play with this. :)
Optimize your layouts using layoutopt
layoutopt is a command-line tool that helps you optimize the layouts and layout hierarchies of your applications. You can run it against your layout files or resource directories to quickly check for inefficiencies or other types of problems that could be affecting the performance of your application.
Wednesday, 9 December 2009
Move the marker on MapView with Zoom Control Seekbar
In the last exercise, Move the marker on MapView, user touch on screen to pan the Map and update marker. It's very confuse with the BuiltInZoomControls function. So I separate the zoom function outside the MapView in this exercise. It's a SeekBar under the MapView, user can change the zoom level by sliding on the SeekBar.
It involve modification on mymapview.xml and AndroidMapView.java.
mymapview.xml
AndroidMapView.java
Download the files.
It involve modification on mymapview.xml and AndroidMapView.java.
mymapview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<CheckBox
android:id="@+id/satellite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" Satellite "
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/longitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Longitude:"
/>
<TextView
android:id="@+id/latitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Latitude:"
/>
</LinearLayout>
</LinearLayout>
<com.google.android.maps.MapView
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
android:apiKey="0pkoAyp5YM52XRlxoRPJeJbP0Tp69yYlrRO7lJg"
/>
<SeekBar
android:id="@+id/zoombar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="20"
android:progress="0"/>
</LinearLayout>
AndroidMapView.java
package com.AndroidMapper;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
public class AndroidMapView extends MapActivity {
private TextView myLongitude, myLatitude;
private CheckBox mySatellite;
private MapView myMapView;
private MapController myMapController;
private SeekBar myZoomBar;
private void SetSatellite()
{
myMapView.setSatellite(mySatellite.isChecked());
};
@Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.mymapview);
Bundle bundle = this.getIntent().getExtras();
int Mode = bundle.getInt("Mode");
myMapView = (MapView)findViewById(R.id.mapview);
myMapController = myMapView.getController();
myMapView.setBuiltInZoomControls(false);
myLongitude = (TextView)findViewById(R.id.longitude);
myLatitude = (TextView)findViewById(R.id.latitude);
mySatellite = (CheckBox)findViewById(R.id.satellite);
mySatellite.setOnClickListener(mySatelliteOnClickListener);
myZoomBar = (SeekBar)findViewById(R.id.zoombar);
SetZoomLevel();
myZoomBar.setOnSeekBarChangeListener(myZoomBarOnSeekBarChangeListener);
SetSatellite();
if(Mode == 0)
{
GeoPoint initGeoPoint = myMapView.getMapCenter();
CenterLocation(initGeoPoint);
}
else if(Mode == 1)
{
int intLatitude = bundle.getInt("Latitude");
int intLongitude = bundle.getInt("Longitude");
GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
CenterLocation(initGeoPoint);
}
}
private SeekBar.OnSeekBarChangeListener myZoomBarOnSeekBarChangeListener =
new SeekBar.OnSeekBarChangeListener(){
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
SetZoomLevel();
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
};
private void SetZoomLevel()
{
int myZoomLevel = myZoomBar.getProgress()+1;
myMapController.setZoom(myZoomLevel);
Toast.makeText(this,
"Zoom Level : " + String.valueOf(myZoomLevel),
Toast.LENGTH_LONG).show();
};
private void placeMarker(int markerLatitude, int markerLongitude)
{
Drawable marker=getResources().getDrawable(
android.R.drawable.ic_menu_myplaces);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
myMapView.getOverlays().add(new InterestingLocations(marker,
markerLatitude, markerLongitude));
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private void CenterLocation(GeoPoint centerGeoPoint)
{
myMapController.animateTo(centerGeoPoint);
myLongitude.setText("Longitude: "+
String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000));
myLatitude.setText("Latitude: "+
String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000));
placeMarker(centerGeoPoint.getLatitudeE6(),
centerGeoPoint.getLongitudeE6());
};
private CheckBox.OnClickListener mySatelliteOnClickListener =
new CheckBox.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
SetSatellite();
}
};
class InterestingLocations extends ItemizedOverlay<OverlayItem>{
private List<OverlayItem> locations =
new ArrayList<OverlayItem>();
private Drawable marker;
private OverlayItem myOverlayItem;
boolean MoveMap;
public InterestingLocations(Drawable defaultMarker,
int LatitudeE6, int LongitudeE6) {
super(defaultMarker);
// TODO Auto-generated constructor stub
this.marker=defaultMarker;
// create locations of interest
GeoPoint myPlace = new GeoPoint(LatitudeE6,LongitudeE6);
myOverlayItem = new OverlayItem(myPlace, "My Place", "My Place");
locations.add(myOverlayItem);
populate();
}
@Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return locations.get(i);
}
@Override
public int size() {
// TODO Auto-generated method stub
return locations.size();
}
@Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
// TODO Auto-generated method stub
super.draw(canvas, mapView, shadow);
boundCenterBottom(marker);
}
@Override
public boolean onTouchEvent(MotionEvent arg0, MapView arg1) {
// TODO Auto-generated method stub
//super.onTouchEvent(arg0, arg1);
int Action = arg0.getAction();
if (Action == MotionEvent.ACTION_UP){
if(!MoveMap)
{
Projection proj = myMapView.getProjection();
GeoPoint loc = proj.fromPixels((int)arg0.getX(), (int)arg0.getY());
//remove the last marker
myMapView.getOverlays().remove(0);
CenterLocation(loc);
}
}
else if (Action == MotionEvent.ACTION_DOWN){
MoveMap = false;
}
else if (Action == MotionEvent.ACTION_MOVE){
MoveMap = true;
}
return super.onTouchEvent(arg0, arg1);
//return false;
}
}
}
Download the files.
Tuesday, 8 December 2009
Word Wrap in Linux/Unix/OS X
Have you ever needed to word wrap a text document at a specific width? Well I did and I found out there is a Unix utility that called fold that does this. Check out an explanation on the nixCraft blog.
Move the marker on MapView
It's a bug here:
Using onTouchEvent(MotionEvent, MapView) to handle user touching as in the example, it's work fine on Android Emulator, but not working on true phone.
Please refer to another article "Problem of onTouchEvent(MotionEvent, MapView) on MapView" for details.
Thanks thibault let me know the case:)
Android Er@2010-06-22
------------------------------------------------
In the last exercises, Display a marker on MapView, using Overlays and Get center location of a map, using MapView.getMapCenter(), a marker is displayed on the center of the MapView. In this exercise, I want to add the capability of moving the marker on the Map. Unfortunately, I can't find any solution (from books and internet) to move (drag) the marker on MapView, similar to web version. Finally, I made a alternative.
If user Touch on screen without moving, it will be treated as update marker, the marker will be place on the new location, and it will be centered on the MapView. If user Touch on screen and Move, it will be treated as pan the MapView, the marker will not be changed.
The main logic is in the method onTouchEvent(MotionEvent arg0, MapView arg1), ACTION_UP, ACTION_DOWN and ACTION_MOVE cases.
((int)arg0.getX(), (int)arg0.getY()) is the on-screen pixel coordinates, it can be translated to latitude/longitude(GePoint) using Projection.fromPixels.
AndroidMapView.java
Download the files.
Using onTouchEvent(MotionEvent, MapView) to handle user touching as in the example, it's work fine on Android Emulator, but not working on true phone.
Please refer to another article "Problem of onTouchEvent(MotionEvent, MapView) on MapView" for details.
Thanks thibault let me know the case:)
Android Er@2010-06-22
------------------------------------------------
In the last exercises, Display a marker on MapView, using Overlays and Get center location of a map, using MapView.getMapCenter(), a marker is displayed on the center of the MapView. In this exercise, I want to add the capability of moving the marker on the Map. Unfortunately, I can't find any solution (from books and internet) to move (drag) the marker on MapView, similar to web version. Finally, I made a alternative.
If user Touch on screen without moving, it will be treated as update marker, the marker will be place on the new location, and it will be centered on the MapView. If user Touch on screen and Move, it will be treated as pan the MapView, the marker will not be changed.
The main logic is in the method onTouchEvent(MotionEvent arg0, MapView arg1), ACTION_UP, ACTION_DOWN and ACTION_MOVE cases.
((int)arg0.getX(), (int)arg0.getY()) is the on-screen pixel coordinates, it can be translated to latitude/longitude(GePoint) using Projection.fromPixels.
AndroidMapView.java
package com.AndroidMapper;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
public class AndroidMapView extends MapActivity {
private TextView myLongitude, myLatitude;
private CheckBox mySatellite;
private MapView myMapView;
private MapController myMapController;
private void SetSatellite()
{
myMapView.setSatellite(mySatellite.isChecked());
};
@Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.mymapview);
Bundle bundle = this.getIntent().getExtras();
int Mode = bundle.getInt("Mode");
myMapView = (MapView)findViewById(R.id.mapview);
myMapController = myMapView.getController();
myMapView.setBuiltInZoomControls(true);
myLongitude = (TextView)findViewById(R.id.longitude);
myLatitude = (TextView)findViewById(R.id.latitude);
mySatellite = (CheckBox)findViewById(R.id.satellite);
mySatellite.setOnClickListener(mySatelliteOnClickListener);
SetSatellite();
if(Mode == 0)
{
GeoPoint initGeoPoint = myMapView.getMapCenter();
CenterLocation(initGeoPoint);
}
else if(Mode == 1)
{
int intLatitude = bundle.getInt("Latitude");
int intLongitude = bundle.getInt("Longitude");
GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
CenterLocation(initGeoPoint);
}
}
private void placeMarker(int markerLatitude, int markerLongitude)
{
Drawable marker=getResources().getDrawable(
android.R.drawable.ic_menu_myplaces);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
myMapView.getOverlays().add(new InterestingLocations(marker,
markerLatitude, markerLongitude));
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private void CenterLocation(GeoPoint centerGeoPoint)
{
myMapController.animateTo(centerGeoPoint);
myLongitude.setText("Longitude: "+
String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000));
myLatitude.setText("Latitude: "+
String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000));
placeMarker(centerGeoPoint.getLatitudeE6(),
centerGeoPoint.getLongitudeE6());
};
private CheckBox.OnClickListener mySatelliteOnClickListener =
new CheckBox.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
SetSatellite();
}
};
class InterestingLocations extends ItemizedOverlay<OverlayItem>{
private List<OverlayItem> locations =
new ArrayList<OverlayItem>();
private Drawable marker;
private OverlayItem myOverlayItem;
boolean MoveMap;
public InterestingLocations(Drawable defaultMarker,
int LatitudeE6, int LongitudeE6) {
super(defaultMarker);
// TODO Auto-generated constructor stub
this.marker=defaultMarker;
// create locations of interest
GeoPoint myPlace = new GeoPoint(LatitudeE6,LongitudeE6);
myOverlayItem = new OverlayItem(myPlace, "My Place", "My Place");
locations.add(myOverlayItem);
populate();
}
@Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return locations.get(i);
}
@Override
public int size() {
// TODO Auto-generated method stub
return locations.size();
}
@Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
// TODO Auto-generated method stub
super.draw(canvas, mapView, shadow);
boundCenterBottom(marker);
}
@Override
public boolean onTouchEvent(MotionEvent arg0, MapView arg1) {
// TODO Auto-generated method stub
//super.onTouchEvent(arg0, arg1);
int Action = arg0.getAction();
if (Action == MotionEvent.ACTION_UP){
if(!MoveMap)
{
Projection proj = myMapView.getProjection();
GeoPoint loc = proj.fromPixels((int)arg0.getX(), (int)arg0.getY());
//remove the last marker
myMapView.getOverlays().remove(0);
CenterLocation(loc);
}
}
else if (Action == MotionEvent.ACTION_DOWN){
MoveMap = false;
}
else if (Action == MotionEvent.ACTION_MOVE){
MoveMap = true;
}
return super.onTouchEvent(arg0, arg1);
//return false;
}
}
}
Download the files.
Sunday, 6 December 2009
MOTODEV Studio for Android
MOTODEV Studio for Android is a Complete Development Package: One installer ensures an integrated development environment with Eclipse 3.5 and Android Development Tools (ADT) plus automatic download and configuration of the latest Android SDK.
MOTODEV Studio for Android Version 1.0.2 now support Android 1.1, Android 1.5, Android 1.6, Android 2.0 (Motorola Droid and Milestone)
MOTODEV Web Site
MOTODEV Studio for Android Version 1.0.2 now support Android 1.1, Android 1.5, Android 1.6, Android 2.0 (Motorola Droid and Milestone)
MOTODEV Web Site
Friday, 4 December 2009
Android 2.0.1, Release 1 is available
Android 2.0.1 is a minor platform release deployable to Android-powered handsets starting in December 2009. This release includes minor API changes, bug fixes and framework behavioral changes.
Details>>>
If you have installed Android 1.6 or later SDK packages with Eclipse, you can update your Android SDK using the Android SDK and AVD Manager.
Click Window on Eclipse top menu, select Android SDK and AVD Manager.
Select Available Packages on the left and select the components you want to update, and click Install Selected.
Click to select Accept All and click Install Accepted.
Wait for Installing, then restart Eclipse.
After Eclipse restarted, click Window -> Preferences, and click Android on the left. You will be asked to update ADT to the latest version.
To update ADT, click Help -> Check for Updates in Eclipse.
The list of Updates will be come out soon. Select All and click Next, and then Finish.
Accept the Security Warning by clicking OK.
And finally accept Restart Eclipse again.
That's All.
Details>>>
If you have installed Android 1.6 or later SDK packages with Eclipse, you can update your Android SDK using the Android SDK and AVD Manager.
Click Window on Eclipse top menu, select Android SDK and AVD Manager.
Select Available Packages on the left and select the components you want to update, and click Install Selected.
Click to select Accept All and click Install Accepted.
Wait for Installing, then restart Eclipse.
After Eclipse restarted, click Window -> Preferences, and click Android on the left. You will be asked to update ADT to the latest version.
To update ADT, click Help -> Check for Updates in Eclipse.
The list of Updates will be come out soon. Select All and click Next, and then Finish.
Accept the Security Warning by clicking OK.
And finally accept Restart Eclipse again.
That's All.
Tuesday, 1 December 2009
Static Factory Methods vs Constructors
I was looking for a good explanation for the advantages of using
static
factory methods instead of constructors. The Redemption in a Blog site has a very good explanation. It just goes to should that old blog posts don't fade away, they just get better with time. :)
Get center location of a map, using MapView.getMapCenter().
In the last exercise, Display a marker on MapView, using Overlays, a marker will be displayed in Mode 1 (with starting location) only. In this exercise, current center location of the Map in Mode 0 (without starting location) will be retrieved using the method MapView.getMapCenter(). Such that the appearance of both mode will be kept consistance.
To achieve it, AndroidMapView have to be modified, to add function in onCreate() to handle Mode 0.
Other files are same as previous exercise.
Download the files.
To achieve it, AndroidMapView have to be modified, to add function in onCreate() to handle Mode 0.
package com.AndroidMapper;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
public class AndroidMapView extends MapActivity {
private TextView myLongitude, myLatitude;
private CheckBox mySatellite;
private MapView myMapView;
private MapController myMapController;
private void SetSatellite()
{
myMapView.setSatellite(mySatellite.isChecked());
};
@Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.mymapview);
Bundle bundle = this.getIntent().getExtras();
int Mode = bundle.getInt("Mode");
myMapView = (MapView)findViewById(R.id.mapview);
myMapController = myMapView.getController();
myMapView.setBuiltInZoomControls(true);
myLongitude = (TextView)findViewById(R.id.longitude);
myLatitude = (TextView)findViewById(R.id.latitude);
mySatellite = (CheckBox)findViewById(R.id.satellite);
mySatellite.setOnClickListener(mySatelliteOnClickListener);
SetSatellite();
if(Mode == 0)
{
GeoPoint initGeoPoint = myMapView.getMapCenter();
CenterLocation(initGeoPoint);
}
else if(Mode == 1)
{
int intLatitude = bundle.getInt("Latitude");
int intLongitude = bundle.getInt("Longitude");
GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
CenterLocation(initGeoPoint);
}
}
private void placeMarker(int markerLatitude, int markerLongitude)
{
Drawable marker=getResources().getDrawable(
android.R.drawable.ic_menu_myplaces);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
myMapView.getOverlays().add(new InterestingLocations(marker,
markerLatitude, markerLongitude));
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private void CenterLocation(GeoPoint centerGeoPoint)
{
myMapController.animateTo(centerGeoPoint);
myLongitude.setText("Longitude: "+
String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000));
myLatitude.setText("Latitude: "+
String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000));
placeMarker(centerGeoPoint.getLatitudeE6(),
centerGeoPoint.getLongitudeE6());
};
private CheckBox.OnClickListener mySatelliteOnClickListener =
new CheckBox.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
SetSatellite();
}
};
class InterestingLocations extends ItemizedOverlay<OverlayItem>{
private List<OverlayItem> locations =
new ArrayList<OverlayItem>();
private Drawable marker;
public InterestingLocations(Drawable defaultMarker,
int LatitudeE6, int LongitudeE6) {
super(defaultMarker);
// TODO Auto-generated constructor stub
this.marker=defaultMarker;
// create locations of interest
GeoPoint myPlace = new GeoPoint(LatitudeE6,LongitudeE6);
locations.add(new OverlayItem(myPlace ,
"My Place", "My Place"));
populate();
}
@Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return locations.get(i);
}
@Override
public int size() {
// TODO Auto-generated method stub
return locations.size();
}
@Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
// TODO Auto-generated method stub
super.draw(canvas, mapView, shadow);
boundCenterBottom(marker);
}
}
}
Other files are same as previous exercise.
Download the files.
Friday, 27 November 2009
Display a marker on MapView, using Overlays.
Expends from last exercise, AndroidMapper. A marker is shown on the current location using Overlays, if MapView started with location, Mode 1.
To use Overlays, a class of InterestingLocations have to be created, extends ItemizedOverlay.
It involve modification on AndroidMapView.java
Download the files.
To use Overlays, a class of InterestingLocations have to be created, extends ItemizedOverlay.
It involve modification on AndroidMapView.java
package com.AndroidMapper;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
public class AndroidMapView extends MapActivity {
private TextView myLongitude, myLatitude;
private CheckBox mySatellite;
private MapView myMapView;
private MapController myMapController;
private void SetSatellite()
{
myMapView.setSatellite(mySatellite.isChecked());
};
@Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.mymapview);
Bundle bundle = this.getIntent().getExtras();
int Mode = bundle.getInt("Mode");
myMapView = (MapView)findViewById(R.id.mapview);
myMapController = myMapView.getController();
myMapView.setBuiltInZoomControls(true);
myLongitude = (TextView)findViewById(R.id.longitude);
myLatitude = (TextView)findViewById(R.id.latitude);
mySatellite = (CheckBox)findViewById(R.id.satellite);
mySatellite.setOnClickListener(mySatelliteOnClickListener);
SetSatellite();
if(Mode == 1)
{
int intLatitude = bundle.getInt("Latitude");
int intLongitude = bundle.getInt("Longitude");
GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
CenterLocation(initGeoPoint);
Drawable marker=getResources().getDrawable(
android.R.drawable.ic_menu_myplaces);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
myMapView.getOverlays().add(new InterestingLocations(marker,
intLatitude, intLongitude));
}
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private void CenterLocation(GeoPoint centerGeoPoint)
{
myMapController.animateTo(centerGeoPoint);
myLongitude.setText("Longitude: "+
String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000)
);
myLatitude.setText("Latitude: "+
String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000)
);
};
private CheckBox.OnClickListener mySatelliteOnClickListener =
new CheckBox.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
SetSatellite();
}
};
class InterestingLocations extends ItemizedOverlay<OverlayItem>{
private List<OverlayItem> locations =
new ArrayList<OverlayItem>();
private Drawable marker;
public InterestingLocations(Drawable defaultMarker,
int LatitudeE6, int LongitudeE6) {
super(defaultMarker);
// TODO Auto-generated constructor stub
this.marker=defaultMarker;
// create locations of interest
GeoPoint myPlace = new GeoPoint(LatitudeE6,LongitudeE6);
locations.add(new OverlayItem(myPlace ,
"My Place", "My Place"));
populate();
}
@Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return locations.get(i);
}
@Override
public int size() {
// TODO Auto-generated method stub
return locations.size();
}
@Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
// TODO Auto-generated method stub
super.draw(canvas, mapView, shadow);
boundCenterBottom(marker);
}
}
}
Download the files.
Adding ls and ll to Windows
When I set up a new windows machine, one of the first things I do is setup a simple alias for Unix
Here are the two files I typically create in the Windows directory. If running Windows 7, you will need to run your editor or command prompt as administrator to create the files.
ls.bat
ll.bat
The extra variables allow you to add extra command line parameters or pass a directory path. Not fancy, but it gets the job done. And, I don't have to think when I need a directory listing.
ls
command and the ll
alias I usually have setup for ls -l
. You don't have to install any special software. Just create two very simple batch files.Here are the two files I typically create in the Windows directory. If running Windows 7, you will need to run your editor or command prompt as administrator to create the files.
ls.bat
dir %1 %2 %3 %4 %5
ll.bat
dir /w %1 %2 %3 %4 %5
The extra variables allow you to add extra command line parameters or pass a directory path. Not fancy, but it gets the job done. And, I don't have to think when I need a directory listing.
Thursday, 26 November 2009
Apache, MySQL and PHP for Windows 7 Starter
Windows 7 starter edition is pretty bare bones. So when I decided I wanted to look into doing some limited web development on my netbook, I needed to install something very small. After Googling around a bit I found this server: http://www.uniformserver.com/
The Uniform Server is a Windows, Apache, MySQL, PHP bundle for Windows designed to work off flash drives. The whole package zips into a file that is only 10 megs. In addition, all the software runs from the directory the software is unzipped into. No registry changes needed. Just run the start.exe program and everything runs. Very cool.
The Uniform Server is a Windows, Apache, MySQL, PHP bundle for Windows designed to work off flash drives. The whole package zips into a file that is only 10 megs. In addition, all the software runs from the directory the software is unzipped into. No registry changes needed. Just run the start.exe program and everything runs. Very cool.
Chrome OS
After launching the Go programming language, Google followed up with the announcement of their Chrome operating system. I know I am a week or two late on this post, but I have been busy. :) Basically, Chrome OS is a Linux distro optimized to be Net connected. The early target hardware appears to be Netbooks. Here are some links to details.
- GeekSmack has a nice detailed review of the OS
- Googles original announcement
- Chrome Blog Announcement and Videos
- Download from GDGT
An OS that is basically just a browser is an interesting idea. With the way things are moving to the Net, I suppose you will be able to find everything you need online. And of course, Google wants to promote their online office apps. But I think I would still want a full featured OS. The computer biz will be interesting the next 5 years.
Monday, 23 November 2009
Exercise AndroidMapper, Android Application using MapView
In the previous exercises, the MapView track the GPS and center on it repeatly. In this exercise, AndroidMapper, it will not track on GPS. Instead, there are three options to center in starting of the MapView.
- Default: Start ViewMap without any center location.
- GPS: It's the current GPS (which will be track before ViewMap start). If no valid GPS, this option will be disable.
- Location: User input location. If no location input, this option will be disable.
After ViewMap loaded, user can move the Map, Zoom-in/out using MapView's BuiltInZoomControls.
This application is not yet finished, more feature (or bug fixed) will be added in the furture.
Create a Android Application named, AndroidMapper.
Package Name: com.AndroidMapper
Target Google Platform 2.0 with Google APIs.
Modify main.xml to have the UI as seen in the picture.
Modify AndroidMapper.java
Modify mymapview.xml
Modify AndroidMapView.java
Also modify AndroidManifest.xml
Download the files.
- Default: Start ViewMap without any center location.
- GPS: It's the current GPS (which will be track before ViewMap start). If no valid GPS, this option will be disable.
- Location: User input location. If no location input, this option will be disable.
After ViewMap loaded, user can move the Map, Zoom-in/out using MapView's BuiltInZoomControls.
This application is not yet finished, more feature (or bug fixed) will be added in the furture.
Create a Android Application named, AndroidMapper.
Package Name: com.AndroidMapper
Target Google Platform 2.0 with Google APIs.
Modify main.xml to have the UI as seen in the picture.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/option_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Default Location" />
<RadioButton
android:id="@+id/option_gps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GPS:" />
<RadioButton
android:id="@+id/option_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Location:" />
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="latitude"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/latitude"
android:inputType="numberDecimal"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="longitude"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/longitude"
android:inputType="numberDecimal"
/>
<Button
android:id="@+id/loadmap"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load Map"
/>
</LinearLayout>
Modify AndroidMapper.java
package com.AndroidMapper;
import com.google.android.maps.GeoPoint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
public class AndroidMapper extends Activity {
private LocationManager myLocationManager;
private LocationListener myLocationListener;
private GeoPoint GeoPoint_GPS, GeoPoint_Location;
RadioButton myoption_default, myoption_gps, myoption_location;
EditText mylatitude, mylongitude;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadMenu();
validGPS();
validLocation();
myLocationManager = (LocationManager)getSystemService(
Context.LOCATION_SERVICE);
myLocationListener = new MyLocationListener();
myLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
0,
0,
myLocationListener);
}
private void loadMenu()
{
setContentView(R.layout.main);
myoption_default = (RadioButton)findViewById(R.id.option_default);
myoption_gps = (RadioButton)findViewById(R.id.option_gps);
myoption_location = (RadioButton)findViewById(R.id.option_location);
mylatitude = (EditText)findViewById(R.id.latitude);
mylongitude = (EditText)findViewById(R.id.longitude);
mylatitude.setOnKeyListener(locationOnKeyListener);
mylongitude.setOnKeyListener(locationOnKeyListener);
Button myLoadMapButton = (Button)findViewById(R.id.loadmap);
myLoadMapButton.setOnClickListener(myLoadMapButtonOnClickListener);
}
Button.OnClickListener myLoadMapButtonOnClickListener =
new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(myoption_default.isChecked()){
OpenIntentAndroidMapView(null);
}
else if(myoption_gps.isChecked()){
OpenIntentAndroidMapView(GeoPoint_GPS);
}
else if(myoption_location.isChecked()){
OpenIntentAndroidMapView(GeoPoint_Location);
}
else{
OpenMissingOptionDialog();
}
}
};
private void OpenIntentAndroidMapView(GeoPoint startLocation)
{
Intent intent = new Intent();
intent.setClass(AndroidMapper.this, AndroidMapView.class);
Bundle bundle = new Bundle();
if (startLocation == null)
{
bundle.putInt("Mode", 0);
}
else
{
bundle.putInt("Mode", 1);
bundle.putInt("Longitude", startLocation.getLongitudeE6());
bundle.putInt("Latitude", startLocation.getLatitudeE6());
}
intent.putExtras(bundle);
startActivityForResult(intent, 0);
}
private void OpenMissingOptionDialog()
{
new AlertDialog.Builder(this)
.setTitle("missing selection")
.setMessage("Please select one of the option")
.setPositiveButton("OK",
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface, int i)
{}
})
.show();
}
EditText.OnKeyListener locationOnKeyListener =
new EditText.OnKeyListener(){
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
validLocation();
return false;
}
};
private void validGPS()
{
GeoPoint_GPS = loadGPS();
if (GeoPoint_GPS==null)
{
myoption_gps.setClickable(false);
}
else
{
myoption_gps.setText("GPS: (" +
String.valueOf((float)GeoPoint_GPS.getLatitudeE6()/1000000) +" : " +
String.valueOf((float)GeoPoint_GPS.getLongitudeE6()/1000000) +")");
myoption_gps.setClickable(true);
}
}
private void validLocation()
{
/*
Toast.makeText(AndroidMapper.this,
mylatitude.getText().toString(),
Toast.LENGTH_LONG).show();*/
if (mylatitude.getText().toString().equals("") || mylongitude.getText().toString().equals(""))
{
myoption_location.setText("Location: ");
myoption_location.setClickable(false);
myoption_location.setChecked(false);
}
else
{
float locationLatitude = Float.parseFloat(mylatitude.getText().toString());
float locationLongitude = Float.parseFloat(mylongitude.getText().toString());
myoption_location.setText("Location: (" +
String.valueOf(locationLatitude) +" : " +
String.valueOf(locationLongitude) +")");
myoption_location.setClickable(true);
myoption_location.setChecked(true);
GeoPoint_Location = new GeoPoint(
(int)(locationLatitude*1000000),
(int)(locationLongitude*1000000));
}
}
private GeoPoint loadGPS()
{
//Get the current location from GPS
myLocationManager = (LocationManager)getSystemService(
Context.LOCATION_SERVICE);
Location initLocation=myLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(initLocation != null)
{
return (
new GeoPoint(
(int)(initLocation.getLatitude()*1000000),
(int)(initLocation.getLongitude()*1000000)));
}
else
return null;
}
private class MyLocationListener implements LocationListener{
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
GeoPoint_GPS = new GeoPoint(
(int)(location.getLatitude()*1000000),
(int)(location.getLongitude()*1000000));
myoption_gps.setText("GPS: (" +
String.valueOf((float)GeoPoint_GPS.getLatitudeE6()/1000000) +" : " +
String.valueOf((float)GeoPoint_GPS.getLongitudeE6()/1000000) +")");
myoption_gps.setClickable(true);
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
}
Modify mymapview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<CheckBox
android:id="@+id/satellite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" Satellite "
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/longitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Longitude:"
/>
<TextView
android:id="@+id/latitude"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Latitude:"
/>
</LinearLayout>
</LinearLayout>
<com.google.android.maps.MapView
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:apiKey="-----Your Own API Key here-------------"
/>
</LinearLayout>
You have to Obtaining a Maps API Key, and insert into the field "apikey"Modify AndroidMapView.java
package com.AndroidMapper;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
public class AndroidMapView extends MapActivity {
private TextView myLongitude, myLatitude;
private CheckBox mySatellite;
private MapView myMapView;
private MapController myMapController;
private void SetSatellite()
{
myMapView.setSatellite(mySatellite.isChecked());
};
@Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.mymapview);
Bundle bundle = this.getIntent().getExtras();
int Mode = bundle.getInt("Mode");
myMapView = (MapView)findViewById(R.id.mapview);
myMapController = myMapView.getController();
myMapView.setBuiltInZoomControls(true);
myLongitude = (TextView)findViewById(R.id.longitude);
myLatitude = (TextView)findViewById(R.id.latitude);
mySatellite = (CheckBox)findViewById(R.id.satellite);
mySatellite.setOnClickListener(mySatelliteOnClickListener);
SetSatellite();
if(Mode == 1)
{
int intLatitude = bundle.getInt("Latitude");
int intLongitude = bundle.getInt("Longitude");
GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
CenterLocation(initGeoPoint);
}
}
@Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
private void CenterLocation(GeoPoint centerGeoPoint)
{
myMapController.animateTo(centerGeoPoint);
myLongitude.setText("Longitude: "+
String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000)
);
myLatitude.setText("Latitude: "+
String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000)
);
};
private CheckBox.OnClickListener mySatelliteOnClickListener =
new CheckBox.OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
SetSatellite();
}
};
}
Also modify AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.AndroidMapper"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidMapper"
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=".AndroidMapView">
</activity>
<uses-library android:name="com.google.android.maps" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-sdk android:minSdkVersion="5" />
</manifest>
Download the files.
Subscribe to:
Posts (Atom)