我们这里做一个简单的计算器demo,其中运算的逻辑由Native实现,而且我们采用动态注册的方式来实现
样式大概如下:
image.png
里面有两个输入框,下面有4个按钮,代表加减乘除,最下面有个TextView,表示结果。
我们把运算的逻辑抽象出来,用一个JNITools
来表示。代码如下:
public class JNITools {
public class JNITools {
<span >static</span> <span >{</span>
<span >System</span><span >.</span><span >loadLibrary</span><span >(</span><span >"jnidemo3"</span><span >)</span><span >;</span>
<span >}</span>
<span class="token comment">//加法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >add</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span class="token comment">//减法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >sub</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span class="token comment">//乘法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >mul</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span class="token comment">//除法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >div</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span >static</span> <span >{</span>
<span >System</span><span >.</span><span >loadLibrary</span><span >(</span><span >"jnidemo3"</span><span >)</span><span >;</span>
<span >}</span>
<span class="token comment">//加法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >add</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span class="token comment">//减法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >sub</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span class="token comment">//乘法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >mul</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
<span class="token comment">//除法</span>
<span >public</span> <span >static</span> <span >native</span> <span >int</span> <span >div</span><span >(</span><span >int</span> a<span >,</span><span >int</span> b<span >)</span><span >;</span>
}
然后,我们先用来看下对应的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.gebilaolitou.jni.MainActivity">
<span ><span ><span ><</span>LinearLayout</span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span><span >></span></span>
<span ><span ><span ><</span>EditText</span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/inputa<span >"</span></span>
<span ><span >android:</span>hint</span><span ><span >=</span><span >"</span>请输入a<span >"</span></span>
<span ><span >android:</span>inputType</span><span ><span >=</span><span >"</span>number<span >"</span></span>
<span ><span >android:</span>layout_weight</span><span ><span >=</span><span >"</span>1.0<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ><</span>EditText</span>
<span ><span >android:</span>inputType</span><span ><span >=</span><span >"</span>number<span >"</span></span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/inputb<span >"</span></span>
<span ><span >android:</span>hint</span><span ><span >=</span><span >"</span>请输入b<span >"</span></span>
<span ><span >android:</span>layout_weight</span><span ><span >=</span><span >"</span>1.0<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ></</span>LinearLayout</span><span >></span></span>
<span ><span ><span ><</span>TextView</span>
<span ><span >android:</span>text</span><span ><span >=</span><span >"</span>请选择符号<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ><</span>LinearLayout</span>
<span ><span >android:</span>orientation</span><span ><span >=</span><span >"</span>horizontal<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span><span >></span></span>
<span ><span ><span ><</span>Button</span>
<span ><span >android:</span>gravity</span><span ><span >=</span><span >"</span>center<span >"</span></span>
<span ><span >android:</span>layout_weight</span><span ><span >=</span><span >"</span>1.0<span >"</span></span>
<span ><span >android:</span>text</span><span ><span >=</span><span >"</span>@string/add<span >"</span></span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/add<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ><</span>Button</span>
<span ><span >android:</span>gravity</span><span ><span >=</span><span >"</span>center<span >"</span></span>
<span ><span >android:</span>layout_weight</span><span ><span >=</span><span >"</span>1.0<span >"</span></span>
<span ><span >android:</span>text</span><span ><span >=</span><span >"</span>@string/sub<span >"</span></span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/sub<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ><</span>Button</span>
<span ><span >android:</span>gravity</span><span ><span >=</span><span >"</span>center<span >"</span></span>
<span ><span >android:</span>layout_weight</span><span ><span >=</span><span >"</span>1.0<span >"</span></span>
<span ><span >android:</span>text</span><span ><span >=</span><span >"</span>@string/mul<span >"</span></span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/mul<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ><</span>Button</span>
<span ><span >android:</span>gravity</span><span ><span >=</span><span >"</span>center<span >"</span></span>
<span ><span >android:</span>layout_weight</span><span ><span >=</span><span >"</span>1.0<span >"</span></span>
<span ><span >android:</span>text</span><span ><span >=</span><span >"</span>@string/div<span >"</span></span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/div<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>match_parent<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
<span ><span ><span ></</span>LinearLayout</span><span >></span></span>
<span ><span ><span ><</span>TextView</span>
<span ><span >android:</span>id</span><span ><span >=</span><span >"</span>@+id/result<span >"</span></span>
<span ><span >android:</span>text</span><span ><span >=</span><span >"</span>计算结果<span >"</span></span>
<span ><span >android:</span>layout_width</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span>
<span ><span >android:</span>layout_height</span><span ><span >=</span><span >"</span>wrap_content<span >"</span></span> <span >/></span></span>
</LinearLayout>
这时候,我们来看下对应的MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
<span >private</span> <span >Button</span> btnAdd<span >,</span>btnSub<span >,</span>btnMul<span >,</span>btnDiv<span >;</span>
<span >private</span> <span >EditText</span> inputA<span >,</span>inputB<span >;</span>
<span >private</span> <span >TextView</span> tvResult<span >;</span>
<span class="token annotation punctuation">@Override</span>
<span >protected</span> <span >void</span> <span >onCreate</span><span >(</span><span >Bundle</span> savedInstanceState<span >)</span> <span >{</span>
<span >super</span><span >.</span><span >onCreate</span><span >(</span>savedInstanceState<span >)</span><span >;</span>
<span >setContentView</span><span >(</span><span >R</span><span >.</span>layout<span >.</span>activity_main<span >)</span><span >;</span>
<span >setupView</span><span >(</span><span >)</span><span >;</span>
<span >addListener</span><span >(</span><span >)</span><span >;</span>
<span >}</span>
<span >private</span> <span >void</span> <span >addListener</span><span >(</span><span >)</span> <span >{</span>
btnAdd<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
btnDiv<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
btnMul<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
btnSub<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
<span >}</span>
<span >private</span> <span >void</span> <span >setupView</span><span >(</span><span >)</span> <span >{</span>
btnAdd<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>add<span >)</span><span >;</span>
btnDiv<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>div<span >)</span><span >;</span>
btnMul<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>mul<span >)</span><span >;</span>
btnSub<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>sub<span >)</span><span >;</span>
inputA<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>inputa<span >)</span><span >;</span>
inputB<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>inputb<span >)</span><span >;</span>
tvResult<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>result<span >)</span><span >;</span>
<span >}</span>
<span class="token annotation punctuation">@Override</span>
<span >public</span> <span >void</span> <span >onClick</span><span >(</span><span >View</span> v<span >)</span> <span >{</span>
<span >double</span> result<span >=</span><span class="token number">0</span><span >;</span>
<span >String</span> strA<span >=</span>inputA<span >.</span><span >getText</span><span >(</span><span >)</span><span >.</span><span >toString</span><span >(</span><span >)</span><span >;</span>
<span >String</span> strB<span >=</span>inputB<span >.</span><span >getText</span><span >(</span><span >)</span><span >.</span><span >toString</span><span >(</span><span >)</span><span >;</span>
<span >int</span> a<span >=</span><span >Integer</span><span >.</span><span >parseInt</span><span >(</span>strA<span >)</span><span >;</span>
<span >int</span> b<span >=</span><span >Integer</span><span >.</span><span >parseInt</span><span >(</span>strB<span >)</span><span >;</span>
<span >switch</span> <span >(</span>v<span >.</span><span >getId</span><span >(</span><span >)</span><span >)</span><span >{</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>add<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >add</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>div<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >div</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>mul<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >mul</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>sub<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >sub</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >}</span>
tvResult<span >.</span><span >setText</span><span >(</span><span >""</span><span >+</span>result<span >)</span><span >;</span>
<span >}</span>
<span >private</span> <span >Button</span> btnAdd<span >,</span>btnSub<span >,</span>btnMul<span >,</span>btnDiv<span >;</span>
<span >private</span> <span >EditText</span> inputA<span >,</span>inputB<span >;</span>
<span >private</span> <span >TextView</span> tvResult<span >;</span>
<span class="token annotation punctuation">@Override</span>
<span >protected</span> <span >void</span> <span >onCreate</span><span >(</span><span >Bundle</span> savedInstanceState<span >)</span> <span >{</span>
<span >super</span><span >.</span><span >onCreate</span><span >(</span>savedInstanceState<span >)</span><span >;</span>
<span >setContentView</span><span >(</span><span >R</span><span >.</span>layout<span >.</span>activity_main<span >)</span><span >;</span>
<span >setupView</span><span >(</span><span >)</span><span >;</span>
<span >addListener</span><span >(</span><span >)</span><span >;</span>
<span >}</span>
<span >private</span> <span >void</span> <span >addListener</span><span >(</span><span >)</span> <span >{</span>
btnAdd<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
btnDiv<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
btnMul<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
btnSub<span >.</span><span >setOnClickListener</span><span >(</span><span >this</span><span >)</span><span >;</span>
<span >}</span>
<span >private</span> <span >void</span> <span >setupView</span><span >(</span><span >)</span> <span >{</span>
btnAdd<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>add<span >)</span><span >;</span>
btnDiv<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>div<span >)</span><span >;</span>
btnMul<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>mul<span >)</span><span >;</span>
btnSub<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>sub<span >)</span><span >;</span>
inputA<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>inputa<span >)</span><span >;</span>
inputB<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>inputb<span >)</span><span >;</span>
tvResult<span >=</span><span >this</span><span >.</span><span >findViewById</span><span >(</span><span >R</span><span >.</span>id<span >.</span>result<span >)</span><span >;</span>
<span >}</span>
<span class="token annotation punctuation">@Override</span>
<span >public</span> <span >void</span> <span >onClick</span><span >(</span><span >View</span> v<span >)</span> <span >{</span>
<span >double</span> result<span >=</span><span class="token number">0</span><span >;</span>
<span >String</span> strA<span >=</span>inputA<span >.</span><span >getText</span><span >(</span><span >)</span><span >.</span><span >toString</span><span >(</span><span >)</span><span >;</span>
<span >String</span> strB<span >=</span>inputB<span >.</span><span >getText</span><span >(</span><span >)</span><span >.</span><span >toString</span><span >(</span><span >)</span><span >;</span>
<span >int</span> a<span >=</span><span >Integer</span><span >.</span><span >parseInt</span><span >(</span>strA<span >)</span><span >;</span>
<span >int</span> b<span >=</span><span >Integer</span><span >.</span><span >parseInt</span><span >(</span>strB<span >)</span><span >;</span>
<span >switch</span> <span >(</span>v<span >.</span><span >getId</span><span >(</span><span >)</span><span >)</span><span >{</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>add<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >add</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>div<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >div</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>mul<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >mul</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >case</span> <span >R</span><span >.</span>id<span >.</span>sub<span >:</span>
result<span >=</span><span >JNITools</span><span >.</span><span >sub</span><span >(</span>a<span >,</span>b<span >)</span><span >;</span>
<span >break</span><span >;</span>
<span >}</span>
tvResult<span >.</span><span >setText</span><span >(</span><span >""</span><span >+</span>result<span >)</span><span >;</span>
<span >}</span>
}
由于我们不是通过javah
来生成.c文件,所以我们要创建一个jni
的文件夹,然后创建一个jnitools.c
文件。这时候jnitools.c
文件里面应该什么都没有,我们看到JNITools
这个文件有4个native方法,所以我们要也要在jnitools.c
里面声明这4个方法。如下:
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint subNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint mulNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint divNumber(JNIEnv *env,jclass clazz,jint a,jint b);
依次对应Java层的native方法,然后我们写出这些方法的具体实现,如下;
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a+b;
}
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a+b;
}
jint subNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a-b;
}
jint mulNumber(JNIEnv env,jclass clazz,jint a,jint b){
return ab;
}
jint divNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a/b;
}
最后,然后加入引用,如下:
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
依照前面动态注册方法的步骤,我们要重写JNI_OnLoad(JavaVM* vm, void* reserved)
函数。所以我们在jnitools.c
中重写函数这个函数,如下:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
return JNI_VERSION_1_6;
}
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
return JNI_VERSION_1_6;
}
有时候,我们要打印日志,来帮助我们识别是否进入这个方法,所以我们要配置一个log,这时候,我们创建一个Android.mk
文件,然后进行如下的编辑:
LOCAL_PATH := $(call my-dir)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=
LOCAL_SRC_FILES := jnitools.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
然后在jnitools.c
添加#include <android/log.h>
代码
这时候,开始注册代码,我们开始编写注册代码
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
<span class="token comment">//打印日志,说明已经进来了</span>
<span >__android_log_print</span><span >(</span>ANDROID_LOG_DEBUG<span >,</span><span >"JNITag"</span><span >,</span><span >"enter jni_onload"</span><span >)</span><span >;</span>
JNIEnv<span >*</span> env <span >=</span> <span >NULL</span><span >;</span>
jint result <span >=</span> <span >-</span><span class="token number">1</span><span >;</span>
<span class="token comment">// 判断是否正确</span>
<span >if</span><span >(</span><span >(</span><span >*</span>vm<span >)</span><span >-></span><span >GetEnv</span><span >(</span>vm<span >,</span><span >(</span><span >void</span><span >*</span><span >*</span><span >)</span><span >&</span>env<span >,</span>JNI_VERSION_1_6<span >)</span><span >!=</span> JNI_OK<span >)</span><span >{</span>
<span >return</span> result<span >;</span>
<span >}</span>
<span class="token comment">//注册四个方法,注意签名</span>
<span >const</span> JNINativeMethod method<span >[</span><span >]</span><span >=</span><span >{</span>
<span >{</span><span >"add"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>addNumber<span >}</span><span >,</span>
<span >{</span><span >"sub"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>subNumber<span >}</span><span >,</span>
<span >{</span><span >"mul"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>mulNumber<span >}</span><span >,</span>
<span >{</span><span >"div"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>divNumber<span >}</span>
<span >}</span><span >;</span>
<span class="token comment">//找到对应的JNITools类</span>
jclass jClassName<span >=</span><span >(</span><span >*</span>env<span >)</span><span >-></span><span >FindClass</span><span >(</span>env<span >,</span><span >"com/gebilaolitou/jni/JNITools"</span><span >)</span><span >;</span>
<span class="token comment">//开始注册</span>
jint ret <span >=</span> <span >(</span><span >*</span>env<span >)</span><span >-></span><span >RegisterNatives</span><span >(</span>env<span >,</span>jClassName<span >,</span>method<span >,</span> <span class="token number">4</span><span >)</span><span >;</span>
<span class="token comment">//如果注册失败,打印日志</span>
<span >if</span> <span >(</span>ret <span >!=</span> JNI_OK<span >)</span> <span >{</span>
<span >__android_log_print</span><span >(</span>ANDROID_LOG_DEBUG<span >,</span> <span >"JNITag"</span><span >,</span> <span >"jni_register Error"</span><span >)</span><span >;</span>
<span >return</span> <span >-</span><span class="token number">1</span><span >;</span>
<span >}</span>
<span >return</span> JNI_VERSION_1_6<span >;</span>
<span class="token comment">//打印日志,说明已经进来了</span>
<span >__android_log_print</span><span >(</span>ANDROID_LOG_DEBUG<span >,</span><span >"JNITag"</span><span >,</span><span >"enter jni_onload"</span><span >)</span><span >;</span>
JNIEnv<span >*</span> env <span >=</span> <span >NULL</span><span >;</span>
jint result <span >=</span> <span >-</span><span class="token number">1</span><span >;</span>
<span class="token comment">// 判断是否正确</span>
<span >if</span><span >(</span><span >(</span><span >*</span>vm<span >)</span><span >-></span><span >GetEnv</span><span >(</span>vm<span >,</span><span >(</span><span >void</span><span >*</span><span >*</span><span >)</span><span >&</span>env<span >,</span>JNI_VERSION_1_6<span >)</span><span >!=</span> JNI_OK<span >)</span><span >{</span>
<span >return</span> result<span >;</span>
<span >}</span>
<span class="token comment">//注册四个方法,注意签名</span>
<span >const</span> JNINativeMethod method<span >[</span><span >]</span><span >=</span><span >{</span>
<span >{</span><span >"add"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>addNumber<span >}</span><span >,</span>
<span >{</span><span >"sub"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>subNumber<span >}</span><span >,</span>
<span >{</span><span >"mul"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>mulNumber<span >}</span><span >,</span>
<span >{</span><span >"div"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>divNumber<span >}</span>
<span >}</span><span >;</span>
<span class="token comment">//找到对应的JNITools类</span>
jclass jClassName<span >=</span><span >(</span><span >*</span>env<span >)</span><span >-></span><span >FindClass</span><span >(</span>env<span >,</span><span >"com/gebilaolitou/jni/JNITools"</span><span >)</span><span >;</span>
<span class="token comment">//开始注册</span>
jint ret <span >=</span> <span >(</span><span >*</span>env<span >)</span><span >-></span><span >RegisterNatives</span><span >(</span>env<span >,</span>jClassName<span >,</span>method<span >,</span> <span class="token number">4</span><span >)</span><span >;</span>
<span class="token comment">//如果注册失败,打印日志</span>
<span >if</span> <span >(</span>ret <span >!=</span> JNI_OK<span >)</span> <span >{</span>
<span >__android_log_print</span><span >(</span>ANDROID_LOG_DEBUG<span >,</span> <span >"JNITag"</span><span >,</span> <span >"jni_register Error"</span><span >)</span><span >;</span>
<span >return</span> <span >-</span><span class="token number">1</span><span >;</span>
<span >}</span>
<span >return</span> JNI_VERSION_1_6<span >;</span>
}
这里补充一下,很多人,最后失败,都是签名的问题,可以建议使用java -p 命令行
来对比签名,我这是这样操作的。首先打开JNITools.class
,如下图:
image.png
然后打开Android Studio
里面的Terminal
,然后拖拽JNITools.class
到Terminal
。这样Terminal
就自动打开了,然后我们在Terminal
里面输入pwd
,就已经在这个目录里面了。然后我们在Terminal
输入如下代码
javap -s JNITools.class
Terminal
就会输出这个类的所有签名,如下:
Compiled from "JNITools.java"
public class com.gebilaolitou.jni.JNITools {
public com.gebilaolitou.jni.JNITools();
descriptor: ()V
Compiled from "JNITools.java"
public class com.gebilaolitou.jni.JNITools {
public com.gebilaolitou.jni.JNITools();
descriptor: ()V
public static native int add(int, int);
descriptor: (II)I
public static native int sub(int, int);
descriptor: (II)I
public static native int mul(int, int);
descriptor: (II)I
public static native int div(int, int);
descriptor: (II)I
static {};
descriptor: ()V
}
我们在这里核对下我们注册方法的签名。
最后,我们在对应的build.gradle里面defaultConfig
里面添加如下代码:
ndk{
moduleName "jnidemo3"
abiFilters 'x86','armeabi-v7a','arm64-v8a'
ldLibs "log"
}
这时候我们目录结构如下:
image.png
jnitools.c
的内容如下:
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint subNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint mulNumber(JNIEnv *env,jclass clazz,jint a,jint b);
jint divNumber(JNIEnv *env,jclass clazz,jint a,jint b);
JNIEXPORT jint JNI_OnLoad(JavaVM vm, void reserved){
<span >__android_log_print</span><span >(</span>ANDROID_LOG_DEBUG<span >,</span><span >"JNITag"</span><span >,</span><span >"enter jni_onload"</span><span >)</span><span >;</span>
JNIEnv<span >*</span> env <span >=</span> <span >NULL</span><span >;</span>
jint result <span >=</span> <span >-</span><span class="token number">1</span><span >;</span>
<span >if</span><span >(</span><span >(</span><span >*</span>vm<span >)</span><span >-></span><span >GetEnv</span><span >(</span>vm<span >,</span><span >(</span><span >void</span><span >*</span><span >*</span><span >)</span><span >&</span>env<span >,</span>JNI_VERSION_1_6<span >)</span><span >!=</span> JNI_OK<span >)</span><span >{</span>
<span >return</span> result<span >;</span>
<span >}</span>
<span >const</span> JNINativeMethod method<span >[</span><span >]</span><span >=</span><span >{</span>
<span >{</span><span >"add"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>addNumber<span >}</span><span >,</span>
<span >{</span><span >"sub"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>subNumber<span >}</span><span >,</span>
<span >{</span><span >"mul"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>mulNumber<span >}</span><span >,</span>
<span >{</span><span >"div"</span><span >,</span><span >"(II)I"</span><span >,</span><span >(</span><span >void</span><span >*</span><span >)</span>divNumber<span >}</span>
<span >}</span><span >;</span>
jclass jClassName<span >=</span><span >(</span><span >*</span>env<span >)</span><span >-></span><span >FindClass</span><span >(</span>env<span >,</span><span >"com/gebilaolitou/jni/JNITools"</span><span >)</span><span >;</span>
jint ret <span >=</span> <span >(</span><span >*</span>env<span >)</span><span >-></span><span >RegisterNatives</span><span >(</span>env<span >,</span>jClassName<span >,</span>method<span >,</span> <span class="token number">4</span><span >)</span><span >;</span>
<span >if</span> <span >(</span>ret <span >!=</span> JNI_OK<span >)</span> <span >{</span>
<span >__android_log_print</span><span >(</span>ANDROID_LOG_DEBUG<span >,</span> <span >"JNITag"</span><span >,</span> <span >"jni_register Error"</span><span >)</span><span >;</span>
<span >return</span> <span >-</span><span class="token number">1</span><span >;</span>
<span >}</span>
<span >return</span> JNI_VERSION_1_6<span >;</span>
}
jint addNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a+b;
}
jint subNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a-b;
}
jint mulNumber(JNIEnv env,jclass clazz,jint a,jint b){
return ab;
}
jint divNumber(JNIEnv *env,jclass clazz,jint a,jint b){
return a/b;
}
至此,整个代码已经全部完成。我们可以运行下试试。其实挺简单的。