天天看點

在Android Studio中使用Jni

前提:

NDK環境已經搭建好,

windows下需要安裝cygwim

android studio指向正确的ndk

在Android Studio中使用Jni

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

在Android Studio中使用Jni

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檔案夾

在Android Studio中使用Jni

在jni檔案夾下建立c檔案和h檔案

在Android Studio中使用Jni

編輯.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.mk和Application.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的環境

在Android Studio中使用Jni

這樣so檔案會在libs目錄下生成

在Android Studio中使用Jni

修改jni的庫目錄 

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

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

修改 gradle->gradle.properties

在檔案的最末行添加:

android.useDeprecatedNdk=true      

最後運作app,就能出現來自c檔案的字元串了。