Tuesday, June 30, 2015

Android ListView Example

Here's a very simple example to get you started with an Android ListView. This example just displays a hard-coded list of colors in a ListView control. The key components are the ArrayAdapter and the additional layout file.

ListViews work via an adapter pattern. So, we have to create an adapter that lists the items that we're going to display in the ListView. We also have to create a layout with the type of entity that we're displaying for each item in the ListView. In this example, each item in the ListView will be a simple TextView. However, it could be something more involved (like an image).


res/layout/activity_main.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context="${relativePackage}.${activityClass}" >



    <ListView

       android:id="@+id/list_of_colors"

       android:layout_width="fill_parent"

       android:layout_height="fill_parent"

       android:padding="10dp"

       android:textSize="20sp" />


</RelativeLayout>


res/layout/listview_item.xml :

<?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">
    
 <TextView android:id="@+id/color_item"   
   android:layout_width="fill_parent"   
   android:layout_height="wrap_content"  
   android:padding="10dp"  
   android:textSize="16sp" />
 
</LinearLayout>


src/{package-name}/MainActivity.java :

public class MainActivity extends Activity {
 
    private  final String[] COLORS = new String[] { "Red", "Orange", 
             "Yellow", "Green", "Blue", "Indigo", "Violet" };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
  
       ArrayAdapter adapter = new ArrayAdapter(this, R.layout.listview_item,
                        R.id.color_item, COLORS);
  
       ListView lv = (ListView) findViewById(R.id.list_of_colors);
       lv.setAdapter(adapter);
    }
}

I put this code on GitHub for you to reference: https://github.com/travisdazell/android-listview-example

Sunday, June 28, 2015

Android Examples

Here is a list of Android examples that I've put together. I will continue adding to it over time.

  • Android Basics
  • Android Concurrency

Android - Starting a New Activity - Explicit Intent

In Android, each screen or presentation is done via its own activity. So, we will have a main activity that runs when the application is first started. Launching a new activity is simple, using an explicit intent.

Let's say that we have a button that launches a new activity when it's clicked. Here's the code for doing this, using an explicit intent.

   public void openOtherActivityClick(View view) {
     // create an explicit intent and specify
     // the exact class name of the activity that we want
     Intent otherActivityIntent = new Intent(this, OtherActivity.class);
  
     // start the other activity
     startActivity(otherActivityIntent);
 }

With an explicit intent, we specify the exact class name of the activity that we want to start. Another way to start an activity, is with an implicit intent. Here's an example of how to use an implicit intent: http://travisdazell.blogspot.com/2015/01/android-implicit-intents.html

Wednesday, June 24, 2015

Android AsyncTask Example

Often times, you will need to run an operation in the background of your Android app, so that you're not blocking the UI thread. For short running operations, AsyncTask is the perfect tool for the job. The best part is that it's very easy to use.

Let's consider an app that takes an image and adjusts the contrast of the image to make it brighter. By clicking a button in the app, a predefined image is made brighter and then displayed on the screen. To implement the image contrast functionality, let's pretend that we've already written a Java class called ImageUtils that contains a method called setContrast. The signature for this method looks like this:

public Bitmap setContrast(Bitmap image, double contrastValue);

Naively, we could call this method within our button's onClickListener. However, if we do that, then while the image is being manipulated, we will block the UI thread and cause the application to "freeze". So, we can use AsyncTask to perform this image manipulation in the background!

Here's a naive approach to processing the image, within the button's onClickListener:

public void onClickListener(View target) {
 // get the Android icon bitmap that's included in this project 
 Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

 ImageUtils imageConverter = new ImageUtils();

 Bitmap result = imageConverter.setContrast(originalBitmap, CONTRAST_VALUE);

 ivAndroidIcon.setImageBitmap(result);
}

Thankfully, to use AsyncTask, all that's needed is for us to create a new Java class that extends AsyncTask. Within this class, we'll call our setContrast method. In a sense, we're simply wrapping our current image logic with a class that extends AsyncTask. Pretty simple indeed! Here's how this new class looks:

class BrightenImageTask extends AsyncTask<Bitmap, Void, Bitmap> {
 @Override
 protected Bitmap doInBackground(Bitmap... params) {
  // create a new image that's much brighter than the original image
  ImageUtils imageConverter = new ImageUtils();

  return imageConverter.setContrast(params[0], CONTRAST_VALUE);
 }
  
 @Override
 protected void onPostExecute(Bitmap result) {
  // display the updated image
  ivAndroidIcon.setImageBitmap(result);
 }
}

Now that we have our image processing logic inside an AsyncTask, we can modify our button's onClickListener to call our AsyncTask:

public void onClickListener(View target) {
 // get the Android icon bitmap that's included in this project 
 Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

 new BrightenImageTask().execute(originalBitmap);
}

There are a couple things to note about AsyncTask:
  1. The generic types that are defined on our AsyncTask class are specifying that a Bitmap is passed into the doInBackground method and a Bitmap is returned by our onPostExecute method.
  2. The VOID type specifies the type that's used to as the unit of progress for the background operation. I didn't use a "progress indicator" in this example, but this is where you would do this type of indication. You could specify this as an Integer and then override the method onProgressUpdate(Integer... progress) to set a progress indicator.
If you really want to get an appreciation for AsyncTask, you can add a Thread.sleep(5000) inside your doInBackground method. You'll notice that you can still click around on the screen while the operation is happening in the background. If instead, you put the image processing logic directly inside the button's onClickListener, you will find that the screen becomes non-responsive while the image is being processed (namely that the button remains depressed and it's obvious that the UI is blocked).

So, next time you need to quickly make an operation run in the background, consider using AsyncTask. Note that this works great for operations that only take a few seconds to complete. However, if you have long running operations, you should consider using an Android service. This is because AsyncTask processes are still connected to the activity stack that executed the AsyncTask. As all of us Android developers know, the Android OS could decide to kill your activity at any time, if the OS needs to recover system resources. This could leave your background task in an unknown state. If you have a long running process, you'll want to use a service that continues to run, just in case your activity is shut down for some unplanned reason.

For reference, I've placed all of the source code for this application on GitHub: https://github.com/travisdazell/asynctask-example