Android NDK入门

还是觉得Android文档太少,在之前的Android 中aidl如何import文件牢骚过一次了已经。于是我来尽微薄之力~

我理解的NDK是允许你把程序的一部分代码用C或C++来实现,通过JNI与Java代码交互。不要想整个程序都用C/C++完成,Android是不允许的,你的程序必须运行在Dalvik虚拟机里。

至于是什么任务需要用C/C++,那就不是我要討論的了,比如下面我要演示的这个傻逼程序就真不适合用NDK

安装NDK

你首先要保证自己的Android SDK已经安装完成,然后下载NDK,随便你解压到哪里。下面的$NDK代表你解压后的NDK路径

新建一个Android项目

如果你用Eclipse或者用Netbeans就不用我说了,记得项目名称是fuckGFW。

android create project -n fuckGFW -t 8 -p fuckgfw -k fuck.gfw -a FuckGFW

然后在项目根目录下建立一个jni文件夹,C/C++代码就要放在那里面

修改FuckGFW.java文件

你得懂JNI,我也是现学的。只是很普通的的JNI操作,内容如下

package fuck.gfw;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class FuckGFW extends Activity
{
  static {
    System.loadLibrary("fuckGFW");
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView tv = new TextView(this);
    tv.setText(fuck("GFW"));
    setContentView(tv);
  }

  private native String fuck(String what);
}

创建fuckgfw.c

还是得懂JNI才行,可以看看JNI简单入门。这个文件要放在jni目录里

#include <jni.h>
#include <stdlib.h>
#include <stdio.h>

JNIEXPORT jstring JNICALL Java_fuck_gfw_FuckGFW_fuck(JNIEnv *env, jobject obj, jstring what) {
  const jbyte *l_what;
  char  *result;

  l_what = (*env)->GetStringUTFChars(env, what, NULL);
  if (l_what == NULL) {
    return NULL; /* OutOfMemoryError already thrown */
  }

  result = malloc(strlen(l_what) + 6);
  if (result == NULL) {
    return NULL;
  }
  sprintf(result, "fuck %s", l_what);

  jstring r = (*env)->NewStringUTF(env, result);
  free(result);
  return r;
}

创建Android.mk

这个也要放在jni目录下。Android.mk就是一个Makefile罢了,不过是Android专用的,推荐查看NDK中的文档ANDROID-MK.TXT,很简洁易懂

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := fuckgfw.c

LOCAL_MODULE := fuckGFW

include $(BUILD_SHARED_LIBRARY)

编译运行

打开你的emulator,在项目目录里运行

$NDK/ndk-build
ant install

于是fuck GFW就已经出现了

13 COMMENTS >>LEAVE<<

  1. wayne

    依旧是那个nb项目名

  2. ABitNo
    @wayne

    我对她情有独钟啊--

  3. tmdab123
    @ABitNo

    和刚学编程的小弟演示IDE

    System.out.println("fuck GFW");

  4. cadmuxe

    我也想买一个。。

  5. Jacket

    請問
    创建fuckgfw.c这个文件要放在jni目录里
    jni目录是在哪?

  6. ABitNo
    @Jacket

    在项目的目录下新建一个就好

  7. mark

    請問ABitNo大大

    使用NDK時
    有沒有辦法只重新build JNI source code
    原本已經build好的.so檔不要重新rebuild
    不然每次修改JNI都必須整個重新rebuild
    工作過程會被拖慢

    謝謝

  8. ABitNo
    @mark

    你应该把ffmpeg和你自己程序的Android.mk分开来写,这样你修改自己的就不会影响另一个了

  9. laoren

    手动malloc有问题吧?

  10. t86010
  11. Neuron Teckid

    我同意上面 @laoren 同学所说这里 malloc 应该配上 free, 即

    return (*env)->NewStringUTF(env, result);

    应该改为

    jstring r = (*env)->NewStringUTF(env, result);
    free(result);
    return r;

    在博主另一篇 JNI 入门文章的例子 (也是官方例子) 中, 使用的 buf 是栈内变量, 可见传出的结果字符串与 C 中的缓冲区的生命周期没有关系, 不能指望 jvm 去释放它.

  12. ABitNo
    @Neuron Teckid

    非常感谢,已经更正。我这真是误人子弟啊

  13. rockman

    請教一下,若用NDK還需要產生.h檔這個步驟嗎?

LEAVE A RESPONSE >>CANCEL<<

loader