昨天Cygwin在线安装安到一半突然就停处了,这网太无耐了

上面搜“cygwin 离线”,注意:下载下来的东西解压后的文件夹是ftp%...,包含%,&之类的特殊字符,把文件夹

名改成123什么的,不然会很莫名其妙的。害哥搞这个离线包搞了个把小时。

为了清楚,上个图:

 

 

敲个LS,什么东西都没有,这个目录是cygwin的安装目录下面的home文件夹下的用户名文件夹。

接下来是配置与Android相关的。在home/用户名,这个文件夹下有一个文件为.bash_profile,打开它,到最后添

加两行NDK的环境变量:

NDK_ROOT=/cygdrive/d/android-ndk-r6

export NDK_ROOT

上面的意思是,ndk的目录是,d:/android-ndk-r6

添加完之后,关闭Cygwin重新启动一下,然后敲入cd $NDK_ROOT,是否进入到ndk的目录了?否则就看看哪个字

母错了。

在ndk的目录下samples下有很多例子,随便弄个就可编译了。下面是新建一个项目,以对C语言在项目中的位置

更清楚。

打开Eclipse新建一个Android项目,取名hellojni,为了清晰,便于维护,及各种各样的好处,JNI的JAVA代码单独

一个类,单独一个包。其实最好能不用JNI就别用JNI,这东西负作用巨大,特别是在用到JNI复杂的地方,什么

内存啊,类型啊,哪里调用的方法,异常啊,可靠性都非常麻烦。非要用JNI的复杂功能,做好两件事,做之前充

分设计,设计之前充分学习一下JNI文档。当然对于一些简单的应用,那只需要充分仔细。作好参数,返回值的检

查,记得释放内存就行了。

新建了一个JNI的类JNIClass,里面申明一个将在C语言中实现的方法。如下:

package com.jjie.jni;
public class JNIClass {
 public native int GetSumFromCFunc(int a, int b);
 }

C语言就是取两个数的和。

接下来在项目中新建一个文件夹jni,参考NDK目录下的sample中的hello-jni,把hello-jni中的jni目录下的

Android.mk拷贝到我们的项目中的jni文件夹,这个文件中的内容是告诉编译器要编译哪些文件,依赖哪些库,现

在里面很简单,照如下改动一下。

LOCAL_MODULE    := hellojni
 LOCAL_SRC_FILES := hellojni.c

就是把那个'-'去掉了,山寨一下。hellojni.c是需要实现JAVA中方法的文件,但是怎么把JAVA中的函数名与C中的对

应起来就是下一步,C语言中的函数名不是随便取的,是通过java生成的。

在Windows的cmd中,进入项目的bin目录,用javah对JNIClass.class进行生成C语言方法的头文件,注意是.class文

件,不是.java文件。

javah -jni com.jjie.jni.JNIClass

成功后,在bin文件夹下生成了一个.h的头文件。把这个文件放到项目的jni这个目录中,在这个目录中再新建一个

hellojni.c的文件用来实现java的方法,c函数的原型已经在刚刚的头文件中了:

JNIEXPORT jint JNICALL Java_com_jjie_jni_JNIClass_GetSumFromCFunc
   (JNIEnv *, jobject, jint, jint);

我们只有两个整型的参数就是最后两个,至于前面两个是什么意思,阅读JNI文档。这个头文件中还引用到jni.h,

#include <jni.h>,注意把<>改成"",在ndk的目录中搜索一个jni.h,把搜到的这个文件同样放到jni的目录中。

hellojni.c实现函数:

#include "com_jjie_jni_JNIClass.h"
JNIEXPORT jint JNICALL Java_com_jjie_jni_JNIClass_GetSumFromCFunc
   (JNIEnv *env, jobject this, jint a, jint b)
 {
  return a + b;
 }

接下来是编译,用到Cygwin了,编译是用到NDK目录下的ndk-build,进入到我们项目的目录,如下命令编译:

$NDK_ROOT/ndk-build

结果:

conan@conan-PC /cygdrive/d/workspace36/hellojni
 $ $NDK_ROOT/ndk-build
 Compile thumb  : hellojni <= hellojni.c
 SharedLibrary  : libhellojni.so
 Install        : libhellojni.so => libs/armeabi/libhellojni.soconan@conan-PC /cygdrive/d/workspace36/hellojni

在项目中刷新一下,发现多一个文件夹libs/armeabi/libhellojni.so。这个就是生成的库了,相当于Windows中的DLL

接下来就是去调用,在MainActivity中加载这个包,加载的时候注意去掉前缀lib。

在layout中的main.xml中的TextView加个id:   android:id="@+id/tvResult"

package com.jjie;
import com.jjie.jni.JNIClass;
import android.app.Activity;
 import android.os.Bundle;
 import android.widget.TextView;public class MainActivity extends Activity {
 private TextView textView = null;
  
  //加载库
  static {
   System.loadLibrary("hellojni");
  }
  
  /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
          setContentView(R.layout.main);         JNIClass jniClass = new JNIClass();
         //调用JNI中的方法
         int result = jniClass.GetSumFromCFunc(1, 6);
         
         textView = (TextView)this.findViewById(R.id.tvResult);
         textView.setText(String.valueOf(result));
         
     }
 }

运行吧。