快速上手ndk開發! Mac/Win下配置和使用!(2018.4重編版)

目錄

  • 前言
  • ndk環境配置
  • 下載ndk
  • 配置ndk路徑
  • 配置ndk環境路徑
  • ndk上手
  • 實現c函數, 並編譯生成.so
  • 其餘項目使用.so
  • 最後

前言

說下個人AndroidStudio版本是2.3.3, 尚未更新到3.x(手動委屈), 主要仍是想把手頭項目搞定了再跳坑. 而後此次添加了mac平臺的配置, 其實沒多大區別, 固然, linux也是大同小異, 畢竟android studio是通用的. 爲何要使用.so?從我本身的理解出發, 有幾點很是主要:java

  • 你每每不是一我的在開發, 並且你的合做夥伴不可能把全部源碼給你編譯. 因此一個解決方案就是他編譯生成.so給你, 再給你個.h文件, 告訴你有哪些函數.對於這些函數, 你只須要知道功能而不須要知道實現細節.
  • .so文件是依靠c/cpp編譯而成的, c/cpp語言的重要性不言而喻, 歷史地位也是不可撼動的, 並且一些原本已經寫好的庫, 不必說由於要寫Android就換成java從新實現一遍. 因此須要讓Android去支持那些已有的庫.
  • java源碼反編譯一下很容易拿到的, 固然能夠加固apk, 會好一點. 而編譯生成.so以後, c的源碼就很難看到了.

ndk環境配置

有個比較頭痛的事情叫作配環境linux

下載ndk

mac下下載ndk

win下下載ndk

配置ndk路徑

mac下配置ndk路徑

win下配置ndk路徑

配置ndk環境變量

  • mac: 用vim打開.bash_profile, 在最後加入ndk所在路徑.
vim .bash_profile
複製代碼

mac下添加ndk路徑

更新配置文件並測試ndk-build指令android

更新配置並測試

  • win:

win下配置ndk環境變量

加入到PATH你們庭

打開PowerShell測試一下vim

打開PowerShell測試一下

終於能夠開始使用NDK了, 或者你能夠管它叫JNIbash


ndk上手

  • 在包目錄下建立HellJNI類, 並寫入必要代碼

mac下

win下

public class HelloJNI {
    //一個加法函數, 用c實現
    public native int AddC (int a, int b);
    static {
        //加載庫, 注意庫名的一致性
        System.loadLibrary("HelloC");
    }
}
複製代碼

使用javah命令生成頭文件, 注意! 這是重點, 要背!(滑稽臉)而後新建一個同名c/cpp.app

  • mac:

mac下生成頭文件

生成後目錄一欄

生成後目錄一欄

  • win:

使用javah命令生成頭文件

一覽


實現c函數, 並編譯生成.so

  • 拷貝.h文件中生成的函數, 在c/cpp中實現它.
/*
 * Class:     com_so_myapplication_HelloJNI
 * Method:    AddC
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_so_myapplication_HelloJNI_AddC
  (JNIEnv *, jobject, jint, jint);
複製代碼
#include "com_so_myapplication_HelloJNI.h"

JNIEXPORT jint JNICALL Java_com_so_myapplication_HelloJNI_AddC
  (JNIEnv * env, jobject obj, jint a, jint b){
    return a + b;
  }
複製代碼

在jni目錄下建立Android.mk和Application.mk文件並寫入內容, 重點! Android.mk內容以下:ide

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := HelloC
LOCAL_SRC_FILES := com_so_myapplication_HelloJNI.c
LOCAL_SRC_FILES += util.c

include $(BUILD_SHARED_LIBRARY)
複製代碼

有2個要點:函數

  • LOCAL_MODULE的名稱要和以前System.loadLibrary("HelloC");中的名稱一致;
  • Win下須要再加一個空的util.c文件進行編譯, 不然會報錯, 不信能夠試試(手動滑稽), mac/linux下無需. Application.mk內容以下:
APP_ABI := all
#APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a mips64 x86_64
複製代碼

有2個要點:測試

  • 我知道這樣不太專業, 不過這個ABI問題牽扯太多, 暫不細說, 主要是和不一樣cpu有關.
  • armeabi彷佛已被淘汰. 配置build.gradle, 重中之重! 先是build.gradle一覽:
android {
    compileSdkVersion 26
    buildToolsVersion "26.0.3"
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    defaultConfig {
        applicationId "com.so.myapplication"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk {
            moduleName "HelloC" //System.loadLibrary("HelloC");
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
複製代碼

ndk須要配置, 注意名字匹配!gradle

ndk {
    moduleName "HelloC" //System.loadLibrary("HelloC");
}
複製代碼

sourceSets配置

sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}
複製代碼

在gradle.properties中加上一句

android.useDeprecatedNdk=true
複製代碼

而後就是ndk-build了, 再查看是否生成成功!

mac下ndk-build

win下ndk-build

一覽

你能夠在這個項目中使用這個由c實現的加法函數了, 可是咱們有更酷的事情要作, 那就是在__另外的項目__中用這個函數.


其餘項目使用.so

這件事其實沒有很難, 基本靠兩步. 第一步就是將前一個項目生成的libs目錄下的所有內容拷貝到AndroidStudio自帶的libs目錄下

一覽

第二步就是建立一個和前一個生成libs目錄的項目相同的包和類, 類中寫入的內容也是同樣的.順帶加下build.gradle中的sourceSets, 不記得位置, 參考以前的build.gradle一覽.

一覽

public class HelloJNI {
    public native int AddC (int a, int b);
    static {
        System.loadLibrary("HelloC");
    }
}
複製代碼
sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}
複製代碼

最後測試下效果, 這段代碼我就不解釋了, 這看不懂也就告別手錶了!

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv_testc = (TextView) findViewById(R.id.tv_testc);
        tv_testc.setText("add: " + new HelloJNI().AddC(1, 2));
    }
}
複製代碼

測試結果


最後

完結散花! 喜歡記得點贊或者關注我哦, 有問題和意見能夠評論區~~

相關文章
相關標籤/搜索