This tutorial is about implementing multilevel listviews in your project. I explained by talking an example of music albums where listviews are displayed for list of albums, list of songs under an album.

Download Code

The first screen will be displayed with list of albums in ListView and the second screen will be displayed with list of songs under an album. Third screen will be displayed with a single song information.

JSON used in this project

I created following sample json files for this project.

> https://api.androidhive.info/songs/albums.php – gives you list of albums

> https://api.androidhive.info/songs/album_tracks.php?id=1 – will give your list of songs under album id = 1. You should pass parameter id as GET parameter. (The id of an album can be fetched from the previous url)

> https://api.androidhive.info/songs/track.php?album=3&song=1 – gives you single song information. album and song ids should be posted as GET parameters

I generated sample json using PHP. You can get php project files along with source code of this project.

Creating new Project

1. Create a new project in your Eclipse IDE by navigating to File ⇒ New ⇒ Android Application Project and fill the required details. Name your main activity as AlbumsActivity.java

2. Create a new package for placing helpers classes. You can create new package by right clicking on project src folder new -> package and naming it as your_package.helper (replace your_package with your actual package name)

3. As our application is connecting to internet, add the required permission in your AndroidManifest.xml file. Also i am adding two more class files (TrackListActivity, SingleTrackActivity) in manifest file.

INTERNET – Required to use internet services
ACCESS_NETWORK_STATE – Required to detect internet connection status

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidhive"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AlbumsActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity android:name=".TrackListActivity" />
        
        <activity android:name=".SingleTrackActivity" />
    </application>
    
    <!-- Permission - Internet Connect -->
    <uses-permission android:name="android.permission.INTERNET" />
 
    <!-- Network State Permissions -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

</manifest>

4. Create a new class file named AlertDialogManager.java under your helper package and paste the following code. This file used to show alert dialog in the application.

package com.example.androidhive.helper;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;

import com.example.androidhive.R;

public class AlertDialogManager {
	/**
	 * Function to display simple Alert Dialog
	 * @param context - application context
	 * @param title - alert dialog title
	 * @param message - alert message
	 * @param status - success/failure (used to set icon)
	 * 				 - pass null if you don't want icon
	 * */
	public void showAlertDialog(Context context, String title, String message,
			Boolean status) {
		AlertDialog alertDialog = new AlertDialog.Builder(context).create();

		// Setting Dialog Title
		alertDialog.setTitle(title);

		// Setting Dialog Message
		alertDialog.setMessage(message);

		if(status != null)
			// Setting alert dialog icon
			alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);

		// Setting OK Button
		alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
			}
		});

		// Showing Alert Message
		alertDialog.show();
	}
}

5. Create a new file under helper package named ConnectionDetector.java an paste the following code. This file used to detect internet connection.

package com.example.androidhive.helper;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
 
public class ConnectionDetector {
 
    private Context _context;
 
    public ConnectionDetector(Context context){
        this._context = context;
    }
 
    /**
     * Checking for all possible internet providers
     * **/
    public boolean isConnectingToInternet(){
        ConnectivityManager connectivity = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
          if (connectivity != null)
          {
              NetworkInfo[] info = connectivity.getAllNetworkInfo();
              if (info != null)
                  for (int i = 0; i < info.length; i++)
                      if (info[i].getState() == NetworkInfo.State.CONNECTED)
                      {
                          return true;
                      }
 
          }
          return false;
    }
}

6. Create a new file called JSONParser.java and paste the following code. This class file used to get json data by making http request. (Please note that this class file only fetches the json from http, it won’t parse the json)

package com.example.androidhive.helper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
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.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;

import android.util.Log;

public class JSONParser {

	static InputStream is = null;
	static JSONObject jObj = null;
	static String json = "";

	// constructor
	public JSONParser() {

	}

	// function get json from url
	// by making HTTP POST or GET mehtod
	public String makeHttpRequest(String url, String method,
			List<NameValuePair> params) {

		// Making HTTP request
		try {

			// check for request method
			if (method == "POST") {
				// request method is POST
				// defaultHttpClient
				DefaultHttpClient httpClient = new DefaultHttpClient();
				HttpPost httpPost = new HttpPost(url);
				httpPost.setEntity(new UrlEncodedFormEntity(params));

				HttpResponse httpResponse = httpClient.execute(httpPost);
				HttpEntity httpEntity = httpResponse.getEntity();
				is = httpEntity.getContent();

			} else if (method == "GET") {
				// request method is GET
				DefaultHttpClient httpClient = new DefaultHttpClient();
				String paramString = URLEncodedUtils.format(params, "utf-8");
				url += "?" + paramString;
				HttpGet httpGet = new HttpGet(url);

				HttpResponse httpResponse = httpClient.execute(httpGet);
				HttpEntity httpEntity = httpResponse.getEntity();
				is = httpEntity.getContent();
			}

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

		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					is, "iso-8859-1"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			json = sb.toString();
		} catch (Exception e) {
			Log.e("Buffer Error", "Error converting result " + e.toString());
		}

		// return JSON String
		return json;

	}
}

