android java層通過jni加載使用第三方的so庫


1、例如我們自己編譯一個so庫,我們的其他模塊要加載如何操作了

首先在c盤新建立一個文件夾sb,在sb下面新建立一個文件夾jni,如果你要使用ndk編譯so庫,必須需要有jni目錄

2、在jni目錄下面建立下面幾個文件

我們來看看c文件

//
// Created by wei.yuan on 2017/11/2.
//
#include<jni.h>
#include<logback_ecmapplication_cetcs_com_myapplicationkldsk_JNI.h>
#include <jni.h>
#include <string.h>
#include <pthread.h>
JNIEXPORT jstring JNICALL Java_logback_ecmapplication_cetcs_com_myapplicationkldsk_JNI_getStringFromC
  (JNIEnv *env, jobject obj){
    int *a = (int *) (NULL);
    *a = 1;
    return (*env)->NewStringUTF(env,"I'm comes from 5454552444444to Native Function!");
  }

然后是頭文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity */

#ifndef _Included_logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity
#define _Included_logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_ABOVE_CLIENT
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_ABOVE_CLIENT 8L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_ADJUST_WITH_ACTIVITY
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_ALLOW_OOM_MANAGEMENT
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_AUTO_CREATE
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_AUTO_CREATE 1L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_DEBUG_UNBIND
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_DEBUG_UNBIND 2L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_IMPORTANT
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_IMPORTANT 64L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_NOT_FOREGROUND
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_NOT_FOREGROUND 4L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_WAIVE_PRIORITY
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_BIND_WAIVE_PRIORITY 32L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_CONTEXT_IGNORE_SECURITY
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_CONTEXT_IGNORE_SECURITY 2L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_CONTEXT_INCLUDE_CODE
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_CONTEXT_INCLUDE_CODE 1L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_CONTEXT_RESTRICTED
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_CONTEXT_RESTRICTED 4L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_APPEND
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_APPEND 32768L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_MULTI_PROCESS
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_MULTI_PROCESS 4L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_PRIVATE
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_PRIVATE 0L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_WORLD_READABLE
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_WORLD_READABLE 1L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_WORLD_WRITEABLE
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_MODE_WORLD_WRITEABLE 2L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_DIALER
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_DIALER 1L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_DISABLE
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_DISABLE 0L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_SHORTCUT
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_DEFAULT_KEYS_SHORTCUT 2L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_RESULT_CANCELED
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_RESULT_CANCELED 0L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_RESULT_FIRST_USER
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_RESULT_FIRST_USER 1L
#undef logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_RESULT_OK
#define logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity_RESULT_OK -1L
/*
 * Class:     logback_ecmapplication_cetcs_com_myapplicationkldsk_MainActivity
 * Method:    getStringFromC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_logback_ecmapplication_cetcs_com_myapplicationkldsk_JNI_getStringFromC
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

現在我們要生成so庫,需要配置android.mk文件和application.mk文化

android.mk文件內容如下所示:

ROOT_PATH := $(call my-dir)

LOCAL_PATH := $(ROOT_PATH)
include $(CLEAR_VARS)

LOCAL_MODULE    := sb_jni
LOCAL_SRC_FILES := logback_ecmapplication_cetcs_com_myapplicationkldsk_JNI.c
LOCAL_CFLAGS :=  -Wl,-g  
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

application.mk文件如下所示:

APP_STL := stlport_static
APP_ABI := all
APP_CXXFLAGS := -std=c++11 -D__STDC_LIMIT_MACROS
APP_PLATFORM := android-12

有了上面的配置之后,我們就可以在cgwin環境中生成對應的so庫文件了,cgwin進入到對應的jni目錄,使用ndk-build命令

編譯成功之后會在jni的目錄下產生下面的兩個文件夾

libs文件下面的so庫就是可以提高給第三方使用的so庫,obj目錄下生成的so庫就是具有調試信息的so庫,當發現奔潰的時候,可以使用工具arm-linux-androideabi-addr2line.exe解決該obj目錄下的so庫來定位文件

現在我們在android studio下面新建立一個工程

我們將上面的libs目錄拷貝到工程和src同級別的目錄下

然后在工程的gradle文件中配置下面的代碼

sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
完成的gradle代碼如下
apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "cn.onlinecache.breakpad"
        minSdkVersion 9
        targetSdkVersion 24
        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 {
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile project(':breakpad')


    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.jakewharton:butterknife:8.4.0'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
}

通過上面的配置,我們編譯工程就會自動生成jNIlibs目錄

 

 然后我們要在代碼中使用so庫中的函數,如何使用了

JNIEXPORT jstring JNICALL Java_logback_ecmapplication_cetcs_com_myapplicationkldsk_JNI_getStringFromC
  (JNIEnv *env, jobject obj){ int *a = (int *) (NULL); *a = 1; return (*env)->NewStringUTF(env,"I'm comes from 5454552444444to Native Function!"); }

從c語言中我們可以看出,這個函數是 通過JNI編程規范編寫的,必須要滿足JNI的編程規范,通過
JNIEXPORT jstring JNICALL Java_logback_ecmapplication_cetcs_com_myapplicationkldsk_JNI_getStringFromC我們可以知道對應該函數的java層對應的
包名是
logback.ecmapplication.cetcs.com.myapplicationkldsk
對應的類名是JNI,對應的函數名是
getStringFromC
所以我們在工程中應該要建立下面的這樣一個文件
package logback.ecmapplication.cetcs.com.myapplicationkldsk;

/**
 * Created by wei.yuan on 2017/11/13.
 */

public class JNI {
    public  native  String  getStringFromC();
    static {
        System.loadLibrary("sb_jni");
    }
}

在這個文件中加載so 庫進行調用

 

調用者:

 new JNI().getStringFromC()

工程結構如下:

 工程項目代碼如下所示:

http://pan.baidu.com/s/1nvHuufB


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM