Open menu with table of contents Android Framework Basics
Logo of Stuttgart Media University for light theme Logo of Stuttgart Media University for dark theme
Android Development

Android Framework Basics

Stuttgart Media University

1 Agenda

  • Framework Components Part I
  • Activities & Intents
    • Activity
    • Intent
  • Android Security & Permissions
    • OS Security Concepts
    • Permissions
  • Framework Components Part II
    • The WebView
    • Progressbar

2 Framework Components Part I

The most important Android components:

  • Activity: The visible part of your app, displaying View objects
  • Fragment: Allows flexible modularisation of Views within Activities
  • Service: Runs code in the background without a View
  • ContentProvider: Provides data for your app
  • BroadcastReceiver: Used to receive messages between activies or even apps
  • Intent: Allows inter-component communication, used e.g. to start Activities and transfer information between them

3 Activities & Intents

4 Activity

  • Apps can have multiple Activities
  • One Activity defines one visible screen and can contain other View components or Fragments
  • Contains business logic (hint: Controller of the Model-View-Controller pattern)
  • Define the Lifecycle of the app

4.1 Activity Lifecycle

center

4.2 Activity Lifecycle

An activity has essentially four states:

  • If an activity is in the foreground of the screen (at the top of the stack), it is active or running.
  • If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your activity), it is paused. A paused activity is completely alive (it maintains all state and member information and remains attached to the window manager), but can be killed by the system in extreme low memory situations.
  • If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however, it is no longer visible to the user so its window is hidden and it will often be killed by the system when memory is needed elsewhere.
  • If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process (it is finished or killed). When it is displayed again to the user, it must be completely restarted and restored to its previous state.

4.3 Activity Class

  • The Activity extends Context and provides the lifecycle methods
  • In order to react on lifecycle state changes, override these methods
class Activity : Context() {
  protected fun onCreate(savedInstanceState: Bundle?)
  
  protected fun onStart()
  
  protected fun onRestart()
  
  protected fun onResume()
  
  protected fun onPause()
  
  protected fun onStop()
  
  protected fun onDestroy()
}

4.4 Activity Class Example

class MainActivity : AppCompatActivity() {
    
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    ...
  }

  ...
}

5 Application Context

  • The Context class provides an Interface to global information about an application environment
  • This is an abstract class whose implementation is provided by the Android system
  • It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc. For example:
// launches a new activity
abstract void startActivity(Intent intent) 

//launches a new service
abstract ComponentName startService(Intent service) 

//Registers a BroadCast Receiver
abstract Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) 

6 Intent

  • An Intent is an abstract description of an operation to be performed
  • It can be used
    • to start an activity (implicitly or explicitly)
    • as broadcast to inform other applications of events
    • to start, stop and communicate with services
    • to access data from content providers

6.1 Two Types of Intents

  • Explicit intents specify the component to start by name (the fully-qualified class name).
  • Implicit intents do not name a specific component, but instead declare a general action to perform, which allows a component from another app to handle it

6.2 Implicit Intent

  • An implicit intent specifies an action that can invoke any app on the device able to perform the action
  • The action might require some specific data
  • Using an implicit intent is useful when your app cannot perform the action, but other apps probably can and you'd like the user to pick which app to use
  • Example for an implicit Intent to dial a number (more examples here)
val dialIntent = Intent()
dialIntent.action = Intent.ACTION_DIAL //specifiy the action to execute
dialIntent.data = Uri.parse("tel:0711-1234") //provide action data
startActivity(dialIntent)

6.3 Implicit Intent

center

  1. Activity A creates an Intent with an action description and passes it to startActivity()
  2. The Android System searches all apps for an intent filter that matches the intent
  3. When a match is found, the system starts the matching activity (Activity B) by invoking its onCreate() method and passing it the Intent.

6.4 Intent Filter

  • To advertise which implicit intents your app can receive, declare one or more intent filters for each of your app components with an <intent-filter> element in your manifest file.
  • Each intent filter specifies the type of intents it accepts based on the intent's action, data, and category.
  • The system delivers an implicit intent to your app component only if the intent can pass through one of your intent filters.

6.5 Intent Filter

  • Each intent filter is defined by an <intent-filter> element in the app's manifest file, nested in the corresponding app component (such as an <activity> element).
  • Inside the <intent-filter>, you can specify the type of intents to accept using one or more of these three elements:
    • <action> - Declares the intent action accepted, in the name attribute. The value must be the literal string value of an action, not the class constant.
    • <data> - Declares the type of data accepted, using one or more attributes that specify various aspects of the data URI (scheme, host, port, path) and MIME type.
    • <category> - Declares the intent category accepted, in the name attribute. The value must be the literal string value of an action, not the class constant.

6.6 Intent Filter

<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Note: To receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter.

6.7 Explicit Intent

  • Explicitly name the class of the component to be called
  • To transfer additional information from one activity to another, the putExtra() method of the Intent class can be used
    • Extras are key-value pairs of certain types, such as Strings, Booleans, etc.
  • Example:
val intent = Intent(applicationContext, LoginActivity::class.java)
intent.putExtra("Name", "Login")
startActivity(intent)

Note: An explicit intent is always delivered to its target, regardless of any intent filters the component declares.

7 Android Assignment 1

8 Android Security & Permissions

8.1 Android Security Architecture: Basic Principles

  • Install time verification

    • APK files are verified at install time, by e.g. verification agents
  • Application sandboxing (process separation)

    • Each application runs in its own process (VM)
    • Only has (write) access to its own data
    • Other than own resources are only available through defined interfaces (using Intents)
    • Has its own unique Linux User ID
    • UID sharing only with same developer signature
  • Permissions

    • Access to critical permissions are granted by the user
      • At install time (Android version < 5, API level 22 and smaller)
      • During runtime (Android verions > 6, API level 23 and greater)

