Chapter 4

  Examining a Basic Android App

In This Chapter

check1 Finding your app’s activities, layouts, menus, and other stuff

check1 Assigning names to things

check1 Choosing API levels

In Chapter 3 of this minibook, you run Android Studio to create a skeletal Android app. The skeletal app doesn’t do much, but the app has all the elements you need for getting started with Android. You get a basic activity (a screen full of stuff for the user to look at). You get an elementary layout for your activity. You get an icon or two, and a little text thingy that says Hello world! You can even run the new app on an emulator or on a real Android device.

Unfortunately, this skeletal app contains many, many parts. The last time I checked, the skeletal app had 66 files and 119 different directories. All this just to display Hello world! on a mobile device’s small screen!

So before you plunge headlong into Android development, you can pause to take a look at this skeletal app. Open Android Studio, make sure that the app from Chapter 3 is showing in the main window, and take this chapter’s ten-cent tour of the app.

A Project’s Files

Figure 4-1 shows a run of the skeletal app that Android Studio creates for you, and Figure 4-2 shows some of the files in this simple Android project. The tree in Figure 4-2 contains a manifests branch, a java branch, a res branch, and some other stuff.

image

Figure 4-1: A run of the app created by Android Studio.

image

Figure 4-2: The structure of a new project in Android Studio.

Notice the word Android at the top of Figure 4-2. Under the word Android, you see a tree containing several branches. This tree with its Android title is called the Project tool window. Whenever you look at the Project tool window, you see one of its many views, including the Android view (which is showing in Figure 4-2), the Packages view, and the Project view. You might also see Project Files, Problems, Production, or Tests. (And while you’re seeing things, see Figure 4-3.)

image

Figure 4-3: Options for the Project tool window.

On your own computer screen, look for the word Android at the top of the Project tool window. If, instead of Android, you see the word Project, the word Packages, or some other word, click that word. When you do, you see a drop-down list, as shown in Figure 4-3. In that drop-down list, select the Android option.

crossreference For more information about the Project tool window’s views, see the sidebar entitled “The many faces of Android Studio,” later in this chapter.

remember The official Android Studio terminology can be confusing. The Project view isn’t the only view that belongs to the Project tool window.

The next several sections describe the files (and the branches of the tree) in the Project tool window shown in Figure 4-2.

The MainActivity.java file

Your app can have files named MainActivity.java, MyService.java, DatabaseHelper.java, MoreStuff.java, and so on. In fact, you can cram hundreds of Java files into a project. But when you create a new project, Android Studio typically creates one activity’s .java file for you. In Chapter 3 of this minibook, when I create an Android project, I accept the default name MainActivity, so Android Studio creates a file named MainActivity.java. Listing 4-1 shows you the code in the MainActivity.java file.

Listing 4-1: Android Studio Creates This Skeletal Activity Class

package com.example.myapplication;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

public class MainActivity extends Activity {

  @Override

  protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

  }

 

  @Override

  public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.menu_main, menu);

    return true;

  }

 

  @Override

  public boolean onOptionsItemSelected(MenuItem item) {

      int id = item.getItemId();

 

      if (id == R.id.action_settings) {

       return true;

    }

 

    return super.onOptionsItemSelected(item);

  }

}

warning What you see in your editor might be different from the code in Listing 4-1. For example, you might see the line

import android.support.v7.app.ActionBarActivity;

You might also see

public class MainActivity extends ActionBarActivity

in place of the reference to Activity in Listing 4-1. Rest assured that, here in Chapter 4, the differences don’t matter.

An Android activity is one “screenful” of components. Think of an activity as a form — perhaps a form for entering information to make a purchase on a website. Unlike most online forms, Android activities don’t necessarily have text boxes — places for the user to type credit card numbers and such. But Android activities have a lot in common with online forms. When you extend the android.app.Activity class (or the similar ActionBarActivity class), you create a new Android activity.

crossreference For more information about Java, see Book II, Chapters 2, 3, and 4.

An Android application can contain many activities. For example, an app’s initial activity might list the films playing in your area. When you click a film’s title, Android then covers the entire list activity with another activity (perhaps an activity displaying a relevant film review).

crossreference Having one activity overlay another activity is typical of small phone screens. But on larger tablet screens, you can display a list of films and a particular film review side by side. Having side-by-side panels is a job for fragments rather than activities. To read about fragments, see Book V, Chapter 1.

Here’s another (possibly surprising) thing to keep in mind: An Android app can invoke an activity belonging to a different app. For example, your app might display a Help button, and pressing Help might open a web page. With the web page housed somewhere on the Internet, your app’s button fires up an activity belonging to Android’s built-in web browser application. In the Android world, applications don’t bogart their activities.

Every Android activity has a lifecycle — a set of stages that the activity undergoes from birth to death to rebirth, and so on. I describe the activity lifecycle in Book III, Chapter 1. But in this chapter, you get a peek at the activity lifecycle with the method onCreate in Listing 4-1.

The onCreate method

