AndroidStudio2.2.3 JNI与NDK开发之一:生成可调用.so库

AndroidStudio2.2.3 JNI与NDK开发之一:生成可调用.so库

网友前辈总结的一种方法,直接用Android Studio中ndk与CMake实现,见博主文章AndroidStudio2.2开发NDK的正确姿势

本文选用的是用ndk和.mk文件实现编译生成.so。首先需要确保电脑中配置了ndk环境变量,这里不赘述,需要的网友可以自己百度,比较简单。

本文选用ndk版本为r9d(AS配置最新为r13b),使用方式基本没有太大的差别。开始进入正文:


1、新建app项目为JniDemo

(1)新建类JniUtil,两个jni层的测试接口getJniString()与getJniAdd(int a,int b);

public class JniUtil {

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

    public static native String getJniString();

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

}


(2)新建jni文件夹,app->new->Folder->JNI Folder, 如图


点击之后弹出框选择


点击finish之后,项目目录下生成jni文件夹,如图:


jni文件夹新建Android.mk文件,用于ndk-build命令时执行编译出.so库,Android.mk内容如下:

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := JniUtil
LOCAL_SRC_FILES := jniUtil.c

include $(BUILD_SHARED_LIBRARY)

LOCAL_MODULE为编译出的.so库的名字,本demo命名为libJniUtil,其中lib编译时候会自动加上,Java中loadLibrary时也会自定加上。LOCAL_SRC_FILES为需要编译的.c文件。

接下来,在AS界面的Terminal窗口下执行 cd app\src\main\java,定位到java文件夹,回车,再执行javah -jni com.example.jnidemo.JniUtil,(这里要注意的是包名com.example.jnidemo一定要完整正确)生成java文件中native方法相应的jni层c代码接口。如图:


新生成的.h文件中,拷贝出两个方法,复制到jni文件夹中新建的jniUtil.c中,如下:

#include <jni.h>

/*
 * Class:     com_example_jnidemo_JniUtil
 * Method:    getJniString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnidemo_JniUtil_getJniString(JNIEnv *env, jclass cls){
    char *str = "this is from c file in jni.";
    return (*env)->NewStringUTF(env,str);
}

/*
 * Class:     com_example_jnidemo_JniUtil
 * Method:    getJniAdd
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_jnidemo_JniUtil_getJniAdd(JNIEnv *env, jclass cls, jint a, jint b){
    return a+b;
}
具体实现JniUtil.java中getJniString和getJniAdd方法。


2编译.so库

编译.so库有两种方法:

(1)ndk-build命令。(说在前面在windows的cmd命令中执行也是可以的,具体和下面步骤一致)

AS的Terminal执行cd app\src\main\jni\    回车,再执行ndk-build命令(ndk-build主要根据Android.mk文件执行)。

如图:

编译出libJniUtil.so。文件生成到app\src\main\libs中


按项目中引用.so库的方法,将生成的.so拷贝到jniLibs文件中,删除无用的文件夹和文件,运行项目测试。


(2)配置build.gradle。

如果嫌命令输入太复杂,也可以配置项目的build.gradle文件,android中增加

sourceSets {
    main {
        jni.srcDirs = ['src/main/jni', 'src/main/jni/']
    }
}

externalNativeBuild {
    ndkBuild {
        path file("src\\main\\jni\\Android.mk")
    }
}
前者告知执行的jni编译.c的文件夹,后者告知ndk-buid编译所需的Android.mk

完整的build.gradle为

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.example.jnidemo"
        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'
}

然后,在配置项目的Project Structure


编译项目,在app\build\intermediates\ndkBuild文件下生成了.so库。



运行demo。


3总结

对比两种方法,第一种在eclipse中使用多,在Android Studio中推荐使用第二种。

增加:

新建Application.mk文件,放在jni文件夹下,设置编译出哪几个版本的.so库。如下:

APP_ABI      := armeabi armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM := android-14























  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值