Click here to Skip to main content
15,886,919 members
Articles / Mobile Apps / Android

Writing an Android GUI using C++: Part 4 - Activity

Rate me:
Please Sign up or sign in to vote.
4.76/5 (24 votes)
20 Jan 2014CPOL3 min read 101.9K   2.6K   81   15
The example given in this article is similar to the previous article, except that it is written with C++.

Introduction

In my previous article, we saw an example of how to create and launch a child activity using Python. In this article, the example is rewritten with C++. Using C++ to create child activities, each activity should be built as a share library, and is loaded with the interface function DoFile of CLE.

The example given in this article is similar to the previous article, except that it is written with C++. The example contains two activities, root and child. The root activity contains an edit widget, which is used to get input from the user, and a button widget. When users press the button, a child activity is created with the input as parameter. The child activity displays the parameter in text widgets, and shows an edit widget for the user to input the result for the parent. Lastly, the text returned from the child is shown in the parent activity.

Root Activity

Layout XML file

We use an XML file layout. The XML file contains text view, button, and edit view, which is listed below.

XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget30"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<LinearLayout
android:id="@+id/widget34"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_gravity="center_vertical"
>
<TextView
android:id="@+id/widget35"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="input text :"
>
</TextView>
<EditText
android:id="@+id/widget38"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello"
android:textSize="18sp"
>
</EditText>
</LinearLayout>
<Button
android:id="@+id/widget39"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="send to child"
>
</Button>
<LinearLayout
android:id="@+id/widget40"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:layout_gravity="center_vertical"
>
<TextView
android:id="@+id/widget41"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="result from child :"
>
</TextView>
<TextView
android:id="@+id/widget42"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
android:textSize="18sp"
>
</TextView>
</LinearLayout>
</LinearLayout>

Code of activity

The boot code of the activity is written in Java, which is simple. Its function is to load the C++ share library.

Java
public class ActivityActivity 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");
    }
} 

code.cpp

Code.cpp” is the main code of the root activity.

Step 1:

The first step of the C++ code is to get the service group object and the activity object created by the Java code.

C++
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)); 
Step 2:

Step 2 obtains widgets defined in the layout file and sets the onClick event listener of the button. When the event is triggered, we build an intent and create a child activity. The child activity is named ChildActivity. It must be declared in AndroidManifest.xml. Otherwise, the call will fail.

AndroidManifest.xml:
XML
<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
    <activity
        android:label="@string/app_name"
        android:name=".ActivityActivity" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".ChildActivity" android:label="@string/app_name"/>
</application>

Get the button defined in the layout file and set the onClick listener:

C++
static VS_INT32 MyButton_onClick(VS_ULONG FunctionChoice,void *EventPara)
{
    void *MyIntent = SRPInterface->MallocObjectL(&VSOBJID_IntentClass,0,NULL);
    SRPInterface -> ScriptCall(MyIntent,NULL,"setClassName","(s)","ChildActivity");
    VS_CHAR *Text = (VS_CHAR *)SRPInterface -> ScriptCall(myEdit,NULL,"getText","()s");
    SRPInterface -> ScriptCall(MyIntent,NULL,"putStringExtra","(ss)","value",Text);
    SRPInterface -> ScriptCall(StarActivity,NULL,"startActivityForResult","(oi)",MyIntent,1);
    SRPInterface->FreeObject(MyIntent);
    return 0;
}
    VS_INT32 widget39 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget39");
    void *myButton = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)O","ButtonClass",widget39);
    SRPInterface -> RegEventFunction(myButton,&VSOUTEVENTID_ViewClass_onClick,myButton,(void *)MyButton_onClick,0);
    SRPInterface -> ScriptCall(myButton,NULL,"setOnClickListener","()"); 
Step 3:

When the child activity returns, we can get the result from the child and show it in a text view. To receive the result, we should override the activity’s function onActivityResult.

