Thursday, April 28, 2011

Disable screen auto-dim, using PowerManager

The class android.os.PowerManager gives you control of the power state of the device.

Device battery life will be significantly affected by the use of this API. Do not acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure to release it as soon as you can.

You can obtain an instance of this class by calling Context.getSystemService().

package com.exercise.AndroidWakeLock;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;

public class AndroidWakeLock extends Activity {

WakeLock wakeLock;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

PowerManager powerManager =
(PowerManager)getSystemService(Context.POWER_SERVICE);
wakeLock =
powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK,
"Full Wake Lock");
}

@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
wakeLock.acquire();
}

@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
wakeLock.release();
}
}


Also have to grant permission of "android.permission.WAKE_LOCK" in AndroidManifest.xml.

Wednesday, April 27, 2011

Beginning Android Games



Product Description

Beginning Android Games offers everything you need to join the ranks of successful Android game developers. You'll start with game design fundamentals and programming basics, and then progress towards creating your own basic game engine and playable games. This will give you everything you need to branch out and write your own Android games.

The potential user base and the wide array of available high-performance devices makes Android an attractive target for aspiring game developers. Do you have an awesome idea for the next break-through mobile gaming title? Beginning Android Games will help you kick-start your project.

The book will guide you through the process of making several example games for the Android platform, and involves a wide range of topics:

  • The fundamentals of game development
  • The Android platform basics to apply those fundamentals in the context of making a game
  • The design of 2D and 3D games and their successful implementation on the Android platform

What you’ll learn

  • How to set up and use the development tools for developing your first Android application
  • The fundamentals of game programming in the context of the Android platform
  • How to use the Android's APIs for graphics (Canvas, OpenGL ES 1.0/1.1), audio, and user input to reflect those fundamentals
  • How to develop two 2D games from scratch, based on the Canvas API and OpenGL ES.
  • How to create a full-featured 3D game
  • How to publish your games, get crash reports, and support your users
  • How to complete your own playable 2D OpenGL games

Who this book is for

This book is for people with a basic knowledge of Java who want to write games on the Android platform. It also offers information for experienced game developers about the pitfalls and peculiarities of the platform.

Table of Contents

  1. Android, the New Kid on the Block
  2. First Steps with the Android SDK
  3. Game Development 101
  4. Android for Game Developers
  5. An Android Game Development Framework
  6. Mr. Nom Invades Android
  7. OpenGL ES: A Gentle Introduction
  8. 2D Game Programming Tricks
  9. Super Jumper: A 2D OpenGL ES Game
  10. OpenGL ES: Going 3D
  11. 3D Programming Tricks
  12. Droid Invaders: the Grand Finale
  13. Publishing Your Game
  14. What’s Next?

About the Author

Mario Zechner runs Badlogic Games, a game development shop focused on Android.

Update GPS TAG, using ExifInterface.setAttribute() and exifInterface.saveAttributes()

Update GPS TAG, using ExifInterface.setAttribute() and exifInterface.saveAttributes()

Last exercise show how to "Read EXIF of JPG file", new member method UpdateGeoTag() will be implemented to update GPS TAG of the file with dummy data.

exifInterface.setAttribute(ExifInterface.TAG_GPS_LATITUDE, DUMMY_GPS_LATITUDE);
exifInterface.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, DUMMY_GPS_LATITUDE_REF);
exifInterface.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, DUMMY_GPS_LONGITUDE);
exifInterface.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, DUMMY_GPS_LONGITUDE_REF);

Once all attributes set, you can call exifInterface.saveAttributes() method to update the file.

with updated GPS TAG

In order to write-back data to file in SD Card, you have to modify AndroidManifest.xml grant permission of "android.permission.WRITE_EXTERNAL_STORAGE".

Related post
- "Convert Exif GPS info to Degree format".

In my exercise, the update Geo location can be recognized automatically by Picasa, Flickr and Nikon ViewNX.

MyExif.java
package com.exercise.AndroidSelectImage;

import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.database.Cursor;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;

public class MyExif {

private File exifFile; //It's the file passed from constructor
private String exifFilePath; //file in Real Path format
private Activity parentActivity; //Parent Activity

private String exifFilePath_withoutext;
private String ext;

private ExifInterface exifInterface;
private Boolean exifValid = false;;

//Exif TAG
//for API Level 8, Android 2.2
private String exif_DATETIME = "";
private String exif_FLASH = "";
private String exif_FOCAL_LENGTH = "";
private String exif_GPS_DATESTAMP = "";
private String exif_GPS_LATITUDE = "";
private String exif_GPS_LATITUDE_REF = "";
private String exif_GPS_LONGITUDE = "";
private String exif_GPS_LONGITUDE_REF = "";
private String exif_GPS_PROCESSING_METHOD = "";
private String exif_GPS_TIMESTAMP = "";
private String exif_IMAGE_LENGTH = "";
private String exif_IMAGE_WIDTH = "";
private String exif_MAKE = "";
private String exif_MODEL = "";
private String exif_ORIENTATION = "";
private String exif_WHITE_BALANCE = "";

//Constructor from path
MyExif(String fileString, Activity parent){
exifFile = new File(fileString);
parentActivity = parent;
exifFilePath = fileString;
PrepareExif();
}

//Constructor from URI
MyExif(Uri fileUri, Activity parent){
exifFile = new File(fileUri.toString());
parentActivity = parent;
exifFilePath = getRealPathFromURI(fileUri);
PrepareExif();
}

private void PrepareExif(){

int dotposition= exifFilePath.lastIndexOf(".");
exifFilePath_withoutext = exifFilePath.substring(0,dotposition);
ext = exifFilePath.substring(dotposition + 1, exifFilePath.length());

if (ext.equalsIgnoreCase("jpg")){
try {
exifInterface = new ExifInterface(exifFilePath);
ReadExifTag();
exifValid = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private void ReadExifTag(){

exif_DATETIME = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
exif_FLASH = exifInterface.getAttribute(ExifInterface.TAG_FLASH);
exif_FOCAL_LENGTH = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
exif_GPS_DATESTAMP = exifInterface.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
exif_GPS_LATITUDE = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
exif_GPS_LATITUDE_REF = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
exif_GPS_LONGITUDE = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
exif_GPS_LONGITUDE_REF = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
exif_GPS_PROCESSING_METHOD = exifInterface.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
exif_GPS_TIMESTAMP = exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
exif_IMAGE_LENGTH = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH);
exif_IMAGE_WIDTH = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH);
exif_MAKE = exifInterface.getAttribute(ExifInterface.TAG_MAKE);
exif_MODEL = exifInterface.getAttribute(ExifInterface.TAG_MODEL);
exif_ORIENTATION = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION);
exif_WHITE_BALANCE = exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE);

}