First Level ListView

7. Create new xml file under res / layout folder and name it as albums_activity.xml (or rename you existing unused main activity xml file)

8. Open your albums_activity.xml and create a list view.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#ffffff">

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    	android:divider="#b5b5b5"
        android:dividerHeight="1dp"
        android:cacheColorHint="#00000000"/>

</LinearLayout>

9. Now create a xml file named list_item_albums.xml for single album listview item and paste the following code. The following list item has album name and songs count of an album.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
 
    <!-- Album id / Hidden by default -->
    <TextView
        android:id="@+id/album_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />
    
    <!-- Album Name -->
    <TextView
        android:id="@+id/album_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="16dip"
        android:textColor="#000000"
        android:paddingTop="15dip"
        android:paddingBottom="15dip"
        android:paddingLeft="10dip"
        android:textStyle="bold"/>
 
    <!-- Album Songs count -->
    <TextView android:id="@+id/songs_count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:textColor="#ffffff"
        android:textStyle="bold"
        android:background="#9ed321"
        android:paddingRight="3dip"
        android:paddingLeft="3dip"/>
    
 
</RelativeLayout>

10. Extend your AlbumsActivity.java file from ListActivity and add the required variables and class instances.

public class AlbumsActivity extends ListActivity {
public class AlbumsActivity extends ListActivity {
	// Connection detector
	ConnectionDetector cd;
	
	// Alert dialog manager
	AlertDialogManager alert = new AlertDialogManager();
	
	// Progress Dialog
	private ProgressDialog pDialog;

	// Creating JSON Parser object
	JSONParser jsonParser = new JSONParser();

	ArrayList<HashMap<String, String>> albumsList;

	// albums JSONArray
	JSONArray albums = null;

	// albums JSON url
	private static final String URL_ALBUMS = "https://api.androidhive.info/songs/albums.php";

	// ALL JSON node names
	private static final String TAG_ID = "id";
	private static final String TAG_NAME = "name";
	private static final String TAG_SONGS_COUNT = "songs_count";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_albums);
		
		cd = new ConnectionDetector(getApplicationContext());
		 
        // Check for internet connection
        if (!cd.isConnectingToInternet()) {
            // Internet Connection is not present
            alert.showAlertDialog(AlbumsActivity.this, "Internet Connection Error",
                    "Please connect to working Internet connection", false);
            // stop executing code by return
            return;
        }

		// Hashmap for ListView
		albumsList = new ArrayList<HashMap<String, String>>();

11. Now i am adding a new Async background thread to get the albums json by making HTTP request. Once getting json is done, I parsed and displayed the json data in lisview.

Also on selecting a single list item (album) i am launching TrackListActivity.class by passing album id to it. Using album id in TrackListActivity.class i will fetch complete songs list.

Following is the complete code for AlbumsActivity.java file

package com.example.androidhive;

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

import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import com.example.androidhive.helper.AlertDialogManager;
import com.example.androidhive.helper.ConnectionDetector;
import com.example.androidhive.helper.JSONParser;

public class AlbumsActivity extends ListActivity {
	// Connection detector
	ConnectionDetector cd;
	
	// Alert dialog manager
	AlertDialogManager alert = new AlertDialogManager();
	
	// Progress Dialog
	private ProgressDialog pDialog;

	// Creating JSON Parser object
	JSONParser jsonParser = new JSONParser();

	ArrayList<HashMap<String, String>> albumsList;

	// albums JSONArray
	JSONArray albums = null;

	// albums JSON url
	private static final String URL_ALBUMS = "https://api.androidhive.info/songs/albums.php";

	// ALL JSON node names
	private static final String TAG_ID = "id";
	private static final String TAG_NAME = "name";
	private static final String TAG_SONGS_COUNT = "songs_count";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_albums);
		
		cd = new ConnectionDetector(getApplicationContext());
		 
