【分享】Android JNI实例​

【分享】Android JNI实例​

Android的SDK中没有包括JNI的支持,而且对如何支持JNI也没有任何文档说明。不过既然整个Android平台是开源的,我们可以通过Google发布的源代码来找到一些线索(比如frameworks/base/media/jni/目录),依葫芦画瓢的实现上层JAVA程序通过JNI来调用Native C程序中的函数。

依照下面的步骤可以实现一个非常简单的JNI的实例程序:

1.  首先编写C模块,实现动态库。(关于如何在Android中编译C模块的更多细节,请参考《Android编译环境(1) - 编译Native C的helloworld模块》。)

在development目录下添加新目录hellolib,并添加hellolib.c和Android.mk文件。hellolib.c的内容如下:

#include <jni.h>

#define LOG_TAG "TestLib"

#undef LOG

#include <utils/Log.h>

 

JNIEXPORT void JNICALL Java_com_test_TestHelloLib_printHello(JNIEnv * env, jobject jobj)

{

    LOGD("Hello LIB!\n");

}

注意这里的函数名需要按照JNI的规范(因此也可以用javah -jni工具来生成头文件,来保证函数名的正确性),Java_com_test_TestHelloLib_printHello的命名对应后面在java代码中,package名字是com.test,类名是TestHelloLib,native函数名是printHello。

另外,LOGD及#define LOG_TAG "TestLib"等打印log的方式是采用了Android所提供的LOG机制,这样才能通过Android的logcat工具看到log。

用于编译C模块的Android.mk文件内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

    hellolib.c

LOCAL_C_INCLUDES := \

    $(JNI_H_INCLUDE)

 

LOCAL_SHARED_LIBRARIES := \

    libutils

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := libhello

include $(BUILD_SHARED_LIBRARY)

该文件中的一些变量分别对应的含义如下:

LOCAL_SRC_FILES - 编译的源文件

LOCAL_C_INCLUDES - 需要包含的头文件目录

LOCAL_SHARED_LIBRARIES - 链接时需要的外部库

LOCAL_PRELINK_MODULE - 是否需要prelink处理(参考prelink的详细介绍:《动态库优化——Prelink(预连接)技术》,Android的Toolchain, prelink工具:《Android Toolchain与Bionic Libc》)

LOCAL_MODULE - 编译的目标对象

BUILD_SHARED_LIBRARY - 指明要编译成动态库。

       接下来回到Android顶层目录,并执行make libhello来编译:

# cd $(YOUR_ANDROID) && make libhello

target thumb C: libhello <= development/hellolib/hellolib.c

target SharedLib: libhello (out/target/product/generic/obj/SHARED_LIBRARIES/libhello_intermediates/LINKED/libhello.so)

target Non-prelinked: libhello (out/target/product/generic/symbols/system/lib/libhello.so)

target Strip: libhello (out/target/product/generic/obj/lib/libhello.so)

Install: out/target/product/generic/system/lib/libhello.so

       编译结果可得到位于out/target/product/generic/system/lib/目录的动态共享库libhello.so

 

2.编写Java模块,来通过JNI方式调用C接口。具体Eclipse环境的搭建请参考Android SDK文档中的详细说明,及Hello Android程序的创建过程,这里仅给出我们需要修改的TestHelloLib.java文件:

package com.test;

import android.app.Activity;

import android.os.Bundle;

public class TestHelloLib extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        printHello();

    }

    static {

    System.loadLibrary("hello");

    }

    private native void printHello();

}

注意上面代码中粗体字部分:private native void printHello()用来声明一个native接口,static { System.loadLibrary("hello"); } 用来加载上面步骤中生成libhello.so(注意loadLibrary方法的参数不是”libhello.so”,而是去掉前缀和后缀之后的”hello”),onCreate()方法中则调用了printHello()接口。

    通过这一步骤可生成Android开发者所熟悉的apk文件:TestHelloLib.apk。

 

3.集成测试TestHelloLib.apk和libhello.so。先运行emulator并将TestHelloLib.apk和libhello.so上传至emulator中。注意要将libhello.so上传到emulator的/system/lib目录,由于该目录是只读的,上传之前先要执行adb remount:

# adb remount

# adb push out/target/product/generic/system/lib/libhello.so /system/lib

