├── README.md
├── build.sbt
├── linux_install_sdk.sh
├── mac_install_sdk.sh
├── project
├── Build.scala
├── build.properties
└── plugins.sbt
├── sbt
└── src
├── main
├── AndroidManifest.xml
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ └── main.xml
│ └── values
│ │ └── strings.xml
└── scala
│ └── com
│ └── myapp
│ └── MainActivity.scala
└── test
└── scala
└── com
└── myapp
└── test
└── MainTest.scala
/README.md:
--------------------------------------------------------------------------------
1 | ## Android Scala Example
2 |
3 | [](https://gitter.im/emstlk/android-scala-example?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge)
4 |
5 | Android project with sbt 0.13.8, Scala 2.11.7 and android-sdk-plugin 1.4.4
6 |
7 | ### Requirements
8 |
9 | * Java 1.7+
10 | * Android SDK
11 |
12 | Also you can use script to install Android SDK
13 |
14 | ##### On Mac
15 | ```
16 | $ ./mac_install_sdk.sh
17 | ```
18 | ##### On Linux
19 | ```
20 | $ ./linux_install_sdk.sh
21 | ```
22 |
23 | ### Usage in console
24 |
25 | To compile and build
26 |
27 | ```
28 | $ ./sbt android:packageDebug
29 | ```
30 |
31 | To run test with Robolectric (not needed device) just type
32 |
33 | ```
34 | $ ./sbt test
35 | ```
36 |
37 | ### Usage in IDE
38 |
39 | You have to import project from Intellij IDEA (I use version 14.1) or Android Studio
40 |
41 | Choose SBT project and Android SDK like this
42 |
43 | 
44 |
45 | Probably you want to run project from IDE, so just make new "Android application" run configuration
46 |
47 | **Warning!**
48 |
49 | In "Before launch" section you should remove "Make" command and add "Run external tool" with `./sbt android:packageDebug` command
50 |
51 | 
52 |
53 | Also you may want to use a good emulator, so I prefer [Genymotion](https://www.genymotion.com) emulator
54 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | minSdkVersion in Android := "15"
2 |
3 | targetSdkVersion in Android := "21"
4 |
5 | platformTarget in Android := "android-21"
6 |
7 | buildToolsVersion in Android := Some("21.1.1")
8 |
9 | scalaVersion := "2.11.7"
10 |
11 | javacOptions ++= Seq(
12 | "-source", "1.7",
13 | "-target", "1.7",
14 | "-Xlint:unchecked",
15 | "-Xlint:deprecation"
16 | )
17 |
18 | scalacOptions ++= Seq(
19 | "-target:jvm-1.7",
20 | "-encoding", "UTF-8",
21 | "-feature",
22 | "-unchecked",
23 | "-deprecation",
24 | "-Xcheckinit"
25 | )
26 |
27 | libraryDependencies ++= Seq(
28 | "com.android.support" % "appcompat-v7" % "21.0.2",
29 | "org.robolectric" % "robolectric" % "3.0" % "test",
30 | "org.scalatest" %% "scalatest" % "2.2.1" % "test",
31 | "junit" % "junit" % "4.11" % "test",
32 | "com.novocode" % "junit-interface" % "0.11" % "test",
33 | "org.apache.maven" % "maven-ant-tasks" % "2.1.3" % "test"
34 | )
35 |
36 | unmanagedClasspath in Test ++= (bootClasspath in Android).value
37 |
38 | proguardOptions in Android += "-keepattributes Signature"
39 |
--------------------------------------------------------------------------------
/linux_install_sdk.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sudo apt-get update -qq
4 | sudo apt-get install libc6-i386 lib32z1 lib32stdc++6
5 |
6 | OLD_PWD=$PWD
7 |
8 | mkdir .sdk
9 | cd .sdk
10 | wget http://dl.google.com/android/android-sdk_r24-linux.tgz
11 | tar xf android-sdk_r24-linux.tgz
12 | SDK_PATH=$PWD/android-sdk-linux
13 |
14 | cd $OLD_PWD
15 |
16 | echo yes | $SDK_PATH/tools/android update sdk --all --filter platform-tools --no-ui
17 | echo yes | $SDK_PATH/tools/android update sdk --all --filter build-tools-21.1.1 --no-ui
18 | echo yes | $SDK_PATH/tools/android update sdk --all --filter android-21 --no-ui
19 | echo yes | $SDK_PATH/tools/android update sdk --all --filter extra-android-support --no-ui
20 | echo yes | $SDK_PATH/tools/android update sdk --all --filter extra-android-m2repository --no-ui
21 |
22 | echo "sdk.dir=$SDK_PATH" > local.properties
23 |
--------------------------------------------------------------------------------
/mac_install_sdk.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | OLD_PWD=$PWD
4 |
5 | if which brew2 >/dev/null; then
6 | brew install android-sdk
7 | SDK_PATH=/usr/local/opt/android-sdk
8 | else
9 | mkdir .sdk
10 | cd .sdk
11 | curl -O http://dl.google.com/android/android-sdk_r24-macosx.zip
12 | unzip android-sdk_r24-macosx.zip
13 | SDK_PATH=$PWD/android-sdk-macosx
14 | fi
15 |
16 | cd $OLD_PWD
17 |
18 | echo yes | $SDK_PATH/tools/android update sdk --all --filter platform-tools --no-ui
19 | echo yes | $SDK_PATH/tools/android update sdk --all --filter build-tools-21.1.1 --no-ui
20 | echo yes | $SDK_PATH/tools/android update sdk --all --filter android-21 --no-ui
21 | echo yes | $SDK_PATH/tools/android update sdk --all --filter extra-android-support --no-ui
22 | echo yes | $SDK_PATH/tools/android update sdk --all --filter extra-android-m2repository --no-ui
23 |
24 | echo "sdk.dir=$SDK_PATH" > local.properties
25 |
--------------------------------------------------------------------------------
/project/Build.scala:
--------------------------------------------------------------------------------
1 | object Build extends android.AutoBuild
2 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.8
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.4.4")
2 |
--------------------------------------------------------------------------------
/sbt:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sbtver=0.13.8
4 | sbtjar=sbt-launch.jar
5 | sbtsha128=57d0f04f4b48b11ef7e764f4cea58dee4e806ffd
6 |
7 | sbtrepo=http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch
8 |
9 | if [ ! -f $sbtjar ]; then
10 | echo "downloading $sbtjar" 1>&2
11 | if ! curl --location --silent --fail --remote-name $sbtrepo/$sbtver/$sbtjar; then
12 | exit 1
13 | fi
14 | fi
15 |
16 | checksum=`openssl dgst -sha1 $sbtjar | awk '{ print $2 }'`
17 | if [ "$checksum" != $sbtsha128 ]; then
18 | echo "bad $sbtjar. delete $sbtjar and run $0 again."
19 | exit 1
20 | fi
21 |
22 | [ -f ~/.sbtconfig ] && . ~/.sbtconfig
23 |
24 | java -ea \
25 | $SBT_OPTS \
26 | $JAVA_OPTS \
27 | -Djava.net.preferIPv4Stack=true \
28 | -XX:+AggressiveOpts \
29 | -XX:+UseParNewGC \
30 | -XX:+UseConcMarkSweepGC \
31 | -XX:+CMSParallelRemarkEnabled \
32 | -XX:+CMSClassUnloadingEnabled \
33 | -XX:MaxPermSize=256m \
34 | -XX:SurvivorRatio=128 \
35 | -XX:MaxTenuringThreshold=0 \
36 | -Xss2M \
37 | -Xms128M \
38 | -Xmx512M \
39 | -server \
40 | -jar $sbtjar "$@"
41 |
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emstlk/android-scala-example/71cb7c1632c3db9d5c8746e677d97181f6ff0d17/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emstlk/android-scala-example/71cb7c1632c3db9d5c8746e677d97181f6ff0d17/src/main/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emstlk/android-scala-example/71cb7c1632c3db9d5c8746e677d97181f6ff0d17/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/emstlk/android-scala-example/71cb7c1632c3db9d5c8746e677d97181f6ff0d17/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Main Activity
4 | Hello World!
5 |
6 |
--------------------------------------------------------------------------------
/src/main/scala/com/myapp/MainActivity.scala:
--------------------------------------------------------------------------------
1 | package com.myapp
2 |
3 | import android.app.Activity
4 | import android.os.Bundle
5 |
6 | class MainActivity extends Activity {
7 |
8 | override def onPostCreate(savedInstanceState: Bundle) {
9 | super.onPostCreate(savedInstanceState)
10 | setContentView(R.layout.main)
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/test/scala/com/myapp/test/MainTest.scala:
--------------------------------------------------------------------------------
1 | package com.myapp.test
2 |
3 | import android.widget.TextView
4 | import com.myapp.{MainActivity, R}
5 | import org.junit.Test
6 | import org.junit.runner.RunWith
7 | import org.robolectric.annotation.Config
8 | import org.robolectric.{Robolectric, RobolectricTestRunner, RuntimeEnvironment}
9 | import org.scalatest.Matchers
10 | import org.scalatest.junit.JUnitSuite
11 |
12 | @RunWith(classOf[RobolectricTestRunner])
13 | @Config(
14 | manifest = "src/main/AndroidManifest.xml",
15 | resourceDir = "../../target/android-bin/resources/res",
16 | sdk = Array(21)
17 | )
18 | class MainTest extends JUnitSuite with Matchers {
19 |
20 | @Test
21 | def simpleCase() {
22 | val context = RuntimeEnvironment.application.getApplicationContext
23 | val mainActivity = Robolectric.setupActivity(classOf[MainActivity])
24 | val view = mainActivity.findViewById(R.id.simpleTextView).asInstanceOf[TextView]
25 | view.getText.toString shouldBe context.getString(R.string.welcome)
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------