When Android creates an activity, Android calls the activity’s onCreate method. This happens much more often than you’d think, because Android destroys and then re-creates activities while the user navigates from place to place. For example, if your phone runs low on memory, Android can kill some running activities. When you navigate back to a killed activity, Android re-creates the activity for you. The same thing happens when you turn the phone from portrait to landscape mode. If the developer doesn’t override the default behavior, Android destroys an activity and re-creates the activity before displaying the activity in the other mode.

In Listing 4-1, the onCreate method has things named savedInstanceState and R.layout.activity_main.

  • The savedInstanceState variable stores information about some of the activity’s values when the activity was previously destroyed.

    The statement super.onCreate(savedInstanceState) tells Android to restore those previous values. This way, the activity takes up where it last left off.

    remember During what appears to the user to be a continuous run, Android might destroy and re-create an activity several times. An activity’s savedInstanceState helps to maintain continuity between destructions and re-creations.

    technicalstuff To be precise, the statement super.onCreate(savedInstanceState) calls the parent class’s onCreate method. To read more about parent classes in Java, see Book II, Chapter 2.

  • The method parameter R.layout.activity_main is a roundabout way of coding the buttons, text fields, and the way they’re all laid out.

    In Listing 4-1, the call to setContentView plops these buttons, text fields, images, and other stuff on the activity screen. For more about this, check the section “The R.java file”, later in this chapter.

The onCreateOptionsMenu method

With a new Android activity comes a new menu. For older Android versions, a separate menu button is somewhere on (or near) the device’s screen. But starting with Honeycomb, apps put a menu icon in an action bar. (In Figure 4-1, the activity’s menu icon has three vertically-aligned dots. The icon appears in the screen’s upper-right corner.)

  • In Listing 4-1, the call getMenuInflater().inflate(R.menu.menu_main, menu) does the same for the look of your menu items as a call to setContentView does for the overall look of your activity.

    The call puts items (and perhaps sub-items) in your app’s menu.

  • The last statement inside the onCreateOptionsMenu method (the return true statement) tells Android to display your app’s menu.

    If, for some reason, you don’t want Android to display the menu, change this statement to return false.

In Listing 4-1, the onCreateOptionsMenu method creates your activity’s menu. That’s fine, but what happens when the user taps a menu item? When the user taps an item, Android calls your activity’s onOptionsItemSelected method.

The onOptionsItemSelected method

In Listing 4-1, the onOptionsItemSelected method doesn’t do too much.

  • The call to item.getItemId() grabs the code number of whatever item the user tapped.

    crossreference For some good reading about Android’s use of code numbers, see the section “The R.java file,” later in this chapter.

  • When your IDE creates a skeletal app, the app has one menu item named action_settings. The code in Listing 4-1 checks to find out if the user tapped this action_settings item.

    In a real-world app, the code would check to find out which of several menu items the user tapped.

  • Returning true tells Android that the tapping of this menu item has been handled. No further action is necessary.

    A return value of false would mean that some other code should do something in response to the user’s tap.

  • Finally, the super.onOptionsItemSelected(item) call tells Android to do, with this menu item tap, whatever Android normally does by default for any old menu item tap.

    This is no big deal because, by default, Android does almost nothing.

crossreference To make use of the code in Listing 4-1, you have to know something about Java. For a big blast of Java, visit Book II, Chapters 2, 3, and 4.

The res branch

In this section, I’m plugging along and exploring the branches in the Project tool window’s tree in Figure 4-2. The project’s res branch (a branch within the app branch) contains resources for use by the project’s Android application. The res branch has sub-branches named drawable, layout, menu, mipmap, and values.

The res/drawable branch

The drawable branch contains images, shapes, and other such things. A single drawable item might come in several different sizes, each with its own dpi (dots per inch) level. The sizes include mdpi (a medium number of dots per inch), hdpi (a high number of dots per inch), xhdpi (extra high), and xxhdpi (extra-extra high). I wonder how many “xs” we’ll need when Android starts powering digital displays on Times Square!

crossreference For more reading about drawables, visit, Book IV, Chapter 1.

The res/layout branch

The layout branch contains descriptions of your activities' screens.

A minimal app’s layout branch contains an XML file describing an activity’s screen. (See the activity_main.xml branch in Figure 4-2.) Listing 4-2 shows the code in the simple activity_main.xml file.

Listing 4-2: A Small Layout File

<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"

    android:paddingBottom="16dp"

    android:paddingLeft="16dp"

    android:paddingRight="16dp"

    android:paddingTop="16dp"

    tools:context=".MainActivity">

 

  <TextView

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:text="Hello world!" />

</RelativeLayout>

 

An Android app consists of Java code, XML documents, and other stuff. The XML code in Listing 4-2 describes a relative layout. (In a relative layout, each element’s position is relative to the positions of other elements. So buttons and text fields appear to the right of one another, to the left of one another, below one another, and so on.) Because of its match_parent attributes, the layout is large enough to fill its surroundings. Its “surroundings” are the entire screen (minus a few doodads on the edges of the screen).

In Listing 4-2, the only item inside the relative layout is an instance of TextView — a place to display text on the screen. Because of the wrap_content attributes, the text view is only wide enough and only tall enough to enclose whatever characters it displays.

crossreference For more info about layouts, see Book IV, Chapter 1.