# adb install TestHelloLib.apk

       接下来在模拟器菜单中可以看到已经安装的TestHelloLib程序,运行即可。

       由于JNI接口printHello()并没有作界面上的改动,要验证其效果需要用Android的logcat工具来查看。运行”adb logcat”可以找到下面的log片断:

I/ActivityManager(   48): Starting activity: Intent { action=android.intent.action.MAIN categories={android.intent.category.LAUNCHER} flags=0x10200000 comp={com.test/com.test.TestHelloLib} }

I/ActivityManager(   48): Start proc com.test for activity com.test/.TestHelloLib: pid=174 uid=10024 gids={}

D/dalvikvm(  174): Trying to load lib /system/lib/libhello.so 0x43481c58

D/dalvikvm(  174): Added shared lib /system/lib/libhello.so 0x43481c58

D/dalvikvm(  174): No JNI_OnLoad found in /system/lib/libhello.so 0x43481c58

D/dalvikvm(  174): +++ not scanning '/system/lib/libwebcore.so' for 'printHello' (wrong CL)

D/dalvikvm(  174): +++ not scanning '/system/lib/libmedia_jni.so' for 'printHello' (wrong CL)

D/TestLib (  174): Hello LIB!

I/ActivityManager(   48): Displayed activity com.test/.TestHelloLib: 806 ms

       这里包含了调用printHello()接口的log信息,其中”D/TestLib (  174): Hello LIB!”就是printHello()所打印的信息。至此成功完成Android JNI的实例验证。

 

转载于:https://www.cnblogs.com/yun111/articles/2834309.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/474765.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode MySQL 1098. 小众书籍

文章目录1. 题目2. 解题1. 题目 书籍表 Books&#xff1a; ------------------------- | Column Name | Type | ------------------------- | book_id | int | | name | varchar | | available_from | date | ------------------------- book_…

mysql linux 还原_linux下java还原mysql数据库

pageEncoding"UTF-8" import"java.lang.*,java.io.*,java.util.*"%>Runtime runtime Runtime.getRuntime();// 将/data/backup.sql 还原到 192.168.0.96 上的demo库 账号密码为 root rootString restore "mysql -u root -proot -h 192.168.0.96 …

解决eclipse无法解析导入org.eclipse.swt库

右键点击项目 -> Build Path -> Config Build Path...然后选择Libraries标签页&#xff0c;点击Add External JARs...再到你的eclipse安装目录下的plugins目录下寻找 org.eclipse.swt.win32.win32.x86_XXXXX.jar&#xff08;XXXXX是版本号&#xff09;。 我的对应库是org…

LeetCode MySQL 1107. 每日新用户统计

文章目录1. 题目2. 解题1. 题目 Traffic 表&#xff1a; ------------------------ | Column Name | Type | ------------------------ | user_id | int | | activity | enum | | activity_date | date | ------------------------ 该表没有主键&a…

mysql gui 有哪些_推荐五款较好的MySQLGUI工具

大多数数据库都是由两个截然不同的部分组成的&#xff1a;后端(存储数据的地方)和前端(一个用于连接数据组件的用户界面)。这种架构可以大多数数据库都是由两个截然不同的部分组成的&#xff1a;后端(存储数据的地方)和前端(一个用于连接数据组件的用户界面)。这种架构可以把用…

共享打印机的方法

共享打印机的方法 1、在计算机上连接好打印机&#xff0c;并安装好打印机的驱动&#xff0c;测试是否在本机上可以打印 &#xff1b; 2、在打印服务器上&#xff0c;共享该打印机&#xff1b; 3、保证打印服务器上的共享资源可以正常地访问&#xff1b; 4、在PC机运行“\\打印服…

LeetCode MySQL 1149. 文章浏览 II

文章目录1. 题目2. 解题1. 题目 Table: Views ------------------------ | Column Name | Type | ------------------------ | article_id | int | | author_id | int | | viewer_id | int | | view_date | date | ---------------------…

调试lua代码

lua没有调试器&#xff0c;但是它提供了很强的调试功能&#xff08;debug 库&#xff09;&#xff0c; 所以其实一些常用的调试功能都能很方便的使用&#xff0c;就像使用一个命令行调试器一样&#xff1a; 【例子程序】 -- debug.luagvar1 100 function foo()local var2 10f…

php增加mysql用户_mysql 增加用户