        // Check for internet connection
        if (!cd.isConnectingToInternet()) {
            // Internet Connection is not present
            alert.showAlertDialog(AlbumsActivity.this, "Internet Connection Error",
                    "Please connect to working Internet connection", false);
            // stop executing code by return
            return;
        }

		// Hashmap for ListView
		albumsList = new ArrayList<HashMap<String, String>>();

		// Loading Albums JSON in Background Thread
		new LoadAlbums().execute();
		
		// get listview
		ListView lv = getListView();
		
		/**
		 * Listview item click listener
		 * TrackListActivity will be lauched by passing album id
		 * */
		lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> arg0, View view, int arg2,
					long arg3) {
				// on selecting a single album
				// TrackListActivity will be launched to show tracks inside the album
				Intent i = new Intent(getApplicationContext(), TrackListActivity.class);
				
				// send album id to tracklist activity to get list of songs under that album
				String album_id = ((TextView) view.findViewById(R.id.album_id)).getText().toString();
				i.putExtra("album_id", album_id);				
				
				startActivity(i);
			}
		});		
	}

	/**
	 * Background Async Task to Load all Albums by making http request
	 * */
	class LoadAlbums extends AsyncTask<String, String, String> {

		/**
		 * Before starting background thread Show Progress Dialog
		 * */
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			pDialog = new ProgressDialog(AlbumsActivity.this);
			pDialog.setMessage("Listing Albums ...");
			pDialog.setIndeterminate(false);
			pDialog.setCancelable(false);
			pDialog.show();
		}

		/**
		 * getting Albums JSON
		 * */
		protected String doInBackground(String... args) {
			// Building Parameters
			List<NameValuePair> params = new ArrayList<NameValuePair>();

			// getting JSON string from URL
			String json = jsonParser.makeHttpRequest(URL_ALBUMS, "GET",
					params);

			// Check your log cat for JSON reponse
			Log.d("Albums JSON: ", "> " + json);

			try {				
				albums = new JSONArray(json);
				
				if (albums != null) {
					// looping through All albums
					for (int i = 0; i < albums.length(); i++) {
						JSONObject c = albums.getJSONObject(i);

						// Storing each json item values in variable
						String id = c.getString(TAG_ID);
						String name = c.getString(TAG_NAME);
						String songs_count = c.getString(TAG_SONGS_COUNT);

						// creating new HashMap
						HashMap<String, String> map = new HashMap<String, String>();

						// adding each child node to HashMap key => value
						map.put(TAG_ID, id);
						map.put(TAG_NAME, name);
						map.put(TAG_SONGS_COUNT, songs_count);

						// adding HashList to ArrayList
						albumsList.add(map);
					}
				}else{
					Log.d("Albums: ", "null");
				}

			} catch (JSONException e) {
				e.printStackTrace();
			}

			return null;
		}

		/**
		 * After completing background task Dismiss the progress dialog
		 * **/
		protected void onPostExecute(String file_url) {
			// dismiss the dialog after getting all albums
			pDialog.dismiss();
			// updating UI from Background Thread
			runOnUiThread(new Runnable() {
				public void run() {
					/**
					 * Updating parsed JSON data into ListView
					 * */
					ListAdapter adapter = new SimpleAdapter(
							AlbumsActivity.this, albumsList,
							R.layout.list_item_albums, new String[] { TAG_ID,
									TAG_NAME, TAG_SONGS_COUNT }, new int[] {
									R.id.album_id, R.id.album_name, R.id.songs_count });
					
					// updating listview
					setListAdapter(adapter);
				}
			});

		}

	}
}

And the output for the above listview

android multilevel listiview

Second Level ListView

12. Now create a new class file called TrackListActivity.java and extend it from ListActivity.

public class TrackListActivity extends ListActivity {

13. Create a xml file for TrackListActivity.java and create a listview in it. Name your xml file as activity_tracks.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="#ffffff">

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
    	android:divider="#b5b5b5"
        android:dividerHeight="1dp"
        android:cacheColorHint="#00000000"/>

</LinearLayout>

14. Also create a xml file named list_item_tracks.xml for single list item and type the following code. In the following code each list item has song title and the duration of the song.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <!-- Album id / Hidden by default -->
    <TextView
        android:id="@+id/album_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />

    <!-- Song id / Hidden by default -->
    <TextView
        android:id="@+id/song_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />
    
