Android基本功:JNI

??

一、什么是JNI

  • Java本地开发接口(Java Native Interface);
  • 用来沟通Java代码和外部的本地代码(c/c++)。通过这个协议,Java代码就可以调用外部的c/c++代码,外部的c/c++也可以调用Java代码;

二、为什么使用JNI

  • Java语言装载到虚拟机中,不能和硬件交互,不能驱动开发。JNI扩展了Java虚拟机的能力,驱动开发(如wifi-hotspost)无线热点共享;
  • Native Code效率高,数学运算、实时渲染的游戏,音视频处理(如极品飞车,opengl);
    • C代码手动回收内存,程序员可以控制,及时回收内容;
    • Java代码自动回收,程序员没法控制,基于算法;
  • 复用代码(文件压缩,人脸识别Opencv,7zip,ffmpeg);
  • 特殊应用场景,如电视、车载系统、微波炉等;
    • 汽车监控系统,传感器基于电信号;

三、NDK是什么

  • Native develop kits工具链,提供了交叉编译的工具链;
  • C语言不跨平台,在Windows系统下使用NDK编译在Linux下能执行的函数库;
    • dll:Windows系统下的函数库文件;
    • so:Linux系统下的函数库文件;
  • 在Linux电脑(x86架构)开发,需要使用NDK编译在手机cpu(arm架构)能执行的函数;

四、怎么使用NDK

  1. 在官网下载适应版本的Ndk包(android-ndk-r10e-windows-x86_64.exe文件),双击改文件即会自动解压(android-ndk-r10e文件夹,非中文目录);
  2. 在环境变量path中添加ndk的目录(D:\DevelopTools\android-ndk-r10e);
  3. 在cmd命令窗口执行ndk-build命令,有如下输出则安装成功;

五、NDK目录结构

  • Builds:ndk搭建的环境;
  • Docs:ndk开发的文档;
  • Platform:
    • arm:英国arm公司,不生产cpu,卖cpu的架构转移,功耗比较低;
    • Mips:cpu架构,龙心;
    • X86:inter,没有特别明显的优势,运行效率高点,功耗比较大;
  • Samples:提供示例代码;
  • Sources:ndk的源码;
  • Toolchains:交叉工具的工具链;
  • ndk-build.cmd:交叉编译的批处理文件;

六、JNI协议规范

  • 规定了Java类型和c类型的转化;

java

在jni中的别名

c代码

boolean

jboolean

unsigned char

float

jfloat

float

double

jdouble

double

byte

jbyte

signed char

char

jchar

unsigned short

short

jshort

short

int

jint/jsize

int

long

jlong

long long

Object

jobject

void *

String

jstring

void *

  • Struct JNINativeInterface 结构体重定义了java的底层方法,底层方法通过c代码实现的;
  • Runtime虚拟机 对之前的虚拟机做了优化;

七、JNI的开发流程

  1. 写c代码突破口native,类似于抽象方法,具体实现由c代码来实现;

public native String helloFromC();

  1. 创建jni目录,在jni目录中创建c代码,让c代码找到对应的native方法;

#include <jni.h>

jstring Java_com_example_hellojni_MainActivity_helloFromC(JNIEnv* env,jobject obj){

jstring jstr=(*env)->NewStringUTF(env,"Hello");

return jstr;

}

  1. 在jni目录下,创建Android.mk文件;

#$ linux执行方法的符号  返回当前的工程目录

LOCAL_PATH := $(call my-dir)

# 清除所有之前的缓存,清除是local开头的变量  唯一不会清除LOCAL_PATH

include $(CLEAR_VARS)

#代表打包生成的函数库的名字  前面自动生成lib 后面自动生成.so  如果前面+上lib 不会再生成lib

LOCAL_MODULE:= hello-jni

# 代表要把哪个c文件打包成函数库

LOCAL_SRC_FILES:= hello.c

# BUILD_SHARED_LIBRARY  生成动态函数库  .so   体积小    把系统的c程序动态加载

