如何使用productflavors和jni设置Android库模块

时间:2015-10-28 16:44:23

标签: android gradle java-native-interface

我正在尝试将mupdf作为带有预编译.so二进制文件的android库模块包含到我的项目中。

我有一个应用程序模块,其中包含我的库模块。

dependencies {
   compile project(':mupdf')
}

在我的mupdf库模块中,我有我编译的二进制文件。

mupdf
- jniLibs
  - arm64-v8a
    libmupdf.so
  - armeabi
    libmupdf.so
  - armeabi-v7a
    libmupdf.so
  - x86
    libmupdf.so
  - x86_64
    libmupdf.so

我的mupdf库项目的build.gradle:

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    publishNonDefault true
    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }
        }
        x64 {
            ndk {
                abiFilter "x86_64"
            }
        }
        arm {
            ndk {
                abiFilter "armeabi"
            }
        }
        arm_v7a {
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        arm64_v8a {
            ndk {
                abiFilter "arm64-v8a"
            }
        }
        fat
    }
}
dependencies{
    compile project(':core')
}

问题很快就是我添加了我的应用程序无法编译的产品风格,因为它找不到mupdf模块中的任何java文件。 如果我从gradle文件中删除产品flavor部分,它将编译。但它在运行时崩溃,因为它无法解析/加载libmupdf库。

2 个答案:

答案 0 :(得分:0)

您可以在没有产品口味的情况下执行此操作。只需删除它们并在启动时调用System.loadLibrary("mupdf") /在使用库之前的某个时刻。此调用将确定将哪个本机lib用于当前设备体系结构。

答案 1 :(得分:0)

确实,我必须为.aar库构建一个胖模块,并在我的app.gradle中应用productflavors。 我在我的图书馆的build.gradle中错过了这个

public boolean testBoard(int[][] board) {
    List<Callable<Boolean>> tests = new ArrayList<>();
    tests.add(() -> Boolean.valueOf(testCols(board));
    tests.add(() -> Boolean.valueOf(testRegions(board));
    tests.add(() -> Boolean.valueOf(testRows(board));
    tests.add(() -> Boolean.valueOf(testSize(board));

    /*Maybe store this threadPool in a field so you dont create it everytime*/
    ExecutorService threadPool = Executors.newCachedThreadPool();
    List<Future<Boolean>> results = threadPool.invokeAll(tests);

    for(Future<Boolean> future: results){
       if(!Boolean.TRUE.equals(future.get()){
          return false;
       }
    }
    return true;
}

没有这个,没有任何方法可以解决。