    <!-- Track serial no -->
    <TextView
        android:id="@+id/track_no"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="15dip"
        android:paddingLeft="5dip"
        android:paddingTop="15dip"
        android:textColor="#000000"
        android:textSize="16dip"
        android:layout_alignParentLeft="true"/>

    <!-- Song Name -->
    <TextView
        android:id="@+id/album_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="15dip"
        android:paddingLeft="5dip"
        android:paddingTop="15dip"
        android:textColor="#000000"
        android:textSize="16dip"
        android:layout_toRightOf="@+id/track_no"/>

    <!-- Song duration -->
    <TextView
        android:id="@+id/song_duration"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:paddingLeft="3dip"
        android:paddingRight="6dip"
        android:textColor="#9ed321" />

</RelativeLayout>

15. Open your TrackListActivity.java and add the following code. In the following code

> First i am receiving album id from the previous activity (which is AlbumsActivity.java)
> I am calling a new async background thread called LoadTracks().execute() which will send http request and get songs list under an album (using album id)
> Once the data is received i parsed it and displayed in listiview.
> Also on selecting a single list item (song) i am launching a new activity named SingleTrackActivity.java by passing album id and song id to it.

package com.example.androidhive;

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

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.example.androidhive.helper.AlertDialogManager;
import com.example.androidhive.helper.ConnectionDetector;
import com.example.androidhive.helper.JSONParser;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class TrackListActivity extends ListActivity {
	// Connection detector
	ConnectionDetector cd;
	
	// Alert dialog manager
	AlertDialogManager alert = new AlertDialogManager();
	
	// Progress Dialog
	private ProgressDialog pDialog;

	// Creating JSON Parser object
	JSONParser jsonParser = new JSONParser();

	ArrayList<HashMap<String, String>> tracksList;

	// tracks JSONArray
	JSONArray albums = null;
	
	// Album id
	String album_id, album_name;

	// tracks JSON url
	// id - should be posted as GET params to get track list (ex: id = 5)
	private static final String URL_ALBUMS = "https://api.androidhive.info/songs/album_tracks.php";

	// ALL JSON node names
	private static final String TAG_SONGS = "songs";
	private static final String TAG_ID = "id";
	private static final String TAG_NAME = "name";
	private static final String TAG_ALBUM = "album";
	private static final String TAG_DURATION = "duration";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_tracks);
		
		cd = new ConnectionDetector(getApplicationContext());
		 
        // Check if Internet present
        if (!cd.isConnectingToInternet()) {
            // Internet Connection is not present
            alert.showAlertDialog(TrackListActivity.this, "Internet Connection Error",
                    "Please connect to working Internet connection", false);
            // stop executing code by return
            return;
        }
        
        // Get album id
        Intent i = getIntent();
        album_id = i.getStringExtra("album_id");

		// Hashmap for ListView
		tracksList = new ArrayList<HashMap<String, String>>();

		// Loading tracks in Background Thread
		new LoadTracks().execute();
		
		// get listview
		ListView lv = getListView();
		
