Friday, April 15, 2011

Populating a ListView from external source on Android

Hello again,
There are many tutorials on how to create and manage ListView on Android, the difficulty here is whether you can find a method that will satisfy your needs.
Here is a tutorial on how to best create a ListView and customize it.

First, lets take a look on our Php script that will provide our data.
if (isset($_POST['JSON'])) {
    header('Content-Type: application/json; charset=iso-8859-1');
    $response = array(
        array('id' => '149', 'title' => 'Revolution',
            'artist' => 'Bob Marley', 'duration' => '271'),
        array('id' => '150', 'title' => 'Natural Mystic',
            'artist' => 'Bob Marley', 'duration' => '312'),
        array('id' => '151', 'title' => 'Redemption Song',
            'artist' => 'Bob Marley', 'duration' => '268'),
        array('id' => '152', 'title' => 'No More Trouble',
            'artist' => 'Bob Marley', 'duration' => '285'),
    );
    print_r(json_encode($response));
}
As you can see, we are going to get some tracks from our data source.
Now let's create our android application.
Here is the class that will hold one track, Track.java:
public class Track {
 private int id;
 private String title;
 private String artist;
 private int duration;

 public Track(int id, String title, String artist, int duration) {
  this.id = id;
  this.title = title;
  this.artist = artist;
  this.duration = duration;
 }
 /**
  * ... getters here
  */
}
- The layout for the listView in main.xml

    

- The layout for one row in the list view, this will give us more options to better customize our view, row.xml, the example here is from romain guy here

     
    
        
        
    

Now we are done with the view layout, let's put every thing together.
It is time to write our custom TrackAdapter that extends TrackAdapter
private class TrackAdapter extends ArrayAdapter {
        // a list that will store our tracks
 private List trackList;
 public LineAdapter(Context context, int textViewResourceId,
   List items) {
  super(context, textViewResourceId, items);
  this.trackList = items;
 }
        // this methode returns a single row from the list view
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  View v = convertView;
  if (v == null) {
   LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   v = vi.inflate(R.layout.row, null);
  }
  Track track = trackList.get(position);
  if (track != null) {
   TextView tt = (TextView) v.findViewById(R.id.toptext);
   TextView bt = (TextView) v.findViewById(R.id.bottomtext);
   if (tt != null) {
    tt.setText("Artist: " + track.getArtist());
   }
   if (bt != null) {
    bt.setText("Title: " + track.getTitle());
   }
  }
  return v;
 }
}
This is a private class and should be added under our MainActivity class.

Now, let's fetch the track list from our external source. I have already made a tutorial on how to get data using a Http post method in my previous blog here so we gonna use that except that we are not sending anything to the server. the doRequest methode wont have any parameters.
private List getTracks() {
 String response = Server.doRequest();
 JSONArray json;
 List trackList = new ArrayList();
 int id, duration;
 String title, artist;
 try {
  json = new JSONArray(response);
  for (int i = 0; i < json.length(); i++) {
   id = json.optJSONObject(i).getInt("id");
   duration = json.optJSONObject(i).getInt("duration");
   title = json.optJSONObject(i).getString("title");
   artist = json.optJSONObject(i).getString("artist");
   trackList.add(new Track(id, title, artist, duration));
  }
 } catch (JSONException e) {
  Log.e("Json", e.getMessage(), e.fillInStackTrace());
 }
 return trackList;
}
Finally, all we need to do is make some calls in the onCreate method
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    m_tracks = new ArrayList();
    m_tracks = getTracks();
    this.m_adapter = new TrackAdapter(this, R.layout.row, m_tracks);
    setListAdapter(this.m_adapter);
}
Also we can add ItemClickListner to the list and even more stuffs. For a more detailed tutorial you can check softwarepassion.com Feel free to leave your comments.

Wednesday, April 13, 2011

JSON via Http on Android

There are many ways to handle JSON data on android. Here is my way to do that.
In this tutorial, I am going to get external JSON data with some Http post request and response.

First, let's create the class that will handle the incoming and outgoing data.
public class HttpUtils {
 private static final String URL = "http://path/to/php/script.php";

 public static String doRequest(String username, String password) {
  HttpClient client = new DefaultHttpClient();
  HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
  JSONObject jsonObject = new JSONObject();
  HttpPost post;
  HttpResponse response;
  String responseStr = "[{}]";
  try {
   post = new HttpPost(URL);
   Log.i("Http", "Requesting " + URL);
   
   //Puting the username and password as JSON data
   jsonObject.put("username", username);
   jsonObject.put("password", password);
   StringEntity se = new StringEntity("JSON=" + jsonObject.toString());
   se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,"application/x-www-form-urlencoded"));
   post.setEntity(se);
   Log.i("Http", "Sending :" + slurp(post.getEntity().getContent()));
   response = client.execute(post);

