Skip to main content

01 - Android Intro

Topics

  • Android overview
  • Basic Android Studio usage
  • Kotlin language
  • UI creation
  • App lifecycle and state
  • Local storage and data access (SQLite)
  • Sensors (proximity, geomagnetic, motion, GPS, …)
  • Web services (REST API)
  • Modern architecture

Android

Operating system, devised for mobile equipment (mostly)

Usage: phones, tablets, TV-s, watches, glasses, cars, laptops, cameras, game consoles, …

Market share among smartphones – ca 85% (iOS 14%)

Open-source project

Google apps and services are closed source (mail, map, etc.)

History

  • 2003 – founded (lead: Andy Rubin)
    • Initial idea – OS for cameras
    • New plan – Mobile OS, (others: Symbian/Nokia and Win Mobile)
  • 2005 – Google acquires the whole project
  • 2007 – Open Handset Alliance
    • Google, HTC, Sony, Samsung, Dell, Motorola, LG, Qualcomm, Intel, etc…
  • 2008 – Android 1.0 (HTC Dream, no touchscreen)
  • 2009 – Android 1.5 Cupcake (iPhone 2007, iPhone 3G 2008)
  • 2010 – Android 2.2 Froyo, 2.3 Gingerbread
  • 2011 – Android 3.0 Honeycomb (tablets only)
  • 2011 - Android 4.0 Ice Cream Sandwich
    • HOLO UI
  • 2014 - Android 5 Lollipop
    • Material design
    • Dalvik vs ART (Android Runtime) (JIT or precompile, garbage collection)
  • 2015 - Android 6 Marshmallow
  • 2016 – Android 7 Nougat
  • 2017 – Android 8 Oreo
  • 2018 – Android 9 Pie
  • 2019 – Android 10 Q – moves closer to iOS, security clamped down

Version distribution

2020

  • Pie – 9.X – 10%
  • Oreo – 8.X – 28%
  • Nougat – 7.X - 19%
  • Marshmallow – 6.X – 17%
  • Lollipop - 5.X – 14%
  • KitKat – 4.4 – 7%
  • 4.4 and higher - ca 95%

Market

Latest info (2024 fall)

  • 22 LolliPop 99.6%
  • 23 Nougat 98.8%
  • 27 Oreo 93.9%
  • 28 Pie 89.6%
  • 29 Android 10 81.2%
  • 30 Android 11 67.6%
  • 31 Android 12 48.6%
  • 33 Android 13 33.9%
  • 34 Android 14 13.0%

Android Architecture

Market

App types

  • NDK - C/C++
    • Close to hardware and operating system
  • SDK - Native <- this course!!!!
    • Kotlin/Java (ART/Dalvik), using system libraries
  • Hybrid – React Native, Ionic, etc.
  • Cross platform – Xamarin (C#), Flutter (Dart), React Native, etc.
  • Html/JS – Progressive Web Apps
    • One codebase/layout for different platforms
    • Problems with UI, weak access to hardware
  • There is also course on Hybrid Mobile Apps - ICD0018 (fall semester)

App architecture - AndroidManifest.xml

  • The manifest file presents essential information about your app to the Android system, information the system must have before it can run any of the app's code.
  • Describes the components of the application — the activities, services, broadcast receivers, and content providers that the application is composed of.
  • Declares which permissions the application must have in order to access protected parts of the API and interact with other applications.
  • Declares hardware requirements.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Test01"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

App architecture - build.gradle (app)

  • Declares the minimum level of the Android API that the application requires (minSdk).
  • Additional libraries (dependencies)
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}

android {
namespace = "ee.taltech.test01"
compileSdk = 34

defaultConfig {
applicationId = "ee.taltech.test01"
minSdk = 27
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}

App code

  • MainActivity.kt
package ee.taltech.test01

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
}
}
  • actvity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • UI generated from XML

Market

Other resources

  • Images
  • Animations
  • Menu
  • Strings
  • Misc files

APK

  • Android Application Package
  • ZIP file, combines all the resources and java bytecode
  • Signed with developer key
  • Developer key must be the same from version to next version
    • Don’t lose your keys (passwords)
  • Android Studio takes care of APK creation
  • APK-s can be downloaded from store, using 3-rd party utilities
  • Resources can be used as is
  • Most elements/code can be decompiled/recompiled

Google Play - app store

  • Almost no review process
  • Problems are dealt with afterwards
  • App hijacking, etc. are real problems

App security

  • Every app works in its own private virtual machine (Zygote)
  • Need permission for system resources/hardware
    • confirmed on app install
    • reconfirmed when app has not been used for some time
  • Data is private, no other app can access directly other app data
  • Everything is possible on rooted device
  • End user is the weakest link

Developer problems

  • Gazillion different hardware devices and capabilities
  • Lots of different Android implementations
    • Samsung TouchWiz
    • HTC Sense
    • ...
  • Migration to newer versions very slow (or not done at all)
  • Rooted phones
  • Ca 2X time spent on development compared to iOS
  • Ca 60% better income on iOS

Testing on devices

Market Market

Device variability

Market Market

Other hardware

Market Market Market Market Market

Hands on demo time - Notes

findViewById vs
Add kotlin-android-extensions to build.gradle (deprecated) for initial view elemnts to code binding.

plugins {
id 'com.android.application'
id 'kotlin-android'
}

apply plugin: 'kotlin-android-extensions'

Remove virtual keyboard from screen when done with it

fun buttonGreetClicked(view: View) {
textViewGreeting.text = "Hello, " + editTextName.text + "!"
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus()?.windowToken, 0)
}