Thursday, June 17, 2010

Plugins

I blogged 2 years ago that Android is a surprisingly modern application platform, I even said that it was the most modern application platform. This is partly due to Android's advanced component features. These features are not always evident to the naked eye so I present here a standard exercise to demonstrate them.

Click here to download the example program.

In this exercise we will implement a plugin framework for an example program. Plugins are components that connect to the main application over a uniform interface and are dynamically deployable. The download package contains two Android applications. The first, pluginapp is the example application that will use the plugins. The second, plugin1 is a plugin package that contains two plugins for pluginapp. Plugin1 package is not visible among the executable applications, it does not expose any activity that may be launched by the end user. If deployed, however, its plugins appear in pluginapp. Plugin deployment/undeployment is dynamic, if you uninstall plugin1 package while pluginapp is running, pluginapp notices the changes and the plugins disappear from the plugin list.




In order to implement these functionalities, the following features of the Android framework were used.


  • Each plugin is a service. Plugin1 exposes two of them. In order to identify our plugins, I defined a specific Intent (aexp.intent.action.PICK_PLUGIN) and I attached an intent filter listening to this intent in plugin1's AndroidManifest.xml. In order to select a particular plugin, I abused the category field again. One plugin can be accessed therefore by binding a service with an intent whose action is aexp.intent.action.PICK_PLUGIN and whose category equals to the category listed in AndroidManifest.xml of the package that exposes the plugin service.
  • Plugins are discovered using the Android PackageManager. Pluginapp asks the PackageManager to return the list of plugins that are bound to aexp.intent.action.PICK_PLUGIN action. Pluginapp then retrieves the category from this list and can produce an intent that is able to bindthe selected plugin.
  • Pluginapp updates the plugin list dynamically by listening to ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and ACTION_PACKAGE_REPLACED intents. Whenever any of these intents are detected, it refreshes the plugin list.
Even though Android is not as sophisticated as OSGi when it comes to component framework, it has every necessary element. It has a searchable service registry, packages can be queried for the services they expose and there are deployment events.

Sunday, June 6, 2010

Shake-walk-run

Well, anybody can draw up frightening equations like I did in the acceleration signal analysis report in my previous post and claim that they work just because of some diagrams made by a mathematical analysis program. You'd better not believe this sort of bullshit before you experience it yourself. To help you along that path, I implemented a simple application that let you try out, how these methods work in real life.

Click here to download the example program.

If you open this simple application, you can enable the sampling with a checkbox. Once the sampling is switched on, the service behind the app constantly samples the acceleration sensor and tries to detect motion patterns. It is able to distinguish 3 patterns now: shake, walk and run. Not only it distinguishes these patterns, it also tries to extract shake, step and run count. Unfortunately I tested it only on myself so the rule base probably needs some fine tuning but it works for me. The walk detector uses the w3 wavelet (read the report if you are curious, what w3 wavelet can be) and is therefore a bit slow, it takes about 2-3 seconds before it detects walking and starts counting the steps but that delay is consistent - if you stop walking, it continues counting the steps it has not counted yet.

The moral for this application is that the tough part in detecting motion patterns is the rule base behind the signal processing algorithms. It is OK that wavelets separate frequency bands and signal power calculation allows to produce "gate" signals that enable/disable counting for certain motion patterns. But where are the signal power limits for e.g. shaking and how to synchronize "gate" signals with the signals to be counted? This example program is a good exercise as you can observe, how it uses delayers and peak counters synchronized with signal power calculators to achieve the desired functionality.

Some notes on the implementation. The machinery behind the background service that sends events to an activity is described in this and this blog posts. Also, observe the debug flags in SamplingService, if you set one of these, the service spits out signal data that you can analyse with Sage later. I did not include the keep-awake hack into this implementation because it was not necessary on my Nexus One with the leaked Android 2.2. I put a public domain license on the download page because somebody was interested in the license of the example programs.

I have to think a bit, where I want to go from here. The most attractive target for me is to formalize all these results into a context framework for Android applications but I may fiddle a bit more on signal processing.