Thursday, December 9, 2010

Playing with lists in Android - Part II

I hope you already read my first topic about listView. In part II, I am just extending the part I topic. So please read part I before reading part II.

In this, I am creating an adapter, in which each list item consists of two views, a TextView and an IMageView respectively. I am putting these two views in a relative layout. Then I am aligning the imageView to the right end of the layout using the addRule(). One more thing is, here I am putting a static image, that is the standard Android icon.

The adapter class is,



class MyAdapter extends BaseAdapter {

Context mContext;

public MyAdapter(Context context) {
mContext = context;
}

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

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

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

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

android.widget.RelativeLayout.LayoutParams params = new android.widget.RelativeLayout.LayoutParams
(android.widget.RelativeLaout.LayoutParams.WRAP_CONTENT,
android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT);

android.widget.RelativeLayout.LayoutParams imgParams = new android.widget.RelativeLayout.LayoutParams\(android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT,
android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT);

TextView tv = new TextView(mContext);
ImageView img = new ImageView(mContext);
tv.setText(list.get(position));
img.setImageResource(R.drawable.icon);
layout.addView(tv, params);
imgParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layout.addView(img, imgParams);
return layout;
}
}



The complete code is,



public class SampleListView_Chatextends Activity {

ListView lView;
ArrayList list;
EditText eText;
Button but;
ArrayAdapter adapter;
LinearLayout layout, subLayout;
LayoutParams params, lParams;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
subLayout = new LinearLayout(this);
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
eText = new EditText(this);
but = new Button(this);
lView = new ListView(this);
list = new ArrayList();
but.setText("Send");
/*adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);*/
lView.setAdapter(new MyAdapter(this));
but.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {
list.add(eText.getText().toString());
eText.setText(null);
/*lView.setAdapter(adapter);*/
lView.setAdapter(new MyAdapter(SampleListView_Chat.this));
}
});
lParams.height = 380;
layout.addView(lView, lParams);
eText.setWidth(260);
subLayout.addView(eText, params);
subLayout.addView(but, params);
layout.addView(subLayout, params);
setContentView(layout);
}

class MyAdapter extends BaseAdapter {

Context mContext;

public MyAdapter(Context context) {
mContext = context;
}

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

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

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

public View getView(int position, View convertView, ViewGroup parent) {

RelativeLayout layout = new RelativeLayout(mContext);

android.widget.RelativeLayout.LayoutParams params = new android.widget.RelativeLayout.LayoutParams(android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT, android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT);

android.widget.RelativeLayout.LayoutParams imgParams = new android.widget.RelativeLayout.LayoutParams(android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT, android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT);

TextView tv = new TextView(mContext);
ImageView img = new ImageView(mContext);
tv.setText(list.get(position));
img.setImageResource(R.drawable.icon);
layout.addView(tv, params);
imgParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layout.addView(img, imgParams);
return layout;
}
}
}



Screenshot

Wednesday, November 24, 2010

Some Android Tips

If we connect the device and if it show offline in DDMS, from the options menu click "Reset ADB" or from command prompt first execute "adb kill-server". After executing that execute "adb start-server"

Wednesday, September 8, 2010

Playing with Lists in Android - Part I

In this tutorial, first I am going to show you a simple but useful tutorial on ListView in Android.

Whatever we are entering in the editText will be shown in the list, like a starting for chat application UI.

Things required for this are ListView, adapter, arrayList, editText and a button. I created the layout in XML, as this is a small UI with few components. Another reason for this is, for my few previous projects, I need to use java for creating layouts.

The complete code will look like this..



public class SampleListView_Chat extends Activity {

ListView lView;
ArrayList list;
EditText eText;
Button but;
ArrayAdapter adapter;
LinearLayout layout, subLayout;
LayoutParams params, lParams;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
subLayout = new LinearLayout(this);
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
eText = new EditText(this);
but = new Button(this);
lView = new ListView(this);
list = new ArrayList();
but.setText("Send");
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
but.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {
list.add(eText.getText().toString());
eText.setText(null);
lView.setAdapter(adapter);
}
});
lParams.height = 380;
layout.addView(lView, lParams);
eText.setWidth(260);
subLayout.addView(eText, params);
subLayout.addView(but, params);
layout.addView(subLayout, params);
setContentView(layout);
}
}



Another thing that is very useful in chat applicationa and for other purposes is to see the last entry that we entered. For scrolling the listview, in XML



android:transcriptMode="alwaysScroll"



In java, the code is,


listView.setStackFromBottom(true);
listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);




Sunday, August 29, 2010

Creating shortcuts through Intent in Android

We can create shortcut for an application through intent. Its not so difficult. First create an intent with the package name of the application and add some flags to it. Then create another intent and add the first intent to it as extras and broadcast the intent. That is it.

The complete code is,



public class CreateShortcut extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent shortcutIntent = new Intent();
Log.i("CreateShortcut", "Creating first intent called shortcutIntent");
shortcutIntent.setClassName(getPackageName(), "CreateShortcut");
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent intent = new Intent();
Log.i("CreateShortcut", "Creating intent for broadcasting");
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "ShortcutName");
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, false);
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(intent);
}
}



Steps for launching the shortcut is,


-> Long press on the empty part of the home screen

-> Select "Shortcuts" from the dialog that pop-up




-> Select "Applications" from the dialog that pop-up





-> Select "CreateShortcut" from the dialog that pop-up





-> Now, we can see the shortcut for our application in home screen.

Creating LiveFolder in Android

In Android, a live folder is simply a real-time view of a ContentProvider. LiveFolder allow displaying of data on home screen without launching the application.



public class CreateLiveFolder extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri uri = Browser.BOOKMARKS_URI;
final Intent intent = getIntent();
final String action = intent.getAction();
if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
setResult(RESULT_OK, createLiveFolder(this, uri,
"Books", R.drawable.icon));
} else {
setResult(RESULT_CANCELED);
}
finish();
}

private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
final Intent intent = new Intent();
intent.setData(uri);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
Intent.ShortcutIconResource.fromContext(context, icon));
intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);
return intent;
}
}



The manifest file will look like this,



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.createlivefolder" android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".CreateLiveFolder"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.CREATE_LIVE_FOLDER"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>



In this case, I don't have any bookmark in my browser, so an empty content provider is shown.


Steps to launch LiveFolder :


After launching the application
-> Long press on the empty space of the home screen
-> Select "Folder" from the dialog that pop-up



-> Select "CreateLiveFolder".





This will create the live folder in home screen in the name of "SampleLiveFolder".



The screenshots are,



When we click on the icon, our live folder called "SampleLiveFolder" will open. As my "bookmarks" in browser is empty, it will show an empty dialog box

Saturday, August 28, 2010

Opening Contacts, Gallery and other system applications through Intent in Android

Code snippets for opening contacts, gallery etc through intent


// opening Contact
Intent intent = new Intent(Intent.ACTION_PICK, People.CONTENT_URI);
startActivityForResult(intent, REQUEST_CODE);



               
// opening Gallery
Intent i = new Intent(Intent.ACTION_PICK);
i.setType("image/*");
startActivityForResult(i, 1);



// opening All
Intent i = new Intent(Intent.ACTION_PICK);
i.setType("*/*");
startActivityForResult(i, 1);


By setting the type of the intent object to image/*, gallery will display, accordingly if we put corresponding action and data , we can display SMS, settings page etc.

If we put the data of intent as "*/*", a pop-up will display, which shows the available list of the applications that can display.

The screen shot is,

Friday, August 6, 2010

Live Wallpaper in Android

Live wallpaper is richer, animated, interactive backgrounds on the home screen of Android devices. A live wallpaper is very similar to a normal Android application and has access to all the facilities of the platform: SGL (2D drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc.

A live wallpaper is very similar to a regular Android service. The only difference is the addition of a new method, onCreateEngine() whose goal is to create a WallpaperService.Engine. The engine is responsible for handling the lifecycle and the drawing of a wallpaper.

Here, I am showing a general method for creating Live Wallpaper. According to our requirement or to our wish, we can draw some image when we touch anywhere on the screen, or according to the time, we can set different images like for morning from 6AM to 12PM, then 12PM to 6PM another image like that. or according to the location, we can set some image. In office one image, in home, another image like that.

First thing for creating Live Wallpaper in android is, declare the service in manifest file.


<service android:label="@string/wallpaper_cube1"
android:name=".LiveWallpaper"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper" android:resource="@xml/livewallpaper" />
</service>


A file named "livewallpaper.xml" should be placed in res/xml, which should look like this as,


<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
/>


In the manifest file, we also need to put,


<uses-sdk android:minSdkVersion="7" />
<uses-feature android:name="android.software.live_wallpaper" />


Live Wallpaper is from 2.1 SDK onwards.


The implementation of the live LiveWallpaper.java is as,


public class LiveWallpaperService extends WallpaperService {

@Override
public Engine onCreateEngine() {
return new WallpaperEngine();
}

@Override
public void onCreate() {
super.onCreate();
}

@Override
public void onDestroy() {
super.onDestroy();
}
public class WallpaperEngine extends Engine {
private LiveWallpaperPainting painting;

WallpaperEngine () {
SurfaceHolder holder = getSurfaceHolder();
painting = new LiveWallpaperPainting(holder,
getApplicationContext());
}

@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
setTouchEventsEnabled(true);
}

@Override
public void onDestroy() {
super.onDestroy();
painting.stopPainting();
}

@Override
public void onVisibilityChanged(boolean visible) {
if (visible) {
painting.resumePainting();
} else {
painting.pausePainting();
}
}

@Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
painting.setSurfaceSize(width, height);
}

@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
// start painting
painting.start();
}

@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
boolean retry = true;
painting.stopPainting();
while (retry) {
try {
painting.join();
retry = false;
} catch (InterruptedException e) {}
}
}

@Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xStep, float yStep, int xPixels, int yPixels) {
}

@Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
painting.doTouchEvent(event);
}
}
}



The "LiveWallpaperPainting .java" is as follows,


public class LiveWallpaperPainting extends Thread {

private SurfaceHolder surfaceHolder;
private Context context;

private boolean wait;
private boolean run;

private int width;
private int height;

private long previousTime;
private long currentTime;

public LiveWallpaperPainting(SurfaceHolder surfaceHolder,
Context context) {
this.surfaceHolder = surfaceHolder;
this.context = context;
this.wait = true;
}

public void pausePainting() {
this.wait = true;
synchronized(this) {
this.notify();
}
}

public void resumePainting() {
this.wait = false;
synchronized(this) {
this.notify();
}
}

public void stopPainting() {
this.run = false;
synchronized(this) {
this.notify();
}
}

@Override
public void run() {
this.run = true;
Canvas c = null;
while (run) {
try {
c = this.surfaceHolder.lockCanvas(null);
synchronized (this.surfaceHolder) {
currentTime = System.currentTimeMillis();
updatePhysics();
doDraw(c);
previousTime = currentTime;
}
} finally {
if (c != null) {
this.surfaceHolder.unlockCanvasAndPost(c);
}
}
synchronized (this) {
if (wait) {
try {
wait();
} catch (Exception e) {}
}
}
}
}

public void setSurfaceSize(int width, int height) {
this.width = width;
this.height = height;
synchronized(this) {
this.notify();
}
}

public void doTouchEvent(MotionEvent event) {
this.wait = false;
synchronized(this) {
notify();
}
}

private void doDraw(Canvas canvas) {}

private void updatePhysics() {
// if nothing was updated :
// this.wait = true;
}

}

Wednesday, July 28, 2010

Uninstalling installed applications using Intent in Android

To uninstall the install application using Intent, the code snippet is

Intent intent = new Intent(Intent.ACTION_DELETE);
intent.setData(Uri.parse("package:com.example.android.apis"));
startActivity(intent);


The screenshot is,

Getting List of Installed Applications in Android

We can get the list of android applications that is installed in the android device through PacketManager and using the API queryIntentActivities(). To get the list of installed applications in the device,

The complete code snippet is,


public class AppList extends Activity {
private ListView lView;
private ArrayList results = new ArrayList();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lView = (ListView) findViewById(R.id.list1);
PackageManager pm = this.getPackageManager();

Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

List list = pm.queryIntentActivities(intent, PackageManager.PERMISSION_GRANTED);
for (ResolveInfo rInfo : list) {
results.add(rInfo.activityInfo.applicationInfo
.loadLabel(pm).toString());
Log.w("Installed Applications", rInfo.activityInfo.applicationInfo
.loadLabel(pm).toString());
}
lView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, results));
}
}


The screenshot is,

Monday, July 12, 2010

Listening to Phone calls using PhoneStateListener

When an incoming call is coming to your mobile, you can get the number of the incoming call, through the interface phoneStateListener. Then we can also get the state the mobile phone throught the same phoneStateListener. Here, I used two emulators to show the scenario.

For this, first install the application in two emulators.

The complete code is,


public class CaptureCall extends Activity {

TelephonyManager tm;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
tm.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}

private PhoneStateListener mPhoneListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
try {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Toast.makeText(CaptureCall.this, "CALL_STATE_RINGING", Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(CaptureCall.this, "CALL_STATE_OFFHOOK", Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(CaptureCall.this, "CALL_STATE_IDLE", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(CaptureCall.this, "default", Toast.LENGTH_SHORT).show();
Log.i("Default", "Unknown phone state=" + state);
}
} catch (Exception e) {
Log.i("Exception", "PhoneStateListener() e = " + e);
}
}
};
}



Then of course, we need to give permission as,


