AndroidStudio2.2.3 JNI與NDK開發之二:生成可調用jar包

本文是繼前文 

AndroidStudio2.2.3 JNI與NDK開發之一:生成可調用.so庫的跟進文章

       主要用於解決生成的.so庫中,jni的方法名有包名的限制,導致其他項目工程引用時,包名不一致,出現jni層接口調用無效的問題。即,A項目的a.so,在B項目使用時,報uncaughtException的錯誤,導致程序崩潰。

uncaughtException Ljava/lang/ThreadGroup;
12-30 23:07:09.936 4604-4604/com.example.jnitest E/AndroidRuntime: FATAL EXCEPTION: main
                                                                   Process: com.example.jnitest, PID: 4604
                                                                   java.lang.UnsatisfiedLinkError: getJniString
                                                                       at com.example.jnitest.JniUtil.getJniString(Native Method)
                                                                       at com.example.jnitest.MainActivity.onCreate(MainActivity.java:15)
                                                                       at android.app.Activity.performCreate(Activity.java:5451)
                                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)

引起這個崩潰的原因是,jni的getJniString接口對應的包名爲com.example.jnidemo,而本項目中包名爲com.example.jnitest.

       一般來說,編譯的.so庫就是爲了使用方便,通用性好,不管本項目工程或者是其他的項目工程,於是要編譯出一個適用性強的.so提供使用,需要將jni層的.so對應Java層的類接口打包成一個.jar,給其他項目工程使用,其他工程使用時,只需要添加.jar包和.so文件即可。本文主要介紹新建一個Library,生成.so和jar提供給其他工程使用。


1、新建項目爲JniTest

(1)、爲JniTest新建Module,選擇Android Library命名爲jnilibrary


然後再java的com.example.jnilibrary下新建JniUtil.java,如圖:


JniUtil的內容依然爲測試內容

public class JniUtil {

    static {
        System.loadLibrary("JniUtil");
    }

    public static native String getJniString();

    public static native int getJniAdd(int a, int b);

}
接下來就是進行jni操作,編譯.so庫的步驟,也是在src\main文件下新建jni文件夾,如圖:


配置build.gradle和Project Structure中ndk-build路徑,具體步驟參考前一篇文章

(2)、配置並生成jar文件

主要是對JniUtil.java生成.jar文件。

在jnilibrary這個module下的build.gradle中配置如下信息

def SDK_NAME = "JniUtil";
def SDK_VERSION = "_V1.0";
def sdkDestinationPath = "build";
def zipFile = file('build/intermediates/bundles/release/classes.jar')

task deleteBuild(type: Delete) {
    delete sdkDestinationPath + SDK_NAME + SDK_VERSION + ".jar"
}

task makeJar(type: Jar) {
    from zipTree(zipFile)
    from fileTree(dir: 'src/main',includes: ['assets/**'])
    baseName = SDK_NAME + SDK_VERSION
    destinationDir = file(sdkDestinationPath)
}

makeJar.dependsOn(deleteBuild, build)
聲明jar的文件名,版本,路徑,以及編譯依賴的編譯文件等。完整的build.gradle文件如下:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jni.srcDirs = ['src/main/jni', 'src/main/jni/']
        }
    }

    externalNativeBuild {
        ndkBuild {
            path file("src\\main\\jni\\Android.mk")
        }
    }


}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.0'
    testCompile 'junit:junit:4.12'
}

def SDK_NAME = "JniUtil";
def SDK_VERSION = "_V1.0";
def sdkDestinationPath = "build";
def zipFile = file('build/intermediates/bundles/release/classes.jar')

task deleteBuild(type: Delete) {
    delete sdkDestinationPath + SDK_NAME + SDK_VERSION + ".jar"
}

task makeJar(type: Jar) {
    from zipTree(zipFile)
    from fileTree(dir: 'src/main',includes: ['assets/**'])
    baseName = SDK_NAME + SDK_VERSION
    destinationDir = file(sdkDestinationPath)
}

makeJar.dependsOn(deleteBuild, build)

接下來下Android Srudio的Gradle窗口,找到makejar(沒有時,Gradle窗口左上角的刷新按鈕進行刷新),雙擊。如圖:




等待編譯一會在如下目錄下生成想要的.jar文件:


3、新建一個Test項目工程驗證,目錄結構如下圖


在真機上運行如下結果



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章