在Android Studio中使用Jni

前提:

NDK環境已經搭建好,

windows下需要安裝cygwim

android studio指向正確的ndk




1、新建一個Android項目, 選擇Empty Activity



2、在MainActivity中定義Native方法

在static語句塊中先加載so庫,這時Android Studio會報錯,先忽略


package com.cxq.jniexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("JNI",printHello());
    }

    // 新定義的native方法,意思是該方法的具體實現交給c語言實現
    public native String printHello();

    // 加載libprintHello.so動態庫,但是我們在加載時必須去掉lib和後綴
    static {
        System.loadLibrary("printHello");
    }
}


3、創建jni文件夾,以及.c/.cpp文件和.h文件

將視圖切換至Project下,在app\src\main\目錄下創建jni文件夾




在jni文件夾下創建c文件和h文件



編輯.c文件如下:

// 引入頭文件
#include <stdio.h>
#include <jni.h>
#include "printHello.h"


// 定義在MainActivity.java類中的printHello對應的C語言函數
jstring Java_com_cxq_jniexample_MainActivity_printHello(JNIEnv* env, jobject obj){
    char* str = "this hello is from jni";
    // 調用 jni.h中定義的創建字符串函數
    jstring string = (*(*env)).NewStringUTF(env, str);
    return string;
}


說明

1、jstring是方法返回值類型,我們可以把jstring看成是java中String跟C語言中char*類型的一箇中間轉換類型,  

2、方法的命名規則  


Java_[pkgName]_[className]_[funcName]  


pkgName:你的包名,但是不能含".",將其替換爲“_”  

className:用到native方法的類名  

funcName:native方法名  

3、方法的形參有兩個是必須的也就是不管java中的方法是否有形參,但是C語言中對應的方法必須有JNIEnv* env,和jobject obj,  

    如果java方法中還用其他形參,那麼在C語言中嚴格按照順序排在jobject obj參數的後面即可。  



至此,Android Studio的部分已經準備完畢。


4、使用NDK編譯生成hello.so文件


首先so文件是根據mk文件生成的,因此我們需要先準備好mk文件,方便起見,我們直接從NDK安裝目錄的sample/hello-jni/jni目錄複製文件Android.mkApplication.mk


Android.mk的修改

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := printHello
LOCAL_SRC_FILES := printHello.c

include $(BUILD_SHARED_LIBRARY)

說明:

我們只需要修改LOCAL_MODULE和LOCAL_SRC_FILES兩個參數即可。
LOCAL_MODULE參數是指定編譯後的目標文件的名稱,其實編譯好的目標文件名爲libhello.so,
LOCAL_SRC_FILES指定了要編譯的源文件。


Application.mk的修改


通過修改Application.mk文件來指定生成的動態庫的類型:
如按以的修改則只會生成一種動態庫:
# Build both ARMv5TE and ARMv7-A machine code.
APP_ABI := armeabi x86

爲了方便,也可以指定所有類型

APP_ABI := all

下一步使用cygwin(windows)或則終端進入到工程的jni目錄

輸入:

${NDK}/ndk-build.cmd

這一步的前提是你已經配置好了NDK的環境



這樣so文件會在libs目錄下生成



修改jni的庫目錄 


將app->src->main->libs改成app->src->main->jniLibs

注意:每次運行後ndk-build後,都需要修改這個目錄名,否則對動態庫的修改不會生效;


修改 gradle->gradle.properties


在文件的最末行添加:

android.useDeprecatedNdk=true


最後運行app,就能出現來自c文件的字符串了。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章