SlideShare a Scribd company logo
1 of 36
Android NDK & JNI
Sergey Komlach
GDG Kremenchuk, StickyPassword
Skype: s.komlach
sergey.komlach@stickypassword.com
Я очень рад снова оказаться в
Хмельницком :)
Что такое JNI/NDK? Быстродействие, много готовых либ, платформозависимость, не-
"Write once, run anywhere" (WORA), аналогия с Reflection, используемые типы и
вызовы
Настройка окружения (NDK x 2), отладка, поддержка и тестирование всех платформ
Особенности выполнения кода (BlackBerry10 (mktime()), IntelAtom, х64), tmpdir(), флаги
оптимизации, порезаный Bionic и прочие либы в Андроид, удаление SO-шек на Sony
при апдейте
Рассмотрим….
Wiki: Java Native Interface (JNI) — стандартный механизм для запуска кода, под
управлением виртуальной машины Java (JVM), который написан на языках С/С++ или
Ассемблера, и скомпонован в виде динамических библиотек, позволяет не
использовать статическое связывание. Это даёт возможность вызова функции С/С++
из программы на Java, и наоборот. Более ранние интерфейсы, в отличие от JNI, не
удовлетворяли условию двоичной совместимости.
Wiki: В 2009 году в дополнение к ADT был опубликован Android Native Development Kit
(NDK) — пакет инструментариев и библиотек, позволяющий реализовать часть
приложения на языке С/С++. NDK рекомендуется использовать для разработки
участков кода, критичных к скорости.
JNI/NDK
Реально же наиболее частое применение:
Работа с OpenGL ES
Использование кросс-платформенных игровых движков, например Cocos2Dx
Использование уже написанного на C/C++ кода (а его ох как дофига написано!). Часто,
это работа с мультимедиа, например FFMPEG, libpng или наукоемкие вещи типа openCV
«Обход» «бутылочного горлышка» в программе (UP! «тяжелых» процессов)
Кроссплатформенное (повторное) использование кода
JNI/NDK
Работа с NDK на порядок усложняет разработку.
- Разработчик должен понимать Java (само собой)
- С/С++ (особенно внимание на память, указатели, треды/семафоры и т.д)
- команды и принципы работы JVM (очень пригодится если вы уже работали с
Reflection)
Class cls = sample1.getClass();
try {
cls.getDeclaredMethod("print", String.class).invoke(sample1, "sample class");
cls.getDeclaredMethod("print", String.class).invoke(sample1, "test string");
cls.getDeclaredMethod("print", null).invoke(sample2, null);
cls.getDeclaredMethod("print", null).invoke(sample3, null);
} catch (Exception e) {}
- Нужно учитывать большое количество ограничений JNI в Android (порезаные
библиотека, размеры типов, «пустышки» реализаций)
- Сложная настройка среды и особенно отладка
Таким образом, работа с NDK чаще всего представляем из себя процесс (часто —
мучительный) сборки некой библиотеки и написание оберток (wrappers) на нативные
методы. В тоже время, сейчас есть возможность ваять приложение практически без
использования Java, используя NativeActivity (API 9 и выше).
package com.example;
public class NativeTest{
static {
System.loadLibrary("nativetest"); // libs/armeabi-v7a/libnativetest.so
}
public native boolean testMethod(int arg);
}
JNIEXPORT jboolean JNICALL Java_com_example_NativeTest_testMethod(JNIEnv *env, jobject caller, jint arg);
JNIEXPORT — необходимый для JNI модификатор. Типы данных с префиксом «j»:
jdouble, jobject, jstring etc — это «отражения» объектов и типов Java в C/C++.
Именование
jstring
JAVA_JNI_This_1Is_1Native_00024Wrapper_00024_000408_000413
_000397(...)
Дело в том, что _1 это аналог нижнего подчёркивания.
_00024 это символ $, то есть может как разделитель внутреннего класса
использоваться. _00408, 0xxxx, это код в юникоде.
В итоге получается:
class JNI {
static class This_Is_Native {
static class Wrapper$ {
static String Юникод(...)
}
}
}
Именование, часть 2
Java JNI JNI array Code Array Code
boolean jboolean jbooleanArray Z [Z
byte jbyte jbyteArray B [B
char jchar jcharArray C [C
double jdouble jdoubleArray D [D
float jfloat jfloatArray F [F
int jint jintArray I [I
long jlong jlongArray J [J
short jshort jshortArray S [S
Object/Class/
String
jobject/jclass/
jstring
jobjectArray/-/- L/L/L [L/[L/[L
void void - V -
https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
Методы зеркальны Java:
NewString, GetStringLength, GetStringChars, ReleaseStringChars, NewStringUTF, GetStringUTFLength, GetStringUTFChars,
ReleaseStringUTFChars,
jstring NewString(JNIEnv *env, const jchar *unicodeChars,jsize len);
char* cchars = “test me plz”;
size_t clength = strlen(cchars);
return env->NewString((jchar*) cchars, (jsize) clength ); //equels NewString(env, (jchar*) cchars, (jsize) clength );
Методы
Внутренности JNI в Android
Устаналивается APK
Если внутри находятся SO-файлы (аналог DLL) они копируются в
/data/data/apppackage/app_lib/*.so
При первом обращении к классу, использующему нативные библиотеки, последние
загружаются через System.load(«name»)
Библиотека «живет» пока не будет завершено приложение
Как работает взаимодействие
между Java и Native
Качаем NDK. Если вам нужна поддержка только 32-битных архитектур, то нужно NDK
x32 (для arm6, arm7a, x86 & mips), иначе можно исполользовать NDK x64 (arm8,
x86_64 & mips_64 и все х32)
Устанавливаем окружение (путь к папке NDK) «цепляем» в IDE
Альтернативные компиляторы: GCC, Clang, MinGW
Альтернатива - Crysta X NDK (https://www.crystax.net/ru/android/ndk ) (wide chars, C
localizations, full math, C++11/C++14, Boost, Object-C/C++ etc.)
Android* NDK for Intel® Architecture
Выбираем STL
С чего начинается NDK
javah создает файлы заголовков и исходники C из Java класса.
Эти файлы обеспечивают связь, которая позволит взаимодействовать вашему Java и C
коду
javah -classpath bin/classes -jni -d jni com.my.javaclass
javah
Before (Ant/Eclipse) Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_FEATURES += rtti # Enable exceptions in Android.mk
LOCAL_CPP_FEATURES += exceptions # Enable exceptions in Android.mk
LOCAL_LDLIBS := -llog -lz
LOCAL_MODULE := nativeTest
LOCAL_CFLAGS := -DANDROID -O3 -pipe
LOCAL_CXXFLAGS := -DANDROID -O3 -pipe
LOCAL_SRC_FILES :=com_test.cpp
APP_PLATFORM := android-9
APP_STL := stlport_static
APP_ABI := all32
APP_CPPFLAGS += -std=c++11
Before (Ant/Eclipse)
Application.mk
Now: Like a pro (see
NDKSamples)
Gradle/Android Studio
ndk {
moduleName = 'sanangeles'
CFlags.addAll(['-DANDROID_NDK', '-DDISABLE_IMPORTGL'])
CFlags.addAll(['-Wall', '-Werror'])
ldLibs.addAll(['android', 'log', 'dl', 'GLESv1_CM'])
abiFilters.addAll(['armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'])
}
Migrating from Traditional
Android Gradle Plugin
A typical Android Studio project may have a directory structure as follows. File that needs to be change is highlighted in red:
There are some significant changes in the DSL between the new plugin and the traditional one.
.
├── app/
│ ├── app.iml
│ ├── build.gradle
│ └── src/
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew*
├── gradlew.bat
├── local.properties
├── MyApplication.iml
└── settings.gradle
http://tools.android.com/tech-docs/new-
build-system/gradle-experimental
Standart Template Library
Standart Template Library
libstdc++(default) The default minimal system C++ runtime library. N/A
gabi++_static The GAbi++ runtime (static). C++ Exceptions and RTTI
gabi++_shared The GAbi++ runtime (shared). C++ Exceptions and RTTI
stlport_static The STLport runtime (static). C++ Exceptions and RTTI; Standard Library
stlport_shared The STLport runtime (shared). C++ Exceptions and RTTI; Standard Library
gnustl_static The GNU STL (static). C++ Exceptions and RTTI; Standard Library
gnustl_shared The GNU STL (shared). C++ Exceptions and RTTI; Standard Library
c++_static The LLVM libc++ runtime (static). C++ Exceptions and RTTI; Standard Library
c++_shared The LLVM libc++ runtime (shared). C++ Exceptions and RTTI; Standard Library
@echo off
echo Build
set ROOT=%CD%
echo %%ROOT%% = %ROOT%
del build.log 2>nul
call D:androidandroid-ndkndk-build.cmd clean
call D:androidandroid-ndkndk-build.cmd >>build.log 2>&1
pause
Сборка из командной строки
- Логгирование
__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
- StackTrace в LogCat
Dalvik:
F/libc (17861): invalid address or address of corrupt block 0x7f51ce50 passed to dlfree
F/libc (17861): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 29266 (Thread-9488)
ART:
A/art(21149): sart/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xa3
….
A/art(21149): sart/runtime/check_jni.cc:65] native: #07 pc 000bfaad /system/lib/libart.so (art::CheckJNI::NewStringUTF(_JNIEnv*, char const*)+44)
A/art(21149): sart/runtime/check_jni.cc:65] native: #08 pc 00008fbb /data/app/com.stickypassword.android-1/lib/arm/libSPCAgent.so (setValue(_jobject*,
int, long, char*, char*)+202)
A/art(21149): sart/runtime/check_jni.cc:65] native: #09 pc 00009ac7 /data/app/com.stickypassword.android-1/lib/arm/libSPCAgent.so
(Java_com_spc_SPCManager_GetAuthCredentialsV2+82)
Отладка
- GDB (GNU Debugger) — переносимый отладчик проекта GNU, который работает на
многих UNIX-подобных системах и умеет производить отладку многих языков
программирования, включая Си, C++, Free Pascal, FreeBASIC, Ada и Фортран. GDB
— свободное программное обеспечение, распространяемое по лицензии GPL.
- NVIDIA Debug Manager for Android NDK https://developer.nvidia.com/nvidia-
debug-manager-android-ndk
- CoffeeCatch (https://github.com/xroche/coffeecatch) - небольшая библиотека для
перехвата POSIX сигналов и имитирующая работу try{} catch(){} из Java
COFFEE_TRY() {
recurse_madness(42);
*fault = 0;
} COFFEE_CATCH() {
const char*const message = coffeecatch_get_message();
snprintf(string_buffer, sizeof(string_buffer), "%s", message);
*fault = 1;
} COFFEE_END();
GDB & CoffeCatch
http://forum.xda-developers.com/showthread.php?t=2754997
- Optimized for speed yet more all instructions - ARM and THUMB (-O3)
- Optimized for speed also parts which are compiled with Clang (-O3)
- Turned off all debugging code (lack of -g)
- Eliminated redundant loads that come after stores to the same memory location, both partial and full redundancies (-fgcse-las)
- Ran a store motion pass after global common subexpression elimination. This pass attempts to move stores out of loops (-fgcse-sm)
- Performed interprocedural pointer analysis and interprocedural modification and reference analysis (-fipa-pta)
- Performed induction variable optimizations (strength reduction, induction variable merging and induction variable elimination) on trees (-fivopts)
- Didn't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it
also makes an extra register available in many functions (-fomit-frame-pointer)
- Attempted to avoid false dependencies in scheduled code by making use of registers left over after register allocation. This optimization most benefits
processors with lots of registers (-frename-registers)
Flags
http://www.learnopengles.com/a-performance-comparison-between-java-and-c-on-the-nexus-5/
Benchmarks
Blackberry10 и mktime
Android 5 (копирование массивов)
tmpdir()/tmpfile()
флаги оптимизации ( -03,-Ofast, -SSE etc)
порезаный Bionic и прочие либы в Андроид
*.so на Sony
Проблема 01.01.2037
TTF
Грабли
Code Examples
package com.example.testsimplycall;
public class NativeTest {
static {
try{
System.loadLibrary("testSimplyCall");
} catch (UnsatisfiedLinkError err){
//need catch exception
err.printStackTrace();
}
}
public native void testMePlz(String msg);
}
project/jni/com_example_testsimplycall_NativeTest.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#ifndef _Included_com_example_testsimplycall_NativeTest
#define _Included_com_example_testsimplycall_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env,jobject
jobj, jstring msg);
#ifdef __cplusplus
}
#endif
#endif
project/jni/com_example_testsimplycall_NativeTest.cpp
#include <def.h>
#include <jni.h>
#include "com_example_testsimplycall_NativeTest.h"
JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env,
jobject jobj, jstring msg){
jboolean isCopy;
const char * Str = env->GetStringUTFChars(msg, &isCopy);
LOGI("string = "%s"",Str);
}
package com.example.testcallback;
import android.util.Log;
public interface NativeCallback {
public void print(String str);
}
public class NativeTest {
static {
try{
System.loadLibrary("testCallback");
} catch (UnsatisfiedLinkError err){
err.printStackTrace();
}
}
public NativeCallback nativecallback = new NativeCallback(){
@Override
public void print(String str) {
Log.d("JAVA_CALLBACK", str);
}};
public native void testMePlz(String msg);
public native void SetListener(NativeCallback javacallback);
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#ifndef _Included_com_example_testcallback_NativeTest
#define _Included_com_example_testcallback_NativeTest
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env,
jobject jobj, jstring msg);
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener(
JNIEnv *env, jobject jobj, jobject callback);
#ifdef __cplusplus
}
#endif
#endif
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "com_example_testcallback_NativeTest.h"
jobject javaCallback;
JavaVM* mJVM;
/* Reference to Java-object*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
{
mJVM = jvm;
return JNI_VERSION_1_2;
}
JNIEnv* getJniEnv() {
JavaVMAttachArgs attachArgs;
attachArgs.version = JNI_VERSION_1_2;
attachArgs.name = ">>>NativeThread__Any";
attachArgs.group = NULL;
JNIEnv* env;
if (mJVM->AttachCurrentThread(&env, &attachArgs) != JNI_OK) {
env = NULL;
}
return env;
void printToLogcat(const char* msg) {
JNIEnv* pEnv = getJniEnv();
jclass javaClass = pEnv->GetObjectClass(javaCallback);
if (javaClass != NULL) {
jmethodID javaMethodID = pEnv-
>GetMethodID(javaClass,"print","(Ljava/lang/String;)V");
jstring logmsg = pEnv->NewStringUTF(msg);
if (logmsg != NULL) {
pEnv->CallVoidMethod(javaCallback, javaMethodID, logmsg);
pEnv->DeleteLocalRef(logmsg);
logmsg = NULL;
}
pEnv->DeleteLocalRef(javaClass);
javaClass = NULL;
}
}
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener(JNIEnv *env, jobject
jobj, jobject callback) {
if(javaCallback)
env->DeleteGlobalRef(javaCallback);
javaCallback = env->NewGlobalRef(callback);
}
JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env,jobject jobj,
jstring msg){
jboolean isCopy;
const char * Str = env->GetStringUTFChars(msg, &isCopy);
printToLogcat(Str);
}

More Related Content

What's hot

C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.Igor Shkulipa
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомTatyanazaxarova
 
C++ весна 2014 лекция 5
C++ весна 2014 лекция 5C++ весна 2014 лекция 5
C++ весна 2014 лекция 5Technopark
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.Igor Shkulipa
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage CollectorOlexandra Dmytrenko
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.Igor Shkulipa
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4Technopark
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыcorehard_by
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.Igor Shkulipa
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.Igor Shkulipa
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Yauheni Akhotnikau
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and catscorehard_by
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.Igor Shkulipa
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковSergey Platonov
 
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаАндрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаSergey Platonov
 
Секреты сборки мусора в Java
Секреты сборки мусора в JavaСекреты сборки мусора в Java
Секреты сборки мусора в Javaaragozin
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Sergey Platonov
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о BoostSergey Platonov
 

What's hot (20)

C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.C++ STL & Qt. Занятие 11.
C++ STL & Qt. Занятие 11.
 
Разница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментомРазница в подходах анализа кода компилятором и выделенным инструментом
Разница в подходах анализа кода компилятором и выделенным инструментом
 
JRebel
JRebelJRebel
JRebel
 
C++ весна 2014 лекция 5
C++ весна 2014 лекция 5C++ весна 2014 лекция 5
C++ весна 2014 лекция 5
 
C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.C++ STL & Qt. Занятие 01.
C++ STL & Qt. Занятие 01.
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage Collector
 
C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.C++ STL & Qt. Занятие 08.
C++ STL & Qt. Занятие 08.
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.C++ STL & Qt. Занятие 02.
C++ STL & Qt. Занятие 02.
 
C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.C++ STL & Qt. Занятие 05.
C++ STL & Qt. Занятие 05.
 
Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++Шишки, набитые за 15 лет использования акторов в C++
Шишки, набитые за 15 лет использования акторов в C++
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
C++ refelection and cats
C++ refelection and catsC++ refelection and cats
C++ refelection and cats
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
 
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаАндрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кода
 
Секреты сборки мусора в Java
Секреты сборки мусора в JavaСекреты сборки мусора в Java
Секреты сборки мусора в Java
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
Антон Полухин, Немного о Boost
Антон Полухин, Немного о BoostАнтон Полухин, Немного о Boost
Антон Полухин, Немного о Boost
 

Similar to New Android NDK & JNI

IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаMikhail Chinkov
 
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray ChapelЛекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray ChapelMikhail Kurnosov
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Yandex
 
Лекция 11: Программирование графических процессоров на NVIDIA CUDA
Лекция 11: Программирование графических процессоров на NVIDIA CUDAЛекция 11: Программирование графических процессоров на NVIDIA CUDA
Лекция 11: Программирование графических процессоров на NVIDIA CUDAMikhail Kurnosov
 
Opensource на .NET
Opensource на .NETOpensource на .NET
Opensource на .NETlugnsk
 
Работа высоконагруженного DNS-сервера
Работа высоконагруженного DNS-сервераРабота высоконагруженного DNS-сервера
Работа высоконагруженного DNS-сервераudmlug
 
Dz Java Hi Load 0.4
Dz Java Hi Load 0.4Dz Java Hi Load 0.4
Dz Java Hi Load 0.4HighLoad2009
 
CUDA Course 2010 at MSU
CUDA Course 2010 at MSUCUDA Course 2010 at MSU
CUDA Course 2010 at MSUlarhat
 
Разработка приложений для Android на С++. Юрий Береза, Shturmann
Разработка приложений для Android на С++. Юрий Береза, ShturmannРазработка приложений для Android на С++. Юрий Береза, Shturmann
Разработка приложений для Android на С++. Юрий Береза, Shturmannyaevents
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
Desktop app based on node js and html5
Desktop app based on node js and html5Desktop app based on node js and html5
Desktop app based on node js and html5Provectus
 
Язык параллельного программирования Cray Chapel
Язык параллельного программирования Cray ChapelЯзык параллельного программирования Cray Chapel
Язык параллельного программирования Cray ChapelMikhail Kurnosov
 
доклад про Llvm
доклад про Llvmдоклад про Llvm
доклад про LlvmVadim Evard
 
Внедрение параллельного рендеринга в игровой движок
Внедрение параллельного рендеринга в игровой движокВнедрение параллельного рендеринга в игровой движок
Внедрение параллельного рендеринга в игровой движокRoman_Lut
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"oelifantiev
 
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется всеОмские ИТ-субботники
 
Доклад в Mail.ru 01.11.12
Доклад в Mail.ru 01.11.12Доклад в Mail.ru 01.11.12
Доклад в Mail.ru 01.11.12Alex Tutubalin
 

Similar to New Android NDK & JNI (20)

IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчика
 
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray ChapelЛекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
Лекция 12 (часть 1): Языки программирования семейства PGAS: Cray Chapel
 
Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"Леонид Васильев "Python в инфраструктуре поиска"
Леонид Васильев "Python в инфраструктуре поиска"
 
Node.js (RichClient)
 Node.js (RichClient) Node.js (RichClient)
Node.js (RichClient)
 
Лекция 11: Программирование графических процессоров на NVIDIA CUDA
Лекция 11: Программирование графических процессоров на NVIDIA CUDAЛекция 11: Программирование графических процессоров на NVIDIA CUDA
Лекция 11: Программирование графических процессоров на NVIDIA CUDA
 
Opensource на .NET
Opensource на .NETOpensource на .NET
Opensource на .NET
 
Работа высоконагруженного DNS-сервера
Работа высоконагруженного DNS-сервераРабота высоконагруженного DNS-сервера
Работа высоконагруженного DNS-сервера
 
Dz Java Hi Load 0.4
Dz Java Hi Load 0.4Dz Java Hi Load 0.4
Dz Java Hi Load 0.4
 
CUDA Course 2010 at MSU
CUDA Course 2010 at MSUCUDA Course 2010 at MSU
CUDA Course 2010 at MSU
 
Разработка приложений для Android на С++. Юрий Береза, Shturmann
Разработка приложений для Android на С++. Юрий Береза, ShturmannРазработка приложений для Android на С++. Юрий Береза, Shturmann
Разработка приложений для Android на С++. Юрий Береза, Shturmann
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
php frameworks
php frameworksphp frameworks
php frameworks
 
Desktop app based on node js and html5
Desktop app based on node js and html5Desktop app based on node js and html5
Desktop app based on node js and html5
 
Язык параллельного программирования Cray Chapel
Язык параллельного программирования Cray ChapelЯзык параллельного программирования Cray Chapel
Язык параллельного программирования Cray Chapel
 
доклад про Llvm
доклад про Llvmдоклад про Llvm
доклад про Llvm
 
Внедрение параллельного рендеринга в игровой движок
Внедрение параллельного рендеринга в игровой движокВнедрение параллельного рендеринга в игровой движок
Внедрение параллельного рендеринга в игровой движок
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"
 
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
2013-01-05 01 Леонид Евдокимов. Web scale. Взорвется все
 
Доклад в Mail.ru 01.11.12
Доклад в Mail.ru 01.11.12Доклад в Mail.ru 01.11.12
Доклад в Mail.ru 01.11.12
 
Native Development
Native DevelopmentNative Development
Native Development
 

More from Stfalcon Meetups

Conversion centered design 3
Conversion centered design 3Conversion centered design 3
Conversion centered design 3Stfalcon Meetups
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon Meetups
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon Meetups
 
Design of the_future_30_05_2019
Design of the_future_30_05_2019Design of the_future_30_05_2019
Design of the_future_30_05_2019Stfalcon Meetups
 
Global sales - a few insights
Global sales - a few insightsGlobal sales - a few insights
Global sales - a few insightsStfalcon Meetups
 
How to build your own startup
How to build your own startupHow to build your own startup
How to build your own startupStfalcon Meetups
 
Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом Stfalcon Meetups
 
Парнерство нидерланды
Парнерство нидерландыПарнерство нидерланды
Парнерство нидерландыStfalcon Meetups
 
Риси гарного менеджера
Риси гарного менеджераРиси гарного менеджера
Риси гарного менеджераStfalcon Meetups
 
Между заказчиком и разработчиком
Между заказчиком и разработчикомМежду заказчиком и разработчиком
Между заказчиком и разработчикомStfalcon Meetups
 
майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”Stfalcon Meetups
 
Kubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CDKubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CDStfalcon Meetups
 

More from Stfalcon Meetups (20)

Conversion centered design 3
Conversion centered design 3Conversion centered design 3
Conversion centered design 3
 
Discovery phase
Discovery phaseDiscovery phase
Discovery phase
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020
 
Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020Stfalcon QA Meetup 31.01.2020
Stfalcon QA Meetup 31.01.2020
 
Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11
 
Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11Stfalcon PM Meetup 21.11
Stfalcon PM Meetup 21.11
 
Design of the_future_30_05_2019
Design of the_future_30_05_2019Design of the_future_30_05_2019
Design of the_future_30_05_2019
 
2 5404811386729530203
2 54048113867295302032 5404811386729530203
2 5404811386729530203
 
Team evolution
Team evolutionTeam evolution
Team evolution
 
Mobile&Privacy
Mobile&PrivacyMobile&Privacy
Mobile&Privacy
 
Global sales - a few insights
Global sales - a few insightsGlobal sales - a few insights
Global sales - a few insights
 
How to build your own startup
How to build your own startupHow to build your own startup
How to build your own startup
 
Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом Первая и последняя встреча с клиентом
Первая и последняя встреча с клиентом
 
Парнерство нидерланды
Парнерство нидерландыПарнерство нидерланды
Парнерство нидерланды
 
Риси гарного менеджера
Риси гарного менеджераРиси гарного менеджера
Риси гарного менеджера
 
Между заказчиком и разработчиком
Между заказчиком и разработчикомМежду заказчиком и разработчиком
Между заказчиком и разработчиком
 
Cv vs resume
Cv vs resumeCv vs resume
Cv vs resume
 
Vue.js
Vue.jsVue.js
Vue.js
 
майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”майстер-клас “Управління ризиками”
майстер-клас “Управління ризиками”
 
Kubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CDKubernetes: від знайомства до використання у CI/CD
Kubernetes: від знайомства до використання у CI/CD
 

New Android NDK & JNI

  • 1. Android NDK & JNI Sergey Komlach GDG Kremenchuk, StickyPassword Skype: s.komlach sergey.komlach@stickypassword.com
  • 2. Я очень рад снова оказаться в Хмельницком :)
  • 3. Что такое JNI/NDK? Быстродействие, много готовых либ, платформозависимость, не- "Write once, run anywhere" (WORA), аналогия с Reflection, используемые типы и вызовы Настройка окружения (NDK x 2), отладка, поддержка и тестирование всех платформ Особенности выполнения кода (BlackBerry10 (mktime()), IntelAtom, х64), tmpdir(), флаги оптимизации, порезаный Bionic и прочие либы в Андроид, удаление SO-шек на Sony при апдейте Рассмотрим….
  • 4. Wiki: Java Native Interface (JNI) — стандартный механизм для запуска кода, под управлением виртуальной машины Java (JVM), который написан на языках С/С++ или Ассемблера, и скомпонован в виде динамических библиотек, позволяет не использовать статическое связывание. Это даёт возможность вызова функции С/С++ из программы на Java, и наоборот. Более ранние интерфейсы, в отличие от JNI, не удовлетворяли условию двоичной совместимости. Wiki: В 2009 году в дополнение к ADT был опубликован Android Native Development Kit (NDK) — пакет инструментариев и библиотек, позволяющий реализовать часть приложения на языке С/С++. NDK рекомендуется использовать для разработки участков кода, критичных к скорости. JNI/NDK
  • 5. Реально же наиболее частое применение: Работа с OpenGL ES Использование кросс-платформенных игровых движков, например Cocos2Dx Использование уже написанного на C/C++ кода (а его ох как дофига написано!). Часто, это работа с мультимедиа, например FFMPEG, libpng или наукоемкие вещи типа openCV «Обход» «бутылочного горлышка» в программе (UP! «тяжелых» процессов) Кроссплатформенное (повторное) использование кода JNI/NDK
  • 6. Работа с NDK на порядок усложняет разработку. - Разработчик должен понимать Java (само собой) - С/С++ (особенно внимание на память, указатели, треды/семафоры и т.д) - команды и принципы работы JVM (очень пригодится если вы уже работали с Reflection) Class cls = sample1.getClass(); try { cls.getDeclaredMethod("print", String.class).invoke(sample1, "sample class"); cls.getDeclaredMethod("print", String.class).invoke(sample1, "test string"); cls.getDeclaredMethod("print", null).invoke(sample2, null); cls.getDeclaredMethod("print", null).invoke(sample3, null); } catch (Exception e) {} - Нужно учитывать большое количество ограничений JNI в Android (порезаные библиотека, размеры типов, «пустышки» реализаций) - Сложная настройка среды и особенно отладка Таким образом, работа с NDK чаще всего представляем из себя процесс (часто — мучительный) сборки некой библиотеки и написание оберток (wrappers) на нативные методы. В тоже время, сейчас есть возможность ваять приложение практически без использования Java, используя NativeActivity (API 9 и выше).
  • 7. package com.example; public class NativeTest{ static { System.loadLibrary("nativetest"); // libs/armeabi-v7a/libnativetest.so } public native boolean testMethod(int arg); } JNIEXPORT jboolean JNICALL Java_com_example_NativeTest_testMethod(JNIEnv *env, jobject caller, jint arg); JNIEXPORT — необходимый для JNI модификатор. Типы данных с префиксом «j»: jdouble, jobject, jstring etc — это «отражения» объектов и типов Java в C/C++. Именование
  • 8. jstring JAVA_JNI_This_1Is_1Native_00024Wrapper_00024_000408_000413 _000397(...) Дело в том, что _1 это аналог нижнего подчёркивания. _00024 это символ $, то есть может как разделитель внутреннего класса использоваться. _00408, 0xxxx, это код в юникоде. В итоге получается: class JNI { static class This_Is_Native { static class Wrapper$ { static String Юникод(...) } } } Именование, часть 2
  • 9. Java JNI JNI array Code Array Code boolean jboolean jbooleanArray Z [Z byte jbyte jbyteArray B [B char jchar jcharArray C [C double jdouble jdoubleArray D [D float jfloat jfloatArray F [F int jint jintArray I [I long jlong jlongArray J [J short jshort jshortArray S [S Object/Class/ String jobject/jclass/ jstring jobjectArray/-/- L/L/L [L/[L/[L void void - V -
  • 10. https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html Методы зеркальны Java: NewString, GetStringLength, GetStringChars, ReleaseStringChars, NewStringUTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars, jstring NewString(JNIEnv *env, const jchar *unicodeChars,jsize len); char* cchars = “test me plz”; size_t clength = strlen(cchars); return env->NewString((jchar*) cchars, (jsize) clength ); //equels NewString(env, (jchar*) cchars, (jsize) clength ); Методы
  • 12. Устаналивается APK Если внутри находятся SO-файлы (аналог DLL) они копируются в /data/data/apppackage/app_lib/*.so При первом обращении к классу, использующему нативные библиотеки, последние загружаются через System.load(«name») Библиотека «живет» пока не будет завершено приложение Как работает взаимодействие между Java и Native
  • 13. Качаем NDK. Если вам нужна поддержка только 32-битных архитектур, то нужно NDK x32 (для arm6, arm7a, x86 & mips), иначе можно исполользовать NDK x64 (arm8, x86_64 & mips_64 и все х32) Устанавливаем окружение (путь к папке NDK) «цепляем» в IDE Альтернативные компиляторы: GCC, Clang, MinGW Альтернатива - Crysta X NDK (https://www.crystax.net/ru/android/ndk ) (wide chars, C localizations, full math, C++11/C++14, Boost, Object-C/C++ etc.) Android* NDK for Intel® Architecture Выбираем STL С чего начинается NDK
  • 14. javah создает файлы заголовков и исходники C из Java класса. Эти файлы обеспечивают связь, которая позволит взаимодействовать вашему Java и C коду javah -classpath bin/classes -jni -d jni com.my.javaclass javah
  • 15. Before (Ant/Eclipse) Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CPP_FEATURES += rtti # Enable exceptions in Android.mk LOCAL_CPP_FEATURES += exceptions # Enable exceptions in Android.mk LOCAL_LDLIBS := -llog -lz LOCAL_MODULE := nativeTest LOCAL_CFLAGS := -DANDROID -O3 -pipe LOCAL_CXXFLAGS := -DANDROID -O3 -pipe LOCAL_SRC_FILES :=com_test.cpp
  • 16. APP_PLATFORM := android-9 APP_STL := stlport_static APP_ABI := all32 APP_CPPFLAGS += -std=c++11 Before (Ant/Eclipse) Application.mk
  • 17. Now: Like a pro (see NDKSamples) Gradle/Android Studio ndk { moduleName = 'sanangeles' CFlags.addAll(['-DANDROID_NDK', '-DDISABLE_IMPORTGL']) CFlags.addAll(['-Wall', '-Werror']) ldLibs.addAll(['android', 'log', 'dl', 'GLESv1_CM']) abiFilters.addAll(['armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']) }
  • 18. Migrating from Traditional Android Gradle Plugin A typical Android Studio project may have a directory structure as follows. File that needs to be change is highlighted in red: There are some significant changes in the DSL between the new plugin and the traditional one. . ├── app/ │ ├── app.iml │ ├── build.gradle │ └── src/ ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew* ├── gradlew.bat ├── local.properties ├── MyApplication.iml └── settings.gradle
  • 21. Standart Template Library libstdc++(default) The default minimal system C++ runtime library. N/A gabi++_static The GAbi++ runtime (static). C++ Exceptions and RTTI gabi++_shared The GAbi++ runtime (shared). C++ Exceptions and RTTI stlport_static The STLport runtime (static). C++ Exceptions and RTTI; Standard Library stlport_shared The STLport runtime (shared). C++ Exceptions and RTTI; Standard Library gnustl_static The GNU STL (static). C++ Exceptions and RTTI; Standard Library gnustl_shared The GNU STL (shared). C++ Exceptions and RTTI; Standard Library c++_static The LLVM libc++ runtime (static). C++ Exceptions and RTTI; Standard Library c++_shared The LLVM libc++ runtime (shared). C++ Exceptions and RTTI; Standard Library
  • 22. @echo off echo Build set ROOT=%CD% echo %%ROOT%% = %ROOT% del build.log 2>nul call D:androidandroid-ndkndk-build.cmd clean call D:androidandroid-ndkndk-build.cmd >>build.log 2>&1 pause Сборка из командной строки
  • 23.
  • 24. - Логгирование __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) - StackTrace в LogCat Dalvik: F/libc (17861): invalid address or address of corrupt block 0x7f51ce50 passed to dlfree F/libc (17861): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 29266 (Thread-9488) ART: A/art(21149): sart/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xa3 …. A/art(21149): sart/runtime/check_jni.cc:65] native: #07 pc 000bfaad /system/lib/libart.so (art::CheckJNI::NewStringUTF(_JNIEnv*, char const*)+44) A/art(21149): sart/runtime/check_jni.cc:65] native: #08 pc 00008fbb /data/app/com.stickypassword.android-1/lib/arm/libSPCAgent.so (setValue(_jobject*, int, long, char*, char*)+202) A/art(21149): sart/runtime/check_jni.cc:65] native: #09 pc 00009ac7 /data/app/com.stickypassword.android-1/lib/arm/libSPCAgent.so (Java_com_spc_SPCManager_GetAuthCredentialsV2+82) Отладка
  • 25. - GDB (GNU Debugger) — переносимый отладчик проекта GNU, который работает на многих UNIX-подобных системах и умеет производить отладку многих языков программирования, включая Си, C++, Free Pascal, FreeBASIC, Ada и Фортран. GDB — свободное программное обеспечение, распространяемое по лицензии GPL. - NVIDIA Debug Manager for Android NDK https://developer.nvidia.com/nvidia- debug-manager-android-ndk - CoffeeCatch (https://github.com/xroche/coffeecatch) - небольшая библиотека для перехвата POSIX сигналов и имитирующая работу try{} catch(){} из Java COFFEE_TRY() { recurse_madness(42); *fault = 0; } COFFEE_CATCH() { const char*const message = coffeecatch_get_message(); snprintf(string_buffer, sizeof(string_buffer), "%s", message); *fault = 1; } COFFEE_END(); GDB & CoffeCatch
  • 26. http://forum.xda-developers.com/showthread.php?t=2754997 - Optimized for speed yet more all instructions - ARM and THUMB (-O3) - Optimized for speed also parts which are compiled with Clang (-O3) - Turned off all debugging code (lack of -g) - Eliminated redundant loads that come after stores to the same memory location, both partial and full redundancies (-fgcse-las) - Ran a store motion pass after global common subexpression elimination. This pass attempts to move stores out of loops (-fgcse-sm) - Performed interprocedural pointer analysis and interprocedural modification and reference analysis (-fipa-pta) - Performed induction variable optimizations (strength reduction, induction variable merging and induction variable elimination) on trees (-fivopts) - Didn't keep the frame pointer in a register for functions that don't need one. This avoids the instructions to save, set up and restore frame pointers; it also makes an extra register available in many functions (-fomit-frame-pointer) - Attempted to avoid false dependencies in scheduled code by making use of registers left over after register allocation. This optimization most benefits processors with lots of registers (-frename-registers) Flags
  • 28. Blackberry10 и mktime Android 5 (копирование массивов) tmpdir()/tmpfile() флаги оптимизации ( -03,-Ofast, -SSE etc) порезаный Bionic и прочие либы в Андроид *.so на Sony Проблема 01.01.2037 TTF Грабли
  • 30. package com.example.testsimplycall; public class NativeTest { static { try{ System.loadLibrary("testSimplyCall"); } catch (UnsatisfiedLinkError err){ //need catch exception err.printStackTrace(); } } public native void testMePlz(String msg); }
  • 31. project/jni/com_example_testsimplycall_NativeTest.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #ifndef _Included_com_example_testsimplycall_NativeTest #define _Included_com_example_testsimplycall_NativeTest #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env,jobject jobj, jstring msg); #ifdef __cplusplus } #endif #endif project/jni/com_example_testsimplycall_NativeTest.cpp #include <def.h> #include <jni.h> #include "com_example_testsimplycall_NativeTest.h" JNIEXPORT void JNICALL Java_com_example_testsimplycall_NativeTest_testMePlz(JNIEnv *env, jobject jobj, jstring msg){ jboolean isCopy; const char * Str = env->GetStringUTFChars(msg, &isCopy); LOGI("string = "%s"",Str); }
  • 32. package com.example.testcallback; import android.util.Log; public interface NativeCallback { public void print(String str); } public class NativeTest { static { try{ System.loadLibrary("testCallback"); } catch (UnsatisfiedLinkError err){ err.printStackTrace(); } } public NativeCallback nativecallback = new NativeCallback(){ @Override public void print(String str) { Log.d("JAVA_CALLBACK", str); }}; public native void testMePlz(String msg); public native void SetListener(NativeCallback javacallback); }
  • 33. /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #ifndef _Included_com_example_testcallback_NativeTest #define _Included_com_example_testcallback_NativeTest #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env, jobject jobj, jstring msg); JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener( JNIEnv *env, jobject jobj, jobject callback); #ifdef __cplusplus } #endif #endif
  • 34. #include <jni.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include "com_example_testcallback_NativeTest.h" jobject javaCallback; JavaVM* mJVM; /* Reference to Java-object*/ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { mJVM = jvm; return JNI_VERSION_1_2; } JNIEnv* getJniEnv() { JavaVMAttachArgs attachArgs; attachArgs.version = JNI_VERSION_1_2; attachArgs.name = ">>>NativeThread__Any"; attachArgs.group = NULL; JNIEnv* env; if (mJVM->AttachCurrentThread(&env, &attachArgs) != JNI_OK) { env = NULL; } return env;
  • 35. void printToLogcat(const char* msg) { JNIEnv* pEnv = getJniEnv(); jclass javaClass = pEnv->GetObjectClass(javaCallback); if (javaClass != NULL) { jmethodID javaMethodID = pEnv- >GetMethodID(javaClass,"print","(Ljava/lang/String;)V"); jstring logmsg = pEnv->NewStringUTF(msg); if (logmsg != NULL) { pEnv->CallVoidMethod(javaCallback, javaMethodID, logmsg); pEnv->DeleteLocalRef(logmsg); logmsg = NULL; } pEnv->DeleteLocalRef(javaClass); javaClass = NULL; } }
  • 36. JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_SetListener(JNIEnv *env, jobject jobj, jobject callback) { if(javaCallback) env->DeleteGlobalRef(javaCallback); javaCallback = env->NewGlobalRef(callback); } JNIEXPORT void JNICALL Java_com_example_testcallback_NativeTest_testMePlz(JNIEnv *env,jobject jobj, jstring msg){ jboolean isCopy; const char * Str = env->GetStringUTFChars(msg, &isCopy); printToLogcat(Str); }