# BUILD_STATIC_LIBRARY  生成静态函数库  .a    体积大   把用到的系统的c代码 一次性加载到函数库中

include $(BUILD_SHARED_LIBRARY)

  1. 交叉编译,在cmd控制台,进入当前工程目录下,执行ndk-build指令;

  1. 在java在代码中引入函数库,直接调用native方法;

static{

//不管android.mk文件是怎么写的  就是去掉已有的函数库的lib  .so

System.loadLibrary("hello-jni");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Toast.makeText(getApplicationContext(), helloFromC(), 0).show();

}

八、NDK的简单开发流程

  1. 配置Eclipse的NDK路径;

  1. 创建Android项目,右键Android项目->Android Tools->Add Native Support;

  1. 添加完成native方法,在PrjectDir/scr目录下执行javah命令。生成标头文件com_example_hellojni2_MainActivity.h,并且拖拽到jni目录下;

  1. 将hellojni2.cpp文件修改为hello.c文件,并且将com_example_hellojni2_MainActivity.h文件中生成的方法,粘贴到hellojni2.c文件中,如下;

#include "com_example_hellojni2_MainActivity.h"

jstring Java_com_example_hellojni2_MainActivity_helloFromC(JNIEnv *env, jobject obj){

jstring jstr=(*env)->NewStringUTF(env,"Hello");

return jstr;

}

  1. 修改Android.mk文件中的相关配置后,点击“小锤子”生成hello-jni2.so文件;

  1. 同上,在MainActivity中调用hello-jni2.so文件中的c方法;

九、NDK常见错误

  1. 没有引入函数库/c代码和java代码不对应

11-02 14:47:33.259: E/AndroidRuntime(1185): java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.example.hellojni2.MainActivity.helloFromC() (tried Java_com_example_hellojni2_MainActivity_helloFromC and Java_com_example_hellojni2_MainActivity_helloFromC__)

  1. 没有Android.mk文件

D:\DevelopTools\android-ndk-r10e\ndk-build.cmd all

Android NDK: WARNING: APP_PLATFORM android-21 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml

Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk

D:/DevelopTools/android-ndk-r10e/build/core/add-application.mk:199: *** Android NDK: Aborting...    .  Stop.

  1. c代码有编译时错误

Android NDK: WARNING: APP_PLATFORM android-21 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml

[armeabi] Compile thumb  : hello-jni2 <= hello.c

jni/hello.c: In function ‘Java_com_example_hellojni2_MainActivity_helloFromC‘:

jni/hello.c:4:2: error: unknown type name ‘a‘

a

^

jni/hello.c:5:10: error: expected ‘=‘, ‘,‘, ‘;‘, ‘asm‘ or ‘__attribute__‘ before ‘jstr‘

jstring jstr=(*env)->NewStringUTF(env,"Hello");

  1. c代码有运行时异常

十、跨CPU的开发

  1. 在jni目录下添加Application.mk文件,定义支持的CPU类型;

APP_ABI := x86

APP_PLATFORM := android-8

  1. 重新交叉编译项目的so文件,会看见在支持的平台下,都会生成so文件,然后运行模拟器;

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 11:05:47

Android基本功:JNI的相关文章

【转】Android与JNI(二) -- 不错

原文网址:http://www.cnblogs.com/eddy-he/archive/2012/08/09/2629974.html 软件版本: ubuntu10.04 java version "1.6.0_30-ea" eclipse android-ndk-r5b 目录: 1. 简介 2. JNI 组件的入口函数 3. 使用 registerNativeMethods 方法 4. 测试 5. JNI 帮助方法 6. 参考资料 1. 简介 Android与JNI(一)已经简单介绍

Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块

一直想写一份技术文档,但因为自感能力有限而无从下笔,近期做了个关于Android平台下实现与C语言的通讯来操作蓝牙模块的项目,中间碰到了很多问题,也在网上查了很多资料,在完毕主要功能后.也有一些人在网上问我一些问题.这里写下这篇文档算是一个阶段性的总结. 假设反响好.兴许将会发上Android Stub与新版Android HAL的学习文档. 因为蓝牙模块是串口通讯机制.使用C语言来訪问,而Android的应用层採用Java.无法直接操作硬件.故使用JNI的技术实现主要功能.Android的JN

