arvinljw

  • 主页
  • Android
  • Java
  • Python
  • 技术杂谈
所有文章 关于我

arvinljw

  • 主页
  • Android
  • Java
  • Python
  • 技术杂谈

Android JNI开发系列之配置

2018-08-29

在老早以前就想要去接触了解这一块的知识了,奈何在工作中一直都没有机会去接触,就迟迟没有去学习这一块的知识。到现在终于开始去学习了,简单的搜索了一下,都没有太明确的博客去学习,都是很零碎的,而且在最新的版本中也有问题,到最后只能去看官方的文档,当然这才正确的选择,其实一开始就该去看的。废话不多说,这一个系列因为我才开始学习,不知道会有多长,但是会将常用的东西全部总结学习完。

首先来学习一下官方的配置。

一、必要的下载

这一条没啥说的,就是下载一些工具方便开发,当然是在Android Studio中。

对于ndk的开发,需要下载:

  • NDK(Native Development Kit):用来让你调用c或者c++代码的工具
  • cmake:方便在gradle中构建的,不再使用以前的ndk-build(比较麻烦)
  • LLDB:可以调试c或者c++代码的

这三个都可以直接在SDK Manager中去下载(当然也可以手动下载配置好)。目前我使用的版本对应分别是:

1
2
3
NDK : 17.1.4828580
cmake : 3.6.4111459
LLDB : 3.1.4508709

二、在项目中配置NDK

这一点分为两种情况:

  • 新建项目时配置
  • 在已有项目中配置

第一种情况没啥说的,就是在新建项目时,选中第一个界面的include C++ support这个选择框,之后一直默认next(最后finish)即可。

重点是第二种情况,因为大多数在在项目一开始时可能没有想着要使用ndk开发功能,后来需要了,那么就去配置即可。

1、创建cpp文件夹

在已有项目的main目录下创建cpp文件夹

2、创建一个c文件

在cpp文件夹下创建一个c文件,右键->new->c/c++ Source File,例如取名叫做Hello,后缀名为.c,不创建.h文件,点击ok。

注:内部暂时可以不用写代码。

3、创建CMakeLists.txt

在当前module中创建一个CMakeLists.txt文件,右键->new->File,取名叫做CMakeLists.txt,点击ok。加上以下代码:

1
2
3
4
5
6
7
8
9
10
cmake_minimum_required(VERSION 3.4.1)

add_library( # Specifies the name of the library.
Hello

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
src/main/cpp/Hello.c )

add_library方法:

  • 第一个参数:Hello,就是lib的名称,之后在gradle中的ndk ModuleName一致
  • 第二个参数暂时不管
  • 第三个参数要与上文中创建的c文件路径和名字完全相同,后缀相同

4、使用cmake配置gradle关联

选择Android视图,在需要构建的module下,右键->Link C++ Project with Gradle->选择CMakeLists.txt的路径,就是上文中创建的CMakeLists.txt,点击ok。

构建完成,可以看到在当前module下的build.gradle文件中多了以下这段话:

1
2
3
4
5
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}

这时候再在当前的build.gradle中,android模块,defaultConfig下,添加以下代码:

1
2
3
ndk{
moduleName 'Hello'
}

这里的moduleName就是要与CMakeLists.txt中定义的libraryName一致,这里加入叫Hello吧。

到此基本配置就算是完成了。下面就开始写代码,先从java调用c开始。

三、Java调用C代码

1、定义Java方法

到这一步,终于回到熟悉的Java代码,我们在对应的包名中创建一个类,例如取名叫做Hello,加入一个简单的本地方法,只比普通抽象方法多了一个native关键字,如下:

1
public native String stringFromC();

2、定义C方法

这时候这个方法是找不到的,还需要在之前的Hello.c文件中写上对应的方法,如下:

1
2
3
4
5
#include<jni.h>

jstring Java_net_arvin_androidstudy_jni_Hello_stringFromC(JNIEnv *env, jobject instance) {
return (*env)->NewStringUTF(env, "I am from c!");
}

代码不长,以此来解释,首先必须要引入的是jni.h,下边的JNIEnv和jstring,jobject等都是在这里边去定义的。

函数的申明部分,jstring表示在java中定义的String,这个位置也就是返回值,然后Java_net_arvin_androidstudy_jni_Hello_stringFromC这一部分看起来很长其实就是三个部分:Java_类的完全限定名_方法名,只是完全限定名中的点改为了下划线,后边的两个参数env和instance,env是一个环境,用它可以操作Java类,创建字符串之类的;instance就是当前调用这个代码的类的实例,这里就是Hello类的实例。

