如何告诉Gradle不要在我的.jar依赖项中排除.so文件?

时间:2018-11-28 14:40:40

标签: android android-studio gradle android-gradle apk

我有一个.jar依赖项,其中包含.so库。

library.jar
       |
       -----com/company
              |
              -----.class files
       -----libs
              |
              -----libX.so

jar会在内部使用此.so库,而我正在构建一个使用jar的Android应用。

一切都很好,直到我构建apk之后:通过使用7zip探索它,我发现.so文件已消失,导致在使用该应用程序时出现各种错误。

那么,有什么方法可以告诉Gradle在构建时不要排除.so文件吗?我不想手动将它们复制到我的Android项目中的文件夹中,因为我没有直接使用它们,但是.jar库是加载它们的库。

编辑1:添加build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.company.myapp"
        minSdkVersion 24
        targetSdkVersion 28
        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(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:28.0.0'
    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'
    implementation files('libs/lib1.jar')
    implementation files('libs/lib2.jar')
}

编辑2:这是遵循@shizhen先前建议的解决方案

1-我的.jar.so目录中包含了libs文件。我不得不将其重命名为lib

2-我解开了.jar的包装以收集.so个文件。

3-我创建了src/jniLibs文件夹,并将.so文件放入各自的<ANDROID_ABI>文件夹中。

4-我修改了build.gradle文件,使其包含:

android {
...
sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDir 'src/jniLibs'
        }
    }
}

5-瞧!现在,最终的.apk包括本地库。

3 个答案:

答案 0 :(得分:1)

  

一切都很好,直到我构建apk之后:通过使用7zip进行探索,我发现.so文件消失了,从而在使用该应用程序时导致各种错误。

我相信您的jar依赖项不是最初不是用于Android 的,而是通常用于Java的。

Android应用使用 .dex 格式,因此所有 .jar 依赖项都将重新打包为一个或多个dex文件。您的 .so 文件将不会被使用,因为它在jar中。

  

那么,有什么方法可以告诉Gradle在构建时不要排除.so文件吗?我不想手动将它们复制到我的Android项目中的文件夹中,因为我没有直接使用它们,但是.jar库是加载它们的库。

因此,为了使jar适应Android应用,您必须解压缩jar,取出所有 .so 文件并手动 >将它们放入public void UploadImageToServer() { FixBitmap.compress(Bitmap.CompressFormat.JPEG, 40, byteArrayOutputStream); byteArray = byteArrayOutputStream.toByteArray(); ConvertImage = Base64.encodeToString(byteArray, Base64.DEFAULT); class AsyncTaskUploadClass extends AsyncTask<Void,Void,String> { @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = ProgressDialog.show(MainActivity.this,"Image is Uploading","Please Wait",false,false); } @Override protected void onPostExecute(String string1) { super.onPostExecute(string1); progressDialog.dismiss(); Toast.makeText(MainActivity.this,string1,Toast.LENGTH_LONG).show(); } @Override protected String doInBackground(Void... params) { ImageProcessClass imageProcessClass = new ImageProcessClass(); HashMap<String,String> HashMapParams = new HashMap<String,String>(); HashMapParams.put(ImageTag, GetImageNameFromEditText); HashMapParams.put(ImageName, ConvertImage); String FinalData = imageProcessClass.ImageHttpRequest("http://192.168.18.175/Android%20Upload%20Image/upload-image-to-server.php", HashMapParams); return FinalData; } } AsyncTaskUploadClass AsyncTaskUploadClassOBJ = new AsyncTaskUploadClass(); AsyncTaskUploadClassOBJ.execute(); } 中,例如

function vowel2index(string) {

  var result = [];

  for(var i = 0; i < string.length; i++) {
    var c = string.charAt(i);
    if(c.match(/[aeiou]/gi)) {
      result.push(i + 1);
    } else {
      result.push(c);
    }
  }
  return result.join('');
}

答案 1 :(得分:0)

仅基于“Shrink your code and resources”上的Android文档进行猜测:似乎ProGuard会自动用于发行版本,以删除显然未使用的代码。您可以尝试禁用它:

// …
    buildTypes {
        release {
            minifyEnabled false
            useProguard false
        }
    }
// …

如果有帮助,那么ProGuard将是您的罪魁祸首。除了禁用它,您还可以尝试显式tell it to keep the files禁止删除的内容。

答案 2 :(得分:0)

只需在build.gradle(Module:app)中设置您的sourceSets

android {
   ...
   ...
sourceSets {
    main {
        jniLibs.srcDirs = [
                './src/main/jniLibs'
        ]
    }
 }
}

如果您的项目需要使用ndk:

defaultConfig {
    ...
    ndk {
        abiFilters "armeabi-v7a", "x86"
    }
}