Table of Contents
This is a collection of notes I took during the Mobile Programming course at my University.
Project
The project needs to follow a specific structure to be compiled and packaged correctly by the Android Software Development Kit.
At a higher level, we subdivide it in modules, such as:
- Android application modules: with code, resources, and configurations. These will be transformed into an apk file that will be installed to devices.
- test modules: containing Junit tests.
- library modules: which are code shared with other projects. These will be included in the apk as well.
Files
build/
: application build artifacts.libs/
: private libraries.src/
: the source code.androidTest/
: Java tests.main/java/com.project.app
: Java code such as activities.main/assets/
: store for game assets.main/res/
: various resources.anim/
: XML files compiled into animation objects.color/
: XML files with colors.drawable/
: bitmap files (PNG, JPEG, GIF), 9-Patch, and XML describing drawables.mipmap/
: Application icons.layout/
: XML files compiled into layouts.menu/
: XML files defining menus.raw/
: for various assets, like mp3 or ogg files.values/
: XML files defining generic values.xml/
: other XML files.
AndroidManifest.xml
: main file describing the applications and all of its components.
.gitignore/
: files to be ignored from git versioning.app.iml/
: IntelliJ IDEA config file.build.gradle
: build config file.proguard-rules.pro
: ProGuard config file.
Localization
When the user launches an app, Android automatically selects and loads the right resources according to the device configuration.
In the res/values/string.xml
files are stored strings that are used by default, though it is possible to specify alternative resources using qualifiers for different languages.
For instance, to localize text content in italian, we need to create an alternative string.xml
file under the res/values-it/
folder.
Testing
It is possible to test our apps on an emulator or a reald Android device.
The number of smartphones on the market is huge and continuously growing. Nevertheless every device is different and deciding which ones to test could be challenging.
It would be ideal to support as much devices as possible. We could buy a certain number of devices and test our app under real conditions, but it would definitely be more expensive that using the emulator.
The emulator might not allow us to see how apps work on real devices, but it does not hurt from a financial perspective.
When developing on a device, it is still good practive to use the emulator to test our apps on configurations that are different than those of real devices available to us. Even though the emulator can not test all settings, it can verify that the apps work correctly on different Android versions, or screen size and orientations.
A mix between real device testing and emulator testing could guarantee a good test coverage at a reasonable price.
Layout
A layout is the visual structure of a user interface and it can be defined in two ways:
- XML: Android provides XML tags corresponding to classes of the View.
- Runtime: you can create View and ViewGroup objects programmatically.
We can use one or both methods to declare and manage the graphic interface of our application. For example, we could declare some layout in XML, and later add code to modify at runtime the state of the elements on the screen.
The benefit of using XML files is the separation between presentation and code controlling the behaviour of the application. The description of the user interface is external to the logic code, enabling us to modify it without needing to recompile. Moreover, declaring the layout in XML makes it easier to visualize the structure of the user interface and it simplifies debugging.
View
A View is basically a rectangle with width and height, and a position expressed as left and top. The unit is the pixel. We can also distinguish two pairs of width and height: measured width and height relative to its parent, and drawing width and height which define the size when drawing on screen.
Drawing a layout involves two steps: measure and layout. The measure step is implemented in measure(int, int)
which is a top-down traversal of the view-tree where their dimensions are calculated. The second step is implemented in layout(int, int, int, int)
, top-down as well, where every parent is responsible to move their children using values calculated during the measure step.
ViewGroup
Linear Layout
A linear layout is a ViewGroup which aligns their children horizontally or vertically (android:orientation
).
Relative Layout
A relative layout is a ViewGroup which shows children with relative positions relative to their siblings (left-of, below, …) or parent (bottom, left, center, …).
List View
A list view is a ViewGroup showing a list of elements. The elements are added automatically using an Adapter, which takes the content of a source, like an array or a database, and converts each element into a View to be inserted into the list.
Grid View
A grid view is a ViewGroup which shows a grid of elements which, as the list view, is populated through an Adapter.
Adapter View
When the content is dynamic, we can use an AdapterView subclass to populate it at runtime. An AdapterView subclass uses an Adapter, which behaves like a mediator between the data source and the layout. The Adapter receives data and converts each entry into a View that can be added to the layout.
Android provides some Adapter subclasses for some cases:
- ArrayAdapter: useful when the data source is an array. By default, it creates a View for every element of the array by calling
toString()
and puts it into a TextView.
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this, android.R.layout.simple_list_item1, myStringArray);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
- SimpleCursorAdapter: useful when data come from a Cursor.
Toast
A Toast provides a simple feedback for an operation in a little popup. It occupies only the spaces required by the message and the current Activity remains visible and interactive. Toasts vanishes automatically after a timeout. We can create them with the static method Toast.makeText()
, which takes three arguments (context, message and duration), and can show with the show()
method.
Toast.makeText(context, "text", Toast.LENGTH_SHORT)
We can position with the setGravity()
method which accepts three arguments (gravity constant, x offset, and y offset).
toast.setGravity(Gravity.TOP | Gravity.LEFT, 0, 0);
It is also possible to create a custom layout for toasts in XML and use it by passing it to the toast through the setView(View)
method.