Skip to content

Commit d22af68

Browse files
committed
update android app, very basic functionality
1 parent 2e2af8e commit d22af68

File tree

5 files changed

+148
-15
lines changed

5 files changed

+148
-15
lines changed

mobile/examples/model_tester/android/app/build.gradle.kts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ plugins {
55

66
android {
77
namespace = "com.onnxruntime.example.modeltester"
8-
compileSdk = 33
8+
compileSdk = 34
99

1010
defaultConfig {
1111
applicationId = "com.onnxruntime.example.modeltester"
1212
minSdk = 24
13-
targetSdk = 33
13+
targetSdk = 34
1414
versionCode = 1
1515
versionName = "1.0"
1616

@@ -42,10 +42,10 @@ android {
4242
buildFeatures {
4343
viewBinding = true
4444
}
45+
ndkVersion = "28.1.13356709"
4546
}
4647

4748
dependencies {
48-
4949
implementation("androidx.core:core-ktx:1.9.0")
5050
implementation("androidx.appcompat:appcompat:1.7.0")
5151
implementation("com.google.android.material:material:1.12.0")

mobile/examples/model_tester/android/app/src/main/cpp/CMakeLists.txt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ cmake_minimum_required(VERSION 3.22.1)
1111
# build script scope).
1212
project("modeltester")
1313

14+
set(CMAKE_CXX_STANDARD 20)
15+
1416
# Creates and names a library, sets it as either STATIC
1517
# or SHARED, and provides the relative paths to its source code.
1618
# You can define multiple libraries, and CMake builds them for you.
@@ -24,14 +26,26 @@ project("modeltester")
2426
# System.loadLibrary() and pass the name of the library defined here;
2527
# for GameActivity/NativeActivity derived applications, the same library name must be
2628
# used in the AndroidManifest.xml file.
29+
add_library(onnxruntime SHARED IMPORTED)
30+
set_target_properties(onnxruntime PROPERTIES
31+
IMPORTED_LOCATION
32+
${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libonnxruntime.so
33+
INTERFACE_INCLUDE_DIRECTORIES
34+
${CMAKE_SOURCE_DIR}/include)
35+
2736
add_library(${CMAKE_PROJECT_NAME} SHARED
28-
# List C/C++ source files with relative paths to this CMakeLists.txt.
29-
native-lib.cpp)
37+
${CMAKE_CURRENT_SOURCE_DIR}/native-lib.cpp
38+
${CMAKE_CURRENT_SOURCE_DIR}/../../../../../common/include/model_runner.h
39+
${CMAKE_CURRENT_SOURCE_DIR}/../../../../../common/model_runner.cpp)
40+
41+
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
42+
${CMAKE_CURRENT_SOURCE_DIR}/../../../../../common/include)
3043

3144
# Specifies libraries CMake should link to your target library. You
3245
# can link libraries from various origins, such as libraries defined in this
3346
# build script, prebuilt third-party libraries, or Android system libraries.
3447
target_link_libraries(${CMAKE_PROJECT_NAME}
3548
# List libraries link to the target library
3649
android
37-
log)
50+
log
51+
onnxruntime)
Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,101 @@
1+
#include <android/log.h>
2+
13
#include <jni.h>
4+
5+
#include <memory>
26
#include <string>
7+
#include <stdexcept>
8+
#include <vector>
9+
10+
#include "model_runner.h"
11+
12+
namespace util {
13+
struct JstringUtfCharDeleter {
14+
JstringUtfCharDeleter(JNIEnv& env, jstring jstr) : env{env}, jstr{jstr} {}
15+
16+
void operator()(const char* p) {
17+
env.ReleaseStringUTFChars(jstr, p);
18+
}
19+
20+
JNIEnv& env;
21+
jstring jstr;
22+
};
23+
24+
auto MakeUniqueJstringUtfCharPtr(JNIEnv& env, jstring jstr) {
25+
const auto* raw_utf_chars = env.GetStringUTFChars(jstr, nullptr);
26+
return std::unique_ptr<const char, JstringUtfCharDeleter>{
27+
raw_utf_chars, JstringUtfCharDeleter{env, jstr}};
28+
}
29+
30+
std::string JstringToStdString(JNIEnv& env, jstring jstr) {
31+
auto utf_chars = MakeUniqueJstringUtfCharPtr(env, jstr);
32+
return std::string{utf_chars.get()};
33+
}
34+
35+
std::vector<std::string> JstringArrayToStdStrings(JNIEnv& env, jobjectArray jobjs) {
36+
std::vector<std::string> strs;
37+
const auto java_string_class = env.FindClass("java/lang/String");
38+
const auto length = env.GetArrayLength(jobjs);
39+
for (jsize i = 0; i < length; ++i) {
40+
const auto jobj = env.GetObjectArrayElement(jobjs, i);
41+
if (!env.IsInstanceOf(jobj, java_string_class)) {
42+
throw std::runtime_error("jobjectArray element is not a string");
43+
}
44+
const auto jstr = static_cast<jstring>(jobj);
45+
strs.emplace_back(JstringToStdString(env, jstr));
46+
}
47+
return strs;
48+
}
49+
50+
struct JbyteArrayElementsDeleter {
51+
JbyteArrayElementsDeleter(JNIEnv& env, jbyteArray array) : env{env}, array{array} {}
52+
53+
void operator()(jbyte* p) {
54+
env.ReleaseByteArrayElements(array, p, 0);
55+
}
56+
57+
JNIEnv& env;
58+
jbyteArray array;
59+
};
60+
61+
auto MakeUniqueJbyteArrayElementsPtr(JNIEnv& env, jbyteArray array) {
62+
auto* jbytes_raw = env.GetByteArrayElements(array, nullptr);
63+
return std::unique_ptr<jbyte[], JbyteArrayElementsDeleter>{
64+
jbytes_raw, JbyteArrayElementsDeleter{env, array}};
65+
}
66+
} // namespace util
367

468
extern "C" JNIEXPORT jstring JNICALL
5-
Java_com_onnxruntime_example_modeltester_MainActivity_stringFromJNI(
6-
JNIEnv* env,
7-
jobject /* this */) {
8-
std::string hello = "Hello from C++";
9-
return env->NewStringUTF(hello.c_str());
69+
Java_com_onnxruntime_example_modeltester_MainActivity_run(JNIEnv* env, jobject thiz,
70+
jbyteArray java_model_bytes,
71+
jint num_iterations,
72+
jstring execution_provider_type,
73+
jobjectArray execution_provider_option_names,
74+
jobjectArray execution_provider_option_values) {
75+
try {
76+
auto model_bytes = util::MakeUniqueJbyteArrayElementsPtr(*env, java_model_bytes);
77+
const size_t model_bytes_length = env->GetArrayLength(java_model_bytes);
78+
auto model_bytes_span = std::span{reinterpret_cast<const std::byte*>(model_bytes.get()),
79+
model_bytes_length};
80+
81+
auto config = model_runner::RunConfig{};
82+
config.model_path_or_bytes = model_bytes_span;
83+
config.num_iterations = num_iterations;
84+
85+
// TODO handle EP type and EP options
86+
87+
auto result = model_runner::Run(config);
88+
89+
auto summary = model_runner::GetRunSummary(config, result);
90+
91+
return env->NewStringUTF(summary.c_str());
92+
} catch (const std::exception& e) {
93+
const auto java_exception_class = env->FindClass("java/lang/RuntimeException");
94+
env->ThrowNew(java_exception_class, e.what());
95+
96+
__android_log_print(ANDROID_LOG_ERROR, "com.onnxruntime.example.modeltester",
97+
"Error: %s", e.what());
98+
99+
return nullptr;
100+
}
10101
}

mobile/examples/model_tester/android/app/src/main/java/com/onnxruntime/example/modeltester/MainActivity.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.onnxruntime.example.modeltester
22

33
import androidx.appcompat.app.AppCompatActivity
44
import android.os.Bundle
5-
import android.widget.TextView
65
import com.onnxruntime.example.modeltester.databinding.ActivityMainBinding
76

87
class MainActivity : AppCompatActivity() {
@@ -15,15 +14,24 @@ class MainActivity : AppCompatActivity() {
1514
binding = ActivityMainBinding.inflate(layoutInflater)
1615
setContentView(binding.root)
1716

18-
// Example of a call to a native method
19-
binding.sampleText.text = stringFromJNI()
17+
val modelResourceId = R.raw.model
18+
val modelBytes = resources.openRawResource(modelResourceId).readBytes()
19+
20+
val summary = run(modelBytes, 10, null, null, null)
21+
22+
binding.sampleText.text = summary
2023
}
2124

2225
/**
2326
* A native method that is implemented by the 'modeltester' native library,
2427
* which is packaged with this application.
2528
*/
26-
external fun stringFromJNI(): String
29+
external fun run(modelBytes: ByteArray,
30+
numIterations: Int,
31+
executionProviderType: String?,
32+
executionProviderOptionNames: Array<String>?,
33+
executionProviderOptionValues: Array<String>?,
34+
): String
2735

2836
companion object {
2937
// Used to load the 'modeltester' library on application startup.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
setup instructions:
2+
3+
1. manually set up native onnxruntime libraries. unzip onnxruntime-android.aar, then put shared libraries and headers into these directories:
4+
5+
under mobile/examples/model_tester/android/app/src/main/cpp:
6+
include/onnxruntime_session_options_config_keys.h
7+
include/nnapi_provider_factory.h
8+
include/cpu_provider_factory.h
9+
include/onnxruntime_lite_custom_op.h
10+
include/onnxruntime_run_options_config_keys.h
11+
include/onnxruntime_float16.h
12+
include/onnxruntime_cxx_inline.h
13+
include/onnxruntime_cxx_api.h
14+
include/onnxruntime_c_api.h
15+
lib/armeabi-v7a/libonnxruntime.so
16+
lib/x86/libonnxruntime.so
17+
lib/arm64-v8a/libonnxruntime.so
18+
lib/x86_64/libonnxruntime.so
19+
20+
2. copy an onnx model file to mobile/examples/model_tester/android/app/src/main/res/raw/model.onnx

0 commit comments

Comments
 (0)