android 集成NDK jni 讲解 笔记

官方ndk下载地址 :https://developer.android.google.cn/ndk/downloads/

 

正文

说到NDK,相信大家都不陌生,它是Google为便于Android开发提供的一种原生开发集:NativeNDKDevelopment Kit,而且也是一个包含API、构建工具、交叉编译、调试器、文档示例等一系列的工具集,可以帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成APK。

与NDK密切相关的另一个词汇则是JNI,它是NDK开发中的枢纽,Java与底层交互绝大多数都是通过它来完成的,那么接下来看看什么是JNI?

JNI:Java Native Interface 也就是java本地接口,它是一个协议,这个协议用来沟通java代码和本地代码(c/c++)。通过这个协议,Java类的某些方法可以使用原生实现,同时让它们可以像普通的Java方法一样被调用和使用,而原生方法也可以使用Java对象,调用和使用Java方法。也就是说,使用JNI这种协议可以实现:java代码调用c/c++代码,而c/c++代码也可以调用java代码。

那为什么要使用NDK开发呢?

    我们都知道,java是半解释型语言,很容易被反汇编后拿到源代码文件,在开发一些重要协议时,我们为了安全起见,使用C语言来编写这些重要的部分,来增大系统的安全性。

    在一些复杂性的计算中,要求高性能的场景中,C/C++更加的有效率,代码也更便于复用。

当然还有其他的优点,这些都驱使我们选择相对来说高效和安全的NDK来开发我们的应用程序。

OK,说了那么多NDK,那到底怎么使用NDK来开发应用程序呢?

俗话说,工欲善其事必先利其器,想要使用NDK开发,必先打磨好工具。那下面首先来看看NDK的环境搭建吧。

NDK的环境搭建

安装配置NDK

一,首先下载NDK,这里我使用的是android-ndk-r14b-windows-x86_64,可以自主选择。

1). 解压NDK的zip包,注意路径目录不要出现空格和中文,这里建议大家把包解压到SDK目录里面,并命名为ndk-bundle,好处是,启动AS的时候会检查它并直接添加到ndk.dir中,减少我们的配置工作;

2). 配置path : 把解压好的路径添加到环境变量path中;

3).ndk-build:cd到解压后NDK的根目录,执行ndk-build命令。

二,给AS配置关联NDK,这里我使用的是androidstudio,使用Eclipse的会有所不同,请自行查找资料来配置。

1). 在建立的工程中的local.properties中添加如下配置
ndk.dir=D:\guanmanman\androidStudio\sdk\ndk-bundle,这里注意下要使用转义字符“\”来进行字符转义。如果ndk目录是存放在SDK中,并命名为ndk-bundle,这个配置会自动为添加上去。

<也可以通过下面 点击Download Android NDK 下载安装>

2). 在工程中gradle.properties中添加对旧版本的NDK支持的配置
android.useDeprecatedNdk=true

OK,到这里我们基本的NDK环境配置已基本完成,那接下来就开始我们的NDK开发旅程吧。

注意:在3.0以后的 android studio  会报错 Error:No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android

原因 新版本的NDK与3.0及以前旧版的Android Gradle plugin插件不兼容

解决办法 1,下载老版本找到 mips64el-linux-android 文件夹复制到自己的对应位置

                2,使用版本高于3.2的 Gradle plugin插件

原文   :https://blog.csdn.net/qq_36355271/article/details/89314148

 

Demo实例之调用本地无参方法直接返回字符串

一 layout布局

直接在layout中添加一个按钮ImageView控件,用于点击调用本地方法:(我用自己项目做测试)

<ImageView
    android:id="@+id/imag_login"
    android:layout_width="wrap_content"
    android:layout_weight="1"
    android:layout_marginTop="45dp"
    android:src="@mipmap/index_02"
    android:layout_height="0dp" />

二 在MainActivity中获取该控件并注册它的点击监听器

@BindView(R.id.imag_login)
ImageView imag_login;
@OnClick({R.id.logn,R.id.go_register,R.id.imag_login})
public void OnClick(View v){
    switch (v.getId()){
        case R.id.imag_login:
            break;

}}

三 创建Java2CJNI类及本地方法

在我们的包下直接创建一个Java2CJNI类,并在类里创建一个java2C的本地方法:

package com.example.jpushdemo;

/**
 * Created by Administrator on 2019/4/15.
 */

public class Java2CJNI {

    public native String java2C();
}

四 通过javah命令获取到本地头文件

在项目根目录下,进入main->java目录(按自己的实际路径),全选文件目录栏,直接输入cmd命令并按回车键进入docs命令,在命令中执行javah com.sanhui.ndkdemo.Java2CJNI命令:( javah 包名.Java2CJNI)

执行完javah命令后,会在java当前目录下创建一个.h的头文件

六 创建实现头文件的.C源文件

在jni目录下创建一个Java2C.c的源文件,通过#include引入我们的头文件com_sanhui_ndkdemo_Java2CJNI.h,并把在头文件下的声明方法JNIEXPORT jstring JNICALL Java_com_example_jpushdemo_Java2CJNI_java2C(JNIEnv *, jobject);复制到我们的Java2C.c中,补全方法参数,并实现一个C字符串“I am From Native C .”的返回:

OK,至此我们的代码已编写完毕,接下来我们需要配置编译后的so名称和支持的cpu类型。

七 在该项目下的build.gradle配置生成的so名称和支持的cpu类型

在android->defaultConfig下添加如下代码:

ndk {
    //选择要添加的对应cpu类型的.so库。
    moduleName "Java2C" //so文件名
    abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a','x86', 'x86_64', 'mips', 'mips64'
    // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
}

八 加载so库

在我们创建的Java2CJNI类中加载so库,主要是为了在我们调用本地方法之前先编译本地源码。

在使用 System.loadLibrary(“Java2C”);加载库时,库名一定要与在build.gradle中配置的moduleName 名称一致,否则将找不到库。

九 生成so文件

在项目的工具类中选择Build->Rebuild Project,进行重新编译工程,然后AS会为我们生成so文件,so文件所在目录为:NDKDemo\app\build\intermediates\ndk\debug\lib下

注意:so文件命名方式是:lib+moduleName+.so

注意  3.0 以后版本这种方式会报错无法发完成  推荐使用 ndk-build  生成so文件

用法定位的jni位置 使用如下:

生成完成:如失败 会有错误提示  查看修改即可

注 常见错误:

Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: D:/AndroidWorkspace/HospitalProject_jpust/jni/Android.mk
D:/android/sdk/sdk/ndk-bundle/build//../build/core/add-application.mk:88: *** Android NDK: Aborting...    .  Stop.


解决办法在 jni 文件夹新建 Android.mk 打开编写如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := Java2C
LOCAL_LDFLAGS := -Wl,--build-id
LOCAL_SRC_FILES := \
   D:\AndroidWorkspace\HospitalProject_jpust\jni\Android.mk \
   D:\AndroidWorkspace\HospitalProject_jpust\jni\Java2C.c \

LOCAL_C_INCLUDES += D:\AndroidWorkspace\HospitalProject_jpust\jni
LOCAL_C_INCLUDES += D:\AndroidWorkspace\HospitalProject_jpust\jni

include $(BUILD_SHARED_LIBRARY)

其中路径按自己实际情况修改

十 执行调用本地方法

在MainActivity中点击Button按钮调用本地方法。并通过Toast打印出来。

public void onClick(View view) {
    Toast.makeText(MainActivity.this,new Java2CJNI().java2C(),Toast.LENGTH_LONG).show();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值