1. 程式人生 > >WIN7+64位+ndk配置

WIN7+64位+ndk配置

想學ndk,不知道ndk是什麼?有Android開發經驗的都知道jdk,sdk.好了其實他們三個處於同一等級,你怎麼理解jdk,sdk就怎麼理解ndk,當然它們各有各的作用

一、NDK產生的背景

  Android平臺從誕生起,就已經支援C、C++開發。眾所周知,Android的SDK基於Java實現,這意味著基於Android SDK進行開發的第三方應用都必須使用Java語言。但這並不等同於“第三方應用只能使用Java”。在Android SDK首次釋出時,Google就宣稱其虛擬機器Dalvik支援JNI程式設計方式,也就是第三方應用完全可以通過JNI呼叫自己的C動態庫,即在Android平臺上,“Java+C”的程式設計方式是一直都可以實現的。

  不過,Google也表示,使用原生SDK程式設計相比Dalvik虛擬機器也有一些劣勢,Android SDK文件裡,找不到任何JNI方面的幫助。即使第三方應用開發者使用JNI完成了自己的C動態連結庫(so)開發,但是so如何和應用程式一起打包成apk併發布?這裡面也存在技術障礙。比如程式更加複雜,相容性難以保障,無法訪問Framework API,Debug難度更大等。開發者需要自行斟酌使用。

  於是NDK就應運而生了。NDK全稱是Native Development Kit。

  NDK的釋出,使“Java+C”的開發方式終於轉正,成為官方支援的開發方式。NDK將是Android平臺支援C開發的開端。

二、為什麼使用NDK

  1.程式碼的保護。由於apk的java層程式碼很容易被反編譯,而C/C++庫反匯難度較大。

  2.可以方便地使用現存的開源庫。大部分現存的開源庫都是用C/C++程式碼編寫的。

  3.提高程式的執行效率。將要求高效能的應用邏輯使用C開發,從而提高應用程式的執行效率。

  4.便於移植。用C/C++寫得庫可以方便在其他的嵌入式平臺上再次使用。

三、NDK簡介

       1.NDK是一系列工具的集合

       NDK提供了一系列的工具,幫助開發者快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。這些工具對開發者的幫助是巨大的。

NDK集成了交叉編譯器,並提供了相應的mk檔案隔離CPU、平臺、ABI等差異,開發人員只需要簡單修改mk檔案(指出“哪些檔案需要編譯”、“編譯特性要求”等),就可以創建出so。

NDK可以自動地將so和Java應用一起打包,極大地減輕了開發人員的打包工作。

       2.NDK提供了一份穩定、功能有限的API標頭檔案宣告

       Google明確宣告該API是穩定的,在後續所有版本中都穩定支援當前釋出的API。從該版本的NDK中看出,這些API支援的功能非常有限,包含有:C標準庫(libc)、標準數學庫(libm)、壓縮庫(libz)、Log庫(liblog)。

 四、NDK環境配置

      下載android-ndk-r9c解壓到相應目錄(我的  E:\adt\android-ndk-r9c)

       開啟我們的eclipse(含有adt外掛的安卓開發環境)->window->preference->android->ndk設定ndk路徑apply->ok


建立JNITest應用程式右鍵單擊專案->Android Tools->Add Native Support...然後給我們的.so檔案取名,例如jni-test


這時候工程就會多一個jni的資料夾,jni下有Android.mk和jni-test.cpp檔案。Android.mk是NDK工程的Makefile,my-ndk.cpp就是NDK的原始檔。

好了專案建立成功,剩下的就是jni-test.cpp裡面的C語言程式碼實現和activity裡面JAVA程式碼實現

入門的最好辦法就是學習Android自帶的例子, 這裡就通過學習Android的NDK自帶的demo程式:hello-jni來達到這個目的。

五、把專案匯入到環境編譯執行

在NDKr7開始,google的windos版NDK提供了一個ndk-build.cmd的指令碼,這樣就可以直接利用這個指令碼編譯,而不需要cygwin了。

1,選擇你的android工程,右擊->Properties->Builders->new,新新增一個編譯器,點選之後出現新增介面,選擇Program,點選ok。


2,出現了新增介面,我們先給編譯器設定名稱,如XXX_builder。設定Location為<NDK安裝目錄>\ndk-build.cmd

  設定Working Directory為${workspace_loc:/專案名稱}


3,切換到Refersh選項卡,給Refersh resources upon completion打上勾,選擇The entire resource選項。


4,切換到Build Options選項卡,勾選上最後三項。再點選Specify Resource按鈕,選擇你的android工程的


5,在編譯工具列表,我們最好將我們新建的編譯器置頂。選中點選Up按鈕置頂ok.


編譯後


hello-jni.c

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <string.h>
#include <jni.h>

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
 */
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
#if defined(__arm__)
  #if defined(__ARM_ARCH_7A__)
    #if defined(__ARM_NEON__)
      #define ABI "armeabi-libhello-jni.so/NEON"
    #else
      #define ABI "armeabi-libhello-jni.so"
    #endif
  #else
   #define ABI "armeabi"
  #endif
#elif defined(__i386__)
   #define ABI "x86"
#elif defined(__mips__)
   #define ABI "mips"
#else
   #define ABI "unknown"
#endif

    return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
}

HelloJni.java
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.hellojni;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;


public class HelloJni extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        /* Create a TextView and set its content.
         * the text is retrieved by calling a native
         * function.
         */
        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(tv);
    }

    /* A native method that is implemented by the
     * 'hello-jni' native library, which is packaged
     * with this application.
     */
    public native String  stringFromJNI();

    /* This is another native method declaration that is *not*
     * implemented by 'hello-jni'. This is simply to show that
     * you can declare as many native methods in your Java code
     * as you want, their implementation is searched in the
     * currently loaded native libraries only the first time
     * you call them.
     *
     * Trying to call this function will result in a
     * java.lang.UnsatisfiedLinkError exception !
     */
    public native String  unimplementedStringFromJNI();

    /* this is used to load the 'hello-jni' library on application
     * startup. The library has already been unpacked into
     * /data/data/com.example.hellojni/lib/libhello-jni.so at
     * installation time by the package manager.
     */
    static {
        System.loadLibrary("hello-jni");
    }
}


右鍵專案run as->android application