		/**
		 * Listview on item click listener
		 * SingleTrackActivity will be lauched by passing album id, song id
		 * */
		lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> arg0, View view, int arg2,
					long arg3) {
				// On selecting single track get song information
				Intent i = new Intent(getApplicationContext(), SingleTrackActivity.class);
				
				// to get song information
				// both album id and song is needed
				String album_id = ((TextView) view.findViewById(R.id.album_id)).getText().toString();
				String song_id = ((TextView) view.findViewById(R.id.song_id)).getText().toString();
				
				Toast.makeText(getApplicationContext(), "Album Id: " + album_id  + ", Song Id: " + song_id, Toast.LENGTH_SHORT).show();
				
				i.putExtra("album_id", album_id);
				i.putExtra("song_id", song_id);
				
				startActivity(i);
			}
		});	

	}

	/**
	 * Background Async Task to Load all tracks under one album
	 * */
	class LoadTracks extends AsyncTask<String, String, String> {

		/**
		 * Before starting background thread Show Progress Dialog
		 * */
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			pDialog = new ProgressDialog(TrackListActivity.this);
			pDialog.setMessage("Loading songs ...");
			pDialog.setIndeterminate(false);
			pDialog.setCancelable(false);
			pDialog.show();
		}

		/**
		 * getting tracks json and parsing
		 * */
		protected String doInBackground(String... args) {
			// Building Parameters
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			
			// post album id as GET parameter
			params.add(new BasicNameValuePair(TAG_ID, album_id));

			// getting JSON string from URL
			String json = jsonParser.makeHttpRequest(URL_ALBUMS, "GET",
					params);

			// Check your log cat for JSON reponse
			Log.d("Track List JSON: ", json);

			try {
				JSONObject jObj = new JSONObject(json);
				if (jObj != null) {
					String album_id = jObj.getString(TAG_ID);
					album_name = jObj.getString(TAG_ALBUM);
					albums = jObj.getJSONArray(TAG_SONGS);

					if (albums != null) {
						// looping through All songs
						for (int i = 0; i < albums.length(); i++) {
							JSONObject c = albums.getJSONObject(i);

							// Storing each json item in variable
							String song_id = c.getString(TAG_ID);
							// track no - increment i value
							String track_no = String.valueOf(i + 1);
							String name = c.getString(TAG_NAME);
							String duration = c.getString(TAG_DURATION);

							// creating new HashMap
							HashMap<String, String> map = new HashMap<String, String>();

							// adding each child node to HashMap key => value
							map.put("album_id", album_id);
							map.put(TAG_ID, song_id);
							map.put("track_no", track_no + ".");
							map.put(TAG_NAME, name);
							map.put(TAG_DURATION, duration);

							// adding HashList to ArrayList
							tracksList.add(map);
						}
					} else {
						Log.d("Albums: ", "null");
					}
				}

			} catch (JSONException e) {
				e.printStackTrace();
			}

			return null;
		}

		/**
		 * After completing background task Dismiss the progress dialog
		 * **/
		protected void onPostExecute(String file_url) {
			// dismiss the dialog after getting all tracks
			pDialog.dismiss();
			// updating UI from Background Thread
			runOnUiThread(new Runnable() {
				public void run() {
					/**
					 * Updating parsed JSON data into ListView
					 * */
					ListAdapter adapter = new SimpleAdapter(
							TrackListActivity.this, tracksList,
							R.layout.list_item_tracks, new String[] { "album_id", TAG_ID, "track_no",
									TAG_NAME, TAG_DURATION }, new int[] {
									R.id.album_id, R.id.song_id, R.id.track_no, R.id.album_name, R.id.song_duration });
					// updating listview
					setListAdapter(adapter);
					
					// Change Activity Title with Album name
					setTitle(album_name);
				}
			});

		}

	}
}
android multilevel listview two

Third Level View

16. Create a class file called SingleTrackActivity.java and an xml file called activity_single_track.xml

17. Open activity_single_track.xml file and paste the following code. In the following layout file i added TextViews for song title, album and duration.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffffff" >
    
    <!-- Song Title -->
    <TextView android:id="@+id/song_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="25dip"
        android:padding="10dip"
        android:textColor="#444444"
        android:textStyle="bold"/>
    
    <!-- Album Name -->
	<TextView android:id="@+id/album_name"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:paddingLeft="10dip"
	    android:textSize="15dip"
	    android:textColor="#000000"
	    android:paddingBottom="10dip"/>
	
	<!-- Song Duration -->
	<TextView android:id="@+id/duration"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:paddingLeft="10dip"
	    android:textSize="15dip"
	    android:textColor="#000000"
	    android:paddingBottom="10dip"/>
	
</LinearLayout>

18. Open SingleTrackActivity.java file and try following code. In the following code

> From the previous activity TracksListActivity.java, album id and song id is received
> a new asyc background thread LoadSingleTrack().execute() is called to get single song information. To get single song information album id and song id is posted as GET parameters.
> After fetching json from http, json data is parsed and displayed in view.

Complete code for SingleTrackActivity.java

package com.example.androidhive;

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

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.widget.TextView;

import com.example.androidhive.helper.AlertDialogManager;
import com.example.androidhive.helper.ConnectionDetector;
import com.example.androidhive.helper.JSONParser;

public class SingleTrackActivity extends Activity {
	// Connection detector
	ConnectionDetector cd;
	
	// Alert dialog manager
	AlertDialogManager alert = new AlertDialogManager();
	
	// Progress Dialog
	private ProgressDialog pDialog;

	// Creating JSON Parser object
	JSONParser jsonParser = new JSONParser();

	// tracks JSONArray
	JSONArray albums = null;
	
	// Album id
	String album_id = null;
	String song_id = null;
	
	String album_name, song_name, duration;

	// single song JSON url
	// GET parameters album, song
	private static final String URL_SONG = "https://api.androidhive.info/songs/track.php";

	// ALL JSON node names
	private static final String TAG_NAME = "name";
	private static final String TAG_DURATION = "duration";
	private static final String TAG_ALBUM = "album";
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_single_track);
		
		cd = new ConnectionDetector(getApplicationContext());
		 
        // Check if Internet present
        if (!cd.isConnectingToInternet()) {
            // Internet Connection is not present
            alert.showAlertDialog(SingleTrackActivity.this, "Internet Connection Error",
                    "Please connect to working Internet connection", false);
            // stop executing code by return
            return;
        }
        
        // Get album id, song id
        Intent i = getIntent();
        album_id = i.getStringExtra("album_id");
        song_id = i.getStringExtra("song_id");
        
        // calling background thread
        new LoadSingleTrack().execute();
	}
	
	/**
	 * Background Async Task to get single song information
	 * */
	class LoadSingleTrack extends AsyncTask<String, String, String> {

		/**
		 * Before starting background thread Show Progress Dialog
		 * */
		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			pDialog = new ProgressDialog(SingleTrackActivity.this);
			pDialog.setMessage("Loading song ...");
			pDialog.setIndeterminate(false);
			pDialog.setCancelable(false);
			pDialog.show();
		}

		/**
		 * getting song json and parsing
		 * */
		protected String doInBackground(String... args) {
			// Building Parameters
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			
			// post album id, song id as GET parameters
			params.add(new BasicNameValuePair("album", album_id));
			params.add(new BasicNameValuePair("song", song_id));

			// getting JSON string from URL
			String json = jsonParser.makeHttpRequest(URL_SONG, "GET",
					params);

			// Check your log cat for JSON reponse
			Log.d("Single Track JSON: ", json);

			try {
				JSONObject jObj = new JSONObject(json);
				if(jObj != null){
					song_name = jObj.getString(TAG_NAME);
					album_name = jObj.getString(TAG_ALBUM);
					duration = jObj.getString(TAG_DURATION);					
				}			

			} catch (JSONException e) {
				e.printStackTrace();
			}

			return null;
		}

		/**
		 * After completing background task Dismiss the progress dialog
		 * **/
		protected void onPostExecute(String file_url) {
			// dismiss the dialog after getting song information
			pDialog.dismiss();
			
			// updating UI from Background Thread
			runOnUiThread(new Runnable() {
				public void run() {
					
					TextView txt_song_name = (TextView) findViewById(R.id.song_title);
					TextView txt_album_name = (TextView) findViewById(R.id.album_name);
					TextView txt_duration = (TextView) findViewById(R.id.duration);
					
					// displaying song data in view
					txt_song_name.setText(song_name);
					txt_album_name.setText(Html.fromHtml("<b>Album:</b> " + album_name));
					txt_duration.setText(Html.fromHtml("<b>Duration:</b> " + duration));
					
					// Change Activity Title with Song title
					setTitle(song_name);
				}
			});

		}

	}
}
android multilevel listview three
This image is for thumbnail purpose
android multilevel listview tutorial
Subscribe
Notify of
guest
154 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Michael
Michael
9 years ago

Hi Ravi, excellent the tutorial thanks!

Can you consider create a tutorial/serie about design for Android? For example, how to create a nice design and configure the xml based on psd?

Thanks

Jitterydadav
Jitterydadav
8 years ago
Reply to  Michael

dgagdafg

Sur
Sur
9 years ago

Thanks for each and every tutorial you have posted. It has been so helpful.
Can you please post tutorial on generating notification depending upon the time stored on database.
Waiting for your Next Tutorial

Ram Sharan
Ram Sharan
9 years ago

Hi Ravi, Such a great post,
no words to say, and in simple words
“Stunning” biggest task you have made very easily for learners…Thanks a lot.

I need your help:-
for example: “imagepath” => “www.pizzahut.com.au/images/menu/Pizza-Lge-BBQ_Meatlovers.png” but i am not getting proper link in generated JSON, so please tell me how i need to write image url to fetch images using data.php

k
k
8 years ago
Reply to  Ram Sharan

remove the cots ” ” and put the url in database

deddy
deddy
9 years ago

Thanks for the tutorials and all the ideas.

Subhanivizag
Subhanivizag
9 years ago

Hi Ravi, I m following ur articles, they are very nice. Ravi can u please suggest me any UI designing tool for android, apart from droiddraw. I looking for rich UI interface designing tools.

Florian Froehlich
Florian Froehlich
9 years ago

Tnx Ravi,
can you please explain, how search and filter the entries in the list by an edittext?

Phamhoang2106
Phamhoang2106
9 years ago

