Posterous theme by Cory Watilo

Caching Android Images by Least Recently Used Algorithm

LinkedHashMap is created for easy least recently used data structures. You can store images, get and put by using this data structure easily.

Greatartistsstealuc4

But before using this data structure you should extend this class and overwrite some methods.

First you should use LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) constructor not the default one. And set accessOrder variable to true for LRU algorithm. Then you should overwrite removeEldestEntry method to remove least recently used object. This method is called before putting into hashmap, if map size is greated than cache size, then removeEldestEntry method is called. (You can look at javadoc if you are curios about LinkedHashMap, it helped me a lot)

At last you I am overwriting remove method, then unbinding drawable object to be sure that there won't be a reference that will cause memory leak and then recycle the bitmap. You should be carefull as you are forcing to recycle a bitmap, if it is in use on screen than it will cause an error. So implementing remove method is up to you. I would recommend that, if you are not getting an out of memory error, then do not overwrite remove method and do not unbind your drawable objects.

I am using a SoftReference to be sure that if memory is getting bigger and bigger Dalvik garbage collection will take care of these drawable objects. And getting a memory leak error would be much harder.

You can see full implementation of this class below.

 
import java.lang.ref.SoftReference; 
import java.util.LinkedHashMap; 
import java.util.Map; 
 
import android.graphics.drawable.BitmapDrawable; 
import android.graphics.drawable.Drawable; 
 
class LruCacheLinkedHashMap extends LinkedHashMap { 
 private final int maxEntries; 
 
 public LruCacheLinkedHashMap(final int maxEntries) { 
 super(maxEntries + 1, 1.0f, true); 
 this.maxEntries = maxEntries; 
 } 
 
 @Override 
 protected boolean removeEldestEntry(final Map.Entry eldest) { 
 return super.size() > maxEntries; 
 } 
 
 @Override 
 public Object remove(java.lang.Object key) 
 { 
 SoftReference softReferanceDrawable = (SoftReference) get(key); 
 unBindDrawable(softReferanceDrawable.get()); 
 return super.remove(key); 
 } 
 
 private void unBindDrawable(Drawable drawable) 
 { 
 if(drawable != null) 
 { 
 drawable.setCallback(null);   
 if(!((BitmapDrawable)drawable).getBitmap().isRecycled())   
 {   
 ((BitmapDrawable)drawable).getBitmap().recycle();   
 }   
 drawable = null; 
 } 
 } 
 
} 

You can create your LruCacheLinkedHashMap object in your java class.

 
static int CACHE_SIZE = YOUR_CACHE_SIZE_HERE; 
static Map> drawableHashMap = Collections.synchronizedMap(new LruCacheLinkedHashMap>(CACHE_SIZE)); 

And then you can put your drawable object into that data structure.

 
SoftReference softReferenceDrawable = new SoftReference(YOUR_DRAWABLE_OBJECT_HERE); 
drawableHashMap.put(YOUR_KEY_HERE, softReferenceDrawable); 

You do not need to worry about removing objects, this class will take care of this stuff. Just put your drawable object into that hashmap.

Have a nice day!

How to Fullscreen Android Activity in Landscape Mode

Google music is a great android application that is designed by google. When you change orientation to landscape status bar is hidden and application becomes fullscreen. To achieve this usefull trick you can use this code.

Googlemusic
In your activity add this function

 

 
private void updateFullscreenStatus(Boolean bUseFullscreen) 
 {    
 if(bUseFullscreen) 
 { 
 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 
 } 
 else 
 { 
 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 
 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
 } 
 } 

Then in your onCreate method call method according to your orientation.

 
boolean fullscreen = false; 
if(getResources().getConfiguration().orientation == 
getResources().getConfiguration().ORIENTATION_LANDSCAPE) 
{ 
 fullscreen = true; 
} 
updateFullscreenStatus(fullscreen); 
Have fun of Android development!

Fast ListView Scrolling in Android

ListView is the most complex and useful component in Android. I will show how to get smooth scrolling that improves your overall application performance.

Lascaux_painting

First of all while implementing your Adapter's getView method you should not execute a time consuming code.As a result of this method is called again and again when the user scrolls the ListView, performance will be affected too much. For example if you are getting an image from web in your getView method, it will decrease scrolling performance drastically. To prevent this, execute your drawables before the method is executed and store them in a drawable object.

 

