用C/C++开发android应用
16lz
2022-05-11
在某些情况下,比如原来与很多c/c++的代码, 可能希望采用c/c++编写android应用程序.在这种情况下,一般使用NDK.但是由于android直提供了java接口,因此不能够直接调用android中的各种对象或者部件. 如何直接使用c/c++开发android应用? 可以使用cle和wrapandroid项目作为中间件. CLE项目提供了多种语言的通用接口,其中就包含对c/c++的支持.
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
更多相关文章
- Android面试必备——AsyncTask源码解析
- android 内存管理
- Android(安卓)startActivity源码详解
- 深入理解Android插件化技术
- Android开发之低调的Service
- Android(安卓)Service,startService binderService 以及 AIDL
- Android应用程序消息处理机制(Looper、Handler)分析(4)
- 箭头函数的基础使用
- 类和 Json对象