In a nutshell Mechanoid is an Eclipse Plugin sporting a set of code generators for Android driven by DSL's (Domain Specific Languages) with full Eclipse Editor Support for the rapid development of Android applications.
The following building blocks currently make up the high-level feature set of Mechanoid.
Mechanoid DB
Use the Sqlite language itself to generate Android content providers and the ActiveRecord pattern with rich editor support.
Mechanoid Net
Generate REST over JSON service clients with this simple language to describe JSON Objects and REST methods.
Mechanoid Ops
A Framework to create and run decoupled background operations as described in Virgil Dobjanschi's Google IO REST 2010 presentation.
Mechanoid Prefs
A simple DSL to generate thin wrappers for strongly typed access to shared preferences.
Learn More
Scroll down to learn more about each component or see the Getting Started Guide for details on how to setup an Android project with Mechanoid.
Mechanoid DB
Mechanoid DB is a powerful tool with fully blown editor supporting the Sqlite language itself as the driver to generate top quality Android Sqlite-backed Content Providers.
Define your database
With Mechanoid DB you define your database in a mechdb file with a full featured Eclipse editor supporting syntax-highlighting, code completion and more.
package com.robotoworks.examples.recipes.content database RecipesDB { migration { create table recipes ( _id integer primary key autoincrement, title text, description text ); } }
Use the generated API
After saving the mechdb file you can start using the generated code.
You can insert data easily
Recipes.newBuilder() .setTitle("Omelette") .setDescription("Wonderful omelette with cheese") .insert();
Or insert with ActiveRecord if you prefer?
RecipesRecord record = new RecipesRecord(); record.setTitle("Ragu"); record.setDescription("Serve with pasta"); record.save();
SQuery for your CursorLoader's
CursorLoader loader = SQuery.newQuery().createSupportLoader( Recipes.CONTENT_URI, new String[] { Recipes._ID, Recipes.TITLE, Recipes.DESCRIPTION });
Learn More
Mechanoid DB supports schema migrations first class and almost all of the sqlite syntax including views, joins, triggers and more, you just need to define the sql and Mechanoid will generate the code!
To find out more read the Mechanoid DB Documentation.
Mechanoid Net
Mechanoid Net is a JSON over REST client generator for Android, backed by a powerful Eclipse editor
Define your service client
Define your REST client with a language that represents the HTTP Protocol
client RecipesServiceClient "http://www.robotoworks.com/example" { get getRecipeList /recipes { params limit:int, query:String response Recipe[] } get getRecipe /recipe/id:int { response Recipe[] } post addRecipe /recipes { response { recipe_id:int } body Recipe } delete deleteRecipe /recipe/id:int { response boolean } }
And describe your JSON entities
Describe your JSON graph with entities
entity generate Recipe { recipe_id:int, title:String, description:String }
Then use the generated API
Use the generated client API to access your REST service
RecipesServiceClient client = new RecipesServiceClient(); // Get a list of recipes Response<GetRecipeListResult> recipeListResponse = client.getRecipeList(); // Get a recipe Response<GetRecipeResult> recipeResponse = client.getRecipe(new GetRecipeRequest(123)); // Add a recipe Recipe recipe = new Recipe(); recipe.setTitle("Ragu"); recipe.setDescription("Great with Pasta"); Response<AddRecipeResult> addRecipeResponse = client.addRecipe(new AddRecipeRequest(recipe)); // Delete a recipe Response<DeleteRecipeResult> deleteRecipeResponse = client.deleteRecipe(new DeleteRecipeRequest(123));
Learn More
Mechanoid Net is a powerful tool to describe your JSON over REST service clients, it can save you hours of time writing parsing logic and fixing issues freeing yourself from boiler-plate problems.
To find out more read the Mechanoid Net Documentation.
Mechanoid Ops
Mechanoid Ops is a framework for running background operations that are decoupled from the UI, first described by Virgil Dobjanschi in his GOOGLE IO REST 2010 Presentation.
In Mechanoid we call this the Operation Service Pattern, we describe our operations using a simple DSL, for each operation a class stub is generated in which we can do our background work and return the result to listeners.
Define your operations
We use a simple DSL to define our operations in a *.mechnet file
package com.robotoworks.examples.recipes.ops service Recipes { operation getRecipes() operation getRecipe(long id) operation addRecipe(String title, String description) operation deleteRecipe(long id) }
Implement your operation stubs
For each operation a java class stub is generated, we can then, for instance, make network requests...
public class AddRecipeOperation extends AbstractAddRecipeOperation { @Override protected OperationResult onExecute(Args args) { // Operation arguments are available in Args, ie:- String title = args.title; String description = args.description; // Using a Mechanoid Net generated rest client... Recipe recipe = new Recipe(); recipe.setTitle(title); recipe.setDescription(description); RecipesServiceClient client = new RecipesServiceClient(); int newRecipeId = 0; try { Response<AddRecipeResult> response = client.addRecipe(new AddRecipeRequest(recipe)); response.checkResponseCodeOk(); AddRecipeResult result = response.parse(); newRecipeId = result.getRecipeId(); } catch (ServiceException e) { // In the event of an error we can // return the Exception as an error result return OperationResult.error(e); } // If everything is good we return an ok result, return OperationResult.ok(bundle); } }
Execute your operations asynchronously
For each defined service, a service bridge is generated which we use to execute operations
// Bind a callback listener Ops.bindListener(listener); // Create an operation intent using the generated static helper method Intent intent = AddRecipeOperation.newIntent("Ragu", "Great with Pasta"); // Execute int addRecipeOperationId = Ops.execute(intent);
Listen and act on operations completing
Implement an OperationServiceListener to handle the callback
private OperationServiceListener listener = new OperationServiceListener() { @Override public void onOperationComplete(int id, OperationResult result) { if(id == addRecipeOperationId) { if(result.isOk()) { // TODO: Do something } else { Throwable error = result.getError(); // TODO: Deal with the error } } } };
Check to see if operations are currently pending
We can use the generated service bridge to check if an operation is currently pending completion with a given operation id.
boolean isPending = Ops.isOperationPending(addRecipeOperationId);
Alternatively, use an OperationManager in your UI
Managing callbacks for operation ids and checking operations can be cumbersome in UI, especially with orientation changes, instead we can use a manager and provide our own unique identifiers to identify specific operations.
public class AddRecipesActivity extends FragmentActivity { // Define your own ID private static final int OP_ADD_RECIPES = 123; private SupportOperationManager mOperationManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create an instance of manager for your bridge mOperationManager = SupportOperationManager.create(this, mCallbacks); // Execute your operation using the manager Intent intent = AddRecipeOperation.newIntent("Ragu", "Great with Pasta"); mOperationManager.execute(intent, OP_ADD_RECIPES, false); } // Implement the callbacks private OperationManagerCallbacks mCallbacks = new OperationManagerCallbacks() { @Override public void onOperationComplete(int id, OperationResult result, boolean fromCache) { if(id == OP_ADD_RECIPES) { if(result.isOk()) { // TODO Do something } else { Throwable error = result.getError(); // TODO Do something with the error } } } }; }
Learn More
Mechanoid Ops provides a framework for executing asynchronous operations, and takes the pain away from handling background operations in the Android UI Lifecycle.
To find out more read the Mechanoid Ops Documentation.
Mechanoid Prefs
Mechanoid Prefs is a simple DSL to describe and generated Android Shared Preferences wrappers.
Define your shared preferences
Preferences are defined in a *.mechprefs file, with Eclipse Editor support.
preferences User { name:String = "Anonymous" age:int cash_balance:float likes_ragu:boolean }
Access your generated preferences wrapper
We can now access preferences using the generated code.
// Get an instance of the generated wrapper UserPreferences prefs = UserPreferences.getInstance(); // Easily access preferences int age = prefs.getAge(); boolean likesRagu = prefs.getLikesRagu(); float cashBalance = prefs.getCashBalance(); // Easily save prefences prefs.edit() .putAge(37) .putLikesRagu(true) .putCashBalance(-10000) .commit(); // And the same flexibility... // Still access properties String ageKey = UserPreferences.Keys.AGE; // Still Register listeners prefs.registerOnSharedPreferenceChangeListener(listener); // Access underlying preferences SharedPreferences realPreferences = prefs.getSharedPreferences();
Learn More
Although very simple, Mechanoid Prefs makes access to your preferences look pretty but offers the same flexibility as the underlying SharedPreferences.
To find out more read the Mechanoid Prefs Documentation.
Get Started
Visit the Mechanoid Documentation to get started.