本系列文章如下:
我们这里做一个简单的计算器demo,其中运算的逻辑由Native实现,而且我们采用动态注册的方式来实现
样式大概如下:
里面有两个输入框,下面有4个按钮,代表加减乘除,最下面有个TextView,表示结果。
我们把运算的逻辑抽象出来,用一个JNITools
来表示。代码如下:
public class JNITools {
<span class="token keyword">static</span> <span class="token punctuation">{</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">loadLibrary</span><span class="token punctuation">(</span><span class="token string">"jnidemo3"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//加法</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">native</span> <span class="token keyword">int</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span><span class="token keyword">int</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//减法</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">native</span> <span class="token keyword">int</span> <span class="token function">sub</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span><span class="token keyword">int</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//乘法</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">native</span> <span class="token keyword">int</span> <span class="token function">mul</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span><span class="token keyword">int</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//除法</span> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">native</span> <span class="token keyword">int</span> <span class="token function">div</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span><span class="token keyword">int</span> b<span class="token punctuation">)</span><span class="token punctuation">;</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 class="token tag"><span class="token tag"><span class="token punctuation"><</span>LinearLayout</span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>EditText</span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/inputa<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>hint</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>请输入a<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>inputType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>EditText</span> <span class="token attr-name"><span class="token namespace">android:</span>inputType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>number<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/inputb<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>hint</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>请输入b<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>LinearLayout</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TextView</span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>请选择符号<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>LinearLayout</span> <span class="token attr-name"><span class="token namespace">android:</span>orientation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>horizontal<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Button</span> <span class="token attr-name"><span class="token namespace">android:</span>gravity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>center<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/add<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/add<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Button</span> <span class="token attr-name"><span class="token namespace">android:</span>gravity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>center<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/sub<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/sub<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Button</span> <span class="token attr-name"><span class="token namespace">android:</span>gravity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>center<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/mul<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/mul<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>Button</span> <span class="token attr-name"><span class="token namespace">android:</span>gravity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>center<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1.0<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@string/div<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/div<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>LinearLayout</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TextView</span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/result<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>计算结果<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
</LinearLayout>
这时候,我们来看下对应的MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
<span class="token keyword">private</span> <span class="token class-name">Button</span> btnAdd<span class="token punctuation">,</span>btnSub<span class="token punctuation">,</span>btnMul<span class="token punctuation">,</span>btnDiv<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">EditText</span> inputA<span class="token punctuation">,</span>inputB<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">TextView</span> tvResult<span class="token punctuation">;</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">onCreate</span><span class="token punctuation">(</span><span class="token class-name">Bundle</span> savedInstanceState<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onCreate</span><span class="token punctuation">(</span>savedInstanceState<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">setContentView</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>layout<span class="token punctuation">.</span>activity_main<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">setupView</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">addListener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">addListener</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> btnAdd<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> btnDiv<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> btnMul<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> btnSub<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">setupView</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> btnAdd<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>add<span class="token punctuation">)</span><span class="token punctuation">;</span> btnDiv<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>div<span class="token punctuation">)</span><span class="token punctuation">;</span> btnMul<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>mul<span class="token punctuation">)</span><span class="token punctuation">;</span> btnSub<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>sub<span class="token punctuation">)</span><span class="token punctuation">;</span> inputA<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>inputa<span class="token punctuation">)</span><span class="token punctuation">;</span> inputB<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>inputb<span class="token punctuation">)</span><span class="token punctuation">;</span> tvResult<span class="token operator">=</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">findViewById</span><span class="token punctuation">(</span><span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onClick</span><span class="token punctuation">(</span><span class="token class-name">View</span> v<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">double</span> result<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> <span class="token class-name">String</span> strA<span class="token operator">=</span>inputA<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">String</span> strB<span class="token operator">=</span>inputB<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> a<span class="token operator">=</span><span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token function">parseInt</span><span class="token punctuation">(</span>strA<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">int</span> b<span class="token operator">=</span><span class="token class-name">Integer</span><span class="token punctuation">.</span><span class="token function">parseInt</span><span class="token punctuation">(</span>strB<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>v<span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>add<span class="token operator">:</span> result<span class="token operator">=</span><span class="token class-name">JNITools</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>div<span class="token operator">:</span> result<span class="token operator">=</span><span class="token class-name">JNITools</span><span class="token punctuation">.</span><span class="token function">div</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>mul<span class="token operator">:</span> result<span class="token operator">=</span><span class="token class-name">JNITools</span><span class="token punctuation">.</span><span class="token function">mul</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token class-name">R</span><span class="token punctuation">.</span>id<span class="token punctuation">.</span>sub<span class="token operator">:</span> result<span class="token operator">=</span><span class="token class-name">JNITools</span><span class="token punctuation">.</span><span class="token function">sub</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> tvResult<span class="token punctuation">.</span><span class="token function">setText</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token operator">+</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</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 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 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>
依照前面动态注册方法的步骤,我们要重写JNI_OnLoad(JavaVM* vm, void* reserved)
函数。所以我们在jnitools.c
中重写函数这个函数,如下:
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){
return JNI_VERSION_1_6;
}
有时候,我们要打印日志,来帮助我们识别是否进入这个方法,所以我们要配置一个log,这时候,我们创建一个Android.mk
文件,然后进行如下的编辑:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jnidemo3
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){
<span class="token comment">//打印日志,说明已经进来了</span> <span class="token function">__android_log_print</span><span class="token punctuation">(</span>ANDROID_LOG_DEBUG<span class="token punctuation">,</span><span class="token string">"JNITag"</span><span class="token punctuation">,</span><span class="token string">"enter jni_onload"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> JNIEnv<span class="token operator">*</span> env <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span> jint result <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">// 判断是否正确</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token operator">*</span>vm<span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">GetEnv</span><span class="token punctuation">(</span>vm<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token operator">&</span>env<span class="token punctuation">,</span>JNI_VERSION_1_6<span class="token punctuation">)</span><span class="token operator">!=</span> JNI_OK<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//注册四个方法,注意签名</span> <span class="token keyword">const</span> JNINativeMethod method<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">=</span><span class="token punctuation">{</span> <span class="token punctuation">{</span><span class="token string">"add"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>addNumber<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">"sub"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>subNumber<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">"mul"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>mulNumber<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">"div"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>divNumber<span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">//找到对应的JNITools类</span> jclass jClassName<span class="token operator">=</span><span class="token punctuation">(</span><span class="token operator">*</span>env<span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">FindClass</span><span class="token punctuation">(</span>env<span class="token punctuation">,</span><span class="token string">"com/gebilaolitou/jni/JNITools"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//开始注册</span> jint ret <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token operator">*</span>env<span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">RegisterNatives</span><span class="token punctuation">(</span>env<span class="token punctuation">,</span>jClassName<span class="token punctuation">,</span>method<span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//如果注册失败,打印日志</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>ret <span class="token operator">!=</span> JNI_OK<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">__android_log_print</span><span class="token punctuation">(</span>ANDROID_LOG_DEBUG<span class="token punctuation">,</span> <span class="token string">"JNITag"</span><span class="token punctuation">,</span> <span class="token string">"jni_register Error"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> JNI_VERSION_1_6<span class="token punctuation">;</span>
}
这里补充一下,很多人,最后失败,都是签名的问题,可以建议使用java -p 命令行
来对比签名,我这是这样操作的。首先打开JNITools.class
,如下图:
然后打开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
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"
}
这时候我们目录结构如下:
jnitools.c
的内容如下:
#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 class="token function">__android_log_print</span><span class="token punctuation">(</span>ANDROID_LOG_DEBUG<span class="token punctuation">,</span><span class="token string">"JNITag"</span><span class="token punctuation">,</span><span class="token string">"enter jni_onload"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
JNIEnv<span class="token operator">*</span> env <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
jint result <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token operator">*</span>vm<span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">GetEnv</span><span class="token punctuation">(</span>vm<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token operator">&</span>env<span class="token punctuation">,</span>JNI_VERSION_1_6<span class="token punctuation">)</span><span class="token operator">!=</span> JNI_OK<span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> JNINativeMethod method<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">=</span><span class="token punctuation">{</span>
<span class="token punctuation">{</span><span class="token string">"add"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>addNumber<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span><span class="token string">"sub"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>subNumber<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span><span class="token string">"mul"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>mulNumber<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span><span class="token string">"div"</span><span class="token punctuation">,</span><span class="token string">"(II)I"</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token keyword">void</span><span class="token operator">*</span><span class="token punctuation">)</span>divNumber<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
jclass jClassName<span class="token operator">=</span><span class="token punctuation">(</span><span class="token operator">*</span>env<span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">FindClass</span><span class="token punctuation">(</span>env<span class="token punctuation">,</span><span class="token string">"com/gebilaolitou/jni/JNITools"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
jint ret <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token operator">*</span>env<span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">RegisterNatives</span><span class="token punctuation">(</span>env<span class="token punctuation">,</span>jClassName<span class="token punctuation">,</span>method<span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ret <span class="token operator">!=</span> JNI_OK<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">__android_log_print</span><span class="token punctuation">(</span>ANDROID_LOG_DEBUG<span class="token punctuation">,</span> <span class="token string">"JNITag"</span><span class="token punctuation">,</span> <span class="token string">"jni_register Error"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> JNI_VERSION_1_6<span class="token punctuation">;</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;
}
至此,整个代码已经全部完成。我们可以运行下试试。其实挺简单的。