Let Android support multiple programming languages
Can we write programs in Android with other languages? The answer is yes.
Introduction
Java is used as the main language on Android to write applications. Although NDK is provided, it is difficult to write native GUI applications. Can we write programs with other languages? The answer is yes. We can wrap Android Java classes to expose to special languages, and then uses that language to develop applications. The work should be done once instead of doing it for each language again and again. Using the middleware named CLE (Common Language Extension), we can achieve this. Using CLE, all the work needed to be done to encapsulate Android classes into CLE objects is done, then multiple languages are supported through the CLE interface.

Wrapping an Android class into a CLE object, there are four steps
1. Create CLE service and object description.
OnCreate
and OnDestroy
event. In the procedure of the OnCreate
event, we create and record a corresponding instance of the Android class, and in the OnDestroy
event, we free the instance.
OnCreate
event, after creating the Android instance, we add the event listeners to it. When the listener is triggered, we generate the CLE event, and the event will be routed by CLE to the application layer.
A simple example
Here we use a simple example to explain the above procedure in detail. In this example, we encapsulate a button class.
Wrapping the Android Button class
1. Create a CLE service and object description, we can do this with srpdebug tools.
<!--?xml version="1.0" encoding="utf-8" ?-->
<?xml version="1.0" encoding="utf-8" ?>
<service ID="0d0af7b9-32f3-4708-ab91-c32f57e15dca" Password="123" Name="WrapAndroidService">
<sysrootitem>
<BasicServiceItem ID="c15c5dfa-253f-4198-b1c3-34473487fb90" NameID="cb0338e8-e22f-48c0-931e-01b97502e374">
<object>
<AndroidBaseClass ID="e51b7626-160e-485e-b4ee-1f37686736dd">
<attribute>
<AndroidRefCount Type="VS_INT32" SyncFlag="1" />
</attribute>
<function>
<incAndroidRef ID="b4b43eb0-ec45-44aa-8af7-93b3f09a847c" />
<decAndroidRef ID="d7f5f007-b86f-4fd9-bc8f-86e1e5285e3b" />
<getActivity ID="e183d80f-1544-447a-928a-83702f475e0d">
<output Type="VS_OBJPTR" />
</getActivity>
</function>
</AndroidBaseClass>
<ViewClass ID="2f669713-d0e6-484b-9473-5c50afd8bbd2" Class="AndroidBaseClass" />
<ActivityClass ID="16371687-dc7e-4177-a7cc-76fd118c9c3c" Class="AndroidBaseClass">
<attribute>
<ViewGroupQueue Type="void *" Class="AbsoluteLayoutClass" />
</attribute>
<function>
<runScript ID="1d7668e4-b7e2-4c85-99cd-3cdb11ce5438">
<input Name="scriptInterface" Type="VS_CHAR *" />
<input Name="script" Type="VS_CHAR *" />
<output Type="VS_BOOL" />
</runScript>
<DoFile ID="542be0a5-bd21-4765-b004-5e336587367c">
<input Name="scriptInterface" Type="VS_CHAR *" />
<input Name="path" Type="VS_CHAR *" />
<output Type="VS_BOOL" />
</DoFile>
<DoAssetsFile ID="e894f038-1776-47c3-a6ec-802e5b86403c">
<input Name="scriptInterface" Type="VS_CHAR *" />
<input Name="path" Type="VS_CHAR *" />
<output Type="VS_BOOL" />
</DoAssetsFile>
<pushActivity ID="b8b252ec-e3e7-4194-a557-4f98a5e43c22">
<input Name="activity" Type="VS_OBJPTR" />
</pushActivity>
<popActivity ID="e024762e-cd83-4032-917b-9984bd91d725">
<output Type="VS_OBJPTR" />
</popActivity>
<getCurrent ID="cfcabd6e-028d-45b4-9e34-ebe7dc4c56b6">
<output Type="VS_OBJPTR" />
</getCurrent>
</function>
</ActivityClass>
<AbsoluteLayoutClass ID="155920e1-fdaa-489f-b4e9-4e3ac4cf5d7e" Class="ViewClass">
<attribute>
<ViewQueue Type="void *" Class="ViewClass" />
</attribute>
</AbsoluteLayoutClass>
<ButtonClass ID="f12ab1a2-2694-4165-8b4f-889b8f9aa872" Class="ViewClass">
<function>
<setText ID="1c6e8c3b-42db-41b9-988d-b7fb540b93be">
<input Name="text" Type="VS_CHAR *" />
</setText>
</function>
<outevent>
<onClick ID="328adf46-b65a-49d4-a10a-bd308552de05" />
</outevent>
</ButtonClass>
</object>
</BasicServiceItem>
</sysrootitem>
</service>
2. OnCreate event of the button
/* _OnCreate Event */
public Object[] _OnCreate(Hashtable Ev){
StarObjectClass self = (StarObjectClass)Ev.get("_DesObject");
StarObjectClass parent = (StarObjectClass)self._Get("_Parent");
StarObjectClass activity = (StarObjectClass)self._Call("getActivity");
/* create android button instance */
StarCLEButton button = new StarCLEButton((Activity)WrapAndroidClass.GetAndroidObject(activity,"AndroidObject"),self);
/* record android button instance */
WrapAndroidClass.SetAndroidObject(self,"AndroidObject",(Object)button);
/* set android button instance’s parent */
if( parent != null ){
if( activity == parent ){
Activity android_activity = (Activity)WrapAndroidClass.GetAndroidObject(parent,"AndroidObject");
android_activity.setContentView(button);
}else{
ViewGroup android_viewgroup = (ViewGroup)WrapAndroidClass.GetAndroidObject(parent,"AndroidObject");
android_viewgroup.addView(button);
}
self._LockGC();
self._Call("decAndroidRef"); // release with parent
}
/* Add event listener */
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
StarObjectClass self = ((BasicAndroidInterface)v).getBasicAndroid().getStarObject();
/* trigger CLE object’s event onClick */
self._ProcessEvent("onClick");
}
});
return null;
}
3. Set Text function of Button
public void setText(StarObjectClass self,String Text){
/*get recorded android instance*/
TextView textview = (TextView)WrapAndroidClass.GetAndroidObject(self,"AndroidObject");
if( textview != null )
/*call android instance’s function setText*/
textview.setText(Text);
}
4. Export to jar files: “wrapandroid.jar”
Programming with lua
a. Create Android project named “myluaexample”
b. Add Java build library
Copy “wrapandroid.jar” and “starcore_android_r5.jar” to your project directory. Add jar library to your project.
c. Copy “WrapAndroidService.xml” to assets directory of your project
d. Add Permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
e. Create the code.lua file
Create the code.lua file in the asserts directory, input text
SrvGroup = libstarcore._GetSrvGroup()
Service = SrvGroup:_GetService("","")
--get activity
StarActivity = Service.ActivityClass.getCurrent();
--create AbsoluteLayout
MyLayout = Service.AbsoluteLayoutClass:_New(StarActivity);
--create Button
MyButton = Service.ButtonClass:_New(MyLayout);
MyButton:setText("Hello");
function MyButton:onClick(Event)
self:setText("Is Clicked");
end