What you see isn’t what you get

When you look at the activity_main.xml text in Android Studio’s editor, you see the stuff in Listing 4-2. But you can also visit the activity_main.xml file using Windows File Explorer or Mac Finder. You can open this file with Windows Notepad or Mac TextEdit. When you do, you see the text in Listing 4-3.

Listing 4-3: The Real activity_main.xml File

<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"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context=".MainActivity">

 

  <TextView

      android:layout_width="wrap_content"

      android:layout_height="wrap_content"

      android:text="@string/hello_world" />

</RelativeLayout>

 

What you see in Listing 4-3 is the text that’s really in the app’s activity_main.xml file. But what you typically see in Android Studio’s editor isn’t the same as the text in Listing 4-3. (In Listing 4-3, the text that I’ve set in bold is different from what you see in Android Studio’s editor.)

Android Studio’s editor doesn’t show you all the text (and only the text) in a file such as activity_main.xml. Instead, the editor replaces some expressions with the values of those expressions. It’s like displaying the number 42 when the actual file contains the text 20 + 22.

  • In the activity_main.xml file, the value of the expression @dimen/activity_vertical_margin is 16.

    That’s why you see @dimen/activity_vertical_margin in Listing 4-3, but you see 16 in Listing 4-2.

    To be more precise, the expression @dimen/activity_vertical_margin stands for 16 device independent pixels (16dp). To find out what a device independent pixel is, see Book IV, Chapter 1.

  • In the activity_main.xml file, the value of the expression @string/hello_world is Hello world!

    To find out why @dimen/activity_vertical_margin stands for 16dp and why @string/hello_world stands for Hello world, see the section “The res/values branch,” later in this chapter.

In Android Studio’s editor, things like "16dp" appear as light-gray characters. The light-gray shade indicates that the editor isn’t showing you the text that’s really in the activity_main.xml file (the text that you’d probably type if you were composing this code from scratch).

  • If you hover over the light-gray text, a pop-up shows you the text that’s really in the file.
  • If you click on the light-gray text, Android Studio replaces it with the text that’s really in the file. Instead of seeing Hello world! in light gray, you see @string/hello_world in an off shade of green.
  • (Here’s the thing that drove me crazy until I figured out what was going on.) You can select the text in the Android Studio editor, copy that stuff to the Clipboard, and then paste it into a regular editor (Windows Notepad, Mac TextEdit, or whatever). When you do, you don’t necessarily see whatever you see in Android Studio’s editor. You see @dimen/activity_vertical_margin instead of 16dp, and you see @string/hello_world instead of Hello world! (As an author who regularly copies and pastes material into a Word document, this behavior sends me running and screaming!)

The res/menu branch

Each file in the menu branch describes a menu belonging to your app. The simple app that your IDE creates contains only one menu. The file to describe that menu is named menu_main.xml.

Listing 4-4 contains the bare-bones menu_main.xml file.

Listing 4-4: The menu_main.xml Menu File

<menu xmlns:android=

      "http://schemas.android.com/apk/res/android"

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

  tools:context="com.example.myapplication.MainActivity" >

 

  <item

    android:id="@+id/action_settings"

    android:orderInCategory="100"

    android:showAsAction="never"

    android:title="Settings"/>

 

</menu>

 

The menu contains only one item, and in other parts of this app’s code, you refer to that item by the name action_settings.

technicalstuff Android Studio’s editor doesn’t show you exactly what’s in the menu_main.xml file. Where you see android:title="Settings" in Listing 4-4 (and in Android Studio’s editor), the file really contains the text android:title="@string/action_settings". The expression @string/action_settings has a value, and that value is the word Settings. For more information about @string expressions, see the “The res/values branch” section.

crossreference For more info about menus, see Book IV, Chapter 2.

The res/mipmap branch

The res/mipmap branch is like the res/drawable branch, except that the res/mipmap branch contains your app’s icons. The term mipmap stands for multum in parvo mapping. And the Latin phrase multum in parvo means “much in little.” A mipmap image contains copies of textures for many different screen resolutions.

technicalstuff The mipmap folder was introduced in Android 4.3, so you don’t see it in older Android apps (including some of this book’s apps).

The res/values branch

The files in the values branch describe miscellaneous things that an app needs to know. For example, Listing 4-3 shows you what’s actually in your app’s activity_main.xml file. In that file, the @string/hello_world attribute tells Android what text to display inside the TextView element. In Figure 4-1, these words happen to be Hello world! To find out how @string/hello_world gets turned into Hello world!, and how Hello world! gets to be displayed as part of your app, see Figure 4-4.

image

Figure 4-4: All this work to put Hello world! on the screen!

Why does the activity_main.xml file contain the following cryptic line?

android:text="@string/hello_world"

 

Why don’t you simply code

android:text="Hello World!"

 

in the activity_main.xml file (the way the editor displays the file in Listing 4-2)?

Here’s why: If you create a good Android app, people all around the world download your app. These people speak many different languages, so you don’t put actual words (like Hello world!) in your app’s Java code or even in your app’s activity_main.xml layout file. Instead, you put Hello world! in your res/values/strings.xml file. Then, to localize your app for French, you put Bonjour tout le monde! in a res/values-fr/strings.xml file. To localize your app for Romanian, you put Salut lume! in a res/values-ro/strings.xml file.

