Institute of Computer Science
  1. Courses
  2. 2019/20 fall
  3. Mobile Computing and Internet of Things (LTAT.06.009)
ET
Log in

Mobile Computing and Internet of Things 2019/20 fall

  • Main
  • Lectures
  • Labs
  • Homeworks & Home Assignments
  • Projects
    • Teams & Topics
    • Presentations & Report
    • Grading & Submission
  • Google Group
  • Task submission
  • Results
  • Other

Lab 6 - Background Threads, AsyncTask

Create a new Android Studio project with a blank MainActivity.

To get you started, copy the code from MainActivity.kt into your MainActivity and from main_activity.xml to your view XML.

The MainActivity UI has a Spinner (a dropdown), an ImageView, and 3 buttons. The code also takes of permission management for you.

Your task is to display a list of files in the applications external storage directory in the spinner. When a file is selected in the spinner, then clicking a button will show the file in the imageview, using different methods (depending on which button was pressed).

1. Setting up Spinner and Files

The below code should be written inside setUpFileSpinner() function

  1. To get the app-specific external storage folder for pictures, you can use
    • getExternalFilesDir(Environment.DIRECTORY_PICTURES), which returns a object of type File. (The same File type is used for both files & folders)
      • To do this, you need permission android.permission.READ_EXTERNAL_STORAGE in your manifest file
      • Until you call the getExternalFilesDir(..) above, this folder won't be created. After it gets created, initially, this folder will be empty. Push some image files to it using Android Studio's Device File explorer.
  • with the above File object, you can call list(), which returns a list of filenames
  • Assign the above two objects to the lateinit vars directory, fileNameList defined at the start of MainActivity.kt
  • It's a good idea to try and log the exact directory of the pictures folder, e.g. you can call getAbsolutePath() on File objects.
  1. We will attach the fileNameList to the spinner using an array adapter
    • Create an ArrayAdapter<String>, using 3 arguments:
      1. Activity context (this)
      2. The layout resource android.R.layout.simple_spinner_dropdown_item
      3. filename list object we acquired by calling list() above
    • Set the spinners adapter to the arrayAdapter
      • <<my_spinner_id>>.adapter = <<myAdapter>>

You should now be able to see files in your apps external Pictures folder appearing in the spinner

2. Loading image into ImageView

Let's first read the file and display it on the UI thread. inside setupMainThreadButton(), set a click listener to the button with id button_ui which:

  • gets the element from the fileNameList using spinner.selectedItemPosition as index
  • Creating a File object of the selected element by resolving the full path to the selected file with directory.resolve(fileName)

Now, we have the chosen picture file, let's read it from the storage.

  • Create a new function loadImage(), that takes as argument a File and returns a Bitmap - which is a class for representing images.
    • The file object can be read from storage into a Bitmap using BitmapFactory.decodeStream(<<myFile>>.inputStream())
    • Since very large images can cause crashes, let's scale the image down before returning it:
        val ratio = fullBitmap.width.toDouble() / fullBitmap.height
        val scaledBitmap = Bitmap.createScaledBitmap(fullBitmap, (800*ratio).toInt(), 800, false)
  • return the scaled bitmap.
  • Update the clickListener defined inside setupMainThreadButton() so that it passes the File to the loadImage() function.
  • Display the result of loadImage() in ImageView, using picture_view.setImageBitmap(bitmap)

Run the application and verify that you can see the picture appear in the ImageView

2.1 Running in background thread

Finish the code for setupWorkerThreadButton(), setting up a click listener for button button_worker, loading & displaying the image, except this time, call loadImage() inside a background thread.

  • Threads can be created with
    val myThread = Thread {
            // do some work
    }
  • To run the thread, you have to call start(), e.g. myThread.start()
  • To update the UI from inside the thread, you can use <<activityContext>>.runOnUiThread { // some work } or <<some_ui_view_object>>.post { // some work }

2.2 Running in AsyncTask

Finish the setupAsyncTaskButton(), which should set a clickHandler that runs an AsyncTask to load the image.

  • Define an inner class that extends AsyncTask. We are using type File for input of doInBackground(), and type Bitmap as the output of the background task, which in turn is used as input for onPostExecute()
    inner class MyAsyncTask : AsyncTask<File, Void, Bitmap>(){
        override fun doInBackground(vararg params: File?): Bitmap {
            // do work and return bitmap (asynctask runs this on background thread)
        }

        override fun onPostExecute(result: Bitmap?) {
            // display image in ui (this runs on ui thread)
        }
    }
  • Run the AsyncTask in the click handler by calling MyAsyncTask().execute(imgFile)
  • Institute of Computer Science
  • Faculty of Science and Technology
  • University of Tartu
In case of technical problems or questions write to:

Contact the course organizers with the organizational and course content questions.
The proprietary copyrights of educational materials belong to the University of Tartu. The use of educational materials is permitted for the purposes and under the conditions provided for in the copyright law for the free use of a work. When using educational materials, the user is obligated to give credit to the author of the educational materials.
The use of educational materials for other purposes is allowed only with the prior written consent of the University of Tartu.
Terms of use for the Courses environment