Android 開發 DNK開發將.c文件打包成os

前言

  不廢話太多,Java與C之間聯繫的JNI的概念,這個要了解能夠參考下面這個博客:java

  https://www.jianshu.com/p/87ce6f565d37linux

 

  此博客只說明如何將.C文件經過NDK打包成so庫而且使用的一個簡單demo.android

 

第一步 建立用於引用本地os庫的Java工具類

目錄

工具類代碼

package zq.ndkdemo;

public class NDKTools {

    static {
        System.loadLibrary("ndkdemomk-jni");//這裏的"ndkdemomk-jni"是下面.mk文件裏局部模塊的值,這個到後面我會解釋
    }

    public static native String getNDKcontent();//您在Java裏調用so庫的靜態方法
}

 

第二步 將Java工具類打包成.h文件

打開Android studio的Terminal準備用javah打包.h文件, cd進入到app/src/目錄下 而後輸入 javah -o ndkdemoHFile.h -jni -classpath ./main/java/  zq.ndkdemo.NDKTools 命令.(下面會解釋這條命令)

解釋一下這行命令

javah -o ndkdemoHFile.h -jni -classpath ./main/java/  zq.ndkdemo.NDKTools
javah -o 你要打包的.h文件名加後綴 -jni -classpath 中間的路徑  app包名+工具類名

輸入這條命令後,若是沒報錯,你就會在src目錄下得到您的.h文件,以下圖:

打開.h能夠看到:app

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class zq_ndkdemo_NDKTools */

#ifndef _Included_zq_ndkdemo_NDKTools
#define _Included_zq_ndkdemo_NDKTools
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     zq_ndkdemo_NDKTools
 * Method:    getNDKcontent
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_zq_ndkdemo_NDKTools_getNDKcontent
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

 

第三步 建立jni文件夾而且將.h文件移入

在main目錄下建立一個jni文件夾

 

將咱們打包好的.h文件移動到jni文件夾裏

第四步 建立c語言函數文件

進入到jni文件夾裏,點擊建立任意名稱加.c後綴的文件ide

打開寫入代碼以下:函數

#include "ndkdemoHFile.h" 

JNIEXPORT jstring JNICALL Java_zq_ndkdemo_NDKTools_getNDKcontent
  (JNIEnv *env, jobject obj){
     return (*env)->NewStringUTF(env,"Hellow World,這是NDK的第一行代碼");
  }

 注意!代碼裏最好別寫註釋特別是中文註釋.工具

#include "ndkdemoHFile.h" 

這行代碼引用的就是.h文件名稱gradle

 JNIEXPORT jstring JNICALL Java_zq_ndkdemo_NDKTools_getNDKcontent 

這行代碼中 jstring 爲返回值ui

Java_zq_ndkdemo_NDKTools_getNDKcontent  爲 Java + 路徑 + 類名 + 方法名稱
spa

 

第五步 建立.mk文件

 在jni目錄下建立一個叫Android.mk的文件

內容以下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := ndkdemomk-jni

LOCAL_SRC_FILES := ndkdemoCFile.c

include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir)

每一個Android.mk文件必須以定義開始。它用於在開發tree中查找源文件。宏my-dir則由Build System 提供。返回包含Android.mk目錄路徑。

include $(CLEAR_VARS)

CLEAR_VARS變量由Build System提供。並指向一個指定的GNU Makefile,由它負責清理不少LOCAL_xxx。例如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES等等。但不是清理LOCAL_PATH。這個清理是必須的,由於全部的編譯控制文件由同一個GNU Make解析和執行,其變量是全局的。因此清理後才能便面相互影響。

LOCAL_MODULE := ndkdemomk-jni

LOCAL_MODULE模塊必須定義,以表示Android.mk中的每個模塊。名字必須惟一且不包含空格。Build System 會自動添加適當的前綴和後綴。例如,demo,要生成動態庫,則生成libdemo.so。但請注意:若是模塊名字被定義爲libabd,則生成libabc.so。再也不添加前綴。 另外咱們一開始寫的Java工具類裏的System. loadLibrary("ndkdemomk-jni"); 就是這個值

OCAL_SRC_FILES := ndkdemCFile.c

這行代碼表示將要打包的C/C++源碼。沒必要列出頭文件,build System 會自動幫咱們找出依賴文件。缺省的C++ 源碼的擴展名爲.cpp。

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY是Build System提供的一個變量,指向一個GUN Makefile Script。它負責收集自從上次調用 include $(CLEAR_VARS)後的全部LOCAL_xxxxinx。並決定編譯什麼類型
  • BUILD_STATIC_LIBRARY:編譯爲靜態庫
  • BUILD_SHARED_LIBRARY:編譯爲動態庫
  • BUILD_EXECUTABLE:編譯爲Native C 可執行程序
  • BUILD_PREBUILT:該模塊已經預先編譯

第六步 在build.gradle文件裏添加部分代碼

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "zq.ndkdemo"
        minSdkVersion 27
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        
        //須要添加的部分
        ndk{
            moduleName "ndkdemo-jni"
            abiFilters "armeabi-v7a", "x86"
        }


    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        //須要添加的部分
        externalNativeBuild {
            ndkBuild {
                path 'src/main/jni/Android.mk'
            }
        }
        //須要添加的部分
        sourceSets.main {
            jni.srcDirs = []
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
    }
    //須要添加的部分
    sourceSets{
        main {
            jni.srcDirs = []
        }
    }

}

第七步  檢查Android studio是否已經下載配置過ndk

點擊local.properties打開

 
查看是否有ndk
ndk.dir=/media/E/tools/SDK/androidsdklinux/ndk-bundle
sdk.dir=/media/E/tools/SDK/androidsdklinux

若是沒有就須要進入到File >> Settings  裏下載ndk

 

第八步 編譯SO文件

在Android studio的工具欄裏,點擊Build >> clean Project  先清理一下以前的編譯

在點擊Build >> Rebuild Project  從新建立編譯文件

而後能夠打開下圖所示路徑,就能夠看到咱們的so文件了

第九步 調用工具類方法,run APP

public class MainActivity extends AppCompatActivity {
    private TextView mDemoText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDemoText = findViewById(R.id.demo_text);
        String content = NDKTools.getNDKcontent();
        mDemoText.setText(content);
    }
}

運行APP 便可.

相關文章
相關標籤/搜索