在某些情况下,比如原来与很多c/c++的代码, 可能希望采用c/c++编写android应用程序.在这种情况下,一般使用NDK.但是由于android直提供了java接口,因此不能够直接调用android中的各种对象或者部件. 如何直接使用c/c++开发android应用? 可以使用cle和wrapandroid项目作为中间件. CLE项目提供了多种语言的通用接口,其中就包含对c/c++的支持.


本文简单介绍了如何使用CLE和wrapandroid编写GUI应用程序。CLE可以作为多种语言的通用平台,支持java, python,c/c++,lua, 等,且可以扩展至其它多种语言,也可以自定义语言。在CLE中,对象作为1个基本的操作元素。对象对外提供了统一的接口,可以通过这些接口,调用对象的函数,重载对象的函数,捕获对象的事件.
Wrapandroid将android类封装成为CLE对象,从而可以使程序员在c/c++中使用android的类。一般有以下几个步骤: 1.使用CLE接口函数MallocObjectL创建android类的实例对象 2.使用ScriptCall接口函数调用对象的方法 3.使用CreateOvlFunction重载对象的函数 4.使用RegEventFunction注册对象的事件处理函数

步骤1: 准备环境

a: CLE可以在应用启动的时候自动安装,只需要在工程中包含starcore_android_r6.jar,该文件在starcore_devfiles_r6.zip压缩包中, 可以从链接: http://code.google.com/p/cle-for-android 下载。

b: Wrapandroid是一个jar库,可以从http:/code.google.com/p/wrapandroid-for-multilaguage/download/wrapandroid_devfiles_0_8_5.rar下载。

步骤2 : 开始编程


开发工具使用eclipse和NDK. 这两个如何安装和使用,请参阅相关的文档.
a. 打开eclipse, 创建一个新工程,名字为“introduction”

b. cle可以在应用启动的时候从网络下载,此时需要在工程中增加以下许可:

<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

c. 将java库文件starcore_android_r6.jar和wrapandroid.jar拷贝到工程目录,并加入到工程中:



d. 编辑IntroductionActivity.java,如下修改,装载共享库
import com.srplab.wrapandroid.*;
public class IntroductionActivity 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/"+getPackageName()+"/lib/libCode.so"); } }
e cle也可以打包到工程中,此时需要将CLE的共享库文件放到工程目录中,如下:

同时,将下载标志设置为false
public class IntroductionActivity extends WrapAndroidActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { DownloadFromNetFlag = false; super.onCreate(savedInstanceState); setContentView(R.layout.main); StarActivity._Call("DoFile","","/data/data/"+getPackageName()+"/lib/libCode.so"); } }
f. 编辑布局文件:main.xml.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget73" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >
<TextView android:id="@+id/widget45" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/widget74" android:layout_width="220dp" android:layout_height="48dp" android:text="thank for your use" android:typeface="serif" android:textStyle="bold" android:textColor="#ffff0000" android:layout_x="284dp" android:layout_y="220dp" android:textSize="16dp" /> </LinearLayout>
g. 在工程目录下,创建jni目录, 将wrap android和cle头文件拷贝到该目录下. 创建新文件code.cpp. and Android.mk, 编辑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 SRPWrapAndroidEngine_UUIDDef.cpp
LOCAL_SRC_FILES := ${MODULE_CXXSRCS} LOCAL_LDLIBS := cle_files/libs/armeabi/libstarlib.a
LOCAL_MODULE := Code
include $(BUILD_SHARED_LIBRARY)

#------------------------ include $(CLEAR_VARS)
LOCAL_SRC_FILES := cle_files/so/armeabi/libstarcore.so LOCAL_MODULE := starcore
include $(PREBUILT_SHARED_LIBRARY)
#------------------------ include $(CLEAR_VARS)
LOCAL_SRC_FILES := cle_files/so/armeabi/libstar_java.so LOCAL_MODULE := star_java
include $(PREBUILT_SHARED_LIBRARY)

步骤3. Code.cpp

采用原生代码编写android应用,需要将其编译成为共享库。共享库输出两个接口函数: VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore) void StarCoreService_Term(class ClassOfStarCore *starcore)
第一个函数在共享库装载的时候调用,可以进行一些初始化工作;第二个函数在共享库卸载的时候调用
代码如下: //--wrap android头文件 #include "SRPWrapAndroidEngine_VSClass.h"
//--服务接口,其它所有函数都通过该接口调用. static class ClassOfSRPInterface *SRPInterface; //--android Activity对象,由java代码创建. static void *StarActivity;
//--按钮的事件函数。 事件函数的处理原型都相同. static VS_INT32 MyButton_onClick(VS_ULONG FunctionChoice,void *EventPara) { //--当事件被触发时,显示一些信息. //--创建toast对象。 void *toast = SRPInterface->MallocObjectL(&VSOBJID_ToastClass,0,NULL); //--调用toast的函数“makeText”, (si) 为输入参数的类型,详细解释需要参阅CLE文档. SRPInterface -> ScriptCall(toast,NULL,"makeText","(si)","Button is click", 0); //--调用toast的函数“show” SRPInterface -> ScriptCall(toast,NULL,"show","()"); return 0; }
static VS_INT32 MyButton1_onClick(VS_ULONG FunctionChoice,void *EventPara) { void *toast = SRPInterface->MallocObjectL(&VSOBJID_ToastClass,0,NULL); SRPInterface -> ScriptCall(toast,NULL,"makeText","(si)","Button is click", 0); SRPInterface -> ScriptCall(toast,NULL,"show","()"); return 0; }

