232 views
in System Integration by
Hi,
I am using Embedded Wizard 12.04 with the Android platform package. I am using commandlinetools-win-9477386_latest, jdk 14.0.2 and on the target device Android version 13.
I am just starting to work with this platform package.

Would it be possible to get some simple example using native code on this platform?

Best regards,
Kyo.

1 Answer

0 votes
by

Hi Kyo,

please have a look to the example DeviceIntegration that you will find in the folder /Examples of the Android Build Environment. It shows the principles of integrating native code with your Embedded Wizard GUI application.

Does this answer your question?

Best regards,

Manfred.

by

Hi.
In order to integrate the project with native code, I made a few changes to the configuration files. Currently, the native code executes correctly but there were problems with displaying application elements such as text, background, etc.
The native code at application startup calls a "toast" with "Hello from JNI"; 

The expected look of the application:

 

 

Current:

 

 

In the Embedded Wizard project itself, I have the library declared inline:

I have created 2 files MainActivity.java and native-lib.c:
native-lib.c ( C:\Android\Application\Project\app\src\main\cpp\native-lib.c):

#include <jni.h>
#include <stdio.h>
#include <string.h>

JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    const char* hello = "Hello from JNI";
    return (*env)->NewStringUTF(env, hello);
}

 

MainActivity.java (C:\Android\Application\Project\app\src\main\java\com\example\myapplication\MainActivity.java):

package com.example.myapplication;

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

public class MainActivity extends Activity {
    
    // Load the native library
    static {
        System.loadLibrary("myapplication");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Call the native method to get the string from JNI
        String messageFromJNI = stringFromJNI();

        // Display the string as a Toast
        Toast.makeText(this, messageFromJNI, Toast.LENGTH_SHORT).show();

        // Finish the activity
        
    }

    // Declare the native method
    public native String stringFromJNI();
}

 

 

And I have modified the following config file:
build.gradle (C:\Android\Application\Project\build.gradle):

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
       jcenter()
       google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.0'
    }
}

allprojects {
    repositories {
        jcenter()
        google()
    }

    tasks.withType(JavaCompile) {
        options.compilerArgs << '-Xlint:-options' 
    }
}


task appStart(type: Exec, dependsOn: ':app:installDebug') {
    // windows
    commandLine 'cmd', '/c', 'adb', 'uninstall', 'com.example.myapplication.'
    commandLine 'cmd', '/c', 'adb', 'shell', 'am', 'start', '-n', 'com.example.myapplication.MainActivity'
}

task clean(type: Delete) {
    delete rootProject.buildDir
    delete "app/.externalNativeBuild"
}

 

build.gradle (C:\Android\Application\Project\app\build.gradle):

apply plugin: 'com.android.application'

