Android Search Filter XML Parse Images and Texts Tutorial

In this tutorial, you will learn how to implement a search functionality into your XML Parser that filters images and texts in your Android application. A listview can be filtered by the user input and is enabled using addTextChangedListener method. The search function will filter the listview with a matching string from the user input. Searching through the listview provides users an easy way to find the information they needed. The search function will filter the ListView with a matching string from the user input. We will create a listview with an edittext placed on top and on text input will filter the results of images and texts and on listview item click will open a new activity. We will parse the images and texts from an URL using an XML parser. So lets begin…

Create a new project in Eclipse File > New > Android Application Project. Fill in the details and name your project SearchXMLParse.

Application Name : SearchXMLParse

Project Name : SearchXMLParse

Package Name : com.androidbegin.searchxmlparse

Open your MainActivity.java and paste the following code.

MainActivity.java

package com.androidbegin.searchxmlparse;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;
import android.widget.ListView;

public class MainActivity extends Activity {
	// Declare Variables
	ListView listview;
	ListViewAdapter adapter;
	ProgressDialog mProgressDialog;
	static String RANK = "rank";
	static String COUNTRY = "country";
	static String POPULATION = "population";
	static String FLAG = "flag";
	EditText editsearch;
	private List<WorldPopulation> worldpopulationlist = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Get the view from listview_main.xml
		setContentView(R.layout.listview_main);
		// Execute DownloadXML AsyncTask
		new DownloadXML().execute();
	}

	// DownloadXML AsyncTask
	private class DownloadXML extends AsyncTask<Void, Void, Void> {

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			// Create a progressdialog
			mProgressDialog = new ProgressDialog(MainActivity.this);
			// Set progressdialog title
			mProgressDialog.setTitle("Android Search Filter XML Parse");
			// Set progressdialog message
			mProgressDialog.setMessage("Loading...");
			mProgressDialog.setIndeterminate(false);
			// Show progressdialog
			mProgressDialog.show();
		}

		@Override
		protected Void doInBackground(Void... params) {
			// Create the array
			worldpopulationlist = new ArrayList<WorldPopulation>();
			XMLParser parser = new XMLParser();
			// Retrive nodes from the given website URL in XMLParser.class
			String xml = parser
					.getXmlFromUrl("https://www.androidbegin.com/tutorial/xmlparseimgtxt.xml");
			// Retrive DOM element
			Document doc = parser.getDomElement(xml);

			try {
				// Locate the NodeList name
				NodeList nl = doc.getElementsByTagName("ranking");
				for (int i = 0; i < nl.getLength(); i++) {
					Element e = (Element) nl.item(i);
					WorldPopulation map = new WorldPopulation();
					map.setRank(parser.getValue(e, RANK));
					map.setCountry(parser.getValue(e, COUNTRY));
					map.setPopulation(parser.getValue(e, POPULATION));
					map.setFlag(parser.getValue(e, FLAG));

					worldpopulationlist.add(map);
				}
			} catch (Exception e) {
				Log.e("Error", e.getMessage());
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void args) {
			// Locate the listview in listview_main.xml
			listview = (ListView) findViewById(R.id.listview);
			// Pass the results into ListViewAdapter.java
			adapter = new ListViewAdapter(MainActivity.this,
					worldpopulationlist);
			// Binds the Adapter to the ListView
			listview.setAdapter(adapter);
			// Close the progressdialog
			mProgressDialog.dismiss();
			// Locate the EditText in listview_main.xml
			editsearch = (EditText) findViewById(R.id.search);

			// Capture Text in EditText
			editsearch.addTextChangedListener(new TextWatcher() {

				@Override
				public void afterTextChanged(Editable arg0) {
					// TODO Auto-generated method stub
					String text = editsearch.getText().toString()
							.toLowerCase(Locale.getDefault());
					adapter.filter(text);
				}

				@Override
				public void beforeTextChanged(CharSequence arg0, int arg1,
						int arg2, int arg3) {
					// TODO Auto-generated method stub
				}

				@Override
				public void onTextChanged(CharSequence arg0, int arg1,
						int arg2, int arg3) {
					// TODO Auto-generated method stub
				}
			});
		}
	}
}

