http://blog.csdn.net/ownwell/article/details/8137376
首先我先給大家推薦一個很好的博客哦,這個是我無意間看到的~~
我首先給大家帶來的是一個Helloworld的程序。
步驟會一步步貼圖給出哦,至於現在的我會相信大家可以搞定的。
1 確保你已經安裝了NKD(我目前用的是NDK r4) 還有就是希望大家要記得在自己的Eclipse上安裝CDT插件哦,另外在編譯的過程中我們還要安裝Cygwin的,還得在Cygwin中配置ndk4(下面用的$NDK4就是我們自己配置的)
2 那就開始程序的開發了:
2.1 新建程序
新建一個Android程序叫HelloWorld。
- package com.example.helloworld;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- public class MainActivity extends Activity {
- public static native String getString();
- static {
- System.loadLibrary("HelloWorld");
- }
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.activity_main, menu);
- return true;
- }
- }
2.2 開始編譯生成頭文件。
看了很多帖子感覺有些帖子是轉載的沒有實際的自己的操作,我現在給大家一個很好用的方法:
先打開自己的命令行吧,我的已經安裝了Cygwin了有點linux的意思,呵呵,不過沒關係。
然後呢就可以看到在src下看到一個頭文件了:
好了,這就搞定了第一步了
2.3 開始編譯so庫了,所謂的so庫就是動態的鏈接庫,window下用的是dll,我們現在用的是android系統(其內核還是Linux的)。
我們先得自己將我們剛纔生成的.h頭文件考到一個新建的jni的文件夾下,還得實現剛纔的.h中的方法。
- #include "com_example_helloworld_MainActivity.h"
- JNIEXPORT jstring JNICALL Java_com_example_helloworld_MainActivity_getString
- (JNIEnv *env, jobject obj)
- {
- char *str="Hello World";
- return (*env)->NewStringUTF(env,str);
- }
另外我們還得自己寫一個Android.mk文件就相當於Linux的makeFile:
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := HelloWorld
- LOCAL_SRC_FILES := com_example_helloworld_MainActivity.c
- include $(BUILD_SHARED_LIBRARY)
這個.mk我解釋一下
**************************************************************
local_path就是本地文件,地位到當前的文件夾
$(CLEAR_VARS) 先clear下系統的變量
本地的模塊(LOCAL_MODULE) HelloWorld就是我們要生成的so庫的名字
包含的頭文件(LOCAL_SRC_FILES) 就是我們自己寫的源文件
*************************************************************
在Cygwin下編譯生成so庫:
好吧在bin文件夾下看一下吧:
我們還需要讓這個字符顯示出來哦,來一起改下activity的代碼:
- package com.example.helloworld;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- import android.widget.TextView;
- public class MainActivity extends Activity {
- public static native String getString();
- private TextView helloText;
- //加載的HelloWolrd.so
- tatic {
- System.loadLibrary("HelloWorld");
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- findView();
- }
- //找到在layout下的xml佈局中的textview
- private void findView() {
- helloText = (TextView)findViewById(R.id.hello);
- helloText.setText("JNIString "+getString());
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.activity_main, menu);
- return true;
- }
- }
OK全部完成了。
附上代碼吧
這是一個很小的demo,我們要實現的也很簡單就是讓JAVA層的能直接調用c層的實現,因爲在很多的情況下我們需要通過c來直接調用系統的硬件的接口,其實我們對jni 的瞭解還是很少,我們就從android開始吧!
hello-jni在Java環境中的類MainActivity中聲明的函數名爲getString,前面要用到修飾符native,類HelloJni所在的包名爲com.example.helloworld,需要用函數System.loadLibrary加載lib庫HelloWorld.so,採用static修飾符確保只加載一次。然後按正常函數使用就行了。而在NDK這邊,即C語言這層,函數命名要遵循Java_包_類_函數的命名方式,中間用下劃線_進行連接,如上面所示,在包com.example.hellojni中的類HelloJni聲明爲stringFromJNI,則在C/C++文件中定義的函數名爲JNIEXPORT jstring JNICALL Java_com_example_helloworld_MainActivity_getString,注意區分大小寫。函數可以傳參數,本例子中沒有傳入參數,只是有返回參數,返回參數的數據類型爲jstring,即Java中的String類型。對於C/C++中與上面的Java環境打交道的數據類型可以參照JNI,具體可訪問官方網站http:// java.sun.com/docs/books/jni/。對於函數JNIEXPORT jstring JNICALL Java_com_example_helloworld_MainActivity_getString中的兩個參數env和thiz是系統必須的,如果需要輸入參數,必須再增加參數。
精品貼:
講到了c/c++的不同實現:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=180287