android {
    compileSdkVersion = 33 

    defaultConfig {
        applicationId = 'com.example.myapplication'
        minSdkVersion 33
        targetSdkVersion  33
        versionCode 1
        versionName "1.0"
        externalNativeBuild {
            cmake {
                arguments '-DANDROID_STL=c++_static'
            }
        }
         sourceSets {
        main {
            java {
               // srcDirs 'src/main/java/com/example/myapplication' 
            }
        }
    }
        ndk {
            abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path '../../Source/CMakeLists.txt'
        }
    }
    buildFeatures {
        viewBinding true
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:25.4.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}

 

CmakeList ( C:\Android\Application\Source):


# Copyright (C) The Android Open Source Project

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#      http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.4.1)

project("myapplication")

# Dodaj ścieżkę do plików źródłowych C++
set(SOURCE_FILES C:/Android/Application/Project/app/src/main/cpp/native-lib.c)

# Dodaj bibliotekę C++
add_library(myapplication SHARED ${SOURCE_FILES})

# Znajdź i dodaj bibliotekę log
find_library(log-lib log)

# Powiąż bibliotekę log z naszą biblioteką C++
target_link_libraries(myapplication ${log-lib})

get_filename_component(ABSOLUTE_PATH ../GeneratedCode/ewfiles.cmake ABSOLUTE)
if(NOT EXISTS ${ABSOLUTE_PATH})
message(FATAL_ERROR "\n\n>>> Please open Embedded Wizard project and generate code first <<<\n")
endif()

# defines

add_definitions(
  -DEW_USE_OPERATING_SYSTEM=1
)

# OpenGL zooming
add_definitions(
  -DEW_BORDER_AROUND_GLYPHS=1
)

# 64-bit
message( STATUS "Architecture: ${ANDROID_ABI}" )
if ("$ENV{EVALUATION}" STREQUAL "arm64-v8a")
add_definitions(-D__LP64__)
endif()
if ("$ENV{EVALUATION}" STREQUAL "x86_64")
add_definitions(-D__LP64__)
endif()

...

 

AndroidManifest (C:\Android\Application\Project\app\src\main):

<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.myapplication"
          android:versionCode="1"
          android:versionName="1.0">
   <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30" />

    <!-- Needed only if your app looks for Bluetooth devices.
         If your app doesn't use Bluetooth scan results to derive physical
         location information, you can strongly assert that your app
         doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!-- Wymagany vluetooth Classic-->
    <uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
  <!-- Wymagany vluetooth LE-->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
  <!-- This .apk has no Java code itself, so set hasCode to false. -->
  <application
      android:allowBackup="false"
      android:fullBackupContent="false"
      android:icon="@drawable/icon"
      android:label="@string/app_name"
      android:hasCode="true">

    <!-- Our activity is the built-in NativeActivity framework class.
         This will take care of integrating with our NDK code. -->
         <!-- android:name="android.app.NativeActivity" -->
    <activity android:name="com.example.myapplication.MainActivity" 
              android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
              android:label="@string/app_name"
              android:keepScreenOn="true"
              android:launchMode="singleTask"
              android:configChanges="keyboardHidden|orientation"
              android:screenOrientation="landscape" 
              android:exported="true">
      <!-- Tell NativeActivity the name of our .so -->
      <meta-data android:name="android.app.lib_name"
                 android:value="embedded_wizard_activity" />
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>
  <uses-feature android:glEsVersion="0x00020000"/>

</manifest>
<!-- END_INCLUDE(manifest) -->

I noticed that the display error is caused by changing: package="de.embedded_wizard.embedded_wizard_activity" and android:name="android.app.NativeActivity" in the Manifest file.
If there was a possibility, I would ask for advice or help in solving the problem. 

 

Android: https://we.tl/t-SEZaOYLbfQ
Project: https://we.tl/t-cXwR4LnH11

Best regards,
Kyo.

by

Hi Kyo,

maybe I haven't fully understood your goals. Our intension of the Embedded Wizard BuildEnvironment for Android is to have an exclusive Embedded Wizard based GUI on an Android device.
My understanding is that if you add a Java based activity (public class MainActivity extends Activity {...}) you will get a 2nd activity completely separated from the native Embedded Wizard activity.

So, could you please explain in more detail what do you mean with 'using native code'.
Do you plan to realise an application containing both, Java activities and Embedded Wizard based native activity?
Or do you just want to write parts of your Embedded Wizard based native activity in Java?

Possible solutions to combine Embedded Wizard GUI with a Java based Android activity: 

  • Normal Java based Android activity, that shares a surface to the Embedded Wizard environment
  • Embedded Wizard GUI via WebGL displayed in a Android WebView
  • Progressive Web App with Embedded Wizard GUI via WebGL

Best Regards,
Martin

by
Hi martin.

I was just referring to the option: "Normal Java based Android activity, that shares a surface to the Embedded Wizard environment".
I would like to create a standard Android activity, using Java, and in this activity share a surface to the Embedded Wizard environment so that it can display the GUI. That is, in other words, I want the Embedded Wizard to be responsible for creating the GUI, and the Java activity to act as an intermediary that provides space for displaying the GUI.
By the way, I would like to be able to access the function call from the API, because I want to implement the ability to receive as well as send data via Bluetooth Classic or BLE.

Best Regards,
Kyo
by

Hi Kyo,

for some time, we did some POC sharing a GL surface to the Embedded Wizard environment running as native code. However it's too long ago to provide you some example.
It was based on a GLSurfaceView. I'm not sure, if this API is still available.
Basically the approach was as follows. In a Java based activity such GLSurfaceView was created and in the native part the function glGetIntegerv( GL_FRAMEBUFFER_BINDING, &framebuffer ); was used to get the frame buffer used for rendering of the Embedded Wizard GUI. However, from my point of view this approach is rather complicated.

Have you ever checked, if Bluetooth access is also possible directly using the Android NDK API?

Maybe a further alternative solution could be to create some helper class in in Java (no extra activity, just some bluetooth helpers) and to use it in you native code via JNI.

Best Regards,
Martin

 

by
Hi Martin,

Referring to what you wrote.

From what I checked there is no direct access to Bluetooth APIs from NDK.

As you wrote in this case I think the only sensible solution in this case would be to create a Java helper class without additional activity.

Earlier I just tried to do something similar but had big problems implementing it together with embedded wizard.

Would it be possible for you to give me some guidance on this topic or provide some simplest example using Java and jni?

Best Regards,

Kyo
by
Hi Kyo,

I'm sorry, but currently I have no example regarding Java, jni and Native Activity, that I could provide you.
However, I think there should be many examples in the net regarding Java and jni and how to handle it with Android Studio.
Since the communication between the Java part and the Native part is no specific Embedded Issue, I think a general jni example should be sufficient.

Best Regards,
Martin

Ask Embedded Wizard

Welcome to the question and answer site for Embedded Wizard users and UI developers.

Ask your question and receive answers from the Embedded Wizard support team or from other members of the community!

Embedded Wizard Website | Privacy Policy | Imprint

...