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的更多相关文章

  1. Xamarin.Android再体验之简单的登录Demo

    一.前言 在空闲之余,学学新东西 二.服务端的代码编写与部署 这里采取的方式是MVC+EF返回Json数据,(本来是想用Nancy来实现的,想想电脑太卡就不开多个虚拟机了,用用IIS部署也好) 主要是 ...

  2. mac实现jni的demo

    今天在看ArrayList 源码时看到了System.arraycopy 这个方法,但是这个方法没有java实现. 后面一通查询查找,才知道 如下图 native是一个java调用c语言来实现的操作的 ...

  3. C#开发微信公众平台-就这么简单(附Demo)转载

    C#开发微信公众平台-就这么简单(附Demo)  来源:https://www.cnblogs.com/xishuai/p/3625859.html#!comments 写在前面 阅读目录: 服务号和 ...

  4. 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 ...

  5. 简单数学算法demo和窗口跳转,关闭,弹框

     简单数学算法demo和窗口跳转,关闭,弹框demo <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...

  6. Maven+SpringMVC+Dubbo 简单的入门demo配置

    转载自:https://cloud.tencent.com/developer/article/1010636 之前一直听说dubbo,是一个很厉害的分布式服务框架,而且巴巴将其开源,这对于咱们广大程 ...

  7. Android调用Jni,非常简单的一个Demo

    step1:创建一个android项目       Project Name:jnitest       Build Target: Android 1.6       Application Nam ...

  8. vue+node+es6+webpack创建简单vue的demo

    闲聊: 小颖之前一直说是写一篇用vue做的简单demo的文章,然而小颖总是给自己找借口,说没时间,这一没时间一下就推到现在了,今天抽时间把这个简单的demo整理下,给大家分享出来,希望对大家也有所帮助 ...

  9. EasyUI+MVC+EF简单用户管理Demo(问题及解决)

    写在前面 iframe-src EntityFramework版本 connectionStrings View.Action.页面跳转 EasyUI中DataGrid绑定 新增.修改和删除数据 效果 ...

随机推荐

  1. Slave SQL_THREAD如何重放Relay log

    复制的介绍: 根据日志定义的模式不一样,可以分为:Statement(SBR)模式,Row(RBR)格式或者是MIXED格式,记录最小的单位是一个Event,binlog日志前4个字节是一个magic ...

  2. Oracle学习笔记--第2章 oracle 数据库体系结构

    第2章 oracle 数据库体系结构 目录: ————————————— 2.1物理存储结构 2.1.1数据文件 2.2.2控制文件 2.1.3重做日志文件 2.1.4其他文件 2.2逻辑存储结构 2 ...

  3. python下载文件的方法

    前一段时间是爬文字,最近准备爬图片 找到了两种保存文件的方法 一种是用urllib.urlretrieve方法 #-*- coding: utf-8 -*- import urllib def cal ...

  4. json转成java对象

    avro生成的代码里,String是CharSequence,不能通过Gson反序列化,于是有了下面的代码,ParseArray里还不完善: static <T> List<T> ...

  5. php中$this->是什么意思

    $this 的含义是表示    实例化后的 具体对象! 我们一般是先声明一个类,然后用这个类去实例化对象! 但是,当我们在声明这个类的时候,想在类本身内部使用本类的属性或者方法.应该怎么表示呢? 例如 ...

  6. HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法

    这篇文章主要介绍了HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法,需要的朋友可以参考下 HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面 ...

  7. Win10 下 hadoop3.0.0 单机部署

    前言 因近期要做 hadoop 有关的项目,需配置 hadoop 环境,简单起见就准备进行单机部署,方便开发调试.顺便记录下采坑步骤,方便碰到同样问题的朋友们. 安装步骤 一.下载 hadoop-XX ...

  8. C# JSON帮助类(可互转)

    public class JsonHelper { public JsonHelper() { // // TODO: Add constructor logic here // } /// < ...

  9. Hbuilder ios证书申请

      最近负责app开发上线,一些心的总结 1.需要先用 苹果操作系统的证书管理  生成 .csr (多次使用) 2.进入开发者帐号 - 证书与配置c&p + App store and AD ...

  10. Lucene、ES好文章

    1.lucene4.5源码分析系列:lucene概述 http://blog.csdn.net/liweisnake/article/details/10348969 http://www.cnblo ...