In this activity, we have hosted an XML file in our server and used the XML parser to retrieve nodes from the URL address. We have created an AsyncTask as a background task to load the XML nodes into a string array and pass it to the ListViewAdapter.

XML File Link : https://www.androidbegin.com/tutorial/xmlparseimgtxt.xml

Output :

<worldpopulation>

    <ranking>
        <rank>1</rank>
        <country>China</country>
        <population>1,354,040,000</population>
        <flag>https://www.androidbegin.com/tutorial/flag/china.png</flag>
    </ranking>

    <ranking>
        <rank>2</rank>
        <country>India</country>
        <population>1,210,193,422</population>
        <flag>https://www.androidbegin.com/tutorial/flag/india.png</flag>
    </ranking>

    <ranking>
        <rank>3</rank>
        <country>United States</country>
        <population>315,761,000</population>
        <flag>https://www.androidbegin.com/tutorial/flag/unitedstates.png</flag>
    </ranking>

    <ranking>
        <rank>4</rank>
        <country>Indonesia</country>
        <population>237,641,326</population>
        <flag>https://www.androidbegin.com/tutorial/flag/indonesia.png</flag>
    </ranking>

    <ranking>
        <rank>5</rank>
        <country>Brazil</country>
        <population>193,946,886</population>
        <flag>https://www.androidbegin.com/tutorial/flag/brazil.png</flag>
    </ranking>

    <ranking>
        <rank>6</rank>
        <country>Pakistan</country>
        <population>182,912,000</population>
        <flag>https://www.androidbegin.com/tutorial/flag/pakistan.png</flag>
    </ranking>

    <ranking>
        <rank>7</rank>
        <country>Nigeria</country>
        <population>170,901,000</population>
        <flag>https://www.androidbegin.com/tutorial/flag/nigeria.png</flag>
    </ranking>

    <ranking>
        <rank>8</rank>
        <country>Bangladesh</country>
        <population>152,518,015</population>
        <flag>https://www.androidbegin.com/tutorial/flag/bangladesh.png</flag>
    </ranking>

    <ranking>
        <rank>9</rank>
        <country>Russia</country>
        <population>143,369,806</population>
        <flag>https://www.androidbegin.com/tutorial/flag/russia.png</flag>
    </ranking>

    <ranking>
        <rank>10</rank>
        <country>Japan</country>
        <population>127,360,000</population>
        <flag>https://www.androidbegin.com/tutorial/flag/japan.png</flag>
    </ranking>

</worldpopulation>

All images in this tutorial are hosted in our server. You can download the sample images below and host it on your server.

Sample Images

[wpfilebase tag=file id=35 tpl=download-button /]

Next, create an XML graphical layout for your listview. Go to res > layout > Right Click on layout > New > Android XML File

Name your new XML file listview_main.xml and paste the following code.

listview_main.xml

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

    <EditText
        android:id="@+id/search"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <requestFocus />
    </EditText>

    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/search" />

</RelativeLayout>

Output:
SearchXMLParse XML Main

Next, create an array class. Go to File > New > Class and name it WorldPopulation.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your WorldPopulation.java and paste the following code.

WorldPopulation.java

package com.androidbegin.searchxmlparse;

public class WorldPopulation {
	private String rank;
	private String country;
	private String population;
	private String flag;

	public String getRank() {
		return rank;
	}

	public void setRank(String rank) {
		this.rank = rank;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getPopulation() {
		return population;
	}

	public void setPopulation(String population) {
		this.population = population;
	}

	public String getFlag() {
		return flag;
	}

	public void setFlag(String flag) {
		this.flag = flag;
	}

}

Next, create an XML Parser class. Go to File > New > Class and name it XMLParser.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your XMLParser.java and paste the following code.

XMLParser.java

package com.androidbegin.searchxmlparse;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.util.Log;

public class XMLParser {

