Android Studio ndk-Jni開發詳細


http://www.open-open.com/lib/view/open1451917048573.html

Java Native Interface (JNI)標准是java平台的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI 是本地編程接口,它使得在 Java 虛擬機 (VM) 內部運行的 Java 代碼能夠與用其它編程語言(如 C、C++ 和匯編語言)編寫的應用程序和庫進行交互操作。
由於Android的應用層的類都是以Java寫的,這些Java類編譯為Dex型式的Bytecode之后,必須靠Dalvik虛擬機(VM: Virtual Machine)來執行。VM在Android平台里,扮演很重要的角色。
(多的咱不說了,介紹什么的 到處都有可以去搜一下)
咱們先建一個NdkJniDemo的工程

新建工程.png


新建JniUtils類實現native方法

public class JniUtils {    public static native String getStringFormC();
}

build.png


然后clean project 再rebuild project 生成class文件,
這時候打開如下圖的文件夾看是否生成了classes文件夾,沒有生成請重新來過。

文件夾.png


再打開Terminal輸入指令
cd app/build/intermediates/classes/debug
然后再輸入指令
javah -jni com.wobiancao.ndkjnidemo.ndk.JniUtils
注意 這里javah -jni后面跟的是JniUtils類的全路徑,如果javah報不存在之類的,是你的java環境沒有配置好。

Paste_Image.png


這時候打開classes/debug下面的文件發現多了一個文件
com_wobiancao_ndkjnidemo_ndk_JniUtils.h
然后在src/main下新建文件夾jni,把生成的.h文件復制或者剪切到jni文件夾下面去,新建一個c類隨便取一個名字,添加代碼如下

//// Created by XY on 16/1/4.//#include "com_wobiancao_ndkjnidemo_ndk_JniUtils.h"/* 
* Class:     Java_com_wobiancao_ndkjnidemo_ndk_JniUtils 
* Method:    getStringFormC 
* Signature: ()Ljava/lang/String; 
*/JNIEXPORT jstring JNICALL Java_com_wobiancao_ndkjnidemo_ndk_JniUtils_getStringFormC
        (JNIEnv *env, jobject obj){ 
   return (*env)->NewStringUTF(env,"這里是來自c的string");

這里發現頭文件#include <jni.h>報紅色,是因為咱們還沒有配置ndk環境,打開file->project structure
選擇你所下載的ndk環境路徑,如果沒有ndk這里有個地址大家可以去下載 一個安卓工具集合的網站:http://androiddevtools.cn/

Paste_Image.png


設置好了之后,發現頭文件還是紅色的,然后再build一下工程,就會有提示

Error: NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin. For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental. Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.

按着提示做就行了 在gradle.properties文件末尾添加android.useDeprecatedNdk=true就ok啦
然后在app文件下得build.gradle ->defaultConfig括號內添加如下代碼

ndk {    
   moduleName "NdkJniDemo"          //生成的so名字 
   abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫,目前可有可無。}

到了這一步重新build項目,發現已經沒有變紅了。接下來就是運用了,在JniUtils類里面添加如下代碼

static {    
   System.loadLibrary("NdkJniDemo");//之前在build.gradle里面設置的so名字,必須一致}

然后簡單調用就行了,MainActivity代碼如下

public class MainActivity extends AppCompatActivity { 
   TextView textView;    
@Override    protected void onCreate(Bundle savedInstanceState) { 
       super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.ndk_text);
        textView.setText(JniUtils.getStringFormC());
    }
}

運行結果如圖

運行圖.png


咱們打開app->intermediates-ndk-debug發現生成了三個文件夾,並且對應了之前我們在build.gradle配置的abiFilters
大功告成。
新建libs文件夾把這三個文件夾放進去

Paste_Image.png


然后刪除咱們的jni文件試試,是否工程還能運用?
ok 教程完畢
最后出一個利用jni的Aes加密demo運行結果如圖所示

Aes加密.png


項目地址:https://github.com/a12a15a05/NdkJniDemo
謝謝star歡迎點贊=。=轉載請注明來源

 

來自: http://www.jianshu.com/p/d8cde65cb4f7

 

 

Android Studio進行NDK開發筆記

http://blog.csdn.net/enlangs/article/details/51881718

方案一

  • AS自帶的有NDK插件,但是會出現Deprecated錯誤。解決方法:按提示操作即可。
  • AS的NDK插件不需要編寫Application.mk和Android.mk,所以自己編寫的無效!!,關鍵是那插件功能太弱了(很多Android.mk的屬性不能修改)。如果想用自己的mk文件,需要在app/build.gradle中打掉NDK的所有配置。

    android {
    compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "ckm.xxx.testndk" minSdkVersion 19 targetSdkVersion 23 versionCode 1 versionName "1.0" // 如果要使用自己的Application.mk和Android.mk需要修改下面2處。 // 修改1,直接打掉下面配置 // ndk{ // moduleName "test" // abiFilters "armeabi","armeabi-v7a" // } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } // sourceSets { main { jni.srcDirs = ['src/main/jni'] } } // 修改2,需要把jni.srcDirs設置為空。 // sourceSets { // main { // jni.srcDirs = [] // } // } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 自動生成頭文件,在extend tool中增加配置: 
    位置1
    參數內容:

Program:C:\Program Files\Java\jdk1.8.0_25\bin\javah.exe Parameters:-v -jni -d $ModuleFileDir$\src\main\jni $FileClass$ Working directory:$SourcepathEntry$
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

設置結果 
具體設置
- 設置ndk-build的extend tool

Program:C:\ndk\ndk-build.cmd Parameters:NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1 Working directory:$SourcepathEntry$
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

最終結果:這里寫圖片描述

疑惑:

  • 我不相信AS不支持mk文件(只能當做文本文件識別),肯定有地方設置,還為找到設置地方。

注意:

如果按照上面的方式使用自定義Android.mk那么AS將無法識別到native函數。

方案二

來源:http://stackoverflow.com/questions/21096819/jni-and-gradle-in-android-studio

此方案主要是直接修改build.gradle

apply plugin: 'com.android.application' android { compileSdkVersion 14 buildToolsVersion "20.0.0" defaultConfig { applicationId "com.example.application" minSdkVersion 14 targetSdkVersion 14 ndk { moduleName "YourModuleName" } } sourceSets.main { jni.srcDirs = [] // This prevents the auto generation of Android.mk jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project. } task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = android.ndkDirectory commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } task cleanNative(type: Exec, description: 'Clean JNI object files') { def ndkDir = android.ndkDirectory commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative } } dependencies { compile 'com.android.support:support-v4:20.0.0' }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

參考:圖片和extend tool設置都來自這位博主,非常感謝。

參考(請同事寫了段代碼處理下):

#!/bin/sh

for arg in "$@" do if [[ $arg == NDK_PROJECT_PATH=* ]];then param1=`echo $arg | awk -F = '{printf $1}'` elif [[ $arg == APP_BUILD_SCRIPT=* ]];then param2=`echo $arg | awk -F = '{printf $2}'` else param="$param $arg" fi done #echo $param2 param2=`echo $param2 | sed 's#build/intermediates/ndk/debug/Android.mk#src/main#g'` #echo $param2 #echo "" if [[ -n "$param1" ]] && [[ -n "$param2" ]] then param1="$param1=$param2" param="$param1 $param" fi DIR="$(cd "$(dirname "$0")" && pwd)" $DIR/build/ndk-build $param


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM