操作环境:32bit Ubuntu12.04+Android编译环境
配置Android编译环境和NDK的过程不再叙述,下面记录一个完整的例子。例子功能是:按下button1,从jni中取出一个字符串到textview;按下button2,把两个editview的int值传递到jni进行加法运算然后返回结果到textview显示。顺便实现了最简单的jni的参数传递。
eclipse可以按照下面的步骤逐步建立,也可以下载整个工程文件,下载链接:http://download.youkuaiyun.com/detail/cleanness/6281613
1、打开eclipse,创建工程“MyJniTest”
XML如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="85dp"
android:text="Button" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="39dp"
android:text="Button" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignRight="@+id/button1"
android:layout_marginTop="35dp"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/button2"
android:layout_marginTop="42dp"
android:layout_toLeftOf="@+id/button2"
android:ems="10" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/editText1"
android:layout_alignBottom="@+id/editText1"
android:layout_alignParentRight="true"
android:layout_toRightOf="@+id/button2"
android:ems="10" />
</RelativeLayout>
MyJniTestActivity 如下:
package com.example.myjnitest;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MyJniTestActivity extends Activity implements OnClickListener{
public native int addint(int a,int b);
public native String StringFromJni();
private Button btn1;
private Button btn2;
private TextView text1;
private EditText edit1;
private EditText edit2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myjnitestxml);
btn1 = (Button)findViewById(R.id.button1);
btn2 = (Button)findViewById(R.id.button2);
text1 = (TextView)findViewById(R.id.textView1);
edit1 = (EditText)findViewById(R.id.editText1);
edit2 = (EditText)findViewById(R.id.editText2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
}
public void onClick(View v)
{
switch(v.getId())
{
case R.id.button1:
{
int a1 = Integer.parseInt(edit1.getText().toString());
int a2 = Integer.parseInt(edit2.getText().toString());
int a = addint(a1,a2);
String aa = String.valueOf(a);
text1.setText(aa);
}
break;
case R.id.button2:
{
text1.setText(StringFromJni());
}
break;
default:break;
}
}
static{
System.loadLibrary("MyJniTest");
}
}
2、用eclipse编译该工程,生成相应的.class文件,这步必须在下一步之前完成,因为生成.h文件需要用到相应的.class文件。
编译生成的class文件在你的bin目录先,比如我的是在/home/kang/workspace/MyJniTest/bin/classes/com/example/myjnitest/中有一个MyJniTestActivity.class既是生成的class文件。
3、生成",h"头文件
1)进入工程目录,方法:在终端执行 cd /home/kang/workspace/MyJniTest/
2)在工程目录下建立jni文件夹,方法:在终端执行 mkdir jni
3) 使用工具javah生成.h文件,方法:在终端执行 javah -classpath /home/kang/workspace/MyJniTest/bin/classes/ -d /home/kang/workspace/MyJniTest com.example.myjnitest.MyJniTestActivity
这条命令的意思是利用MyJniTestActivity.class在路径/home/kang/workspace/MyJniTest/jni生成.h文件
如果出现如下错误:
Error: cannot access android.app.Activity
class file for android.app.Activity not found
这一步出现的问题大部分都是路径错误,仔细检查路径即可解决。
4、编写c/c++文件
在Eclipse里面New->File->MyJniTest(选择项目)->jni(选择新建文件存放路径),填写File Name: MyJniTest.c(可任意命名)
#include<string.h>
#include<jni.h>
JNIEXPORT jint JNICALL Java_com_example_myjnitest_MyJniTestActivity_addint(JNIEnv * env,jobject thiz,jint a,jint b)
{
int c = a+b;
return c;
//return (*env)->NewStringUTF(env,"this is 1");
}
JNIEXPORT jstring JNICALL Java_com_example_myjnitest_MyJniTestActivity_StringFromJni(JNIEnv * env,jobject thiz,jint a,jint b)
{
return (*env)->NewStringUTF(env,"haha from .c");
}
在Eclipse里面New->File->MyJniTest(选择项目)->jni(选择新建文件存放路径),填写File Name: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=MyJniTest
LOCAL_SRC_FILES :=MyJniTest.c
include $(BUILD_SHARED_LIBRARY)
6、生成.so动态链接库
1)进入jni目录,方法:终端执行 cd /home/kang/workspace/MyJniTest/jni
2)用NDK工具生成动态链接库,方法:终端执行 ndk-build
成功后你会看到多了一个.so。
7、在eclipse中reflash工程,编译运行。
可能还会遇到其他的问题,大部分都是编译环境没有配置好,编译过程中路径没有取对的问题,仔细检查即可修复。