前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android NDK的初步认识(Android Studio 2.2 + CMake)

Android NDK的初步认识(Android Studio 2.2 + CMake)

作者头像
胖虎哥
发布2023-05-10 19:04:27
2330
发布2023-05-10 19:04:27
举报
文章被收录于专栏:胖虎的研发之路

序言: 做NDK开发也有一段时间了,还记得初学的时候各种找大神、搜教程,最后在诸多大神的帮助下,成功的做出了我的第一个NDK小玩意,很感谢他们,而后慢慢的越入越深(keng),今天在群里看到了很多像我之前那样各种找问题的哥们,感受颇多,遂写下此文章,给那些新入坑的哥们一些方向。

1.什么是JNI?

代码语言:javascript
复制
    java Native Interface (JNI) 标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互(一般是C/C++、汇编语言)。
    JNI是本地编程接口, 它使得Java虚拟机(VM)内部运行的Java代码能够与用其他编程语言编写的应用程序和库进行交互操作。

众所周知,由于Android 的应用层的类都市以Java写的, 这些Java类编译成dex形式的bytecode之后,必须依靠Dalvik虚拟机(vm)来执行。此外,在执行Java类的过程中,如果Java类需要与C组件进行沟通的话,那么jvm就会通过jni去调用c组件的函数,这就是jni的作用。

2.主要应用场景

代码语言:javascript
复制
1.要求高精度、高敏感的需求;
2.代码的保密性;
3.图片的渲染;
4.游戏复杂算法的实现。

其实主要就是两点: 安全,效率, 最起码我认为是这样的,如果你有不同的想法,欢迎前来探(si)讨(bi),好了废话不多话了,一起来学习吧。

3.实践步骤

本文是基于 Android Studio 2.2+CMake实现的, 如果你不是的话也可以做个参考,仅限参考,出事概不负责哦。

代码语言:javascript
复制
首先去新建一个Android项目,注意填写好名称,下面的勾勾不要打。

然后填写完成之后,点击下一步,这个时候如果你是新手的话,就什么也不要选,有经验的我就不多说了。

然后再去选择一个空的,不要随意乱点,不然处理起来就会很麻烦,继续下一步。

继续下一步,这是给你的主界面起名字的,我们先叫这个。

然后你就来到了程序开发的主界面,点击新建folder→jnifolder

完成之后就会如下图所示,建议不要动,这意思是说,你的文件将产生在什么地方,我们就默认给他一个就好了。

然后点击确定你就会看到出现了一个新的文件夹(cpp):

然后选中此文件夹,右键新建;

随意起个名,我们给他起一个jni,建议你也起的跟我一样,后续还要进行一系列的操作,以防出现不必要的问题,要注意的是下面勾勾也要选上,这是生成头文件。

之后点击确定,会出现两个文件,现在我们不要去管他,去jni目录之下新建一个txt文件CMakeLists.txt

内容如下

代码语言:javascript
复制
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib
             # 这个是jni编译生产的so库的名字
             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             # 要编译的c/c++文件列表 文件路径想对于cmake文件路径
             ./jni.cpp )  

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib
              # 依赖的系统so库
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib    //要生成的名字so

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

完成之后,点击项目右键,选中link c++…

然后跳转到 如下界面,这个的意思主要是说,让你找到你刚才写的txt文件在哪, 然后点击确定,

然后等待系统同步完成,完成之后我们的jni算是构建完成了。

开始写代码

首先是java代码, 我们在main里面要写好;

代码语言:javascript
复制
   private TextView Stram;

    //静态代码块,会首先执行
    static {
        /*
        加载生成的动态库,动态库加载的时候,Jni_onLoad 函数(c中的函数)会被调用
        在C函数中,java虚拟机通过函数表的形式将JNI函数和java类中Native函数对应起来,(两个名字必须一致)
         */
        System.loadLibrary("native-lib");//这个参数跟刚才我们写的txt文本中的native相同
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Stram= (TextView) findViewById(R.id.Stram);

        Stram.setText(getStramInfo());

    }

    // native 代表的就是本地方法
    private static native String getStramInfo ();

然后是 cpp代码 :

代码语言:javascript
复制
//
// Created by chason on 2017/2/17 0017.
//

#include "jni.h"

//                                 尤其注意: 找到与之相关联的java代码。
#define JNI_AN_MainActivity        "com/cn/chason/mndkdemo/MainActivity"

#define METHOD_NUM 1
JNINativeMethod g_nativeMethod[METHOD_NUM]={
        {"getStramInfo","()Ljava/lang/String;",(void*)getStramInfo}
};

/*
 * 被虚拟机自动调用, JNI_OnLoad  被虚拟机自动调用
 */
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK)
        return JNI_ERR;

    jclass jClass = env->FindClass(JNI_AN_MainActivity);
    env->RegisterNatives(jClass,g_nativeMethod,METHOD_NUM);
    env->DeleteLocalRef(jClass);
    return JNI_VERSION_1_6;
}

void JNI_OnUnload(JavaVM* vm, void* reserved) {
    JNIEnv *env;
    int nJNIVersionOK = vm->GetEnv((void **)&env, JNI_VERSION_1_6) ;
    jclass jClass = env->FindClass(JNI_AN_MainActivity);
    env->UnregisterNatives(jClass);
    env->DeleteLocalRef(jClass);
}

//具体实现 
jstring getStramInfo(JNIEnv *env, jobject callObj)
{
    return env->NewStringUTF("String From Jni With c++");
}

然后是 头文件 : .h

代码语言:javascript
复制
//
// Created by chason on 2017/2/17 0017.
//

#ifndef NDKDEMO_JNI_LIB_H
#define NDKDEMO_JNI_LIB_H
#include "jni.h"
//这个方法就是我们的本地方法,切记方法名要相同。
jstring getStramInfo(JNIEnv* env,jobject callObj);
#endif //NDKDEMO_JNI_LIB_H

然后去美美哒运行吧, 至此我们的基本认识算是完成了,如图;

github Demo 地址: https://github.com/ichason/NDKDemo

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-02-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.什么是JNI?
  • 2.主要应用场景
  • 3.实践步骤
    • 开始写代码
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档