简单JNI使用demo
android中使用JNI的小例子,直接上代码。
首先是Java类JniClient,定义native方法,User实体类就不上代码了,就简单定义了三个属性,name、age、sex。
package com.example.ndkdemo; public class JniClient { /**
* 通过JNI简单输出字符串
* @return
*/
static public native String printStr(); /**
* 通过JNI简单进行整形加法操作
* @param a
* @param b
* @return
*/
static public native int addInt(int a, int b); /**
* 通过JNI输入JAVA对象信息
* @param user
* @return
*/
static public native String printUser(User user); /**
* 通过JNI创建java对象
* @param name
* @param age
* @param sex
* @return
*/
static public native User newUser(String name, int age, String sex); /**
* 通过JNI调用无参构造函数创建java对象并且设置相应属性值
* @param name
* @param age
* @param sex
* @return
*/
static public native User newUserNoArgs(String name, int age, String sex);
}
然后使用cmd进入工程的classes目录通过javah命令生成c代码的头文件,命令:javah com.example.ndkdemo.JniClient ,这里生成的文件名字为:com_example_ndkdemo_JniClient.h
在工程下面新建一个jni目录,将生成的头文件拷贝到jni目录下面,创建com_example_ndkdemo_JniClient.c文件,在com_example_ndkdemo_JniClient.c文件里面实现各个native方法,代码如下:
#include "com_example_ndkdemo_JniClient.h"
#include <stdlib.h>
#include <stdio.h> // 引入log头文件
#include <android/log.h>
// log标签
#define TAG "jniCLient"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) #ifdef __cplusplus
extern "C"
{
#endif
/*
* Class: com_example_ndkdemo_JniClient
* Method: printStr
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_JniClient_printStr
(JNIEnv *env, jclass arg)
{
jstring str = (*env)->NewStringUTF(env, "HelloWorld from JNI !");
LOGI("log from jni");
return str;
} /*
* Class: com_example_ndkdemo_JniClient
* Method: AddInt
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_ndkdemo_JniClient_addInt
(JNIEnv *env, jclass arg, jint a, jint b)
{
return a + b;
} /**
* printUser
* jclass arg:因为方法为static,所以需要传入jclass参数,表明是哪个类的方法
*/
/**
*1)如果是C++代码,则用(*env),如果是C代码,则用env,否则报错: request for member 'GetObjectClass' in something not a structure or union
*2)所有方法都加了一个参数env,否则报错:too few arguments to function '(*env)->GetObjectClass'
*3)不能把.C文件改成.CPP文件,否则没有规则可以创建“out/apps/JNI_0529/armeabi/objs/JNI_0529/android_jni_MyJNINative.o”需要的目标“apps/JNI_0529/proje*ct/jni/android_jni_MyJNINative.c”
* 一个小例子错误真多啊!!NDK不简单啊!!
*/
JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_JniClient_printUser
(JNIEnv *env, jclass arg, jobject obj)
{
LOGI("add from jni--打印用户信息--");
//获得obj对象的类
jclass cls_objClass = (*env)->GetObjectClass(env, obj);
/**
* 获得obj对象中特定方法getName的id
* env
* cls_objClass 方法所属类
* getName 方法名字
* ()Ljava/lang/String; 方法签名
*/
jmethodID nameMethodId = (*env)->GetMethodID(env, cls_objClass, "getName", "()Ljava/lang/String;");
/**
* 调用obj对象的特定方法getName
* obj 调用方法的目标对象
* nameMethodId 调用方法的方法名
* ... 后面还可以添加方法需要的参数
*/
jstring js_name = (jstring)(*env)->CallObjectMethod(env, obj, nameMethodId);
//将jstring转为c中的字符数组
const char * name = (char *)(*env)->GetStringUTFChars(env, js_name, ); jmethodID ageMethodId = (*env)->GetMethodID(env, cls_objClass, "getAge", "()I");
jint ji_age = (*env)->CallIntMethod(env, obj, ageMethodId); jmethodID sexMethodId = (*env)->GetMethodID(env, cls_objClass, "getSex", "()Ljava/lang/String;");
jstring js_sex = (jstring)(*env)->CallObjectMethod(env, obj, sexMethodId);
const char * sex = (char *)(*env)->GetStringUTFChars(env, js_sex, ); //打印信息
LOGI("user info----name:%s, age:%d, sex:%s.", name, ji_age, sex); //释放资源
(*env)->ReleaseStringUTFChars(env, js_name, name);
(*env)->ReleaseStringUTFChars(env, js_sex, sex);
// printf("%s", str);
return js_name;
} /**
* 创建一个对象(调用有参构造函数)
*/
JNIEXPORT jobject JNICALL Java_com_example_ndkdemo_JniClient_newUser
(JNIEnv *env, jclass arg, jstring name, jint age, jstring sex)
{
//创建一个class的引用,使用类的全包名
jclass cls = (*env)->FindClass(env, "com/example/ndkdemo/User");
//注意这里方法的名称是"<init>",它表示这是一个构造函数
jmethodID id = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;ILjava/lang/String;)V");
//获得一实例,后面接构造函数参数
// jobject obj = (*env)->NewObject(env, cls, id, name, age, sex);
jstring jname = (*env)->NewStringUTF(env, "jni-liuling");
jstring jsex = (*env)->NewStringUTF(env, "jni-男");
jobject obj = (*env)->NewObject(env, cls, id, jname, 18L, jsex); return obj;
} /**
* 创建一个对象(调用无参构造函数)
*/
JNIEXPORT jobject JNICALL Java_com_example_ndkdemo_JniClient_newUserNoArgs
(JNIEnv *env, jclass arg, jstring name, jint age, jstring sex)
{
//创建一个class的引用,使用类的全包名
jclass cls = (*env)->FindClass(env, "com/example/ndkdemo/User");
//注意这里方法的名称是"<init>",它表示这是一个构造函数
jmethodID id = (*env)->GetMethodID(env, cls, "<init>", "()V");
//获得一实例,后面接构造函数参数
jobject obj = (*env)->NewObject(env, cls, id);
jstring jname = (*env)->NewStringUTF(env, "jni-liuling");
jstring jsex = (*env)->NewStringUTF(env, "jni-男"); //获取jfieldID
jfieldID nameId = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
jfieldID ageId = (*env)->GetFieldID(env, cls, "age", "I");
jfieldID sexId = (*env)->GetFieldID(env, cls, "sex", "Ljava/lang/String;");
(*env)->SetObjectField(env, obj, nameId, jname);
(*env)->SetIntField(env, obj, ageId, 18L);
(*env)->SetObjectField(env, obj, sexId, jsex); return obj;
} #ifdef __cplusplus
}
#endif
代码注释写的很详细,就不多讲了。
下面创建在jni目录下面创建编译文件Android.mk,内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := NDKDemo
LOCAL_SRC_FILES := com_example_ndkdemo_JniClient.c
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
编译过程可以参考网上的,网上很多。下面是在android中调用的代码:
package com.example.ndkdemo; import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends ActionBarActivity { static {
System.loadLibrary("NDKDemo");
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//调用jni返回字符串
//Toast.makeText(MainActivity.this, JniClient.printStr(), Toast.LENGTH_LONG).show();
User user = new User("刘玲", 25, "男hahaah");
String name = JniClient.printUser(user);
Log.e("name", name + "");
// User user = JniClient.newUser("liuling", 18, "男");
// User user = JniClient.newUserNoArgs("liuling", 18, "男");
// Toast.makeText(MainActivity.this, user.toString(), Toast.LENGTH_LONG).show();
}
});
final EditText num1 = (EditText) findViewById(R.id.num1);
final EditText num2 = (EditText) findViewById(R.id.num2);
final EditText result = (EditText) findViewById(R.id.result);
Button addBtn = (Button) findViewById(R.id.addBtn); addBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int n1 = Integer.valueOf(num1.getText().toString().trim());
int n2 = Integer.valueOf(num2.getText().toString().trim());
int n3 = JniClient.addInt(n1, n2);
result.setText(n3 + "");
}
}); } }
这里要注意14-16行,一定要加载so文件。
简单JNI使用demo的更多相关文章
- Xamarin.Android再体验之简单的登录Demo
一.前言 在空闲之余,学学新东西 二.服务端的代码编写与部署 这里采取的方式是MVC+EF返回Json数据,(本来是想用Nancy来实现的,想想电脑太卡就不开多个虚拟机了,用用IIS部署也好) 主要是 ...
- mac实现jni的demo
今天在看ArrayList 源码时看到了System.arraycopy 这个方法,但是这个方法没有java实现. 后面一通查询查找,才知道 如下图 native是一个java调用c语言来实现的操作的 ...
- C#开发微信公众平台-就这么简单(附Demo)转载
C#开发微信公众平台-就这么简单(附Demo) 来源:https://www.cnblogs.com/xishuai/p/3625859.html#!comments 写在前面 阅读目录: 服务号和 ...
- C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序
C#中缓存的使用 缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可: <%@ Outp ...
- 简单数学算法demo和窗口跳转,关闭,弹框
简单数学算法demo和窗口跳转,关闭,弹框demo <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...
- Maven+SpringMVC+Dubbo 简单的入门demo配置
转载自:https://cloud.tencent.com/developer/article/1010636 之前一直听说dubbo,是一个很厉害的分布式服务框架,而且巴巴将其开源,这对于咱们广大程 ...
- Android调用Jni,非常简单的一个Demo
step1:创建一个android项目 Project Name:jnitest Build Target: Android 1.6 Application Nam ...
- vue+node+es6+webpack创建简单vue的demo
闲聊: 小颖之前一直说是写一篇用vue做的简单demo的文章,然而小颖总是给自己找借口,说没时间,这一没时间一下就推到现在了,今天抽时间把这个简单的demo整理下,给大家分享出来,希望对大家也有所帮助 ...
- EasyUI+MVC+EF简单用户管理Demo(问题及解决)
写在前面 iframe-src EntityFramework版本 connectionStrings View.Action.页面跳转 EasyUI中DataGrid绑定 新增.修改和删除数据 效果 ...
随机推荐
- C#泛型(一)
简介: 先看看泛型的概念--“通过参数化类型来实现在同一份代码上操作多种数据类型.利用“参数化类型”将类型抽象化,从而实现灵活的复用”. 很多初学者在刚开始接触泛型的时候会比较难理解 “泛型” 在这里 ...
- 快速定位 Android APP 当前页面的三种方法(Activity / Fragment)
方法一.通过adb命令打印当前页面: Android 如何快速定位当前页面是哪个Activity or Fragment (1)查看当前Activity :adb shell "dumpsy ...
- python爬取百度贴吧帖子
最近偶尔学下爬虫,放上第二个demo吧 #-*- coding: utf-8 -*- import urllib import urllib2 import re #处理页面标签类 class Too ...
- zend studio调试
XDdebug搞了我一天 先把php.ini的代码发一下 [XDebug] zend_extension = "d:/WAMP/wamp/bin/php/php5.5.12/zend_ext ...
- tarjan 算法求强连通分量
#include<bits/stdc++.h> #define ll long long using namespace std; const int P=1e6; ; ; const i ...
- <构建之法>阅读笔记6
第九章:项目经理 是讲项目经理的作用功能和重要性,书里面主要讲的是微软的PM(Programe Manager)和其他团队PM(Project Manager)的区别,还介绍了PM的能力要求以及人物, ...
- P1197 [JSOI2008]星球大战 并查集 反向
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
- jquery $与jQuery
jquery的兼容 ie8 <script type="text/javascript" src="<%=path%>/js/jquery-3.1.1. ...
- mysql DISTINCT的用法
http://justcoding.iteye.com/blog/2116837 SELECT count(*) FROM tablename:百万级别的数据也能很快返回结果,但是如果加了where条 ...
- HDU 1025 城市供应 【LIS】
题目链接:https://vjudge.net/contest/228455#problem/A 题目大意: 有2n个城市,其中有n个富有的城市,n个贫穷的城市,其中富有的城市只在一种资源富有,且富有 ...