Inflating a view from xml is a heavy load in Android. So do not inflate the xml from scratch, just inflate once. And make your convertView reusable so that you use just an instance, not to create everytime you scroll the listview again and again.

 
LayoutInflater layoutInflator; 
if (convertView == null) 
{ 
 convertView = layoutInflator.inflate(R.layout.YOUR_LIST_ITEM_XML, parent, false); 
} 

findViewById is another time consuming code that you should avoid, as it searches every object reference. To avoid this, create a class that mimics your list item. For example I have two imageView's and one textView in a row. So that my class is just like below. (It is located as an inner class in my adapter, but you can put it everywhere you like)

 
class FeedViewHolder 
{ 
 ImageView feedPhotoImageView; 
 ImageView userPhotoImageView; 
 TextView textView; 
} 

Then you can find the views by using findViewById method only once and then set it to a FeedViewHolder object instance.

 
LayoutInflater layoutInflator; 
FeedViewHolder feedViewHolder; 
if (convertView == null) 
{ 
 convertView = layoutInflator.inflate(R.layout.YOUR_LIST_ITEM_XML, parent, false); 
 feedViewHolder = new FeedViewHolder(); 
 feedViewHolder.textView = (TextView) convertView.findViewById(R.id.YOUR_TEXTVIEW_ID); 
 feedViewHolder.feedPhotoImageView = (ImageView) convertView.findViewById(R.id.YOUR_IMAGE_VIEW_ID_1); 
 feedViewHolder.userPhotoImageView = (ImageView) convertView.findViewById(R.id.YOUR_IMAGE_VIEW_ID_2); 
} 

Setting a tag to your convertView and then getting by using that tag will increase performance too.

 
LayoutInflater layoutInflator; 
FeedViewHolder feedViewHolder; 
if (convertView == null) 
{ 
 convertView = layoutInflator.inflate(R.layout.YOUR_LIST_ITEM_XML, parent, false); 
 feedViewHolder = new FeedViewHolder(); 
 feedViewHolder.textView = (TextView) convertView.findViewById(R.id.YOUR_TEXT_VIEW_ID); 
 feedViewHolder.feedPhotoImageView = (ImageView) convertView.findViewById(R.id.YOUR_IMAGE_VIEW_ID_1); 
 feedViewHolder.userPhotoImageView = (ImageView) convertView.findViewById(R.id.YOUR_IMAGE_VIEW_ID_2); 
 convertView.setTag(feedViewHolder); 
} else 
{ 
 feedViewHolder = (FeedViewHolder) convertView.getTag(); 
} 

You can increase performance by setting smooth scrolling to false of your ListView. In your xml file where you put your ListView. After this modification android will not calculate rows height again and again, so that will increase performance but your scroll will loose smoothness, so it is optional to use this or not.

 
< ListView 
 ... 
 android:smoothScrollbar="false" /> 

After all, overall code will look like this

  
 ... 
 LayoutInflater layoutInflator; 
 
 @Override 
 public View getView(int position, View convertView, ViewGroup parent) 
 { 
 FeedViewHolder feedViewHolder; 
 if (convertView == null) 
 { 
 convertView = layoutInflator.inflate(R.layout.YOUR_LIST_ITEM_XML, parent, false); 
 feedViewHolder = new FeedViewHolder(); 
 feedViewHolder.textView = (TextView) convertView.findViewById(R.id.YOUR_TEXT_VIEW_ID); 
 feedViewHolder.feedPhotoImageView = (ImageView) convertView.findViewById(R.id.YOUR_IMAGE_VIEW_ID_1); 
 feedViewHolder.userPhotoImageView = (ImageView) convertView.findViewById(R.id.YOUR_IMAGE_VIEW_ID_2); 
 convertView.setTag(feedViewHolder); 
 } else 
 { 
 feedViewHolder = (FeedViewHolder) convertView.getTag(); 
 } 
 //YOUR CODE HERE, DO NOT FORGET NOT TO WRITE A HEAVY CODE HERE LIKE NETWORK COMMUNICATION 
 return convertView; 
 } 
} 
 
