我们知道android主要使用java作为编程语言, 对于熟悉其它语言的开发者, 如果再android上开发,不仅需要熟悉java开发环境,而且以前的一些基于其它语言的工作成果,也不能够继续使用. android也提供了ndk可以进行native c的开发,但是只是为了补充java,且除了使用opengl之外,不能够使用android的GUI组件. 那么, 能否对android java类进行针对特定语言的封装,从而使对应的语言也能够开发android应用程序, 答案应该是可以.
对java类进行封装,最好封装一次,就能够支持多种语言, 否则针对每种语言都封装一次,那工作量就太大了. 从这一点来说, CLE作为中间件是一个不错的选择, CLE提供了多种语言的通用接口, 将android java类封装成为cle对象之后,就可以在多种语言中进行调用. 而且,用CLE封装java类非常简单和直接. 如下图:
将android java类封装成cle对象, 有四个步骤
1. 创建CLE服务和对象的描述文件
2. 实现对象的OnCreate和OnDestroy事件. 在OnCreate事件中,创建一个对应的android类的实例, 并记录下来. 在OnDestroy释放对应的实例
3. 在OnCreate事件中, 在创建了android实例之后, 建立实例的event listeners. 当listener触发之后, 产生一个cle event, 该事件由cle转交给应用
4. 编写接口函数,对于每个函数, 首先获取记录的android实例,然后调用该实例对应的函数.
在cle的支持下,上述的封装过程相对比较简单. 我们可以使用ecllipse和java编写并进行测试. 然后,可以用lua, python, or native c++进行调用.
这里, 作为一个例子, 我们简单封装一个button class.
1. 创建CLE服务和对象的描述文件, 可以使用srpdebug工具建立.
<?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事件处理
/* _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");
/*创建对应的android Button*/
StarCLEButton button = new StarCLEButton((Activity)WrapAndroidClass.GetAndroidObject(activity,"AndroidObject"),self);
/* 记录android实例*/
WrapAndroidClass.SetAndroidObject(self,"AndroidObject",(Object)button);
/* 设置button对象的父对象*/
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
}
/* 添加event listener */
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
StarObjectClass self = ((BasicAndroidInterface)v).getBasicAndroid().getStarObject();
/*产生CLE对象事件onClick */
self._ProcessEvent("onClick");
}
});
return null;
}
3. set Text function of Button.
public void setText(StarObjectClass self,String Text){
/*获取记录的android实例*/
TextView textview = (TextView)WrapAndroidClass.GetAndroidObject(self,"AndroidObject");
if( textview != null )
/*调用实例的函数setText*/
textview.setText(Text);
}
4. 将封装类输出成为jar文件: “wrapandroid.jar”
经过上述步骤, 我们可以获得“wrapandroid.jar” 和服务描述文件“WrapAndroidService.xml”.
然后,可以使用其它语言编写应用程序, 使用eclipse环境.
5. 使用lua语言编程.
a. 创建android project : “myluaexample”
b. 拷贝 “wrapandroid.jar” 和 “starcore_android_r5.jar” 到工程的目录下, 添加jar到工程中
c. 拷贝 “WrapAndroidService.xml” 到assets目录
d. 添加许可
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
e. 在assets目录下建立code.lua文件:
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
f. 编辑 “MyluaexampleActivity”:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
StarActivity._Call("DoAssetsFile", "lua", "code.lua");
}
6. 使用python语言编程
a. 安装 SL4A
b. 创建android project:“mypythonexample”
c. 在assets目录下建立 code.py文件
SrvGroup = libstarpy._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");
def MyButton_onClick(self,Event) :
self.setText("Is Clicked");
MyButton.onClick = MyButton_onClick
d. 编辑 “MypythonexampleActivity”:
public class MypythonexampleActivity extends WrapAndroidActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
StarActivity._Call("DoAssetsFile", "python", "code.py");
}
}
其它步骤与lua例子相同
7. 使用native c 语言编程
a. 创建android project:“mycexample”
b. 创建 jni目录, 进入该目录下, 生成服务的头文件,使用下面的命令
star2h ..\assets\WrapAndroidService.xml
c. 建立Code.cpp
#include "WrapAndroidService_VSDHeader.h"
static class ClassOfSRPInterface *SRPInterface;
static void *StarActivity;
static VS_INT32 MyButton_onClick(VS_ULONG FunctionChoice,void *EventPara)
{
VS_EVENTPARAM *EventParam;
EventParam = (VS_EVENTPARAM *)EventPara;
SRPInterface -> ScriptCall(EventParam->SrcObject,NULL,"setText","(s)","Is Clicked");
return 0;
}
VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
{
class ClassOfBasicSRPInterface *BasicSRPInterface;
//--init star core
BasicSRPInterface = starcore ->GetBasicInterface();
SRPInterface = BasicSRPInterface ->GetSRPInterface(BasicSRPInterface->QueryActiveService(NULL),"","");
void *ActivityClass;
ActivityClass = SRPInterface -> GetObjectEx(NULL,"ActivityClass");
StarActivity = (void *)SRPInterface -> ScriptCall(ActivityClass,NULL,"getCurrent","()O");
SRPInterface -> Print("Get Main Activity = %s", SRPInterface -> GetName(StarActivity));
//--create AbsoluteLayout
void *MyLayout = SRPInterface->MallocObject(StarActivity,VSATTRINDEX_ACTIVITYCLASS_VIEWGROUPQUEUE,&VSOBJID_AbsoluteLayoutClass,0,NULL);
//--create Button
void *MyButton = SRPInterface->MallocObject(MyLayout,VSATTRINDEX_ABSOLUTELAYOUTCLASS_VIEWQUEUE,&VSOBJID_ButtonClass,0,NULL);
SRPInterface -> ScriptCall(MyButton,NULL,"setText","(s)","Hello");
SRPInterface -> RegEventFunction(MyButton,&VSOUTEVENTID_ButtonClass_onClick,MyButton,(void *)MyButton_onClick,0);
return VS_TRUE;
}
void StarCoreService_Term(class ClassOfStarCore *starcore)
{
SRPInterface -> Release();
return;
}
d. 建立Android.mk.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and sourcefile(s)
LOCAL_CFLAGS += -Wno-write-strings -DENV_ANDROID
LOCAL_CPPFLAGS += -Wno-write-strings -fexceptions -DENV_ANDROID
LOCAL_LDFLAGS += -Wno-write-strings -DENV_ANDROID
LOCAL_C_INCLUDES += cle_files/include
#--------source file
MODULE_CXXSRCS := Code.cpp WrapAndroidService_UUIDDef.cpp
LOCAL_SRC_FILES := ${MODULE_CXXSRCS}
LOCAL_LDLIBS := cle_files/libs/armeabi/libstarlib.a
LOCAL_MODULE := Code
include $(BUILD_SHARED_LIBRARY)
e. 编辑“MycexampleActivity”
public class MycexampleActivity extends WrapAndroidActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
StarActivity._Call("DoFile","","/data/data/com.srplab.mycexample/lib/libCode.so");
}
}