fdfdfd

Farhan shah
Farhan shah
9 years ago

Thank You Very Much.Awsome Post..

Syam Kumar
9 years ago

Hi.. ravi,,, i am syamkumar new to android ,,, i want your help ,,, i want to connect to sqlite database in android ,,, can you pleae guide me how i can do ,

Med
Med
9 years ago

Thankyou very much. But i want a listview with an icon..and a event on it.. thankyou again ! 🙂

pravin
pravin
9 years ago

Ravi can You pls post the example of Multi-column listview (Like Table Formate) and Data come from php, json

Kumar
Kumar
9 years ago

Hi Ravi,

Lots of thank for your tutorials.
I m getting german characters Ä ü from XML. How can I display thses characters ? I have been searching to fix this problem but still didnt find any solution.

Thanks

Vasudevan M.R.
Vasudevan M.R.
9 years ago

Outstanding buddy. The code works, it’s easy to understand and it’s short.
Good show !!!

Dewa Surya
Dewa Surya
9 years ago

Bravo for all … great share. Great thanks.

James
James
9 years ago

Clean, detailed & commented.. Nice work

Terminartur
Terminartur
9 years ago

Hi! Could you please make an example how to setup MySQL and get JSON from it for this project.

Akhil Soni
Akhil Soni
9 years ago

hi Ravi,
i am waiting for your new Tutorial .

chandu
chandu
9 years ago

hi Ravi
post any tutorials about creating live wallpapers

Bogaga
Bogaga
8 years ago

Salam brother

Thank you very much for these tutoriels, you helped me very well

Thank you again

from Morocco

Gauri
Gauri
8 years ago

give me the same tutorial with xml web service plz

Gauri
Gauri
8 years ago
Reply to  Gauri

plz soon

sebastien
sebastien
8 years ago
Ankit Saini
Ankit Saini
8 years ago

It’s a very helpful link.

Thanks
Ankit

Gramugade
Gramugade
8 years ago

hey your code is great but its not working properly the albums are not loaded jst the album layout file is display nw what to do?????

Ali Madan
Ali Madan
8 years ago

thanks for this great example, but I have a problem
I want to parse Arabic characters, so when I change album name to Arabic, I got “null” in the list of albums

Ali Madan
Ali Madan
8 years ago
Reply to  Ali Madan

I fixed this problem, but now once I change the album name, i got a blank page on android

Ali Madan
Ali Madan
8 years ago
Reply to  Ali Madan

i mean any change i make in the data.php file gives me a blank page

Cesar
Cesar
7 years ago
Reply to  Ali Madan

did you fixed it ?? how did you use the phps for customising info thx

Karan
Karan
8 years ago

Hello Sir!
Please post an example on “Android – Multiple Screen Support”.

Arise Rayamangalam
8 years ago

Here is a another simple tutorial of ListView for displaying ListView with Local (custom font) Language and multiple color (with source code)
http://android-helper4u.blogspot.com/2013/02/b-how-make-listview-in-android-that.html

Shinigami
Shinigami
8 years ago

thx for this tutorial….
i’m just a beginner and i got error @ jsonParser.makeHttpRequest….
can anyone help me???
T_T

Sanjaypandey00777
Sanjaypandey00777
8 years ago

Thanks Ravi for this wonderful tutorial . May I know if you have used MySql database in this project??

Codereborn
Codereborn
8 years ago

Hi Ravi
you have post superb tutorial which help me a lot to develop my first android app. Now i have to develop app for IPhone and i am developing this first time. So can anyone suggest some good site like (androidhive) that help me to develop IPhone App.
Thanks.

Sanjaypandey00777
Sanjaypandey00777
8 years ago

Thanks Ravi . will you please help me?? where to save the php files in eclipse if I change the url to localhost ?? plz reply

Cesar
Cesar
7 years ago

we need help with this , were do we put the files please

Isla Aloha
Isla Aloha
8 years ago

Ravi,

Any chance you will show us how to interface with the internal sensors such as the multi-touch screen and the acceleronometer, compass, etc?

Bpron45
Bpron45
8 years ago

hello,
very good tutorial!
thanks!!

i have a problem tto make files with php