<uses-permission android:name="android.permission.READ_PHONE_STATE"/>


The screenshots are,


Read Package information from Manifest in Android

We can get the package name, version number, version code, permissions, META-DATA like what ever we faced placed in the manifest file can be retrieved using PackageManager.

The code snippet is,

 
public class ReadPackage extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Read package name and version number from manifest
try {
PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
Toast.makeText(
this,
"PackageName = " + info.packageName + "\nVersionCode = "
+ info.versionCode + "\nVersionName = "
+ info.versionName + "\nPermissions = "+info.permissions, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
System.out.println(" Exception in onCreate() : e = " + e);
}
}
}

Sunday, June 27, 2010

Showing Route through Google Map in Android

To show the route between two places in google map, we can use

"http://maps.google.com/maps?&saddr=13.042206,80.17000&daddr=9.580000,78.100000"

this url.

Here I used the latitude and longitude of Chennai and Madurai, two cities in India.

The complete code snippet is,

 

public class LaunchMap extends MapActivity {

Uri uri;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uri =Uri.parse("http://maps.google.com/maps?&saddr=13.042206,80.17000&daddr=9.580000,78.100000");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
finish();
}

@Override
protected boolean isRouteDisplayed() {
return false;
}
}



For showing this, we need to include the google map library in Manifest file.

A the time of launching , a pop up will ask to open in Browser or Google maps, just click on google map and it will show a list displaying the step by step direction as,



If we click on the list item it will show the map as,

Friday, June 25, 2010

Live Audio streaming using MediaPlayer in Android

Live Audio streaming in android, from 1.6 sdk onwards is become so easy. In setDataSource() API directly pass the url and audio will play without any issues.

The complete code snippet is,


 
public class AudioStream extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String url = "http://www.songblasts.com/songs/hindi/t/three-idiots/01-Aal_Izz_Well-(SongsBlasts.Com).mp3";
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(url);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.prepare();
mp.start();
} catch (Exception e) {
Log.i("Exception", "Exception in streaming mediaplayer e = " + e);
}
}
}


The Url I used here is a song from a bollywood film 3 Idiots.


Happy Coding

Creating SDCard and using it in emulator

The command for creating sdcard is

mksdcard 16M image.iso

Here we created a sdcard of name "image" with 16MB of size.

For using the sdcard in emulator, give this command

-sdcard /image.iso

in "Additional Emulator Command Line Options"

Wednesday, June 23, 2010

INSTALL_PARSE_FAILED_NO_CERTIFICATES in Android

Today, when I am doing a project in Android, suddenly I got this error. Actually, when I got this error is, after putting a png file in drawable called "close_btn_nmb". After putting this png file and try to run, I got tINSTALL_PARSE_FAILED_NO_CERTIFICATES error in 1.6 SDK. After some googling, I just renamed the file as, "close_btnnmb" and it worked fine. At that time, I came to know about Issue-830

So, when giving name to drawable files, try to avoid, two underscores. This is not a hard core rule, just my insight.

File Browser in Andriod

File browser in android is used to access the internal file system in Android. Through the file browser, we can browse through the files. The features are

- sorting,
- size of the file
- an icon to recognize the file or directory
- open the file, if permission is there.

Then a Home button, to come to the root directory, SDcard button, to show sdcard files. A back button is always there, if the parent directory is not null.

For opening the file, there is function, I created called openFile(), in that, according to the extension of the file, I am setting the MIME type for intent using the API called setDataAndType(). The android file system contains lot of file types like audio, video, text, (text itself contain html, php, xml, csv etc).

Another important method(API), is listFiles(). This will return an array of files and this array, we are passing to the fill() in the FileBrowser class. We will check a file is a directory or not using isDirectory()


The code for openFile() which is an very important function in the fileBrowser application and can be used in several applications is,


 