最后就是函数的实现内容,这里是返回一个字符串然后,看一看env这个变量的类型,JNIEnv的定义可以看到是一个typedef const struct JNINativeInterface* JNIEnv;。本身就是指针,然后在方法中的env又是指针,相当于二级指针,所以调用的时候使用的就是(*env)->函数。

3、Java代码与C代码关联

回到Hello类中,在类中加一段静态初始化的代码:

1
2
3
static {
System.loadLibrary("Hello");
}

其中Hello是上文中在build.gradle中ndk下配置的moduleName。

到这里就可以在其他地方创建Hello类的实例,然后调用stringFromC的方法了。

例如:

1
2
Hello jni = new Hello();
System.out.println(jni.stringFromC());

就会在run tab下看到I am from c!这样一句话的输出。

至此Android JNI开发系列之配置就告一段落了。当然后边肯定还有进一步的配置学习,例如需要引入多个c文件,需要引用其他c++库等,肯定也是需要配置的,那些都会在之后的文章中讲到。

感谢

借鉴官方教程

  • Android

扫一扫,分享到微信

微信分享二维码
Android JNI开发系列之Java与C相互调用
Android学习之RecyclerView.ItemDecoration实践
  1. 1. 一、必要的下载
  2. 2. 二、在项目中配置NDK
    1. 2.1. 1、创建cpp文件夹
    2. 2.2. 2、创建一个c文件
    3. 2.3. 3、创建CMakeLists.txt
    4. 2.4. 4、使用cmake配置gradle关联
  3. 3. 三、Java调用C代码
    1. 3.1. 1、定义Java方法
    2. 3.2. 2、定义C方法
    3. 3.3. 3、Java代码与C代码关联
  4. 4. 感谢
Like Issue Page
Error: Comments Not Initialized
Login with GitHub
Styling with Markdown is supported
Powered by Gitment
© 2019 arvinljw
Hexo Theme Yilia by Litten
  • 所有文章
  • 关于我

tag:

  • Android
  • 项目经验
  • Java
  • 《Effective Java》
  • 开源库
  • 源码分析
  • 《Thinking in Java》
  • 技术杂谈
  • sql
  • FFmpeg交叉编译
  • Python
  • Scrapy爬虫
  • 数据分析
  • git操作

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • Mac下交叉编译FFmpeg3.4.5出Android的so包

    2019-01-10

    #技术杂谈#FFmpeg交叉编译

  • Android开源之PermissionHelper

    2018-09-19

    #Android#开源库

  • Java之类和接口

    2018-09-03

    #Java#《Effective Java》

  • Android JNI开发系列之Java与C相互调用

    2018-08-31

    #Android

  • Android JNI开发系列之配置

    2018-08-29

    #Android

  • Android学习之RecyclerView.ItemDecoration实践

    2018-07-26

    #Android#开源库

  • MySQL基础语句

    2018-07-18

    #技术杂谈#sql

  • Android学习之联系人列表

    2018-07-12

    #Android

  • git常用操作

    2018-07-04

    #技术杂谈#git操作

  • Android学习之ConstraintLayout

    2018-06-26

    #Android

  • Java之字符串

    2018-06-25

    #Java#《Thinking in Java》

  • Java之类的通用方法

    2018-06-23

    #Java#《Effective Java》

  • Python抓取QQ音乐歌单并分析

    2018-06-20

    #Python#Scrapy爬虫#数据分析

  • Java之接口和内部类

    2018-06-14

    #Java#《Thinking in Java》

  • Java之多态

    2018-06-12

    #Java#《Thinking in Java》

  • Python生成词云

    2018-06-11

    #Python

  • Java之复用类

    2018-06-06

    #Java#《Thinking in Java》

  • Java之操作符、流程控制、初始化和清理以及访问权限控制

    2018-06-05

    #Java#《Thinking in Java》

  • Java之对象的创建和销毁

    2018-06-03

    #Java#《Effective Java》

  • Java之一切皆对象

    2018-05-30

    #Java#《Thinking in Java》

  • Android源码分析之PhotoView

    2017-12-28

    #Android#源码分析

  • Android开源之SocialHelper

    2017-12-01

    #Android#开源库

  • Android动态更换桌面图标

    2017-10-10

    #Android

  • Android之ViewPager使用

    2017-06-05

    #Android

  • Android代码混淆

    2017-04-10

    #Android

  • Android消息机制

    2017-02-20

    #Android

  • Android之Activity总结

    2016-11-19

    #Android

热爱Android开发
喜欢学习新技术...

有问题可以给我发邮件~