	public XMLParser() {

	}

	// Retrive XML from URL
	public String getXmlFromUrl(String url) {
		String xml = null;

		try {
			DefaultHttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(url);

			HttpResponse httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			xml = EntityUtils.toString(httpEntity);

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return xml;
	}

	// Retrive DOM element
	public Document getDomElement(String xml) {
		Document doc = null;
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {

			DocumentBuilder db = dbf.newDocumentBuilder();

			InputSource is = new InputSource();
			is.setCharacterStream(new StringReader(xml));
			doc = db.parse(is);

		} catch (ParserConfigurationException e) {
			Log.e("Error: ", e.getMessage());
			return null;
		} catch (SAXException e) {
			Log.e("Error: ", e.getMessage());
			return null;
		} catch (IOException e) {
			Log.e("Error: ", e.getMessage());
			return null;
		}

		return doc;
	}

	// Retrive Node element
	public final String getElementValue(Node elem) {
		Node child;
		if (elem != null) {
			if (elem.hasChildNodes()) {
				for (child = elem.getFirstChild(); child != null; child = child
						.getNextSibling()) {
					if (child.getNodeType() == Node.TEXT_NODE) {
						return child.getNodeValue();
					}
				}
			}
		}
		return "";
	}

	// Retrive Node Value
	public String getValue(Element item, String str) {
		NodeList n = item.getElementsByTagName(str);
		return this.getElementValue(n.item(0));
	}
}

This class downloads the XML file and checks whether it is built accordingly.

Next, create a custom listview adapter. Go to File > New > Class and name it ListViewAdapter.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your ListViewAdapter.java and paste the following code.

ListViewAdapter.java

package com.androidbegin.searchxmlparse;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class ListViewAdapter extends BaseAdapter {

	// Declare Variables
	Context context;
	LayoutInflater inflater;
	ArrayList<HashMap<String, String>> data;
	ImageLoader imageLoader;
	private List<WorldPopulation> worldpopulationlist = null;
	private ArrayList<WorldPopulation> arraylist;

	public ListViewAdapter(Context context,
			List<WorldPopulation> worldpopulationlist) {
		this.context = context;
		this.worldpopulationlist = worldpopulationlist;
		inflater = LayoutInflater.from(context);
		this.arraylist = new ArrayList<WorldPopulation>();
		this.arraylist.addAll(worldpopulationlist);
		imageLoader = new ImageLoader(context);
	}

	public class ViewHolder {
		TextView rank;
		TextView country;
		TextView population;
		ImageView flag;
	}

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

	@Override
	public Object getItem(int position) {
		return worldpopulationlist.get(position);
	}

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

	public View getView(final int position, View view, ViewGroup parent) {
		final ViewHolder holder;
		if (view == null) {
			holder = new ViewHolder();
			view = inflater.inflate(R.layout.listview_item, null);
			// Locate the TextViews in listview_item.xml
			holder.rank = (TextView) view.findViewById(R.id.rank);
			holder.country = (TextView) view.findViewById(R.id.country);
			holder.population = (TextView) view.findViewById(R.id.population);
			// Locate the ImageView in listview_item.xml
			holder.flag = (ImageView) view.findViewById(R.id.flag);
			view.setTag(holder);
		} else {
			holder = (ViewHolder) view.getTag();
		}
		// Set the results into TextViews
		holder.rank.setText(worldpopulationlist.get(position).getRank());
		holder.country.setText(worldpopulationlist.get(position).getCountry());
		holder.population.setText(worldpopulationlist.get(position)
				.getPopulation());
		// Set the results into ImageView
		imageLoader.DisplayImage(worldpopulationlist.get(position).getFlag(),
				holder.flag);
		// Listen for ListView Item Click
		view.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// Send single item click data to SingleItemView Class
				Intent intent = new Intent(context, SingleItemView.class);
				// Pass all data rank
				intent.putExtra("rank",
						(worldpopulationlist.get(position).getRank()));
				// Pass all data country
				intent.putExtra("country",
						(worldpopulationlist.get(position).getCountry()));
				// Pass all data population
				intent.putExtra("population",
						(worldpopulationlist.get(position).getPopulation()));
				// Pass all data flag
				intent.putExtra("flag",
						(worldpopulationlist.get(position).getFlag()));
				// Start SingleItemView Class
				context.startActivity(intent);
			}
		});
		return view;
	}

	// Filter Class
	public void filter(String charText) {
		charText = charText.toLowerCase(Locale.getDefault());
		worldpopulationlist.clear();
		if (charText.length() == 0) {
			worldpopulationlist.addAll(arraylist);
		} else {
			for (WorldPopulation wp : arraylist) {
				if (wp.getCountry().toLowerCase(Locale.getDefault())
						.contains(charText)) {
					worldpopulationlist.add(wp);
				}
			}
		}
		notifyDataSetChanged();
	}
}

