使用 C++ 编写 Android GUI: 第 4 部分 - Activity
本文给出的例子与之前的文章类似,只不过是用 C++ 编写的。
引言
在之前的文章中,我们看到了一个使用 Python 创建和启动子 Activity 的例子。在本文中,该示例用 C++ 重新编写。 使用 C++ 创建子 Activity 时,每个 Activity 都应构建为共享库,并使用 CLE 的接口函数 DoFile
加载。
本文给出的例子与之前的文章类似,只不过是用 C++ 编写的。 该示例包含两个 Activity,根 Activity 和子 Activity。 根 Activity 包含一个编辑小部件,用于从用户那里获取输入,以及一个按钮小部件。 当用户按下按钮时,将使用输入作为参数创建一个子 Activity。 子 Activity 在文本小部件中显示参数,并显示一个编辑小部件供用户输入父 Activity 的结果。 最后,子 Activity 返回的文本将显示在父 Activity 中。
根 Activity
布局 XML 文件
我们使用 XML 文件布局。 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>
Activity 的代码
Activity 的启动代码是用 Java 编写的,很简单。 它的功能是加载 C++ 共享库。
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” 是根 Activity 的主要代码。
步骤 1
C++ 代码的第一步是获取 Java 代码创建的服务组对象和 Activity 对象。
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));
第二步
第 2 步获取在布局文件中定义的控件,并设置按钮的 onClick
事件监听器。 当事件触发时,我们构建一个 Intent 并创建一个子 Activity。 子 Activity 的名称为 ChildActivity
。 必须在 AndroidManifest.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>
获取在布局文件中定义的按钮并设置 onClick
监听器
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","()");
步骤 3
当子 Activity 返回时,我们可以从子 Activity 中获取结果并将其显示在文本视图中。 为了接收结果,我们应该重写 Activity 的函数 onActivityResult
。
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);
子 Activity
布局 XML 文件
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>
子 Activity 的代码
子 Activity 的启动代码与父 Activity 相同。
code.cpp
步骤 1
C++ 代码的第一步是获取 Java 代码创建的服务组对象和 Activity 对象,这与父 Activity 相同。
第二步
首先,我们获取父 Activity 设置的启动 Intent。 然后,获取在布局文件中定义的文本视图,并在文本视图中显示 Intent 的字符串。 现在获取按钮控件并设置其 onClick
事件监听器。 当事件触发时,我们为父 Activity 构建结果 Intent,并调用 finish 函数来结束子 Activity。
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);
获取定义的布局按钮并设置 onClick
监听器。
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","()");
我们还应该捕获“BACK”键事件。 当按下该键时,我们也会结束 Activity。
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)