Listing 4-5 shows the code in the simple strings.xml file.

Listing 4-5: A Small strings.xml File

<?xml version="1.0" encoding="utf-8"?>

<resources>

 

  <string name="app_name">My Application</string>

  <string name="hello_world">Hello world!</string>

  <string name="action_settings">Settings</string>

 

</resources>

 

In Listing 4-5, the line

<string name="hello_world">Hello world!</string>

 

tells Android that, in other parts of the app’s code, the expressions @string/hello_world and R.string.hello_world refer to the words Hello world!

remember In an Android app, one string of characters, such as Hello world! goes by many different names. Listing 4-5 describes a "hello_world" string containing the characters Hello world!. To refer to that "hello_world" string in Listing 4-1 (a .java file), you type R.string.hello_world. To refer to the same "hello_world" string in another XML file (such as the file in Listing 4-2), you type @string/hello_world. With either @string/hello_world or R.string.hello_world, you refer to the thing named "hello_world" (the thing in Listing 4-5). And, either way, you point to the words Hello world! in Figure 4-1. (Yes, it can be confusing. I’ve dealt with this string-naming business for several years, but I still have to stop and think about it.)

In Listing 4-5, expressions such as @dimen/activity_horizontal_margin work the same way as the @string expression. The app/res/values branch in the Project tool window contains a dimens.xml branch. That dimens.xml branch typically contains two dimens.xml files. These dimens.xml files contain lines such as

<dimen name="activity_horizontal_margin">16dp</dimen>

 

When a device runs your app, the device substitutes an actual value (such as 16dp — 16 device independent pixels) for the expression @dimen/activity_horizontal_margin in your activity_main.xml file. With this substitution trick, a single activity_main.xml file works for screens of many shapes and sizes. To accommodate a certain screen size, a device consults one of your app’s dimens.xml files.

crossreference To read all about XML documents, like the ones in Listings 4-2 through 4-5, see Book II, Chapter 5.

Other files in an Android project

A simple Android app contains dozens of files. Many of these files appear in the Android view (in the Project tool window). Some of the files that don’t appear are still worth knowing about.

The build.gradle file

Gradle is a software tool. When the tool runs, it takes a whole bunch of files and combines them to form a complete application. For example, a run of Gradle can use the files shown in Figure 4-2 to build a single .apk file for posting on Google’s Play store. Of course, Gradle can combine files in many different ways, so to get Gradle to do things properly, someone has to provide Gradle with a script of some kind.

A new Android app comes with its own ready-made script. In Figure 4-2, that script appears in the branch labeled build.gradle (Module: app).

Listing 4-6 shows the contents of a simple app’s build.gradle file.

Listing 4-6: A Little build.gradle File

apply plugin: 'com.android.application'

android {

    compileSdkVersion 21

    buildToolsVersion "21.1.2"

 

    defaultConfig {

        applicationId "com.example.myapplication"

        minSdkVersion 15

        targetSdkVersion 21

        versionCode 1

        versionName "1.0"

      }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile

              ('proguard-android.txt'), 'proguard-rules.pro'

        }

 

    }

}

 

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

}

 

I cover some build.gradle code in the section “Your app’s API levels,” later in this chapter. So, in this section, I describe only a few of the listing’s highlights.

An app’s versions

In Listing 4-6, the versionCode and versionName properties have similar (but slightly different) meanings.

  • The versionCode property is an integer. For publication on the Google Play Store, the versionCode must increase from one version of your app to another. The numbers don’t have to be consecutive. So your first published version can have versionCode 47, and the next published version can be number 63. The app’s user doesn’t see the versionCode.
  • The versionName can be any string of characters, so this attribute’s value is largely cosmetic. The user sees the versionName.

Listing 4-6 contains values for an app’s compileSdkVersion, minSdkVersion, and targetSdkVersion. To find out what these SDK versions are, see the section “Your app’s API levels,” later in this chapter.

What is ProGuard?

Obfuscation is a way of making your Java code difficult to understand (which makes the code difficult to steal, difficult to modify, and difficult to infect), and ProGuard is a tool that can obfuscate your Java programs. In order to obfuscate your code, Android Studio needs to configure the ProGuard tool. Listing 4-6 says that this configuration information lives in files named proguard-android.txt and progard-rules.pro. (You can peek at the proguard-rules.pro file by switching to the Project view in the Project tool window.)

crossreference To read about ProGuard’s role in Android app development, see Book VI, Chapter 1.

The AndroidManifest.xml file

An app’s AndroidManifest.xml file describes some of the things a device needs in order to run the app. (See Listing 4-7.)

Listing 4-7: A Little AndroidManifest.xml File

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=

    "http://schemas.android.com/apk/res/android"

  package="com.example.myapplication" >

 

  <application

    android:allowBackup="true"

    android:icon="@drawable/ic_launcher"

    android:label="@string/app_name"

    android:theme="@style/AppTheme" >

    <activity

      android:name=

        "com.example.myapplication.MainActivity"

      android:label="@string/app_name" >

      <intent-filter>

        <action android:name=

            "android.intent.action.MAIN" />

 

        <category android:name=

            "android.intent.category.LAUNCHER" />

      </intent-filter>

    </activity>

    </application>

 