C++
static void StarActivity_onActivityResult(void *Object,int requestCode, int resultCode, void *data)  
{
    if( requestCode == 1 && data != NULL ){
        VS_CHAR *Text = (VS_CHAR *)SRPInterface -> ScriptCall(data,NULL,"getStringExtra","(s)s","value");
        SRPInterface -> ScriptCall(myText,NULL,"setText","(s)",Text);
    }
}
SRPInterface -> CreateOVLFunction(StarActivity,
  &VSFUNCID_ActivityClass_onActivityResult,(void *)StarActivity_onActivityResult,NULL); 

Child Activity

Layout XML file

The XML file also contains a text view, button, and edit view, which are listed below.

XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget30"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<LinearLayout
android:id="@+id/widget31"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/widget32"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="from parent :"
>
</TextView>
<TextView
android:id="@+id/widget33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
>
</TextView>
</LinearLayout>
<LinearLayout
android:id="@+id/widget34"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/widget35"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="input text : "
>
</TextView>
<EditText
android:id="@+id/widget36"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="EditText"
android:textSize="18sp"
>
</EditText>
</LinearLayout>
<Button
android:id="@+id/widget37"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="return to parent"
>
</Button>
</LinearLayout> 

Code of child activity

The boot code of the child activity is the same as the parent activity.

code.cpp

Step 1:

The first step of the C++ code is to get the service group object and activity object created by the Java code, which is the same as the parent activity.

Step 2:

First, we get the start intent, which is set by the parent. Then, obtain the text view defined in the layout file and show the string of the intent in the text view. Now get the button widget and set its onClick event listener. When the event is triggered, we build the result intent for the parent and call the finish function to end the child activity.

C++
void *child_intent = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"getIntent","()o");
VS_INT32 widget33 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget33");
void *ChildText = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)O","TextViewClass",widget33);
VS_CHAR *Text = (VS_CHAR *)SRPInterface -> ScriptCall(child_intent,NULL,"getStringExtra","(s)s","value");
SRPInterface -> ScriptCall(ChildText,NULL,"setText","(s)",Text);
SRPInterface -> ScriptCall(ChildText,NULL,"setTextColor","(i)",0xFFFF0000); 

Get the button defined layout and set the onClick listener.

C++
static VS_INT32 MyButton_onClick(VS_ULONG FunctionChoice,void *EventPara)
{
    void *MyIntent = SRPInterface->MallocObjectL(&VSOBJID_IntentClass,0,NULL);
    VS_CHAR *Text = (VS_CHAR *)SRPInterface -> ScriptCall(myEdit,NULL,"getText","()s");
    SRPInterface -> ScriptCall(MyIntent,NULL,"putStringExtra","(ss)","value",Text);
    SRPInterface -> ScriptCall(StarActivity,NULL,"setResult1","(io)",0,MyIntent);
    SRPInterface->FreeObject(MyIntent);
    SRPInterface -> ScriptCall(StarActivity,NULL,"finish","()");
    return 0;
}

VS_INT32 widget37 = SRPInterface -> ScriptCall(StarActivity,NULL,"getResource","(s)i","id/widget37");
void *myButton = (void *)SRPInterface -> ScriptCall(StarActivity,NULL,"findViewById","(si)O","ButtonClass",widget37);
SRPInterface -> RegEventFunction(myButton,&VSOUTEVENTID_ViewClass_onClick,myButton,(void *)MyButton_onClick,0);
SRPInterface -> ScriptCall(myButton,NULL,"setOnClickListener","()");

We also should capture the “BACK” key event. When the key is pressed, we also end the activity.

C++
static VS_BOOL StarActivity_onKeyDown(void *Object,int keyCode, void *event)  
{
    if( keyCode == KEYCODE_BACKId ){
        void *MyIntent = SRPInterface->MallocObjectL(&VSOBJID_IntentClass,0,NULL);
        SRPInterface -> ScriptCall(MyIntent,NULL,"putStringExtra","(ss)","value","press key back");
        SRPInterface -> ScriptCall(StarActivity,NULL,"setResult1","(io)",0,MyIntent);
        SRPInterface->FreeObject(MyIntent);
        SRPInterface -> ScriptCall(StarActivity,NULL,"finish","()");
        return VS_TRUE;
    } 
    return VS_FALSE;
}

