准备的资源是一个activity和一个JniService,activity中一个Button触发native代码执行。
第一步:
先新建JniService.java源代码,里面全是本地代码的声明,不用在这个文件中实现。
package com.vincent.org.networkapp.jnidemo;
public class JniService {
private native static int getIntSum(int num1, int num2);
private native static float getFloatSum(float num1, float num2);
private native static double getDoubleSum(double num1, double num2);
private native static void displayString(String text);
static {
//这里这个字符串的名字必须和Android.mk中LOCAL_MODULE变量的值一致。
//可以到最后看下Android.mk文件中关于LOCAL_MODULE变量设置是否跟这里一样。
System.loadLibrary("vincentjni");
}
public static String getintSum(int num1, int num2) {
int sum = getIntSum(num1, num2);
return String.valueOf(sum);
}
}
第二步:
进入项目src目录下面打开一个终端用javac编译上面那个文件,注意上面那个java文件是有package语句的,所以编译要在src目录下面指定编译路径,同时给定的路径形式是反斜杠形式,注意下面的第三步的区别。
通过上面执行后,在存放java文件的目录下生成了一个JniService.class文件。
第三步:
通过还是在src目录下面用javah工具生成.h头文件。
这里有个小插曲,因为路径间隔符号的问题造成了一定问题,如下:
Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: com/vincent/org/networkapp/jnidemo/JniService
事后我知道因为在javah工具事后需要使用”.”作为间隔符号。
然后在修正后在src目录下面正确生成了.h文件,最后将生成的这个.h文件存放到工程根目录下面的jni目录下面(jni目录如果没有那就新建一个)。
第四步:
将上一步生成的.h文件修改成后缀名为.c并最声明的方法实现。
实现如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_vincent_org_networkapp_jnidemo_JniService */
#ifndef _Included_com_vincent_org_networkapp_jnidemo_JniService
#define _Included_com_vincent_org_networkapp_jnidemo_JniService
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_vincent_org_networkapp_jnidemo_JniService
* Method: getIntSum
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_vincent_org_networkapp_jnidemo_JniService_getIntSum
(JNIEnv *env, jobject jo, jint ji1, jint ji2){
return ji1+ji2;
}
/*
* Class: com_vincent_org_networkapp_jnidemo_JniService
* Method: getFloatSum
* Signature: (FF)F
*/
JNIEXPORT jfloat JNICALL Java_com_vincent_org_networkapp_jnidemo_JniService_getFloatSum
(JNIEnv *env, jobject jo, jfloat jf1, jfloat jf2){
return jf1+jf2;
}
/*
* Class: com_vincent_org_networkapp_jnidemo_JniService
* Method: getDoubleSum
* Signature: (DD)D
*/
JNIEXPORT jdouble JNICALL Java_com_vincent_org_networkapp_jnidemo_JniService_getDoubleSum
(JNIEnv *env, jobject jo, jdouble jb1, jdouble jb2){
return jb1+jb2;
}
/*
* Class: com_vincent_org_networkapp_jnidemo_JniService
* Method: displayString
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_vincent_org_networkapp_jnidemo_JniService_displayString
(JNIEnv *env, jobject jo, jstring js){
}
#ifdef __cplusplus
}
#endif
#endif
第五步:
在jni目录下面生成Android.mk文件,内容如下。
#2016/09/18 vincent用#标识的是注释内容
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := vincentjni #指示最终生成的动态链接库的名字,没有加前缀lib,这个名字不能有空格
LOCAL_SRC_FILES := com_vincent_org_networkapp_jnidemo_JniService.c
#制定这个库的源文件列表,多文件之间用空格做分隔符
include $(BUILD_SHARED_LIBRARY)#表示构建共享库
第六步:
在工程根目录下面用ndk-build 构建命令自动执行本地代码编译。
输出如下信息说明可以成功:
然后在activity上面通过button触发调用本地代码:
public void getJniData(View view) {
//更新到textview上面进行显示结果
tView.setText(JniService.getintSum(56, 44));
}