class FeedViewHolder 
{ 
 ImageView feedPhotoImageView; 
 ImageView userPhotoImageView; 
 TextView textView; 
} 

At last your listview will have a smooth scrolling performance.

Have fun of Android!

How to Get Images Asynchronously from Web in Android

Hi all,

This method will help you much if you care about android application responsiveness and do not want to get ANR notifications while getting images from internet.

Generate a class called WebUtil, which will get images from web as a drawable object. (Note that this class will fix a common error in image decoder library skia - "decoder->decode returned false error")

Picasso_kadin
 
import java.io.InputStream; 
import java.net.URI; 
 
import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.entity.BufferedHttpEntity; 
import org.apache.http.impl.client.DefaultHttpClient; 
 
import android.graphics.drawable.Drawable; 
 
public class WebUtil 
{ 
 static int i = 0; 
 
 public static Drawable drawable_from_url(String url) 
 { 
 InputStream instream = null; 
 try 
 { 
 HttpGet httpRequest = new HttpGet(new URI(url)); 
 HttpClient httpclient = new DefaultHttpClient(); 
 HttpResponse response = (HttpResponse) httpclient.execute(httpRequest); 
 HttpEntity entity = response.getEntity(); 
 BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity); 
 try 
 { 
 instream = bufHttpEntity.getContent(); 
 String src_name = "image" + i++; 
 return Drawable.createFromStream(instream, src_name); 
 } catch (Exception e) 
 { 
 ExceptionUtil.convertExceptionToString(e); 
 } finally 
 { 
 if (instream != null) 
 { 
 instream.close(); 
 } 
 } 
 } catch (Exception e) 
 { 
 ExceptionUtil.convertExceptionToString(e); 
 } 
 return null; 
 } 
}  
Then create a class called ImageUtil which will create a thread that downloads image and then refreshes imageview.
 
import java.util.ArrayList;    
import android.graphics.drawable.Drawable;    
import android.os.Handler;    
import android.widget.ImageView;    
 
public class ImageUtil    
{    
 public static void getImageByURL(final ImageView imageView, final String url)    
 {    
 final ArrayList drawableArrayList = new ArrayList();    
 // Create runnable for posting    
 final Runnable mUpdateResults = new Runnable() {    
 public void run() {    
 updateResultsInUi();    
 }        
 private void updateResultsInUi()    
 {    
 
imageView.setBackgroundDrawable(drawableArrayList.get(0));    
 }    
 };    
 final Handler mHandler = new Handler();    
 Thread thread = new Thread() {    
 public void run() {    
 Drawable remoteDrawable = WebUtil.drawable_from_url(url);    
 drawableArrayList.add(remoteDrawable);    
 mHandler.post(mUpdateResults);    
 }    
 };    
 thread.start();    
 }    
}    
After all, you can call your method and update your imageview by just one line.
  ImageUtil.getImageByURL(YOUR_IMAGE_VIEW_OBJECT_HERE, "YOUR_URL_HERE");  
Get fun!

C# Serial Port Communication

I needed to send data from serial port in C# for my senior project.

Here is my PIC circuit that will handle the data.

Pic

Add a class file called CommunicationManager.cs

 
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.IO.Ports;    
namespace motion  
{  
 class CommunicationManager  
 {  
 public enum TransmissionType { Text, Hex }  
 public enum MessageType { Incoming, Outgoing, Normal, Warning, Error };  
 private string _baudRate = string.Empty;  
 private string _parity = string.Empty;  
 private string _stopBits = string.Empty;  
 private string _dataBits = string.Empty;  
 private string _portName = string.Empty;  
 private TransmissionType _transType;  
 private SerialPort comPort = new SerialPort();  
 
 public string BaudRate  
 {  
 get { return _baudRate; }  
 set { _baudRate = value; }  
 }  
 
 public string Parity  
 {  
 get { return _parity; }  
 set { _parity = value; }  
 }  
 
 public string StopBits  
 {  
 get { return _stopBits; }  
 set { _stopBits = value; }  
 }  
 
 public string DataBits  
 {  
 get { return _dataBits; }  
 set { _dataBits = value; }  
 }  
 
 public string PortName  
 {  
 get { return _portName; }  
 set { _portName = value; }  
 }  
 