my php is like
0) {
// looping through all results
// products node
//$response[“products”] = array();

while ($row = mysql_fetch_array($result)) {
// temp user array
//$product = array();
$product[“id”] = $val_id;
$product[“name”] = $row[“titre”];
$product[“duration”] = $row[“zoomlevel”];

// push single product into final response array
// array_push( $product);
array_push($response,$product);
$val_id=$val_id+1;

}

$product2[“for test3”]=$response;

array_push($response2,$product2);

// success
// $response[“success”] = 1;

// echoing JSON response
echo json_encode($response2);

//echo json_encode($response);
} else {
// no products found
$response[“success”] = 0;
$response[“message”] = “No products found”;

// echo no users JSON
echo json_encode($response);
}
?>

and it return

[{“T1″:”12″,”T2″:”2″,”T4”:[{“id”:1,”name”:”Shipchandlers du reseau ACCASTILLAGE DIFFUSION”,”duration”:”6″},
……..
,{“id”:54,”name”:”Magasins Vogele Shoes en Suisse”,”duration”:”7″}]}]

i want to make it
{“id”:1,”album”:”127 Hours”,”songs”:[{“id”:1,”name”:”Never Hear Surf Music Again”,”duration”:”5:52″},
……….
,{“id”:14,”name”:”Nocturne No. 2 in E flat”,”duration”:”4:01″}]}

[{[{ }]}] no good
{…[{…}]} good

can you help me to make my php files for album track

thanks
Chris

shivabalaji
shivabalaji
8 years ago

nice

Kamran
Kamran
8 years ago

Hello Sir!
Please post an example on “Android – Multiple Screen Support”.

Roney
Roney
8 years ago

STEP BY STEP ANDROID TUTORIALS FROM VERY BEGINNING

VISIT

http://www.androidituts.com

Vafa
Vafa
8 years ago

Hello dear.
Please make a tutorial for download center (downloading files) in android from a webserver.

Vafa Sajad
Vafa Sajad
8 years ago

Hello.
What is the project for?

Eoin
Eoin
8 years ago

I can see the json in the log but cant get it on my app. I just get a blank screen. I get these errors. of type org.json.JSONObject cannot be converted to JSONArray

at org.json.JSON.typeMismatch(JSON.java:111)

03-20 19:06:26.401: W/System.err(4866): at org.json.JSONArray.(JSONArray.java:91)

03-20 19:06:26.416: W/System.err(4866): at org.json.JSONArray.(JSONArray.java:103)

03-20 19:06:26.416: W/System.err(4866): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)

03-20 19:06:26.416: W/System.err(4866): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)

03-20 19:06:26.421: W/System.err(4866): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)

03-20 19:06:26.421: W/System.err(4866): at java.lang.Thread.run(Thread.java:864)

Sur
Sur
8 years ago

Hi Ravi,
why don’t you keep a list of tutorial in home page so visitor can see directly th list of tutorial you have done

Nick M
Nick M
8 years ago

Just wanted to say thanks for all your great tutorials. From beginning to end they all build very well off one another. They have been a great help!

androidituts
8 years ago

ANDROID IS BECOMING BOOMING TO LEARN AND EARN IN THE WORLD

ITS EASY TO LEARN AND EARN

VISIT ANDROIDITUTS

http://www.androidituts.com

Jimmy Hill
Jimmy Hill
8 years ago

Great Tutorial and Superb Code…much useful, please also post some code to work with images as well…..

max
max
8 years ago

on:

alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);

im getting an error message:

Multiple markers at this line:
– fail cannot be resolved or is not a field
– success cannot be resolved or is not a field

mahdi
mahdi
8 years ago

hello sir!
I have problem :
on:

alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);

im getting an error message:

Multiple markers at this line:
– fail cannot be resolved or is not a field
– success cannot be resolved or is not a field

please help me and response to this address:

my email : [email protected]

The Voice Of Sikkim
8 years ago

ravi ji you are superb

Nick
Nick
8 years ago

Changing the url with same setup for php folders doesnot actviate albums activity…. puzzled!

Sameer
Sameer
8 years ago

This tutorial is Little bit disappointing, First wrongly name the concept here. Except this, i am admirer of your article. Look at better explanation of Expandable ListView in android. I need some good tutorial from you.

Sanjeev
Sanjeev
8 years ago

Wonderful Explanation..

sreenu vasu
sreenu vasu
8 years ago

Hi Friends anybody tell me i want to display the customer details code name this details when i click button it will go to next screen i will enter code and name after clicking the save Button this details will add to the code ,name in first activity

Martin
Martin
8 years ago

Thank you so much, you saved my so much time when I used many of your tutorials for my android application (Goal Do+)!

154
0
Would love your thoughts, please comment.x
()
x