文档章节

Android Native jni 编程入门

x
 xchsp
发布于 2015/03/07 09:39
字数 1053
阅读 7
收藏 0
点赞 0
评论 0

在某些情况下,java编程已经不能满足我们的需要,比如一个复杂的算法处理,这时候就需要用到jni(java native interface)技术;

  • jni 其实就是java和c/cpp之间进行通信的一个接口规范,java可以调用c/cpp里面的函数,同样,c/cpp也可以调用java类的方法;

jni开发工具ndk的安装:
在最新的ndk版本中,安装ndk很简单,只需要装ndk的路径配置到系统环境变量中即可;
在编译的时候,进入工程根目录;执行命令  ndk-build  即可完成编译;

 

下面就通过一个例子一步一步的来初步学习jni

一、HelloWorld

新建一个工程,你甚至不需要其它额外的设置,然后在工程中添加一个jni目录,然后就可以开始了;

1.新建一个java类HelloWorld.java

复制代码

package com.jni;public class HelloWorld {    static {
        System.loadLibrary("helloworld");
    }    public native String helloworld();
}

复制代码

在HelloWorld中,定义了一个方法helloworld(),只不过这个方法被申明成了native的,并没有具体的实现,具体功能我们在接下来的cpp文件中实现;

2.在jni目录下添加一个helloworld.cpp

复制代码

#include <jni.h>#include <android/log.h>#include <string.h>#ifndef _Included_com_jni_HelloWorld // 1#define _Included_com_jni_HelloWorld#ifdef __cplusplus // 2extern "C" {#endif // 2JNIEXPORT jstring JNICALL Java_com_jni_HelloWorld_helloworld(JNIEnv *, jobject);
#ifdef __cplusplus // 3}#endif // 3#endif // 1JNIEXPORT jstring JNICALL Java_com_jni_HelloWorld_helloworld(JNIEnv * env,
        jobject obj) {    return env->NewStringUTF("helloworld");
}

复制代码

从上面这个cpp文件中可以很明白的看出,它有一个方法,具体包括方法申明和方法实现两个部分;但是相信大家也都看出来了,方法的命令很怪异,怎么这么长的方法名?

我们在这里先思考一个问题,java类中的方法是如何调用c++中的方法的呢?要解决这个问题,就得先来看这个长长的方法名;

其实这是jni的一个规范之一,用于映射java方法和c/c++中的方法对应;

再来看在cpp中定义的函数名:Java_com_jni_HelloWorld_helloworld

其实不难看出,java文件与cpp文件中函数名的配对定义方式为Java + 包名 + java类名 + 方法/函数名,中间用_分隔;其中两个参数分别是:

    • env:当前该线程的内容,包含线程里面全部内容;

    • obj:当前类的实例,指.java文件的内容(在该例子中即是HelloWorld类);

这里的helloworld方法,其实就只是返回了一个单词"helloworld";

3.在jni目录下添加一个Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := helloworld
LOCAL_SRC_FILES := helloworld.cpp
include $(BUILD_SHARED_LIBRARY)

4.在命令行下进入工程目录执行 ndk-build 命令,然后运行程序,调用HelloWorld实例的helloworld方法就可以得到它的返回字符串了;

 

二、jni调用Java类的方法(1)

通过上面的helloworld练手之后,我们来看一下jni调用java类里面的方法的实现;

1.新建设一个MethodCall.java文件如下

复制代码

public class MethodCall {    final String tag = "MethodCall";    static {
        System.loadLibrary("methodcall");
    }    public native String jniCallMethod1();    public native String jniCallMethod2();    public native String jniCallStaticMethod();    public void javaMethod1() {
        Log.e(tag, "javaMethod1");
    }    public String javaMethod2() {
        Log.e(tag, "javaMethod2");        return "javaMethod2";
    }    public static void javaStaticMethod(String input) {
        Log.e("MethodCall", "" + input);
    }
}

复制代码

该类有6个方法,其中有3个是java类的方法,另外3个是native方法,3个native方法分别去调用3个java方法;

2.添加三个native方法具体实现 methodcall.cpp

复制代码

#include <jni.h>#include <android/log.h>#include <string.h>#ifndef _Included_com_jni_MethodCall#define _Included_com_jni_MethodCall#ifdef __cplusplusextern "C" {#endifJNIEXPORT jstring JNICALL Java_com_jni_MethodCall_jniCallMethod1(JNIEnv *,
        jobject);
