-
Notifications
You must be signed in to change notification settings - Fork 57
Tutorial
Lein-droid is a plugin for Leiningen, so first you should
make sure you have Leiningen 2.3 or higher installed. To install
lein-droid as a plugin open your ~/.lein/profiles.clj
file and
insert the following line into the plugins section:
If you do not already have a ~/.lein/profiles.clj
file, create it with the following content:
{:user {:plugins [ [lein-droid "whatever-the-last-version-is"] ]}}
Now, the first time you try to use the droid
task, Leiningen will
automatically download the plugin from Clojars.
NB: Neko has a minimal SDK version requirement of 15. This means that you need a device with Android 4.0 “Ice Cream Sandwich” or higher to use Neko and lein-droid.
Due to Android’s slow transition to JDK7, it is somewhat tricky to
setup the SDK properly. Prior to version 19, Android build tools
didn’t support JDK7 at all. If you want to use lein-droid with
Android SDK/Build tools <19, make sure you use neko
3.0.0-preview4
or earlier, and either JDK6 or add this line to your
project.clj
:
:javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
If you are using the latest version 19, you must use JDK7 and
neko 3.0.0
or higher.
You can specify the path to the SDK either globally in profiles.clj
in
:android-common profile, or on the per-project basis (in project.clj
).
Either way, you should put :sdk-path
value into :android
map:
:android {:sdk-path "/path/to/android-sdk-linux_x86"}
Related options: :sdk-path, :target-version.
You might have problems with running Android SDK on a 64-bit system. On my Arch Setup it was enough for me to install lib32-ncurses from multilib repository. Here’s the guide how to deal with this on Fedora (thanks to Przemysław Wojnowski for this).
To create a new Android project execute the following command:
lein droid new <project-name> <package-name> [optional-args]
project-name
is the name of the new Clojure project. By
default it also acts as an Android application name but you can
specify a custom application name in the optional arguments.
package-name
represents an Android package name by which all applications are distinguished.
Package name should have at least two levels (like
foo.bar
) and not contain any hyphens (underscores can be used
instead).
Optional args are specified in a key-value fashion. Available optional args:
- activity
- target-sdk
- app-name
For example:
lein droid new clojuroid org.stuff.clojuroid :activity MyActivity :target-sdk 15 :app-name ClojureMeetsAndroid
When a new project is created, project.clj
is generated almost ready to be
used. The only thing you have to change is to specify the path to your
Android SDK (if you haven’t already done it in profiles.clj
).
You will also eventually have to set the path to private keystore
and key alias under the :release
profile. It is needed to sign
your release version of the application. When signing you will be
prompted a store password and a key password.
For the full list of supported options see this file.
To compile, build and deploy with one command use:
lein droid doall
This is the command to go from source code to a running application on your device with REPL ready. You’ll use it most of the time when finer-grained build process is not necessary. In case it is, next paragraphs describe the build process step-by-step.
In order to compile/build your project execute the following:
lein droid build
This creates R.java file from the resources, compiles the Java files (if available), and all the Clojure files including all dependencies. This takes some time (but only for the first time), and it is specific for the development build - the release version will include only those compiled files that are used.
After the compilation a DEX file is created. This is the most time-consuming operation in the whole process, it fully loads CPU and may last up to 2 minutes. The good thing is that you won’t have to do it often since you’ll have a REPL available.
NOTE: You can run the commands separately by executing lein
droid code-gen
, lein droid compile
and lein droid create-dex
.
Related options: :aot, :aot-exclude-ns, :dex-opts, :external-classes-paths, :force-dex-optimize, :native-libraries-paths, :support-libraries.
To create an APK file of your application run this command:
lein droid apk
It will crunch the resources, package them, create an APK file, sign it (with either debug or real key - depends on the profile you use) and zipaligns it. The result file will be called ApplicationName-debug.apk (for the debug build) or ApplicationName.apk (for the release build).
To install the newly created application to the device run:
lein droid install
After that, to run your application execute this (of course, you can run it from the device):
lein droid run
The application will start and run the REPL server by default. To connect to it run the following command:
lein do droid forward-port, droid repl
The first command binds the port on the device to the port on the computer (by default they are both 9999). You only have to run this command once per development session (while adb daemon is running). The second command connects to the nREPL server using REPLy client.
If all goes well you’ll see a REPL prompt. Then execute:
(in-ns 'your_application_namespace)
Or switch to any other namespace with (ns …) command.
You can execute first three subtasks (install
, run
,
forward-port
) by running lein droid deploy
.
That’s all, now you are able to execute Clojure code in a REPL on the Android device!
Related options: :repl-device-port, :repl-local-port.
Prior to cutting a release read through the following page: Specifics of release version.
In order to make a release version of your application execute the following command:
lein with-profile release droid doall
For smaller subtasks you can chain them like in lein do
command, but
remember that you have to mention droid
every time:
lein with-profile release droid build, droid apk, droid deploy
Debug versions are automatically signed with debug.keystore which has a standard password and parameters. For the release version you need to obtain/create the personalized keystore.
You can read a detailed information on what is a keystore and why do need signing your applications here.
To create a personal keystore execute this:
keytool -genkeypair -keyalg RSA -keystore "/path/to/keystore/file" -alias "the_alias_for_you_key" -validity 36500
The last parameter validity specifies in days for how long should the key be valid. In the example we set it to be 100 years.
After you execute the command you will be asked few more questions, and then a keystore will be generated.
Related options: :keystore-path, :key-alias, :sigalg, :storepass, :keypass.
By default if you have only one device/emulator currently attached to your
computer, the tasks install
, run
and forward-port
will run against it.
If there are multiple devices attached you will be prompted to choose the
correct device from the list.
You can save some time (that is spent by lein-droid running adb devices
) by
providing special flags to the task. For example, if there is only one
physical device connected you can call the tasks in this way: lein droid
install -d
or for the only emulator: lein droid install -e
. You can even
directly specify the device in the command by its serial number:
lein droid run -s I29751849af4
NOTE: subtasks don’t share any information between them, so if you have two
devices and you run lein do droid install, droid run, droid forward-port
you will be prompted to choose the device three times. To avoid this you
can either specify the flag for each subtask or use the lein droid deploy
meta-task which executes all above-mentioned tasks and asks for device only
once.
You can use specify common Java dependencies the same way you do in
Clojure/JVM projects, by adding them to :dependencies
vector.
Although Android dependencies (that contain resources) cannot be
used in such a manner (current Android toolchain limitation), but
you can use source (project) dependencies with lein-droid. First
you need to go to the dependency directory and initialize a project
by running:
lein init
This will create project.clj
file with a library flag. You may
also want to specify :java-only flag as true
for Java libraries,
and remove extra Clojure dependencies from there.
Then go to your main project, open its project.clj and add this
line to the :android
map:
:project-dependencies [ "/path/to/library/project" ]
You can specify multiple project dependencies there.
That’s all you have to do. Next time you run compilation/building tasks in your project all the dependency projects will be automatically compiled, and their resources will be included into your application.
Neko uses nREPL as REPL backend, so you can connect to it using
your favorite editor with the nREPL plugin. You will have to
initiate the connection, provide localhost
as host and the local
port specified in project.clj
(9999 by default). Here are some
editor plugins that will allow you to do that:
- Emacs - cider (formerly nrepl.el). Use
M-x cider
to connect. - Vim - fireplace.vim
- Eclipse - Counterclockwise
If anything strange happens during the build, try to execute the command with the DEBUG environment variable set to 1. For example, on *NIX machine:
DEBUG=1 lein droid apk
This will provide additional information and will show the exact shell commands that are spawned by the plugin.
To troubleshoot problems on the device you can use the following Android SDK command:
<sdk-path>/platform-tools/adb logcat
This will print device log into console. It is ongoing, so you can execute this command, then perform some lein-droid tasks while Logcat continues logging. This is also useful to discover problems related to app installation onto a device.
First, make sure that nREPL server starts on the device. You can see this in
Logcat as the application loads. Execute adb logcat -s neko.init
to filter
the irrelevant output and watch for the following line:
I/neko.init( 1234 ): Nrepl started at port 9999
If you can’t see this, then probably neko.init/init
was not
called. This only happens if you neither use the default
SplashActivity.java
, nor defactivity
to create your
activities. In this case you have to call neko.init/init manually.
If nREPL starts, then check if the device port is forwarded to
your machine. Execute lein droid forward-port
(droid doall
metatask does this as well) and view the list of listened ports.
On GNU/Linux you can do:
netstat -plnt
You are looking for a process that listens on the port specified as your :repl-local-port (or 9999 by default).
Tutorial
- Installation
- Creating a new project
- Quick start
- Libraries and dependencies
- Editors and IDEs
- Troubleshooting
Profiles
Lean compilation
Multi-DEX project
Creating AAR libraries
Hacking the plugin
project.clj options
-
:android
- :aot
- :aot-exclude-ns
- :assets-paths
- :build-tools-version
- :build-type
- :dex-opts
- :external-classes-paths
- :external-res-paths
- :force-dex-optimize
- :ignore-log-priority
- :key-alias
- :keypass
- :keystore-path
- :lean-compile
- :library
- :manifest-options
- :manifest-template-path
- :multi-dex
- :multi-dex-proguard-conf-path
- :native-libraries-paths
- :proguard-execute
- :proguard-conf-path
- :rename-manifest-package
- :repl-device-port
- :repl-local-port
- :res-path
- :resource-jars-paths
- :sdk-path
- :sigalg
- :skummet-skip-vars
- :start-nrepl-server
- :storepass
- :target-version
- :use-debug-keystore
- :dependencies
- :java-only
- :profiles
- *warn-on-reflection*