 public TransmissionType CurrentTransmissionType  
 {  
 get { return _transType; }  
 set { _transType = value; }  
 }  
 
 public CommunicationManager(string baud, string par, string sBits, string dBits, string name)  
 {  
 _baudRate = baud;  
 _parity = par;  
 _stopBits = sBits;  
 _dataBits = dBits;  
 _portName = name;  
 //now add an event handler  
 comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);  
 }   
 
 public CommunicationManager(string port_name)  
 {  
 _baudRate = string.Empty;  
 _parity = string.Empty;  
 _stopBits = string.Empty;  
 _dataBits = string.Empty;  
 _portName = port_name;  
 //add event handler  
 comPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);  
 }  
 
 public void WriteData(string msg)  
 {  
 
 switch (CurrentTransmissionType)  
 {  
 case TransmissionType.Text:  
 //first make sure the port is open  
 //if its not open then open it  
 if (!(comPort.IsOpen == true)) comPort.Open();  
 //send the message to the port 
 //here we are sending a carriage return with data to handle other side  
 comPort.Write(msg + "\r");  
 
 //display the message  
 DisplayData(MessageType.Outgoing, msg + "\n");  
 break;  
 
 case TransmissionType.Hex:  
 try  
 {  
 //convert the message to byte array  
 byte[] newMsg = HexToByte(msg);  
 //send the message to the port  
 comPort.Write(newMsg, 0, newMsg.Length);  
 //convert back to hex and display  
 DisplayData(MessageType.Outgoing, ByteToHex(newMsg) + "\n");  
 }  
 catch (FormatException ex)  
 {  
 //display error message  
 DisplayData(MessageType.Error, ex.Message);  
 }  
 finally  
 {  
 }  
 break;  
 default:  
 //first make sure the port is open  
 //if its not open then open it  
 if (!(comPort.IsOpen == true)) comPort.Open();  
 //send the message to the port  
 comPort.Write(msg);  
 //display the message  
 DisplayData(MessageType.Outgoing, msg + "\n");  
 break;  
 break;  
 }  
 }  
 
 private byte[] HexToByte(string msg)  
 {  
 //remove any spaces from the string  
 msg = msg.Replace(" ", "");  
 //create a byte array the length of the  
 //divided by 2 (Hex is 2 characters in length)  
 byte[] comBuffer = new byte[msg.Length / 2];  
 //loop through the length of the provided string  
 for (int i = 0; i < msg.Length; i += 2)  
 //convert each set of 2 characters to a byte  
 //and add to the array  
 comBuffer[i / 2] = (byte)Convert.ToByte(msg.Substring(i, 2), 16);  
 //return the array  
 return comBuffer;  
 }  
 
 private string ByteToHex(byte[] comByte)  
 {  
 //create a new StringBuilder object  
 StringBuilder builder = new StringBuilder(comByte.Length * 3);  
 //loop through each byte in the array  
 foreach (byte data in comByte)  
 //convert the byte to a string and add to the stringbuilder  
 builder.Append(Convert.ToString(data, 16).PadLeft(2, '0').PadRight(3, ' '));  
 //return the converted value  
 return builder.ToString().ToUpper();  
 }  
 
 [STAThread]  
 private void DisplayData(MessageType type, string msg)  
 {  
 Console.WriteLine(msg);  
 }  
 
 public bool OpenPort(string port_Name)  
 {  
 try  
 {  
 //first check if the port is already open  
 //if its open then close it  
 if (comPort.IsOpen == true) comPort.Close();  
 
 //set the properties of our SerialPort Object  
 comPort.BaudRate = int.Parse(_baudRate);    //BaudRate  
 comPort.DataBits = int.Parse(_dataBits);    //DataBits  
 comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits);    //StopBits  
 comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity);    
