Developing with the Kanzi Android framework¶
Use the Kanzi Android framework when you want to create an application for the Android platform, and you intend to use Android APIs and services extensively.
Kanzi Android framework is a framework dedicated for developing Kanzi applications for Android. It exposes the Kanzi Java API, which allows you to write application and plugin code entirely in Java or Kotlin. You do not need to write any C++ or JNI code, but you can still use native Kanzi plugins. Kanzi Android framework provides strong integration with the Android UI, including support for multiple simultaneous Kanzi-based Views and flexible composition of Kanzi and Android UI elements.
Creating an Android application in Kanzi Studio¶
In Kanzi Studio in the New Project window, select the template for your Android application:
Android application template creates a Kanzi Studio project with a Kanzi Android framework-based application.
Android application with Java plugin template creates a Kanzi Studio project with a Kanzi Android framework-based application that contains a Kanzi Engine Java plugin.
When you create a project with one of these templates, Kanzi Studio creates a complete Android application project in the <ProjectName>/Application/configs/platforms/Android_gradle directory.
To learn how to build and deploy your application, see Deploying Kanzi applications to Android.
Adding the Kanzi Android framework to an existing Android application¶
This procedure assumes that your Android application project uses the default directory structure.
Note
The Kanzi Gradle plugin 0.6.2 supports only Android Gradle plugin 4.1.3 and Gradle 6.7.1 and lower. If you created a new project with the latest Android Studion, you must downgrade your tooling.
To add the Kanzi Android framework to an existing Android application:
Copy the contents of
<ProjectName>/Application/bindirectory of your Kanzi Studio project to theapp/src/main/assetsdirectory of your Android Studio project.This way you import your kzb files into an Android package.
Introduce cmake to your project. This way you can link native Kanzi Engine plugins to your application.
Add to the
app/src/main/cpp/CMakeLists.txtfile:cmake_minimum_required(VERSION 3.5.1) project(<ProjectName>) if(NOT KANZI_ENGINE_BUILD) find_package(Kanzi REQUIRED CONFIG CMAKE_FIND_ROOT_PATH_BOTH HINTS "$ENV{KANZI_HOME}/Engine/lib/cmake") endif() include(kanzi-common) add_executable(<ProjectName> # This file is only needed because cmake does not allow an executable without any sources. <ProjectName>.cpp) target_link_libraries(<ProjectName> -Wl,--whole-archive Kanzi::kzdroidfw -Wl,--no-whole-archive) target_link_libraries(<ProjectName> Kanzi::kzui Kanzi::kzcoreui Kanzi::kzjava Kanzi::kzinterop) target_link_font_engine_backends(<ProjectName>) set_target_properties(<ProjectName> PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/bin") set_target_properties(<ProjectName> PROPERTIES VS_DEBUGGER_ENVIRONMENT "${KANZI_VS_DEBUGGER_ENVIRONMENT}") install_kanzi_libs_to_output_directory() install_kzbs_to_output_directory(${CMAKE_SOURCE_DIR}/bin) install_target_to_output_directory(<ProjectName>)
Add to the
app/src/main/cppdirectory an empty<ProjectName>.cppfile.
Copy the
getkanzi.gradlefile from the<KanziWorkspace>/Templates/Android_application_template/Application/configs/platforms/android_gradledirectory to your Android project root directory.Gradle uses the
getkanzi.gradlefile to find Kanzi Engine and Kanzi Gradle plugins.In the
build.gradlefile in the Android project root directory, get the Kanzi Gradle plugins and add Kanzi as a dependency:buildscript { apply from: 'getkanzi.gradle' repositories { google() mavenCentral() flatDir { dirs getKanziPlugins().toString() } } dependencies { classpath "com.android.tools.build:gradle:4.1.3" classpath "com.rightware.gradle:kanzi:0.6.2" }
In the
app/build.gradlefile of your Android Studio project, add the Kanzi Gradle plugin, and import the Kanzi Android framework and its dependencies:apply plugin: 'com.rightware.gradle.kanzi' ... android { ... defaultConfig { ... externalNativeBuild { cmake { arguments "-DKANZI_LINK_FREETYPE=ON" arguments "-DKANZI_LINK_ITYPE=OFF" } } } ... externalNativeBuild { cmake { path file('src/main/cpp/CMakeLists.txt') } } } ... kanzi { appFramework 'kanziruntime-droidfw' } dependencies { ... implementation 'com.rightware.kanzi:kzjava@aar' }
Adding a Kanzi View¶
Kanzi exposes the KanziSurfaceView and KanziTextureView View types derived from the Android SurfaceView and TextureView respectively.
KanziSurfaceViewrenders directly to a surface obtained from hardware composer, which makes its performance better. But it comes with the restriction that an application can render it only behind or on the top of the rest of the Views in an Activity.KanziTextureViewrenders to a texture like a regular View. This allows an application to mix its content freely with Android content and you can move, transform, animate, and even make it translucent.
See Android SurfaceView vs TextureView.
You can declare a KanziView in the Android layout and inflate it anywhere in the same way as a regular Android View.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.rightware.kanzi.KanziSurfaceView
android:id="@+id/view1"
app:name="View1"
app:startupPrefabUrl="kzb://project1/Prefabs/View1" />
Configuring a Kanzi View¶
These View types expose various configurations that you can assign directly from a layout.
Attribute |
Use |
Format |
Default value |
|---|---|---|---|
|
Name of the View. |
string |
|
|
URL of the startup prefab. When set, Kanzi asynchronously loads and instantiates this prefab as a child of the View. |
string |
|
|
Color used to clear the surface. |
color |
|
|
Flag to enable the clearing of the surface. |
boolean |
|
Alternatively, you can assign these configuration options with setters after inflation.
public class Activity1 extends FragmentActivity {
@Override
protected void onCreate(Bundle) {
...
// Inflate the content from the layout.
setContentView(R.layout.activity1);
// Get the reference to the View.
KanziView view = findViewById(R.id.view1);
// Set the name.
view.setName("View1");
// Set the startup prefab.
view.setStartupPrefabUrl("kzb://project1/Prefabs/View1");
If a KanziView uses startup prefabs, make sure that the application loads the correct kzb files before you inflate the View.
@Override
protected void onCreate(Bundle) {
...
// Load the kzb.
try {
KanziRuntime.getInstance(this).loadKzb("project1.kzb");
} catch (FileNotFoundException e) {
Log.e(e.getMessage());
return;
}
// Inflate the content from the layout.
setContentView(R.layout.activity1);
Accessing the Kanzi Java API¶
From the View, you can access the node tree root, from where you have access to the full Kanzi Java API.
// Get root.
Node root = view.getRoot();
// Look up a node using an alias.
Node button = root.lookupNode("#Button");
// Set property.
button.setProperty(ButtonConcept.ToggleStateProperty, 0);
// Add message handler.
button.addMessageHandler(ButtonConcept.ToggleStateMessage,
new Node.MessageSubscriptionFunction() {
@Override
public void handle(MessageArguments messageArguments) {
int toggleState = messageArguments.getArgument(ButtonConcept.ToggleStateProperty);
Log.i("Button State is " + toggleState);
}});
Observing state changes¶
You can implement KanziViewListener to listen for state changes in KanziView. Use this to inject custom initialization and un-initialization logic.
For example, when the startup prefab is set, access the node tree only after the startup prefab loading is complete. To do this, use the onStartupPrefabLoaded() callback.
// Add listener to a View.
view.addListener(new KanziViewListener() {
@Override
public void onStartupPrefabLoaded(KanziView view) {
// Add your application code here.
Attaching Kanzi to an existing View¶
You can instantiate and attach a KanziViewAdapter to an existing Android SurfaceView or TextureView.
@Override
protected void onCreate(Bundle) {
...
// Get reference to a View.
SurfaceView view = findViewById(R.id.view1);
// Instantiate an adapter and assign a View.
mAdapter = new KanziViewAdapter(view, "View1");
// Assign a startup prefab.
view.setStartupPrefabUrl("kzb://project1/Prefabs/View1");
Using Kanzi from View-less contexts¶
You can also instantiate and use a KanziViewAdapter without a View. For example, from a WallpaperService.
class WallpaperEngine1 extends WallpaperService.Engine {
KanziViewAdapter mAdapter;
@Override
public void onCreate(SurfaceHolder) {
...
// Instantiate an adapter.
mAdapter = new KanziViewAdapter(getApplicationContext(), "WallpaperEngine1");
// Assign a startup prefab.
mAdapter.setStartupPrefabUrl("kzb://project1/Prefabs/Wallpaper");
Handling input¶
While KanziSurfaceView and KanziTextureView handle input events by default, an arbitrary View using KanziViewAdapter must manually forward any input events that it wants Kanzi to process, through the handleTouchEvent(), handlekeyEvent(), and handleFocusChange() interfaces.
All Kanzi Views by default set focusableInTouchMode to True, unless otherwise set programmatically or through layout attributes. This makes them gain and keep focus when clicked on. See Android touch mode.
Handling orientation change¶
When the screen orientation changes, an Android application, by default, destroys and recreates the activity. This allows an application to use an alternate layout for portrait and landscape screens, but it also means that you lose all internal Kanzi states.
You can override this by adding the android:configChanges="orientation" property to the AndroidManifest.xml file. With this option, the activity is no longer destroyed on orientation changes, instead onConfigurationChanged() is called on the activity. Forward this event manually to handleOrientationChange(). This option avoids recreating the Kanzi controls and therefore all internal state is retained. See Android configuration changes.
Handling the Android lifecycle¶
While KanziSurfaceView and KanziTextureView handle window and surface events by default, an arbitrary view using KanziViewAdapter must manually forward the window and surface events it wants Kanzi to process, through the handleAttachedToWindow(), handleSurfaceCreated(), handleSurfaceChanged(), handleSurfaceDestroyed(), and handleDetachedFromWindow() interfaces.
Creating multiple Views¶
You can activate multiple Kanzi-based Views simultaneously within an app and access them across different Activities or Fragments.
See also¶
Kanzi Android framework API reference
Deploying Kanzi applications to Android