Android Studio 之 JNI 開發(fā)詳解

前言

  1. 什么是NDK?
    NDK全稱是Native Development Kit,NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C(或C++)的動態(tài)庫,并能自動將so和java應用一起打包成apk。NDK集成了交叉編譯器(交叉編譯器需要UNIX或LINUX系統(tǒng)環(huán)境),并提供了相應的mk文件隔離CPU、平臺、ABI等差異,開發(fā)人員只需要簡單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so。

  2. 為什么使用NDK?
    1.)代碼的保護。由于apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大。
    2.)可以方便地使用現(xiàn)存的開源庫。大部分現(xiàn)存的開源庫都是用C/C++代碼編寫的。
    3.)提高程序的執(zhí)行效率。將要求高性能的應用邏輯使用C開發(fā),從而提高應用程序的執(zhí)行效率。
    4.)便于移植。用C/C++寫得庫可以方便在其他的嵌入式平臺上再次使用。

  3. 什么是JNI?
    JNI全稱為:Java Native Interface。JNI 是本地編程接口,它使得在 Java 虛擬機內(nèi)部運行的 Java 代碼能夠與用其它語言(如 C、C++)編寫的代碼進行交互。

  4. 為什么使用JNI?
    JNI的目的是使java方法能夠調(diào)用c實現(xiàn)的一些函數(shù)。

  5. 安卓中的so文件是什么?
    Android中用到的so文件是一個c++的函數(shù)庫。在android的JNI中,要先將相應的C語言打包成so庫,然后導入到lib文件夾中供java調(diào)用。

本例開發(fā)環(huán)境如下:
操作系統(tǒng):Mac
開發(fā)環(huán)境:Android Studio 2.2 Beta3 + NDK r12 + Gradle 2.14.1

NDK安裝

  1. 從Android Studio安裝(需翻墻)
    1.)打開AndroidStudio,選擇頂部工具條,Tools->Android->SDK Manager

    2.)在彈出來的對話框中選擇SDK Tools選項卡

    3.)勾選上圖中NDK,點擊 Apply,開始安裝
    4.)安裝完成后,重啟Android Studio
  2. AndroidDevTools安裝
    1.)打開AndroidDevTools網(wǎng)頁,選擇導航欄中Android SDK Tools->NDK,選擇相應平臺的NDK開始下載。

    2.)下載完成后,將NDK解壓到某個文件夾下,打開Android Studio,選擇File->Project Structure

    在彈出來的對話框中,配置NDK路徑,如下所示:

JNI開發(fā)

下面我們就一步一步來完成一個示例,從C語言編寫的程序中獲取字符串,然后在TextView上顯示出來。

  1. 新建一個Android Project,命名為 MyApplication


    注意:項目路徑中不能有空格!

  2. 項目新建完成后,默認為Android視圖,這里為了更清楚的展示,我們切換到Project視圖。



    項目結(jié)構(gòu)如下:


  3. 在項目gradle.properties文件中加上以下代碼,表示我們要使用NDK進行開發(fā)。

android.useDeprecatedNdk=true
  1. 在項目local.properties中加入ndk和sdk的路徑:
sdk.dir=/Users/用戶名/android-sdk-macosx
ndk.dir=/Users/用戶名/android-sdk-macosx/ndk-bundle
  1. 在app文件夾下的build.gradle中的defaultConfig里加入如下代碼
ndk{    
      moduleName "hello"       //生成的so文件名字,調(diào)用C程序的代碼中會用到該名字    
      abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種平臺下的so庫
}

如下所示:


  1. 打開布局文件activity_main.xml,我們來添加一個TextView顯示從C程序中返回的字符串
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    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="me.jockio.myapplication.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp" />
</RelativeLayout>
  1. 打開MainActivity.java,添加如下代碼:
public class MainActivity extends AppCompatActivity {

    //固定寫法,表示我們要加載的資源文件為libhello.so
    static {
        System.loadLibrary("hello");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = (TextView) findViewById(R.id.textView);
        textView.setText(getStringFromNative());
    }

    //聲明一個本地方法,用native關(guān)鍵字修飾
    public native String getStringFromNative();
}
  1. 生成.h頭文件
    打開Android Studio底部的Terminal,默認命令行窗口路徑已經(jīng)在當前項目,輸入以下命令:
cd app/src/main/java
javah -jni 包名+類名

執(zhí)行完上面兩條命令后,會自動生成.h文件



生成.h文件內(nèi)容如下:



這里關(guān)鍵部分就是:
JNIEXPORT jstring JNICALL Java_me_jockio_myapplication_MainActivity_getStringFromNative  (JNIEnv *, jobject);
  1. 新建jni文件夾,并拷貝上面生成的.h文件到jni目錄
    選擇File->New->Folder->JNI Folder


    在彈出的對話框中勾選Change Folder Location,并在下面輸入文件夾名,如下圖所示:

  2. 在jni目錄下,右鍵新建C文件,文件名任意,輸入如下內(nèi)容:

//引入上面生成的頭文件,并實現(xiàn)頭文件中聲明的方法
#include "me_jockio_myapplication_MainActivity.h"
JNIEXPORT jstring JNICALL Java_me_jockio_myapplication_MainActivity_getStringFromNative
        (JNIEnv *env, jobject obj){
    char *str="String from native C";
    return (*env)->NewStringUTF(env, str);
}

注意觀察函數(shù)方法名為:Java_包名_類名_方法名,了解到這些后我們以后就可以不生成.h文件,而是直接去寫.c文件了。

  1. 選擇 Build->Make Project,看app/build/intermediates/ndk/debug/lib目錄下是否生成.so文件,如果沒有生成,選擇 Build->Clean Project,等clean完成后,再Build->Rebuild Project,一般經(jīng)過上面兩步以后都能夠解決問題。


  2. 打開模擬器,運行Android程序。這里可以看到已經(jīng)從libhello.so文件中讀取到字符串,并顯示在了TextView中。


參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容