//Parity  
 _portName = port_Name;  
 comPort.PortName = _portName;   //PortName  
 //now open the port  
 comPort.Open();  
 //display message  
 DisplayData(MessageType.Normal, "Port opened at " + DateTime.Now + "\n");  
 //return true  
 return true;  
 }  
 catch (Exception ex)  
 {  
 DisplayData(MessageType.Error, ex.Message);  
 return false;  
 }  
 }  
 
 void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)  
 {  
 //determine the mode the user selected (binary/string)  
 switch (CurrentTransmissionType)  
 {  
 //user chose string  
 case TransmissionType.Text:  
 //read data waiting in the buffer  
 string msg = comPort.ReadExisting();  
 //display the data to the user  
 DisplayData(MessageType.Incoming, msg + "\n");  
 break;  
 //user chose binary  
 case TransmissionType.Hex:  
 //retrieve number of bytes in the buffer  
 int bytes = comPort.BytesToRead;  
 //create a byte array to hold the awaiting data  
 byte[] comBuffer = new byte[bytes];  
 //read the data and store it  
 comPort.Read(comBuffer, 0, bytes);  
 //display the data to the user  
 DisplayData(MessageType.Incoming, ByteToHex(comBuffer) + "\n");  
 break;  
 default:  
 //read data waiting in the buffer  
 string str = comPort.ReadExisting();  
 //display the data to the user  
 DisplayData(MessageType.Incoming, str + "\n");  
 break;  
 }  
 }  
 }  
}  
Then you can create a communicationmanager object and send data.
 
CommunicationManager comm; 
comm = new CommunicationManager();  
//this configuration is for me, you should change these for your appropriate conditions 
string transType = string.Empty;   
comm.Parity = "None";  
comm.StopBits = "One";  
comm.DataBits = "8";  
comm.BaudRate = "115200";  
comm.OpenPort("COM5"); 
comm.CurrentTransmissionType = CommunicationManager.TransmissionType.Text;  
comm.WriteData("YOUR_DATA_HERE");  
As you See it is not that much hard. Have fun!

 

 

How to Handle Orientation Changes Effectively in Android

Android SDK has solved orientation change problem with a general solution which is restarting the current activity. As a result you should handle some situations like not downloading the same pictures or getting the same http response while changing orientation.

Miro_bleu2
If you change the orientation android will call these methods of your activity in this order.

OnPause > OnStop > onRetainNonConfigurationInstance > OnDestroy > OnCreate > OnStart > OnResume

These methods will be executed arbitrarly in this order. As you see a difference which is onRetainNonConfigurationInstance method is called between OnStop and OnDestroy. This function will be called only on orientation changes. It returns an object and can be used not to download the same information again and again by using the getLastNonConfigurationInstance method while creating your activity. You can see a nice tutorial about this here. But I will offer a nicer way that works for me.

I am making lots of get request during one activity creation so, I could not solved my problem by calling getLastNonConfigurationInstance method and returning just one object. And the method told above can easily leak memory as the returned object is referenced by activity. Activity object is connected to application object so it does not collected by garbage collector. You should be careful while using the getLastNonConfigurationInstance method. Lets come to my simple solution.

Define a static boolean in your activity class

 public class YOUR_ACTIVITY extends Activity { 
 static boolean isOrientationChanged = false; //static variable to hold orientation change 
 static ArrayList YOUR_DRAWABLE_LIST; //your drawable arraylist that will be downloaded from internet 
 static String response; //your response here that will be returned by http get 
 //overrided onRetainNonConfigurationInstance method which will be called while destroying activity 
 @Override     public Object onRetainNonConfigurationInstance()     {          
 isOrientationChanged = true;  
 return null; //as you are not returning an object you are not leaking memory here      
 } 
 @Override public void onCreate(Bundle savedInstanceState)      
 {          
 super.onCreate(savedInstanceState);         
 if(!isOrientationChanged) //this part is executed if orienation is not changed (activity starts as usual) 
 { 
 unbindDrawables(); //you can unbind your drawables for not to leak memory here (this will be your method, optional)             
 response = AndroidHttpClient.executeHttpGet(callBackURL); //this is again your method to get an http request             
 YOUR_DRAWABLE_LIST = new ArrayList(); //initialize your drawable list 
 DOWNLOAD_ALL_DRAWABLES_FROM_INTERNET_AND_FILL_LIST(YOUR_DRAWABLE_LIST); 
 } 
 isOrientationChanged = false; 
 //you can continue writing your application code here. if your activity starts after an orientation change, than old values that are defined static will be used 
 // If your activty starts as usual, that initial conditions will be set and internet and image related objects will get from the heap. 
 ... 
 } 
} 

