How to get started with Android development

andro02Learning how to build a mobile application is a good project to improve your programming skills while learning to work in a different environment than the desktop or a web browser. You can get started without worrying about a large stack, making it easy for a beginner to pick it up and start playing with quickly.

Building applications with the Android SDK is self-contained if you stick with the standard libraries. You only need to download the package from Google containing all the tools and you’re ready to go. If you know object-oriented programming and how layouts are done for the web, many patterns and practices will feel familiar to you. The barrier to entry is low: all the tools are free, so you only need an Android device and your computer to get started.

Also, the open philosophy of Android means that you can do as you wish with your applications and your device. As long as you have an installer file (.apk), you can distribute your application to any device. It’s easy to send a copy of your application to your friends so they can test it out. This is great if you have a small project that you only want to deploy on a few machines such as a kiosk an art project. Once you have more experience, there are many open source libraries that improve on what is available in the SDK, and the open source community is active and welcoming.

The following will teach you how to get up and running with the samples included with the Android SDK.

Setting up an Android development environment

You don’t need much to get started with Android. Any decent PC, Mac or Linux box will do the job. All the tools are free, and you can install them as a single package from the Google Android Developers site at https://developer.android.com/sdk/.

There are two main tools you need to know about: the Android SDK Manager and the Android Studio IDE.

The Android SDK Manager is used to download the libraries, tools, system images and code samples for the platform (version) of the Android OS you want to develop for. By default, the package contains the latest version of the SDK Platform (6.0/API level 23 as I’m writing this). When a new version comes out or a new developer kit is available, you must download it using the SDK Manager.

The Android Studio IDE is where you’re going to spend most of your time. It is based on IntelliJ and includes a code editor, a layout editor and all the tools you need to compile your application and debug it on an emulator or on your Android device. Eclipse was previously available as an IDE so you’re going to see some references to it online, but Android Studio is now the official IDE for Android and everybody is now using it.

Installing the drivers for your tablet

By default, when you plug in an Android device in your computer, you’ll see the content of the external storage like you would see the content of a USB key. It’s enough to upload data, but if you want to debug an application on your device, you must install the drivers. You could develop applications using the emulator, but it’s a lot slower and it’s going to be hard to see if the touch interactions work as you intended.

If you have a Nexus device, the drivers are available from the Android SDK Manager. For other manufacturers like Samsung or ASUS, you can find the driver on their website. It’s not always clear what you should download, since the driver is often packaged with other software such as synchronization tools.

To be able to attach a debugger, you must also enable the debugging mode on your device by navigating to the About option in the Settings menu. Click 10 times on About and the Developers Options menu will appear, allowing you to set the debugging mode.

Running the sample projects from the Android SDK

The language used with the Android SDK is Java, but Android has its own virtual machine, Dalvik, that uses a subset of the standard Java classes. Since it’s such a small subset of Java, you don’t need experience in Java to get started. If you have a good basis in any object-oriented language, you should be able to pick it up pretty fast. The rest of the files, such as language files and layouts, are in XML.

To get started quickly, I’m going to show you how to run one of the sample projects. Those samples are from Google and they are a good starting point to learn what you can do in an Android application and how to do it. Google regularly adds new samples as new APIs becomes available, so check them before trying to do something.

When you start Android Studio for the first time, you’ll see the following screen. To get started running an application right now, just select Import an Android code sample to create a project.

AndroidStudioWelcome

In the following screen, choose the Borderless button example and click Next to create the project:

Once the project is loaded, select Debug… from the Run menu to launch the application in debugging mode on your device. A Device Chooser window will pop up, allowing you to select your device (if the driver has been properly installed) or to launch the emulator. Press OK and the sample will run on your device.

You can now play with the sample and add breakpoints in the source code (located in the Application\src\ folder) to see how it behaves. For example, you can put a breakpoint in the onCreate method of the MainActivity.js file, and try to understand how it behaves when you rotate your device.

Follow up articles:
Basic structure of an Android application
Layout of an activity using a layout manager

Using the jQuery UI datepicker with ASP.NET MVC

