为什么需要JNI??
定义:Java Native Interface,即 Java本地接口
作用: 使得Java 与 本地其他类型语言(如C、C++)交互 .
在下面几种情况下,我们要使用JNI:
1、 程序当中用到了 JAVA API 不提供的特殊系统环境才会有的特征。而跨进程操作又不现 实。
2、 你可能想访问一些己有的本地库,但又不想付出跨进程调用时的代价,如效率,内存, 数据传递方面。
3、JAVA 程序当中的一部分代码对效率要求非常高,如算法计算,图形渲染等。
在 Java代码 里调用 C、C++等语言的代码 或 C、C++代码调用 Java 代码
特别注意:
JNI是 Java 调用 Native 语言的一种特性。
JNI 是属于Java 的,与 Android无直接关系。
JNI 的强大特性使我们在使用 Java 平台的同时,还可以重用原来的本地代码。作为虚拟机 实现的一部分,JNI 允许 Java 和本地代码间的双向交互。
Jni 函数命名:
对于传统的JNI编程来说,JNI方法跟Java类方法的名称之间有一定的对应关系,要遵循一定的命名规则,如下:
1)前缀: Java_
2) 类的全限定名,用下划线进行分隔(_):com_lms_jni_JniTest
3) 方法名:getTestString
3) jni函数指定第一个参数: JNIEnv *
4) jni函数指定第二个参数: jobject
5) 实际Java参数: jstring, jint …
6) 返回值的参数 : jstring, jint… 所以对于在Java类 com.lms.jni.HwDemo中的一个方法:
https://blog.csdn.net/conowen/article/details/7523145
修改CMakeLists.txt
由于是复制的demo工程的CMakeLists.txt文件,比较简单,不能够满足现有工程,需要修改一下。这里说一下常用的几个功能:
1,设置其他后缀文件(例如.S汇编文件)为可编译源文件:
set_property(SOURCE src/main/cpp/art/art_quick_dexposed_invoke_handler.S PROPERTY LANGUAGE C)
2,设置多个不定数量的源文件(也即使用星号通配符的方式):
file(GLOB native_srcs "src/main/cpp/.cpp" “src/main/cpp/dalvik/.cpp" "src/main/cpp/art/.cpp” “src/main/cpp/art/*.S”)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${native_srcs}
)
C调用Java:
步骤:
1,通过jobject获取调用类的jclass env-GetObjectClass(obj);
2,通过GetMethodID获取方法id. env->GetMethodId();
GetMethodID中sig参数是对函数的签名,也可以说标识,具体的格式为
(函数参数)返回值
类型符号对照表:
Java类型
符号
Boolean
Z
Byte
B
Char
C
Short
S
Integer
I
Long
L
Float
F
Double
D
Void
V
Object对象
L开头,包名/类名,”;”结尾,$标识嵌套类
数组
[内部类型
例子:
public void demo1(int a,int b){} //(II)V
public void demo2(String a){} //(Ljava/lang/String;)V
public void demo3(String [] arr){}//([Ljava/lang/String;)V
public int demo4(){return 0;}//()I
public boolean demo5(){return false;} //()Z
public String demo6(String [] a){ return “”;}//([java/lang/String;)Ljava/lang/String;
public String[] demo7(){return null;}//()Ljava/lang/String;
public void demo8(String[] a,String[] b){}//([Ljava/lang/String;[Ljava/lang/String;)V
public void demo8(String[] a,int b){}//([Ljava/lang/String;I)V
public void demo9(int[] a,int b){}//([II)V
3, 通过env调用方法,并传递相应的参数数据。env->CallVoidMethod();
现在来进行操作
创建好项目之后,来操作布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout
android:layout_weight="2"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="0dp">
<EditText
android:layout_weight="1"
android:id="@+id/e1"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<EditText
android:id="@+id/e2"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:layout_weight="5"
android:layout_width="match_parent"
android:layout_height="0dp">
<Button
android:id="@+id/b_jia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="加"
/>
<Button
android:id="@+id/jian"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="减"
/>
<Button
android:id="@+id/chu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="除"
/>
<Button
android:id="@+id/cheng"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="乘"
/>
</LinearLayout>
<TextView
android:id="@+id/sure"
android:layout_weight="3"
android:layout_width="match_parent"
android:layout_height="0dp">
</TextView>
测试类
package com.example.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
EditText editText1;
EditText editText2;
Button b1,b2,b3,b4;
TextView tv1;
float ff;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
editText1=findViewById(R.id.e1);
editText2=findViewById(R.id.e2);
b1=findViewById(R.id.b_jia);
b2=findViewById(R.id.jian);
b3=findViewById(R.id.cheng);
b4=findViewById(R.id.chu);
tv1=findViewById(R.id.sure);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
b3.setOnClickListener(this);
b4.setOnClickListener(this);
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public native String getString();
public native float jia(int a,int b);
public native float jian(int a,int b);
public native float cheng(int a,int b);
public native float chu(int a,int b);
@Override
public void onClick(View v) {
String s1 = editText1.getText().toString();
String s2 = editText2.getText().toString();
int a1 = Integer.parseInt(s1);
int b1 = Integer.parseInt(s2);
switch (v.getId()){
case R.id.b_jia:
ff = jia(a1, b1);
break;
case R.id.jian:
ff=jian(a1,b1);
break;
case R.id.cheng:
ff=cheng(a1,b1);
break;
case R.id.chu:
ff=chu(a1,b1);
break;
}
tv1.setText(ff+"");
}
}
native.lib.cpp操作
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_getString(JNIEnv *env, jobject instance) {
return env->NewStringUTF("aaaaaa");
}extern "C"
JNIEXPORT jint JNICALL
Java_com_example_myapplication_MainActivity_aaa(JNIEnv *env, jobject instance, jint c) {
return c+1;
}extern "C"
JNIEXPORT jfloat JNICALL
Java_com_example_myapplication_MainActivity_jia(JNIEnv *env, jobject instance, jint a, jint b) {
// TODO
return a+b;
}extern "C"
JNIEXPORT jfloat JNICALL
Java_com_example_myapplication_MainActivity_jian(JNIEnv *env, jobject instance, jint a, jint b) {
// TODO
return a-b;
}extern "C"
JNIEXPORT jfloat JNICALL
Java_com_example_myapplication_MainActivity_cheng(JNIEnv *env, jobject instance, jint a, jint b) {
// TODO
return a*b;
}extern "C"
JNIEXPORT jfloat JNICALL
Java_com_example_myapplication_MainActivity_chu(JNIEnv *env, jobject instance, jint a, jint b) {
// TODO
return a/b;
}