1. 新增用户 Sql代码 mysql insert into mysql. user (Host, User , Password ) values ( localhost , lionbule , password ( hello1234 )); mysqlflush privileges ; 或者 CREATEUSER usernamehost IDENTIFIEDBYpassword; 例子:CREATEUSERdoglo1. 新增用户Sql代码mysql>i…

2012总结--序

新时代Fans同学一直有 总结的习惯&#xff01;2012总结不同以往&#xff0c;这次总结是 划时代的。 世界末日已过&#xff0c;新的时代已经开始&#xff01; 2012年是至关重要的一年&#xff0c;不在于 IT技术上有多大提高&#xff0c;而是在于&#xff1a; 1. 离开校园&#x…

LeetCode MySQL 1164. 指定日期的产品价格 *

文章目录1. 题目2. 解题1. 题目 产品数据表: Products ------------------------ | Column Name | Type | ------------------------ | product_id | int | | new_price | int | | change_date | date | ------------------------ 这张表的主键是 (…

python tkinter 实例_Python tkinter模版代码实例

这篇文章主要介绍了Python tkinter模版代码实例,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下代码如下import tkinterimport timeimport threadingfrom tkinter import ttkevent threading.Event()once0def s…

判断浏览器版本

用jquery判断浏览器类型&#xff1a; 判断浏览器类型是IE浏览器还是火狐甚至是opera或者苹果浏览器safari&#xff0c;jquery 特效代码如下&#xff1a; $(function(){if($.browser.msie) {alert("这是一个IE浏览器");}else if($.browser.opera) {alert("这是一…

自己动手写cpu 光盘_自己动手写CPU配套源码

自己动手写CPU的源代码&#xff0c;一共15章&#xff0c;可以完整实现MIPS的指令文件&#xff1a;n459.com/file/25127180-476886294以下内容无关&#xff1a;-------------------------------------------分割线---------------------------------------------目录一、往期回顾…

LeetCode 1484. 克隆含随机指针的二叉树(哈希/递归)

文章目录1. 题目2. 解题2.1 原地算法2.2 哈希表1. 题目 给你一个二叉树&#xff0c;树中每个节点都含有一个附加的随机指针&#xff0c;该指针可以指向树中的任何节点或者指向空&#xff08;null&#xff09;。 请返回该树的 深拷贝 。 该树的输入/输出形式与普通二叉树相同…

QTreeWidget的基本操作

在主函数中增加&#xff1a; init();connect(ui->treeWidget,SIGNAL(itemChanged(QTreeWidgetItem*, int)),this,SLOT(treeItemChanged(QTreeWidgetItem*,int)));函数实现&#xff1a; void Widget::init() {ui->treeWidget->setHeaderLabels(QStringList()<<&q…

extjs2.0 ie8 下拉树_ExtJs下拉树的实现

直接上代码&#xff1a;Ext.ux.TreeCombo Ext.extend(Ext.form.ComboBox, {constructor : function(cfg) {cfg cfg || {};Ext.ux.TreeCombo.superclass.constructor.call(this, Ext.apply({maxHeight : 300,editable : false,mode : local,triggerAction : all,rootVisible :…

LeetCode 294. 翻转游戏 II(记忆化递归)

文章目录1. 题目2. 解题1. 题目 你和朋友玩一个叫做「翻转游戏」的游戏&#xff0c; 游戏规则&#xff1a;给定一个只有 和 - 的字符串。 你和朋友轮流将 连续 的两个 "" 反转成 "--"。 当一方无法进行有效的翻转时便意味着游戏结束&#xff0c;则另一方…

CMD 命令行查看端口被哪个程序占用,并根据PID值,找到相应的程序,关闭掉对应服务或进程!...

CMD 命令行查看端口被哪个程序占用&#xff0c;并根据PID值&#xff0c;找到相应的程序&#xff0c;关闭掉对应服务或进程&#xff01;不用任何第三方软件的情况下&#xff0c;打开CMD执行如下命令&#xff1a;1&#xff0c;netstat -ano 你可以查看到Local Address下面的80端口…

mysql 逻辑备份导入数据库_mysql逻辑备份(mysql dump的使用)

mysqldump 属于MySQL客户端工具mysqldump备份工具对于MyISAM存储引擎实现备份是温备份&#xff0c;对innodb存储引擎是可以实现热备份。使用mysqldump备份数据库可以实现完全备份 二进制日志文件&#xff0c;这样也算是完全备份 增量备份。首先将这个数据库备份下来这就是完全…