</manifest>

 

remember What you see in Android Studio’s editor isn’t the same as what I show in Listing 4-7. Some of the text composed by Android Studio changes from one version of Android Studio to the next. In addition, Android Studio’s editor might display android:label="My Application" with My Application in light-gray text. But in place of that text, the AndroidManifest.xml file actually contains the reference android:label="@string/app_name".

tip All Android apps have AndroidManifest.xml files. But only newer Android apps have build.gradle files. For older apps, information about versionCode, versionName, and SDK versions lives in the AndroidManifest.xml file:

<manifest xmlns:android=

  "http://schemas.android.com/apk/res/android"

    package="com.example.myapplication "

    android:versionCode="1"

    android:versionName="1.0">

  <uses-sdk android:minSdkVersion="15"/>

… Etc.

The <application> element

In Listing 4-7, the application element has several attributes, including android:icon and android:label. The user sees the application’s icon and label on the device’s Apps screen. The application’s label (and sometimes the icon) appears when one of the app’s activities is in the foreground. (See the words My Application in Figure 4-1.)

The <activity> element

In Listing 4-7, the activity element has an android:label attribute. An app’s activity can have its own icon and label, overriding the app’s icon and label.

One way or another, an activity element in an AndroidManifest.xml file must have an android:name attribute. The android:name attribute has either of the following values:

  • The fully qualified name of the activity class.

    In Listing 4-7, the fully qualified name is com.example.myapplication.MainActivity.

  • The abbreviated activity class name, preceded by a dot.

    The name .SomeClass stands for “the class named SomeClass in this project’s package.” So, in Listing 4-7, the following lines work just fine:

    package="com.example.myapplication"

    android:name= ".MainActivity"

     

    technicalstuff The manifest element’s package attribute isn’t in the android namespace. In Listing 4-7, I type package, not android:package. For more information about XML namespaces, see Book II, Chapter 5.

Within an activity element, an intent-filter element describes the kinds of duties that this activity can fulfill. Intent filters consume an entire chapter (see Book III, Chapter 2). So in this section, I don’t dare open the whole intent filter can of worms. But to give you an idea, action android.intent.action.MAIN indicates that this activity’s code can be the starting point for an app’s execution. And the category android.intent.category.LAUNCHER indicates that this activity’s icon can appear in the device’s Apps screen.

remember If you create a second activity for your app, you must declare the new activity in the app’s AndroidManifest.xml file. If you don’t, your app will crash with an ActivityNotFoundException.

The R.java file

Each Android project has an R.java file. Android Studio generates this file, and protects this file as if the file were made of gold. You, the developer, never create or modify the R.java file’s text.

tip You don’t see R.java in Figure 4-2 because the R.java file doesn’t appear in the Android Project view. If you want to see the R.java file, switch the Project tool window to its Packages view. Follow the instructions on switching views in the sidebar “The many faces of Android Studio.” When the Packages view replaces the Android Project view, visit the app/com.example.myapplication/test/R branch in the tree.

Listing 4-8 shows some of the lines in an R.java file.

Listing 4-8: Don’t Even Look at This File

/* AUTO-GENERATED FILE. DO NOT MODIFY.

  *

  * This class was automatically generated by the

  * aapt tool from the resource data it found. It

  * should not be modified by hand.

  */

 

package com.example.myapplication;

 

public final class R {

  public static final class attr {

  }

  public static final class drawable {

    public static final int ic_launcher=0x7f020000;

  }

  public static final class id {

    public static final int action_settings=0x7f080000;

  }

  public static final class layout {

    public static final int activity_main=0x7f030000;

  }

  public static final class menu {

    public static final int main=0x7f070000;

  }

  public static final class string {

    public static final int action_settings=0x7f050002;

    public static final int app_name=0x7f050000;

    public static final int hello_world=0x7f050001;

  }

  // … There’s more stuff here

}

 

The hexadecimal values in an R.java file are the jumping-off points for Android’s resource management mechanism. Android uses these numbers for quick and easy loading of the things you store in the res branch. For example, the code in Listing 4-1 sets the look of your activity to R.layout.activity_main, and according to Listing 4-8, R.layout.activity_main has the hex value 0x7f030000.

