为了让工程的jni更清爽,通常会将更底层的代码ndk-build成第三方.so库,在jni中引用该库。
在实现之前必须保证,第三方.so库是ndk-build编译而成,若在Linux环境下编译成.so库,在Android中是不能被引用的,会出现:
Unable to recognise the format of the input file `./libs/armeabi/lib***.so的错误。因为此.so库是x86或其他编译结构编译的,ndk-build是armeabi架构编译。
尝试方法一:将用ndk-build编译得到的liba.so直接放到armeabi目录中,你会发现,在build的时候,armeabi文件会被自动清空,所以此方法行不通。
尝试方法二:此方法也是测试通过的,现介绍如下:
(1)、首先写一个测试库:libmaxmin.so,此库的功能是比较两个数的大小,max.c-返回较大数,min.c-返回较小数。
max.h:
int max(int a,int b);
max.c:
#include "max.h"
#include <stdlib.h>
#include <stdio.h>
int max(int a,int b){
if(a >= b){
return a;
}else{
return b;
}
}
min.h:
int min(int a ,int b);
min.c:
#include "min.h"
#include <stdio.h>
int min(int a ,int b){
if (a<=b){
return a;
}else{
return b;
}
}
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := maxmin
LOCAL_SRC_FILES := max.c \
min.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/testinclude
include $(BUILD_SHARED_LIBRARY)
然后用ndk-build编译得到libmaxmin.so
(2)、a:将libmaxmin.so文件放到工程Test/jni/prebuilt目录中
b:在prebuilt文件夹中添加Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := maxmin
LOCAL_SRC_FILES := libmaxmin.so
include $(PREBUILT_SHARED_LIBRARY)
c:在jni文件加下添加Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := maxmin
LOCAL_C_INCLUDES := $(LOCAL_PATH)/testinclude
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c \
include $(BUILD_SHARED_LIBRARY)
include $(LOCAL_PATH)/prebuilt/Android.mk
d:TestJNA.h文件:
#include <jni.h>
/* Header for class com_aoshuo_testall_TestJNA */
#ifndef _Included_com_aoshuo_testall_TestJNA
#define _Included_com_aoshuo_testall_TestJNA
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_aoshuo_testall_TestJNA
* Method: tests
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_aoshuo_testall_TestJNA_tests
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
e:hello-jni.c文件:
#include "TestJNA.h"
#include <string.h>
#include <jni.h>
#include "max.h"
#include "min.h"
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*
* apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
*/
JNIEXPORT jint JNICALL Java_com_aoshuo_testall_TestJNA_tests
(JNIEnv *env, jclass thiz, jint a, jint b){
return max(a,b);
f:工程jni目录结构如下图所示:
想要的hello-jni.so库成功得到。
(3)、编辑Android代码测试:
TestJNA.class文件内容如下:
package com.aoshuo.testall;
public class TestJNA{
public static native int tests(int a ,int b);
static{
System.loadLibrary("hello-jni");
}
}
TestJNAActivity文件内容如下:
package com.aoshuo.testall;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class JNAActivity extends Activity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_jna);
init();
}
private void init(){
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("开始测试");
int a = TestJNA.tests(1, 2);
Toast.makeText(getApplicationContext(), "较大的是:" + a, Toast.LENGTH_LONG).show();
}
});
}
}
activity_jna.xml文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello JNI"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="按下"/>
</LinearLayout>
运行后的结果为:
over