Channels ▼
RSS

JVM Languages

Developing Android Apps with Scala and Scaloid: Part 2


In the first installment of this two-part series on developing Android Apps with Scala and Scaloid, I explained how Scaloid simplifies and reduces the required Android code as much as possible while leveraging type safety. In this article, I explain how to utilize asynchronous task processing, the execution of methods from system services, and specific Scaloid classes and traits.

Creating a Scaloid Project Based on a Template

The easiest way to start a new Scaloid project is to use one of the available template projects as a starting point. Following the instructions on how to do this can be difficult, so I provide some details on starting a successful Scaloid project with Maven. Scaloid also works with Scala's simple build tool (sbt although there were issues in previous versions.

First, you need to fork the Hello world of Scaloid for maven project from its GitHub repository. Then, open the pom.xml file, located in the root folder, and change the value of the target Android SDK platform from 8 to the API Level value of the Android Virtual Device you want to target. You can find the value in project -> build > plugins -> plugin -> configuration -> sdk -> platform. The following lines show the default value and the previous lines in the XML file:

...
	<build>
		<plugins>
			<plugin>
				<groupId>com.jayway.maven.plugins.android.generation2</groupId>
				<artifactId>android-maven-plugin</artifactId>
				<version>3.6.0</version>
				<configuration>
					<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
					<assetsDirectory>${project.basedir}/assets</assetsDirectory>
					<resourceDirectory>${project.basedir}/res</resourceDirectory>
					<nativeLibrariesDirectory>${project.basedir}/src/main/native</nativeLibrariesDirectory>
					<sdk>
						<platform>8</platform>
					</sdk>
...

The Android Virtual Device Manager displays the list of your existing virtual devices. Use the API level for one of your devices instead of the default 8. If you keep the 8 and you are working with a more modern API level, the build will fail. For example, Figure 1 shows a single entry in the Android Virtual Device Manager with an API Level equal to 18. In this case, it is necessary to replace 8 with 18, so both the build and deploy will work for that API Level installed in the Android SDK. Obviously, you will need to install and use the minimum API Level you want to support for your Android App.

Scaloid Part 2
Figure 1: The Android Virtual Device Manager displaying one virtual device with its API Level.

You can also check the minimum API Level installed in the Android SDK by checking the API value in the Android SDK Manager (see Figure 2).

Scaloid Part 2
Figure 2: The Android SDK Manager displaying the installed API Level, Android 4.3 (API 18).

The AndroidManifest.xml file specifies the main Scala class for the App that extends SActivity and the minimum required SDK version. Here again, you need to update the value for uses-sdk android:minSdkVersion to the minimum API Level you want to support. Notice that activity android:name="org.scaloid.hello.HelloScaloidActivity" specifies that the main activity is HelloScaloidActivity, located in the org.scaloid.hello package. The following lines show the edited version of the AndroidManifest.xml file in the Maven Scaloid template:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="org.scaloid.hello"
	android:versionCode="1"
	android:versionName="1.0-SNAPSHOT">

	<uses-sdk android:minSdkVersion="18" />

	<application android:label="@string/app_name">
		<activity android:name="org.scaloid.hello.HelloScaloidActivity">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
	</application>

</manifest>

As you might notice, the only difference with the AndroidManifest.xml file when you develop apps in Java is that the target class for each activity you define in the XML file is a Scala class instead of a Java class.

You can use the Maven call mvn clean package to build the project and generate the Android Application Package File, known as an APK, with the Android debug certificate. The build process runs Proguard to optimize the size of the final app.

After a successful build, you can use the mvn android:deploy Maven call to deploy the generated APK to all the devices connected with the Android Debug bridge.

If you work with the Scala IDE for Eclipse or just Eclipse, you can generate the project files for Eclipse with the mvn eclipse:eclipse Maven call (Figure 3).

Scaloid Part 2
Figure 3: The hello-scaloid-maven project structure in Eclipse, opened after Maven generated the project files for Eclipse.

Once you have the template project running on the Android device you use for debugging purposes, you can replace HelloScaloidActivity.scala with your new Scala file indicating your main activity. Then, you can make the necessary changes to the AndroidManifest.xml file with the activities definitions and the required permissions. This way, you can easily start a new Scaloid project.

Running Asynchronous Jobs and Notifying the UI

The Android API provides the android.os.AsyncTask helper class around Thread and Handler to enable you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers. Scaloid makes it easier to run a job with an asynchronous execution and notify the UI thread without using AsyncTask. You can combine the use of the runOnUiThread method to schedule the execution on the UI thread and scala.concurrent.ops.spawn to evaluate an expression asynchronously. Because Scaloid handles runOnUiThread for you in some methods (such as alert, toast and spinnerDialog), the code is even easier to read and understand.

The following lines define a runJob method that retrieves the contents of a URL and returns the first 10 lines as a string separated by \n. The method takes some time to retrieve the contents of the URL, so it is a great candidate for an asynchronous execution.

def runJob(uri: String): String = scala.io.Source.fromURL(uri).getLines().take(10).mkString("\n")

The following lines simulate a sign-in process that takes some time when you click the Sign In button. The code requires import scala.concurrent.ops._ because it uses spawn to call the runJob method with an asynchronous execution. Notice that the code is really easy to read because there aren't many different methods (which AsyncTask usage would require). The code displays a spinner dialog while the asynchronous job is running (see Figure 4), dismisses the dialog when it finishes, and shows an alert with the result of the runJob method (see Figure 5). There is no need to use the runOnUiThread method because both spinnerDialog and alert handle the execution on the UI thread for you. The spinnerDialog method reduces the code required to call ProgressDialog.show because Scaloid uses the implicit context I explained in the previous article. I've excluded exception handling to simplify the code.

SButton("Sign in").onClick({
  val progressDialog = spinnerDialog("Scaloid App", "Authentication in progress...")
  spawn {
      val result = runJob("http://drdobbs.com")
      progressDialog.dismiss()
      alert("Welcome to the Scaloid App. Check the results:", result)
  }
})

Scaloid Part 2
Figure 4: The App displaying the spinner dialog while an asynchronous job is retrieving contents from a URL.

Scaloid Part 2
Figure 5: The App displaying the results of the asynchronous job.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video