private void openFile(File aFile) {
Log.i("openFile()", "openFile()");
String type = "";
String extension = "";
try {
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri data = Uri.parse("file://" + aFile.getAbsolutePath());
int dot = aFile.getName().lastIndexOf(".");
extension = aFile.getName().substring(dot);
type = extension.toLowerCase();
// audio-types
if (type.equals(".ogg"))
type = "audio/x-ogg";
if (type.equals(".mp3"))
type = "audio/mp3";
if (type.equals(".wav"))
type = "audio/wav";
if (type.equals(".mid"))
type = "audio/mid";
if (type.equals(".midi"))
type = "audio/midi";
if (type.equals(".amr"))
type = "audio/AMR";
// video-types
if (type.equals(".mpeg"))
type = "video/mpeg";
if (type.equals("..3gp"))
type = "video/3gpp";
// package-types
if (type.equals(".jar"))
type = "application/java-archive";
if (type.equals(".zip"))
type = "application/zip";
if (type.equals(".rar"))
type = "application/x-rar-compressed";
if (type.equals(".gz"))
type = "application/gzip";
// android-specific
if (type.equals(".apk"))
type = "application/vnd.android.package-archive";
// web browser-types
if (type.equals(".htm"))
type = "text/html";
if (type.equals(".html"))
type = "text/html";
if (type.equals(".php"))
type = "text/php";
// text-types
if (type.equals(".txt"))
type = "text/plain";
if (type.equals(".csv"))
type = "text/csv";
if (type.equals(".xml"))
type = "text/";
// image-types
if (type.equals(".png"))
type = "image/png";
if (type.equals(".gif"))
type = "image/gif";
if (type.equals(".jpg"))
type = "image/jpg";
if (type.equals(".jpeg"))
type = "image/jpeg";
if (type.equals(".bmp"))
type = "image/bmp";

intent.setDataAndType(data, type);
startActivity(intent);
} catch (Exception e) {
Toast.makeText(this, "Protected, File can't open",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}


The complete code snippet is,

 
public class FileBrowser extends ListActivity {

private enum DISPLAYMODE {
ABSOLUTE, RELATIVE;
}

static boolean SORT_NAME = false;
static boolean SMALL_ICON = false;
private final DISPLAYMODE displayMode = DISPLAYMODE.RELATIVE;
private static List directoryEntries = new ArrayList();
private File currentDirectory = new File("");
private TextView fullPath;
private File[] filesToFill = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fileui);
fullPath = (TextView) findViewById(R.id.path);
findViewById(R.id.home).setOnClickListener(new OnClickListener() {

public void onClick(View view) {
Log.i("onClick, HomeButton", "onClick, HomeButton");
browseToRoot();
}
});
findViewById(R.id.sdcard).setOnClickListener(new OnClickListener() {


public void onClick(View view) {
browseTo(new File("/sdcard"));
}

});
browseToRoot();
}

private void browseToRoot() {
browseTo(new File("/"));
}

private void upOneLevel() {
if (this.currentDirectory.getParent() != null) {
this.browseTo(this.currentDirectory.getParentFile());
} else {
Toast.makeText(this, "FileBrowser can't go Up", Toast.LENGTH_SHORT)
.show();
}
}

private void browseTo(final File aDirectory) {

if (this.displayMode == DISPLAYMODE.RELATIVE) {
Log.i("browseTo(), DISPLAYMODE_RELATIVE, absPath : "
+ aDirectory.getAbsolutePath(), "DISPLAYMODE_RELATIVE : ");
fullPath.setText("CurrentPath :" + aDirectory.getAbsolutePath());
}
if (aDirectory.isDirectory()) {
Log.i("browseTo(), isDir() == true", "browseTo(), isDir() == true");
this.currentDirectory = aDirectory;
fill(aDirectory.listFiles());
} else {
Log.i("browseTo(), isDir() != true", "browseTo(), isDir() != true");
openFile(aDirectory);
}
}

private void openFile(File aFile) {
Log.i("openFile()", "openFile()");
String type = "";
String extension = "";
try {
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri data = Uri.parse("file://" + aFile.getAbsolutePath());
int dot = aFile.getName().lastIndexOf(".");
extension = aFile.getName().substring(dot);
type = extension.toLowerCase();
// audio-types
if (type.equals(".ogg"))
type = "audio/x-ogg";
if (type.equals(".mp3"))
type = "audio/mp3";
if (type.equals(".wav"))
type = "audio/wav";
if (type.equals(".mid"))
type = "audio/mid";
if (type.equals(".midi"))
type = "audio/midi";
if (type.equals(".amr"))
type = "audio/AMR";
// video-types
if (type.equals(".mpeg"))
type = "video/mpeg";
if (type.equals("..3gp"))
type = "video/3gpp";
// package-types
if (type.equals(".jar"))
type = "application/java-archive";
if (type.equals(".zip"))
type = "application/zip";
if (type.equals(".rar"))
type = "application/x-rar-compressed";
if (type.equals(".gz"))
type = "application/gzip";
// android-specific
if (type.equals(".apk"))
type = "application/vnd.android.package-archive";
// web browser-types
if (type.equals(".htm"))
type = "text/html";
if (type.equals(".html"))
type = "text/html";
if (type.equals(".php"))
type = "text/php";
// text-types
if (type.equals(".txt"))
type = "text/plain";
if (type.equals(".csv"))
type = "text/csv";
if (type.equals(".xml"))
type = "text/";
// image-types
if (type.equals(".png"))
type = "image/png";
if (type.equals(".gif"))
type = "image/gif";
if (type.equals(".jpg"))
type = "image/jpg";
if (type.equals(".jpeg"))
type = "image/jpeg";
if (type.equals(".bmp"))
type = "image/bmp";

intent.setDataAndType(data, type);
startActivity(intent);
} catch (Exception e) {
Toast.makeText(this, "Protected, File can't open",
Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}

private void fill(File[] files) {
Log.i("in fill(), from browseTo()", "in fill(), from browseTo()");
FileBrowser.directoryEntries.clear();
filesToFill = files;

if (this.currentDirectory.getParent() != null) {
FileBrowser.directoryEntries.add(new IconifiedText("Back",
getResources().getDrawable(R.drawable.ic_menu_back_small)));
}
Drawable currentIcon = null;
for (File currentFile : files) {
String fileName = "";
Log.i("currentFile : Length :" + currentFile.length() + "Bytes",
"Size of currentFile");
if (currentFile.isDirectory()) {
currentIcon = getResources().getDrawable(R.drawable.folder3);
} else {
// String fileName = currentFile.getName();
// if (checkEndsWithInStringArray(fileName, getResources()
// .getStringArray(R.array.fileEndingImage))) {
// // currentIcon =
// // getResources().getDrawable(R.drawable.image);
// } else if (checkEndsWithInStringArray(fileName,
currentIcon = getResources().getDrawable(R.drawable.file);

}
switch (this.displayMode) {
case ABSOLUTE:
/* On absolute Mode, we show the full path */
FileBrowser.directoryEntries.add(new IconifiedText(currentFile
.getPath(), currentIcon));
break;
case RELATIVE:
int currentPathStringLength = this.currentDirectory.getPath()
.length();
fileName = currentFile.getAbsolutePath().substring(
currentPathStringLength);
Log.i("else part :" + fileName, "else part");
break;
}

if (FileBrowser.SMALL_ICON) {
if (currentFile.isDirectory())
currentIcon = getResources().getDrawable(R.drawable.folder);
else
currentIcon = getResources()
.getDrawable(R.drawable.webtext);
}
FileBrowser.directoryEntries.add(new IconifiedText(fileName,
currentIcon));

}

if (FileBrowser.SORT_NAME) {
Collections.sort(FileBrowser.directoryEntries);
}
IconifiedTextListAdapter itla = new IconifiedTextListAdapter(this);
itla.setListItems(FileBrowser.directoryEntries);
this.setListAdapter(itla);
}


@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String selectedFileString = FileBrowser.directoryEntries.get(position)
.getText();
Log.i("selectedItem : " + selectedFileString, "onListItemClick()");
if (selectedFileString.equals("Home")) {
// Refresh
// this.browseTo(this.currentDirectory);
browseToRoot();
} else if (selectedFileString.equals("Back")) {
this.upOneLevel();
} else if (selectedFileString.equals("data")) {
this.browseTo(new File("/data/misc/"));
} else {
File clickedFile = null;
switch (this.displayMode) {
case RELATIVE:
clickedFile = new File(this.currentDirectory.getAbsolutePath()
+ FileBrowser.directoryEntries.get(position).getText());
break;
case ABSOLUTE:
clickedFile = new File(FileBrowser.directoryEntries.get(
position).getText());
Log.i("ABSOLUTE", "ABSOLUTE");
break;
}
if (clickedFile != null) {
this.browseTo(clickedFile);
}
}
}



This itself is not complete, other class like IconifiedText, Adapter class , xml files are there.

The screenshots are,



Sunday, June 20, 2010

Launching Google Map using Intent in Android

Using intent we can open google map. The URI for launching google map is geo:13.042206,80.17000?z=10

The complete code snippet is,

 

double latitude = 13.042206;
double longitude = 80.17000;
uri = Uri.parse("geo:" + latitude + "," + longitude +"?z=10");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);


The latitude and longitude , I specified here is for Chennai. We can also specify the zoom level. Here I specified the zoom level as 10.

The screenshot is,



From the menu you will get all the options that are available in google map as,

Vibration in Android

The code snippet for vibrating android phone is,

 
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(2000);


Here 2000 is 2000 milliseconds, the phone will vibrate. And of course you can't test this in emulator, you need a real device to test this.

Opening an Application using Intent

In Android, if we know the package name and the activity which is launching the application, we can open or launch the application from anywhere using Intent.

The code snippet is,

 
Intent intent = new Intent("android.intent.action.MAIN");
ComponentName component = new ComponentName("com.sample", "com.sample.Sample");
intent.setComponent(component );
startActivity(intent);

Tuesday, June 15, 2010

Manufacturer Name and phone model in Android

To get the manufacturer name and other details about the android phone, we can use the class called android.os.Build
 
To get the manufacturer name use, Build.MANUFACTURER
To get the phone model use, Build.MODEL

Friday, June 4, 2010

Accelerometer Sensor in Android

Android phones has lot of sensors. In this, I am showing you the how accelerometer sensor works. Accelerometer will show you thew x, y and z co-ordinates of your phone movement. Actually, this sensor, we used in one of our application. In that, when shake the phone horizontally, doing some action. So like this, you can also do according to the values you get from the onSensorChanged() in SensorEventListener interface.

The complete code is,

AndAccelorometer.java
 

public class AndAccelorometer extends Activity implements SensorEventListener {

SensorManager sMgr;
Sensor accelrometerSensor;
 
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE); accelrometerSensor = sMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sMgr.registerListener(this, accelrometerSensor, SensorManager.SENSOR_DELAY_UI); } public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } public void onSensorChanged(SensorEvent event) { // TODO Auto-generated method stub float[] sensorValues = event.values; if (event.sensor == accelrometerSensor) Toast.makeText(AndAccelorometer.this, "X = " + sensorValues[0] + " Y = " + sensorValues[1] + " Z = " + sensorValues[2], Toast.LENGTH_SHORT).show(); } }

Opening Camera from Application

The basic things for augmented reality are camera, Sensor to know the direction, and the GPS or network provider to get the current location details. Gradually, I will show you the Augmented Reality in Android. In this, showing you how to open a camera from application.

CameraPreview.java


 
class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

SurfaceHolder holder;
Camera camera;

public CameraPreview(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

@Override
public void surfaceChanged(SurfaceHolder holder2, int format, int w,
int h) {
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(w, h);
camera.setParameters(parameters);
camera.startPreview();
}

@Override
public void surfaceCreated(SurfaceHolder holder1) {
try {
camera = Camera.open();
camera.setPreviewDisplay(holder1);
} catch (Exception e) {
Log.i("Exception surfaceCreated()", "e = " + e);
camera.release();
camera = null;
}

}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
camera.stopPreview();
camera.release();
camera = null;
}
}