In this custom listview adapter class, string arrays are passed into the ListViewAdapter and set into the TextViews and ImageViews followed by the positions. On listview item click will pass the string arrays and position to a new activity.

Next, create an XML graphical layout for your listview item. Go to res > layout > Right Click on layout > New > Android XML File

Name your new XML file listview_item.xml and paste the following code.

listview_item.xml

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

    <TextView
        android:id="@+id/ranklabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/ranklabel" />

    <TextView
        android:id="@+id/rank"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/ranklabel" />

    <TextView
        android:id="@+id/countrylabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ranklabel"
        android:text="@string/countrylabel" />

    <TextView
        android:id="@+id/country"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/rank"
        android:layout_toRightOf="@+id/countrylabel" />

    <TextView
        android:id="@+id/populationlabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/countrylabel"
        android:text="@string/populationlabel" />

    <TextView
        android:id="@+id/population"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/country"
        android:layout_toRightOf="@+id/populationlabel" />

    <ImageView
        android:id="@+id/flag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:background="#000000"
        android:padding="1dp" />

</RelativeLayout>

Output:

SearchXMLParse XML Item

Next, create an imageloader class. Go to File > New > Class and name it ImageLoader.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your ImageLoader.java and paste the following code.

ImageLoader.java

package com.androidbegin.searchxmlparse;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.os.Handler;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageView;

public class ImageLoader {

	MemoryCache memoryCache = new MemoryCache();
	FileCache fileCache;
	private Map<ImageView, String> imageViews = Collections
			.synchronizedMap(new WeakHashMap<ImageView, String>());
	ExecutorService executorService;
	// Handler to display images in UI thread
	Handler handler = new Handler();

	public ImageLoader(Context context) {
		fileCache = new FileCache(context);
		executorService = Executors.newFixedThreadPool(5);
	}

	final int stub_id = R.drawable.temp_img;

	public void DisplayImage(String url, ImageView imageView) {
		imageViews.put(imageView, url);
		Bitmap bitmap = memoryCache.get(url);
		if (bitmap != null)
			imageView.setImageBitmap(bitmap);
		else {
			queuePhoto(url, imageView);
			imageView.setImageResource(stub_id);
		}
	}

	private void queuePhoto(String url, ImageView imageView) {
		PhotoToLoad p = new PhotoToLoad(url, imageView);
		executorService.submit(new PhotosLoader(p));
	}