   // Checking response
   if (response.getStatusLine().getStatusCode() == 200) {
    // Get the data in the entity
    InputStream in = response.getEntity().getContent();
    responseStr = slurp(in);
    Log.i("Http", "Getting :" + responseStr);
   } else {
    throw new HttpException("HttpMethod Returned Status Code: "
      + response.getStatusLine().getStatusCode()
      + " when attempting: " + URL);
   }
  } catch (Exception e) {
   Log.e("Http", e.getMessage(), e.fillInStackTrace());
  }

  return responseStr;
 }

 /**
  * Convert an InputStream to String
  * 
  * @param in the InputStream to be converted to String
  * @return the result string
  * @throws IOException
  */
 private static String slurp(InputStream in) throws IOException {
  StringBuffer out = new StringBuffer();
  byte[] b = new byte[4096];
  for (int n; (n = in.read(b)) != -1;) {
   out.append(new String(b, 0, n));
  }
  return out.toString();
 }
}
As you can see, we used a JSONObject to post some data to our php script witch look like this :
if (isset($_POST['JSON'])) {
    header('Content-Type: application/json; charset=iso-8859-1');
    $data = json_decode($_POST['JSON'], true);
    $username = $data['username'];
    $password = $data['password'];
    if ($username == 'ElWardi' && $password == 'json') {
        $response = array(
            array('success' => true),
            array('name' => 'PFA', 'description' => 'PFA test'),
            array('name' => 'PFA1', 'description' => 'PFA1 test'),
            array('name' => 'PFA2', 'description' => 'PFA2 test'),
            array('name' => 'PFA3', 'description' => 'PFA3 test'),
            array('name' => 'PFA4', 'description' => 'PFA4 test')
        );
    } else {
        $response = array(
            array('success' => false)
        );
    }
    print_r(json_encode($response));
}
[Update] : The php script will encode an array of data and send it back to the android application. The encoded data will look like this :
[{"success":true},
{"name":"PFA","description":"PFA test"},
{"name":"PFA1","description":"PFA1 test"},
{"name":"PFA2","description":"PFA2 test"},
{"name":"PFA3","description":"PFA3 test"},
{"name":"PFA4","description":"PFA4 test"}]
Now, all the rest to do is call the doRequest method then parse the response data. I made that in the MainActivity.java :
public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        String response = HttpUtils.doRequest("ElWardi", "json");
  JSONArray json;
  try {
   /*
    *  Build the JSAONArray from a string
    */
   json = new JSONArray(response);
   Log.i("JSON", "Number of data fetched : " + json.length()); // data count
   /*
    * get the data from the JSONArray if the authentifcation data are valid
    */
   if (json.optJSONObject(0).getBoolean("success")) {
    for (int i = 1; i < json.length(); i++) {
     Log.i("MyData", "Name : " + json.optJSONObject(i).getString("name")
       + "Description : " + json.optJSONObject(i).getString("description"));
    }
   }else 
    Log.e("MyData", "Some entered data (username or password) are invalid"); 
  } catch (JSONException e) {
   Log.e("JSON", e.getMessage(), e.fillInStackTrace());
  }
    }
}
You can see the results on the LogCat or any other debugging tool you use.
Well, I guess this will be all for my first blog here, I hope you will find it quite useful :).
Feel Free to leave your comments :)

Monday, April 4, 2011

First Sight !

If you want to be really good at something, it's going to involve relentlessly pushing past your comfort zone, as well as frustration, struggle, setbacks and failures. That's true as long as you want to continue to improve, or even maintain a high level of excellence. The reward is that being really good at something you've earned through your own hard work can be immensely satisfying.
Here, then, are the six keys to achieving excellence we've found are most effective for our clients:
  1. Pursue what you love. Passion is an incredible motivator. It fuels focus, resilience, and perseverance.
  2. Do the hardest work first. We all move instinctively toward pleasure and away from pain. Most great performers, Ericsson and others have found, delay gratification and take on the difficult work of practice in the mornings, before they do anything else. That's when most of us have the most energy and the fewest distractions.
  3. Practice intensely, without interruption for short periods of no longer than 90 minutes and then take a break. Ninety minutes appears to be the maximum amount of time that we can bring the highest level of focus to any given activity. The evidence is equally strong that great performers practice no more than 4 ½ hours a day.
  4. Seek expert feedback, in intermittent doses. The simpler and more precise the feedback, the more equipped you are to make adjustments. Too much feedback, too continuously can create cognitive overload, increase anxiety, and interfere with learning.
  5. Take regular renewal breaks. Relaxing after intense effort not only provides an opportunity to rejuvenate, but also to metabolize and embed learning. It's also during rest that the right hemisphere becomes more dominant, which can lead to creative breakthroughs.
  6. Ritualize practice. Will and discipline are wildly overrated. As the researcher Roy Baumeisterhas found, none of us have very much of it. The best way to insure you'll take on difficult tasks is to build rituals — specific, inviolable times at which you do them, so that over time you do them without having to squander energy thinking about them.