Create an object of CameraPreview and using setContentView(), just display the camera

OpenCamera.java

 
public class OpenCamera extends Activity {

CameraPreview preview;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
preview = new CameraPreview(this);
setContentView(preview);
}
}


And ofcourse, the permission is needed,


<uses-permission android:name="android.permission.CAMERA"/>

Thursday, June 3, 2010

HTTP 100 Conitnue Error in Android

When I am doing a project in Android suddenly, I got this error "HTTP 100 conitnue" when sending request to server and I am not getting the proper response from the server. After some googling, I came to know about one API, and I want to share with all about that. It is setUseExpectContinue()

The complete code snippet is,


HttpProtocolParams.setUseExpectContinue(client.getParams(), false);

Here, client is an object of "HttpClient"

After using this code snippet, I got proper response from server and all work fine.

Happy Coding

Sunday, May 30, 2010

Different ways for Notifying Users in Android

The 3 main different ways to notify an user are,

Dialog
Toast
Notification

Dialog

For notifying users with dialog, We will create an object of dialog. In this, I am removing the title using requestWindowFeature(Window.FEATURE_NO_TITLE) and adding a layout to the dialog to it using addContentView().

Toast

Second one is toast, that will flash and will display for a predefined period either as, Toast.LENGTH_SHORT or Toast.LENGTH_LONG.

Notification

Third one is notification, to notify user, about any background activity is started.

The complete sample programs is,

 
public class NotifyUser extends Activity {

LayoutParams panelParams, compParams, tvParams;
LinearLayout popupGrid;
LinearLayout buttonLayout;
TextView tv;
Button b1, b2;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
displayDialog();
displayToast();
displayNotification();
}

public void displayDialog() {
Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().getAttributes().width = 250;
popupGrid = new LinearLayout(this);
buttonLayout = new LinearLayout(this);
tv = new TextView(this);
b1 = new Button(this);
b2 = new Button(this);
panelParams = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
panelParams.width = 250;
compParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
tvParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);

buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
popupGrid.setOrientation(LinearLayout.VERTICAL);
tv.setText("Are you sure?");
b1.setWidth(100);
b2.setWidth(100);
b1.setText("Yes");
b2.setText("No");
tvParams.setMargins(80, 0, 0, 0);
panelParams.setMargins(20, 0, 0, 0);
popupGrid.addView(tv, tvParams);
buttonLayout.addView(b1, compParams);
buttonLayout.addView(b2, compParams);
popupGrid.addView(buttonLayout, panelParams);
dialog.addContentView(popupGrid, panelParams);
dialog.show();
}

public void displayToast() {
Toast.makeText(this, "Sorry, please try again", Toast.LENGTH_SHORT)
.show();
}

public void displayNotification() {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Nithin";
CharSequence message = "Crazy About Android...";
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(), 0);
Notification notif = new Notification(R.drawable.icon,
"Crazy About Android...", System.currentTimeMillis());
notif.setLatestEventInfo(this, from, message, contentIntent);
nm.notify(1, notif);
}
}



In notification, itself different forms are there. - when we click on the notification, it will take us to a new activity. For this, in pendingIntent, for the intent object, specify the acitivity, that we want to go.


PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, SampleActivity.class), 0);


Another form is, we can customize the notification layout using custom expanded view. For this create a layout in XML and use remoteView to use the XML. Use remoteView methods to set ImageView and TextView. The XML is,


android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="3dp"
>
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#000"
/>




The complete method is,


public void displayNotificationWithExandedView() {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = new Notification(R.drawable.icon,
"Crazy About Android...", System.currentTimeMillis());
RemoteViews contentView = new RemoteViews(getPackageName(),
R.layout.notify_layout);
contentView.setImageViewResource(R.id.image, R.drawable.icon);
contentView.setTextViewText(R.id.text,
"Hello, this message is in a custom expanded view");
notif.contentView = contentView;
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, SampleActivity.class), 0);
notif.contentIntent = contentIntent;
nm.notify(1, notif);
}



The screenshots are,







Saturday, May 29, 2010

Data Storage in Android

The storage system in Android are mainly divided into 3 types.

Database(sqlite)
File
SharedPreference

Database is already explained in my older post and you can see here

Files

Android can save files directly to the device internal storage. These files are private to the application and will be removed if you uninstall the application.

We can create a file using openFileOutput() with parameters as file name and the operating mode. Similarly, we can open the file using openFileInput() passing the parameter as the fileName. One thing, that we need to remeber is, give the file name with extension. In this example I am creating a text(.txt) file.

