我正在使用sqlite4java开始一个简单的java测试项目,并使用java进行构建。
我可以轻松下载核心sqlite4java库,但我不确定让gradle下载本机库并将它们放在正确的位置的最佳方法。
这是我的构建。gradle文件:
apply plugin: 'java'
/* We use Java 1.7 */
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '1.0'
repositories {
mavenCentral()
}
sourceSets {
main {
java.srcDir 'src'
output.classesDir = 'build/main'
}
test {
java.srcDir 'test'
output.classesDir = 'build/test'
}
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
compile "com.almworks.sqlite4java:sqlite4java:1.0.392"
compile "com.almworks.sqlite4java:libsqlite4java-osx:1.0.392"
}
但是当我运行一个简单的测试时,我得到:
TestTest > testSqlite4Basic FAILED
com.almworks.sqlite4java.SQLiteException at TestTest.java:15
Caused by: java.lang.UnsatisfiedLinkError at TestTest.java:15
(我从IntelliJ内部构建,但我使用gradle构建选项-所以我不认为它是ItelliJ在运行测试时填充类路径…)
我很确定我第一次尝试构建时,我得到了一些关于无法解压缩libsqlite4java-osx ZIP文件的消息,(这并不奇怪,因为maven central说它是一个dylib文件)。
我需要做什么来让gradle做正确的事情?
ASIDE:我能够通过手动将下载的.dylib
从maven缓存复制到我的java.library.path
中列出的某个地方来运行代码(认为我在mac上使用$HOME/Library/Java/Extensions
)。但是,这似乎与在.gradle
文件中打包所有设置和依赖关系的整个要点相反,并且不会让我稍后轻松分发任何内容。
我想,你需要使用额外的gradle插件来处理本地库或做你自己的特定任务,上传和放置本地库在正确的地方,以便他们可以被找到和链接。
目前我只知道一个这样的插件,希望它能解决你的问题https://github.com/cjstehno/gradle-natives
编辑:在您的情况下,插件的问题是,您的依赖项"com.almworks.sqlite4java:libsqlite4java-osx:1.0.392"本身是本机库,而不是像我想象的那样包含本机库的jar。因此,在这种情况下,您可以简单地在构建脚本的dependencies par中添加此依赖项,就像已经完成的那样,然后创建一个自定义复制任务,将其放在您需要的任何位置。尝试在Win7上使用gradle 2.6来做,看起来像:
task copyNtiveDeps(type: Copy) {
from (configurations.compile+configurations.testCompile) {
include "libsqlite4java-osx-1.0.392.dylib"
}
into "c:\tmp"
}
在您的情况下,您只需要将"into"属性设置为java.library.path中的某个路径。第二,你可以使用gradle任务属性dependsOn和mustRunAfter让这个任务自动运行。
以下是根据Stanislav的评论得出的完整答案。
apply plugin: 'java'
/* We use Java 1.8 */
sourceCompatibility = 1.8
targetCompatibility = 1.8
version = '1.0'
repositories { mavenCentral() }
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
compile "com.almworks.sqlite4java:sqlite4java:1.0.392"
compile "com.almworks.sqlite4java:libsqlite4java-osx:1.0.392"
}
sourceSets {
main {
java.srcDir 'src'
output.classesDir = 'build/main'
}
test {
java.srcDir 'test'
output.classesDir = 'build/test'
}
}
/* Copy the native files */
task copyNativeDeps(type: Copy) {
from (configurations.compile+configurations.testCompile) {
include "*.dylib"
}
into 'build/libs'
}
/* Make sure we setup the tests to actually copy
* the native files and set the paths correctly. */
test {
dependsOn copyNativeDeps
systemProperty "java.library.path", 'build/libs'
}
和运行它的示例测试源:
import com.almworks.sqlite4java.SQLiteConnection;
import com.almworks.sqlite4java.SQLiteStatement;
import org.junit.Test;
import java.io.File;
public class SqliteTest {
@Test public void aTest() throws Exception {
SQLiteConnection db = new SQLiteConnection(new File("/tmp/database"));
db.open(true);
SQLiteStatement st = db.prepare("SELECT name FROM dummy");
try {
while(st.step()) {
System.err.printf("name = %sn", st.columnString(1));
}
} finally {
st.dispose();
}
}
}
要编译您自己的sqlite3库,您可以查看github android-sqlite3
对于当前Android Studio(3.3.1),您可以简单地在app/build.gradle
中添加.so
文件,如下所示:
android {
...
sourceSets {
main {
jniLibs.srcDirs += ['<your-path>/your-libs']
}
}
...
}
jniLibs.srcDirs
是指向jni库的gradle路径,操作符 +=
表示除了app/src/main/jniLibs
内部的默认库之外的 jni库,如下所示:
app/
├──libs/
| └── *.jar <-- java libs
├──src/
└── main/
├── AndroidManifest.xml
├── java/
└── jniLibs/ <-- default directory for jni libs, i.e. <ANDROID_ABI>/**.so
请注意,jni库必须根据android ABI组织,即
your-libs/
├── arm64-v8a/ <-- ARM 64bit
│ └── lib-your-abc.so
├── armeabi-v7a/ <-- ARM 32bit
│ └── lib-your-abc.so
├── x86_64/ <-- Intel 64bit
│ └── lib-your-abc.so
└── x86/ <-- Intel 32bit
└── lib-your-abc.so
我用这个方法在anroid studio 3.1.4中安装了sqlite4java。
首先从这个链接下载库:https://bitbucket.org/almworks/sqlite4java
下载将包含一个zip文件,其中包含一个名为android的文件夹和其他。jar, .so和。dll文件。
将android中的'armeabi', 'armeabi-v7a'和'x86'三个文件夹复制到名为'jniLibs'的文件夹中。
将上面的文件夹,即'jniLibs'复制到你的project/app/src/main/文件夹中。
然后实现java4sqlite的gradle依赖:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "your.project.name"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:26.1.0'
implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1'
implementation "com.almworks.sqlite4java:sqlite4java:1.0.392"
implementation "com.almworks.sqlite4java:libsqlite4java-osx:1.0.392"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}