As you see it is so simple but will make a great user experience difference. Before ending this post I want to mention one thing.

If you want to load different layout's that will be used in different orientation types, then you can create your layout xml in different directories.

Create two directories called layout-land and layout-port under res directory. Then put your landscape xml under layout-land directory and your portrait xml under layout-port directory. Nothing special, android will call correct xml while creating that view.

Have a nice coding!

How to Make a Loading Animation in Android

When I was trying to build my new android app, I wanted to put a loading image while getting images in another thread. But I faced with the fact that animated gif images are not supported on android sdk, so you must make your own animation. There are two alternatives to accompolish this task.

100

  • Frame animation

This method works just like animated gif's work. You are creating frame by frame animations and then starting animation.

Create a xml file called loadinganim.xml under res/drawable directory with the content below.



<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/load0" android:duration="60" />
    <item android:drawable="@drawable/load1" android:duration="60" />
    <item android:drawable="@drawable/load2" android:duration="60" />
    <item android:drawable="@drawable/load3" android:duration="60" />
    <item android:drawable="@drawable/load4" android:duration="60" />
    <item android:drawable="@drawable/load5" android:duration="60" />
    <item android:drawable="@drawable/load6" android:duration="60" />
    <item android:drawable="@drawable/load7" android:duration="60" />
    <item android:drawable="@drawable/load8" android:duration="60" />
    <item android:drawable="@drawable/load9" android:duration="60" />
    <item android:drawable="@drawable/load10" android:duration="60" />
    <item android:drawable="@drawable/load11" android:duration="60" />
    <item android:drawable="@drawable/load12" android:duration="60" />
    <item android:drawable="@drawable/load13" android:duration="60" />
    <item android:drawable="@drawable/load14" android:duration="60" />
    <item android:drawable="@drawable/load15" android:duration="60" />
    <item android:drawable="@drawable/load16" android:duration="60" />
    <item android:drawable="@drawable/load17" android:duration="60" />
    <item android:drawable="@drawable/load18" android:duration="60" />
    <item android:drawable="@drawable/load19" android:duration="60" />
    <item android:drawable="@drawable/load20" android:duration="60" />
    <item android:drawable="@drawable/load21" android:duration="60" />
    <item android:drawable="@drawable/load22" android:duration="60" />
    <item android:drawable="@drawable/load23" android:duration="60" />
    <item android:drawable="@drawable/load24" android:duration="60" />
    <item android:drawable="@drawable/load25" android:duration="60" />
    <item android:drawable="@drawable/load26" android:duration="60" />
    <item android:drawable="@drawable/load27" android:duration="60" />
    <item android:drawable="@drawable/load28" android:duration="60" />
    <item android:drawable="@drawable/load29" android:duration="60" />
</animation-list>

 

Then put this imageview in your layout file where you want to show the loading image

<ImageView
        android:id="@+id/blankImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/load0"/>

Then in your java code where you want to put

setContentView(R.layout.YOUR_LAYOUT_THAT_CONTAINS_IMAGE_VIEW_ABOVE);
final ImageView imageView = (ImageView) findViewById(R.id.blankImageView); 
AnimationDrawable yourAnimation; 
imageView.setBackgroundResource(R.drawable.loadinganim); 
yourAnimation = (AnimationDrawable) imageView.getBackground();  
imageView.setOnClickListener(new OnClickListener(){  
            @Override 
            public void onClick(View v) 
            {                 yourAnimation.start(); 
            } 
});

When you click on the image it will start to animate. You should be careful about not putting start() code on your oncreate method, because while executing that method ui have not been created, so you won't see an animated image. As a result of this, I put start() code in a clicklistener. You can put it in your applications right place that is guaranteed to have a valid ui. (you can use your activities onWindowFocusChanged method) I have created a nice animation that you can see above, and you can download the images for the code above here.(Unzip and put these images under res/drawable folder)

  • Tween Animation

Other method is tween animation. We will use rotate for this purpose, you can use whatever you want. You can see a list of tween animations here

Create a xml called rotate.xml under res/anim folder, (if this folder is not there, create one)