private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = parentActivity.managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}

public String getSummary(){
if(!exifValid){
return ("Invalide EXIF!");
}else{
return( exifFilePath + " : \n" +

"Name without extension: " + exifFilePath_withoutext + "\n" +
"with extension: " + ext + "\n" +

//"Date Time: " + exif_DATETIME + "\n" +
//"Flash: " + exif_FLASH + "\n" +
//"Focal Length: " + exif_FOCAL_LENGTH + "\n" +
//"GPS Date Stamp: " + exif_GPS_DATESTAMP + "\n" +
"GPS Latitude: " + exif_GPS_LATITUDE + "\n" +
"GPS Latitute Ref: " + exif_GPS_LATITUDE_REF + "\n" +
"GPS Longitude: " + exif_GPS_LONGITUDE + "\n" +
"GPS Longitude Ref: " + exif_GPS_LONGITUDE_REF);
//"Processing Method: " + exif_GPS_PROCESSING_METHOD + "\n" +
//"GPS Time Stamp: " + exif_GPS_TIMESTAMP + "\n" +
//"Image Length: " + exif_IMAGE_LENGTH + "\n" +
//"Image Width: " + exif_IMAGE_WIDTH + "\n" +
//"Make: " + exif_MAKE + "\n" +
//"Model: " + exif_MODEL + "\n" +
//"Orientation: " + exif_ORIENTATION + "\n" +
//"White Balance: " + exif_WHITE_BALANCE + "\n");
}
}

public void UpdateGeoTag(){
//with dummy data
final String DUMMY_GPS_LATITUDE = "22/1,21/1,299295/32768";
final String DUMMY_GPS_LATITUDE_REF = "N";
final String DUMMY_GPS_LONGITUDE = "114/1,3/1,207045/4096";
final String DUMMY_GPS_LONGITUDE_REF = "E";

exifInterface.setAttribute(ExifInterface.TAG_GPS_LATITUDE, DUMMY_GPS_LATITUDE);
exifInterface.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, DUMMY_GPS_LATITUDE_REF);
exifInterface.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, DUMMY_GPS_LONGITUDE);
exifInterface.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, DUMMY_GPS_LONGITUDE_REF);
try {
exifInterface.saveAttributes();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}
}


AndroidSelectImage.java
package com.exercise.AndroidSelectImage;

import java.io.File;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class AndroidSelectImage extends Activity {

TextView textTargetUri;
ImageView targetImage;
Button buttonSaveImage;

File targetFile;
String exifAttribute;

MyExif myExif;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonLoadImage = (Button)findViewById(R.id.loadimage);
buttonSaveImage = (Button)findViewById(R.id.saveimage);
textTargetUri = (TextView)findViewById(R.id.targeturi);
targetImage = (ImageView)findViewById(R.id.targetimage);

buttonLoadImage.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
buttonSaveImage.setEnabled(false);
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}});

buttonSaveImage.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
myExif.UpdateGeoTag(); //with dummy data
}});
}

@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK){
Uri targetUri = data.getData();

Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver()
.openInputStream(targetUri));
targetImage.setImageBitmap(bitmap);
buttonSaveImage.setEnabled(true);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

myExif = new MyExif(targetUri, this);
textTargetUri.setText(myExif.getSummary());
}
}

}


main.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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/loadimage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load Image"
/>
<Button
android:id="@+id/saveimage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Update Geo Tag (with DUMMY data)"
android:enabled="false"
/>
<TextView
android:id="@+id/targeturi"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/targetimage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>


Download the files.

Monday, April 25, 2011

Read EXIF of JPG file

Work on the exercise "Display Gallery selected image using BitmapFactory", function of reading EXIF is added.

EXIF of JPG file

A new class MyExif is implemented to handle the operation on the JPG file, it's used to read EXIF. (May be more functions will be added later)

Note that it's target for API Level 8, Android 2.2, other version will provide more or less TAG of EXIF.

MyExif.java
package com.exercise.AndroidSelectImage;

