CompileArtisan

Mobile Application Development

Table of Contents

1. Prelude

  • These notes don’t include Android Studio tutorials as:
    1. Graphical tutorials are a lot of effort
    2. Android Studio keeps evolving so it’s going to be different when you’re reading this.
  • Unlike most of my other notes, these should be used as complementary material. I really don’t think these notes can replace lectures or a course itself.

2. Introduction to Android

2.1. Why Android

Android is a mobile operating system based on the Linux Kernel, designed for touch screen devices. There are several reasons to use it such as:

2.1.1. Large Market Reach

It is used in 80% of the smartphones in the world.

2.1.2. Open Source

All of the code is open to the developers for customization.

2.1.3. Versatility

Android is used in smartphones, smart watches, TVs and cars.

2.1.4. Customizable

Vendors can tailor Android to specific hardware or user needs.

2.1.5. User Interaction

  1. Touch Gestures
    • Swiping
    • Tapping
    • Pinching
  2. Virtual Keyboard
    • Characters
    • Numbers
    • Emojis
  3. External
    • Bluetooth
    • USB controllers
    • Peripherals

2.2. Sensors that Android Uses

2.2.1. Accelerometer

  • Detects device orientation, motion and speed.

2.2.2. Gyroscope

  • Measures angular rotation.
  • Used in steering in games.

2.2.3. GPS/Location

  • Detects the user’s geographic position.

2.2.4. Proximity Sensor

  • Detects how close the user’s face is.
  • This disables the screen during phone calls.

2.3. Four Components of Android Application Development

2.3.1. Resources

  • This contains all static data which is to be separated from the code.
  • Includes:
    • XML Layouts (stored in res/layout/)
    • Strings
    • Images
    • Colors
    • Media Files

2.3.2. Components / Android Stack

  • These are the executable of an app.
  • These includes:
System Apps OR User Apps
Java API Framework
Native C/C++ Runtime OR Android Runtime (ART)
Hardware Abstraction Layer
Linux Kernel
  • Every layer in this stack, uses services of the layer below, to serve the layer above.
  • The linux kernel is responsible for low-level memory management and security features.
  • The kernel talks to the hardware directly, and hardware abstraction layer makes accessing hardware more abstract and standardized.
  • Native C/C++ libraries (Android Native Development Kit, or NDK) or Android Runtime (ART), do all the backend work involved in an app. These include managing databases, graphics, web rendering engines, and in basic system functions too.
  • The Java API Framework consists of premade classes which correspond to different parts of an app.

2.3.3. Manifest

  • A configuration file that the Android Runtime reads first.
  • This declares all of the components of the App.

2.3.4. Build Configuration (Gradle)

  • Manages dependencies and build settings using the .gradle config files.
  • It also manages APK (Android Package) versions.

2.4. Navigation

  • The back button on the bottom of the screen is called the temporal/back navigation button and that is controlled by the Android System’s back stack.
  • The left-arrow on the top-left of the screen is called the ancestral/up navigation button, and it’s provided by the app’s action bar.
  • Ancestral navigation is controlled by defining parent-child relationships between activities in the Android manifest.

2.5. Android Application Components

Component What it is
Activity A visible screen
Service Background work
Intent A message/request
BroadcastReceiver Listens to system level broadcast messages (like “battery low”)
ContentProvider Data Management

3. How the App works

3.1. Activity

3.1.1. What it is

  • A Java Class that serves as a controller for a specific screen, is called an activity.
  • Such a Java Class must extend Activity (basic activity lifecycle features provided here) or extend AppCompatActivity (this is preferred because modern Android features are backported to older versions too). AppCompatActivity extends FragmentActivity which extends ComponentActivity which extends Activity.
  • The screen that the app starts with, is controlled with the help of the MainActivity.java file.

3.1.2. Activity Life Cycle

  • It is a set of states an activity can be in during it’s lifetime, from when it is created until it is destroyed.
  • It’s a graph where the nodes are the states, the edges are the callbacks. activityStates.png
    • Created (not visible yet)
    • Started (visible)
    • Resume (In foreground and interactive)
    • Paused(partially invisible)
    • Stopped (hidden)
    • Destroyed (gone from memory)