	private Bitmap getBitmap(String url) {
		File f = fileCache.getFile(url);

		Bitmap b = decodeFile(f);
		if (b != null)
			return b;

		// Download Images from the Internet
		try {
			Bitmap bitmap = null;
			URL imageUrl = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) imageUrl
					.openConnection();
			conn.setConnectTimeout(30000);
			conn.setReadTimeout(30000);
			conn.setInstanceFollowRedirects(true);
			InputStream is = conn.getInputStream();
			OutputStream os = new FileOutputStream(f);
			Utils.CopyStream(is, os);
			os.close();
			conn.disconnect();
			bitmap = decodeFile(f);
			return bitmap;
		} catch (Throwable ex) {
			ex.printStackTrace();
			if (ex instanceof OutOfMemoryError)
				memoryCache.clear();
			return null;
		}
	}

	// Decodes image and scales it to reduce memory consumption
	private Bitmap decodeFile(File f) {
		try {
			// Decode image size
			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inJustDecodeBounds = true;
			FileInputStream stream1 = new FileInputStream(f);
			BitmapFactory.decodeStream(stream1, null, o);
			stream1.close();

			// Find the correct scale value. It should be the power of 2.
			final int REQUIRED_SIZE = 70;
			int width_tmp = o.outWidth, height_tmp = o.outHeight;
			int scale = 1;
			while (true) {
				if (width_tmp / 2 < REQUIRED_SIZE
						|| height_tmp / 2 < REQUIRED_SIZE)
					break;
				width_tmp /= 2;
				height_tmp /= 2;
				scale *= 2;
			}

			// Decode with inSampleSize
			BitmapFactory.Options o2 = new BitmapFactory.Options();
			o2.inSampleSize = scale;
			FileInputStream stream2 = new FileInputStream(f);
			Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
			stream2.close();
			return bitmap;
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	// Task for the queue
	private class PhotoToLoad {
		public String url;
		public ImageView imageView;

		public PhotoToLoad(String u, ImageView i) {
			url = u;
			imageView = i;
		}
	}

	class PhotosLoader implements Runnable {
		PhotoToLoad photoToLoad;

		PhotosLoader(PhotoToLoad photoToLoad) {
			this.photoToLoad = photoToLoad;
		}

		@Override
		public void run() {
			try {
				if (imageViewReused(photoToLoad))
					return;
				Bitmap bmp = getBitmap(photoToLoad.url);
				memoryCache.put(photoToLoad.url, bmp);
				if (imageViewReused(photoToLoad))
					return;
				BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
				handler.post(bd);
			} catch (Throwable th) {
				th.printStackTrace();
			}
		}
	}

	boolean imageViewReused(PhotoToLoad photoToLoad) {
		String tag = imageViews.get(photoToLoad.imageView);
		if (tag == null || !tag.equals(photoToLoad.url))
			return true;
		return false;
	}

	// Used to display bitmap in the UI thread
	class BitmapDisplayer implements Runnable {
		Bitmap bitmap;
		PhotoToLoad photoToLoad;

		public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
			bitmap = b;
			photoToLoad = p;
		}

		public void run() {
			if (imageViewReused(photoToLoad))
				return;
			if (bitmap != null)
				photoToLoad.imageView.setImageBitmap(bitmap);
			else
				photoToLoad.imageView.setImageResource(stub_id);
		}
	}

	public void clearCache() {
		memoryCache.clear();
		fileCache.clear();
	}

}

An imageloader is class that helps you download, display and cache images. By using an imageloader, images will be unloaded automatically if the device memory is low and it makes sure that the images are sized appropriately, and cached in the memory. Insert a temporary image for the imageloader to display when an image is unavailable or its still loading. For this tutorial, we have prepared a sample temporary image. Insert your downloaded sample image into your res drawable-hdpi.

Temporary Image

[wpfilebase tag=file id=85 tpl=download-button /]

Next, create a memory cache class. Go to File > New > Class and name it MemoryCache.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your MemoryCache.java and paste the following code.

MemoryCache.java

package com.androidbegin.searchxmlparse;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import android.graphics.Bitmap;
import android.util.Log;

public class MemoryCache {

	private static final String TAG = "MemoryCache";

