Android NDK開發入門

來源:互聯網
上載者:User

Android NDK開發入門

網上一大堆的都是使用javah命令來產生標頭檔來完成JNI編寫,但其實ADT整合NDK後,點點滑鼠就可以了,懶人方法網上介紹很少,這邊主要講懶人JNI開發。

對於ADT配置NDK,請個人google或查看Android developer,這邊不多做介紹。

1. 建立一個Android工程,我這邊取名為JNI_Learn,一鍵產生後程式碼片段如下:

public class JNI extends ActionBarActivity {static{System.loadLibrary("JNI_Learn");}public native int plus(int x, int y);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_jni);                if (savedInstanceState == null) {            getSupportFragmentManager().beginTransaction()                    .add(R.id.container, new PlaceholderFragment())                    .commit();        }                Log.d("JNITest", "3+5=" + plus(3, 5));            }
高亮部分是我自己添加部分,簡單解釋一下。

loadLibrary的話,裡面的名字稍後我會再標註一下,這邊主要是native層產生的so庫的名字,需要去掉lib首碼和.so尾碼。

聲明native方法要在存取權限之後,其他聲明之前,加一個native標記此方法實現在native層。

使用plus方法與正常使用無異。

2. 之後就是懶人操作了,在工程上右擊滑鼠,選擇Android Tools->Add Native Support...


之後查看工程裡面有兩個檔案


第一個是JNI_Learn.cpp,這個稍後詳述。第二個是Android.mk,在Android編譯中,都會尋找目錄下是否存在Android.mk,然後根據這個檔案進行編譯。裡面編寫了具體的編譯規則,開啟檔案後,內容如下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_LDLIBS := -llogLOCAL_MODULE    := JNI_LearnLOCAL_SRC_FILES := JNI_Learn.cppinclude $(BUILD_SHARED_LIBRARY)
除加紅部分外,其他都為自動產生,加紅部分是我添加為了使用native的log方法
其中LOCAL_PATH表示編譯源檔案的路徑,LOCAL_LDLIBS表示編譯模組時需要附加的連接器選項,LOCAL_MODULE表示最終編譯出來模組的名稱,LOCAL_SRC_FILES表示需要編譯的源檔案,include $(BUILD_SHARED_LIBRARY)表示最終編譯成一個共用庫檔案。


3. 下面具體添加native層對plus方法的實現代碼

#include #include #define LOG_TAG "JNITest"//log func//int __android_log_print(int prio, const char *tag,  const char *fmt, ...)#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)extern "C"JNIEXPORT int Java_com_example_jni_1learn_JNI_plus");return x + y;}

使用了Android log將log列印到了logcat一樣,想瞭解的可以自行查閱相關知識,這邊沒太大關係,這個也是在Android.mk中為什麼需要增加LOCAL_LDLIBS原因。

extern “C”是必須要加的,因為C++和C編譯後的匯出函數原型不同,java只能call C類型的,所以需要將C++轉化為C類型的,增加extern "C"聲明。

JNIEXPORT聲明他是一個匯出函數。

方法名字必須以Java開頭,然後包名和類名及方法名之間底線隔開,如果不巧剛好你的包名中有底線,那如何處理JNI中java包名含底線情況呢?在前面加一個“1”。


這麼簡單程式,遇到幾個錯誤:

第一個是說JNI Load Library失敗,因為apk中可以看到so是不是被壓縮排去了(更改apk尾碼為rar,解壓rar可以看到有個lib檔案夾內有這個so),我這邊看到壓縮排去了,結果還是載入失敗。原因在於loadLibrary的參數必須要不帶首碼lib不加尾碼.so才可以。

爆出undefined reference to,原因是由於我沒有聲明extern "C",java找不到C++聲明方式的。

還有就是包名中恰好出現底線,比如JNI_Learn,需要更改為_1才可以規避。

還有就是使用LOG,必須要在Android.mk中增加LOCAL_LDLIBS。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.