8.2 Android Permissions

  • Applications by default have no permission to perform operations that might impact other applications
  • Critical permissions needed must be explicitly declared in AndroidManifest.xml
  • Predefined permissions exist, e.g. INTERNET, READ_CONTACTS,...
  • Permissions are checked at runtime, escalation of access violation into the framework using SecurityExceptions

8.4 Android Permissions Declaration

  • To make use of protected features of the device, the <uses-permission> tags app manifest must be used
  • For example, an app that needs to monitor incoming SMS messages would specify:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.app.myapp" >
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    ...
</manifest>

8.5 Android Permissions Declaration

  • Since API level 23 (Android 6.0) of the SDK users need to grant permissions to an app while it is running, not only during installation
  • The folowing are the most common protection levels:
    • Normal permission - do not risk the user’s privacy - permission is listed in manifest and granted on installation
    • Dangerous permission - app can access user’s confidential data - user is asked for approval during runtime
  • Both types of permissions need to be declared in manifest and for dangerous permissions the app needs to request access during runtime
  • Users can revoke a permission any time in the OS settings
    • Make sure that you handle this in your app!

8.6 Requesting Permissions at Runtime

To request a dangerous permission at runtime, some additional code is required in your Activity class:

  • First check, if you have a permission by calling:
// Assume thisActivity is the current activity
val permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR)

8.7 Requesting Permissions at Runtime

  • If the permission was not granted before, then the user will be shown an system dialog that asks him, if he is willing to grant the permission, as soon as it is requested.
  • So, before requesting the permission, it should be explained to the user why the app needs it:
// ...
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(
        thisActivity,
        Manifest.permission.READ_CONTACTS)
) {
    // Show an explanation to the user *asynchronously* -- don't block
    // this thread waiting for the user's response! After the user
    // sees the explanation, try again to request the permission.
} else {
    // ... see next slide

8.8 Requesting Permissions at Runtime

  • Now, after explaining the user, why the app needs the permission, it can be requested by calling:
// ...
else {
    // No explanation needed, we can request the permission.

    ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant. The callback method gets the
    // result of the request.
}
// ...
  • The user is then shown a system dialog, asking to grant the permission

8.9 Requesting Permissions at Runtime

  • The permission request returns in an asynchronous callback (handler). In order to handle the permission request the following method needs to be overridden:
fun onRequestPermissionsResult(
  requestCode: Int,
  permissions: Array<String?>?, grantResults: IntArray
) {
  when (requestCode) {
    MY_PERMISSIONS_REQUEST_READ_CONTACTS -> {

      // If request is cancelled, the result arrays are empty.
      if (grantResults.size > 0
        && grantResults[0] == PackageManager.PERMISSION_GRANTED
      ) {
        // permission was granted, yay! Do the
        // contacts-related task you need to do.
      } else {
        // permission denied, boo! Disable the
        // functionality that depends on this permission.
      }
      return
    }
  }
}

9 Framework Components Part II

9.1 WebView

  • WebView class: android.webkit.WebView
  • Allows to load and view webpages
  • A browser activity can be started in a new Activity using an implicit Intent:
val uri = Uri.parse("https://www.google.com")
val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent)
  • But you can also embedd a WebView into your own app

9.2 WebView

  • Add the component to your layout:
<WebView
    android:id="@+id/webView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
  • Load a web page into the WebView using:
val myWebView = findViewById(R.id.webView1) as WebView
myWebView.loadUrl("https://www.google.com")

9.3 WebView

  • Requires the Internet Permission in the AndroidManifest.xml in order to access the Internet:
<uses-permission android:name="android.permission.INTERNET" />

9.4 WebView

  • When clicking on a link in the WebView, the default behavior is for Android to launch an application that handles URLs (usually the default web browser)
  • To change this you will need to provide your own WebViewClient implementation, e.g.:
myWebView.webViewClient = object : WebViewClient() {}
  • JavaScript is by default disabled (for security reasons). To enable this, you can use the WebViews settings:
myWebView.getSettings().setJavaScriptEnabled(true);

9.5 ProgressBar

  • The WebView loads websites asynchronously in the background
  • In order to get informed about the loading progress you can register a subclass of the WebChromeClient like this:
val myWebView = findViewById(R.id.webView1) as WebView
myWebView.webChromeClient = object : WebChromeClient() {
  override fun onProgressChanged(view: WebView, progress: Int) {
    val bar = findViewById(R.id.progressBar) as ProgressBar
    bar.progress = progress
  }
}
  • Add a progressbar to the layout in order to show the progress:
<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Note: A progress bar can be used for other purposes too of course.

10 Summary

  • Activities are the „Views“ of your application
  • You can switch between views using Intents
  • Intents can be used to start external views as well
  • A WebView allows to load and present web content
  • Use a progress bar to indicate that something is loading in the background
  • Permissions are required in order to do certain tasks, e.g. loading data from the Internet
  • Permissions are checked at install time

11 Recap Questions

  • What lifecycle states for an app exist?
    • Can you name some of the lifecycle methods of an activity?
  • What types of intents exist? What is the difference?
  • How can you transfer information from one activity to another?
  • How do you start another activity?
  • How does Android prohibit access of apps to other resources than it's own?
  • How can an app access data of another app on Android?
  • What types of permissions exist?
  • Where do you have to request a permission and how do you do it?
  • How can you prohibit a WebView to open URIs the user clicks on?
  • Why does Android by default open URI's in the system browser an not in the WebView?