Tuesday, November 29, 2011

Pass a custom class from one activity to another using Intent

In this article, I am going to discuss about sending a custom class from one activity to another or any custom class to send from one activity to another using Intent.

We can pass a custom class using two ways, rather using two interfaces that are provided by Android which are java.io.Serializable and android.os.Parcelable.

First create a custom class then implements the class with Serializable interface. To make the class serializable include two functions, which are writeObject() and readObject(). Whatever objects we need to pass has to write to the ObjectOutputStream in writeObject() and we have to read from readObject() using ObjectInputStream.
public class MyClass implements Serializable {
     
     String firstName;
     int empID;
     
     public MyClass(String name, int id) {
      firstName = name;
      empID = id;
     }
     
     private void writeObject(ObjectOutputStream out) {
      try {
    out.writeUTF(firstName);
   } catch (IOException e) {
    e.printStackTrace();
   }
     }
     
     private void readObject(ObjectInputStream in) {
      try {
    firstName = in.readUTF();
   } catch (IOException e) {
    e.printStackTrace();
   }
     }
     
     public String getName() {
      return firstName;
     }
     
     public int getEmpId() {
      return empID;
     }
    }
Next step is create an object of the custom class and put it into the intent using putExtra(). In the next activity we can get the custom class object using getIntent().getSerializableExtra()

You can get the full source code from here

Monday, November 28, 2011

Solution for the error "Method called after release()" in Android Camera API

Today when I am working on camera API in android, I got an error telling "ERROR/AndroidRuntime java.lang.RuntimeException: Method called after release()".



Solution

The solution for this is, I am trying to access the camera somewhere after I have released it. So in onResume() set the previewCallback to null. In my case this solved my problem. setPreviewCallback(null);


Happy Coding !!!

Sunday, November 27, 2011

Solution for the error "Debug certificate expired"

Today when I am working suddenly all my projects in eclipse got errors and nothing is compiling. I came to know the the error is "Debug certificate is expired".


Solution



The solution for this is, if you are in windows, then in user profile, you have a folder called ".android", that contains the debug certificate. Delete the debug certificate, then clean and build a project in eclipse. All started working fine.



Example
C:\Users\Nithin\.android

Happy Coding !!!

Access the features of Android device


To access the available features in an Android device, the code snippet,


PackageManager mPackageManager = getPackageManager();
FeatureInfo[] systemFeature = mPackageManager
.getSystemAvailableFeatures();
for (int i = 0; i < systemFeature.length; i++) {
String feature = systemFeature[i].name;
if (feature == null) {
feature = "OpenGL Version : " + systemFeature[i].reqGlEsVersion;
}
systemFeaturesList.add(feature);
}


I just list it into a list, the complete code is,


public class FeaturesListActivity extends Activity {

private final String TAG = "FeaturesListActivity";
private ListView mList;
private ArrayList systemFeaturesList = new ArrayList();

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mList = (ListView) findViewById(R.id.list);
PackageManager mPackageManager = getPackageManager();
FeatureInfo[] systemFeature = mPackageManager
.getSystemAvailableFeatures();
for (int i = 0; i < systemFeature.length; i++) {
String feature = systemFeature[i].name;
if (feature == null) {
feature = "OpenGL Version : " + systemFeature[i].reqGlEsVersion;
}
systemFeaturesList.add(feature);
Log.i(TAG, "**************** System Feature = " + feature);
}
mList.setAdapter(new SystemFeatureListAdapter(this));
}

private class SystemFeatureListAdapter extends BaseAdapter {

private Context mContext;

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

@Override
public int getCount() {
return systemFeaturesList.size();
}

@Override
public Object getItem(int index) {
return systemFeaturesList.get(index);
}

@Override
public long getItemId(int id) {
return id;
}

@Override
public View getView(int position, View view, ViewGroup parent) {
TextView text = new TextView(mContext);
text.setText(systemFeaturesList.get(position));
return text;
}
}
}