	// Last argument true for LRU ordering
	private Map<String, Bitmap> cache = Collections
			.synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));

	// Current allocated size
	private long size = 0;

	// Max memory in bytes
	private long limit = 1000000;

	public MemoryCache() {
		// Use 25% of available heap size
		setLimit(Runtime.getRuntime().maxMemory() / 4);
	}

	public void setLimit(long new_limit) {
		limit = new_limit;
		Log.i(TAG, "MemoryCache will use up to " + limit / 1024. / 1024. + "MB");
	}

	public Bitmap get(String id) {
		try {
			if (!cache.containsKey(id))
				return null;
			return cache.get(id);
		} catch (NullPointerException ex) {
			ex.printStackTrace();
			return null;
		}
	}

	public void put(String id, Bitmap bitmap) {
		try {
			if (cache.containsKey(id))
				size -= getSizeInBytes(cache.get(id));
			cache.put(id, bitmap);
			size += getSizeInBytes(bitmap);
			checkSize();
		} catch (Throwable th) {
			th.printStackTrace();
		}
	}

	private void checkSize() {
		Log.i(TAG, "cache size=" + size + " length=" + cache.size());
		if (size > limit) {
			// Least recently accessed item will be the first one iterated
			Iterator<Entry<String, Bitmap>> iter = cache.entrySet().iterator();
			while (iter.hasNext()) {
				Entry<String, Bitmap> entry = iter.next();
				size -= getSizeInBytes(entry.getValue());
				iter.remove();
				if (size <= limit)
					break;
			}
			Log.i(TAG, "Clean cache. New size " + cache.size());
		}
	}

	public void clear() {
		try {
			cache.clear();
			size = 0;
		} catch (NullPointerException ex) {
			ex.printStackTrace();
		}
	}

	long getSizeInBytes(Bitmap bitmap) {
		if (bitmap == null)
			return 0;
		return bitmap.getRowBytes() * bitmap.getHeight();
	}
}

This memory cache class will limit the memory usage when loading images. Which means, the images will be removed if not shown within the content view.

Next, create a file cache class. Go to File > New > Class and name it FileCache.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your FileCache.java and paste the following code.

FileCache.java

package com.androidbegin.searchxmlparse;

import java.io.File;
import android.content.Context;

public class FileCache {

	private File cacheDir;

	public FileCache(Context context) {
		// Find the dir to save cached images
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED))
			cacheDir = new File(
					android.os.Environment.getExternalStorageDirectory(),
					"SearchXMLParseTutorialCache");
		else
			cacheDir = context.getCacheDir();
		if (!cacheDir.exists())
			cacheDir.mkdirs();
	}

	public File getFile(String url) {
		String filename = String.valueOf(url.hashCode());
		// String filename = URLEncoder.encode(url);
		File f = new File(cacheDir, filename);
		return f;

	}

	public void clear() {
		File[] files = cacheDir.listFiles();
		if (files == null)
			return;
		for (File f : files)
			f.delete();
	}

}

This file cache class saves temporary images into the device internal storage to prevent the images to be downloaded repeatedly.

Next, create an utility class. Go to File > New > Class and name it Utils.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your Utils.java and paste the following code.

Utils.java

package com.androidbegin.searchxmlparse;
import java.io.InputStream;
import java.io.OutputStream;

public class Utils {
    public static void CopyStream(InputStream is, OutputStream os)
    {
        final int buffer_size=1024;
        try
        {
            byte[] bytes=new byte[buffer_size];
            for(;;)
            {
              int count=is.read(bytes, 0, buffer_size);
              if(count==-1)
                  break;
              os.write(bytes, 0, count);
            }
        }
        catch(Exception ex){}
    }
}

Next, create an activity to display results. Go to File > New > Class and name it SingleItemView.java. Select your package named com.androidbegin.searchxmlparse and click Finish.

Open your SingleItemView.java and paste the following code.

SingleItemView.java

package com.androidbegin.searchxmlparse;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

public class SingleItemView extends Activity {
    // Declare Variables
    String rank;
    String country;
    String population;
    String flag;
    String position;
    ImageLoader imageLoader = new ImageLoader(this);

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Get the view from singleitemview.xml
        setContentView(R.layout.singleitemview);

