-
Notifications
You must be signed in to change notification settings - Fork 583
Using Android NDK
Zayin Krige edited this page Sep 7, 2018
·
2 revisions
Created Mar 3, 2013 by noranbora
JavaCPP already supports Android NDK with command option 'properties'. But some people may want to use more Android-way. This document explains how to use javacpp for cpp-generation and android-ndk for compilation with/without maven.
- Android NDK r8d or above. (http://developer.android.com/tools/sdk/ndk/index.html) r8c is a bit buggy.
- JavaCPP 0.10 or above.
- Proper javacpp annotation in java source.
- Use @Platform(library="XXX") to decide cpp&so name which will be used in Android.mk
@Platform(library = "jniHello", include = { "hello.h"})
- jni/Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := jniHello
LOCAL_SRC_FILES := jniHello.cpp
LOCAL_C_INCLUDES := hello.h
LOCAL_LDLIBS := -llog
LOCAL_CPP_FEATURES := exceptions
- jni/Application.mk
APP_ABI := armeabi armeabi-v7a x86 # or simply 'all' then it will generate armeabi, armeabi-v7a, x86, mips
APP_STL := gnustl_static
apply plugin: 'com.android.application'
def ndkPath
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "com.yourpackage"
minSdkVersion 22
targetSdkVersion 28
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
}
}
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters /**/ 'x86', 'x86_64', 'armeabi', 'armeabi-v7a','arm64-v8a'
}
}
externalNativeBuild {
android {
externalNativeBuild {
ndkPath = getNdkDirectory().toString()
}
}
cmake {
path "CMakeLists.txt"
}
}
sourceSets.main {
jniLibs.srcDir 'src/main/libs'
jni.srcDirs = [] //disable automatic ndk-build call
}
}
android.applicationVariants.all { variant ->
println("")
println 'variant.name: ' + variant.name
def projectDir = project.projectDir.absolutePath
def classesDir = variant.javaCompile.destinationDir
def jniDir = file("$projectDir/src/main/cpp/").absolutePath
println(projectDir)
println(classesDir)
println(jniDir)
println("++javacpp file path:" + (configurations.javacpp.asPath))
println(ndkPath)
println(configurations.javacpp.asPath)
// NOTE: The functionlity of javacpp is create jni cpp file from java code.++++++++++++++++
// javacpp workflow:
// 1.generate jni cpp file by javacpp-java code file.
// 2.nkd build with android.mk
// 3.common compile apk file.
variant.javaCompile.doLast {
println '===javacpp start==='
javaexec {
main = 'org.bytedeco.javacpp.tools.Builder'
//NOTE: jar version must be same with the dependency jar.
classpath = files(configurations.javacpp.asPath)
args '-cp', "$classesDir",
'-properties', 'android-arm',
'-Dplatform.root=' + ndkPath,
'-Dplatform.compiler=' + ndkPath + '/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++',
//NOTE: include path will auto work by javacpp.jar 1.1 version.(see Android.mk)
// "-Dplatform.includepath=" + includePath+"/include:" +includePath+"/libs/armeabi/include",
"-nocompile", "idl.baidu.cpp.*",
"-d", "${jniDir}" // jni file destination folder.
}
println '===javacpp done==='
}
}
configurations {
javacpp
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:28.0.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'org.bytedeco:javacpp:1.4.2'
javacpp 'org.bytedeco:javacpp:1.4.2'
}
-
Run javacpp
C:\> java -jar libs\javacpp.jar -cp bin\classes -cp 'path-to-android.jar' -d jni -nocompile com.hello.package.*
-
-cp 'path-to-android.jar'
is only required if static {} code in java classes has Android code such as android.util.Log... -
-d jni, -nocompile
is required so that JavaCPP generates cpp files in jni directory and ndk-build compiles them.
-
-
Run ndk-build
C:\> ndk-build
- so files will be generated under libs\hardware_platform such as libs\armeabi, libs\x86
Assume default android-related plugin is already set in pom.xml.
- Add javacpp dependency in
<dependencies>
.
<dependency>
<groupId>org.bytedeco.javacpp</groupId>
<artifactId>javacpp</artifactId>
<version>0.10</version>
</dependency>
- Use latest android-maven-plugin. Old version cannot properly recognize ndk-build target. (I tested with 3.4.0 and it's ok.)
- To use the property ${org.bytedeco.javacpp:javacpp:jar}, add 'properties' goal in
<build>
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
- To generate cpp files, add 'exec' goal with javacpp in
<build>
.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>javacpp_generate</id>
<phase>process-classes</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar</argument> <argument>${org.bytedeco.javacpp:javacpp:jar}</argument>
<argument>-cp</argument> <argument>${project.build.outputDirectory}</argument>
<argument>-d</argument> <argument>${project.basedir}/jni</argument>
<argument>-nocompile</argument>
<argument>com.package.hello.*</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
- To compile cpp files with ndk-build, add 'ndk-build' goal in
<build>
.
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<executions>
<execution>
<id>javacpp_generate</id>
<phase>process-classes</phase>
<goals>
<goal>ndk-build</goal>
</goals>
<configuration>
<target>all</target>
</configuration>
</execution>
</executions>
</plugin>
- To clean generated files, add 'clean' configuration in
<build>
.
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<filesets>
<fileset>
<directory>libs</directory>
<excludes>
<exclude>*.jar</exclude>
</excludes>
</fileset>
<fileset>
<directory>obj</directory>
</fileset>
<fileset>
<directory>jni</directory>
<includes>
<include>*.cpp</include>
</includes>
</fileset>
</filesets>
</configuration>
</plugin>