The screen-shot of the application is,

Saturday, November 26, 2011

Fetch the unique ID of Android device

To fetch the device ID of any android device, the code snippet is,


TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String android_id = telephonyManager.getDeviceId();


The screen-shot that I got from my HTC phone is,

Wednesday, November 16, 2011

Open Gallery and get the selected image in appplication

In this, the screen will have a button to open the android device Gallery and from there if we select any image, that image we can get it in the application.

The code snipped for opening the Gallery is,


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


We are opening the gallery as a sub activity of our application, because onActivityResult() will get called after selecting the image from gallery. So in onACtivityResult(), we will get the Uri of the selected image and from Mediastore contentprovider, we can get the selected image as bitmap. After that, for showing it in the application, just setting the image in a ImageView.

The complete code is,


public class GalWalActivity extends Activity {

private ImageView selectedImage;
private Bitmap currentImage;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
selectedImage = (ImageView) findViewById(R.id.selectedImage);
Button openGallery = (Button) findViewById(R.id.opengallery);

openGallery.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, 1);
}
});
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);

if (resultCode == RESULT_OK) {
Uri photoUri = data.getData();
if (photoUri != null) {
try {
currentImage = MediaStore.Images.Media.getBitmap(this.getContentResolver(), photoUri);
selectedImage.setImageBitmap(currentImage);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}



The catch here is if we open the gallery for first time from the applicaiotn, the applicaiton will work fine. But if we open gallery for second time and try to get the selected image, we will get an exception OutOfMemory Exception

This is because we are not free the bitmap memory or we need to recycle the bitmap. The solution for this is, every time when we open gallery from our application, onPause() and onStop() of the Activity lifecycle methods will get called. So in either onPause() or onStop(), we need to add the code snippet to recycle the bitmap and to free the memory.


if (currentImage != null) {
currentImage.recycle();
currentImage = null;
System.gc();
}


So onStop() will look like this.


public void onStop() {
super.onStop();
if (currentImage != null) {
currentImage.recycle();
currentImage = null;
System.gc();
}
}


The layout will look like this,


<?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"
>
<Button android:id="@+id/opengallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Gallery"
/>
<ImageView android:id="@+id/selectedImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>


Happy Coding

Wednesday, November 9, 2011

Way to get Bluetooth Address in Android Phone

For getting bluetooth address first we need to enable bluetooth. The code snippet for getting bluetooth address is,


BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
String btMacAddress = btAdapter.getAddress();


The permission that we need to put in Manifest file is,


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

Way to get WiFi address in Android Phones

We will get the WiFi Mac address only if the WiFi is enabled in the device. The code snippet for getting the WiFi address is


WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
String WifiMacAddress = info.getMacAddress();


The permission that we need to put in manifest file is,


<uses-permsission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permsission android:name="android.permission.CHANGE_WIFI_STATE" />

Monday, August 1, 2011

Different ways of Playing a media file in Android

In this I am going to explain different ways of playing a media file in Android. Media here I mean video files. First of all we need a instance of mediaPlayer.

- Unlike audio files, media files require SurfaceView to play the media file.

- Then we need to implement the interface to SurfaceHolder.Callback. To implement the callback methods in SurfaceHolder.

Note:One common error in beginners is, they will try to start mediaPlayer in onCreate() of the activity. But actually at this time, the surfaceView might not be created. So we need to call mediaPlayer.start() in the callback method of surfaceHolder in onSurfaceCreated()

If the media file is in raw folder of the resources, we can get it through,

- AssetFileDescriptor afd = this.getResources().openRawResourceFd(R.raw.monster);

Here monster is the media file name. The media file can be either .mp4 type or .3gp. We can set this fileDescriptor to mediaPlayer instance through the method, setDataSource()

- mediaplayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());

Then if the file is in SDCard, then we can set the media file to mediPlayer through

- String path = "file:///sdcard/monster.3gp";
- mediaPlayer.setDataSource(path);

Tuesday, June 14, 2011

Launching third party application through Intent

The snippet for launching a third party application through intent is,


Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.smartandroidians", "com.smartandroidians.NotificationWithAction");
startActivity(intent);


The first parameter in setClassName() is the package name and the second parameter is the launcher activity class name

Friday, June 3, 2011

Cursor management in Honeycomb

If you are targeting your application for honeycomb, then some APIs related to cursor management are deprecated and your application won't work smoothly in honeycomb, eventhough it will work well in other versions of Android. In Honeycomb, cursor management is more tightly coupled and Some of the APIs that are deprecated are

- startManagingCursor()
- stopManagingCursor()
- managedQuery()
- reQuery()

If you are using any of these methods in HoneyComb, then you will get an exception, like

java.lang.IllegalStateException: trying to requery an already closed cursor

If you are using managedQuery() in lower versions of Android(2.3,2.2) as,

cursor = context.managedQuery(android.provider.Browser.BOOKMARKS_URI, projection, null, null,
null);

then in Honeycomb you need to modify as,

CursorLoader cursorLoader = new CursorLoader(context, android.provider.Browser.BOOKMARKS_URI, projection, null, null,
null);
cursor = cursorLoader .loadInBackground();

Other modification is , you don't need to call reQuery in honeyComb. You have LoaderManager callbacks are there in honeyComb. That will be called if there is any change in the underlying data.

For implementing LoaderManager callbacks

- First implement the interface in your class as LoaderManager.LoaderCallbacks
- in onCreate you need to initialize the loader as
getLoaderManager().initLoader(0, null, this);
- for reQuery, you can use, getLoaderManager().restartLoader(0, null, this);
- Then you need to override three methods in it as,
- onCreateLoader()
- onLoadFinished()
- onLoaderReset()

Tuesday, May 10, 2011

Way to check whether an application is running in Android

Today I came across one interesting thing in Android and I would like to share with you all. In this post I am going to explain the power of the class RunningAppProcessInfo. Through this class we can check whether the application is running, if it is running what is the importance of it, like whether it is in foreground, background, visible etc.

The code snippet is,

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcInfo = activityManager .getRunningAppProcesses();
for(int i = 0; i < runningProcInfo.size(); i++){
        if(runningProcInfo.get(i).processName.equals("com.android.XXXXX")) {
            Log.i(TAG, "XXXX is running");
        }
}


To check the omportance of the process, that is whether it is foreground or in background etc, we can check through the field lru.

for(int i = 0; i < runningProcInfo.size(); i++){
        if(runningProcInfo.get(i).processName.equals("com.android.XXXXX")) {
            Log.i(TAG, "XXXX is running");
            if (runningProcInfo.get(i).lru==RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
                    Log.i(TAG, "XXXX is in foreground");
            }
        }
}

Monday, May 9, 2011

Capture Screen in Android

Capturing screen is a very useful thing in lot of projects. We can use it for thumbnail, in some cases can use it for Animations etc. This post mainly shows the power of setDrawingCacheEnabled() method in Android's View class. Most common use is take the screen shot and use it as a thumbnail. Take a view from the layout xml file and use the code snippet,


TextView tv = (TextView) findViewById(R.id.text);
View img = (View) findViewById(R.id.view);
img = tv.getRootView();
img.setDrawingCacheEnabled(true);
Bitmap bmp = img.getDrawingCache();
ImageView image = (ImageView) findViewById(R.id.img);
image.setImageBitmap(bmp);

Saturday, April 23, 2011

Read bookmark details from Browser provider

Here simply I am reading the contents from the browser provider, bookmark table and listing it in a textView. The contents I am reading here are the title and the URL

The code snippet is,



String[] projection = new String[] { Browser.BookmarkColumns.TITLE,
Browser.BookmarkColumns.URL };
Cursor mCur = managedQuery(android.provider.Browser.BOOKMARKS_URI,
projection, null, null, null);
mCur.moveToFirst();
int titleIdx = mCur.getColumnIndex(Browser.BookmarkColumns.TITLE);
int urlIdx = mCur.getColumnIndex(Browser.BookmarkColumns.URL);
while (mCur.isAfterLast() == false) {
tv.append("\n" + mCur.getString(titleIdx));
tv.append("\n" + mCur.getString(urlIdx));
mCur.moveToNext();
}



You also need to put the permission,


<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />


Screen shot




Get the complete source code from here

Custom Adapter crashes

Wehen I created a custom adapter for a listView, with each list item inflating from a layout. using the statement,


convertView = vi.inflate(R.layout.list_item, parent);

my application crashed, later I put a false to the statement and worked well. The new statement looks like

convertView = vi.inflate(R.layout.list_item, parent, false);

Sunday, February 27, 2011

IOException When uploading a apk

I got a strange exception when I try to upload a apk. The exception looks like this,


Failed to upload xxxxxxxx.apk on device 'emulator-5554'
java.io.IOException: Unable to upload file: timeout


After some googling I fount the solution. I need to increase the ADB connection time-out.

The way to increase is,


Window->Preferences->Android->DDMS->ADB connection time-out


By default, the value is 5000, just increase to the sufficient amount.

Wednesday, January 19, 2011

Playing Ringtone in Android

Android have some system ringtones. We can get the uri for these files through RingtoneManager class. Then using AudioManager and mediaplayer, we can play ringTone up on getting some notifications or for alarm etc.

Note : This code won't work on emulator, this will work only on devices. In emulator, we will get IOException

The complete code is,


try {
Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(this, alert);
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.setLooping(true);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
} catch(Exception e) {
}

Difference between SurfaceView and View in Android

The main difference between SurfaceView and View is,

- Views are drawn in UI thread and surfaceView are drawn in a seperate thread. So if rendering takes long time, its better to use SurfaceView. Then for animations also, its better to use surfaceView.

- SurfaceView uses more resoources than View, so use it when you really want.

Sunday, January 16, 2011

Interprocess Communication in Android - Part I

Interprocess communication can be done in two ways in Android.

- Through AIDL(Android Interface Description Language)
- Through Service and Broadcast Receiver

First I am going to explain inter process communication through AIDL.

Android Interface Description Language(AIDL)

For implementing inter process communication(IPC) through AIDL, the main things that we need are,

- Create a AIDL file containing the functions, that we are going to implement in the Stub class in Service.

- Create a service, in which we need to implement all the the methods that we declare in the AIDL interface. Android will create a stub class and we need to define the methods here. Stub class is nothing but an object of the IBinder. IBinder is an interface for remote objects. It desribes the protocol for interacting with the remote objects.

- Then for calling the AIDL service, we need to implement ServiceConnection interface, for monitoring the state of the application service. This interface contains two methods
a) onServiceConnected() - Called when a connection to the service is established with IBinder of the communication channel.
b) onServiceDisconnected() - Called when a connection to the service has been lost.

In onServiceConnected(), method contains IBinder as an object and using that we can connect to the service and can invoke the methods of the AIDL interface. Android will also create a Java class for our AIDL interface class.

- Then like for all service, we need to declare the service in Manifest.

<service android:name=".RemoteService" />


Now, coming to our case, I declare three methods in our AIDL interface as add(), getPid() and getUid().



You can download the full source code here

Wednesday, January 12, 2011

Fetching screen height, finding screen orientation

Here I am going to explain some simple but useful tips in Android.

Fetch Screen Height and width of our Android Phone


To fetch the screen height and width of our Android phone, the code is
DisplayMetrics displaymetrics = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
int screenHeight = displaymetrics.heightPixels;

To find the orientation of our Android Phone


To find out the orientation, that is whether it is in landscape, portrait or in any another orientation, the code is,

int orientation = getResources().getConfiguration().orientation; 
This will give the current orientation. To check whether it is in landscape or portrait,
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
         // do something
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
         // do something else
}

Androidians