<?xml version="1.0" encoding="UTF-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="359"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:duration="1000"
    android:interpolator="@anim/linear_interpolator" />

Then create a xml called linear_interpolator.xml under res/anim folder. This will generate a linear interpolator, so your animation will not slow down or speed up during animation.

<?xml version="1.0" encoding="utf-8"?>
<linearInterpolator xmlns:android="http://schemas.android.com/apk/res/android" />

Then put this imageview in your layout file where you want to show the loading image

 

<ImageView
        android:id="@+id/blankImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/YOUR_DRAWABLE_THAT_WILL_ROTATE"/>

Then in your java code where you want to put

 

 setContentView(R.layout.YOUR_LAYOUT_THAT_CONTAINS_IMAGE_VIEW_ABOVE);  
final ImageView imageView = (ImageView) findViewById(R.id.blankImageView); 
imageView.setOnClickListener(new OnClickListener(){    
@Override  public void onClick(View v)  {  
imageView.startAnimation(AnimationUtils.loadAnimation(YOUR_CONTEXT, R.anim.rotate)); 
} 
}); 

 

You can see animated image when you click on image. Again I put this to ensure that ui is created. Of course you will change this in your application logic.

You can get fun of your loading images. I found frame animation suits for me, you can use whatever you want.

Have a nice coding!

 

How to Accept Self Signed Certificates in Android

To accept self signed certificates, you do not need to do anything in Android 2.3, but it will crash and raise an "javax.net.ssl.SSLException: Not trusted server certificate" exception on Android 2.2 and below. To accept all self signed certificates you can use the code below.

Miro-chanteur
First you need a Socket Factory class that extends SSLSocketFactory, mine is called AndroidSSLSocketFactory

 
import java.io.IOException; 
import java.net.Socket; 
import java.net.UnknownHostException; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import org.apache.http.conn.ssl.SSLSocketFactory; 
public class AndroidSSLSocketFactory extends SSLSocketFactory { 
 sslContext = SSLContext.getInstance("TLS"); 
 public AndroidSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { 
 super(truststore); 
 TrustManager tm = new X509TrustManager() { 
 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
 } 
 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
 } 
 public X509Certificate[] getAcceptedIssuers() { 
 return null; 
 } 
 }; 
 sslContext.init(null, new TrustManager[] { tm }, null); 
 } 
 @Override 
 public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { 
 return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 
 } 
 @Override 
 public Socket createSocket() throws IOException { 
 return sslContext.getSocketFactory().createSocket(); 
 } 
}   

Then you need a class that initiates a HTTPClient, registers ports 80 and 443 to make a request

 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.URI; 
import java.security.KeyStore; 
import java.util.ArrayList; 
import org.apache.http.HttpResponse; 
import org.apache.http.HttpVersion; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.conn.ClientConnectionManager; 
import org.apache.http.conn.scheme.PlainSocketFactory; 
import org.apache.http.conn.scheme.Scheme; 
import org.apache.http.conn.scheme.SchemeRegistry; 
import org.apache.http.conn.ssl.SSLSocketFactory; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.params.HttpProtocolParams; 
import org.apache.http.protocol.HTTP; 
import YOUR_PACKAGE_NAME.AndroidSSLSocketFactory; 
public class AndroidHttpClient { 
 public static final int HTTP_TIMEOUT = 30 * 1000; // milliseconds 
 public static HttpClient getHttpClient() { 
 try { 
 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
 trustStore.load(null, null); 
 SSLSocketFactory sf = new AndroidSSLSocketFactory(trustStore); 
 sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
 HttpParams params = new BasicHttpParams(); 
 HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
 HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 
 SchemeRegistry registry = new SchemeRegistry(); 
 registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
 registry.register(new Scheme("https", sf, 443)); 
 ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); 
 return new DefaultHttpClient(ccm, params); 
 } catch (Exception e) { 
 return new DefaultHttpClient(); 
 } 
 } 
 public static String executeHttpPost(String url, ArrayList postParameters) throws Exception { 
 BufferedReader in = null; 
 try { 
 HttpClient client = getHttpClient();             
 HttpPost request = new HttpPost(url); 
 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters); 
 request.setEntity(formEntity); 
 HttpResponse response = client.execute(request); 
 in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 
 StringBuffer sb = new StringBuffer(""); 
 String line = ""; 
 String NL = System.getProperty("line.separator"); 
 while ((line = in.readLine()) != null) { 
 sb.append(line + NL); 
 } 
 in.close();           
 String result = sb.toString(); 
 return result; 
 } finally { 
 if (in != null) { 
 try { 
 in.close(); 
 } catch (IOException e) { 
 e.printStackTrace(); 
 } 
 } 
 } 
 } 
 public static String executeHttpGet(String url) throws Exception { 
 BufferedReader in = null; 
 try { 
 HttpClient client = getHttpClient(); 
 HttpGet request = new HttpGet(); 
 request.setURI(new URI(url)); 
 HttpResponse response = client.execute(request); 
 in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 
 StringBuffer sb = new StringBuffer(""); 
 String line = ""; 
 String NL = System.getProperty("line.separator"); 
 while ((line = in.readLine()) != null) { 
 sb.append(line + NL); 
 } 
 in.close();        
 String result = sb.toString(); 
 return result;  
 } finally { 
 if (in != null) { 
 try { 
 in.close(); 
 } catch (IOException e) { 
 e.printStackTrace(); 
 } 
 } 
 } 
 }    
}  

