/* http://my.oschina.net/lifj/blog/177087 */
上一篇講了怎麼配置NDK的開發環境。此次記錄一下寫一個Hello Jni的最簡單的Android程序。java
這裏,咱們須要作一下幾步:
1.Layout中添加TextView的id。
2.MainActivity中聲明native方法。
3.MainActivity中調用native方法。 android
咱們這裏先不loadLibrary。先load總感受個人庫尚未呢,先load作什麼?有點莫名其妙。固然,你也能夠先loadLibrary。看我的習慣了。shell
下面詳細說明:
1.新建Android,名字,包名什麼的隨便取。一路下一步,生成以後,在默認生成的Activity的layout的TextView上加一個id。(這個都會吧)android:id="@+id/hello_jni"。此時的layout文件內容以下:app
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/hello_jni" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
2.在MainActivity.java中聲明native方法。
public native String getHelloJniString();
3.在OnCreate()方法中獲取TextView,並設置text。
((TextView)findViewById(R.id.hello_jni)).setText(getHelloJniString());
通過二、3兩步以後的MainActivity.java文件內容以下:
ide
package com.example.hellojni; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { public native String getHelloJniString(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.hello_jni)).setText(getHelloJniString()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
這一步,你須要C/C++的語言基礎。(這個簡單的例子只須要簡單的。)
按照大多數博客,會告訴你:編譯工程以後,進入工程目錄文件夾下,在控制檯運行
javah -classpath bin/classes -d jni com.example.hellojni.MainAcitivity
,而後就會在工程目錄下生成一個jni文件夾,裏面就會有.h的頭文件了。ui
實際上,你會遇到一個錯誤:
錯誤: 沒法訪問android.app.Activity
找不到android.app.Activity的類文件
是的,大多數人都會遇到這個問題,我對此表示疑問:那些寫博客的人都本身試過沒有?編碼
怎麼辦呢?
1. 有人提出方法,在工程目錄下運行命令:
javah -classpath src -d jni com.example.hellojni.MainAcitivity
就OK了。是的,這個是OK的。(這個命令和上面一個命令的區別就是 -classpath 不一樣了。)
spa
2.還有一種方法:在工程目錄下,上述命令中加上android.jar的classpath。也是可行的。也就是運行以下命令:javah -classpath F:\JNI\env\platforms\android-17\android.jar;bin/classes -d jni com.example.hellojni.MainActivity
這個命令,就是把android.jar的路徑加了進去。這樣,就能找到Activity類了。
以上兩種可行的獲得.h頭文件的方法,生成的.h文件的內容是不同的,你能夠試試看。至於哪種比較好,我目前還不清楚。由於看谷歌NDK的samples裏面(samples這個文件夾,就是NDK的示例程序目錄,對咱們來講,就是教程了)的頭文件,彷佛是第一種方式。第二種方式卻是沒有見到過。
我我的仍是傾向於用第二種方式,雖然命令比較煩。。.net
頭文件生成好了,刷新一下工程,就會看到以下的目錄結構:
code
多了一個jni文件夾和裏面的一長串名字的頭文件。名字太長,咱們改短一點,改爲HelloJni.h吧。省的麻煩。
接下來編寫.c的實現文件。在jni文件夾右擊,選擇file,命名文件名字爲HelloJni.c。肯定。也就是以下:
而後打開新建的HelloJni.c文件,輸入以下語句並保存:
#include <stdio.h> #include "HelloJni.h" jstring Java_com_example_hellojni_MainActivity_getHelloJniString (JNIEnv * env, jobject clazz) { return (*env)->NewStringUTF(env, "Hello Jni!"); }
下面開始編寫mk文件。在jni目錄下建立一個Android.mk的文件(A要大寫哦!!否則編譯會出錯:
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk /home/aditya/android-ndk-r9/build/core/add-application.mk:176: *** Android NDK: Aborting... .
)。加入以下代碼並保存(裏面的一些命令先不瞭解也是能夠的。):
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := HelloJni LOCAL_SRC_FILES := HelloJni.c include $(BUILD_SHARED_LIBRARY)
這裏,主要注意兩個地方:
LOCAL_MODULE := HelloJni 。這裏的HelloJni就是你的庫的名字,也就是你loadLibrary的字符串。生成出來的庫是libHelloJni.so。
LOCAL_SRC_FILES := HelloJni.c 。這裏的HelloJni.c就是c文件的名字。
下面打開Cygwin,進入到工程目錄下,輸入以下命令,並回車:
$NDK/ndk-build
出現以下畫面,就說明ok了。
而後咱們刷新工程,會發現,多了一個obj文件夾,和libs文件夾裏面多了armeabi文件夾和裏面的libHelloJni.so庫。obj文件夾是沒有用的,能夠刪掉了。
最後一步,咱們再次進入MainActivity,加載庫文件。加入後的代碼以下:
package com.example.hellojni; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { static { System.loadLibrary("HelloJni"); } public native String getHelloJniString(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.hello_jni)).setText(getHelloJniString()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
System.loadLibrary("HelloJni"); 這個字符串就是咱們在mk文件中寫的LOCAL_MODULE的值。
好了,至此,咱們編碼ok了。運行起來吧。