3.2. Views

  • All of the components of the UI of a particular screen is created using an XML file or a group of XML files.
  • Such a component is called a view.
  • They’re the building blocks of the user interface.
  • Examples of views include TextView (for displaying text), EditText (for taking text input), RadioButton, Switch, SeekBar (sliders), etc.
  • Each view will have an id (an integer), which can be accessed in a Java Class as R.id.nameOfID, where R is a final class created by Android at build time.
  • An activity is connected to the XML layout because of a line that looks like:

    setContentView(R.layout.activity_main);
    

    where activity_main.xml is the name of the xml file.

  • Views have properties like:
    • Color, dimensions, positions (all static properties)
    • May have Focus
    • May be interactive
    • May be visible or not
    • May have relationship with other views.

3.2.1. How it looks like in XML

Let’s arbitrarily take the <TextView/> view and study its properties defined in XML.

<TextView
       android:id="@+id/nameOfID"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:background="@color/myBackgroundColor"
       android:text="@string/count_initial_value"
       android:textColor="@color/#0000aa"
       android:textSize="@dimen/count_text_size"
       android:gravity="center"
       android:textAlignment="center"
       android:textStyle="bold" 
       android:autoLink="web"
/>
  1. layout_width or layout_height
    Value Meaning
    wrap_content Only as tall/wide as the size of the text
    100dp Fixed width
    0dp Used with layout_weight or ConstraintLayout
    match_constraint ConstraintLayout only

    dp (density-independent pixels) are used for layout dimensions, while sp (scale-independent pixels) are used for text-sizes.

    All of these properties can be modified by changing the XML file, by changing things graphically on Android Studio, or by using the Java code.

  2. android:autoLink="web"

    You can make the content inside a TextView clickable, by specifying where it should take the user to after clicking.

    • web: Detects URLs like https://example.com or www.example.com and opens them in the browser when tapped.
    • email: Detects email addresses like user@gmail.com and opens the email client (mailto intent) when tapped.
    • phone: Detects phone numbers like +1-800-555-0199 and opens the dialer when tapped.
    • map: Detects addresses and opens them in Maps when tapped. This one is the least reliable — address detection is fuzzy and often misses or false-positives.
    • all: Enables all four of the above at once.

3.2.2. Three ways to define a view

  • The three ways to define a view is:
    • Graphically
    • Through XML
    • Programmatically
  • A constraint represents connection or alignment to another view.

3.2.3. ViewGroup

  • A ViewGroup is a type of View that can contain other Views.
  • You can see the View Hierarchy in the component tree.
    • Use the smallest number of simplest views
    • Keep the view hierarchy flat by limiting nesting of views.

3.2.4. Layout

  • Layout is a type of ViewGroup that are designed to position and arrange those views on the screen. view.png
  1. Creating Layouts using Java
    • We’ll use LinearLayout, which just puts items in a row or in a column. To create one and then set the direction, we use:

      LinearLayout x = new LinearLayout(this);
      x.setOrientation(LinearLayout.VERTICAL);
      
    • Let’s have a TextView inside the LinearLayout. To create the TextView:

      TextView tv = new TextView(this);
      tv.setText("hi loll");
      tv.setWidth(LayoutParams.MATCH_PARENT);
      tv.setMinLines(3);
      
    • To add the TextView inside the LinearLayout:

      x.addView(tv);
      setContentView(x);
      
    • To modify properties:

      LinearLayout.LayoutParams layoutParams = new Linear.LayoutParams(
                       LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT
                                                                      );
      x.setLayoutParams(layoutParams);
      

