Android Studio之NDK環境搭建,so文件打包以及使用

關于ndk,jni的介紹請自行谷歌、百度。推薦查看網友的ndk系列文章,寫的較為詳細,深入 Android NDK開發 (該系列教程開發環境為win + Eclipse)

本篇入門教程開發環境為mac + Android Studio + gradle 2.14.1,主要包含以下3塊內容:

  • NDK環境搭建
  • 編寫第一個JNI項目
  • 打包出動態so文件,在其他項目中使用

一、NDK環境搭建

  1. 從Android Studio安裝(自行F墻)
    打開AndroidStudio,選擇頂部工具條,Tools->Android->SDK Manager->SDK Tools->NDK 點擊install
  2. 自行下載ndk包

    1)國內推薦通過 AndroidDevTools鏡像 下載,或者Google的官方網站下載Android NDK的安裝包 https://developer.android.com/ndk/downloads/index.html

    NDK r13b

    2)下載ndk包后解析到某個路徑,打開Project Structure->設置 NDK location

    AndroidDevTools 下載

  3. ndk環境變量配置,我們需要使用到ndk-build命令
    打開終端 -> 輸入 :vim ~/.bash_profile -> 加入ndk 包的路徑(mac中環境變量之間以封號隔開)

自此,ndk開發環境我們已經可以進行jni開發了

二、JNI開發

  1. 創建android項目
  2. 查看項目local.properties中加入ndk和sdk的路徑是否正確
    ndk.dir=/Users/userName/AndroidStudioProjects/ndk/android-ndk-r13b
    sdk.dir=/Users/userName/Library/Android/sdk
  3. 配置項目下的gradle.properties文件,表示我們要使用NDK進行開發。
    android.useDeprecatedNdk=true
  4. 在moudle根目錄下的的build.gradle中的defaultConfig標簽內部里加入如下代碼
    ndk{    
    moduleName "hello"       //生成的so文件名字,調用C程序的代碼中會用到該名字    
    abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種平臺下的so庫,
    // 還可以添加 'x86_64', 'mips', 'mips64'
    }
  5. 編寫jni代碼

    package com.david.ndktest;
    -
    public class MainActivity extends AppCompatActivity {
    
     //使用靜態代碼塊,表示我們要加載的資源文件為libsecret.so
     static {
         System.loadLibrary("secret");
     }
    
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         TextView tv_msg = (TextView) findViewById(R.id.tv_msg);
         tv_msg.setText(stringFromat());
    
     }
     //聲明一個本地方法,用native關鍵字修飾
     public native String stringFromat();
    }
  6. 生成.h頭文件

    直接使用Android Studio 底部的Terminal,默認命令行窗口路徑已經在當前項目,進入到app/src/main/java目錄,輸入以下命令(固定格式:javah -jni 包名+類名)

    javah -jni com.david.ndktest.MainActivity

    為在對應包的根目錄下生成.h文件,熟悉該函數名后,日常開發中可以不用生成.h文件

    生成頭文件

  7. 執行第5部的時候,對應native會提示找不到對應方法,快捷鍵 alt+enter 會生成對應jni文件夾,包含libName.c文件,此處MainActivity中的native方法還是會顯示紅色,但是不影響編譯

    生成.c文件

  8. 編譯項目后會發現app/build中已經生成so文件,并且已經對應的cpu包就是我們在gradle中已經配置的,并且已經調用成功

    build中生成對應so文件

    成功調用native方法

自此我們的第一個JNI項目已經編寫完畢

三、打包出動態so文件,在其他項目中使用

有時候我們的需求是這樣的,我們把一些比較重要的業務邏輯封裝到ndk內部,對java層只暴露接口。我們就需要打包出so文件,并且可能需要在其他項目中使用,下面將介紹so(符合JNI標準)文件的打包,以及在其他項目中如何正確的調用

  • 編寫Android.mk文件,放到jni文件夾根目錄,與.c文件同級
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := secret //lib 名
LOCAL_SRC_FILES := \
    /Users/userName/AndroidStudioProjects/NdkTest/app/src/main/jni/secret.c \ //.c文件名

include $(BUILD_SHARED_LIBRARY)
  • 使用ndk-build命令(需要配置ndk環境變量,參照第一步第3點),生成so文件

    進入到main目錄后在terminal中輸入命令,ndk-build工具便會幫我們打包出所有cpu平臺so文件(目前不知道如何設置需要打包cpu平臺)

    ndk-build

    building so文件

main根目錄下生成lib,obj目錄

  • 其他項目中使用該so文件
    • 拷貝so文件到項目的main/jniLibs目錄
    • ==新建package,包名與類名以及方法名必須與生成so文件的類保持一致!==
    • 使用方法與第二部一致,需要聲明loadLibrary與native方法

  • 調用native方法

    com.keywea.duolintest;
    -
    public class MainActivity extends AppCompatActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         TextView tv_msg = (TextView) findViewById(R.id.tv_msg);
         tv_msg.setText(com.david.ndktest.MainActivity.stringFromat());
    
     }
    }

自此我們已經能夠接入符合JNI標準的so庫,重點在于包名,類名,方法名需要與so庫保持一致,因此我們在提供so庫的時候一定要記錄詳細的交互文檔

 

來自:http://www.jianshu.com/p/fb29ebbf8415

 

 本文由用戶 HeidiMcGuin 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!