zoukankan      html  css  js  c++  java
  • 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 FilesJavajdk1.8.0_25injavah.exe
    Parameters:-v -jni -d $ModuleFileDir$srcmainjni $FileClass$
    Working directory:$SourcepathEntry$
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    设置结果 
    具体设置
    - 设置ndk-build的extend tool

    Program:C:
    dk
    dk-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
  • 相关阅读:
    Java实现 LeetCode 382 链表随机节点
    Java实现 LeetCode 382 链表随机节点
    Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素
    Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素
    Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素
    Java实现 LeetCode 380 常数时间插入、删除和获取随机元素
    Java实现 LeetCode 380 常数时间插入、删除和获取随机元素
    Linux下的iwpriv(iwlist、iwconfig)的简单应用
    OCX控件的注册卸载,以及判断是否注册
    .OCX、.dll文件注册命令Regsvr32的使用
  • 原文地址:https://www.cnblogs.com/jukan/p/6038277.html
Copyright © 2011-2022 走看看