Fork me on GitHub

Thursday, November 28, 2013

Scaloid 3.0 is released

Today we are pleased to announce Scaloid 3.0. Some new feature highlights are as shown below:

Redesign of LocalServiceConnection

LocalServiceConnection is redesigned to use Option, and prevents possibility of NullPointerException, which was very frequent when accessing service with LocalServiceConnection.

This is a breaking change in source code level. Please migrate the code as introduced in a blog post below:
http://blog.scaloid.org/2013/11/redesign-of-localserviceconnection.html

Changed SImageView(r: Int) to SImageView(r: Drawable)

We believe that source level compatibility is not broken. However, rebuild is required because the parameter signature is changed.

https://github.com/pocorall/scaloid/commit/4f708eb4017b848a1f6ae5d542435b61781473fe

SPaint support

We added an initial attempt to embrace graphics feature of Android API. Please refer to this blog post for a design principle behind this addition.

https://github.com/pocorall/scaloid/commit/b0dc224935a9a4c2133d0a5404a72646f04d0215

For a maven project:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>3.0-8</version>
</dependency>
or for an sbt project:
libraryDependencies += "org.scaloid" %% "scaloid" % "3.0-8"

Sunday, November 17, 2013

Usage driven design - choosing parameters

Scaloid is originally made to improve my daily life that codes Android apps. Although Scaloid relies on some core design principles that is behind of automatic wrapper generator, sometimes code can be improved from some heuristics. For example, I found that my code has several functions much like this:

def createMyPaint(): Paint = {
    val p = new Paint()
    p.setColor(0xffff6666)
    p.setTextSize(14.sp)
    p
}

Soon I added a wrapper class of android.graphics.Paint to Scaloid. Then the code above is improved as:

def createMyPaint() = SPaint().color(0xffff6666).textSize(14.sp)

All of my codes and a Google search reveals that setColor() is always called after a new Paint instance is initialized. It is very natural to think about a color when we tried to paint something. So I added it as the first parameter of the method SPaint.apply(); then the code can be rewritten as:

def createMyPaint() = SPaint(0xffff6666).textSize(14.sp)

We have reached the minimum code as possible.

This feature is shipped with Scaloid 3.0-M2. You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>3.0-8-M2</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "3.0-8-M2"

Friday, November 15, 2013

Redesign of LocalServiceConnection

For the current version of Scaloid, the type of LocalServiceConnection.service is [S <: LocalService]. This value is null if the service is not yet connected. So it is exposed to the possibility of NullPointerException. To avoid the exception, users must check that the service is connected, as shown below:

class MyService extends LocalService {
  def getNumber(): Int = 3
}

class Activity extends SActivity {
  val number = new LocalServiceConnection[MyService]

  def onButtonClick(v:View) {
    val num = if(number.connected) number.service.getNumber() else 0
    doSomethingWith(num)
  }
}

The problem is that the checking is very easy to forget. So I changed the type of LocalServiceConnection.service to Option[S], so that the possibility of NPE goes away. Moreover, I added some additional helper methods that decreases clutters from your code:

def onButtonClick(v:View) {
  val num = number(_.getNumber(), 0)
  doSomethingWith(num)
}

The method LocalServiceConnection.apply[T](f: S => T, defaultVal: T): T returns the result of the function f if the service is connected, and returns defaultVal otherwise. This is far more cleaner than the previous one.

If we don't want to return something, and therefore we don't have any default value, we can use it as:
def onButtonClick(v:View) {
  number(s => doSomethingWith(s.getNumber()))
}
We often tests some condition and evaluates different expression according to the condition:
def onButtonClick(v:View) {
  val result = if(number(_.getNumber(), 0) > 10) 
                 "10 < " + number(_.getNumber()) else "fail"
  doSomethingWith(result)
}
It can also be reduced to:
def onButtonClick(v:View) {
  val result = number(_.getNumber() > 10, "10 < " + _.getNumber(), "fail")
  doSomethingWith(result)
}

Because we have a breaking change, this feature will be shipped with Scaloid 3.0. You can evaluate this feature from the first milestone release. For a maven project:
<dependency>
    <groupId>org.scaloidscaloid_2.10</artifactId>
    <version>3.0-8-M1</version>
</dependency>
or for an sbt project:
libraryDependencies += "org.scaloid" %% "scaloid" % "3.0-8-M1"

Wednesday, November 13, 2013

Using scala.concurrent.Future on Android

