让android支持多种编程语言

来源:互联网 发布:关于网络言论自由作文 编辑:程序博客网 时间:2024/05/20 13:39

        我们知道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");
    }
}

 

 

例子下载:
http://www.srplab.com/android/wrapandroid.rar
 
目前正在进行该项目的工作,开源 http://code.google.com/p/wrapandroid-for-multilanguage. 如果感兴趣,欢迎参与。

 

原创粉丝点击