NDK开发入门(二)

1. 基本项目的介绍

1.1 项目结构

1.1.1 项目目录结构

  新建带C++支持的项目自动生成的目录结构,没什么好说的。切到Project模式的目录结构下,主要说两点。

  • 根目录->app->.externalNativeBuild->cmake->debug->armeabi-v7a->cmake_build_command.txt.可以查看编译命令。
  • 根目录->app->build->intermediates->cmake->debug->obj->armeabi-v7a可以查看本地cpp文件生成的so库。

1.1.2 cpp文件的集成方式

  在app目录下的build.gradle定义了外部构建工具,且指定了相应配置文件CMakeLists的路径。
基本的项目结构及作用
  在cpp文件加入构建后,才使Java层能找到native层的具体实现。

1.2 各个文件的说明

1.2.1 MainActivity.java

package com.txs.ndktest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    //在类加载的时候加载名为native-lib的库
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 调用native方法
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * native方法
     */
    public native String stringFromJNI();
}

  在这个文件中,加载了名为native-lib动态链接库,而且写在了static代码块中,对于static代码块中的内容,jvm会在加载类的时候执行,并且仅执行一次。也就是说保证在进行调用时,native方法已经被加载进JVM了。

1.2.2 CMakeLists.txt




# 设置编译所需的cmake的最小版本号
cmake_minimum_required(VERSION 3.4.1)

# 设置需编译的库名称以及所涉及的源文件
add_library( # 设置库的名称
        native-lib

        # 设置库是静态链接库STATIC还是动态链接库SHARED
        SHARED

        # 提供相关的源文档文件们,如果属于同一个功能模块建议放在同一个
        native-lib.cpp
        )

#设置预编译系统库

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# 将多个库连接到 native-lib,第一个库为目标库,将其他库连接到目标库上

target_link_libraries( # 目标库.
        native-lib
        # 后续可以添加好多连接在上面的库,但是第一个为 
        # System.loadLibrary("native-lib")加载的库名称。  
        ${log-lib})

1.2.3 native-lib.cpp

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_txs_ndktest_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
  • 在这个文件中extern "C"关键词代表了后续的编译方式都采用c语言的编译方式进行编译。这是因为C++在进行编译的时候会对函数名称进行一定程度的重命名。C++存在着重载机制,故而对于同名函数要进行一定的区分,所以会在函数名前加一些前缀区分。对这个有兴趣的同学可以查看一下,C++的符号修饰与函数签名。
  • 因为在native层的函数名是需要有映射的,所以不能让编译器给函数改名字,这也是这里extern "C"关键词的作用所在。由于这个特性,所以NDK开发大多也倾向于采用C++,在需要C特性的场景里将代码用extern "C"关键字,示例如下:
extern "C" {
//your c code;
}
  • JNIEXPORT与JNICALL关键字是让JVM能识别这个函数。
  • JNIEnv存着一些与JVM相联系的函数,这个在源码中是一个结构体,在后续章节中会提及。

2. JNI的简略原理

2.1 前置知识点

2.1.1 编译的具体流程

  上图可知,主要包括.dex文件和so库。其中.dex是Java代码生成的字节码,而so库则是C++/C形成的动态链接库。
  这里在回顾一下编译的详细过程。平时我们所提及的编译,包括了预处理,编译和汇编三个过程。

预处理
编译
汇编
.cpp文件&.h文件
.i文件,去掉宏定义等
.s文件,其实由汇编语言构成
.so文件,由二进制机器语言构成

2.1.2 ART(Android Runtime)

  在Lollipop之后,谷歌就已经放弃了Dalvik采用ART模式了,在启用ART模式后,系统在安装应用的时候会进行一次预编译,在安装应用程序时会先将代码转换为机器语言存储在本地,这样在运行程序时就不会每次都进行一次编译了,执行效率也大大提升。DVM是采用just in time的模式进行编译执行,ART是在安装的时候就将他们变成机器语言(以Lollipop为基准,不考虑后续优化),其示意图如下。 对此详见扒一扒Android运行时在这里插入图片描述

2.2 一次代码的执行过程

  下图主要描述了一个工程从构建到运行的大体流程。 在这里插入图片描述

2.2.1 构建后的APK

  首先我们先看一下,APK解压之后都有哪些文件,主要涉及到Java源码编译出的字节码文件和C/C++源码编译出的SO文件。
在这里插入图片描述

2.2.2 安装时所做的工作

  将dex文件翻译成二进制,并引入so库的直接引用。

2.2.3 执行时的动态链接

  在执行代码时进行动态库的链接。

2.3 源码加载so库的具体流程

在这里插入图片描述

3. 参考文献

[1]周志明. 深入理解Java虚拟机[M]. 机械工业出版社, 2013.
[2]https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html
[3]俞甲子, 石凡, 潘爱民. 程序员的自我修养[M]. 电子工业出版社, 2009.

# 高校智慧校园解决方案摘要 智慧校园解决方案是针对高校信息化建设的核心工程,旨在通过物联网技术实现数字化校园的智能化升级。该方案通过融合计算机技术、网络通信技术、数据库技术和IC卡识别技术,初步实现了校园一卡通系统,进而通过人脸识别技术实现了更精准的校园安全管理、生活管理、教务管理和资源管理。 方案包括多个管理系统:智慧校园管理平台、一卡通卡务管理系统、一卡通人脸库管理平台、智能人脸识别消费管理系统、疫情防控管理系统、人脸识别无感识别管理系统、会议签到管理系统、人脸识别通道管理系统和图书馆对接管理系统。这些系统共同构成了智慧校园的信息化基础,通过统一数据库和操作平台,实现了数据共享和信息一致性。 智能人脸识别消费管理系统通过人脸识别终端,在无需接触的情况下快速完成消费支付过程,提升了校园服务效率。疫情防控管理系统利用热成像测温技术、视频智能分析等手段,实现了对校园人员体温监测和疫情信息实时上报,提高了校园公共卫生事件的预防和控制能力。 会议签到管理系统和人脸识别通道管理系统均基于人脸识别技术,实现了会议的快速签到和图书馆等场所的高效通行管理。与图书馆对接管理系统实现了一卡通系统与图书馆管理系统的无缝集成,提升了图书借阅的便捷性。 总体而言,该智慧校园解决方案通过集成的信息化管理系统,提升了校园管理的智能化水平,优化了校园生活体验,增强了校园安全,并提高了教学和科研的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值