从 Kanzi application framework (appfw) 迁移到 Kanzi Android framework (droidfw)。¶
请按照以下说明将 Kanzi 应用程序从 Kanzi application framework (appfw) 迁移到 Kanzi Android framework (droidfw)。
例如,要将 Coin 示例应用程序从 Kanzi application framework (appfw) 迁移到 Kanzi Android framework (droidfw):
在 Quick Start 窗口中,点击 Projects 并选择 Examples 选项卡。在 Coin 示例旁边,点击
。
在
<KanziWorkspace>/Examples/Coin处复制该应用程序。在 Kanzi Studio 中打开 Kanzi Studio 工程
Tool_project/Coin.proj.kzm。在主菜单中,选择 File > Export > Export KZB。
在 Android Studio 中,打开
Application/configs/platforms/android_gradle目录中的项目。在
app/build.gradle:将应用程序
minSdk设置为 26 或更高。这是 Kanzi Android framework (droidfw) 所需的最低 SDK 版本。配置应用程序以使用 Kanzi Android framework (droidfw)。替换
dependencies { ... implementation 'com.rightware.kanzi:kanziruntime@aar'
通过
dependencies { ... implementation 'com.rightware.kanzi:kanziruntime-droidfw@aar'
将
kzjava库添加为依赖项。dependencies { ... implementation 'com.rightware.kanzi:kzjava@aar'
将应用程序的 Java 语言级别设置为 11 或更高。
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 }
在
app/src/main/res/layout/main.xml中,将视图类型从com.rightware.kanzi.KanziView
至 (To)
com.rightware.kanzi.KanziSurfaceView
在应用程序
app/src/main/java/com/rightware/kanzi/coin/Coin.java的活动中:从
onCreate(Bundle icicle)中移除 Activity 生命周期注册。Kanzi Android framework (droidfw) 会自动跟踪 View 生命周期回调。mView = findViewById(R.id.kanzicontent); mView.registerLifecycle(getLifecycle());
在
onCreate(Bundle icicle)中加载 kzb 文件,并在此 KanziSurfaceView 中设置您要加载的预设。在此项目中,您使用默认预设StartupPrefab。在 Kanzi application framework (appfw) 中,本机应用程序代码加载了 kzb 文件,而在 Kanzi Android framework (droidfw) 中,则不使用本机应用程序代码。
mView = findViewById(R.id.kanzicontent); mView.setKzbPathList(new String[]{"Coin.kzb.cfg"}); mView.setStartupPrefabUrl("kzb://coin/StartupPrefab");
将处理屏幕方向更改的方法从
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mView.setOrientation(newConfig.orientation); }
至 (To)
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mView.handleOrientationChange(newConfig.orientation); }
在 CMake 配置
Application/CMakeLists.txt中:替换 (Replace)
if(ANDROID) target_link_libraries(Coin -Wl,--whole-archive Kanzi::kzappfw -Wl,--no-whole-archive)
通过
if(ANDROID) target_link_libraries(Coin -Wl,--whole-archive Kanzi::kzdroidfw -Wl,--no-whole-archive)
将
kzinterop和kzjava库链接到应用程序。替换target_link_libraries(Coin Kanzi::kzui Kanzi::kzcoreui)
通过
target_link_libraries(Coin Kanzi::kzui Kanzi::kzcoreui Kanzi::kzinterop Kanzi::kzjava)
现在应用程序使用 Kanzi Android framework (droidfw),您可以在您的 Android 设备上运行它。
迁移应用程序代码¶
在您将应用程序从 Kanzi application framework (appfw) 迁移到 Kanzi Android framework (droidfw) 之后,该应用程序中的 C++ 代码将不再使用。您可以将应用程序的现有 C++ 代码迁移到 Java 应用程序或插件代码,或者将功能重构为 C++ Kanzi Engine 插件。由于 Java API 并未实现完整的 Kanzi Engine API,因此应用程序代码的迁移方法取决于您的应用程序的功能。
您可以删除除一个 cpp 文件之外的所有文件。要构建应用程序,CMake 需要一个 cpp 文件,即使该文件是空的。 例如,删除 Application/src/coin.cpp 的内容。
例如,要使用 Java 在 Coin 示例中显示 Text Block 节点中的帧时间:
在
app/src/main/java/com/rightware/kanzi/coin/Coin.java中,在应用程序活动中,向Coin类添加一个方法:void updateFrameTime(Duration duration) { TextBlock2D frameTime = mView.getRoot().lookupNode("#FrameTime"); frameTime.setText("Frame time: " + duration.toMillis() + " ms"); }
在
onCreate(Bundle icicle)中,添加一个主循环调度任务以在每一帧执行该方法:KanziRuntime.Reference runtimeRef = KanziRuntime.acquire(this); mView.addListener(new KanziViewListener() { @Override public void onStartupPrefabLoaded(View view, Domain domain) { runtimeRef.get().getDomain().getMainLoopScheduler().appendTask( MainLoopScheduler.UserStage, "Update Frame Time", TaskRecurrence.Recurring, duration -> updateFrameTime(duration)); } });
当您进行更改时,这就是 app/src/main/java/com/rightware/kanzi/coin/Coin.java 的样子:
package com.rightware.kanzi.coin;
import android.content.res.Configuration;
import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import android.view.View;
import android.view.WindowManager;
import com.rightware.kanzi.Domain;
import com.rightware.kanzi.KanziRuntime;
import com.rightware.kanzi.KanziView;
import com.rightware.kanzi.KanziViewListener;
import com.rightware.kanzi.MainLoopScheduler;
import com.rightware.kanzi.TaskRecurrence;
import com.rightware.kanzi.TextBlock2D;
import java.time.Duration;
public class Coin extends FragmentActivity
{
private static final String TAG = "Coin";
private KanziView mView = null;
@Override
protected void onCreate(Bundle icicle)
{
setContentView(R.layout.main);
mView = findViewById(R.id.kanzicontent);
mView.setKzbPathList(new String[]{"Coin.kzb.cfg"});
mView.setStartupPrefabUrl("kzb://coin/StartupPrefab");
// Force the screen to stay on when this app is on front (no need to clear).
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
KanziRuntime.Reference runtimeRef = KanziRuntime.acquire(this);
mView.addListener(new KanziViewListener() {
@Override
public void onStartupPrefabLoaded(View view, Domain domain) {
runtimeRef.get().getDomain().getMainLoopScheduler().appendTask(
MainLoopScheduler.UserStage,
"Update Frame Time",
TaskRecurrence.Recurring, duration -> updateFrameTime(duration));
}
});
super.onCreate(icicle);
}
void updateFrameTime(Duration duration)
{
TextBlock2D frameTime = mView.getRoot().lookupNode("#FrameTime");
frameTime.setText("Frame time: " + duration.toMillis() + " ms");
}
@Override
protected void onDestroy()
{
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mView.handleOrientationChange(newConfig.orientation);
}
}
排除问题¶
以下是将 Kanzi 应用程序从 Kanzi application framework (appfw) 移植到 Kanzi Android framework (droidfw) 时可能遇到的一些最常见问题。
错误:
<KanziWorkspace>\Projects\CoinPort\Application\configs\platforms\android_gradle\app\src\main\java\com\rightware\kanzi\coin\Coin.java:21: error: cannot find symbol mView.registerLifecycle(getLifecycle()); ^ symbol: method registerLifecycle(Lifecycle) location: variable mView of type KanziView原因:Kanzi Android framework (droidfw) 没有此 API。您不必手动注册 Activity 生命周期回调。
解决方案:您可以删除此调用。
错误:
7961-7961/com.rightware.kanzi.coin E/AndroidRuntime: FATAL EXCEPTION: main Process: com.rightware.kanzi.coin, PID: 7961 java.lang.NoSuchMethodError: No static method metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; in class Ljava/lang/invoke/LambdaMetafactory; or its super classes (declaration of 'java.lang.invoke.LambdaMetafactory' appears in /apex/com.android.art/javalib/core-oj.jar) at com.rightware.kanzi.KanziViewAdapter.handleAttachedToWindow(KanziViewAdapter.java:274)原因:您的应用程序不符合 Kanzi Android framework (droidfw) 的最低 Java 语言版本要求。
解决方案:在
app/build.gradle中,将compileOptions中的sourceCompatibility和targetCompatibility设置为JavaVersion.VERSION_11或更高。错误:
9136-9136/? E/ware.kanzi.coin: No implementation found for long com.rightware.kanzi.KanziRuntime.nCreate(android.content.Context) (tried Java_com_rightware_kanzi_KanziRuntime_nCreate and Java_com_rightware_kanzi_KanziRuntime_nCreate__Landroid_content_Context_2) 9136-9136/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.rightware.kanzi.coin, PID: 9136 java.lang.UnsatisfiedLinkError: No implementation found for long com.rightware.kanzi.KanziRuntime.nCreate(android.content.Context) (tried Java_com_rightware_kanzi_KanziRuntime_nCreate and Java_com_rightware_kanzi_KanziRuntime_nCreate__Landroid_content_Context_2) at com.rightware.kanzi.KanziRuntime.nCreate(Native Method) at com.rightware.kanzi.KanziRuntime.<init>(KanziRuntime.java:43) at com.rightware.kanzi.KanziRuntime.getOrCreateInstance(KanziRuntime.java:195) at com.rightware.kanzi.KanziRuntime.acquire(KanziRuntime.java:67) at com.rightware.kanzi.coin.Coin.onCreate(Coin.java:30)原因:您的应用程序链接到
Kanzi::kzappfw而不是Kanzi::kzdroidfw。解决方案:在
Application/CMakeLists.txt中,将链接从Kanzi::kzappfw更改为Kanzi::kzdroidfw。错误:
5629-5629/? E/ware.kanzi.coin: No implementation found for long com.rightware.kanzi.mathJNI.new_ColorRGBA__SWIG_3(float, float, float, float) (tried Java_com_rightware_kanzi_mathJNI_new_1ColorRGBA_1_1SWIG_13 and Java_com_rightware_kanzi_mathJNI_new_1ColorRGBA_1_1SWIG_13__FFFF) 5629-5629/? D/AndroidRuntime: Shutting down VM --------- beginning of crash 5629-5629/? E/AndroidRuntime: FATAL EXCEPTION: main Process: com.rightware.kanzi.coin, PID: 5629 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rightware.kanzi.coin/com.rightware.kanzi.coin.Coin}: android.view.InflateException: Binary XML file line #6 in com.rightware.kanzi.coin:layout/main: Binary XML file line #6 in com.rightware.kanzi.coin:layout/main: Error inflating class com.rightware.kanzi.KanziSurfaceView at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4166) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4312) ...原因:应用程序找不到
Kanzi::kzjava的本机支持。解决方案:在
Application/CMakeLists.txt中将Kanzi::kzinterop Kanzi::kzjava添加到链接目标列表中。