//--共享库的初始化函数 VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore) { class ClassOfBasicSRPInterface *BasicSRPInterface; //--获取基本服务接口 BasicSRPInterface = starcore ->GetBasicInterface(); //---获取当前的服务接口,服务由java代码创建 SRPInterface = BasicSRPInterface ->GetSRPInterface(BasicSRPInterface->QueryActiveService(NULL),"",""); void *ActivityClass; //---获取被封装的acvitity类 ActivityClass = SRPInterface -> GetObjectEx(NULL,"ActivityClass"); //--调用getCurrent function获取当前的activity, 由java代码创建. ()O 表示返回值为一个cle对象 StarActivity = (void *)SRPInterface -> ScriptCall(ActivityClass,NULL,"getCurrent","()O"); //--打印一些信息,打印的信息会显示到logcat中. SRPInterface -> Print("Get Main Activity = %s", SRPInterface -> GetName(StarActivity)); //--调用activity的函数getResource获取布局中定义的资源的ID.输入参数为字符串,输出为整数,使用标记为(s)I. int widget45 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget45"); //--调用findViewById函数获取textview. 该函数与android的函数原型略为不同,输入参数中增加的类的名称。 void *MyText = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)o","TextViewClass",widget45); //--调用textview的函数setText。 SRPInterface -> ScriptCall(MyText,NULL,"setText","(s)","TextViewClass","from layout");
int widget74 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget74"); //--调用findViewById获取按钮对象 void *MyButton = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)o","ButtonClass",widget74); //--调用按钮对象的setText. SRPInterface -> ScriptCall(MyButton,NULL,"setText","(s)","click me"); //--调用按钮对象的函数setOnClickListener. SRPInterface -> ScriptCall(MyButton,NULL,"setOnClickListener","()"); //--注册事件的处理函数 SRPInterface -> RegEventFunction(MyButton,&VSOUTEVENTID_ViewClass_onClick,MyButton,(void *)MyButton_onClick,0); int widget73 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget73"); //--调用findViewById获取LinearLayout. void *MyLinearLayout = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)o","LinearLayoutClass",widget73); //--动态创建按钮对象,是linearlayout的子对象 void *MyDynaButton = SRPInterface->MallocObject(MyLinearLayout,VSATTRINDEX_VIEWGROUPCLASS_VIEWQUEUE,&VSOBJID_ButtonClass,0,NULL); SRPInterface -> ScriptCall(MyDynaButton,NULL,"setText","(s)","created dynamically"); SRPInterface -> ScriptCall(MyDynaButton,NULL,"setOnClickListener","()"); SRPInterface -> RegEventFunction(MyDynaButton,&VSOUTEVENTID_ViewClass_onClick,MyDynaButton,(void *)MyButton1_onClick,0); //--设置布局参数 SRPInterface -> ScriptCall(MyDynaButton,NULL,"setLinearLayoutParams","(ii)",100,50);
return VS_TRUE; }
void StarCoreService_Term(class ClassOfStarCore *starcore) { SRPInterface -> Release(); return; }

Step 4. 使用ndk编译成为共享库

运行结果



例子下载:

http://wrapandroid-for-multilanguage.googlecode.com/svn/wiki/examples/c_introduction.zip

更多相关文章

  1. Android面试必备——AsyncTask源码解析
  2. android 内存管理
  3. Android(安卓)startActivity源码详解
  4. 深入理解Android插件化技术
  5. Android开发之低调的Service
  6. Android(安卓)Service,startService binderService 以及 AIDL
  7. Android应用程序消息处理机制(Looper、Handler)分析(4)
  8. 箭头函数的基础使用
  9. 类和 Json对象

随机推荐

  1. android常用控件(二)
  2. 基本Dalvik VM调用
  3. Android AVD启动失败
  4. Android签名验证简介
  5. Android(安卓)webview 常用配置
  6. Android原生运行uniapp使用5+app创建项目
  7. Android音频介绍
  8. android sdk content loader 一直显示0%
  9. [android] PhoneGap 在 android 下的实现
  10. 一键解决Ubuntu下安装Eclipse Android/C/