JNIEXPORT jstring JNICALL Java_com_jni_MethodCall_jniCallMethod2(JNIEnv *,
        jobject);
JNIEXPORT jstring JNICALL Java_com_jni_MethodCall_jniCallStaticMethod(JNIEnv *,
        jobject);
#ifdef __cplusplus
}#endif#endifJNIEXPORT jstring JNICALL Java_com_jni_MethodCall_jniCallMethod1(JNIEnv * env,
        jobject obj) {
    jmethodID mid; // 方法标识id
    jclass cls = env->GetObjectClass(obj); // 类的对象实例
    mid = env->GetMethodID(cls, "javaMethod1", "()V");
    env->CallVoidMethod(obj, mid);    return env->NewStringUTF("jniCallMethod1");
}

JNIEXPORT jstring JNICALL Java_com_jni_MethodCall_jniCallMethod2(JNIEnv * env,
        jobject obj) {
    jmethodID mid; // 方法标识id
    jclass cls = env->GetObjectClass(obj); // 类的对象实例
    mid = env->GetMethodID(cls, "javaMethod2", "()Ljava/lang/String;");
    jstring js = (jstring) env->CallObjectMethod(obj, mid);    return js;
}

JNIEXPORT jstring JNICALL Java_com_jni_MethodCall_jniCallStaticMethod(
        JNIEnv * env, jobject obj) {
    jmethodID mid; // 方法标识id
    jclass cls = env->GetObjectClass(obj); // 类的对象实例
    mid = env->GetStaticMethodID(cls, "javaStaticMethod",            "(Ljava/lang/String;)V");
    jstring input = env->NewStringUTF("jniCallStaticMethod->>javaStaticMethod");
    env->CallStaticVoidMethod(cls, mid, input);    return env->NewStringUTF("jniCallStaticMethod");
}

复制代码

该cpp文件中有3个方法(我这里把方法名都写得很明白直观,相信不需要注释都知道是调用的哪一个java方法)


本文转载自:

共有 人打赏支持
x
粉丝 0
博文 56
码字总数 129407
作品 0
沈阳
用Android Studio进行NDK编程入门实例

参考了网上各种教程,跌跌撞撞最终才把流程走通,特此记录一下: 有必要先交代下开发环境: 操作系统:Win7 Android Studio 3.0.1 gradle 3.0.1 首先,新建一个Android项目,然后在MainActiv...

analogous_love ⋅ 04/17 ⋅ 0

Android JNI(一)——NDK与JNI基础

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

Android NDK开发的一点尝试

写在前面 笔者是一个“原始”的C++开发者,对Java编程虽说不上抵触但也没有C++那么顺手。而且,作为一个游戏引擎,不管是在什么地方,效率总是第一位的,尤其是在移动平台这样资源吃紧的环境...

闪电的蓝熊猫 ⋅ 04/06 ⋅ 0

AndroidStudio3.0NDK输出多个so库

个人博客地址 http://dandanlove.com/ 前言 去年的 Android之NDK开发初体验 这篇文章讲述NDK开发环境的搭建,以及在AndroidStudio3.0版本之前的NKDK简单开发。这次升级到Android Studio3.1,...

静默加载 ⋅ 04/12 ⋅ 0

Android JNI学习(五)——Demo演示

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

Android JNI学习(二)——实战JNI之“hello world”

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

React Native SDK for OSS

此文主要介绍 React Native SDK for OSS的方方面面,包括相关基本概念、项目背景、项目方案、环境搭建运行、使用姿势、注意事项等。文末的附件可运行Example Zip压缩包和针对新手的入门实用文...

zuozhao ⋅ 05/18 ⋅ 0

Android JNI学习(三)——Java与Native相互调用

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头 ⋅ 05/09 ⋅ 0

Android NDK 入门与实践

Android NDK 入门与实践 吴小龙同學2017-12-271 阅读 NDK NDK 是什么 NDK 全称 Native Development Kit,可以让您在 Android 应用中调用 C 和 C++ 代码的工具。 NDK 好处 1、NDK 可以生成 .s...

吴小龙同學 ⋅ 2017/12/27 ⋅ 0

Android Studio进行NDK编程

近期,转战Android Studio。通过Android Studio进行简单的NDK Demo实现。无奈才疏学浅,资料有限。一直处于碰壁状态。找了好多资料,思量良久。终见实验效果,现分享给大家。通过Java对C语言...

wolfbigbig ⋅ 2016/03/02 ⋅ 4

没有更多内容

加载失败,请刷新页面

加载更多

下一页

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部