Android NDK:在Android Studio下的基本开发步骤和基础知识点总结

/* Header for class com_zhuanghongji_ndkdemo_JNITest */

#ifndef _Included_com_zhuanghongji_ndkdemo_JNITest

#define _Included_com_zhuanghongji_ndkdemo_JNITest

#ifdef __cplusplus

extern “C” {

#endif

/*

  • Class: com_zhuanghongji_ndkdemo_JNITest

  • Method: getStringFromJNI

  • Signature: ()Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_com_zhuanghongji_ndkdemo_JNITest_getStringFromJNI

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

上面代码中的JNIEXPORTJNICALL 是jni的宏,在android的jni中不需要,当然写上去也不会有错。从上面的源码中可以看出这个函数名那是相当的长啊。。。。 不过还是很有规律的, 完全按照:java_pacakege_class_mathod 形式来命名。

注意下上面的注释:

/*

  • 1.该方法所在的类

  • Class: com_zhuanghongji_ndkdemo_JNITest

  • 2.该方法所在类中的对应方法

  • Method: getStringFromJNI

  • 3.其中()表示函数的参数为空

  • 其中Ljava/lang/String;表示函数的返回值是java的String对象

  • Signature: ()Ljava/lang/String;

  • 这里为空是指除了JNIEnv *, jobject 这两个参数之外没有其他参数,

  • JNIEnv*, jobject是所有jni函数必有的两个参数,

  • 分别表示jni环境和对应的java类(或对象)本身

*/

6.接着在jni目录下新建一个 .c文件

来实现头文件里面声明的方法。

我自己建立的是:com_zhuanghongji_ndkdemo_JNITest.c

实现代码后,如下:

// include刚才生成的头文件

#include “com_zhuanghongji_ndkdemo_JNITest.h”

JNIEXPORT jstring JNICALL Java_com_zhuanghongji_ndkdemo_JNITest_getStringFromJNI

(JNIEnv *env, jobject obj){

return (*env)->NewStringUTF(env, “I’m native function: getStringFromJNI() !”);

}

注意:在jni下面再建一个空的.c文件,如temp.c

要不编译有问题,谷歌官方有提到这个问题,可能是android studio的一个bug。

7.在 local.properties 文件中设置ndk的路径:

我的是:ndk.dir=C:\\Android\\android-ndk-r10

8.在gradle.properties文件进行配置”使用NDK”

此文件末尾增加代码:android.useDeprecatedNdk=true

9.在app目录下的 build.gradle中设置库文件名(生成的so文件名):

工程*有两个build.gradle配置文件,我们要修改的是在<Project>\app\build.gradle这个文件

找到 defaultConfig 这项,在里面添加如下内容:

ndk{

moduleName “MyJniName” //设置库(so)文件名称,加载时会被用到

ldLibs “log”, “z”, “m” //链接时使用到的库,对应android.mk文件中的LOCAL_LDLIBS

abiFilters “armeabi”, “armeabi-v7a”, “x86” //最终输出指定三种abi体系结构下的so库,目前可有可无

}

这时,再执行”Build->Make Project”,就可以编译出so文件了。

编译出来的库文件被Studio输出到了下图的路径中:

Android NDK:在Android Studio下的基本开发步骤和基础知识点总结

10.在JNITest.java中增加对so的加载:

static {

System.loadLibrary(“MyJniName”);

}

至此:JNITest.java 的完整代码如下:

// JNITest.java

package com.zhuanghongji.ndkdemo;

public class JNITest {

static {

System.loadLibrary(“MyJniName”);

}

public native String getStringFromJNI();

}

11.现在在MainActivity中使用JNITest类的native方法:

package com.zhuanghongji.ndkdemo;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private TextView mTextView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView= (TextView) findViewById(R.id.tv);

String s = new JNITest().getStringFromJNI();

mTextView.setText(s);

}

}

现在运行的话,你就会看到下面的结果:

Android NDK:在Android Studio下的基本开发步骤和基础知识点总结

上面的字符串I'm native function: getStringFromJNI() !是C文件中的

return (*env)->NewStringUTF(env, “I’m native function: getStringFromJNI() !”);

这段代码返回的。

三、基本知识点总结


1.为什么使用NDK

  1. 代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。

  2. 可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。

  3. 提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。

  4. 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

2.NDK简介

  1. NDK是一系列工具的集合
  • NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库。NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

  • NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

  1. NDK提供了一份稳定、功能有限的API头文件声明

Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)标准数学库(libm)压缩库(libz)Log库(liblog)

3.如何编写Android.mk文件

在jni目录下(即hello-jni.c 同级目录下)新建一个Android.mk文件,Android.mk 文件是Android 的 makefile文件。

  • 下面这个文件是官方示例 hello-jni 的makefile文件。

Copyright © 2009 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the “License”);

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an “AS IS” BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hello-jni

LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

  • 这个Androd.mk文件很短,下面我们来逐行解释下:

LOCAL_PATH := $(call my-dir)

一个Android.mk 文件首先必

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数’my-dir’, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。

include $( CLEAR_VARS)

上一篇:“你们程序员不就是修电脑的吗,你牛什么牛,移动应用开发专业就业前景


下一篇:android opencv NDK人脸识别和对比,Android岗面试