Android’s documentation tells you to put R.java and its hex values out of your mind, and that’s probably good advice (advice that I break in this section). Anyway, here are two things to remember about the role of R.java in an Android app:

  • You cannot edit R.java.

    Long after the creation of a project, your IDE continues to monitor (and if necessary, update) the contents of the R.java file. If you delete R.java, Android Studio re-creates the file. If you edit R.java, Android Studio undoes your edit.

  • Many of Android’s pre-declared methods expect numbers in R.java as their parameters.

    This can lead to some confusion. Consider the following (very bad) chunk of code:

    // THIS IS BAD CODE!

    System.out.println("42");

    System.out.println(42);

     

    textView.setText("42");

    textView.setText(42);

    Java’s two System.out.println calls (rarely used in Android apps) add text to a log file. In the bad code, the first System.out.println sends the string "42" to the file, and the second System.out.println converts the integer value 42 to the string "42" and then sends the string "42" to the log file. (Java’s System.out.println is prepared to print a string, an integer, and various other types of values.) So far, there’s nothing wrong with the code. So let’s move on …

    A text view’s setText method accepts a string parameter or an integer parameter. In the bad code, the call textView.setText("42") is okay. But here’s the gotcha: The integer version of setText doesn’t convert the integer 42 into a string. Instead, textView.setText(42) looks for a resource with code number 42 (in R.java, hex value 0x0000002A). When Android finds nothing with code number 42 in the R.java file, your app crashes.

The assets directory

When Android packages an app, a tool named aapt (short for Android Asset Packaging Tool) compiles the stuff in the app’s res directory. In other words, aapt prepares the res directory’s items for quick retrieval and use. So your application’s access to items in the res directory is highly optimized.

But before there was Android, there was plain old Java, and plain old Java has its own ways to fetch images and strings. Using Java’s techniques, you generally read byte by byte from the Internet or from a device’s file system. To make your Android code grab an image or some other data using Java’s standard tricks, put the image or data in the Android project’s assets directory.

By default, an Android Studio project (the kind of project that’s displayed in Figure 4-2) doesn’t have an assets directory. To create such a directory, do the following:

  1. In the Project tool window (Figure 4-2) right-click the app branch at the top of the tree. (If you’re a Mac user, control-click that branch.)

    A context menu appears.

  2. In the context menu, choose New ⇒ Folder ⇒ Assets Folder.

    A dialog box appears.

  3. In the dialog box, click Finish.

As a result, you see a new assets branch in the Android Project tree.

The android.jar archive

Each Android project’s CLASSPATH includes Android’s pre-declared Java code, and this pre-declared code lives in an android.jar archive file.

In Android Studio, you can see android.jar by switching to the Project view. Follow the instructions on switching views in the sidebar “The many faces of Android Studio.” When the Project view replaces the Android Project view, visit the External Libraries/Android API branch of the tree.

technicalstuff A .jar file is a compressed archive containing a useful bunch of Java classes. In fact, a .jar file is a Zip archive. You can open any .jar file with WinZip, StuffIt Expander, or your operating system’s built-in unzipping utility. (You may or may not have to change the file’s name from whatever.jar to whatever.zip.) Anyway, an android.jar file contains Android’s Java classes for a particular version of Android.

crossreference For more information about .jar files and .zip files, see Book II, Chapter 4.

The android.jar file contains code grouped into Java packages, and each package contains Java classes. (Figures 4-5 and 4-6 show only the tip of the android.jar iceberg.) The android.jar file contains classes specific to Android and classes that simply help Java to do its job. Figure 4-5 shows a bunch of Android-specific packages, and Figure 4-6 displays some all-purpose Java packages.

image

Figure 4-5: Some of the packages and classes in android.jar.

image

Figure 4-6: The android.jar file includes general-purpose Java packages.

The APK file

Android puts the results of all its compiling, packaging, and other “ings” into a single file with the .apk extension. This APK file contains everything a user’s device needs to know in order to run your app. When you install a new app on your Android device, you download and install a new APK file.

technicalstuff An important job of the Gradle tool is to combine your app’s file into one APK file. This happens each time you choose Run ⇒ Run ‘app' in Android Studio’s main menu.

You can find an app’s APK file using your Windows File Explorer or Macintosh Finder. For an Android Studio project, the APK file is in the project’s app/build/outputs/apk subdirectory.

What Did I Agree To?

When you follow the instructions in Chapter 3 of this minibook, you create a new Android project. In doing so, you have lots of choices to make. The instructions in Chapter 3 tell you to accept a bunch of defaults. This section describes some of the “whys” and “wherefores” concerning those defaults.

What’s in a name?

When you create a new application, you assign a bunch of names to things in your application. For example:

  • You create an application name and a package name.
  • You specify a project location, and in doing so, you name the directory that contains the app on your development computer’s hard drive.
  • You name an activity.

In Chapter 3 of this minibook, when you create your first application, I recommend accepting any default names that Android Studio flings at you. For example, you call your app My Application, and you use example.com as a company domain. Of course, in real life, default names aren’t very helpful. Ordinary folks, like Joe and Jane User, will see your Application name in the Android device’s launcher screen, and the name My Application isn’t very inviting. If you’re planning to market your app, your app’s name should be short, sweet, and descriptive.

Here are some guidelines for naming things:

  • When you create a new application, your project and application names may contain blank spaces, but your package name and your activity name must not contain blank spaces.

    In general, I’m not a fan of blank spaces. Blank spaces can gum up the works when your software distinguishes the end of one name and the start of the next name. For example, in Windows, the folder name Program Files is a never-ending source of angst for me and other developers. My advice is, use blank spaces only where an app’s cosmetics demand blank spaces. If things go wrong, be suspicious of any names with blank spaces.

  • For your project name, you can type the name of any valid Java identifier. Make sure to start with a letter and then include only letters, digits, and underscores ( _ ).

    crossreference For the scoop on Java identifiers, see Book II, Chapter 2.

  • Your activity is a Java class. So, to adhere to Java’s stylistic conventions, start your activity’s name with an uppercase letter. In the name, don’t include any exotic characters (such as dots, blank spaces, dashes, dollar signs, or pictures of cows).

In Java, you normally group a bunch of related classes into a package, and you give the package a name. The name can be almost anything, but Java’s rules of etiquette tell you how you should name a package:

  • Reverse your company’s domain name.

    For example, my company’s domain name is allmycode.com. So, when I create a Java package, I start with com.allmycode.

    If you don’t have a company, or if your company doesn’t have a domain name, you can safely ignore this first rule.

  • Add a word that describes this particular package’s purpose.

    For example, I created a Java program to search for words in the user’s input, so this Java program went in my com.allmycode.wordsearch package.

Android takes Java’s package conventions one step further. In the Android world, a package contains the code for one and only one application. For example, I created a game named Hungry Burds, so my entire Hungry Burds game is in my com.allmycode.hungryburds package.

If you create many apps, keeping track of them all can drive you crazy. So it helps if you decide on a formula for naming your apps' packages, and then you stick to that formula as closely as you can.

crossreference For the technical story on Java packages and package names, see Book II, Chapter 2.

Your app’s API levels

In Chapter 3 of this minibook, you create a new app and you select a minimum SDK. The acronym SDK stands for the term Software Development Kit. Like most authors (and like the people who created Android Studio), I often use the acronyms SDK and API (application programming interface) interchangeably. An API level (also known as an SDK version) is a bunch of code that you call upon in your own Android programs. For example, in Listing 4-1, when you write

extends Activity

 

you’re referring to a bunch of code in Android’s SDK. This code is known as Android’s Activity class. In the same listing, when you write

setContentView(R.layout.activity_main)

 

you’re calling a bunch of code known as the setContentView method. All this code lives in Android’s SDK.

From time to time, the stewards of Android introduce improvements in the SDK. When they do, they mark the changes by creating a level number for the new and improved SDK. Level numbers increase as time goes on. That’s why, when you create a new project, you select a minimum API level (minimum SDK version) for your new project.

In Chapter 3 of this minibook, when you select a minimum SDK version, Android Studio records your selection in a build.gradle file. (Refer to Listing 4-6. In that listing, your selection becomes the minSdkVersion number.) If minSdkVersion were the only version number in Listing 4-6, then life would be simple and this chapter would be finished. But life isn’t so simple.

An Android app has several uses for API version numbers. For example, in Listing 4-6, the minSdkVersion is API 15, but the targetSdkVersion and compileSdkVersion numbers are both 21. What’s the deal with all these SDK version numbers?

You design an Android app to run on a range of API versions. You can think informally of the minimum SDK (minSdkVersion) as the lowest version in the range, and the target SDK (targetSdkVersion) as the pinpoint focus of the range. If you select API 15 as the minimum and select 21 as the target, you design your app to run on Ice Cream Sandwich (API level 15), Jelly Bean (levels 16, 17, and 18), KitKat (levels 19 and 20), and Lollipop (level 21). You also say that your app probably runs on API levels 22, 23, and so on.

These informal notions of “lowest version in the range” and “pinpoint focus” are okay. But what do they mean when the rubber meets the road? And for that matter, why do you even bother specifying a range of SDK versions? Why not say “Every Android user can run my app”?

Here’s the story: You can’t put any old 1969 car part on a 2014 car, and you certainly can’t put most 2014 car parts on an old 1969 car. In the same way, an app is as good as the system it runs on. My old Zenith Supersport computer (ca. 1990) had 5MB of memory and a 6 MHz processor. The Supersport can’t run Microsoft Word 2013. And, despite the kinship between older and newer Microsoft operating systems, many of the programs from the Supersport’s old disk drive don’t run on newer Windows versions. (By the way, the Windows compatibility troubleshooter has never helped me with this problem. Not even once!)

In the old days, a system’s underlying software was updated infrequently. When it was, users had to live with whatever consequences were caused by the change. But these days, changes in system software are fast and furious. Your computers and smartphones receive automatic updates over the network. To help you cope, software developers are mindful of compatibility. At the very least, a system update shouldn’t break an existing app. In other words, a system update can add new capabilities, but an update shouldn’t mess up older capabilities. (This principle about maintaining older capabilities is called backward compatibility. The term emphasizes the direction from new systems back to older software.)

Android’s official documentation reports that “… new versions of the platform are fully backward-compatible.” So an app that runs correctly on API level 21 should run correctly on all levels higher than 21. (I write “should run correctly” because in practice, full backward compatibility is difficult to achieve. Anyway, if the Android team is willing to promise full backward compatibility, I’m willing to take my chances.)

One of the ways Android keeps track of system updates is with the software’s API level. In November 2014, 30 percent of the world’s working Android devices had API level 19, but about 50 percent had API levels 16, 17, or 18 (various incarnations of Android Jelly Bean), and a small percentage (about 0.6 percent) still ran API level 8 (Froyo).* So, no matter what API level you use to compile your app, someone will probably try to run it on a device with a different API level. To face the API levels problem head-on, Android stores several level numbers in your app’s files.

