Introduction
MIT App Inventor (previously known as Google App Inventor) is a RAD tool for developing Android applications. It has many useful features, but it has very limited support of web service communications.
Android applications developed with App Inventor can only communicate with web service using TinyWebDb interface. Basically, TinyWebDb is an interface for simple web-based key-value database with only 2 methods: StoreValue(tag, value)
and GetValue(tag)
.
The following article describes the implementation of TinyWebDb interface using WCF service, which allows communication between Android application and .Net code.
Background
WCF (Windows Communications Foundation) is a technology created by Microsoft in the .NET Framework for building connected, service-oriented applications. For introduction into creating web services using WCF, please use this article: A Beginner's Tutorial for Understanding Windows Communication Foundation (WCF)
App Inventor is a very simple web-based tool for visual programming for Android, which doesn’t require any Java skills or Android application lifecycle knowledge. For introduction into App Inventor, please use this article: Google App Inventor
TinyWebDb API
TinyWebDb if a RESTful interface, which means it uses basic HTTP requests like GET or POST (alternatively to more complex protocols like SOAP or CORBA, where protocol-specific request formats are used).
There are 2 methods in TinyWebDb interface: StoreValue and GetValue.
StoreValue is called with HTTP POST request with 2 text parameters “tag” and “value”.
URL: {ServiceURL}/storeavalue
Request format is XML with content type “application/x-www-form-urlencoded
”. This is a default value for WCF service, so it shouldn’t be specifically stated in the method definition.
Response format is JSON: ["STORED", "{tag}", {value}]
, i.e. ["STORED", "testValue", "\"Hello World!\""]
GetValue is called with HTTP POST request with 1 text parameter “tag”.
URL: {ServiceURL}/getvalue
Just like with StoreValue, request format is XML with default content type.
Response format is JSON: ["VALUE","{tag}", {value}]
, i.e. ["VALUE", "testValue", "\"Hello World!\""]
Implementing TinyWebDb API in WCF Service
- Open VS 2010. Select new Project, then select WCF -> WCF Service Application.
- Right click the project, select Add->New item->WCF Service. 2 files will be added: Interface (starts with I, ends with .cs, i.e. IMyService.sc) and service (ends with .svc, i.e. MyService.svc).
- Open interface file. Here we need to define operation contracts for methods StoreValue and GetValue. Following code does the trick:
[ServiceContract]
public interface IMyService
{
[OperationContract(Name = "getvalue")]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "getvalue")]
string[] getvalue(Stream data);
[OperationContract(Name = "storeavalue")]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "storeavalue")]
string[] storeavalue(Stream data);
}
Here we explicitly specify HTTP request type (POST in both cases), response format (JSON), and returning type (array of string, which will be automatically converted to JSON format [“string1”, “string2”,…]).
- Open service file, and implement the interface described above. For the sake of simplicity, I hard-coded returned values. In real life, some meaningful business logic has to be implemented inside these 2 procedures:
public class MyService : IMyService
{
public string[] getvalue(Stream data)
{
StreamReader sr = new StreamReader(data);
string stringData = sr.ReadToEnd();
string tag = stringData.Substring(4);
string[] resultStringArray = new string[3];
resultStringArray[0] = "VALUE";
resultStringArray[1] = "testValue";
resultStringArray[2] = "Hello World!";
return resultStringArray;
}
public string[] storeavalue(Stream data)
{
StreamReader sr = new StreamReader(data);
string stringData = sr.ReadToEnd();
string tag = stringData.Substring(4, stringData.IndexOf("&value=") - 4);
string value = stringData.Substring(stringData.IndexOf("&value=") + 7);
string[] resultStringArray = new string[3];
resultStringArray[0] = "STORED";
resultStringArray[1] = "testValue";
resultStringArray[2] = "Hello World!";
return resultStringArray;
}
}
- Open Web.config file, and apply some changes necessary for RESTful JSON to work. It means we need to define
webHttpBinding
& mexHttpBinding
, and define httpGetEnabled
="true" for service and webHttp
for endpoint:
="1.0"
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceBehavior" >
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="WcfRestBased.MyService"
behaviorConfiguration="myServiceBehavior" >
<endpoint name="webHttpBinding"
address="" binding="webHttpBinding"
contract="WcfRestBased.IMyService"
behaviorConfiguration="webHttp"
>
</endpoint>
<endpoint name="mexHttpBinding"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
/>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
In order to specify correct Service Name, right click the service & select ViewMarkup option.
Now build the project and deploy it to host. If you are going to use local Wi-Fi to access the web server, you can use localhost IIS hosting, like described here: A Beginner's Tutorial on How to Host a WCF Service (IIS Hosting and Self Hosting)
Accessing WCF Service from App Inventor application
- Go to http://appinventor.mit.edu/, click “Create” to create new project. You will be prompted to sign up if it is your first visit to App Inventor. You will see an empty project like this:
- Drag 2 labels and 2 buttons to the screen
- Open “Storage” category in Palette, drag “TinyWebDb” component to the screen. It will be added to “Non-visible components” list
- In properties of TinyWebDb component, change ServiceURL to the address of your newly created service, i.e. http://192.168.1.38/MyService.svc If you don’t know the IP address of your computer, click Start, type “cmd” in search textbox, and type “ipconfig”.
- Click “Blocks” button in top right corner of App Inventor editor. This will open your project code. Drag code components from the “Blocks” category until your application looks like this:
Now you need to test your application on real Android device.
- First, install application “MIT AI2 Companion” from Google Play store to your Android device.
- Next, on your project page in App Inventor, click “Connect”->”AI companion”. Connect your Android device to your project using QR code or text code shown on screen
- When your newly created application opens on Android device, click “Store value” and “Get value” buttons. You should see that the application received response from web server
Conclusion
This simple example demonstrates, how to connect Android application to WCF service. Once connected, we can implement any custom logic we want: create a chat, request and send values from database, and so on. With this technique, you can turn Android device into remote controller for virtually any .Net application of your choice.
Credits
Following articles and blog posts provided valuable insights:
A Beginner's Tutorial on How to Host a WCF Service (IIS Hosting and Self Hosting)
Developing WCF Restful Services with GET and POST Methods
A Beginner's Tutorial for Understanding Windows Communication Foundation (WCF)
Google App Inventor
TinyWebDB PHP Web Service