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

Published my First Book on Leanpub About Android Storage

I just published my first book on Leanpub last week. The book covers the best type of storage to use for various types of data :

  • Saving files in the internal and external storage.
  • Saving user preferences with the Preferences API.
  • Saving data in a SQLite database.

The book also explains what is the best way to save the state of an activity so users don’t loose their input.

This material is available on the blog in my series on Android storage, but I formatted it as a book to make it easier to read. I also added a few new schematics that were created for my DroidCon Montreal talk and that are not on the blog to explain the Android life cycle when an activity is destroyed/paused and recreated.

So, if you need to handle storage in your Android application, check out my book at https://leanpub.com/androidstorage
booklarge

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)});
   }
}