import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.database.Cursor;
import android.media.ExifInterface;
import android.net.Uri;
import android.provider.MediaStore;

public class MyExif {

private File exifFile; //It's the file passed from constructor
private String exifFilePath; //file in Real Path format
private Activity parentActivity; //Parent Activity

private String exifFilePath_withoutext;
private String ext;

private ExifInterface exifInterface;
private Boolean exifValid = false;;

//Exif TAG
//for API Level 8, Android 2.2
private String exif_DATETIME = "";
private String exif_FLASH = "";
private String exif_FOCAL_LENGTH = "";
private String exif_GPS_DATESTAMP = "";
private String exif_GPS_LATITUDE = "";
private String exif_GPS_LATITUDE_REF = "";
private String exif_GPS_LONGITUDE = "";
private String exif_GPS_LONGITUDE_REF = "";
private String exif_GPS_PROCESSING_METHOD = "";
private String exif_GPS_TIMESTAMP = "";
private String exif_IMAGE_LENGTH = "";
private String exif_IMAGE_WIDTH = "";
private String exif_MAKE = "";
private String exif_MODEL = "";
private String exif_ORIENTATION = "";
private String exif_WHITE_BALANCE = "";

//Constructor from path
MyExif(String fileString, Activity parent){
exifFile = new File(fileString);
parentActivity = parent;
exifFilePath = fileString;
PrepareExif();
}

//Constructor from URI
MyExif(Uri fileUri, Activity parent){
exifFile = new File(fileUri.toString());
parentActivity = parent;
exifFilePath = getRealPathFromURI(fileUri);
PrepareExif();
}

private void PrepareExif(){

int dotposition= exifFilePath.lastIndexOf(".");
exifFilePath_withoutext = exifFilePath.substring(0,dotposition);
ext = exifFilePath.substring(dotposition + 1, exifFilePath.length());

if (ext.equalsIgnoreCase("jpg")){
try {
exifInterface = new ExifInterface(exifFilePath);
ReadExifTag();
exifValid = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private void ReadExifTag(){

exif_DATETIME = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);
exif_FLASH = exifInterface.getAttribute(ExifInterface.TAG_FLASH);
exif_FOCAL_LENGTH = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH);
exif_GPS_DATESTAMP = exifInterface.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
exif_GPS_LATITUDE = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
exif_GPS_LATITUDE_REF = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
exif_GPS_LONGITUDE = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
exif_GPS_LONGITUDE_REF = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
exif_GPS_PROCESSING_METHOD = exifInterface.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD);
exif_GPS_TIMESTAMP = exifInterface.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
exif_IMAGE_LENGTH = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_LENGTH);
exif_IMAGE_WIDTH = exifInterface.getAttribute(ExifInterface.TAG_IMAGE_WIDTH);
exif_MAKE = exifInterface.getAttribute(ExifInterface.TAG_MAKE);
exif_MODEL = exifInterface.getAttribute(ExifInterface.TAG_MODEL);
exif_ORIENTATION = exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION);
exif_WHITE_BALANCE = exifInterface.getAttribute(ExifInterface.TAG_WHITE_BALANCE);

}

private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = parentActivity.managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}

public String getSummary(){
if(!exifValid){
return ("Invalide EXIF!");
}else{
return( exifFilePath + " : \n" +

"Name without extension: " + exifFilePath_withoutext + "\n" +
"with extension: " + ext + "\n" +

"Date Time: " + exif_DATETIME + "\n" +
"Flash: " + exif_FLASH + "\n" +
"Focal Length: " + exif_FOCAL_LENGTH + "\n" +
"GPS Date Stamp: " + exif_GPS_DATESTAMP + "\n" +
"GPS Latitude: " + exif_GPS_LATITUDE + "\n" +
"GPS Latitute Ref: " + exif_GPS_LATITUDE_REF + "\n" +
"GPS Longitude: " + exif_GPS_LONGITUDE + "\n" +
"GPS Longitude Ref: " + exif_GPS_LONGITUDE_REF + "\n" +
"Processing Method: " + exif_GPS_PROCESSING_METHOD + "\n" +
"GPS Time Stamp: " + exif_GPS_TIMESTAMP + "\n" +
"Image Length: " + exif_IMAGE_LENGTH + "\n" +
"Image Width: " + exif_IMAGE_WIDTH + "\n" +
"Make: " + exif_MAKE + "\n" +
"Model: " + exif_MODEL + "\n" +
"Orientation: " + exif_ORIENTATION + "\n" +
"White Balance: " + exif_WHITE_BALANCE + "\n");
}
}
}


AndroidSelectImage.java
package com.exercise.AndroidSelectImage;

import java.io.File;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class AndroidSelectImage extends Activity {

TextView textTargetUri;
ImageView targetImage;

File targetFile;
String exifAttribute;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonLoadImage = (Button)findViewById(R.id.loadimage);
textTargetUri = (TextView)findViewById(R.id.targeturi);
targetImage = (ImageView)findViewById(R.id.targetimage);

buttonLoadImage.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}});
}

@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK){
Uri targetUri = data.getData();

Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver()
.openInputStream(targetUri));
targetImage.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

MyExif myExif = new MyExif(targetUri, this);
textTargetUri.setText(myExif.getSummary());
}
}

}


main.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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/loadimage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load Image"
/>
<TextView
android:id="@+id/targeturi"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/targetimage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidSelectImage"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidSelectImage"
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="8" />

</manifest>


Download the files.

