Getting Started With Ceylon on Android Studio
Stephane Epardaud gives step-by-step instructions on how to get started with the Ceylon language to write native Android apps.
Join the DZone community and get the full member experience.
Join For Freein my last post , i explained how you can use ceylon in apache cordova to write applications for every mobile platform, including ios and android. this time, with many apologies for writing it late (“next week” turned into next month), i will explain how to use the ceylon intellij plugin to write native android applications in ceylon in android studio.
getting started with ceylon on android studio
to start writing ceylon applications in android studio, follow these steps:
- download android studio
- start it
-
create a new application by clicking on
start a new android studio project
-
you can use these values for
application name
:ceylondemo
-
and for
company domain
:android.example.com
-
next, select an
empty activity
, withactivity name
:mainactivity
-
click
finish
and wait for the project to be created
at this point you have an android project open, but we still haven't had time to install the ceylon plugin, so let's do this right now:
-
click on
file > settings > plugins > browse repositories
-
then on
manage repositories > +
-
add this repository:
https://downloads.ceylon-lang.org/ide/intellij/development/updateplugins.xml
-
now click on
install ceylon ide
you will likely need to restart android studio, so do that.
next we're going to convert our android project to a ceylon android project:
-
in the
android
view, right-click onapp > configure ceylon in this module
-
click
ok
on the resulting configuration dialog
this will set up the ceylon plugin, and will add most of what you need in your gradle build to build ceylon android applications. you now have your ceylon sources in
app/src/main/ceylon
and it includes a module descriptor and an empty activity:
at the moment this requires a ceylon
1.2.3
distribution to build, and since it's not released yet you're going to have to either
build one yourself
(just the
getting the source
part), or
download a nightly build
. once you have it, edit
app/build.gradle
near then end to add
ceylon > ceylonlocation
and make it point to where you installed your distribution (it needs to point to the ceylon binary, not just the distribution root):
ceylon {
// ...
ceylonlocation ".../ceylon/dist/dist/bin/ceylon"
}
make sure you click on
sync now
to sync your gradle build.
now, there's a bug we're in the process of fixing which fails to detect the exact version of the android sdk tooling and modules, so depending on which version of the android tools you're using you may have to sync the imports of
com.android.support:appcompat-v7:23.1.1
in
app/build.gradle
(in
dependencies
) and in the ceylon module descriptor in
module.ceylon
. make sure the ceylon import version is the same as the gradle import version because the gradle build is what makes it available to ceylon due to android's peculiarities.
in order to finish the conversion, make sure you delete the java activity (since we're going to keep the ceylon one) in
project files
and delete
app/src/main/java
.
due to another pending plugin fix, you may have to click on
tools > ceylon > reset ceylon model
at this point so that the ceylon plugin gets synchronized with all these past changes (don't worry we're fixing this at the moment).
the good news is we're already able to click on
run app
and try this in the emulator, but we're going to make it a little more interesting.
customizing your ceylon android activity
we're going to be displaying a list of ceylon modules published on
ceylon herd
, so we will make use of the ceylon sdk, and in particular you will have to edit
module.ceylon
to add the following imports:
import ceylon.http.client "1.2.3";
import ceylon.uri "1.2.3";
import ceylon.json "1.2.3";
import ceylon.collection "1.2.3";
import ceylon.interop.java "1.2.3";
next, we're going to turn our
mainactivity
into a
listactivity
and run an asynchronous task to connect to the herd rest endpoint, so edit
mainactivity.ceylon
with this:
import android.os { bundle, asynctask }
import android.app { listactivity }
import android.widget { arrayadapter, listadapter }
import android.support.v7.app { appcompatactivity }
import ceylon.interop.java { createjavastringarray }
import java.lang { jstring = string }
import android { androidr = r }
import ceylon.language.meta { modules }
import ceylon.uri { parseuri = parse }
import ceylon.http.client { httpget = get }
import ceylon.json { parsejson = parse, jsonobject = object, jsonarray = array }
import ceylon.collection { mutablelist, linkedlist }
shared class mainactivity() extends listactivity() {
class loadmodules() extends asynctask<string, nothing, list<string>>() {
shared actual list<string> doinbackground(string?* uris){
assert(exists uri = uris.first);
value response = httpget(parseuri(uri)).execute();
value modules = linkedlist<string>();
assert(is jsonobject json = parsejson(response.contents),
is jsonarray results = json["results"]);
// iterate modules
for(res in results) {
assert (is jsonobject res); // get the list of versions
assert (is string name = res["module"],
is jsonarray versions = res["versions"]);
modules.add(name);
print(name);
}
return modules;
}
shared actual void onpostexecute(list<string> result){
print("got result: ``result``");
listadapter adapter = arrayadapter<jstring>(outer, androidr.layout.simple_list_item_1,
createjavastringarray(result));
listadapter = adapter;
}
}
shared actual void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
loadmodules().execute("https://modules.ceylon-lang.org/api/1/complete-modules?module=ceylon.");
}
}
now edit
app/src/main/res/layout/activity_main.xml
to change the activity type to a list activity:
<listview
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@android:id/list"/>
and lastly request the
network
permission for your app, since we're hitting a web service, by adding this to
app/src/main/res/androidmanifest.xml
:
<uses-permission android:name="android.permission.internet"/>
that's all you need, now just click on
run > run app
and watch your ceylon application display the list of modules in the emulator:
some technical info
the ceylon intellij plugin has not been released yet, but a preview is forthcoming really soon. you will see it's already quite advanced when you try this out. don't hesitate to report any bugs , or better yet, contribute fixes.
most of it works well enough for android except the caveats noted above, and the fact that android studio does not yet recognize ceylon classes. they will be marked as errors in the
.xml
files that refer to them, and when you run your application it will report an error:
could not identify launch activity: default activity not found. error while launching activity
it only means it could not start your application, you will have to click on it to start it in the emulator. but the deployment worked. we're fixing this at the moment, so it will only improve.
if you want to revert to the ceylon eclipse ide to edit your ceylon android application, you can, and it will work once you have your project set up with android studio. it's much easier to use it to set it up so all the gradle config is just right. once that is done, you can use eclipse if you want, and use
$ ./gradlew assembledebug
to build your apk.
this work depends on changes we've made in ceylon 1.2.3 (to be released soon) which adds support for jars which provide alternate smaller jdks (such as the android jar), improvements in modularity so that the created applications depend on much fewer runtime ceylon jars than before, fixes in the runtime metamodel to support android runtimes, and several other tweaks. i will probably write an account of all that in a future blog entry.
this work also depends on the
ceylon gradle plugin
written by renato athaydes, and on a new
ceylon gradle android plugin
which adds support for ceylon in android applications. this plugin is by no means finished, and in particular does not yet support incremental compilation (even though the ceylon ide and compiler do). it also does not yet support the latest android
instant run
feature. again, please
report issues
or better, contribute pull-requests.
related refcard:
Published at DZone with permission of Stephane Epardaud, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments