Android Wiki
This article is part of my personal wiki where I write personal notes while I am learning new technologies. You are welcome to use it for your own learning!
I have taken most of this notes as I’ve been tinkering with Android following the different articles in Android’s developer documentation
Getting Started with Android
- Download Android Studio
- Create a project with an empty activity.
When you create a basic project you have:
MainActivity
which contains the main activity of your app. Each part on an app typically maps to an activity in Android terms.activity_main.xml
which represents the view or UI for that activityAndroidManifest.xml
which describes your app and its components- Two
build.gradle
files, one for the project and one for theapp
module. Each module has its ownbuild.gradle
file. You’ll typically configure the module’sbuild.gradle
file to configure how your app gets built. More info
Creating a Basic Hello World
We’ll start by creating a basic hello world that will consist of a TextBox
and a button. When you click on a button we’ll show a dialog that will say Hello whatever_you_type
.
The UI of Android apps resemble a tree of layouts and widgets. Layouts are ViewGroup
objects that can contain other layouts or widgets (View
objects). Layout are just invisible containers used to lay out child views on the screen. These child views can be other layouts or widgets which represent actual visible elements on the screen like text or buttons. They way in which we represent this hierarchy of layouts and widget is through XML.
If you open your main layout file activity_mail.xml
you’ll be able to see that you have a simple UI defined by the following xml code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.vintharas.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Which means that your UI is composed of two items:
- A layout of type
ConstraintLayout
- A
TextView
(a view that shows some text) with the text Hello world
The ConstraintLayout
is a new type of layout that allows you to set the position of a child view based on constraints in relation to the parent layout and sibling view. This type of layout allows you to reduce the complexity in your views by reducing the number of nested layouts you need to create a UI.
Remove the TextView
from your UI and we’ll start by adding an EditText
widget that will allow us to introduce our own input. You can type in the XML element directly and you’ll get help from Android Studio:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Or alternative you can use the WYSIWG editor and drag and drop a “Plain Text” widget. This last option is pretty nice because it’s a great way to find out about the attributes that you can use. For instance, if I drag and drop the component in the UI it will result in the following code:
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
tools:layout_editor_absoluteX="31dp"
tools:layout_editor_absoluteY="16dp" />
The tools:layout_editor_absoluteX="31dp"
and tools:layout_editor_absoluteY="16dp"
reflect the place where I dropped the TextView
. What we want to do instead is to take advantage of the constraints available to this special layout. We can use the designer to achieve that:
- Click on the
TextView
to select it, - You’ll see circle appears on each border of the input,
- if you drag and drop to a border of the layout you’ll create a constraint
You can do that or type:
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
android:layout_marginLeft="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp" />
As you can see from the last 4 attributes we have setup two constraints for the TextView:
- The left border of the input is
16dp
from the left border of the layout - The top border of the input is
16dp
from the top border of the layout
Next we add a button and we setup the following constraints:
- Let the button be
16dp
to the right of the text input - Set a constraint to align the baseline (the text) of these two widgets
Now we have a UI with a EditText
and a Button
that should look like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.vintharas.myapplication.MainActivity">
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
android:layout_marginLeft="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintLeft_toRightOf="@+id/editText"
android:layout_marginLeft="16dp"
app:layout_constraintBaseline_toBaselineOf="@+id/editText" />
</android.support.constraint.ConstraintLayout>
The next step is to write suitable messages to invite the user to type his name:
- The input should say
Type your name
- The button should say
Say hello!
You can update the directly using the android:text
attribute like this:
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Type your name"
android:layout_marginLeft="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp" />
A better way to do it is to collect all the strings within your application within a resource file, that is, a file that contains key/value pairs to identify and collect all the user facing strings of your application. Think of it as a way to remove string duplication from your app, adding an extra level of indirection that allows you to update text faster, translate to different languages, etc.
The way you handle this in Android is via xml resource files. The default app that we created has such a file created from the beginning named strings.xml
:
<resources>
<string name="app_name">My Application</string>
</resources>
We can add a couple of new strings here:
<resources>
<string name="app_name">My Application</string>
<string name="edit_name">Type your name</string>
<string name="button_say_hello">Say hello!</string>
</resources>
And now we can refer to them in our UI xml file. You can either use the designer and select the appropriate text or use the following convention within the xml:
<EditText
android:text="@string/edit_name"
// etc
/>
That is, @string/edit_name
where the string
refers to the type of resource and the edit_name
is the key that identifies the resource.
The next step is to wire everything up so when we click on the button something happens. In order to do that we will update the code of our MainActivity
to include a new sayHi
method that will contain the logic needed to:
- get text typed into input
- display Hello whatever you typed in a new activity
This method will look like this:
package com.vintharas.myapplication;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
public static final String SAY_HI_MESSAGE = "com.vintharas.myapplication.SAY_HI_MESSAGE";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void sayHi(View view){
// create intent that represents our "intent"
// to launch another activity
Intent intent = new Intent(this, SayHiActivity.class);
// Get text we wrote in the input
EditText editText = (EditText) findViewById(R.id.editText);
String name = editText.getText().toString();
// add text as part of the intent
intent.putExtra(SAY_HI_MESSAGE, "Hello " + name + "!" );
// start activity using the intent we just created
startActivity(intent);
}
}
We can break it down as follows: First we create an intent that represents our intent to launch another activity that will contain the message we want to display Hello XXXXX
:
// create intent that represents our "intent"
// to launch another activity
Intent intent = new Intent(this, SayHiActivity.class);
Then we obtain the text the user typed in the text input by:
- Getting a reference to the input using
findViewById
- Using the
getText
method on the input to get the actual text
EditText editText = (EditText) findViewById(R.id.editText);
String name = editText.getText().toString();
After that we add that information to the intent
we created earlier as an extra and launch the new activity:
// add text as part of the intent
intent.putExtra(SAY_HI_MESSAGE, "Hello " + name + "!" );
// start activity using the intent we just created
startActivity(intent);
Now we have a sayHi
method that can launch a new activity with the Hello XXXX message but it isn’t connected to anything, that is, it doesn’t matter how many times we click on the button nothing will happen because we haven’t connected the sayHi
method with the button. We can connect both together using the designer, select the button, look for an onClick
handler and select the sayHi
method. Now when you click on the button the MainActivity
will execute the sayHi
method.
There’s one thing remaining though, we don’t have a SayHiActivity
yet. We can create it using File -> New -> Android -> Activity
. Select Empty Activity, name it SayHiActivity
and place a TextView
in it. Update the code of the new activity to the following and we’re done!
package com.vintharas.myapplication;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class SayHiActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_say_hi);
// Get intent that started this activity
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.SAY_HI_MESSAGE);
// Show message
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(message);
}
}
Or we’re almost done. If you run the example you’ll be able to see that you can click on the button, see the message and… that’s it. You’re trapped for eternity seeing the message and can’t go back to the original view. How can you fix that? You can update your android manifest to include the following information for the SayHiActivity
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.vintharas.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- HERE !!!!! -->
<!-- the parentActivityName is the bit we're interested in -->
<activity android:name=".SayHiActivity"
android:parentActivityName=".MainActivity">
<!-- The meta-data tag is required if you support API level 15 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
</application>
</manifest>
How to Support Different Devices, Sizes, Form Factors, Locales?
The Android ecosystem is huge! There’s multitude of devices with very different sizes, form factors and features, and it’s widely used throughout the world in very disparate locales. This means that there’s a lot of things that you need to take into consideration when developing your app.
Supporting Different Locales
In the previous sample app you saw how we extracted the strings within our app into a resource file called strings.xml
. This is a great practice for localizing your apps (making them available in different languages).
To add support for diverse locales you create additional directories within the res
folder for each separate locale using a naming convention:
<resource type>-b+<language code>[+<country code>]
For instance, the equivalent for the values
folder that contains the strings.xml
resource file for swedish would be:
values-b+SV
As you saw in our previous example app, you can get access to these resources in different ways depending on whether you’re writing code or XML:
- in code by using
R.<resource type>.<resource key>
(for instanceR.id.editText
) - in XML by using
@<resource type>/<resource key>
(for instance@string/edit_name
)
You can find more information about localizing your in the Android developer documentation
Supporting Different Screen Sizes
TODO
Supporting Different Versions of Android
TODO
Building Dynamic UIs with Fragments
*Fragments represent a behavior or a portion of user interface in an Activity. You can think of them as a modular section within an activity or a sub-activity that you can reuse across different activities. They have their own lifecycle and their own input events. If you have a web development background, it is useful to think of Fragments as web components.
You can find more information in the Android developer documentation with sample code
Developing Apps with Data
TODO
References
Written by Jaime González García , dad, husband, software engineer, ux designer, amateur pixel artist, tinkerer and master of the arcane arts. You can also find him on Twitter jabbering about random stuff.