adb shell am kill com.example.android.myapp // Substitute the last String with the domain and name of your app
adb shell am kill com.example.android.myapp // Substitute the last String with the domain and name of your app
Customise the appearance of the action bar at the top of your app.
In our styles.xml file:
<style name="ActionBar.Solid.MyApp.NoTitle" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse"> // Create new style using existing template <item name="displayOptions">useLogo|showHome</item> // Add options <item name="logo">@drawable/ic_logo</item> // provide resources according to options selected </style> <style name="AppTheme.MyTheme" parent="@style/AppTheme"> // Create a style that uses the AppBar customisation above <item name="actionBarStyle">@style/ActionBar.Solid.MyApp.NoTitle</item> </style>In AndroidManifest.xml apply the style to the Activity whose appearance you wish to change:
<activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.MyTheme" // Point to your custom theme android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity>
Gives visual feedback when an item is pressed.
Start with an xml file to define a selector drawable. Right-click on res->New->Android Resource File, Resource type: Drawable, Root element: selector, then 'OK'. We've named this file 'list_item_selector.xml':
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/colorPrimaryLight" android:state_pressed="true" /> // Add all these states to cover the various selection possibilities <item android:drawable="@color/colorPrimaryLight" android:state_activated="true" /> <item android:drawable="@color/colorPrimaryLight" android:state_selected="true" /> <!-- This should have a default drawable color = "@android:color/background_light" --> // Default unselected state <item android:drawable="@android:color/background_light" /> </selector>In the example of a list item in a RecyclerView, go to the xml layout file for the list item and add the following to the root layout:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_item_selector "> // Add the selector xml file as the background ... </LinearLayout>
To cater for the wide variety of device specifications, we need to consider screen size and density.
These are the 5 most popular density buckets:
Density-independent pixels (dp’s) largely overcome these variations in density by making an image of e.g. 48dp look approximately the same physical size on all screens. **Make touch targets 48dp at least** However, you should supply a range of variations of each image to cater for the difference in density e.g. 48px:72px:96px:144px:192px in their appropriate folders to avoid placing unnecessary load on the processor and distorting the image, through scaling. To read more about how to cater for these go here.
For different screen layouts/orientations we can define individual xml files to cater for the variation in available space. Like the density buckets, you can place your layout files in the appropriately named folder and Android will use the layout that corresponds to its current configuration.
At runtime, Android will check the configuration of the device and choose the appropriate resources from the relevant folders accordingly. This is why it is necessary for Android to destroy and recreate Activities on screen rotation, as all of the resources within it could be completely different. Examples of folder variations:
values-fr/ – values for the French language
values-fr-rCA/ – values for the French-Canadian dialect
layout-desk/ – device is docked
layout-stylus/ – for device screens with stylus input
drawable-xhdpi/ – drawable resources for a xhdpi density screen
layout-land/ – landscape orientation
layout-sw720dp/ – minimum smallest screen width the layout will apply to
An example resource directory structure:
res/
layout/
activity_main.xml
detail_activity.xml
list_item.xml
layout-sw600dp/
detail_activity.xml
list_item.xml
layout-sw720dp/
list_item.xml
To create a smallest-width qualifier folder, right-click on res->New->Android Resource Directory, Resource type: layout, Available qualifiers: Smallest Screen Width, enter screen width (in dp), then ‘OK’. File names must be identical across folders to them to be overridden.
To efficiently utilise the space available in a landscape orientation, Android allows the defining of an alternative layout.
Create a new layout resource folder named 'layout-land' and copy your portrait xml layout file into it. Then simply edit the layout according to your preferences. If there are elements of your layout that will remain identical across portrait and landscape modes it makes sense to relocate them into their own layout files as outlined in this post.
The adaptation of a product or service to meet the needs of a particular language, culture or desired population’s “look-and-feel”.
1. Translation - you should always design your app in a way that can be easily translated to other languages. To do so, any text that you would expect to be translated like labels and titles and button descriptions should all be defined as a string resource in res/values/strings.xml. This allows you to create other versions of strings.xml for other languages. This is done by creating a new values folder with the pattern value-xx where xx can be the abbreviation of any language from the ISO 639 code list here, for example res/values-fr/strings.xml will contain the french version of the strings.xml file with all the strings translated from the default language to French. Label Strings you do not want to translate like so:
<string name="timeFormat" translatable="false">hh:mm a</string>2. RTL Support - if you’re distributing to countries where right-to-left (RTL) scripts are used (like Arabic or Hebrew), you should consider implementing support for RTL layouts and text display and editing, to the extent possible. By using the Start and End instead of Left and Right you make it possible for Android to reverse elements when necessary (if supporting API 16 or less include the Left and Right attributes as well):
android:layout_marginStart android:layout_marginEndWhen images with a directional context are used, allow Android to reflect them to maintain the relevance of the image:
<vector android:autoMirrored="true"> </vector>For more info on localisation click here.
See the recommendations here.
The most important is TalkBack which is a pre-installed screen reader service provided by Google. It uses spoken feedback to describe the results of actions such as launching an app, and events such as notifications.
You should include the following in your xml layout files to describe all ImageViews, ImageButtons and all Checkboxes:
<ImageView android:contentDescription="@string/origin_label"/>Others include:
A special Intent sent by the system when events occur on the phone. Examples include:
In order for your app to listen out for any of these System Broadcast Intents you will needs to set up a Broadcast Receiver.
A foreground service is a service that the user is actively aware of because Android requires it to post a non-dismissable ongoing notification. They are typically used to show the user the real-time progress of a long-running operation. Allows the user to perform basic interactions with your service. Examples would be playback controls in a music app or Google Maps navigation instructions.
Android will prioritise these even if the system is memory constrained.
Services are Android Framework components meant for running background tasks that don’t need a visual component, therefore they do not provide a User Interface (UI). An Activity can start a Service which can then continue to run, even after the Activity is shut down. They are ideal for loading and processing data in the background, regardless of whether any of the app’s Activities are open. A common example of this is how you can receive notifications when an app is not running.
A Service should be used when the task is decoupled from (does not directly affect) the UI, and needs to exist even when there is no UI.
There are 3 ways to start a Service:
A Service can be both STARTED and BOUND.
If you want to run a Service in a completely separate thread you can use an Intent Service.
The Lifecycle of a Started Service is depicted below:

Lifecycle has 2 interfaces:
LiveData is lifecycle aware because it is a Lifecycle Observer. This is why we feed in the LifecycleOwner (in this case the Activity) argument when we call the LiveData’s observer() method. LiveData will also know when the Activity is destroyed and automatically unsubscribe the Observers to prevent memory leaks.
To implement this without LiveData:
import ...
class MainActivity : AppCompatActivity() {
private lateinit var myClass: MyClass
// Contains all the views
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Use Data Binding to get reference to the views
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
myClass = MyClass(this.lifecycle) // Instantiate your observer class and pass in the Activity lifecycle (this.lifecycle) as the observed object
}
}
import ...
class MyClass(lifecycle: Lifecycle) : LifecycleObserver { // Set this class up as an observer
init {
lifecycle.addObserver(this) // Initialise the observer to the object passed in to the constructor
}
@OnLifecycleEvent(Lifecycle.Event.ON_START) // Choose a lifecycle event
fun startFunction() { // This function will be called on the lifecycle event specified
// Start something
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stopFunction() {
// Stop something
}
}
To add the desired elements of Android Jetpack to your app. These will need to be updated as the version numbers increment.
Use the following in your build.gradle: Futures
dependencies { def futures_version = "1.0.0-alpha02" implementation "androidx.concurrent:concurrent-futures:$futures_version" }Lifecycle AndroidX
dependencies { def lifecycle_version = "2.0.0" // ViewModel and LiveData implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" // alternatively - just ViewModel implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" // use -ktx for Kotlin // alternatively - just LiveData implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version" // alternatively - Lifecycles only (no ViewModel or LiveData). Some UI // AndroidX libraries use this lightweight import for Lifecycle implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version" annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // use kapt for Kotlin // alternately - if using Java8, use the following instead of lifecycle-compiler implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" // optional - ReactiveStreams support for LiveData implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version" // use -ktx for Kotlin // optional - Test helpers for LiveData testImplementation "androidx.arch.core:core-testing:$lifecycle_version" }Lifecycle pre-AndroidX
dependencies { def lifecycle_version = "1.1.1" // ViewModel and LiveData implementation "android.arch.lifecycle:extensions:$lifecycle_version" // alternatively - just ViewModel implementation "android.arch.lifecycle:viewmodel:$lifecycle_version" // use -ktx for Kotlin // alternatively - just LiveData implementation "android.arch.lifecycle:livedata:$lifecycle_version" // alternatively - Lifecycles only (no ViewModel or LiveData). // Support library depends on this lightweight import implementation "android.arch.lifecycle:runtime:$lifecycle_version" annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // use kapt for Kotlin // alternately - if using Java8, use the following instead of compiler implementation "android.arch.lifecycle:common-java8:$lifecycle_version" // optional - ReactiveStreams support for LiveData implementation "android.arch.lifecycle:reactivestreams:$lifecycle_version" // optional - Test helpers for LiveData testImplementation "android.arch.core:core-testing:$lifecycle_version" }Room AndroidX
dependencies { def room_version = "2.1.0-alpha03" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" // use kapt for Kotlin // optional - RxJava support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Coroutines support for Room implementation "androidx.room:room-coroutines:$room_version" // Test helpers testImplementation "androidx.room:room-testing:$room_version" }Room pre-AndroidX
dependencies { def room_version = "1.1.1" implementation "android.arch.persistence.room:runtime:$room_version" annotationProcessor "android.arch.persistence.room:compiler:$room_version" // use kapt for Kotlin // optional - RxJava support for Room implementation "android.arch.persistence.room:rxjava2:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "android.arch.persistence.room:guava:$room_version" // Test helpers testImplementation "android.arch.persistence.room:testing:$room_version" }Paging AndroidX
dependencies { def paging_version = "2.1.0-rc01" implementation "androidx.paging:paging-runtime:$paging_version" // use -ktx for Kotlin // alternatively - without Android dependencies for testing testImplementation "androidx.paging:paging-common:$paging_version" // use -ktx for Kotlin // optional - RxJava support implementation "androidx.paging:paging-rxjava2:$paging_version" // use -ktx for Kotlin }Paging pre-AndroidX
dependencies { def paging_version = "1.0.0" implementation "android.arch.paging:runtime:$paging_version" // alternatively - without Android dependencies for testing testImplementation "android.arch.paging:common:$paging_version" // optional - RxJava support implementation "android.arch.paging:rxjava2:$paging_version" }Navigation
dependencies { def nav_version = "1.0.0-alpha09" implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin }Work Manager
dependencies { def work_version = "1.0.0-beta02" implementation "android.arch.work:work-runtime:$work_version" // use -ktx for Kotlin+Coroutines // optional - RxJava2 support implementation "android.arch.work:work-rxjava2:$work_version" // optional - Test helpers androidTestImplementation "android.arch.work:work-testing:$work_version" }See more here
Room is one of the Android App Architecture Components. The Room persistence library (Object Relational Mapping library) provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite. It will map our database objects to Java objects.
Its features include:
Room uses Annotations and has 3 main components:
To add the dependencies for Room, see here.
The 4 main components of an Android app are:
Find the full definitions of these here

Activity lifecycle stages and their Callback names
Visible Lifecycle: The part of the Lifecycle between onStart and onStop when the Activity is visible.
Focus: An Activity is said to have focus when it’s the activity the user can interact with.
Foreground: When the activity is on screen.
Background: When the activity is fully off screen, it is considered in the background.
These are the same for both the Fragment Lifecycle and the Activity Lifecycle.
Initialized: This is the starting state whenever you make a new activity. This is a transient state — it immediately goes to Created.
Created: Activity has just been created, but it’s not visible and it doesn’t have focus (you’re not able to interact with it).
Started: Activity is visible but doesn’t have focus.
Resumed: The state of the activity when it is running. It’s visible and has focus.
Destroyed: Activity is destroyed. It can be ejected from memory at any point and should not be referenced or interacted with.
OnCreate: This is called the first time the activity starts and is therefore only called once during the lifecycle of the activity. It represents when the activity is created and initialized. The activity is not yet visible and you can’t interact with it. You must implement onCreate. In onCreate you should:
Inflate the activity’s UI, whether that’s using findViewById or databinding.
Initialize variables.
Do any other initialization that only happens once during the activity lifetime.
onStart: This is triggered when the activity is about to become visible. It can be called multiple times as the user navigates away from the activity and then back. Examples of the user “navigating away” are when they go to the home screen, or to a new activity in the app. At this point, the activity is not interactive. In onStart you should:
Start any sensors, animations or other procedures that need to start when the activity is visible.
onResume: This is triggered when the activity has focus and the user can interact with it. Here you should:
Start any sensors, animations or other procedures that need to start when the activity has focus (the activity the user is currently interacting with).
onPause: The mirror method to onResume. This method is called as soon as the activity loses focus and the user can’t interact with it. An activity can lose focus without fully disappearing from the screen (for example, when a dialog appears that partially obscures the activity). Here you should:
Stop any sensors, animations or other procedures that should not run when the activity doesn’t have focus and is partially obscured.
Keep execution fast. The next activity is not shown until this completes.
onStop: This is the mirror method to onStart. It is called when you can no longer see the activity. Here you should:
Stop any sensor, animations or other procedures that should not run when the activity is not on screen.
You can use this to persist (permanently save) data, which you’ll be learning more about in Lesson 6
Stop logic that updates the UI. This should not be running when the activity is off-screen; it’s a waste of resources.
There are also restrictions as soon as the app goes into the background, which is when all activities in your app are in the background. We’ll talk more about this in Lesson 9.
onDestroy: This is the mirror method to onCreate. It is called once when the activity is fully destroyed. This happens when you navigate back out of the activity (as in press the back button), or manually call finish(). It is your last chance to clean up resources associated with the activity. Here you should:
Tear down or release any resources that are related to the activity and are not automatically released for you. Forgetting to do this could cause a memory leak! Logic that refers to the activity or attempts to update the UI after the activity has been destroyed could crash the app!
Fragments also have lifecycle states that they go between. The lifecycle states are the same as the activity states. You’ll notice that in your Android Trivia app, you’re using the onCreateView callback – while the fragment lifecycle states are the same, the callbacks are different.
A deep dive into the fragment lifecycle could be a lesson in itself. Here, we’ll just cover the basics with the summary below:
onCreate: Similar to the Activity’s onCreate callback. This is when the fragment is created. This will only get called once. Here you should:
Initialise anything essential for you fragment.
DO NOT inflate XML, do that in onCreateView, when the system is first drawing the fragment NOT reference the activity, it is still being created. Do this in onActivityCreated.
onCreateView: This is called between onCreate and onActivityCreated. when the system will draw the fragment for the first time when the fragment becomes visible again. You must return a view in this callback if your fragment has a UI. Here you should:
Create your views by inflating your XML.
onStop: Very similar to Activity’s onStop. This callback is called when the user leaves your fragment. Here you should:
Save any permanent fragment state (this will be discussed in lesson 6)
onAttach: When the fragment is first attached to the activity. This is only called once during the lifecycle of the fragment.
onActivityCreated: Called when the activity onCreate method has returned and the activity has been initialized. If the fragment is added to an activity that’s already created, this still gets called. It’s purpose is to contain any code the requires the activity exists and it is called multiple times during the lifecycle of the fragment. Here you should:
Execute any code that requires an activity instance
onStart: Called right before the fragment is visible to the user.
onResume: When the activity resumes the fragment. This means the fragment is visible, has focus and is running.
onStop: Called when the Activity’s onStop is called. The fragment no longer has focus.
onDestroyView: Unlike activities, fragment views are destroyed every time they go off screen. This is called after the view is no longer visible.
Do not refer to views in this callback, since they are destroyed
onDestroy: Called when the Activity’s onDestroy is called.
onDetach: Called when the association between the fragment and the activity is destroyed.
What you’ve seen up to this point are the Activity Lifecycle and the Fragment Lifecycle for a single Activity or Fragment. For more complicated apps, it becomes important to understand the interactions between Activity and Fragment life cycles and multiple activities. This is outside of the scope of this lesson, but there are a series of excellent blog posts and cheat sheets posted by Googler which are helpful references for this:
The Android Lifecycle cheat sheet — part I: Single Activity – This is a visual recap of much of the material here.
The Android Lifecycle cheat sheet — part II: Multiple Activities – This shows the order of lifecycle calls when two activities interact.
The Android Lifecycle cheat sheet — part III: Fragments – This show the order of lifecycle calls when an activity and fragment interact.