Geoffroy Couprie
Freelance in software security
VLC developer
button.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
//code here
}
}
object Helpers {
implicit def onClick(handler: View => Unit):View.OnClickListener =
new View.OnClickListener() {
override def onClick(source: View) = handler(source)
}
implicit def onClick2(handler: => Unit):View.OnClickListener =
new View.OnClickListener() {
override def onClick(source: View) = handler
}
}
[...]
button.setOnClickListener((source:View) => {
// code here
})
//Even better:
button.setOnClickListener {
// code here
}
Activity code is not reusable
public class MainActivity extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_root, menu);
return true;
}
}
public class OtherActivity extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_root, menu);
return true;
}
}
trait Menu extends Activity {
override def onCreateOptionsMenu(menu: Menu) : Boolean = {
getMenuInflater().inflate(R.menu.activity_root, menu)
true
}
}
[...]
//Use it everywhere
class MainActivity extends Activity with Menu {
...
}
NULL POINTER EXCEPTION /o/
String locProvider = LocationManager.GPS_PROVIDER;
Location loc = locManager.getLastKnownLocation(locProvider);
int satellites = 0;
Bundle extras = loc.getExtras();
int satellites = extras.getInt("satellites");
String locProvider = LocationManager.GPS_PROVIDER;
Location loc = locManager.getLastKnownLocation(locProvider);
int satellites = 0;
if(loc != null) {
Bundle extras = loc.getExtras();
if(extras != null) {
satellites = extras.getInt("satellites");
}
}
VS
val prov = LocationManager.GPS_PROVIDER
val loc = Option( locManager.getLastKnownLocation( prov ) )
val extras = loc.map{_.getExtras()}
val nb = extras.map{_.getInt("satellites")}.getOrElse(0)
private class MyTask extends AsyncTask<String, Integer, Integer> {
protected Integer doInBackground(String... urls) {
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Integer res) {
}
}
import scala.concurrent._
import ExecutionContext.Implicits.global
...
future {
val conn = url.openConnection.asInstanceOf[HttpURLConnection]
val in = new BufferedInputStream(conn.getInputStream())
val res = scala.io.Source.fromInputStream(in).mkString()
conn.disconnect()
res
} onSuccess {
...
}
Futures \o/
import _root_.android.util.Log
import scala.concurrent._
import ExecutionContext.Implicits.global
import rapture.io._
...
future {
val res = (Http / "geoffroycouprie.com").slurp[Char]
Log.v("myapp", res)
}
implicit def toRunnable[A](f: => A):Runnable =
new Runnable() { def run() = f }
...
future {
(Http / "geoffroycouprie.com").slurp[Char]
} onSuccess { value =>
runOnUiThread {
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}
}
new SVerticalLayout {
STextView("Sign in").textSize(24.5 sp).<<.marginBottom(25 dip).>>
STextView("ID")
val userId = SEditText()
STextView("Password")
val pass = SEditText() inputType TEXT_PASSWORD
SButton("Sign in", signin(userId.text, pass.text))
this += new SLinearLayout {
SButton("Help", openUri("http://help.example.com"))
SButton("Sign up", openUri("http://signup.example.com"))
}
}.padding(20 dip)
$g8 Geal/android-app
package [my.android.project]: com.scalaonandroid.testapp
name [MyAndroidProject]: TestApp
main_activity [MainActivity]:
scala_version [2.10.1]:
api_level [10]:
useProguard [true]:
scalatest_version [1.9.1]:
Template applied in ./test-app
$cd test-app && sbt android:install-device
Software sources:
$ time sbt android:install-device
[...]
real 5m23.410s
user 5m6.835s
sys 0m5.469s
-> install libraries on the phone
-> HAXM or Android x86 on VirtualBox
Rapture, etc