Android NDK編譯

記錄下ndk如何編譯.so文件 循序漸進的說下:  首先下載NDK,這個我是直接在Android studio裏面下載的,也沒去官網下載,下載好了,就是配置環境變量了,由於我是從Android studio裏面下載的,因此就直接在path中配置D:android_sdk/ndk-bundle這個路徑了,配好了後咱們能夠用ndk-build去cmd命令臺檢測下看下是否配置成功  接下來就是在Android studio中配置了,須要在sdklocation中配置下,還有local.properties以及gradle.properties中去配置,具體配置網上一大堆,這裏沒有難點  首先咱們想要打出一個.so文件來,咱們確定是要先寫Java代碼java

第一步: 解釋一下這裏代碼的意思:  native這個就是咱們提供出去的方法,這個方法到時候要和.c文件裏面或者.cc文件裏面的方法名一致,咱們再靜態中去加載咱們打出來的.so文件, 這裏的參數名字不是.so文件的名字,而是咱們在打包的時候配置的名字,這個配置下面介紹android

public class JniKit {
    //這裏的方法名若是報錯那是正常的,不影響
    public static native int calculate(int num);

    static {
        System.loadLibrary("JniDemo");
    }
}
複製代碼

第二步:  咱們須要根據這個寫好的Java文件來生成一個.h文件,生成.h文件是經過javah來執行的,這裏我以前嘗試了各類辦法,可是網上說的辦法都沒辦法成功,都是報錯說找不到類文件,我以爲這裏可能和個人文件的方法有點問題,等會我把我如今成功的文件目錄貼出來,執行的代碼bash

javah -classpath D:\360PhoneInfo\small-video-record-master\SmallVideoRecord2\testndk\build\intermediates\classes\debug -d jni
 com.example.testndk.JniKit
複製代碼

根據這個代碼我獲得了.h文件,包括這個jni文件夾也是經過-d jni這個生成出來的,不是本身建立的 app

這裏寫圖片描述

第三步:  如今咱們有了.h文件了,接下來就是寫.c文件了,固然了我不會c語言,因此這裏拿了一個測試的來用,c這部分的不用關注太多 include中指向你建立的.h頭文件 Java_com_example_testndk_JniKit_calculate;Java_包名_類名_方法名(參數)ide

#include "com_example_testndk_JniKit.h"

JNIEXPORT jint JNICALL Java_com_example_testndk_JniKit_calculate(JNIEnv *env, jclass cls, jint num) {
    return num * num;
}
複製代碼

第四步:  如今.h.c文件咱們都有了,接下來就是最關鍵的一步了,生成.so文件了,這一步,我查閱了不少資料,折磨了兩個小時,才弄出來,這裏我不知道是否是個人配置有問題,仍是什麼問題,反正我在build.gradle配置,而後去Make Project生成了好久沒有生成出來,這裏我是用命令行中的ndk-build來解決的測試

解決方式以下:
 1.創建一個Android.mk文件 LOCAL_MODULE表示模塊名稱 LOCAL_SRC_FILES表示須要參與編譯的源文件,就是咱們的c 除了這兩個,其餘照搬便可gradle

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

LOCAL_MODULE := JniDemo
LOCAL_SRC_FILES := jni_test.c
LOCAL_LDLIBS +=-L$(SYSROOT)/usr/lib -lm -llog
include $(BUILD_SHARED_LIBRARY)
複製代碼

2.創建一個Application.mk文件  須要注意的東西都寫在裏面了,以逗號分割cpu指令ui

APP_STL := gnustl_static  
APP_CPPFLAGS := -frtti -fexceptions  
APP_ABI := armeabi-v7a       #這句是設置生成的cpu指令類型,提示,目前絕大部分安卓手機支持armeabi,libs下太多類型,編譯進去 apk 包會過大 
APP_PLATFORM := android-8    #這句是設置最低安卓平臺,能夠不弄 
複製代碼

3.由於個人這兩個文件是和.h.c放在同一個文件夾中-jni,因此咱們要執行ndk-build命令須要進入到jni文件夾下再去執行,好比說D:\360PhoneInfo\small-video-record-master\SmallVideoRecord2\testndk\src\main\jni>ndk-build 如此執行完後就會在 main目錄下生成一個libs文件夾,裏面有咱們配置好的.so文件 ,以下: spa

這裏寫圖片描述
好了,大功告成,測試下吧,我新建了一個工程,將.so包都拷過去了,還有Jnikit.Java文件也拷過去了,由於這是咱們當初定義的Java文件,必須拷過去嘛,這裏要注意的是,移到其餘項目使用,必須把含有native方法的java文件放在與生成so文件的同包名下,也就是說咱們當初在打.h文件時候是什麼包路徑,如今也應該是,我把我測試工程的路徑貼上
這裏寫圖片描述
這裏能夠看到個人Jnikit以前就是在com.example.testndk包下的,如今也是在這個包下,而後就是在build.gradle中配置了,這個配置不難

sourceSets {//在Android的根目錄下配置
        main {
            //你的源碼目錄
            jniLibs.srcDirs  'src/main/libs'
        }
    }
複製代碼

接下來我把我成功調用了的方法貼出來命令行

package com.example.test;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.example.testndk.JniKit;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView viewById = (TextView) findViewById(R.id.tv);
         findViewById (R.id.btn).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 try {
                     int i=JniKit.calculate(4);
                     Log.w("aaa", "---"+i);
                     viewById.setText(i+"");
                 } catch (Exception e) {
                     Log.w("aaa", "---"+e.toString());
                 }
             }
         });

    }
}
複製代碼
相關文章
相關標籤/搜索