一.使用工具
- NDK: Native Development kit
- CDT: C/C++ Development tools 本质上是一个eclipse插件
- Cygwin:在windows提供了一个unix模拟运行环境
二.NDK目录介绍
- docs 开发文档 推荐D:/android-ndk-r9d/documentation.html
- build *.mk 指导编译的配置文件
- platforms 系统头文件D:\android-ndk-r9d\platforms\android-18\arch-arm\usr\include
- prebuild 编译工具 make.exe 工程管理器
- samples 开发例子
- source 相关库的源码
- toolchains 交叉编译工具链
- ndk-build.cmd 谷歌提供的工程编译命令
三.JNI开发流程
- 阶段 编码
1.创建Android工程,用native声明本地方法
public native String helloFromC();
2.在工程新建jni,其中新建.c源文件
#include <jni.h> /** jni规定 本地方法名 Java_调用本地方法类所在的包名_类名_方法名 * JNIEnv * env java环境,提供函数供调用 * jobject obj 调用本地方法的对象 * * typedef const struct JNINativeInterface* JNIEnv; * JNIEnv <=> struct JNINativeInterface* * env : JNIEnv * <=> struct JNINativeInterface** * (*env)->NewStringUTF(); */ jstring Java_com_itheima_helloworld_MainActivity_helloFromC(JNIEnv *env, jobject obj){ //jstring (*NewStringUTF)(JNIEnv*, const char*); 把C字符串转化为java中字符串 // 把C字符串转化为java中字符串 return (*env)->NewStringUTF(env,"hello world"); }
阶段2 编译
3.在jni目录下新建Android.mk文件
LOCAL_PATH := $(call my-dir) #提定当前路径include $(CLEAR_VARS) #清除全局配置变量,LOCAL_XXX,除了LOCAL_PATH LOCAL_MODULE := hello #指定生成动态库名hello,生成的动态库文件libhello.so LOCAL_SRC_FILES := hello.c #指定生成动态库的源文件 include $(BUILD_SHARED_LIBRARY) #提定生成动态库
4.在jni目录下用ndk-build命令编译生成.so动态库(把ndk-build工具路径添加到path)
5.在类中加载动态库
static{ System.loadLibrary("hello");//加载动态库名而不动态库文件名 }
四. jni开发过程中常见错误
- 找不到动态库: Couldn’t load resultfr0mc: findLibrary returned null
- 可能原因库名写错;或者生成动态库与运行平台不符合
- 找不到方法: Caused by: java.lang.UnsatisfiedLinkError: Native method not found: com.itheima.resultfromc.MainActivity.resultFromC:(II)I
- 解决方法检查JNI函数名,
五.项目代码
MainActivity 代码
package com.example.helloworld;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity
{
static
{
System.loadLibrary("hello");
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public native String helloFromC();
public void click(View v)
{
Toast.makeText(this, helloFromC, Toast.LENGTH_LONG).show();
}
}
hello.c代码
#include <jni.h>
jstring Java_com_example_helloworld_MainActivity_helloFromC(JNIEnv *env, jobject obj)
{
return (*env)->NewStringUTF(env,"hello world");
}
Andorid.mk代码
LOCAL_PATH := $(call my-dir) #提定当前路径
include $(CLEAR_VARS) #清除全局配置变量,LOCAL_XXX,除了LOCAL_PATH
LOCAL_MODULE := hello #指定生成动态库名hello,生成的动态库文件libhello.so
LOCAL_SRC_FILES := hello.c #指定生成动态库的源文件
include $(BUILD_SHARED_LIBRARY) #提定生成动态库
布局代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:onClick="click"
android:text="调用C代码" />
</RelativeLayout>