From Scala 2.10, a concurrent execution function scala.concurrent.ops.spawn is deprecated, replaced with scala.concurrent.Future, and will be removed from Scala 2.11.

I rewrote my app with scala.concurrent.Future as an official Scala documentation suggests:
import ExecutionContext.Implicits.global
Future {
// ...
}

However, after I uploaded the app to Google Play, I received a ton of crash report:
java.lang.ExceptionInInitializerError
at scala.concurrent.impl.ExecutionContextImpl.createExecutorService(ExecutionContextImpl.scala:77)
at scala.concurrent.impl.ExecutionContextImpl.<init>(ExecutionContextImpl.scala:28)
at scala.concurrent.ExecutionContext$Implicits$.global$lzycompute(ExecutionContext.scala:63)
at scala.concurrent.ExecutionContext$Implicits$.global(ExecutionContext.scala:63)
at com.soundcorset.client.android.SoundcorsetService$Metronome.start(SoundcorsetService.scala:38)
...
Caused by: java.lang.Error: java.lang.NoSuchFieldException: parkBlocker
at scala.concurrent.forkjoin.ForkJoinPool.<clinit>(ForkJoinPool.java:2852)
... 20 more
Caused by: java.lang.NoSuchFieldException: parkBlocker
at java.lang.ClassCache.findFieldByName(ClassCache.java:510)
at java.lang.Class.getDeclaredField(Class.java:683)
at scala.concurrent.forkjoin.ForkJoinPool.<clinit>(ForkJoinPool.java:2847)
... 20 more

Scala library has its own copy of ForkJoinPool implementation, which includes dynamic invocations, that is parkBlocker in this case. Unfortunately, some Android devices does not have this method, so we've got this awful crash report.

The solution is very simple: Do not use ExecutionContext.Implicits.global. Declare a custom implicit ExecutionContext instead. For example:
implicit val exec = ExecutionContext.fromExecutor(
  new ThreadPoolExecutor(100, 100, 1000, TimeUnit.SECONDS,
    new LinkedBlockingQueue[Runnable]))

Future {
// ...
}

This works perfect in production.

EDIT: If the minimum API level of your app is above 11, consider using AsyncTask.THREAD_POOL_EXECUTOR instead of making your own thread executor:
implicit val exec = ExecutionContext.fromExecutor(
  AsyncTask.THREAD_POOL_EXECUTOR)
Thanks Niklas Klein for this suggestion.

Sunday, November 10, 2013

Scaloid 2.5 is released

We announce Scaloid 2.5, which is a maintenance release.

This version includes screen dimension queries (org.scaloid.util.Configuration) for multiple device configuration.

You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>2.5-8</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "2.5-8"


Next major release will be 3.0, preceded by several milestone releases.

Wednesday, September 18, 2013

Unit of measurement of TextView.setTextSize()

The Soundcorset metronome and tuner, in which I wrote it with Scaloid, is keep growing and hits 70,000 downloads. Until recently, it has a strange problem that it displays very large text for some devices, so that some button texts are clipped away out of the layout. After some code investigation, I found that it is very tricky pitfall because the code does not seems to have any problem at first:
STextView("Hello").textSize(20 sp)  // not correct!
The unit specification like 20 sp is very common in Scaloid. The implicit function sp converts the number from the sp unit to the pixel unit. The code above looks fine because the most of the Android API receives a size as the pixel unit. But there was a single exception. The method TextView.setTextSize(float) does not receives a size as the pixel unit, it receives sp unit instead. It may cause a mistake because the most of other APIs handles a size as the pixel unit, even in TextView.getTextSize()!!! So I overridden STextView.textSize so that the APIs have consistency in pixel units:
@inline def textSize  (p: Int) =  textSize_=(p)
@inline def textSize_=(p: Int) = { 
  basis.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, p)
  basis 
}
Now we can safely use the method textSize with the implicit unit conversions:
STextView("Hello").textSize(20 sp)  // correct :-D
I patched the current snapshot, and it will be available at the next release of Scaloid.

Sunday, September 1, 2013

Syntactic sugar for multiple device configuration

The most common question about Scaloid that I received is that how to adapt multiple device configuration.

Basically, a layout written in Scaloid is just an ordinary Scala code, so you can just freely composite the layout according to the device configuration:
if(width > 900 dip) STextView("The display is wider than 900 dips!")

This is simple, concise and intuitive in compared to XML description. Moreover, this promotes the 'responsive design', which adapts various screen dimensions with single layout description.