The complete code is,

  
public class ReadNWriteFile extends Activity {

final String TEST_STRING = new String("Hello Android");
final String FILE_NAME = "SAMPLEFILE.txt";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
fileCreate();
tv.setText(readFile());
setContentView(tv);
}

private void fileCreate() {
try {
OutputStream os = openFileOutput(FILE_NAME, MODE_WORLD_READABLE);
OutputStreamWriter osw = new OutputStreamWriter(os);
osw.write(TEST_STRING);
osw.close();
} catch (Exception e) {
Log.i("ReadNWrite, fileCreate()", "Exception e = " + e);
}
}

private String readFile() {
try {
FileInputStream fin = openFileInput(FILE_NAME);
InputStreamReader isReader = new InputStreamReader(fin);
char[] buffer = new char[TEST_STRING.length()];
// Fill the buffer with data from file
isReader.read(buffer);
return new String(buffer);
} catch (Exception e) {
Log.i("ReadNWrite, readFile()", "Exception e = " + e);
return null;
}
}
}


SharedPreferences

SharedPreference is another persistent storage mechanism in Android. In this, we can store the data in key-value pairs. One drawback is it allows only primitive data types and String. We can get an object of shared preference using getSharedPreferences(). One thing, we need to remember is after writing anything to sharedPreference, we need to do commit(). Then only new values will be reflected. We can write values into sharedPreference using put() methods like putInt(), putString() etc and can retrieve the values from sharedPreference using get() methods as getInt(), getString() etc.

A sample program is,


public class DataStorage extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences pref = getSharedPreferences("Preference",
MODE_WORLD_READABLE);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("keyBoolean", true);
editor.putFloat("keyFloat", 1.0f);
editor.putInt("keyInt", 1);
editor.putLong("keyLong", 1000000L);
editor.putString("keyString", "Hello Android");
editor.commit();

boolean dataFromPrefBool = pref.getBoolean("keyBoolean", false);
float dataFromPrefflaot = pref.getFloat("keyFloat", 0.0f);
int dataFromPrefInt = pref.getInt("keyInt", 0);
long dataFromPrefLong = pref.getLong("keyLong", 0);
String dataFromPrefString = pref.getString("keyString", null);
}
}


In the put(), we are passing key and value and in get(), we are passing key and the default value if the key is not present in the sharedPreference.

Tuesday, May 18, 2010

Scrolling of TextView

Code Snippet for scrolling textview is

TextView tv;
tv.setMovementMethod(ScrollingMovementMethod.getInstance());

TabActivity in Android

Tabs can be created in Android, in a number of ways. I am going to create using Java only. I don't want to use xml and I want my tab content should be dynamic. So, I am implementing Tabs through TabHost.TabContentFactory. This interface has an abstract method called createTabContent() and it will return a View.

Another interesting fact , I came to know is, Tabs can be created without TabActivity too. Thats a new information for me. I came to know this through a discussion in Android Developers google group. If you are interested you can see the complete discussion here

The complete code for this is,


public class SampleTab extends Activity implements TabHost.TabContentFactory {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

TabHost tabHost = new TabHost(SampleTab.this);
TabWidget tabW = new TabWidget(this);
FrameLayout frame = new FrameLayout(this);
frame.setId(android.R.id.tabcontent);
tabW.addView(frame);
tabW.setId(android.R.id.tabs);
tabHost.addView(tabW);
tabHost.setup();
tabHost.addTab(tabHost.newTabSpec("Tab1").setIndicator("Tab1")
.setContent(this));
tabHost.addTab(tabHost.newTabSpec("Tab2").setIndicator("Tab2")
.setContent(this));
setContentView(tabHost);
}

public View createTabContent(String tag) {
TextView tv = new TextView(SampleTab.this);
tv.setText("This is from : " + tag);
return tv;
}
}


Happy Coding

Monday, April 26, 2010

ExpandableListActivity in Android

I want to use expandablelist activity, when I want to show two lists in a single screen like a main list and a sub-list. For example, a list of countries are there(Main list) and I want to show the main cities(sub-list) of theses countries. In that case, expandable list activity will be very useful. This is just one use of expandable list. Like that it can use for hundreds of purposes.

The complete code is,


public class CountryStateList extends ExpandableListActivity {

private static final String NAME = "NAME";
private static final String IS_EVEN = "IS_EVEN";
private ExpandableListAdapter mAdapter;
List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
List<List<Map<String, String>>> childData = new ArrayList<List<Map<String, String>>>();
InputStream is;
boolean addState = true;
boolean addCountry;
HashMap<String, String> countryMap = new HashMap<String, String>();
HashMap<String, String> stateMap = new HashMap<String, String>();
int count = 0;
int count1 = -1;
int count2 = 0;
List<String> stateCount = new ArrayList<String>();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Reading data from text file to inout stream
is = this.getResources().openRawResource(R.raw.countrystate);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
String line = "";
while ((line = reader.readLine()) != null) {
String[] strings = line.split("-");
String ctry = strings[0].trim();
String st = strings[1].trim();
/*
* loading country and state to two separate hash tables
*/
if (countryMap.containsValue(ctry)) {
addCountry = false;
if (!addState) {
stateMap.put("state" + count1 + count2, st);
count2++;
}
} else {
addCountry = !addCountry;
count1++;
//adding no. of states for a country to a list
stateCount.add("" + count2);
if (addCountry) {
count2 = 0;
countryMap.put("country" + count, ctry);
stateMap.put("state" + count1 + count2, st);
addState = false;
}
count2++;
count++;
}
}
} catch (Exception e) {
}
//re-arranging the state count list
stateCount.add("" + count2);
stateCount.remove(0);
for (int i = 0; i < countryMap.size(); i++) {
Map<String, String> curGroupMap = new HashMap<String, String>();
groupData.add(curGroupMap);
String ctry = countryMap.get("country" + i);
curGroupMap.put(NAME, ctry);
curGroupMap.put(IS_EVEN, "Country " + i);
List<Map<String, String>> children = new ArrayList<Map<String, String>>();
int k = Integer.parseInt(stateCount.get(i));
for (int j = 0; j < k; j++) {
Map<String, String> curChildMap = new HashMap<String, String>();
children.add(curChildMap);
curChildMap.put(NAME, stateMap.get("state" + i + j));
curChildMap.put(IS_EVEN, "State " + j);
}
childData.add(children);
}

// Set up our adapter
mAdapter = new SimpleExpandableListAdapter(this, groupData,
android.R.layout.simple_expandable_list_item_1, new String[] {
NAME, IS_EVEN }, new int[] { android.R.id.text1,
android.R.id.text2 }, childData,
android.R.layout.simple_expandable_list_item_2, new String[] {
NAME, IS_EVEN }, new int[] { android.R.id.text1,
android.R.id.text2 });
setListAdapter(mAdapter);
}
}



