Android NDK基础样例
NDK(Native Development Kit),用C/C++封装一些东西?好像就这么理解好了==
一、环境准备
这个好讨厌==!因为我环境都已经搭了很久了。
已经搭建好,或者不一样环境的可以忽视。(当然看下也无妨撒^^)
1
)先说下我的环境吧
1、系统环境:XP。(总感觉在这上做这些事情不协调T^T)
2、运行环境:Eclispe+Cygwin。
2
)再说下这环境下的建议咯(不知道过时了没==
)
1、Eclispe重新下个C/C++版本,不要在原Android的Eclispe上加CDT组件了。貌似会有冲突。
(补充:
CDT 8.0.2
已不存在这个问题。我在配
Linux
下集成环境时一起装了没事)
2、Cygwin根目录\home\[your name]\ .bash_profile文件内配置下你的NDK路径、工程路径等。先这两样吧==
如果你的ndk路径是“E:\android-ndk-r6”,工作空间在“E:\studyspace”。
export NDKROOT="/cygdrive/e/android-ndk-r6"
export STUDYSPACE="/cygdrive/e/studyspace"
这个ndk版本有点低了哈,我自己笔记本上也有配,是比较高的版本(好像是r9吧)。
3
)怎么开始呢?
1、Eclispe+Cygwin先跑出个C工程的hello world!确定环境没什么问题。
2、在你的Android工程下建一个jni的目录(这个网上搜搜ndk开发,很多的。简要讲讲了,关键的再截个图吧==)
3、在你的C版Eclispe建立C++工程。注意取消Use default location,选择你工程下的jni目录。Project type选择Empty Project。Toolchains选择Other Toolchain。
![create.png]()
图1.3.3 创建工程注意项
4、右键工程属性,选中C/C++ Build,取消Use default build command,改为“bash --login -c "cd $STUDYSPACE/AndroidNDK && $NDKROOT/ndk-build"”。(cygwin下配的东西,你懂的,可以偷点懒==)
提示:ndk-build在很早版本时还没这个,要自己写什么什么的(不太清楚T^T)。总之,你应该不会很低版本的。
![create.png]()
图1.3.4 Build属性修改
5、继续选至C/C++ General的Paths and Symbols。右侧Includes的C++项目,增加include路径。继续假设你的ndk路径是“E:\android-ndk-r6”==,如果是Android 2.2工程。
Include的路径则为“E:\android-ndk-r6\platforms\android-8\arch-arm\usr\include”。
![create.png]()
图1.3.4 Include路径增加
6、把样例工程下的Android.mk、Application.mk复制到你的工程下。写完了你的程序后,仿照着修修改改就成了。
具体的你可以搜“Android.mk详解”什么的。至于Application.mk,你2.2以上要用到Bitmap.h呢,这个就必须加了(不加编译会有什么错误来着?不记得了==)
二、基础样例
这部分才是重点啊!多么切题。直接先看下运行的东西咯^^
![create.png]()
是不是更有看的动力了?还是你拉到下边直接下载去了==。(没被鄙视简单吧T^T)
1
)C
部分
1.1)TestJni.h
-
-
-
-
-
-
-
- #ifndef TESTJNI_H_
- #define TESTJNI_H_
-
- #include <jni.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <android/log.h>
- #include <android/bitmap.h>
-
-
- #include "CallJava.h"
-
- #define LOG_TAG "JNI_DEBUG"
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-
-
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
-
-
-
-
-
-
-
-
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_getStr(JNIEnv*,
- jobject);
-
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_callJava(JNIEnv*,
- jobject, int, int, int, int);
-
- JNIEXPORT void JNICALL Java_org_join_ndk_jni_TestJni_convertToGray(JNIEnv*,
- jobject, jobject);
-
-
- jintArray Java_org_join_ndk_jni_TestJni_getIntArray(JNIEnv*, jobject);
-
-
- jint getInt(JNIEnv*, jobject);
-
- #ifdef __cplusplus
- }
- #endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #endif /* TESTJNI_H_ */
1.2)TestJni.cpp
-
-
-
-
-
-
-
- #include "TestJni.h"
-
-
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_getStr(JNIEnv *env,
- jobject obj) {
- return env->NewStringUTF("I'm from C!");
- }
-
- int min(int x, int y) {
- return (x <= y) ? x : y;
- }
-
-
- JNIEXPORT jstring JNICALL Java_org_join_ndk_jni_TestJni_callJava(JNIEnv *env,
- jobject obj, int add_x, int add_y, int sub_x, int sub_y) {
- char str[128];
- int result_add = add(env, add_x, add_y);
- LOGE("==[%d+%d=%d]==", add_x, add_y, result_add);
- int result_sub = sub(env, sub_x, sub_y);
- LOGE("==[%d-%d=%d]==", sub_x, sub_y, result_sub);
-
- sprintf(str, "Hello, I'm Join! min=%d", min(result_add, result_sub));
- return env->NewStringUTF(str);
- }
-
- typedef struct {
- uint8_t red;
- uint8_t green;
- uint8_t blue;
- uint8_t alpha;
- } argb;
-
-
-
-
-
- JNIEXPORT void JNICALL Java_org_join_ndk_jni_TestJni_convertToGray(JNIEnv * env,
- jobject obj, jobject bitmap) {
- AndroidBitmapInfo info;
- void* pixels;
- int ret;
-
- LOGI("convertToGray");
- if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
- LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
- return;
- }
-
- LOGI(
- "color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d", info.width, info.height, info.stride, info.format, info.flags);
- if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
- LOGE("Bitmap format is not RGBA_8888 !");
- return;
- }
-
- if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
- LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
- }
-
-
-
- int x, y;
- uint8_t gray;
- for (y = 0; y < info.height; y++) {
- argb * line = (argb *) pixels;
- for (x = 0; x < info.width; x++) {
- gray = 0.3 * line[x].red + 0.59 * line[x].green
- + 0.11 * line[x].blue;
- line[x].red = line[x].green = line[x].blue = gray;
-
- }
-
- pixels = (char *) pixels + info.stride;
- }
-
- LOGI("unlocking pixels");
- AndroidBitmap_unlockPixels(env, bitmap);
-
- }
-
-
- jintArray Java_org_join_ndk_jni_TestJni_getIntArray(JNIEnv *env, jobject obj) {
- int array[] = { 12, 34 };
- jintArray result = env->NewIntArray(2);
- env->SetIntArrayRegion(result, 0, 2, array);
- return result;
- }
-
-
- jint getInt(JNIEnv *env, jobject obj) {
- return 256;
- }
1.3)回调相关
2
)Java
部分
2.1)TestJni
- public class TestJni {
-
-
- private static final String TAG = "TestJni";
-
-
-
-
- static {
- System.loadLibrary("TestJni");
- }
-
-
- public static native String getStr();
-
-
- public static int add(int x, int y) {
- Log.e(TAG, "==Java静态add方法==");
- return x + y;
- }
-
-
- public int sub(int x, int y) {
- Log.e(TAG, "==Java非静态sub方法==");
- return x - y;
- }
-
-
- public static native String callJava(int add_x, int add_y, int sub_x,
- int sub_y);
-
-
- public static native void convertToGray(Bitmap bitmap);
-
-
- public static native int[] getIntArray();
-
-
- public static native int getInt();
-
- }
2.2)AndroidNDKActivity
- public class AndroidNDKActivity extends Activity implements
- View.OnClickListener {
-
-
- private TextView text;
-
-
- private Button btn1, btn2, btn3, btn4, btn5;
-
-
- private ImageView imageView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
-
- text = (TextView) findViewById(R.id.text);
- btn1 = (Button) findViewById(R.id.btn1);
- btn1.setOnClickListener(this);
- btn2 = (Button) findViewById(R.id.btn2);
- btn2.setOnClickListener(this);
- btn3 = (Button) findViewById(R.id.btn3);
- btn3.setOnClickListener(this);
- btn4 = (Button) findViewById(R.id.btn4);
- btn4.setOnClickListener(this);
- btn5 = (Button) findViewById(R.id.btn5);
- btn5.setOnClickListener(this);
- imageView = (ImageView) findViewById(R.id.imageView);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.btn1:
-
- text.setText(TestJni.getStr());
- break;
- case R.id.btn2:
-
- text.setText(TestJni.callJava(2, 5, 8, 3));
- break;
- case R.id.btn3:
-
-
-
-
-
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
- R.drawable.ic_launcher);
-
- TestJni.convertToGray(bitmap);
- imageView.setImageBitmap(bitmap);
- break;
- case R.id.btn4:
-
- int[] array = TestJni.getIntArray();
- int len = array.length;
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < len - 1; i++) {
- sb.append(array[i]);
- sb.append(",");
- }
- sb.append(array[len - 1]);
- text.setText(sb.toString());
- break;
- case R.id.btn5:
-
- try {
- int value = TestJni.getInt();
- text.setText(String.valueOf(value));
- } catch (UnsatisfiedLinkError e) {
- text.setText("UnsatisfiedLinkError!");
- e.printStackTrace();
- }
- break;
- }
- }
- }
三、后记
也是整理的基础样例工程,嘿嘿!
注意:
1)需要2.2系统才可,用了Bitmap.h。
2)样例5(不按命名规则的那个),用jni对方法进行注册,不按要求写方法名也是可以的。
3)灰度化是用的标准公式:Gray = R*0.299 + G*0.587 + B*0.114(考虑效率的话,有移位公式)
4)在android-ndk-r6\platforms\android-8\arch-arm\usr\lib目录下是NDK提供的可调用库。(有OpenGL ES^^)