The only problem was that we have to manually prepare required variables, such as width in the example above. To address this issue, I wrote a package of helper methods that can be used to determine device configurations such as screen layout and resolution in dot-per-inch. All you need is just importing org.scaloid.util.Configuration._.
import org.scaloid.util.Configuration._

if(long) SButton("This button is shown only for a long screen "
  + "dimension ("+ width + ", " + height + ")")
if(landscape) this += new SLinearLayout {
  SButton("Buttons for")
  SButton("landscape layout")
  if(dpi >= HDPI) SButton("You have a high resolution display!")
}
The source code is pretty straightforward. Look at the source code to figure out how it works.

Monday, August 5, 2013

Scaloid 2.3 is released

Today I released Scaloid version 2.3. This version is a maintenance release that fixes several issues since the latest version. Major improvements include:

More convenient and organized constructors

Scaloid provided the two-argument apply() function for the object SButton; The first argument represents the text, and the second represents onClick behavior.
val button = SButton("Greet", toast("hello"))

In this version, this kind of initialization is generalized to cover constructors of every classes that inherits TextView. For example:
val textView = new STextView("Greet", toast("hello"))

Scaloid also provides concise initialization functions(in both constructor and apply method) for the classes that inherits ImageView. For example:
val imageView = new SImageView(R.drawable.greet, toast("hello"))

More general constructors for SArrayAdapter

Please refer to the github issues #57 and #58.

...and several minor improvements on APIs


You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>2.3-8</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "2.3-8"

Sunday, June 23, 2013

Scaloid 2.1 is released

Today I released Scaloid version 2.1.

Improvements in this version is shown below:

  • Fixed a regression related to SArrayAdapter
  • Uses ClassTag instead of ClassManifest, which is deprecated from Scala 2.10
  • Improved APIdoc
  • Covers Android API more completely (added SWebView)

This version is not binary compatible with previous versions. Please clean rebuild your project to upgrade Scaloid to 2.1.

You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>2.1-8</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "2.1-8"

Monday, June 17, 2013

Scaloid 2.0 is released

Today I released Scaloid 2.0, a new step forward to Scala+Android development.

This version fixes several regressions that is found since the last release candidate.

Some of the feature highlights on this version are:
  • Build tool is moved to sbt
  • New sbt based template generator, in which large part of the generation is automated (thanks guersam)
  • Therefore Scaloid library covers Android APIs more completely
  • Source code becomes more modular
  • Artifact and version naming is changed to sbt-style.

You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>2.0-8</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "2.0-8"

Saturday, June 8, 2013

Scaloid 2.0-RC2 is released

Scaloid 2.0-RC2 is released.

This version fixes several regression bugs from the RC1. I fixed all of the reported bug. Please test it and report issues to github issues page.

Some of the feature highlights on version 2.0 are:
  • Build tool is moved to sbt
  • New sbt based template generator, in which large part of the generation is automated (thanks guersam)
  • Therefore Scaloid library covers Android APIs more completely
  • Source code becomes more modular
  • Artifact and version naming is changed to sbt-style.

You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>2.0-8-RC2</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "2.0-8-RC2"

Thursday, June 6, 2013

Scaloid 2.0-RC1 is released

I just released Scaloid 2.0-RC1 to the central maven repository.

Thanks to guersam and other contributors, Scaloid progressed large steps toward version 2.0. Some of highlights are listed below:


  • Build tool is moved to sbt
  • New sbt based template generator, in which large part of the generation is automated
  • Therefore Scaloid library covers Android APIs more completely
  • Source code becomes more modular
  • Artifact and version naming is changed to sbt-style.

You can include this version of Scaloid into a maven project by:
<dependency>
    <groupId>org.scaloid</groupId>
    <artifactId>scaloid_2.10</artifactId>
    <version>2.0-8-RC1</version>
</dependency>
or a sbt project by:
libraryDependencies += "org.scaloid" %% "scaloid" % "2.0-8-RC1"

We will focus on making the core library more mature, and launching optional libraries based on the new generator.

Keep thrilling with concise and type-safe Android development!

Wednesday, April 24, 2013

Accessing widgets in view classes

In conventional Android programming, UI widgets are accessed by using findViewById() method as shown below:
var name: EditText = null

override def onCreate(b: Bundle) {
  super.onCreate(b)
  setContentView(R.layout.main)

  name = findViewById(R.id.name).asInstanceOf[EditText]
}