4. Basic Addition

  • This code follows from this video.
  • First declare private variables in the MainActivity class:

    private EditText num1, num2;
    private Button add;
    private TextView result;
    

    Make sure you do alt + enter when your mouse is over the EditText, Button or TextView datatype, to resolve all imports.

  • Next, in the end of onCreate() function, get all of views using their IDs R.id.idName, and then assign them to the private variables you created:

    num1 = (EditText) findViewById(R.id.no1);
    num2 = (EditText) findViewById(R.id.no2);
    result = (TextView) findViewById(R.id.result);
    add = (Button) findViewById(R.id.addButton);
    

    Before assigning, make sure you appropriately typecast the View.

  • To the button object add, use the setOnClickListener() method as add.setOnClickListener();. Inside, add a parameter that starts from new View and just pick the first suggestion (it’s most likely what we need). So the function will look like this:

    add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // here is where we do the logic
        }
    });
    
    
  • Use the setText method on the result TextView. It can only take a String, so typecast whatever you want to show using String.valueOf().

    add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            result.setText(String.valueOf(
                    Integer.parseInt(num1.getText().toString())
                    + Integer.parseInt(num2.getText().toString())
            ));
        }
    });
    
    

    Just try typing whatever is inside, all you need to do is tab your way through.

  • The complete app looks like this:

    public class MainActivity extends AppCompatActivity {
        // declare these variables
        private EditText num1, num2;
        private Button add;
        private TextView result;
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // some code already here, just add the below code
         
            num1 = (EditText) findViewById(R.id.no1);
            num2 = (EditText) findViewById(R.id.no2);
            result = (TextView) findViewById(R.id.result);
            add = (Button) findViewById(R.id.addButton);
            add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    result.setText(String.valueOf(
                            Integer.parseInt(num1.getText().toString())
                            + Integer.parseInt(num2.getText().toString())
                    ));
                }
            });
         
        }
    }
    

5. Intent

  • An Intent is an object used to request an action from another app component via the Android system.
  • It’s a message to the Android runtime to run an Activity.

5.1. Types of Intent

  • There are two types of intent: Explicit and Implicit

5.1.1. Explicit Intent

  • This is the intent used to transfer from one activity to another activity within an application.
  • Right click on the app and create a new activity (Android Studio will automatically create and link the XML file).
  • Trigger the new activity by setting onClick parameter of a button as the name of a function doSomething(), which is a void function defined in MainActivity.

    public void doSomething(View view){
        Intent intent = new Intent(this, Next.class);
        intent.putExtra("answer", String.valueOf(Integer.parseInt(someInput.getText().toString()) +100));
        // in case you're using data instead of extras (both explained later):
        // intent.setData(Uri.parse("http://www.google.com"));
        startActivity(intent);
    }
    
    

    where someInput is the id of an EditText object.

  • And in the new activity’s onCreate() function:

    Intent intent = getIntent();
    textView = (TextView) findViewById(R.id.textView);
    textView.setText(String.valueOf(intent.getStringExtra("answer")));
    
    

5.1.2. Implicit Intent

  • This is used to invoke an activity from another app.
  • Here the system is asked to find an activity that can handle this request.

5.2. Types of Sending data with Intents

Data Extras
Single piece of information represented by a URI Key-Value Pairs of Information

6. Scroll View

  • ScrollView makes a single child under it, vertically scrollable. For horizontal scrolling you’ll have to use HorizontalScrollView.
  • When you use scroll view, drag and drop a linear layout into the component tree, and then put whatever you want in there.
  • Drag and drop only into the component tree (bottom left corner, basically under palette), because all Views should be under the linear layout.

7. Spinner

  • Just add Spinner into the XML, and then in the onCreate() function:

    List<String> spinnerList = new ArrayList<>();
    spinnerList.add("Item 1");
    spinnerList.add("Item 2");
    spinnerList.add("Item 3");
    spinnerList.add("Item 4");
    
    Spinner spinner = findViewById(R.id.spinner);
    
    ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, spinnerList);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    

8. Feedback app

8.1. RatingBar

  • You get the rating as:

    float rating = ratingBar.getRating();
    

8.2. Radio Button

  • Given:

    difficulty = findViewById(R.id.difficulty);
    

    then the selected radio button is obtained through the id (int):

    int selectedId = difficulty.getCheckedRadioButtonId();
    

8.3. CheckBox

recommendCheckBox = findViewById(R.id.recommend);

You check if it’s checked or not by the boolean return value:

boolean recommend = recommendCheckBox.isChecked();

8.4. Making a WebSearch Button

Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, topic);
startActivity(intent);
  • The ACTION_WEB_SEARCH parameter passed to the Intent constructor is actually a string defined like this:

    public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
    

8.5. Solving Data Loss after Screen Rotation

8.5.1. What happens when screen rotates

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        // the below line is what you add
        outState.putString("topic", feedbackTopic.getText().toString());
    }

When you rotate the screen, the state of an activity is destroyed. This is the function that’s called just before the activity is destroyed.

8.5.2. What happens after screen rotates

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // the below line is what you add
        feedbackTopic.setText(savedInstanceState.getString("topic"));
    }

This is the function that is called when the activity is recreated after the screen rotates.