我已经使用生成的本地库ndk-build
它,我能够加载并在我的Android应用程序中使用。 不过,我想对写我的应用程序,这部分的一些测试。
当调用在我的测试本机的功能,我收到此异常消息:
java.lang.UnsatisfiedLinkError: no process in java.library.path
...其中process
是我的本地库导入,命名libprocess.so
。
我使用Roboelectric我的测试,并运行这个特殊的一个与RobolectricTestRunner
,如果它的确与众不同。
我怎样才能得到我的测试项目,以“看到”本地库?
编辑:我加载库在我的应用程序,如下所示:
static {
System.loadLibrary("process");
}
public static native int[] process(double[][] data);
调用Process.process(array)
工作在应用程序(库被加载)的罚款,但是从上面给出的异常运行测试时失败。
编辑2:如果我设置-Djava.library.path="<the directory of libprocess.so>"
作为VM参数,则:
System.out.println(System.getProperty("java.library.path"));
确实显示我设置的路径,但我仍然得到同样的异常。 我设置的目录如下:
<project-name>/libs/x86
......但作为一个绝对路径。
对于任何人还在找,blork有正确的想法 - 你需要编译你的本机库为您的“天然”平台(Windows,Linux,苹果)。 而Android NDK构建Android平台库(.so文件 - 还可以在Linux上工作),这就是为什么在活动测试用例运行(因为它加载了一个Android实例)没有问题。
为了获得低的水平,运行速度快海拉JUnit测试,你需要支持你的JVM。 在Windows中,这可能是生成DLL,在苹果,它的建设dylibs(假设共享库)。
我刚刚完成我的Android NDK,痛饮,例如回购(样本https://github.com/sureshjoshi/android-ndk-swig-example/issues/9 )。
基本上,我CMakeLists,我添加了一个苹果警告:
# Need to create the .dylib and .jnilib files in order to run JUnit tests
if (APPLE)
# Ensure jni.h is found
find_package(JNI REQUIRED)
include_directories(${JAVA_INCLUDE_PATH})
然后,我要确保摇篮运行单元测试,但使用Mac构建系统(未NDK)。
def osxDir = projectDir.absolutePath + '/.externalNativeBuild/cmake/debug/osx/'
task createBuildDir() {
def folder = new File(osxDir)
if (!folder.exists()) {
folder.mkdirs()
}
}
task runCMake(type: Exec) {
dependsOn createBuildDir
workingDir osxDir // Jump to future build directory
commandLine '/usr/local/bin/cmake' // Path from HomeBrew installation
args '../../../../' // Relative path for out-of-source builds
}
task runMake(type: Exec) {
dependsOn runCMake
workingDir osxDir
commandLine 'make'
}
project.afterEvaluate {
// Not sure how much of a hack this is - but it allows CMake/SWIG to run before Android Studio
// complains about missing generated files
// TODO: Probably need a release hook too?
javaPreCompileDebug.dependsOn externalNativeBuildDebug
if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
javaPreCompileDebugAndroidTest.dependsOn runMake
}
}
CAVEAT时间!
当您使用此方法,你技术上没有测试NDK生成库。 您正在测试相同的代码,但使用不同的编译器(MSVC,Xcode中,GCC,铛,无论你在主机上使用)编制。
这意味着实际上,是大多数的测试结果将是有效的 - 当你进入由每个编译器的怪癖,或者STL实现等问题,否则......这不是那么糟糕,因为它是10+年前,但你不能100%肯定地说,与主机库的JUnit测试的结果是相同的Android的库。 你可以说,这是相当接近的,虽然。
话又说回来,除非你正在运行使用的Android NDK为每个支持的架构原生的单元测试,你也不能说肯定无论是什么...因此,采取什么你会的。
矫枉过正的做法(但真的很酷,如果自动)会,但是你做他们(谷歌测试,捕捉等)来编写本地的单元测试,然后编译时,每次使用的架构在Android NDK运行本机库和单元测试。 这提供了在你的潜在目标架构的C / C ++的覆盖范围。
从这里,你可以使用上述主机库使用JUnit迅速单元测试你的JNI层与本地库进行交互。 在你的CI系统,你应该仍然可能运行这些相同的单元测试 - 但作为Android的仪器测试(或别的东西运行一个仿真的Android环境)。
正如一切,只要你有一个接口,您可以创建嘲弄 - 但在某些时候,你需要的系统/功能/集成测试了。
更新:
在博客文章的上面更全面的解释( http://www.sureshjoshi.com/mobile/android-junit-native-libraries/ )
我已经切换到默认的测试风格(使用而不是RoboElectric ActivityUnitTestCase)和它现在运行良好。 这是一个耻辱,我不得不牺牲试运行的速度,但运行在模拟器上测试实际工作。 您还可以创建一个影子类的JNI类,这里详细:
上加载JNI库应用对象Robolectric坦克。 我可以得到一个解决方法吗?
也许编译我的机器库会工作,但我无法花更多的时间就可以了。
为以防万一,为别人寻找解决方案,这一点, 有一种方法来正确设置JUnit测试的lib查找路径(虽然我还没有设法成功地运行测试,不同的问题):
你需要把路径在LD_LIBRARY_PATH
(或PATH
在Windows)环境变量。 我有相同的经历:我设置java.library.path
第一,但似乎它不以任何方式影响本机装载的行为。
欢迎你看看我这里的答案 ,如果你需要关于如何做到这一点与摇篮/ Android Studio中的细节