def printName() {
  println("The name is " + name.getText())
}
This causes some major problems:

  • Not type-safe
    You have to manually track the type of the widget, and no compile-time guarantee that you did not made any mistake.
  • The member name is mutable
    It is better to declare name as immutable because it refers only one widget.
  • Possibility of NullPointerException
    Accessing name before calling onCreate() summons NPE-the-horrible!
  • Requires extra XML configurations to maintain
    Use XML layout if you like housekeeping chores.

  • In Scaloid, you can rewrite it with:
    var name: SEditText = null
    
    onCreate {
      contentView = SVerticalLayout {
        name = SEditText("Default name")
      }
    }
    
    def printName() {
      println("The name is " + name.text)
    }
    
    This looks much better, because it is type-safe and eliminates XML configurations. However, the member name is still a mutable variable. It can be improved as shown below:
    lazy val name = new SEditText("Default name")
    
    onCreate {
      contentView = SVerticalLayout {
        this += name
      }
    }
    
    def printName() {
      println("The name is " + name.text)
    }
    
    Now the member name is a lazy value, therefore the possiblilty of NPE is eliminated as well.

    Friday, March 15, 2013

    Scaloid 1.1 is released

    Today I released Scaloid 1.1. You can download it from the central maven repository.

    Some key improvements in this version are:

    * Dynamically accessing SharedPreferences
    * LocalService
    * Lifecycle management
    * Drops Scala 2.9 support (mainly due to the use of type dynamic in SharedPreferences)

    Sunday, March 10, 2013

    Introducing LocalService

    Activities has a very short-term lifecycle. Even when you rotate your device, the activity is destroyed and newly created. Therefore, a service is needed for a longer term behavior that should persist when the current application is not in foreground. Service is designed to be a pretty powerful tool, that is intended to support inter-process communication. However, I (and probably you) just use a service as an in-process singleton object for most of the time. Just accessing an object in the same VM need not be complex at all. However, the Android Developer Guide misguides developers to write such a horrible length of code:

    public class MyService extends Service {
        private final IBinder mBinder = new LocalBinder();
    
        public class LocalBinder extends Binder {
            MyService getService() {
                return MyService.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        private final Random mGenerator = new Random();
    
        public int getRandomNumber() {
            return mGenerator.nextInt(100);
        }
    }
    
    public class BindingActivity extends Activity {
        MyService mService;
        boolean mBound = false;
    
        @Override
        protected void onStart() {
            super.onStart();
            Intent intent = new Intent(this, MyService.class);
            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            if (mBound) {
                unbindService(mConnection);
                mBound = false;
            }
        }
    
        public void onButtonClick(View v) {
          if (mBound) {
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
          }
        }
    
        private ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName className,
                    IBinder service) {
                LocalBinder binder = (LocalBinder) service;
                mService = binder.getService();
                mBound = true;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName arg0) {
                mBound = false;
            }
        };
    }
    
    This implementation is full of boilerplate code. In Scala, we can rewrite it as follows:
    class MyService extends LocalService {
        private val generator = new Random()
    
        def getRandomNumber() = generator.nextInt(100)
    }
    
    class MyActivity extends SActivity {
      val random = new LocalServiceConnection[MyService]
    
      def onButtonClick(v:View) {
        random( s => toast("number: " + s.getRandomNumber()))
      }
    }
    
    This code snippet does the same thing with the original Java code. All of the clutters are encapsulated in LocalService and LocalServiceConnection, so you can just focus on your idea.

    We often initializes a variable with some default value when the service is not yet connected:
    val num = if(random.connected) random.service.getRandomNumber() else 0
    doSomethingWith(num)
    

    With LocalServiceConnection.apply, the expression above can be shortened as shown below:

    val num = random(_.getRandomNumber(), 0)
    doSomethingWith(num)
    

    The full source code of these traits can be found here

    Friday, March 1, 2013

    Prompt user to rate your Android app

    To make your app is frequently searched, user rating is important. Prompt engaged user with a dialog that asking a (favorable) vote is a common technique. Although it is some kind of exploit, I think that it is not so dirty, because nobody hurts by doing this. I have googled about it and found a code snippet here. However, that code is too long whereas it does a simple thing. I rewrite it using Scaloid

    onCreate {
      val prefs = Preferences()
      val ec = prefs.executionCount(0)
      prefs.executionCount = ec + 1
      if (ec % 20 == 19 && !prefs.wontRate(false)) {
        new AlertDialogBuilder(null, "Please take a moment to rate it.") {
          positiveButton("Rate it", {
            openUri("market://details?id=com.soundcorset.client.android")
            prefs.wontRate = true
          })
          neutralButton("Remind me later")
          negativeButton("No thanks", {
            prefs.wontRate = true
          })
        }.show()
      }
    }
    

    Comparing with the original code, this is really simple, isn't it?

    Dynamically accessing SharedPreferences

    Scala 2.10 ships with a new feature called Type Dynamic, which is borrowed from typeless script language (e.g. Groovy). With this feature, the name of methods and properties can be handled in runtime. One of the practical use case of it is accessing SharedPreference object more concisely. An ordinary way of accessing a SharedPreference property looks like this:

    val ec = pref.getInt("executionCount", 0)
    val editor = pref.edit()
    editor.putInt("executionCount", ec + 1)
    editor.commit()
    

    Doing some work on the backstage with Type Dynamic, the code can be improved as follows:
    val ec = pref.executionCount(0)
    pref.executionCount = ec + 1
    

    Accessing properties becomes more natural. To do this, I wrote some helper classes using Type Dynamic as shown below:
    class Preferences(val preferences: SharedPreferences) extends Dynamic {
      def updateDynamic(name: String)(value: Any) {
        value match {
          case v: String => preferences.edit().putString(name, v).commit()
          case v: Int => preferences.edit().putInt(name, v).commit()
          case v: Long => preferences.edit().putLong(name, v).commit()
          case v: Boolean => preferences.edit().putBoolean(name, v).commit()
          case v: Float => preferences.edit().putFloat(name, v).commit()
        }
      }
    
      def applyDynamic[T](name: String)(defaultVal: T): T = defaultVal match {
        case v: String => preferences.getString(name, v).asInstanceOf[T]
        case v: Int => preferences.getInt(name, v).asInstanceOf[T]
        case v: Long => preferences.getLong(name, v).asInstanceOf[T]
        case v: Boolean => preferences.getBoolean(name, v).asInstanceOf[T]
        case v: Float => preferences.getFloat(name, v).asInstanceOf[T]
      }
    }
    
    When you access pref.executionCount(0), Scala compiler expands it to pref.applyDynamic("executionCount")(0), and pref.executionCount = ec become pref.updateDynamic("executionCount")(ec).

    The full source code can be found here. You can simply download and enjoy it.

    Prompt user to rate your Android app

    Now, you can easily access persistent properties. One of the most popular example is prompting engaged user to rate your Android app. I posted about it here.

    Sunday, February 17, 2013

    Android multiple layout directory considered harmful

    In mobile application, displaying different layout for different orientation or screen size is important. For example, An app can be shown in different layout according to the screen orientation as shown below:




    Android SDK provides a way to specify a different layout for the screen orientation or the size. This specification is based on directory naming. If you place a layout file in "layout-land", it is for the landscape orientation, and a file in "layout-port" for the portrait orientation. This is intuitive and simple. However, it has a major drawback: maintainability.

    Suppose you added a button in /layout/main.xml, you tested your new button works well. Is it OK? No. You may have another layout directory that has main.xml such as /layout-land/main.xml, /layout-large-land/main.xml, /layout-small-land/main.xml  or even /layout-normal-long-hdpi/main.xml. You have to modify and test all of these layouts or some layout does not have the button you added, and omits runtime exception. Writing and testing for every permutations of screen size prevent you to focus on the main idea of your program.

    The function of your app might not be changed regardless the size of the screen. Changed thing is the position and the size of widgets. Maintaining multiple versions of basically the same thing is not a hacker way.

    Responsive layout on Android

    It is much better to write a new layout class that acts responsively. For the example screenshot above, the layout is consisted with two blocks, and the position of each block is changed according to the orientation. This can be achieved with plain-old LinearLayout with the orientation attribute. I wrote a new class that takes charge of the behavior:

    class ResponsiveLayout(implicit context: Context) extends SLinearLayout {
      private val portrait = context.getResources.getConfiguration
                            .orientation == Configuration.ORIENTATION_PORTRAIT
      if (portrait) orientation = VERTICAL
      private var first = true
    
      override def +=(v: View) = {
        if (first) {
          v.<<(if (portrait) FILL_PARENT else WRAP_CONTENT, WRAP_CONTENT)
          first = false
        }
        super.+=(v)
      }
    }
    

    It checks current screen orientation, and assigns different properties according to it. It may feels naive for you, but it works fine in practice. Android layout has much room to improve in current status, especially when it is compared with HTML+CSS. However, HTML+CSS undergone numerous refinements for nearly two decades. Android could catch up with it in short time if intensive researches are done based on a solid foundation.

    Wednesday, February 13, 2013

    Enriched methods of TelephonyManager

    TelephonyManager has several listeners that can be invoked for a certain phone state changes.

    val callStateListener = new PhoneStateListener() {
      override def onCallStateChanged(state: Int, incomingNumber:String) {
        if(state == TelephonyManager.CALL_STATE_RINGING) doSomething()
      }
    }
    
    override def onCreate(b: Bundle) {
      super.onCreate(b)
      // ...
      telephonyManager.listen(callStateListener, 
                              PhoneStateListener.LISTEN_CALL_STATE)
    }
    
    override def onDestroy() {
      telephonyManager.listen(callStateListener, 
                              PhoneStateListener.LISTEN_NONE)
      // ...
      super.onDestroy()
    }
    

    The boilerplates that keeps track the listener object obscures the main idea from your code. Using the trait Destroyable, listening phone states becomes much simpler:
    onCallStateChanged((state, number) => {
      if(state == TelephonyManager.CALL_STATE_RINGING) doSomething()
    })
    

    This enhancement is available on the current snapshot, and will be released in version 1.1.

    Tuesday, February 12, 2013

    Better resource releasing on Android

    In Android programming, suppose you have some resources to release, then you probably override onDestroy() method. For example, unregistering BroadcastReceiver can be done as the following Java code:
    class MyActivity extends ListActivity {
        protected List<BroadcastReceiver> receivers = 
                             new ArrayList<BroadcastReceiver>()
    
        public IntentFilter registerReceiver(BroadcastReceiver receiver,
                                             IntentFilter filter) {
            receivers.add(receiver);
            super.registerReceiver();
        }
    
        public Void onDestroy() {
            for(receiver : receivers) {
                unregisterReceiver(receiver);
            }
            super.onDestroy();
        }
    }
    
    Looks not bad, although the code is wordy. However, a really bad thing is revealed when you have to release various resources in multiple classes. You might have a TCP connection, opened file to be closed, phone state listener to be unregistered, or asynchronous job to be properly cancelled. Therefore, the compact representation of resource releasing is important. Moreover, the resource-releasing code should be reused between different classes when it is needed in both Services and Activities.

    However, current Android resource management has two reusability issues:

    Problem 1: No common parent of Activity and Service

    For the example above, there is no way to reuse the code between Activities and Services, because Activity and Service has no common parent interface sharing onDestroy() method!


    Problem 2: Maintaining list of resources

    The code shown above is consisted with three parts:
    1. Allocates a collection that will contain opened resources (in line 2)
    2. Stores a resource that is acquired (in line 6)
    3. Release the resources (in lines 11-13)
    If you manage different kinds of resources (e.g. TCP connection and files), the code is not reusable between the other kinds of resources. That is, you have to allocate two collections for two different resources, and release it individually in onDestroy() method. For example, suppose your service opens files and starts threads that should be closed onDestroy():

    class MyService extends Serivce {
        protected List<WorkerThread> threads = new ArrayList<WorkerThread>()
        protected List<File> files = new ArrayList<File>()
    
        public void openFile(...) {
            //...
            receivers.add(openedFile);
        }
        public void startNewJob(...) {
            //...
            threads.add(workerThread);
        }
    
        public Void onDestroy() {
            for(file : files) {
                file.close();
            }
            for(thread: threads) {
                thread.sendCancelMessage();
            }
            super.onDestroy();
        }
    }
    

    What if other kinds of resources to be managed? What if the same thing is needed in your Activity? This is a specimen of reusability hell.

    A solution

    In Scala, the example above could be reduced as follows:
    class MyService extends SSerivce {
      def openFile(...) {
        //...
        onDestroy(openedFile.close())
      }
      def startNewJob(...) {
        //... brace can also be used
        onDestroy {
          workerThread.sendCancelMessage()
        }
      }
    }
    

    Because Scala supports anonymous function as a parameter, the code passed through onDestroy(...) method will be executed when the service is destroyed.

    If you have to use the same code in your activity, you can extract it as a trait:
    trait OpenFile extends Destroyable {
      def openFile(...) {
        //...
        onDestroy(openedFile.close())
      }
    }
    
    Then, just inherit it in your activities or services:
    class MyActivity extends SActivity with OpenFile {
      // Done! just use openFile() method and forget about releasing it.
    }
    

    This solved the problems by no explicit access of collection object, and introducing common triats that inherits both SActivity and SService.
    The trait Destroyable is defined for onDestroy(), and Creatable is defined for onCreate(), and other lifecycle related methods including onResume(), onStart(), onPause(), and onStop() are implemented as well.


    Destroyable in Action: UnregisterReceiver

    For the case of BroadcaseReceiver, it is done by just inherit a trait in your class.
    class MyService extends SService with UnregisterReceiver {
      // Done. Every registered receivers unregistered automatically.
    }
    
    This is the full source code of UnregisterReceiver implimentation:
    trait UnregisterReceiver extends ContextWrapper with Destroyable {
      override def registerReceiver(receiver: BroadcastReceiver, 
                                    filter  : IntentFilter) = {
        onDestroy {
          unregisterReceiver(receiver)
        }
        super.registerReceiver(receiver, filter)
      }
    }
    

    Monday, February 11, 2013

    Scaloid 1.0 is released

    Today, I released Scaloid 1.0. Some of major improvements are including:
    • Source code is subdivided into several groups
    • Traits Destroyable and Creatable is introduced
    • style() is safe for non-exhaustive PartialFunction pattern matching

    For a short comment about the last thing, let's see an example as follows:
    new SLinearLayout {
      style {
        case b: SButton => b.text(b.text.toString.toUpperCase)
      }
      STextView("Hello")
    }
    
    The style is defined only for the class SButton. However, a view widget STextView is defined in the layout. Previous version of Scaloid emits an exception because the pattern matching is not exhaustive. In Scaloid 1.0, it simply ignores it when the widget is not defined in the styles.

    Wednesday, February 6, 2013

    Scala is better than injection framework

    Android programming often drives me crazy, because I have to write too much to do a simple work. Hard to write is just a little problem when it is compared to poor maintainability. For example, let us see a typical Activity implementation:

    class AndroidWay extends Activity { 
        TextView name; 
        ImageView thumbnail; 
        LocationManager loc; 
        Drawable icon; 
        String myName; 
    
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main);
            name      = (TextView) findViewById(R.id.name); 
            thumbnail = (ImageView) findViewById(R.id.thumbnail); 
            loc       = (LocationManager) 
                            getSystemService(Activity.LOCATION_SERVICE); 
            icon      = getResources().getDrawable(R.drawable.icon); 
            myName    = getString(R.string.app_name); 
            name.setText(myName); 
        } 
    }
    

    The method onCreate is full of boilerplate code that makes maintaining painful. To reduce them, peoples thought about injection frameworks. Roboguice is one of them. It can improve the original code to the following way:

    class RoboWay extends RoboActivity { 
        @InjectView(R.id.name)             TextView name; 
        @InjectView(R.id.thumbnail)        ImageView thumbnail; 
        @InjectResource(R.drawable.icon)   Drawable icon; 
        @InjectResource(R.string.app_name) String myName; 
        @Inject                            LocationManager loc; 
    
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main);
            name.setText(myName);
        } 
    } 
    

    Although it seems to be much improved, there are some drawbacks in this approach:
    • Runtime performance
    • Wiring verbose XML layout
    • Not type-safe
    If you make a mistake on the type of the view widget, your app will revenge you with a horrible runtime exception. Fortunately, Scala provides a much elegant solution. Here I show a direct translation of the example above to Scala language:

    class ScaloidWay extends SActivity { 
      lazy val name      = findView(TR.id.name) 
      lazy val thumbnail = findView(TR.id.thumbnail)
      lazy val icon      = R.drawable.icon.r2Drawable
      lazy val myName    = R.string.app_name.r2String
      lazy val loc       = locationManager
    
      onCreate { 
        contentView(R.layout.main)
        name.setText(myName)
      } 
    } 

    Lazy values replace injections, with no runtime performance degradation. And the code becomes much cleaner. However, this is not a final improvement. Another clutter that did not shown in this example is XML layout. It is too wordy to write a simple idea, and careful wiring with your code is mandatory. We can eliminate the source of the problem, by not writing layout in XML. The following example builds UI layout within an ordinary Scala code:

    class ScaloidWay extends SActivity { 
      lazy val name      = new STextView(R.string.app_name)
      lazy val thumbnail = new SImageView()
    
      onCreate { 
        contentView(new SVerticalLayout += name += thumbnail)
      } 
    } 

    Less significant `lazy val loc` is omitted because we can use `locationManager` whenever it needed, and implicit conversion replaces the position of `myName` and `icon`.


    Tuesday, February 5, 2013

    Scaloid 0.9 is released

    Scaloid 0.9 is out. Major improvements made on this version are:


    Scaloid is continuously getting mature. Feel free to try out, experience zen of Android programming, and give me a feedback.

    Monday, January 28, 2013

    A CSS-like styling on Android

    Android SDK provides styles and themes to reuse common properties on XML layout. However, XML is verbose, and requires endless findByViewId(...) to reference it in your code.

    Today I released Scaloid 0.8, which features a new way of styling Android components. Before saying too much words, let's start with an example:
    new SVerticalLayout {
      STextView("I am 10 dip tall")
      STextView("Me too")
      STextView("I am taller than you")
      SEditText("Yellow input field")
      SButton("Red alert!")
    }

    This code displays five components on the screen:



    Then, let me add a style:

    new SVerticalLayout {
      style {
        case b: SButton => b.textColor(Color.RED).onClick(toast("Bang!"))
        case t: STextView => t.textSize(10 dip)
        case v => v.backgroundColor(Color.YELLOW)
      }
    
      STextView("I am 10 dip tall")
      STextView("Me too")
      STextView("I am taller than you").textSize(15 dip) // overriding
      SEditText("Yellow input field")
      SButton("Red alert!")
    }
    

    This code results the layout shown below:

    Even if you are new to Scaloid, you may easily get the point of the code. As you expected, if you clicked the button, the toast message "Bang!" is shown.

    In styles of Android SDK or even in CSS, only static properties can be assigned (such as color, margin, font, etc ...). However, Scaloid can do anything with the component, such as assigning onClick behavior, adding a new component, or replacing the component itself with another component.

    For example, Scaloid styles can append another view component to the layout. let's start with a very simple code:
    new SVerticalLayout {
      SEditText("Name")
      SEditText("Address")
    }
    

    Needless to say, this shows an input field with the default value "Name", as shown below:


    Then, we add a style like this:
    new SVerticalLayout {
      style {
        case t: SEditText =>
          STextView(t.text)
          t.text("").onFocusChange(toast("You entered: " + t.text))
      }
       
      SEditText("Name")
      SEditText("Address")
    }
    
    In this time, you can see:

    The value "Name" is moved to a new text view. Also, if you moved the focus, the toast "You entered: ..." will be shown.

    The signiture of the style function is style(stl: View => View). That means the style specification should return a view component, that is actually visualized on the screen. Therefore you can return another component to replace the original. For example:
    new SVerticalLayout {
      style {
        case t: SEditText => new STextView().text(t.text)
      }
     
      SEditText("You cannot edit me")
    }

    Then every SEditText field is relpaced by a STextView component.


    Type-safety for your pleasure

    Thanks to Scala language, all of these examples are type-safe, which means that auto-completion of your IDE will suggest valid candidates, and if you made a mistake, IDE will warn you and the code will not be compiled at all.


    Thursday, January 24, 2013

    Scaloid 0.7.1 is released

    This version contains a quick fix of a bug that occurs when it compiled with Scala 2.10 (pocorall/scaloid#8).

    From this version, compiled artifact of Scaloid will be released for Scala 2.10. However, Scaloid still can be built with Scala 2.9.

    Wednesday, January 23, 2013

    Scaloid powered Soundcorset metronome & tuner


    I recently released all-in-one metronome and tuner application, called Soundcorset metronome & tuner. It covers all of the basic features required to metronomes and tuners, and I will grow it constantly.

    Using Scaloid, the UI layout is written incredibly concise without any XML. For example, the image shown below is the screenshot of the main activity:


    In "bpm" section, the code is written as:

    this += new SLinearLayout {
      SButton("-", bpm -= 1).textSize(25 dip).<<(55 dip, FILL_PARENT).>>
      SButton("+", bpm += 1).textSize(25 dip).<<(55 dip, FILL_PARENT).>>
      this += new SVerticalLayout {
        STextView(R.string.bpm)
        bpmText = STextView().textSize(25 dip)
        latinBpmText = STextView("Allegro")
      }.<<.wrap.marginLeft(10 dip).>>
    }.<<.>>
    

    A simple 9 lines of code actually build the UI and wire the logic. Look at the statement "bpm -= 1" at the line 3. This simple and intuitive code actually play the beat a little slowly, move slidebar, and change the number indicates the bps. All these chores are hidden behind the assignment overload function:

    def bpm_=(b: Int) {
      // move the progress bar and do more
    }
    

    Then Scala language permits fancy expressions such as "bpm += 10".