        Intent i = getIntent();
        // Get the result of rank
        rank = i.getStringExtra("rank");
        // Get the result of country
        country = i.getStringExtra("country");
        // Get the result of population
        population = i.getStringExtra("population");
        // Get the result of flag
        flag = i.getStringExtra("flag");

        // Locate the TextViews in singleitemview.xml
        TextView txtrank = (TextView) findViewById(R.id.rank);
        TextView txtcountry = (TextView) findViewById(R.id.country);
        TextView txtpopulation = (TextView) findViewById(R.id.population);

        // Locate the ImageView in singleitemview.xml
        ImageView imgflag = (ImageView) findViewById(R.id.flag);

        // Set results to the TextViews
        txtrank.setText(rank);
        txtcountry.setText(country);
        txtpopulation.setText(population);

        // Capture position and set results to the ImageView
        // Passes flag images URL into ImageLoader.class
        imageLoader.DisplayImage(flag, imgflag);
    }
}

In this activity, strings are retrieved from the ListViewAdapter by using Intent and sets into the TextViews and pass an image URL into ImageLoader class to load images into the ImageView.

Next, create an XML graphical layout for your SingleItemView. Go to res > layout > Right Click on layout > New > Android XML File

Name your new XML file singleitemview.xml and paste the following code.

singleitemview.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <TextView
        android:id="@+id/ranklabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/ranklabel" />

    <TextView
        android:id="@+id/rank"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/ranklabel" />

    <TextView
        android:id="@+id/countrylabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/ranklabel"
        android:text="@string/countrylabel" />

    <TextView
        android:id="@+id/country"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/rank"
        android:layout_toRightOf="@+id/countrylabel" />

    <TextView
        android:id="@+id/populationlabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/countrylabel"
        android:text="@string/populationlabel" />

    <TextView
        android:id="@+id/population"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/country"
        android:layout_toRightOf="@+id/populationlabel" />

     <ImageView
        android:id="@+id/flag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:background="#000000"
        android:padding="1dp" />

</RelativeLayout>

Output:

SearchXMLParse XML Item

Next, change the application name and texts. Open your strings.xml in your res > values folder and paste the following code.

strings.xml

<resources>

    <string name="app_name">Search XML Parse</string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">Search XML Parse</string>
    <string name="ranklabel">"Rank : "</string>
    <string name="countrylabel">"Country : "</string>
    <string name="populationlabel">"Population : "</string>

</resources>

In your AndroidManifest.xml, we need to declare permissions to allow the application to write an external storage and connect to the Internet. Open your AndroidManifest.xml and paste the following code.

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidbegin.searchxmlparse"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SingleItemView" >
        </activity>
    </application>

</manifest>

Output:

SearchXMLParse ScreenShot

Source Code  

[purchase_link id=”7971″ text=”Purchase to Download Source Code” style=”button” color=”green”]

Latest comments

yeah.. i have an idea.. we can download xml from url.. in card... then mobile app lauch list.. but no idea.. how it implements.. sorry.. plzz anyone help

Shivshambhu Gupta

Android Search Filter XML Parse Images and Texts Tutorial

can i import xml file inside my project liske assests folder i want it to work with out access to internet i used this method but it give me error String xml = parser.getXmlFromUrl("file:///android_asset/xmlparseimgtxt.xml");

Eyad Barham

Android Search Filter XML Parse Images and Texts Tutorial

hello, is there a way to look not only for the name? give an example if I want to do a search for the number of the population?

Antonio Femiano

Android Search Filter XML Parse Images and Texts Tutorial

i implememented oncliklistener for the list views by using (if position==0)method to move to a new activity when i click on the first list item. but when i search for a different country, the activities change position, eg the the first list item is always goes to the first activity, neeed help

Aiden Apeyusi

Android Search Filter XML Parse Images and Texts Tutorial