srplab's blog

Discuss about multi language programming of c/c ,java,c#,python,etc. Distribute object middleware

Post sort order : index

4/28 POSTS
preview
4-6/28 POSTS

close

Writing android gui using c++(introduction)

May 30, 2012 9:17 PMPublicPageviews 235 0

Introduction


For some reason, we might want to write android applications using native code. In this case, NDK will be used. But only NDK does not enough. Because android only exports java interface to programmers, so applications can not call android classes directly. How to solve this problem? Don’t worry about.  Using the result of cle and wrapandroid project, programmers can call android class through interfaces of cle more easily.

The article is an introduction to write android gui applications using cle and wrapandroid. CLE is a middleware for programming using multiple languages, which supports java, python,c/c++,lua, etc. and can be extended to support other languages. Objects, for example, instance of class, will be maintained in the kernel. And then, cle provides common interface to multiple languages. We can call object’s function, get or set object’s attributes, capture object’s events.

Wrapandroid wraps android classes with cle objects, which enables programmers to use android classes in their applications. In normal case, the steps is illustrated below.
1.    create an object of android class using MallocObjectL of cle interface.
2.    call object’s functions using ScriptCall method.
3.    Override object’s function using CreateOvlFunction method
4.    Hook object’s event using RegEventFunction method

Step 1 : Prepare environment

a: CLE may install from network by application automatically, you need only include  starcore_android_r6.jar in the project. The file is in starcore_devfiles_r6.zip, which can be download from http://code.google.com/p/cle-for-android

b: Wrapandroid has a lib files: wrapandroid.jar, which can be download from http:/code.google.com/p/wrapandroid-for-multilaguage/download/wrapandroid_devfiles_0_8_5.rar

Step 2 : Begin programming 


Using eclipse and NDK to development application. How to install them, please refer to other related articles. Android version should be above 2.2.
a. Open eclipse, create a new android project named “introduction”

b. cle may be installed from network when application started, in this case, the following permission should be added:

   
   


c. Copy java library starcore_android_r6.jar and wrapandroid.jar to project directory, and add them into project:



d. edit IntroductionActivity.java,changed as follow,loading native share library.
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 may also be included in the project, in this case, you should copy share libraries of cle to the directory of the project: 


And change download flag to 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. edit layout:main.xml.


    android:id="@+id/widget73"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

   
        android:id="@+id/widget45"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" /> 
   
        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"
    />        

g. Create jni directory under project, copy header files of wrap android and cle into jni directory. create new file named code.cpp. and Android.mk, edit Android.mk as follow

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) 

Step 3. Code.cpp


Write native code in android, we should compile source file into share library. The share library expose two functions : 
VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
void StarCoreService_Term(class ClassOfStarCore *starcore)
the first function will be call when the library is loaded, which can be used to do some initialize. StarCoreService_Term will be called before the share library is unloaded.
The code of code.cpp is list below. We explain in detail;
//--header file of wrap android
#include "SRPWrapAndroidEngine_VSClass.h"
//--service interface, other function calls will be done through this interface.
static class ClassOfSRPInterface *SRPInterface;
//--Activity object of android, which is created by previous java code.
static void *StarActivity;
//--button event function. Each event has the same prototype.
static VS_INT32 MyButton_onClick(VS_ULONG FunctionChoice,void *EventPara)
{
    //--when the event is triggered, we show some information using android Toast.
        //--Create instance of toast.
    void *toast = SRPInterface->MallocObjectL(&VSOBJID_ToastClass,0,NULL);
        //--call toast function “makeText”, (si) is input parameter type and return type. please refer to cle documents.
    SRPInterface -> ScriptCall(toast,NULL,"makeText","(si)","Button is click", 0);
        //--call toast function “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;
}

//--share library init function.
VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
{
    class ClassOfBasicSRPInterface *BasicSRPInterface;
    
    //--get basic interface of cle
    BasicSRPInterface = starcore ->GetBasicInterface();    
        //---get current service interface, the service is create by java code.
    SRPInterface = BasicSRPInterface ->GetSRPInterface(BasicSRPInterface->QueryActiveService(NULL),"","");
    
    void *ActivityClass;
        //---get wrapped acvitity
    ActivityClass = SRPInterface -> GetObjectEx(NULL,"ActivityClass");
        //--call getCurrent function to get current activity, which is created by java code. ()O means the return type is cle object;
    StarActivity = (void *)SRPInterface -> ScriptCall(ActivityClass,NULL,"getCurrent","()O");
        //--show some infotmation.
    SRPInterface -> Print("Get Main Activity = %s", SRPInterface -> GetName(StarActivity));    
    //--call activity function getResource to obtained resource id of above layout. Input parameter is a string and output is an integer, so here we use (s)I tag.
int widget45 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget45");
        //--Call findViewById function of activity, which is a textview. For this function, we should provide class name as input parameter, which is little different from android function. Input parameter is string and integer and return type is cle object. So, here uses tag (si)o.
void *MyText = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)o","TextViewClass",widget45);
        //--Call setText of textview object.
        SRPInterface -> ScriptCall(MyText,NULL,"setText","(s)","TextViewClass","from layout");
        int widget74 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget74");
        //--Call findViewById function of activity to get button object.
        void *MyButton = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)o","ButtonClass",widget74);
        //--Call setText function of button object.
        SRPInterface -> ScriptCall(MyButton,NULL,"setText","(s)","click me");
        //--Call setOnClickListener function of button object.
        SRPInterface -> ScriptCall(MyButton,NULL,"setOnClickListener","()");
        //--register event function of button object.
        SRPInterface -> RegEventFunction(MyButton,&VSOUTEVENTID_ViewClass_onClick,MyButton,(void *)MyButton_onClick,0);
    
        int widget73 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget73");
        //--Call findViewById function of activity to get LinearLayout.
    void *MyLinearLayout = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)o","LinearLayoutClass",widget73);
        //--Dynamically create a button, which as a child of linear out.
    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);
        //--set layout parameters of button created.
        SRPInterface -> ScriptCall(MyDynaButton,NULL,"setLinearLayoutParams","(ii)",100,50);
    return VS_TRUE;
}
void StarCoreService_Term(class ClassOfStarCore *starcore)
{
    SRPInterface -> Release();
    return;
}

Step 4. Compile to share library


Result:



Example can be download from : 

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





Report abuse for this article

Copyright © 2013 Yahoo!, Inc. All rights reserved