For getting data about country and cities, I used a text file

countrystate.txt

India - Delhi
India - Haryana
India - Uttar Pradesh
India - Rajastan
India - Jammu Kashmir
India - Orissa
India - West Bengal
India - Manipur
India - Tripura
India - AndraPradesh
India - Gujarat
India - Maharashtra
India - Madhya Pradesh
India - Karnataka
India - Tamil nadu
India - Kerala
India - Goa
Sri Lanka - Colombo
Sri Lanka - Kandalama
Sri Lanka - Gampola
Sri Lanka - Haragama
West Indies - Jamaica
West Indies - Barbados
West Indies - Virgin Islands
West Indies - Trinidad
West Indies - Bermuda
Australia - Melbourne
Australia - Perth
Australia - Sydney
Australia - Adelaide
Australia - Gulginni
Pakistan - Islamabad
Pakistan - Peshawar
Pakistan - Lahore
Pakistan - Karachi
Bangladesh - Dhaka
Bangladesh - Khulna
Bangladesh - Silet
South Africa - Johannesburg
South Africa - Cape Town



The screenshots are,



AlarmManager and Notification in Android

In this, I am going to explain AlarmManager and Notification. For Notifying Users in Android, we can use mainly 3 methods as,

Dialog
Toast
Notification

The full picture of this can seen here

AlarmManager, we can use in two ways, as

-To start some action, if a particular event happens,
-To do some particular actions in every time interval.

As specified in Android developer site, we will use AlarmManager, when we need to do some actions, even if our application is not running. For normal timing operations use handlers.

For using AlaramManager, first we need to declare the BroadcastReceiver in Manifest file as,

<receiver android:name=".TimeAlarm" />
We need to get the object of the AlarmManager using getSystemService(), then define an intent with parameters as the current context and the BoradcastReceiver class(TimeAlarm). Then define a pendingIntent, we will get the object of it using PendingIntent.getBroadcast(). Now we can call the set() of AlarmManager for doing some action for only once. For repetitive action we have to call setRepeating() of the AlarmManager.

In TimeAlarm, to show to user that our AlarmManager is working we will show a notification in status bar. For that first get the object of NotificationManager using, getSystemService(). Create an object of pendingIntent using PendingIntent.getActivity(). Then create an object of the notification and pass it to the notification manager object.

I created a sample program and the complete source code is,


CustomAlarm.java

  
public class CustomAlarm extends Activity {

 AlarmManager am;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
  setOneTimeAlarm();
 }

 public void setOneTimeAlarm() {
  Intent intent = new Intent(this, TimeAlarm.class);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
  am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), pendingIntent);
 }

 public void setRepeatingAlarm() {
  Intent intent = new Intent(this, TimeAlarm.class);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
  am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (5 * 1000), pendingIntent);
 }
}


TimeAlarm.java

public class TimeAlarm extends BroadcastReceiver {

 NotificationManager nm;

 @Override
 public void onReceive(Context context, Intent intent) {
  nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
  CharSequence from = "Nithin";
  CharSequence message = "Crazy About Android...";
  PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
  Notification notif = new Notification(R.drawable.icon, "Crazy About Android...", System.currentTimeMillis());
  notif.setLatestEventInfo(context, from, message, contentIntent);
  nm.notify(1, notif);
 }
}


The screenshots are,



AsyncTask in Android

AsyncTask allows us to do proper background operations without creating threads and handlers. AsyncTask will run in the background thread and whose results we can pass to the UI thread. To implement AsyncTask, what we need to do is, create a class which extends AsyncTask and need to override some methods in it like doInBackground(), onPostExecute(), onProgressUpdate().

Sample program is,

  
private class BackgroundTask extends AsyncTask {

@Override
protected Void doInBackground(Void... params) {
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
protected void onProgressUpdate(Integer... progress) {
}

}


We can call AsyncTask using, new BackgroundTask().execute();

Fetching IMEI number in Android

We can fetch the IMEI number of android phones using,


TelephonyManager mTelephonyMgr = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
String imei = mTelephonyMgr.getDeviceId();

ContentProvider in Android

I already told about the built-in content-providers in Android, in one of my tutorial

In this, I am creating a new custom content provider. For this, first we will declare the content provider in Manifest file as,

<provider android:name="Provider" android:authorities="simple.provider"/>

So,Provider is my content provider name. Created a class called Provider which extends ContentProvider. The CONTENT_URI, which I am going to use is, "content://simple.provider/mytable"

The complete source code is,

Provider.java

 
public class Provider extends ContentProvider {

public static final String AUTHORITY = "simple.provider";
// public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
// + "/table1");
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/mytable");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.provider.mytable";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.provider.mytable";
public static final String DATABASE_NAME = "MyDatabase";
public static final String TABLE_NAME = "mytable";
public static final int DATABASE_VERSION = 2;
public static final int TABLE = 1;
public static final int ROW_ID = 2;
public static final UriMatcher sUriMatcher;
public static final String FIRSTNAME = "first_name";
public static final String LASTNAME = "last_name";
private SQLiteDatabase sqlitedb;

static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, "mytable", TABLE);
sUriMatcher.addURI(AUTHORITY, "mytable/#", ROW_ID);
}

class DatabaseHelper extends SQLiteOpenHelper {

public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db
.execSQL("CREATE TABLE IF NOT EXISTS mytable "
+ "(id INTEGER PRIMARY KEY AUTOINCREMENT, first_name VARCHAR,"
+ "last_name VARCHAR);");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS mytable;");
onCreate(db);
}
}

// creating database
@Override
public boolean onCreate() {
DatabaseHelper databaseHelper = new DatabaseHelper(getContext());
sqlitedb = databaseHelper.getWritableDatabase();
return (sqlitedb == null) ? false : true;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}

@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case TABLE:
return CONTENT_TYPE;
case ROW_ID:
return CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknown URI : " + uri);
}
}

// inserting data into database
@Override
public Uri insert(Uri uri, ContentValues values) {
long row_id = sqlitedb.insert(TABLE_NAME, "", values);
try {
if (row_id > 0) {
Uri uri1 = ContentUris.withAppendedId(CONTENT_URI, row_id);
getContext().getContentResolver().notifyChange(uri1, null);
return uri1;
}
} catch (Exception e) {
Log.e("Fail to insert the row into database",
"Fail to insert the row into database");
}
return null;
}

// accessing records from database
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
sqlBuilder.setTables(TABLE_NAME);
if (sUriMatcher.match(uri) == ROW_ID)
sqlBuilder.appendWhere("id" + " = " + uri.getPathSegments().get(1));
Cursor c = sqlBuilder.query(sqlitedb, projection, selection,
selectionArgs, null, null, sortOrder);
// ---register to watch a content URI for changes---
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}
}



To accessing the ContentProvider, use ContentResolver. We can get the object using getContentResolver()