and you can make post requests by using the code below.

String response = AndroidHttpClient.executeHttpPost(YOUR_URL_HERE, POST_PARAMETERS_AS_NAME_VALUE_PAIRS);

You can find this method unsecure as it is open to man in the middle attacks. You can accept only the required certificates by using the blog post here.

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

Android Memory Management

Android Dalvik VM has a garbage collector, which works pretty well, but the problem is garbage collection does not ensures memory leak. As telephones have low memory, and android have a great variety of devices which have a greater or smaller memory, you should be so much carefull about memory management.

Memory

The biggest problem occurs when you play with big files like images. Images are not stored as byte array and not stored in VM heap space. But your applications overall memory is calculated by adding this extra storege that are used for images(or other media) and heap space. You should not exceed 4 MB. Memory leak is easier than you think while garbage collection is on. Let me explain.

  TextView textView = new TextView(this);
  textView.setBackgroundDrawable(getDrawable(R.drawable.your_image));  
  setContentView(textView);

This code seems so innocent but it is not. As you are binding a drawable object (which consumes too much space on memory) to a textView, and afterwards you are binding this textView to your Activity object (which is alive till your application kills). As there exists a reference to all of these objects garbage collector can not release these objects. And your application crashes by operating system when it exceeds and have much  limits.

Solution: I am collecting all the images in a arrayList and when it is not visible to the user I set all drawables callbacks to null and recycle drawable that can be leaked.

drawable.setCallback(null);
if(!((BitmapDrawable)drawable).getBitmap().isRecycled())
{
  ((BitmapDrawable)drawable).getBitmap().recycle();
}
drawable = null;

This code will remove all references that are connected to drawble. And garbage collector can work as expected. Otherwise you will have a outofmemory error and your application will be killed by operating system.

Anyway, you should be carefull as you are freeing an image from a view, you should handle situations that these null images are not shown to user. When user does an action like clicking back button or inflating that view, you should override and handle these situtions and generate new drawable objects. Creating new drawables will slow your application a little but it won't crash because of out of memory.

At last I want to say something about google maps on anroid. Google maps uses its own memory management system, and it won't consume your memory space. So be patient when memory consumption increases while playing with google maps.

You can use ddms tool under android_sdk/tools directory. To run it execute command ./ddms

Have fun of android development as it is pretty well designed but lacks of tools that iphone has. Anyway I like android as it is free.

How to speed up android emulator

This method will decrease android emulator starting and closing time drastically, it will not speed up android emulator running time performance.

First you should save a snapshot, to do this start android emulator as shown in the screenshot.

Savetosnapshot
When you close the emulator it will save a snapshot, so closing time of the emulator can lengthen to minutes, so please patient.

Next time you start the emulator, you can launch the emulator from a snapshot, it is shown in the screenshot below. As you see below, I did not checked save to snapshot, so closing time of the emulator is short.

Launchfromsnapshot
As a result, android emulator starts in 3 seconds, and closes in 1 second on my machine.

Get fun of it!