I wanted to start the real code for my side project by making a small skeleton of the project in ASP.NET MVC. This skeleton includes a basic form to create an event, which will be the starting point of the application. An event has a name with a start date and an end date that are represented as DateTime, so I figured I’d try my hand at integrating the jQuery UI datepicker to my form. That way, I’ll be able to make sure that jQuery UI is properly included in the application.

First, I included a bundle for the jQuery UI library along with jQuery on the page where I wanted the date picker to be.

After this, I created a input box using the TextBoxFor Razor helper which will be used to initialize the datepicker in JavaScript. I used the short date string so I would only get the date and not the time, and set the control as being read only so the user would be forced to pick the date from the picker. That way, I won’t have to handle the various date formats that could be entered.

<div>
   @Html.LabelFor(model => model.ScheduledEvent.StartDate)
      <div>
         @Html.TextBoxFor(model => model.ScheduledEvent.StartDate, 
                          new { Value = Model.ScheduledEvent.StartDate.ToShortDateString(),
                                @class = "datefield", 
                                @readonly = "readonly" })
      </div>
</div>

After this, I added the following to the JavaScript for my page to initialize the jQuery UI datepicker when the page is loaded.

$(document).ready(function () {
   $(".datefield").datepicker();
});

This already looked good when the page was first loaded, but there was a bug when a date was selected in the picker: the format of the date was not the same. Here is how it looked like with the original start date and the end date that was modified by the date picker:

AfterDatepicker

It works for saving the date, but it doesn’t look very good so this has to be fixed. But why is the format wrong? Well, my development machine is currently set to the fr-CA culture. ASP.NET MVC understands the fr-CA culture just fine and renders the dates in the format specified for that culture. On the client side thought, jQuery UI does not include the localization file to handle the date format for this culture by default, so it fallbacks to a standard format when setting an new date.

Fortunately, the fix is simple: you must set a default culture in you Web.config that jQuery UI can understand, which is en-US if no localization file is included. That will also make sure that you have the right culture in ASP.NET too regardless of the current culture of the server the application is executing on.

<system.web>
   <globalization uiCulture="en-US" culture="en-US" />
</system.web>

If you want to handle other cultures you must download and use the localization files from the jQuery UI at https://github.com/jquery/jquery-ui/tree/master/ui/i18n. For my project, I decided to force everything to en-US for now since the date format should be the same regardless of the culture of the browser of the user. This is to avoid confusion if multiple users with browsers set to different cultures are using the application to plan an event together.

A few closing notes

Don’t set the type of the input text box to the HTML5 date format, leave it as a standard text box. Otherwise, Chrome will use its own format for the date and you will get the following error when posting the form:
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.

I also looked for the problem in the wrong place for quite a while: I usually submit values to WebAPI instead of submitting an ASP.NET MVC form, and WebAPI uses a different parser for dates.

Saving an image in a SQLite database in your Android application

When you start caching data to a local database from your Android application, sooner or later you’ll need to save images in that database too. For example, if you’re storing reports about observations the users make in the field that will be uploaded to the main system later, it can be handy to add a picture to better describe the problem.

The first idea that comes to mind to store those images is saving them directly in the database as BLOBs (Binary Large OBjects). It can work, but it’s not the most efficient way to do it since SQLite is meant to store values and not large binary values. Also, the local database could get big pretty fast, especially if you need to save full size, high quality pictures. You can check out a benchmark on the official SQLite site at https://www.sqlite.org/intern-v-extern-blob.html if you want to have a better idea of the performance.

What you really want to do in that case is keep only the path to the image in your database and save the image in the internal storage of your application. When you need to use the image, you can simply use the path to fetch the image from the file system. I recommend you save the pictures to the internal storage since so it’s accessible only from your application and is available at all times; actually, the SQLite database itself is also stored in the internal storage.

Here is an example of how to add an image to an existing report, saving it in the internal storage and keeping the path in the database. To learn more about how to create a database and store data to it, you can read my article about saving to a SQLite database.

