Click here to Skip to main content
11,503,750 members (61,309 online)
Click here to Skip to main content

Writing an Android GUI using C++: Introduction

, 14 Mar 2013 CPOL 48.2K 80
Rate this:
Please Sign up or sign in to vote.
Using CLE and the Wrapandroid project, programmers can call Android classes through interfaces of CLE more easily.

Introduction

For some reason, we might want to write Android applications using native code. In this case, the NDK will be used. But using only NDK is not enough. Because Android only exports Java interface to programmers, so applications can not call Android classes directly. How do we solve this problem? Using CLE and the Wrapandroid project, programmers can call Android classes 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, instances of classes, will be maintained in the kernel. And then, CLE provides a common interface to multiple languages. We can call an object’s function, get or set object’s attributes, capture object’s events, etc.

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 an Android class using MallocObjectL of the 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

  1. CLE may be installed from the network by the application automatically, you only need to 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.
  2. Wrapandroid has lib files: wrapandroid.jar, which can be download from here.

Step 2: Begin programming 

We will be using Eclipse and NDK to develop the application. How to install these, please refer to other related articles. Android version should be above 2.2.

  1. Open Eclipse, create a new Android project named “introduction”.
  2. CLE may be installed from the network when the application is started; in this case, the following permissions should be added:
  3. <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
  4. Copy the Java libraries starcore_android_r6.jar and wrapandroid.jar to the project directory and add them into the project:
  5. Edit IntroductionActivity.java, change as follows loading the native share library.
  6. 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");
        }
    }
  7. CLE may also be included in the project, in this case, you should copy the share libraries of CLE to the directory of the project:
  8. And change the 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");
        }
    }
  9. Edit layout: main.xml.
  10. <?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>
  11. Create a jni directory under the project, copy header files of Wrapandroid and CLE into the jni directory. Create new files named code.cpp and Android.mk, and edit Android.mk as follows:
  12.  LOCAL_PATH := $(call my-dir)
    <pre>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 the source file into a share library. The share library exposes two functions:

VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
void StarCoreService_Term(class ClassOfStarCore *starcore)

The first function will be called when the library is loaded, which can be used to do some initializing. StarCoreService_Term will be called before the share library is unloaded. 

The code for code.cpp is listed below. We will see it in detail:

//--header file of wrap android
<pre>#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:

The example can be download from: http://wrapandroid-for-multilanguage.googlecode.com/svn/wiki/examples/c_introduction.zip.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

li9705

China China
No Biography provided

Comments and Discussions

 
QuestionWhat advantage does it have compare to traditonal way which write android app in Java? Pin
ltn6142-Dec-12 15:43
memberltn6142-Dec-12 15:43 
AnswerRe: What advantage does it have compare to traditonal way which write android app in Java? Pin
viaducting19-Mar-13 2:02
memberviaducting19-Mar-13 2:02 
Questiondemo crashed Pin
ltn6142-Dec-12 1:52
memberltn6142-Dec-12 1:52 
AnswerRe: demo crashed Pin
li97052-Dec-12 3:52
memberli97052-Dec-12 3:52 
GeneralRe: demo crashed Pin
ltn6142-Dec-12 15:12
memberltn6142-Dec-12 15:12 
QuestionAndroid, C++ Pin
Old Black Cat7-Aug-12 8:44
memberOld Black Cat7-Aug-12 8:44 
Very nice work, thanks a lot! Big Grin | :-D
GeneralCOOL Pin
Xiang Zhai10-Jun-12 15:42
memberXiang Zhai10-Jun-12 15:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150520.1 | Last Updated 14 Mar 2013
Article Copyright 2012 by li9705
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid