我们这里做一个简单的计算器demo,其中运算的逻辑由Native实现,而且我们采用动态注册的方式来实现

样式大概如下:






android加减数值 安卓加法运算_学习


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.classTerminal。这样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;
}

至此,整个代码已经全部完成。我们可以运行下试试。其实挺简单的。