Related article:
- Update GPS TAG, using ExifInterface.setAttribute() and exifInterface.saveAttributes()

Sunday, April 24, 2011

Convert URI to real path format

In the exercises "Select Image using Android build-in Gallery" ad "Display Gallery selected image using BitmapFactory", the uri returned from build-in Gallery app is in the format of "content://media/external/images/...". To convert it to the real path format (eg. /mnt/sdcard/dropbox/Eric/....png), the following function can be used.

 public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index
= cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}


in real path format

Saturday, April 23, 2011

Beginning Android Application Development


PProduct Description

Create must-have applications for the latest Android OS

The Android OS is a popular and flexible platform for many of today's most in-demand mobile devices. This full-color guide offers you a hands-on introduction to creating Android applications for the latest mobile devices. Veteran author Wei Meng Lee accompanies each lesson with real-world examples to drive home the content he covers. Beginning with an overview of core Android features and tools, he moves at a steady pace while teaching everything you need to know to successfully develop your own Android applications.

  • Explains what an activity is and reviews its lifecycle
  • Zeroes in on customizing activities by applying styles and themes
  • Looks at the components of a screen, including LinearLayout, AbsoluteLayout, and RelativeLayout, among others
  • Details ways to adapt to different screen sizes and adjust display orientation
  • Reviews the variety of views such as TextView, ProgressBar, TimePicker, and more

Beginning Android Application Development pares down the most essential steps you need to know so you can start creating Android applications today.

From the Back Cover

Create applications for the latest Android OS

The Android OS is a popular and flexible platform for many of today's most in-demand mobile devices. This full-color guide offers you a hands-on introduction to creating Android applications for the latest mobile devices. Veteran author Wei-Meng Lee accompanies each lesson with real-world examples to drive home the content he covers. Beginning with an overview of core Android features and tools, the author proceeds to teach everything you need to know to successfully develop your own Android applications.

Beginning Android Application Development:

  • Explains what an activity is and reviews its lifecycle

  • Zeroes in on how to customize activities by applying styles and themes

  • Looks at the components of a screen, including LinearLayout, AbsoluteLayout, and RelativeLayout, among others

  • Details ways to adapt to different screen sizes and adjust display orientation

  • Reviews the variety of views such as TextView, ProgressBar, TimePicker, and more

  • Covers SMS messaging and networking

  • Walks you through how to create an Android Service and interact with it

  • Pares down the most essential steps for publishing Android applications

Wrox Beginning guides are crafted to make learning programming languages and technologies easier than you think, providing a structured, tutorial format that will guide you through all the techniques involved.

wrox.com Programmer Forums

Join our Programmer to Programmer forums to ask and answer programming questions about this book, join discussions on the hottest topics in the industry, and connect with fellow programmers from around the world.

Code Downloads

Take advantage of free code samples from this book, as well as code samples from hundreds of other books, all ready to use.

Read More

Find articles, ebooks, sample chapters and tables of contents for hundreds of books, and more reference resources on programming topics that matter to you.

Update Notification

Each notification is uniquely identified by the NotificationManager with an integer ID, the notification can be revised by calling setLatestEventInfo() with new values, change some field values of the Notification, and then call notify() again.

It's a exercise demonstrate how to updte notification, modified from exercise "Start a service to send Notification".

Update Notification

The service will be started when App start. To make it clear to understand, two buttons are implemented to request service to send notification using different Notification ID. Use enter target URL in the EditText field, and click any button to send notification, it will be send out and update notification with the ID.

Layout, main.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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="\nService Start in App Start\n"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Target address to open in Browser"
/>
<EditText
android:id="@+id/targetaddr"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/sendnotification_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send Notification ID 1"
/>
<Button
android:id="@+id/sendnotification_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send Notification ID 2"
/>
<Button
android:id="@+id/stopservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Stop Service"
/>
</LinearLayout>


Main activity, AndroidNotifyService.java
package com.exercise.AndroidNotifyService;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class AndroidNotifyService extends Activity {

EditText targetAddr;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button buttonStopService = (Button)findViewById(R.id.stopservice);
Button buttonSendNotification1 = (Button)findViewById(R.id.sendnotification_1);
Button buttonSendNotification2 = (Button)findViewById(R.id.sendnotification_2);
targetAddr = (EditText)findViewById(R.id.targetaddr);

//Start the service in App start, instead of clicking button
Intent intent = new Intent(AndroidNotifyService.this, com.exercise.AndroidNotifyService.NotifyService.class);
AndroidNotifyService.this.startService(intent);

buttonStopService.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setAction(NotifyService.ACTION);
intent.putExtra("RQS", NotifyService.RQS_STOP_SERVICE);
sendBroadcast(intent);
}});

buttonSendNotification1.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setAction(NotifyService.ACTION);
intent.putExtra("RQS", NotifyService.RQS_SEND_NOTIFICATION_1);
intent.putExtra("TARGET", targetAddr.getText().toString());
sendBroadcast(intent);
}});

buttonSendNotification2.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setAction(NotifyService.ACTION);
intent.putExtra("RQS", NotifyService.RQS_SEND_NOTIFICATION_2);
intent.putExtra("TARGET", targetAddr.getText().toString());
sendBroadcast(intent);
}});

}
}


The service, NotifyService.java
package com.exercise.AndroidNotifyService;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.IBinder;

public class NotifyService extends Service {

final static String ACTION = "NotifyServiceAction";
//final static String STOP_SERVICE = "";
final static int RQS_STOP_SERVICE = 1;
final static int RQS_SEND_NOTIFICATION_1 = 2;
final static int RQS_SEND_NOTIFICATION_2 = 3;

NotifyServiceReceiver notifyServiceReceiver;

private static final int MY_NOTIFICATION_ID_1=1;
private static final int MY_NOTIFICATION_ID_2=2;
private NotificationManager notificationManager;
private Notification myNotification;

Context myContext;
String myNotificationTitle = "Exercise of Notification!";

@Override
public void onCreate() {
// TODO Auto-generated method stub
notifyServiceReceiver = new NotifyServiceReceiver();
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION);
registerReceiver(notifyServiceReceiver, intentFilter);

// Send Notification
notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
myNotification = new Notification(R.drawable.icon,
"Notification!",
System.currentTimeMillis());
myContext = getApplicationContext();
myNotification.defaults |= Notification.DEFAULT_SOUND;
myNotification.flags |= Notification.FLAG_AUTO_CANCEL;

return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
this.unregisterReceiver(notifyServiceReceiver);
super.onDestroy();
}

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}

public class NotifyServiceReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
int rqs = arg1.getIntExtra("RQS", 0);
if (rqs == RQS_STOP_SERVICE){
stopSelf();
}else if(rqs == RQS_SEND_NOTIFICATION_1){
String myTarget = arg1.getStringExtra("TARGET");
SendNotification(MY_NOTIFICATION_ID_1, myTarget);

}else if(rqs == RQS_SEND_NOTIFICATION_2){
String myTarget = arg1.getStringExtra("TARGET");
SendNotification(MY_NOTIFICATION_ID_2, myTarget);
}
}

private void SendNotification(int id, String target){
String notificationText = target;
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(target));
PendingIntent pendingIntent
= PendingIntent.getActivity(myContext,
0, myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);

myNotification.setLatestEventInfo(myContext,
myNotificationTitle,
notificationText,
pendingIntent);
notificationManager.notify(id, myNotification);
}
}

}


AndroidManifest.xml, to include NotifyService.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidNotifyService"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidNotifyService"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotifyService"/>
</application>
</manifest>


Download the files.

Friday, April 22, 2011

Send Notification inside background Thread

In my old exercise, it's shown how to "Start a service to send Notification". It's modified to send the notification inside a background thread here.

package com.exercise.AndroidThreadNotification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;

public class AndroidThreadNotification extends Activity {

BackgroundThread backgroundThread;
Handler backgroundHandler;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
backgroundThread = new BackgroundThread();
backgroundThread.setRunning(true);
backgroundThread.start();
}

@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
boolean retry = true;
backgroundThread.setRunning(false);

while(retry){
try {
backgroundThread.join();
retry = false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

public class BackgroundThread extends Thread {
boolean running = false;
final static String ACTION = "NotifyServiceAction";
NotificationManager notificationManager;
Notification myNotification;
private final String myBlog = "http://android-er.blogspot.com/";
private static final int MY_NOTIFICATION_ID=1;

void setRunning(boolean b){
running = b;
}

@Override
public synchronized void start() {
// TODO Auto-generated method stub
super.start();
notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
}

@Override
public void run() {
// TODO Auto-generated method stub
while(running){
try {
sleep(10000); //send notification in every 10sec.
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// Send Notification
myNotification = new Notification(R.drawable.icon,
"Notification!",
System.currentTimeMillis());
Context context = getApplicationContext();
String notificationTitle = "Exercise of Notification!";
String notificationText = "http://android-er.blogspot.com/";
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
PendingIntent pendingIntent
= PendingIntent.getActivity(getBaseContext(),
0, myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification.defaults |= Notification.DEFAULT_SOUND;
myNotification.flags |= Notification.FLAG_AUTO_CANCEL;
myNotification.setLatestEventInfo(context,
notificationTitle,
notificationText,
pendingIntent);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}
}
}
}


Download the files.

HelloGallery, read picture files from SD, display in ImageView.

It's a old exercise "HelloGallery, read picture files from SD, using File ArrayList" to demonstrate how to use Gallery. It's modified to add a ImageView to show the large version of the clicked item in Gallery.

HelloGallery, read picture files from SD, display in ImageView.

Create a file /res/values/attrs.xml.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Theme">
<attr name="android:galleryItemBackground" />
</declare-styleable>
</resources>


Modify /res/layout/main.xml to include a Gallery and ImageView.
<?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">
<Gallery
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/imageview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>


Main code, HelloGallery.java.
package com.exercise.HelloGallery;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class HelloGallery extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final ImageView imageView = (ImageView)findViewById(R.id.imageview);

Gallery g = (Gallery) findViewById(R.id.gallery);
final List<String> SD = ReadSDCard();
g.setAdapter(new ImageAdapter(this, SD));

g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {

String imageInSD = SD.get(position);

Toast.makeText(HelloGallery.this,
imageInSD,
Toast.LENGTH_LONG).show();

Bitmap bitmap = BitmapFactory.decodeFile(imageInSD);
imageView.setImageBitmap(bitmap);

}
});
}