SRPInterface -> CreateOVLFunction(StarActivity,&VSFUNCID_ActivityClass_onKeyDown,(void *)StarActivity_onKeyDown,NULL); 

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and sourcefile(s)
LOCAL_CFLAGS += -Wno-write-strings -O0 -DENV_ANDROID
LOCAL_CPPFLAGS += -Wno-write-strings -O0 -fexceptions -DENV_ANDROID
LOCAL_LDFLAGS += -Wno-write-strings -O0 -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)
# Here we give our module name and sourcefile(s)
LOCAL_CFLAGS += -Wno-write-strings -O0 -DENV_ANDROID
LOCAL_CPPFLAGS += -Wno-write-strings -O0 -fexceptions -DENV_ANDROID
LOCAL_LDFLAGS += -Wno-write-strings -O0 -DENV_ANDROID
LOCAL_C_INCLUDES += cle_files/include
#--------source file
MODULE_CXXSRCS := childcode.cpp SRPWrapAndroidEngine_UUIDDef.cpp
LOCAL_SRC_FILES := ${MODULE_CXXSRCS}
LOCAL_LDLIBS := cle_files/libs/armeabi/libstarlib.a
LOCAL_MODULE  := childcode
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)   

Screenshot

Parent Activity

Image 1

Child Activity

Image 2

License

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


Written By
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerWriting an Android GUI using C++: Part 4 - Activity Pin
Member 1326677818-Jun-17 22:20
Member 1326677818-Jun-17 22:20 
QuestionWell done! Pin
Paul Conrad23-Jan-14 6:12
professionalPaul Conrad23-Jan-14 6:12 
GeneralMy vote of 4 Pin
skyformat99@gmail.com22-Jan-14 1:57
skyformat99@gmail.com22-Jan-14 1:57 
Questionhow to code C++ in Android Pin
Member 1037417418-Jan-14 2:11
Member 1037417418-Jan-14 2:11 
AnswerRe: how to code C++ in Android Pin
li970518-Jan-14 16:24
li970518-Jan-14 16:24 
GeneralRe: how to code C++ in Android Pin
Member 1037417418-Jan-14 21:57
Member 1037417418-Jan-14 21:57 
GeneralRe: how to code C++ in Android Pin
li970518-Jan-14 22:40
li970518-Jan-14 22:40 
GeneralRe: how to code C++ in Android Pin
Member 1037417419-Jan-14 14:30
Member 1037417419-Jan-14 14:30 
GeneralRe: how to code C++ in Android Pin
li970520-Jan-14 2:27
li970520-Jan-14 2:27 
hi,
Use cle apis to interact with android java. Compile the c or c++ code into share library using ndk. The following is an example to create a button using c code.

C++
#include "vsopenapi.h"

static class ClassOfSRPInterface *SRPInterface;
static void *mainobject;
static void *Toast;
static void *BtnCallBackClass;
static VS_OBJPTR g_activity;

static void Btn_OnClick(void *Object,VS_OBJPTR view)
{
	SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"btn on click is called");
	void *toast = (void *)SRPInterface ->ScriptCall(Toast,NULL,"makeText","(osi)O",g_activity,"Is clicked",SRPInterface ->ScriptGetInt(Toast,"LENGTH_SHORT"));
	SRPInterface ->ScriptCall(toast,NULL,"show","()");
}