Android使用JNI(从java调用本地函数)

当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本地函数. 在Java端,开发者所需要做的仅仅是在连接本地函数的方法之前加上native关键字.这样VM就会去寻找这个本地函数. 1.从Java调用本地函数 从Java调用本地函数时,需要在类中定义一个带有native关键字的特有方法,作为连接本地代码的桥梁.通过这个定义,尝试调用本地方法时JVM会找

I.MX6 android BatteryService jni hacking

/**************************************************************************** * I.MX6 android BatteryService jni hacking * 声明: * 本文主要是为了知道Android的获取的电源管理的数据的jni是从Linux系统的 * 什么位置获取的,获取的机制是什么. * * 2016-2-22 深圳 南山平山村 曾剑锋 ********************************

Android之——JNI初探

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47405683 这里,我将用一个小例子的形式来帮助大家初探JNI的用法,首先,大家要先搭建好NDK环境,请大家先阅读<Android之--NDK环境搭建>一文. 一.实现 这个小例子实现的功能就是,通过Android中的java代码来调用C代码实现java代码与C代码之间的交互. 1.布局文件 我们首先在布局文件activity_main.xml中,添加一个按钮控件,并给按钮控件

[Android] 图片JNI(C++\Java)高斯模糊 多线程

在我的博客中,曾经发布了一篇高斯模糊(堆栈模糊)的文章:在其中使用了国外的一个堆栈模糊来实现对图片的模糊处理:同时弄了一个JNI C++ 的版本. 这篇文章依然是堆栈模糊:可以说最原始的地方还是堆栈模糊部分:只不过是支持多线程的. 纳尼??感情是之前那个不支持多线程?Sorry,我说错了:两个都是支持多线程调用的.不过新讲的这个是能在内部采用多线程进行分段模糊. 原来的:[Android]-图片JNI(C++\Java)高斯模糊的实现与比较 开工吧 说明:其中代码大部分来源于网络,不过都是开源的

Android - Android调用JNI方法 及 代码

Android调用JNI方法 及 代码 本文地址: http://blog.csdn.net/caroline_wendy JNI: Java Native Interface, 实现Java和C/C++的互通. 在Android上使用JNI的方法. 时间:2014.9.3 环境: 必须使用标准Eclipse, 安装Android的环境, 才可以使用NDT插件. Eclipse Standard/SDK Version: Luna Release (4.4.0); Android: ADT-23

OpenCV4Android释疑: 透析Android以JNI调OpenCV的三种方式(让OpenCVManager永不困扰)

前文曾具体探讨了关于OpenCV的使用,原本以为天下已太平.但不断有人反应依旧配不好OpenCV4Android,不能得心应手的在Android上使用OpenCV.大量的精力都浪费在摸索配置上.尤其是OpenCVManager诞生之后.更让人无语.大家第一个反应就是怎样才干不安装OpenCVManager.由于要多安装这个东西对客户来说体验太不好了. 咱家昨夜研究至两点,今早七点起床.最终把头绪理清了. 以下咱家以之前做过的一个基于OpenCV2.3.1.android通过jni调用opencv

Android中JNI的使用

Android中JNI编程的那些事儿 首先说明,Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须是通过Java代码嵌入Native C/C++——即通过JNI的方式来使用本地(Native)代码.因此JNI对Android底层开发人员非常重要. 如何将.so文件打包到.APK 让我们 先 从最简单的情况开始,假如已有一个JNI实现——libxxx.so文件,那么如何在APK中使用它呢? 在我最初写类似程序的时候,我会将libxxx.so文件push到/system/lib/目

Android(Java):jni源代码

public void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        Button btn = new Button(this);        btn.setText("测试ndk");        btn.setOnClickListener(new ButtonOnClickListener());        setContentView(