7/13/2010 update:
Thanks to the great response (and many hundreds of visits to this page over the last two days), I’ve gone ahead and created a real project website for AML at http://www.amlcode.com, as well as the @amlcode Twitter account. If you’re interested in more updates, check those out. Thanks for all the comments and ideas! Keep them coming!
This post still has some good info and some great comments, so don’t neglect it completely. It might get lonely.
I gave myself a crash course in Android development over the last few days. I’d officially been part of an Android team as part of a project management class in my last quarter at Cal Poly Pomona, but some of the other members on the team ended up doing most of the actual development, so my instructive coding experience was pretty minimal. I knew enough to get the Android SDK installed in Eclipse (which is painfully slow, by the way!), but that was all. Everything else was new to me.
Now, I am very familiar with C, C++, and Java, even though most of my coding for my job is done in PHP, so picking up the Android vocabulary within Java was much easier for me than it would have been if I had no programming experience at all.
I don’t have a specifically defined project to work on yet, but I do have some general requirements for the Android app(s) I’m sure I will be developing in the near future. Specifically, I know I will need these features:
- Native implementation (Android UI, not HTML5)
- Dynamic externally generated content and navigation
Both of those two features together are, I believe, not a common combination. It’s simple to have dynamic externally generated content and navigation, if you use HTML and a browser. It’s also simple to have a native UI support externally generated content, if that content always fits into a pre-defined structure which you build into your app. But what if you want an app that supports a system with very little known ahead of time—just an email address and password, for instance—and the rest of it need is determined based on parameters, permissions, and a web service API?
Then, I thought, why not write a native Android library that will accommodate that very thing?
And that’s what I did.
I even had the presumptuous audacity to give it an official-sounding name, though it is by no means official (or truly useful) just yet. There is no W3C specification for it. And for all I care, it may never become official, but even if I’m the only one who uses it, this library it will certainly make things easier for me. And on top of that, it’s been a great learning experience over the last four days.
Ladies and gentlemen, I introduce to you AML, the App Markup Language, a simple XML-based language that allows you to easily build a clean, functional application for your mobile device.
It resembles HTML in some ways, but it is not a subset of HTML. It is designed to be intuitive and easy, and while it does not implement every possible feature achievable with native Android code, the goal is for it to cover the vast majority of what is necessary for information-based apps, and leave the rest up to you to implement as you desire. It probably won’t help out much with games, but it’s perfect for mobile implementations of websites. It can even be used as part of a local-only application to quickly build the UI instead of using Java code or Android’s layout XML structure.
Additionally, I would love at some point to extend AML in two directions: one, to have it support other devices (namely the iPhone and iPad), and two, to support different languages for the markup (namely JSON, perhaps YAML). While I don’t need these right now and may not actually need them for some time, there is nothing really Android-specific or XML-specific about the language. I have never written code for iOS, so I don’t know if the behavior is inherently different enough to cause a problem, but I bet it isn’t. You should be able to use the same AML markup to generate nearly identical experiences on Android and on iOS.
So, why is AML so cool? Why would anyone want to use it? Check this out.
The images on the right shows a set of different input objects in an Android app. It’s just an example, obviously—an app in the Market that looked like this would be odd indeed. However, it does illustrate a very basic layout with a few different objects.
Now, anyone who has done any Android development know that there isn’t anything truly difficult about building something like this. If you write your own “main.xml” layout file and use it for your Activity object’s content view though, it can be a little tedious. You can use a tool like DroidDraw to speed things up (which is an excellent idea if you need a static layout), but with both of these approaches, your design will be hard-coded into your app. You can only make changes on the fly through clever uses of the LayoutInflater service.
Your other option is to build the layout using only code. This allows for more dynamic design, for sure, but doing this manually is still tedious. AML bridges the gap between an external data source and the native application, so that the external source can very simply instruct the app what to build and how it should behave.
This is the Android layout XML necessary to create the layout shown above in the screenshot on the right:
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Button" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Checkbox" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon" />
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Text"
android:singleLine="true" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Password"
android:password="true"
android:singleLine="true" />
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="Radio Button 1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Radio Button 2" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Radio Button 3" />
</RadioGroup>
</LinearLayout>
Keep in mind that the above code is basically fixed, and cannot really be customized at runtime on a large scale. Now, for comparison, here is the AML necessary to create the layout above:
<aml>
<input type="button">Test Button</input>
<input type="checkbox">Test CheckBox</input>
<input type="togglebutton" checked="yes" />
<input type="imagebutton" image="drawable/icon" />
<input type="text">Test Text</input>
<input type="password">Test Password</input>
<radiogroup>
<input type="radiobutton" checked="yes">Radio Button 1</input>
<input type="radiobutton">Radio Button 2</input>
<input type="radiobutton">Radio Button 3</input>
</radiogroup>
</aml>
It’s that simple. Additionally, for my tests, this layout info was actually being pulled from a web service, just so I could prove to myself that I could do it. The web service dynamically built that layout.
Seriously, can it get any easier than that? You can store this kind of layout definition in your app code and reference it directly from there, or you can use a web service to build this stuff on the fly and send it to your app (though you might want to implement some sort of caching mechanism in that case, for efficiency). The AML library is in its own package, and doesn’t require any imports from your package to work. You do need to put the template layout XML files into your /res/layout
folder, but that’s all. AML doesn’t require you or your web service to know the details of how Android builds its views. It doesn’t depend on some extra plugin installed on your device, and it isn’t passing your app code through another service. You probably still have to write some Java code to accomplish your goal, but this makes the whole thing easier.
So far, what I have written only supports layouts, but no actions. Many objects support attributes like align
, valign
, fontsize
, padding
, color
, and bgcolor
, to name a few. The rest of the code just isn’t there yet. I have been building the tap
and hold
attributes into buttons and other clickable objects, but I’m not done. I haven’t done a date picker, time picker, or spinner (Android’s version of an HTML <select>
element). But it’s coming together very quickly—a lot faster than I thought it might. It’s been an awesome learning experience so far though.
I’m writing this for me, honestly, but I’m really interested in any kind of outside interest. Any questions, comments, or recommendations? Has anyone else done this? Would you be excited to get your hands on this code? If you used it, what would you need it to be able to do?
Let me know in the comments!