The complete source code for this is,

SimpleProvider.java

 
public class SimpleProvider extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

ContentValues values = new ContentValues();
values.put(Provider.FIRSTNAME, "Nithin");
values.put(Provider.LASTNAME, "Warrier");
getContentResolver().insert(Provider.CONTENT_URI, values);

ContentValues values1 = new ContentValues();
values1.put(Provider.FIRSTNAME, "Guna");
values1.put(Provider.LASTNAME, "Boss");
getContentResolver().insert(Provider.CONTENT_URI, values1);

Cursor c = managedQuery(Provider.CONTENT_URI, null, null, null, null);
int count = 1;
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
Log.i("Row " + count + " "
+ c.getString(c.getColumnIndex(Provider.FIRSTNAME)), c
.getString(c.getColumnIndex(Provider.LASTNAME)));
count++;
}
}
}

ViewStub in Android

In this, I just going to show how to use ViewStub in Android. Once again, I am telling this is just a very basic tutorial for ViewStub.

The complete code is,

SampleViewStub.java


public class SampleViewStub extends Activity {

ViewStub stub;
boolean click = true;

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

public void onClick(View v) {
if (click) {
stub = (ViewStub) findViewById(R.id.stub1);
stub.inflate();
click = false;
}
}
});
}
}


main.xml


<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout 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="Showing ViewStub" />

<Button android:id="@+id/openstub" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Open ViewStub" />

<ViewStub android:id="@+id/stub1" android:inflatedId="@+id/showlayout"
android:layout="@layout/layout1" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_gravity="bottom"/>
</LinearLayout>
</merge>



layout1.xml


<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView android:id="@+id/label_import" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Textview from Viewstub" />

<Button android:id="@+id/button_cancel" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:minWidth="100dip"
android:text="Next" />

</LinearLayout>


The screenshots are,



Sunday, April 25, 2010

Swipe Action and ViewFlipper in Android

Last tutorial I talked about ViewFlipper, in this I am just extending the functonality of ViewFlipper with swipe action. ViewFlipper is mainly used to animate views. I have two or three views added to the ViewFlipper and using the API showNext() and showPrevious(), we can show the next and previous view in the ViewFlipper. At the time of switching, we can create some animation and it looks great.

Foe switching between views, we can either use time interval or through user interaction. Last tutorial I used button for switching between Views. In this tutorial I am going to use swipe action for switching views.

class MyGestureDetector extends SimpleOnGestureListener {

  private static final int SWIPE_MIN_DISTANCE = 120;
  private static final int SWIPE_MAX_OFF_PATH = 250;
  private static final int SWIPE_THRESHOLD_VELOCITY = 200;

  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   System.out.println(" in onFling() :: ");
   if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
    return false;
   if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
     && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
    flipper.setInAnimation(inFromRightAnimation());
    flipper.setOutAnimation(outToLeftAnimation());
    flipper.showNext();
   } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
     && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
    flipper.setInAnimation(inFromLeftAnimation());
    flipper.setOutAnimation(outToRightAnimation());
    flipper.showPrevious();
   }
   return super.onFling(e1, e2, velocityX, velocityY);
  }
}


SWIPE_MIN_DISTANCE is used to make sure, the action is a swipe. Swipe will be valid only if we swipe upto this SWIPE_MIN_DISTANCE.
SWIPE_MAX_OFF_PATH is to make sure the swipe is almost in a straight line.

Then create an object of GestureDetector and pass our MyGestureDetector as an argument to its constructor.

GestureDetector gestureDetector;
gestureDetector = new GestureDetector(new MyGestureDetector());

Then create a OnTouchListener for flipper and attach the object of GestureDetector to it.

flipper.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View v, MotionEvent event) {
    if (gestureDetector.onTouchEvent(event)) {
     return false;
    } else {
     return true;
    }
   }
});

Thursday, April 22, 2010

Changing layout height dynamically

We can change the layout height dynamically to say, x by using

getLayoutParams().height= x;
requestLayout(); or invalidate();

ViewFlipper in Android

ViewFlipper is used to do animation when switching between views. There are lot of options for doing animations between views like ViewAnimator, LayoutAnimationController, applying animation to the view itself. But I feel ViewFlipper is the better option for doing animation for switching views.

In this I am controlling the switching between views using user interaction(Button click). We can set duration also for switching between views.

The complete code for showing ViewFlipper is,


public class ShowFlipper extends Activity {

ViewFlipper flipper;
Button button1;
Button button2;
LinearLayout l1;
LinearLayout l2;
TextView tv1, tv2, tv3, tv4, tv5, tv6;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);

flipper = new ViewFlipper(this);
l1 = new LinearLayout(this);
l2 = new LinearLayout(this);
button1 = new Button(this);
button2 = new Button(this);
button1.setText("Button 1");
button2.setText("Button 2");

l1.setOrientation(LinearLayout.VERTICAL);
l2.setOrientation(LinearLayout.VERTICAL);
tv1 = new TextView(this);
tv2 = new TextView(this);
tv3 = new TextView(this);
tv4 = new TextView(this);
tv5 = new TextView(this);
tv6 = new TextView(this);
tv1.setText("text view 1");
tv2.setText("text view 2");
tv3.setText("text view 3");
tv4.setText("text view 4");
tv5.setText("text view 5");
tv6.setText("text view 6");
l1.addView(tv1, params);
l1.addView(tv2, params);
l1.addView(tv3, params);
l1.addView(button1, params);
l2.addView(tv4, params);
l2.addView(tv5, params);
l2.addView(tv6, params);
l2.addView(button2, params);

flipper.addView(l1);
flipper.addView(l2);

button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
flipper.setInAnimation(inFromRightAnimation());
flipper.setOutAnimation(outToLeftAnimation());
flipper.showNext();
}
});

button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
flipper.setInAnimation(inFromLeftAnimation());
flipper.setOutAnimation(outToRightAnimation());
flipper.showPrevious();
}
});
setContentView(flipper);
}

private Animation inFromRightAnimation() {
Animation inFromRight = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, +1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
inFromRight.setDuration(500);
inFromRight.setInterpolator(new AccelerateInterpolator());
return inFromRight;
}

private Animation outToLeftAnimation() {
Animation outtoLeft = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, -1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
outtoLeft.setDuration(500);
outtoLeft.setInterpolator(new AccelerateInterpolator());
return outtoLeft;
}

private Animation inFromLeftAnimation() {
Animation inFromLeft = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, -1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
inFromLeft.setDuration(500);
inFromLeft.setInterpolator(new AccelerateInterpolator());
return inFromLeft;
}

private Animation outToRightAnimation() {
Animation outtoRight = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, +1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 0.0f);
outtoRight.setDuration(500);
outtoRight.setInterpolator(new AccelerateInterpolator());
return outtoRight;
}
}


You can download the full source code from here

Androidians