public class ApplicationDatabaseHelper extends SQLiteOpenHelper {
/**
  * Updates the current picture for the report.
  *
  * @param reportId the identifier of the report for which to save the picture
  * @param picture the picture to save to the internal storage and save path in the database.
  */
public void updateReportPicture(long reportId, Bitmap picture) {
   // Saves the new picture to the internal storage with the unique identifier of the report as 
   // the name. That way, there will never be two report pictures with the same name.
   String picturePath = "";
   File internalStorage = mContext.getDir("ReportPictures", Context.MODE_PRIVATE);
   File reportFilePath = new File(internalStorage, reportId + ".png");
   String picturePath = reportFilePath.toString();

   FileOutputStream fos = null;
   try {
      fos = new FileOutputStream(reportFilePath);
      picture.compress(Bitmap.CompressFormat.PNG, 100 /*quality*/, fos);
      fos.close();
      }
   catch (Exception ex) {
      Log.i("DATABASE", "Problem updating picture", ex);
      picturePath = "";
      }

   // Updates the database entry for the report to point to the picture
   SQLiteDatabase db = getWritableDatabase();

   ContentValues newPictureValue = new ContentValues();
   newPictureValue.put(ReportContract.ReportEntry.COLUMN_PICTURE_TITLE, 
                       picturePath);

   db.update(ReportContract.TABLE_NAME,
             newPictureValue,
             ReportContract.ReportEntry._ID + "=?",
             new String[]{String.valueOf(reportId)});
   }
}

If you save a picture to the database, you also need a way to get that picture to display it in your application. Here is how to get the image that was just saved to display it again :

public class ApplicationDatabaseHelper extends SQLiteOpenHelper {
/**
  * Gets the picture for the specified report in the database.
  *
  * @param reportId the identifier of the report for which to get the picture.
  *
  * @return the picture for the report, or null if no picture was found.
  */
public Bitmap getReportPicture(long reportId) {
   String picturePath = getReportPicturePath(reportId);
   if (picturePath == null || picturePath.length() == 0)
      return (null);

   Bitmap reportPicture = BitmapFactory.decodeFile(picturePath);

   return (reportPicture);
   }

/**
  * Gets the path of the picture for the specified report in the database.
  *
  * @param reportId the identifier of the report for which to get the picture.
  *   
  * @return the picture for the report, or null if no picture was found.
  */
private String getReportPicturePath(long reportId) {
   // Gets the database in the current database helper in read-only mode
   SQLiteDatabase db = getReadableDatabase();

   // After the query, the cursor points to the first database row
   // returned by the request
   Cursor reportCursor = db.query(ReportContract.TABLE_NAME,
                                  null,
                                  ReportContract.ReportEntry._ID + "=?",
                                  new String[]{String.valueOf(reportId)},
                                  null,
                                  null,
                                  null);
   reportCursor.moveToNext();
    
   // Get the path of the picture from the database row pointed by
   // the cursor using the getColumnIndex method of the cursor.
   String picturePath = reportCursor.getString(reportCursor.
                             getColumnIndex(ReportContract.ReportEntry.COLUMN_PICTURE_TITLE));

   return (picturePath);
   }
}

Finally, you need to make sure to delete the picture from the internal storage if you delete the associated record from the database. If you keep the pictures, the internal storage used by your application will grow larger with time and your users won’t have any way to delete those pictures since the internal storage is hidden from them.

public class ApplicationDatabaseHelper extends SQLiteOpenHelper {
/**
  * Deletes the specified report from the database, removing also the associated picture from the
  * internal storage if any.
  *
  * @param reportId the report to remove.
  */
public void deleteReport(long reportId) {
   // Remove picture for report from internal storage
   String picturePath = getReportPicturePath(reportId); // See above
   if (picturePath != null && picturePath.length() != 0) {
      File reportFilePath = new File(picturePath);
      reportFilePath.delete();
   }

   // Remove the report from the database
   SQLiteDatabase db = getWritableDatabase();

   db.delete(ReportContract.TABLE_NAME,
             ReportContract.ReportEntry._ID + "=?",
             new String[]{String.valueOf(reportId)});
   }
}