【发布时间】:2016-02-18 21:19:57
【问题描述】:
我正在尝试将本机库添加到我现有的应用程序中。我的目标是使用插件在 Android Studio 中自己的模块中编译 C++ 库,而无需手动步骤(如果可能)。我尝试了许多建议,并得到提示,构建系统在将模块之间的库复制到构建中时存在问题。我没能解决这个问题。
以下是我设置的相关部分(和一些):
Android 工作室: Gradle 版本:2.10
项目文件结构:
myproject
+libmodule
| +src/main
| | +java
| | | `-MyWrapper.java
| | `jni
| | `-MyJNI.cpp
| `-build.gradle
+appmodule
| +src/main
| | `java
| | `-MyClass.java
| `-build.gradle
+gradle/wrapper
| `-gradle-wrapper.properties
+-build.gradle
`-settings.gradle
我的项目/settings.gradle:
include ':appmodule', ':libmodule'
我的项目/build.gradle:
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha9'
}
}
allprojects {
repositories {
mavenCentral()
}
}
gradle-wrapper.properties:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
myproject/libmodule/build.gradle:
apply plugin: 'com.android.model.library'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 23
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file("proguard-rules.txt"))
proguardFiles.add(file("proguard-android.txt"))
}
}
android.ndk {
moduleName = "MyLibrary"
stl = "gnustl_shared"
cppFlags.add("-nostdinc++")
cppFlags.add("-I\$(NDK)/sources/cxx-stl/stlport/stlport")
cppFlags.add("-fexceptions")
cppFlags.add("-frtti")
cppFlags.add("-fpermissive")
ldFlags.add("-nodefaultlibs")
ldFlags.add("-Lsrc/main/jniLibs/armeabi-v7a")
ldLibs.add("c")
ldLibs.add("m")
ldLibs.add("dl")
ldLibs.add("log")
ldLibs.add("gcc")
}
android.productFlavors {
create("arm") {
ndk.abiFilters.add("armeabi")
}
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
create("arm8") {
ndk.abiFilters.add("arm64-v8a")
}
create("x86") {
ndk.abiFilters.add("x86")
}
create("x86-64") {
ndk.abiFilters.add("x86_64")
}
create("mips") {
ndk.abiFilters.add("mips")
}
create("mips-64") {
ndk.abiFilters.add("mips64")
}
create("all")
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.1.1'
}
myproject/appmodule/build.gradle:
apply plugin: 'com.android.model.application'
buildscript {
repositories {
mavenCentral()
}
dependencies {
}
}
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile project(':libmodule')
// Support Libraries
// Maven Provided Libraries
compile fileTree(dir: 'libs', include: ['*.jar'])
}
model {
android {
compileSdkVersion = 23
buildToolsVersion = '23.0.2'
defaultConfig.with {
applicationId = "com.me.myandroidapp"
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 23
}
}
android.dexOptions {
jumboMode = true
}
android.packagingOptions {
//Some specific removals for an included lib from maven
}
android.lintOptions {
checkReleaseBuilds = false
abortOnError = false
}
android.buildTypes {
debug {
debuggable = true
minifyEnabled = false
buildConfigFields.with {
create() {
type = "boolean"
name = "SCREENSHOTS"
value = "true"
}
}
buildConfigFields.with {
create() {
type = "boolean"
name = "DEBUGGABLE"
value = "true"
}
}
proguardFiles.add(file("proguard-rules.txt"))
proguardFiles.add(file("proguard-android.txt"))
}
release {
debuggable = false
minifyEnabled = true
buildConfigFields.with {
create() {
type = "boolean"
name = "SCREENSHOTS"
value = "false"
}
}
buildConfigFields.with {
create() {
type = "boolean"
name = "DEBUGGABLE"
value = "false"
}
}
proguardFiles.add(file("proguard-rules.txt"))
proguardFiles.add(file("proguard-android.txt"))
}
}
android.productFlavors {
create("prod") {
applicationId = "com.me.myandroidapp"
}
create("dev") {
applicationId = "com.me.myandroidapp"
}
create("beta") {
applicationId = "com.me.myandroidapp"
}
create("staging") {
applicationId = "com.me.myandroidapp"
}
}
}
if (project.hasProperty("MyProject.properties") && new File(project.property("MyProject.properties")).exists()) {
// Get properties in the property file
Properties props = new Properties()
props.load(new FileInputStream(file(project.property("MyProject.properties"))))
model {
android {
signingConfigs {
//several configs here
}
}
android.buildTypes {
release {
signingConfig = signingConfigs.release
}
}
}
}
MyWrapper.java:
package com.me.androidwrapper;
public class MyWrapper {
private native String doItNatively(String stringinput);
public String doIt(String stringinput) {
return doItNatively(stringinput);
}
static {
System.loadLibrary("MyLibrary");
}
}
myjni.cpp:
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_me_androidwrapper_MyWrapper_doItNatively(JNIEnv *env, jobject instance, jstring stringinput_) {
// C++ happens here
}
}
MyClass.java:
// Weird behavior for IDE adding dependency module happens here:
import com.me.androidwrapper.MyWrapper;
public class MyClass {
public String makeItHappen(String inputstring) {
MyWrapper mywrapper = new myWrapper();
return mywrapper.doIt(inputstring);
}
}
JNI 中没有 android.mk 文件。
从一个清理过的项目中,gradle 成功执行。当我在 appmodule 上运行 Make Module 时出现错误:
Error:(5, 37) error: package com.me.androidwrapper does not exist
...来自 MyClass.java 的 import 语句被突出显示。
如上所述,在 MyClass.java 的代码中,Android Studio 提供了一个快速修复,包括对模块“libmodule”的依赖,如果我选择它,IDE 会删除错误。如果我通过命令单击包、类或方法,IDE 会正确解析项目链接。
我在 StackOverflow 和插件组中关注了许多解决方案。有提到新的实验性插件和构建系统不会在其中几个模块之间复制本机库,我尝试了将 aar/jar 模块设置为中介的方法。我还尝试了手动将 aar 文件复制到模块库中并将其作为文件或 aar 引用的方法。大多数这些方法都不起作用,我得到的最好结果是成功构建,但是应用程序崩溃找不到 libMyLibrary.so
我已经通过使用 gradle 2.8 和 android 实验插件 0.4.0 将 JNI 直接包含到 appmodule 模块中成功地测试了该项目。这不是一个很好的解决方案,因为模块很复杂并且 C++ 代码是单独维护的。 0.4.0 插件作为多模块失败,库的 .so 不打包。
我对新的实验性插件的了解存在差距,我知道它有错误,它不完整,一些功能仍在讨论中。任何帮助追查我的错误,或为插件缺乏功能提供全面的解决方法将不胜感激。
【问题讨论】:
标签: android android-studio android-ndk android-build