Here’s what these level numbers mean:

  • The minimum SDK (midSdkVersion) is the lowest system on which your app is (pretty much) guaranteed to run.

    Imagine putting the following code in your app:

    SharedPreferences prefs =

      PreferenceManager.getDefaultSharedPreferences(this);

    SharedPreferences.Editor editor = prefs.edit();

    editor.putInt("amount", 100);

    editor.apply();

    In that last line of code, the word apply can cause trouble. Android didn’t use the word apply this way until API level 9. So, when you create your app, you better specify level 9 or higher as the minimum SDK.

    If you specify a minimum SDK level of 9, then when you publish your app on the Google Play Store, the store doesn’t offer the app to users whose devices run API level 8 or lower.

    An Android project’s minimum SDK number is normally in the project’s build.gradle file. For older projects (created before the Android Studio days), the minimum SDK number appears in the project’s AndroidManifest.xml file.

  • Another number, the maximum SDK (maxSdkVersion), is the highest system on which your app is guaranteed to run.

    Listing 4-6 has no maxSdkVersion and hardly anyone ever specifies a maximum SDK version for an Android project. In fact, the maximum SDK value is a feature that the stewards of Android probably wish they had never created. The Android documentation discourages the use of a maximum SDK version. The docs warn that a maximum SDK version might cause an app to be uninstalled when the app is still usable.

  • The compile SDK (compileSdkVersion) is the SDK version used to turn your Java code into code that’s ready to run.

    Put the earlier bullet’s editor.apply() code in your app, and in the build.gradle file, specify a compileSdkVersion of 8. Android Studio immediately displays an error message, because the level 8 SDK doesn’t understand this use of the word apply. (There’s no danger that you’ll run your app on a level 8 device because API level 8 can’t even compile your app.)

    Of course, you can try to sneak around the constraints by specifying level 8 as the minimum SDK and some higher level for the compile SDK. But then Android Studio warns you that you’re treading on very thin ice. When you test your app on an API Level 9 device, everything is ducky. But when you test your app on an API Level 8 device, the app crashes.

    An Android project’s compile SDK version number is in the project’s build.gradle file. You can change a project’s compile SDK version by changing the number in that build.gradle file. For an older app (created before Android Studio became part of the picture), you might find the compile SDK number in a project.properties or default.properties file.

  • The target SDK (targetSdkVersion) is the API level of the system on which you intend to test your app.

    This notion of intending to test your app is an elusive concept. If you’re a thorough developer, you test your app on many devices with many different API levels. Also, if a device or AVD with your app’s target SDK isn’t available, then Android Studio looks for another device that meets your app’s minimum SDK requirement.

    So the idea of a target SDK remains slippery. I’m sure that your IDE or your device uses this value somewhere in the app’s lifecycle, but I’m not convinced that you should think about the target SDK too much. Most websites devoted to Android tips and techniques tell you to make the target SDK the same as the compile SDK, and to leave it at that.

    An Android project’s target SDK number is in the project’s build.gradle file.

In addition to its backward compatibility concerns, Android has some forward compatibility features. An example of forward compatibility is when a system running API level 4 magically enters a time machine and runs an app with fragments — a feature that wasn’t created until API level 11. (I don’t know. Maybe an Android-enabled DeLorean can do this.)

In reality, forward compatibility in Android comes from things called support libraries. An Android library is an app that can’t run on its own. A library exists only to help another app do its duties. And a support library is a library that helps an older system deal gracefully with a newer app’s features. When you create a new project with fairly disparate minimum and target API levels, Android Studio adds a support library to your code. You often notice this when things named android.support and appcompat appear without warning as part of your code.

crossreference To read more about the ways Android keeps track of its versions, see Chapter 2 in this minibook. For more info on compilers, visit Book II, Chapter 2.

While I’m on the subject of versions numbers, I should describe the buildToolsVersion line in Listing 4-6. In spite of what I write elsewhere, remember that Android Studio is nothing but an IDE — a main window with a bunch of views, panels, tabs, and other visual aids. In its purest form, Android Studio doesn’t create an Android app. Android Studio simply provides an interface to you, the developer. This interface is a go-between to help you work with the real, underlying Android development tools — the tools that actually compose skeletal code, compile the code, run Gradle, bundle up the icons, and package the whole business into a single APK file.

Those underlying tools are the real workhorses of Android development, and the folks at Google strive continuously to improve those tools. That’s why, when you go to the main menu and choose Tools ⇒ Android ⇒ SDK Manager, you frequently see a check mark offering to update your Android SDK Build Tools software.

To help maintain compatibility, an Android Studio project keeps a record of the version of the tools that built the project. For the project that I describe in this chapter, the tools are Version 21.1.2. Your own first project is newer than the sample project in this chapter, so the project’s build tools version number is likely to be higher. With a different build tools version, you might see some slightly different code. The skeletal Java class in Listing 4-1 might have a few more lines in it. One way or another, Android’s basic principles apply to this chapter’s example and to your own examples as well.

Notes

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.42.129