• Android studio 使用NDK工具实现JNI编程


    前言:

    Android开发中常常会使用到第三方的.so库。在使用.so库的时候就要用到JNI编程。JNI是Java Native Interface的缩写。它提供了若干的API实现了Java和其它语言的通信(主要是C&C++)。开发中一般都用第三方的库,非常多时候也可能我们自己来编写C或者C++来实现JNI编程,这篇博客主要是介绍Android studio 使用NDK工具来开发JNI编程。

    环境配置

    JNI编程须要满足例如以下前提:

    1. 你必须有安装Android studio开发idea编辑器(本人使用的是android studio 1.3版本号)。

    2. 下载最新版本号的NDK工具,然后解压到一个文件夹就可以(配置NDK环境变量时使用到该路径)。

      我的ndk版本号为 android-ndk-r10e

    3. 配置ndk环境变量,计算机–>属性–>高级系统设置–>环境变量–>系统变量–>新建 变量名:NDK_ROOT;变量值:F:AndroidSDK1android2android-ndk-r10e(此处是我的ndk路径。换成你自己的ndk路径就可以)。

    4. 当然前提是你要配置了jdk环境变量,配置如同第三点:变量名:JAVA_HOME;变量值:F:AndroidSDK1android2Javajdk1.7.0_67(此处是我的jdk路径。换成你自己的jdk路径就可以)。

      除此之外,你还得新建一个CLASSPATH环境变量,变量名:CLASSPATH;变量值为 .;%HOME_PATH%lib; 一開始的 . 和;和最后的;都是须要的。

    5. 你还须要在gradle.progerties文件下加入例如以下代码
    android.useDeprecatedNdk=true

    假设没有gradle.progerties文件,请直接在当前project下新建该文件就可以。

    JNI编程

    1.新建JniUtils类。用来调用jni方法。代码例如以下:

    package com.example.xjp.myjnidmoe;
    
    public class JniUtils {
    //载入静态库
        static {
            System.loadLibrary("Test");//此处载入的是对应的模块库,名称必须和 ndk的moduleName名一样。
        }
    //定义本地方法
        public native String getValue();
    }

    2.Build 编译当前project,最后会在build文件夹下生成例如以下文件
    这里写图片描写叙述
    该文件夹下生成了 JniUtils.class文件。

    然后打开AS的Terminal终端,跳到debug文件夹下:这里写图片描写叙述
    然后运行 javah -jni *(此处为你的目标文件路径。即JniUtils路径)
    这里写图片描写叙述
    最后会在debug文件夹以下生成 com_example_xjp_myjnidmoe_JniUtils.h 头文件。代码例如以下:

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_example_xjp_myjnidmoe_JniUtils */
    
    #ifndef _Included_com_example_xjp_myjnidmoe_JniUtils
    #define _Included_com_example_xjp_myjnidmoe_JniUtils
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_example_xjp_myjnidmoe_JniUtils
     * Method:    getValue
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_example_xjp_myjnidmoe_JniUtils_getValue
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    以上代码是自己主动生成的,无需开发人员去改动。

    3.在你的main文件夹下新建jni子文件夹。例如以下:这里写图片描写叙述
    将刚才生成的 .h头文件拷贝到该jni文件夹下。然后新建一个 test.c文件,test.c文件代码例如以下:

    //
    // Created by 850302 on 2016/4/26.
    //
    
    #include "com_example_xjp_myjnidmoe_JniUtils.h"
    
    JNIEXPORT jstring JNICALL Java_com_example_xjp_myjnidmoe_JniUtils_getValue
            (JNIEnv *env, jobject obj) {
        return (*env)->NewStringUTF(env, "This is my first JNI demo!");
    }

    因为jni编程对方法的名称有一定规则要求。开头须要Java_ 后面依次是jni方法的java类路径。以“_”切割。

    开发人员为了不写错,能够直接将刚才的.h头文件中的方法 copy下来直接实现就可以。

    4.配置Gradle文件
    首先你得配置当前project的 build.gradle文件,事实上配置非常easy,直接在原来的build.gradle文件中加入 ndk的配置就可以。

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 23
        buildToolsVersion "22.0.1"
    
        defaultConfig {
            applicationId "com.example.xjp.myjnidmoe"
            minSdkVersion 21
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
    
            //这里是配置ndk
            ndk{
                //定义库的模块名称。该名称用于System.loadLibrary("Test")
                moduleName "Test" 
            }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
    }
    

    是不是非常easy。不过定义了 ndk 的moduleName的名称而已。

    其次是为当前project配置指定的ndk,配置方法例如以下:右键当前project名。选择Open Module Settings。弹出例如以下窗体。这里写图片描写叙述
    如图。1:sdk路径;2:jdk路径。3:ndk路径;点击ok之后。

    会在local.properties文件下配置指定的sdk和ndk路径:

    #Tue Apr 26 18:36:18 CST 2016
    ndk.dir=F:\Android\SDK1\android2\android-ndk-r10e
    sdk.dir=F:\Android\SDK1\android2\sdk

    如此,全部的准备工作都已经完毕。如今能够在你的代码中使用Test库了,调用代码例如以下:

    @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            TextView textView = (TextView) findViewById(R.id.text);
    
            //start=====
            JniUtils jniUtils = new JniUtils();
            String content = jniUtils.getValue();
            //end=====
            textView.setText(content);
    
        }

    结果例如以下:这里写图片描写叙述

    可能会有人问。代码生成的libTest.so库在哪里呢?事实上生成的libTest.so库已经打包到apk中去了,那么假如我要把这个so库给别人使用怎么办?非常easy,在你编译的过程事实上已经生成了libTest.so,在哪里呢?文件夹例如以下:bulid/intermediates/ndk文件夹下。该文件夹是编译成功之后生成的。

    这里写图片描写叙述
    看到没?生成了不同平台下的libTest.so库。

    总结

    该博客主要是记录Android studio 下使用NDK工具实现JNI编程和生成so库的整个过程。以便开发人员了解JNI编程的一个完整的过程。

  • 相关阅读:
    请简单说一下你了解的端口及对应的服务?
    地址解析协议ARP和逆地址解析协议RARP
    IP地址分类
    OSI分层和五层协议
    对象如何晋升到老年代?
    JVM 垃圾回收机制,何时触发 MinorGC 等操作
    什么是引用?
    类加载机制
    Solaris10怎么创建flash archive
    RPC: program not registered (ZT)
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7338966.html
Copyright © 2020-2023  润新知