static VS_BOOL Init(void *Object,VS_OBJPTR activity)
{
	VS_PARAPKGPTR Para;
	
	g_activity = activity;
	SRPInterface ->AddRefEx(g_activity);
	
	SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"main is called");
	
	Toast = SRPInterface -> ImportRawContext("java","android/widget/Toast",true,"");
	
    void *absoluteLayout = SRPInterface -> ImportRawContext("java","android/widget/AbsoluteLayout",true,""); 
    SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"absoluteLayout = %s",SRPInterface ->GetName(absoluteLayout));
    
    Para = SRPInterface -> GetParaPkgInterface();
    Para ->InsertObject(0,activity);
    void *abslayout = SRPInterface ->IMallocObjectL( SRPInterface ->GetIDEx(absoluteLayout),Para);
    SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"activity = %s",SRPInterface ->GetName(abslayout));
    
    SRPInterface ->ScriptCall(activity,NULL,"setContentView","(O)",abslayout);
    SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"set content view to absolute layout");
    
    void *button = SRPInterface -> ImportRawContext("java","android/widget/Button",true,"");
    SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"button = %s",SRPInterface ->GetName(button));
    
    void *btn1 = SRPInterface ->IMallocObjectL( SRPInterface ->GetIDEx(button),Para);
    SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"btn1 = %s",SRPInterface ->GetName(btn1));
    SRPInterface ->ScriptCall(btn1,NULL,"setText","(s)","Hello World");
        
	//---create proxy to handle click of button 
	void *BtnCallBackClass = SRPInterface ->CreateAtomicObjectSimple("TestItem","BtnCallBackClass",NULL,NULL,NULL);
	void *OnClickFunction = SRPInterface ->CreateAtomicFunctionSimple(BtnCallBackClass,"onClick","VS_BOOL onClick(VS_OBJPTR view);",NULL,NULL,VS_FALSE,VS_FALSE);
    //---Set Function Address
	SRPInterface -> SetAtomicFunction(OnClickFunction,(void *)Btn_OnClick);
	
	void *BtnClickProxyObject = SRPInterface ->MallocObjectL(SRPInterface ->GetIDEx(SRPInterface ->AtomicToObject(BtnCallBackClass)),0,NULL);
    void *btnevent_proxy = SRPInterface ->NewRawProxy("java",BtnClickProxyObject,"","android.view.View$OnClickListener",0);
    SRPInterface ->ProcessError(VSFAULT_DISP,"testc",__LINE__,"btnevent_proxy = %s",SRPInterface ->GetName(btnevent_proxy));
    SRPInterface ->ScriptCall(btn1,NULL,"setOnClickListener","(o)",btnevent_proxy);
    
    //--create linear layout under absolute layout
    void *viewGroup_LayoutParams = SRPInterface -> ImportRawContext("java","android/view/ViewGroup$LayoutParams",true,"");
    void *layoutParams = SRPInterface -> ImportRawContext("java","android/widget/AbsoluteLayout$LayoutParams",true,"");    
		
    //--add button to layout
    Para ->Clear();
    Para ->InsertInt(0,SRPInterface -> ScriptGetInt(viewGroup_LayoutParams,"WRAP_CONTENT"));
    Para ->InsertInt(1,SRPInterface -> ScriptGetInt(viewGroup_LayoutParams,"WRAP_CONTENT"));
    Para ->InsertInt(2,0);
    Para ->InsertInt(3,100);
    
    void *lp1 = SRPInterface ->IMallocObjectL( SRPInterface ->GetIDEx(layoutParams),Para);
    SRPInterface ->ScriptCall(abslayout,NULL,"addView","(oo)",btn1,lp1);
 
    //-free objects
    SRPInterface ->DelRefEx(absoluteLayout);   //--can not call FreeObject
    SRPInterface ->DelRefEx(abslayout);
    SRPInterface ->DelRefEx(button);
    SRPInterface ->DelRefEx(btn1);
    SRPInterface ->DelRefEx(btnevent_proxy);
    SRPInterface ->DelRefEx(viewGroup_LayoutParams);
    SRPInterface ->DelRefEx(layoutParams);
    Para ->Release();
     	
}



VS_BOOL StarCoreService_Init(class ClassOfStarCore *starcore)
{
	void *mainClass,*initFunction;
	class ClassOfBasicSRPInterface *BasicSRPInterface;
	
	//--init star core
	BasicSRPInterface = starcore ->GetBasicInterface();	
	SRPInterface = BasicSRPInterface ->GetSRPInterface(BasicSRPInterface->QueryActiveService(NULL),"","");
		
	//---Create mainClass Class, for define function, no attribute 
	mainClass = SRPInterface ->CreateAtomicObjectSimple("TestItem","TestMainClass",NULL,NULL,NULL);
	initFunction = SRPInterface ->CreateAtomicFunctionSimple(mainClass,"Init","VS_BOOL Init(VS_OBJPTR activity);",NULL,NULL,VS_FALSE,VS_FALSE);
    //---Set Function Address
	SRPInterface -> SetAtomicFunction(initFunction,(void *)Init);
	
	mainobject = SRPInterface ->MallocObjectL(SRPInterface ->GetIDEx(SRPInterface ->AtomicToObject(mainClass)),0,NULL);
	SRPInterface ->SetName(mainobject,"mainobject");

	return VS_TRUE;
}

void StarCoreService_Term(class ClassOfStarCore *starcore)
{
	SRPInterface ->FreeObject(mainobject);
	SRPInterface ->FreeObject(BtnCallBackClass);
	SRPInterface ->FreeObject(Toast);
	SRPInterface ->DelRefEx(g_activity);
	SRPInterface -> Release();	
	return;
}


using java code to load the share library

package com.srplab.examples;

import android.app.Activity;
import android.os.Bundle;

import com.srplab.www.starcore.*;

public class TestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

StarCoreFactoryPath.StarCoreCoreLibraryPath = "/data/data/"+ getPackageName()+"/lib";
StarCoreFactoryPath.StarCoreShareLibraryPath = "/data/data/"+getPackageName()+"/lib";

final StarCoreFactory starcore= StarCoreFactory.GetFactory();
StarServiceClass Service=starcore._InitSimple("test","123",0,0);
StarSrvGroupClass SrvGroup = (StarSrvGroupClass)Service._Get("_ServiceGroup");
Service._CheckPassword(false);

starcore._RegMsgCallBack_P(new StarMsgCallBackInterface(){

public Object Invoke(int arg0, int arg1, Object arg2, Object arg3) {
// TODO Auto-generated method stub
if( arg0 == starcore._Getint("MSG_VSDISPMSG") ||
arg0 == starcore._Getint("MSG_VSDISPLUAMSG") ||
arg0 == starcore._Getint("MSG_DISPMSG") ||
arg0 == starcore._Getint("MSG_DISPLUAMSG") )
System.out.println("....."+arg2); /*--capture information from c */
return null;
}
});

Object[] Result = Service._DoFile("", "/data/data/"+ getPackageName()+"/lib/libtest_c.so","");
if( Result[0] == (Boolean)false )
System.out.println("execute c shared library false");
else
System.out.println("execute c shared library true");

StarObjectClass mainobject = (StarObjectClass)Service._Get("mainobject");
boolean initresult = mainobject._Callbool("Init", this);
if( initresult == false )
System.out.println("init false..............");
else
System.out.println("init true..............");
}
}

we will add the exmaple to download list. test_c.zip
GeneralRe: how to code C++ in Android Pin
Member 1037417420-Jan-14 18:39
Member 1037417420-Jan-14 18:39 
QuestionAndroid Pin
gchugh12327-Mar-13 17:34
gchugh12327-Mar-13 17:34 
QuestionAndroid, C++ Pin
Old Black Cat7-Aug-12 8:30
Old Black Cat7-Aug-12 8:30 
Question强大 Pin
tangbongbong6-Jul-12 4:29
tangbongbong6-Jul-12 4:29 
QuestionVote of 5 Pin
Ganesan Senthilvel2-Jul-12 18:19
Ganesan Senthilvel2-Jul-12 18:19 
GeneralMy vote of 5 Pin
Jason Leatherface2-Jul-12 12:35
Jason Leatherface2-Jul-12 12:35 

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

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