private List<String> ReadSDCard()
{
List<String> tFileList = new ArrayList<String>();

//It have to be matched with the directory in SDCard
File f = new File("/sdcard/pictures/");

File[] files=f.listFiles();

for(int i=0; i<files.length; i++)
{
File file = files[i];
//add the selected file type only
String curFile=file.getPath();
String ext=curFile.substring(curFile.lastIndexOf(".")+1,
curFile.length()).toLowerCase();
if(ext.equals("jpg")||ext.equals("gif")||ext.equals("png"))
tFileList.add(file.getPath());
}

return tFileList;
}

public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private List<String> FileList;

public ImageAdapter(Context c, List<String> fList) {
mContext = c;
FileList = fList;
TypedArray a = obtainStyledAttributes(R.styleable.Theme);
mGalleryItemBackground = a.getResourceId(
R.styleable.Theme_android_galleryItemBackground,
0);
a.recycle();
}

public int getCount() {
return FileList.size();
}

public Object getItem(int position) {
return position;
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView,
ViewGroup parent) {
ImageView i = new ImageView(mContext);

Bitmap bm = BitmapFactory.decodeFile(
FileList.get(position).toString());
i.setImageBitmap(bm);

i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);

return i;
}
}
}


Download the files.


next:
- HelloGallery, read picture files from SD, display in ImageView, and set as Wallpaper

Wednesday, April 20, 2011

Unzip compressed file, using java.util.zip

java.util.zip package of Android can help to extract compressed file in ZIP format.

Modify from previous exercise "How to get file extension using java code", implement a function unzip().

If the extention of the returned file using Intent.ACTION_GET_CONTENT" is "zip", call the function unzip() to extract compressed file.

package com.exercise.AndroidPick_a_File;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class AndroidPick_a_File extends Activity {

TextView textFile, textFileName, textFolder;
TextView textFileName_WithoutExt, textFileName_Ext;

private static final int PICKFILE_RESULT_CODE = 1;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button buttonPick = (Button)findViewById(R.id.buttonpick);
textFile = (TextView)findViewById(R.id.textfile);
textFolder = (TextView)findViewById(R.id.textfolder);
textFileName = (TextView)findViewById(R.id.textfilename);

textFileName_WithoutExt
= (TextView)findViewById(R.id.textfilename_withoutext);
textFileName_Ext
= (TextView)findViewById(R.id.textfilename_ext);

buttonPick.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent,PICKFILE_RESULT_CODE);

}});
}

@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
// TODO Auto-generated method stub
switch(requestCode){
case PICKFILE_RESULT_CODE:
if(resultCode==RESULT_OK){

String FilePath = data.getData().getPath();
String FileName = data.getData().getLastPathSegment();
int lastPos = FilePath.length() - FileName.length();
String Folder = FilePath.substring(0, lastPos);

textFile.setText("Full Path: \n" + FilePath + "\n");
textFolder.setText("Folder: \n" + Folder + "\n");
textFileName.setText("File Name: \n" + FileName + "\n");

filename thisFile = new filename(FileName);

textFileName_WithoutExt.setText("Filename without Ext: "
+ thisFile.getFilename_Without_Ext());
textFileName_Ext.setText("Ext: " + thisFile.getExt());

if(thisFile.getExt().equalsIgnoreCase("zip")){
unzip(FilePath, Folder);
}

}
break;

}
}

private class filename{

String filename_Without_Ext = "";
String ext = "";

filename(String file){
int dotposition= file.lastIndexOf(".");
filename_Without_Ext = file.substring(0,dotposition);
ext = file.substring(dotposition + 1, file.length());
}

String getFilename_Without_Ext(){
return filename_Without_Ext;
}

String getExt(){
return ext;
}
}

private void unzip(String src, String dest){

final int BUFFER_SIZE = 4096;

BufferedOutputStream bufferedOutputStream = null;
FileInputStream fileInputStream;
try {
fileInputStream = new FileInputStream(src);
ZipInputStream zipInputStream
= new ZipInputStream(new BufferedInputStream(fileInputStream));
ZipEntry zipEntry;

while ((zipEntry = zipInputStream.getNextEntry()) != null){

String zipEntryName = zipEntry.getName();
File file = new File(dest + zipEntryName);

if (file.exists()){

} else {
if(zipEntry.isDirectory()){
file.mkdirs();
}else{
byte buffer[] = new byte[BUFFER_SIZE];
FileOutputStream fileOutputStream = new FileOutputStream(file);
bufferedOutputStream
= new BufferedOutputStream(fileOutputStream, BUFFER_SIZE);
int count;

while ((count
= zipInputStream.read(buffer, 0, BUFFER_SIZE)) != -1) {
bufferedOutputStream.write(buffer, 0, count);
}

bufferedOutputStream.flush();
bufferedOutputStream.close();
}
}
}
zipInputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


Keep using the layout file main.xml in the previous exercise "How to get file extension using java code".

In order to write back the extracted files, modify AndroidManifest.xml to grant permission of "android.permission.WRITE_EXTERNAL_STORAGE".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidPick_a_File"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidPick_a_File"
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>
</manifest>


Download the files.

Monday, April 18, 2011

Read Text file from internet, using Java code

This exercise show how to read text file from internet. The file's url is hard coded to be "http://sites.google.com/site/androidersite/text.txt".

Read Text file from internet, using Java code

package com.exercise.AndroidInternetTxt;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidInternetTxt extends Activity {

TextView textMsg, textPrompt;
final String textSource = "http://sites.google.com/site/androidersite/text.txt";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textPrompt = (TextView)findViewById(R.id.textprompt);
textMsg = (TextView)findViewById(R.id.textmsg);

textPrompt.setText("Wait...");

URL textUrl;
try {
textUrl = new URL(textSource);
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(textUrl.openStream()));
String StringBuffer;
String stringText = "";
while ((StringBuffer = bufferReader.readLine()) != null) {
stringText += StringBuffer;
}
bufferReader.close();
textMsg.setText(stringText);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
textMsg.setText(e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
textMsg.setText(e.toString());
}

textPrompt.setText("Finished!");

}
}


main.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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<TextView
android:id="@+id/textprompt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textmsg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>


Modify AndroidManifest.xml to grant permission of "android.permission.INTERNET".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidInternetTxt"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidInternetTxt"
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>
</manifest>


Download the files.

Sunday, April 17, 2011

How to get file extension using java code

To get extension, we can use the following java code:

int dotposition= file.lastIndexOf(".");
filename_Without_Ext = file.substring(0,dotposition);
ext = file.substring(dotposition + 1, file.length());


Modify last exercise "More for Pick a file using Intent.ACTION_GET_CONTENT", a new class filename is implemented to get file extention and filename without extention.

get file extension using java code

main.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"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<Button
android:id="@+id/buttonpick"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="- PICK a file -"
/>
<TextView
android:id="@+id/textfile"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textfolder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textfilename"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textfilename_withoutext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textfilename_ext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>


main code
package com.exercise.AndroidPick_a_File;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class AndroidPick_a_File extends Activity {

TextView textFile, textFileName, textFolder;
TextView textFileName_WithoutExt, textFileName_Ext;

private static final int PICKFILE_RESULT_CODE = 1;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button buttonPick = (Button)findViewById(R.id.buttonpick);
textFile = (TextView)findViewById(R.id.textfile);
textFolder = (TextView)findViewById(R.id.textfolder);
textFileName = (TextView)findViewById(R.id.textfilename);

textFileName_WithoutExt = (TextView)findViewById(R.id.textfilename_withoutext);
textFileName_Ext = (TextView)findViewById(R.id.textfilename_ext);

buttonPick.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent,PICKFILE_RESULT_CODE);

}});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
switch(requestCode){
case PICKFILE_RESULT_CODE:
if(resultCode==RESULT_OK){

String FilePath = data.getData().getPath();
String FileName = data.getData().getLastPathSegment();
int lastPos = FilePath.length() - FileName.length();
String Folder = FilePath.substring(0, lastPos);

textFile.setText("Full Path: \n" + FilePath + "\n");
textFolder.setText("Folder: \n" + Folder + "\n");
textFileName.setText("File Name: \n" + FileName + "\n");

filename thisFile = new filename(FileName);
textFileName_WithoutExt.setText("Filename without Ext: " + thisFile.getFilename_Without_Ext());
textFileName_Ext.setText("Ext: " + thisFile.getExt());

}
break;

}
}

private class filename{

String filename_Without_Ext = "";
String ext = "";

filename(String file){
int dotposition= file.lastIndexOf(".");
filename_Without_Ext = file.substring(0,dotposition);
ext = file.substring(dotposition + 1, file.length());
}

String getFilename_Without_Ext(){
return filename_Without_Ext;
}

String getExt(){
return ext;
}
}

}


Download the files.

Related:
- Unzip compressed file, using java.util.zip

Thursday, April 14, 2011

More for Pick a file using Intent.ACTION_GET_CONTENT

In the exercise "Pick a file using Intent.ACTION_GET_CONTENT", with full path of the returned file. It will will modified to retrieve the folder path, and file name.

More for Pick a file using Intent.ACTION_GET_CONTENT

package com.exercise.AndroidPick_a_File;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class AndroidPick_a_File extends Activity {

TextView textFile, textFileName, textFolder;

private static final int PICKFILE_RESULT_CODE = 1;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button buttonPick = (Button)findViewById(R.id.buttonpick);
textFile = (TextView)findViewById(R.id.textfile);
textFolder = (TextView)findViewById(R.id.textfolder);
textFileName = (TextView)findViewById(R.id.textfilename);

buttonPick.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("file/*");
startActivityForResult(intent,PICKFILE_RESULT_CODE);

}});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
switch(requestCode){
case PICKFILE_RESULT_CODE:
if(resultCode==RESULT_OK){

String FilePath = data.getData().getPath();
String FileName = data.getData().getLastPathSegment();
int lastPos = FilePath.length() - FileName.length();
String Folder = FilePath.substring(0, lastPos);

textFile.setText("Full Path: \n" + FilePath + "\n");
textFolder.setText("Folder: \n" + Folder + "\n");
textFileName.setText("File Name: \n" + FileName + "\n");
}
break;

}
}
}


<?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/buttonpick"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="- PICK a file -"
/>
<TextView
android:id="@+id/textfile"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textfolder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/textfilename"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>


Download the files.

Related:
- How to get file extension using java code

Wednesday, April 13, 2011

Auto start a service with Intent of "android.intent.action.BOOT_COMPLETED" action

Last exercise "Start a service to send Notification" show how to start a service by user clicking in a activity. In this exercise, a BroadcastReceiver will be implemented to receive Intent of "android.intent.action.BOOT_COMPLETED" action after power-up, no interactive with user.

"android.intent.action.BOOT_COMPLETED" is Broadcast Action, is broadcast once, after the system has finished booting. It can be used to perform application-specific initialization. You must hold the RECEIVE_BOOT_COMPLETED permission in order to receive this broadcast.

