Android NDK使用執行個體

來源:互聯網
上載者:User
Android系統中的應用程式都是用Java開發的。Android NDK使我們能夠在android上使用C/C++開發的原生代碼。有兩個理由使用NDK: 一是合理的重用現有的代碼;二是在程式中某些關鍵的部分提高執行效率。

這裡先講幾個符號的約定:

<project> - 你的Android應用程式工程的目錄

<ndk> - 你的ndk安裝的目錄

捷徑

這裡先扯一句題外話 -- 如果你不需要使用NDK開發,只是需要使用第三方用NDK開發的庫,那麼你只需要這樣做:

把第三方提供的libxxx.so放到你的<project>/libs/armeabi/下, 然後在程式隨便什麼地方中加入

static {

    System.loadLibray("xxx");

}

就可以使用該庫了。

安裝NDK

NDK的安裝很簡單:

1. 首先要將SDK升級至最新,然後下載ndk(可能要翻牆,恩恩)將它解壓到某個目錄<ndk>下。

2. 運行: <ndk>/build/host-setup.sh
(註:r4版本或更高版本,無須執行這步,詳情請看ndk/doc/install.html)

3. 如果成功的話就OK了,如果失敗的話檢查一下你是不是下載了正確的ndk版本(例如你的作業系統是linux而下載了windows版的ndk).



附:

Android SDK 3.0

Windows

http://dl.google.com/android/installer_r10-windows.exe

http://dl.google.com/android/android-sdk_r10-windows.zip

Mac OS X(intel)

http://dl.google.com/android/android-sdk_r10-mac_x86.zip

Linux(i386)

http://dl.google.com/android/android-sdk_r10-linux_x86.tgz

 

Android NDK r5b

Windows

http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip

Mac OS X(intel)

http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2

Linux

http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2

 

Android SDK 2.3

Windows

http://dl.google.com/android/android-sdk_r08-windows.zip

http://dl.google.com/android/installer_r08-windows.exe

Linux (i386)

http://dl.google.com/android/android-sdk_r08-linux_86.tgz

MAC OS X (intel)

http://dl.google.com/android/android-sdk_r08-mac_86.zip

 

Android NDK r5

Windows

http://dl.google.com/android/ndk/android-ndk-r5-windows.zip

Mac OS X (intel) r5

http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2

Linux 32/64-bit (x86) r5

http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2

 


Java部分

現在我們用一個很簡單的例子來說明NDK的使用。我們在eclipse中建立一個android工程,其中:

Project Name:jnitest

Build Target: Android 1.6

Application Name: JNI Test

Package Name: org.eshock.jnitest

Create Activity: JNITest


JNITest.java:


package org.eshock.jnitest;


import android.app.Activity;

import android.os.Bundle;


public class JNITest extends Activity {

    public native int plus (int x, int y);

    

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        int x = plus(1, 2);

        android.util.Log.d("jni", String.valueOf(x));

    }

    

    static {

        System.loadLibrary("mylib");

    }

}


我們只是示範NDK,所以就不要介面了。在這個程式中,我們調用一個c語言編寫的plus(int, int)函數來計算1+2的值,然後在log中列印它。這個庫的名稱叫做mylib。

要使用一個c語言的函數,需要在java中聲明:

public native int plus(int x, int y);

這樣java編譯器就知道這個函數是外部庫中實現的。


C部分


接下來我們使用C語言實現這個plus函數。

建立<project>/jni/mylib.c:


#include <string.h>

#include <jni.h>


JNIEXPORT jint JNICALL

Java_org_eshock_jnitest_JNITest_plus( JNIEnv* env,

                                                  jobject thiz,

                                                  jint x,

                                                  jint y )

{

    return x + y;

}


裡我們看到,mylib.c裡的plus函數比java裡面的plus函數的簽名要複雜了很多,主要是plus前面增加了包名,函數中多了兩個參數,以及
所有的int變成了jint。關於c中類型與jni中類型的對應關係,可以參見jni的相關文檔,例如core Java
II中的最後一章。如果你不想去查閱文檔,有一個方法:

首先隨便在某個目錄下建立一個檔案JNITest.java:


public class JNITest {

    public native int plus (int x, int y);

}


然後在命令列下執行:

javac JNITest.java && javah JNITest 

將產生一個檔案JNITest.h:


/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class JNITest */


#ifndef _Included_JNITest

#define _Included_JNITest

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     JNITest

 * Method:    plus

 * Signature: (II)I

 */

JNIEXPORT jint JNICALL Java_JNITest_plus

  (JNIEnv *, jobject, jint, jint);


#ifdef __cplusplus

}

#endif

#endif


這裡自動產生了java中native函數對應的簽名,你可以在c代碼中使用它。小斤:記得修改包名
如果Java_org_eshock_jnitest_JNITest_plus與Java代碼中的包名不一致,編譯不會出現錯誤,但運行時會出現

java.lang.UnsatisfiedLinkError

Android.mk和Application.mk

Android.mk是一個makefile,用來告訴NDK需要編譯哪些檔案,產生哪些模組。我們建立<jni>/Android.mk檔案:


LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)


LOCAL_MODULE    := mylib

LOCAL_SRC_FILES := mylib.c


include $(BUILD_SHARED_LIBRARY)


其中LOCAL_PATH表示c原始碼檔案的位置;LOCAL_MODULE表示產生的共用庫的名稱;LOCAL_SRC_FILES代表c代碼的檔案。不需要把標頭檔列在裡面;標頭檔的依賴關係是ndk自動計算的。


Application.mk的作用是告訴Android SDK需要哪些庫檔案。有了它,NDK就可以把庫放在正確的位置。我們建立<project>/Application.mk:


APP_PROJECT_PATH := $(call my-dir)

APP_MODULES      := mylib


APP_PROJECT_PATH代表android工程所在目錄,在本例中它被放在<project>中; APP_MODULES表示工程需要的庫,如果有多個以空格分開。


編譯共用庫

由於ndk規定Application.mk必須放在<ndk>/apps/project_name,我們在<ndk>下建立一個符號串連:

ln -s <project> <ndk>/apps/jnitest

這樣,我們就可以開始編譯共用庫了:

在<ndk>目錄下運行:

make APP=jnitest


Android NDK: Building for application 'jnitest'

Compile thumb  : mylib <= apps/jnitest/jni/mylib.c

SharedLibrary  : libmylib.so

Install        : libmylib.so => apps/jnitest/libs/armeabi


可以看到編譯成功,並在<project>/libs/armeabi/下產生了libmylib.so。

小斤:NDK r4版本後,無需建立串連,直接在<project>下執行ndk-build命令即可,該命令位於ndk的目錄下。

測試

在運行之前,首先確認一下你的工程裡面各個檔案都齊全,應該類似於這樣:

 然後測試,正常的話應該能看到log中有輸出3.
以上轉自:http://blog.163.com/hancker_31/blog/static/355873612011376517108/
 《
初學Android NDK》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.