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

Saturday, January 24, 2015

Android Implicit Intents

There are times that you want to utilize another application on the Android device for some action in your application. For example, let's say you have an application that opens a browser and navigate to a web site. You wouldn't want to build your own browser (most likely anyway), so you'd just let the Android device choose an application to use for navigating to the web site. When you do this, you're using an implicit intent. Here's how you do it.

private void navigateToWebSite() {
   // Create an intent for viewing a specific web site
   Uri google = Uri.parse("http://developer.android.com");
  
   Intent intent = new Intent(Intent.ACTION_VIEW, google);
  
   // Create a chooser intent
   Intent chooserIntent = Intent.createChooser(intent, "Browse with...");
        
   // Start the chooser activity
   if (intent.resolveActivity(getPackageManager()) != null) {
      startActivity(chooserIntent);
   }
}

The chooserIntent is optional. I'm using it to add a custom title to the chooser dialog. You can simply create the intent and call "startActivity(intent)" and let Android display the standard chooser dialog.

In this example, we just told Android to include any application that can handle the ACTION_VIEW intent. What if you have written your own application that you want to include as an option for handling  this type of intent? In your application's AndroidManifest.xml file, you simply add an intent-filter within the definition of the activity.

For example, here I've added a second intent-filter to handle any applications that initiates an intent on the Intent.ACTION_VIEW with "http" requests, just like in the example above.

<activity android:label="@string/app_name" android:name=".MyOtherActivity">

       <intent-filter>
           <action android:name="android.intent.action.MAIN" />

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

         <intent-filter>
             <action android:name="android.intent.action.VIEW">

             <category android:name="android.intent.category.DEFAULT">

             <data android:scheme="http">
         </intent-filter>

</activity>



Monday, January 19, 2015

Android - Handling Configuration Changes Yourself

There are many things that can happen outside of your Android application. One of the most common occurrences is a change in the device settings. For example, the user might leave your app running, while they go into the display settings and change the font size.

Android Font Size Setting

When the user goes back to your application, the activity in your application is recreated, which means onCreate() is called all over again. Most times, this is o.k. In fact, for the most part, you want to trust Android to handle these global settings and manage the effects of those changes to the lifecycle of your application's activities. However, there are times when you may want to manually handle these configuration changes. One obvious advantage to manually handling the config changes, is that you can avoid the activity being killed and recreated. Note that onStart(), onResume(), and onRestart() will still be called.

To manually handle config changes, simply add the "android:configChanges" attribute to the activity in your Manifest file. For example:

        <activity
            android:configChanges="fontScale"
            android:name="net.company.app.MainActivity"
            android:label="@string/app_name" >

There's a listing of the configChanges defined here: http://developer.android.com/guide/topics/manifest/activity-element.html.

The next step, is to override the onConfigurationChanged() method in the activity, like this:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Log.i(TAG, "newConfig.fontScale = " + newConfig.fontScale);

        super.onConfigurationChanged(newConfig);
    }


When the font size changes in the device settings, your onConfigurationChanged() method is called and an object containing the new device configuration is passed to the method, for you to handle as you please.

Saturday, January 17, 2015

Android Development - Hello World Application

If you know Java, you can learn Android development. In this blog post, we'll create a very simple Android application in Android Studio and run it with an Android emulator. To get started, download the Android Studio installer here: http://developer.android.com/sdk/index.html.

Take note of the system requirements, most importantly being the Java Development Kit (JDK).

Now that you've installed Android Studio, let's create a simple application for Android. Start up Android Studio and click the option for "Start a new Android Studio project".

Welcome to Android Studio Dialog

The next dialog prompts you to name your application and provide the Company Domain. For all intents and purposes, this is simply the package name for your Java classes. Choose a name for your application and package directory and click the "Next" button.

Android Studio New Project Dialog

The next dialog prompts you for the platform where you want to develop and deploy your application. Android is a very cool platform, in that you can develop apps for TV and wearables (e.g. watches), but for this example, I'm going to select "Phone and Tablet" and choose "API 8: Android 2.2 (Froyo)" for my minimum SDK version. When you develop applications for Android, you specify the minimum and maximum SDK version. For this application, API 8 Froyo will be the minimum SDK version needed to run the application. After you select the platform, click "Next".

Android Studio Select API Version Dialog

Next, you select an activity for you application and click "Next". I'm going to choose a Blank Activity. As you get more experienced with Android development, you'll become familiar with activities and the Activity class. For now, you can think of an activity as a screen or view in your application. By choosing Blank Activity, the application will have a blank screen to start building an application.

Android Studio Activity Dialog

The next dialog prompts you for a name for the activity. I'm going to leave it as MainActivity and click "Finish".

Android Studio - Name Activity Dialog



After clicking the "Finish" button, you'll see a progress dialog, as your application is being created.

Android Studio - Create Project Progress Dialog

When Android Studio is finished building your project, you'll see your new Android application open in the IDE.

Android Studio - IDE Screenshot



Next, let's run the application in an Android emulator. You can start up an emulator from the menu option under Tools-> Android -> AVD Manager. Note that AVD Manager is short for Android Virtual Device Manager.

Android Studio - AVD Manager Menu Option

The AVD Manager dialog prompts you to start a virtual device / emulator. If you don't have a virtual device created, you need to click the button for "Create Virtual Device...". This will allow you to device configuration and Android API version that you want to emulate. For this example, I'm going to use the virtual device that emulates a Nexus 5 using API 21. Because I already have it created, I'll click the green start button on the right side of the device listing, to start the device emulator.

Android Studio - Choose Virtual Device

Next, you'll see a progress dialog, as your device emulator is starting.

Android Studio - Starting Android Virtual Device Progress Dialog

Note that it can take a few minutes to start the emulator, so be patient. After your emulator has started, you'll see the Android welcome screen (just as you'd see if you were powering on an actual Android device). After powering on, you'll see the Android home screen.

Android Studio - Galaxy Nexus Startup Screen

To unlock the welcome screen, just click on the unlock icon and swipe upwards, as you would on an actual Nexus device.



Android Studio - Galaxy Nexus Home Screen

Now that the emulator is running, go back to your Android Studio IDE to run your application on the emulator. From the Android Studio menu, select Run -> Run...


Android Studio - Run Application Menu

You'll be prompted for the device where you want to run the application. Choose the emulator that's already running and click "OK".

Android Studio - Choose Running Device Dialog

After a few seconds, you'll see the application running on the device emulator.


Android Studio - Hello World Application

Congratulations, you've just created your first Android application! In the next Android blog post, I'll talk about the project structure and the files in the project, as well as provide a more involved application example.