Create a new class AutoStartNotifyReceiver.java, extends BroadcastReceiver. Simple do the same thing as that in Start button OnClickListener in last exercise "Start a service to send Notification", start a service.
package com.exercise.AndroidNotifyService;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class AutoStartNotifyReceiver extends BroadcastReceiver {

private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub

if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
Intent myIntent = new Intent(context, com.exercise.AndroidNotifyService.NotifyService.class);
context.startService(myIntent);
}

}

}


In order to receive Intent of "android.intent.action.BOOT_COMPLETED", modify AndroidManifest.xml to add <receiver> for AutoStartNotifyReceiver, also grant permission of "android.permission.RECEIVE_BOOT_COMPLETED".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidNotifyService"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidNotifyService"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotifyService"/>
<receiver android:name=".AutoStartNotifyReceiver" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
</application>
</manifest>


Keep using the other files implemented in last exercise "Start a service to send Notification".

Download the files.

Tuesday, April 12, 2011

Start a service to send Notification

Last exercise show how to "send a Notification" in activity. In this exercise, main activity start a service, and notification is sent in service run in background.

Start a service to send Notification

main.xml to have buttons to start and stop service.
<?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/startservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Start Service to send Notification"
/>
<Button
android:id="@+id/stopservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Stop Service"
/>
</LinearLayout>

main activity, AndroidNotifyService.java simple start and stop the service.
package com.exercise.AndroidNotifyService;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class AndroidNotifyService extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonStartService = (Button)findViewById(R.id.startservice);
Button buttonStopService = (Button)findViewById(R.id.stopservice);

buttonStartService.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(AndroidNotifyService.this, com.exercise.AndroidNotifyService.NotifyService.class);
AndroidNotifyService.this.startService(intent);
}});

buttonStopService.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent();
intent.setAction(NotifyService.ACTION);
intent.putExtra("RQS", NotifyService.STOP_SERVICE);
sendBroadcast(intent);
}});

}
}
[================================================
Correction@2011-0424: Please change the code
intent.putExtra("RQS", NotifyService.STOP_SERVICE);
to
intent.putExtra("RQS", NotifyService.RQS_STOP_SERVICE);
================================================]

NotifyService.java, our service to send notification.
package com.exercise.AndroidNotifyService;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.IBinder;

public class NotifyService extends Service {

final static String ACTION = "NotifyServiceAction";
final static String STOP_SERVICE = "";
final static int RQS_STOP_SERVICE = 1;

NotifyServiceReceiver notifyServiceReceiver;

private static final int MY_NOTIFICATION_ID=1;
private NotificationManager notificationManager;
private Notification myNotification;
private final String myBlog = "http://android-er.blogspot.com/";

@Override
public void onCreate() {
// TODO Auto-generated method stub
notifyServiceReceiver = new NotifyServiceReceiver();
super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION);
registerReceiver(notifyServiceReceiver, intentFilter);

// Send Notification
notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
myNotification = new Notification(R.drawable.icon,
"Notification!",
System.currentTimeMillis());
Context context = getApplicationContext();
String notificationTitle = "Exercise of Notification!";
String notificationText = "http://android-er.blogspot.com/";
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
PendingIntent pendingIntent
= PendingIntent.getActivity(getBaseContext(),
0, myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification.defaults |= Notification.DEFAULT_SOUND;
myNotification.flags |= Notification.FLAG_AUTO_CANCEL;
myNotification.setLatestEventInfo(context,
notificationTitle,
notificationText,
pendingIntent);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);

return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
this.unregisterReceiver(notifyServiceReceiver);
super.onDestroy();
}

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}

public class NotifyServiceReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
int rqs = arg1.getIntExtra("RQS", 0);
if (rqs == RQS_STOP_SERVICE){
stopSelf();
}
}
}

}


Modify AndroidManifest.xml to add our service.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidNotifyService"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidNotifyService"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotifyService"/>
</application>
</manifest>


Download the files.

Related:
- Auto start a service with Intent of "android.intent.action.BOOT_COMPLETED" action
- Send Notification inside background Thread
- Update Notification

Monday, April 11, 2011

A simple example to send a Notification

A simple example to send a Notification

package com.exercise.AndroidNotification;

import java.util.Calendar;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class AndroidNotification extends Activity {

private static final int MY_NOTIFICATION_ID=1;
private NotificationManager notificationManager;
private Notification myNotification;

private final String myBlog = "http://android-er.blogspot.com/";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonSend = (Button)findViewById(R.id.send);

buttonSend.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
notificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
myNotification = new Notification(R.drawable.icon,
"Notification!",
System.currentTimeMillis());
Context context = getApplicationContext();
String notificationTitle = "Exercise of Notification!";
String notificationText = "http://android-er.blogspot.com/";
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
PendingIntent pendingIntent
= PendingIntent.getActivity(AndroidNotification.this,
0, myIntent,
Intent.FLAG_ACTIVITY_NEW_TASK);
myNotification.defaults |= Notification.DEFAULT_SOUND;
myNotification.flags |= Notification.FLAG_AUTO_CANCEL;
myNotification.setLatestEventInfo(context,
notificationTitle,
notificationText,
pendingIntent);
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);

}});
}
}


<?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/send"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Send a Notification"
/>
</LinearLayout>


Download the files.

Related Article:
- Start a service to send Notification