Android NDK JNI之HelloWorld两种方法汇总
来源:互联网 发布:淘宝crm软件排名 编辑:程序博客网 时间:2024/05/21 14:06
建立一个JNI工程的步骤:
(1)新建android工程
(2) 添加NDK路径
(3) 添加本地支持
(4) 给本地库起名
此时工程目录下会自动生成jni文件夹
此时Makefile也自动生成
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := hello.cpp include $(BUILD_SHARED_LIBRARY)(5) 编写准备生成本地库的cpp文件:hello.cpp
#include <jni.h> #include <string.h> extern "C" { JNIEXPORT jstring JNICALL Java_com_snail_helloworld_MainActivity_myhello(JNIEnv * env, jobject obj); }; JNIEXPORT jstring JNICALL Java_com_snail_helloworld_MainActivity_myhello(JNIEnv * env, jobject obj) { return env->NewStringUTF("Hello From CPP"); }注意
Java_com_snail_hello_MainActivity_myhello
Java 为固定的
com_snail_helloworld 为包名
MainActivity 为Activity名称
myhello 为上层调用的函数名
这几个命名一定要对应,否则上层调用会出现错误:
“java.lang.UnsatisfiedLinkError: Native method not found”
(1)JNIEnv * env:这个env可以看做是Jni接口本身的一个对象,在上一篇中提到的jni.h头文件中存在着大量被封装好的函数,这些函数也是Jni编程中经常被使用到的,要想调用这些函数就需要使用JNIEnv这个对象。例如:env->GetObjectClass()。(详情请查看jni.h)(2)jobject obj:如在Test类的main方法中有这样一段代码:
Test t=new Test(); t.firstTest();
这个jobject需要两种情况分析。上段代码中firstTest方法是一个非静态方法,在Java中要想调用它必须先实例化对象,然后再用对象调用它,那这个时候jobject就可以看做Java类的一个实例化对象,也就是obj就是t。如果firstTest是一个静态方法,那么在Java中,它不是属于一个对象的,而是属于一个类的,Java中用Test.firstTest()这样的方式来调用,这个时候jobject就可以看做是java类的本身,也就是obj就是Test.class。
(6)编译本地cpp生成库文件
在cmd下进入工程目录:
执行 ndk-build 进行编译(前提是NDK路径已经加入到Path环境变量中)
(6)在Activity中调用本地函数库
package com.snail.helloworld; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView myTextField = (TextView)findViewById(R.id.myText); myTextField.setText(myhello()); } public native String myhello(); static { System.loadLibrary("hello"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }运行,OK了.
{方法二:} 手动生成jni文件
(1) 新建Android工程.
(2) 生成.h头文件
编译工程之后,进入工程目录文件夹下,在控制台运行:
javah -classpath bin/classes -d jni com.example.hellojni.MainAcitivity ,然后就会在工程目录下生成一个jni文件夹,里面就会有.h的头文件了。网上很多都这么说,但实际上这里会遇到一个问题:
1. 有人提出方法,在工程目录下运行命令:javah -classpath src -d jni com.example.hellojni.MainAcitivity
就OK了。是的,这个是OK的。
2.还有一种方法:在工程目录下,上述命令中加上android.jar的classpath。也是可行的。也就是运行如下命令:javah -classpath F:\JNI\env\platforms\android-17\android.jar;bin/classes -d jni com.example.hellojni.MainActivity
这个命令,就是把android.jar的路径加了进去。这样,就能找到Activity类了。
头文件生成好了,刷新一下工程,就会看到如下的目录结构:
(3) 接下来编写.c的实现文件。
在jni文件夹右击,选择file,命名文件名字为HelloJni.c,确定。
然后打开新建的HelloJni.c文件,输入如下语句并保存:
#include <stdio.h>#include "HelloJni.h"jstring Java_com_example_hellojni_MainActivity_getHelloJniString (JNIEnv * env, jobject clazz){ return (*env)->NewStringUTF(env, "Hello Jni!");}这里要说明 一下,在方法一中是CPP文件,方法二中是.C文件.它们在使用JNIEnv时是有区别的,即
原因:参见jni.h中对于JNIEnv的定义:
#if defined(__cplusplus)typedef _JNIEnv JNIEnv;#elsetypedef const struct JNINativeInterface* JNIEnv;#endif
下面开始编写mk文件。在jni目录下创建一个Android.mk的文件.加入如下代码并保存.
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := HelloJniLOCAL_SRC_FILES := HelloJni.cinclude $(BUILD_SHARED_LIBRARY)
这里,主要注意两个地方:
LOCAL_MODULE := HelloJni 。这里的HelloJni就是你的库的名字,也就是你loadLibrary的字符串。生成出来的库是libHelloJni.so。
LOCAL_SRC_FILES := HelloJni.c 。这里的HelloJni.c就是c文件的名字。
下面打开Cygwin,进入到工程目录下,输入如下命令,并回车:
$NDK/ndk-build然后我们刷新工程,会发现,多了一个obj文件夹,和libs文件夹里面多了armeabi文件夹和里面的libHelloJni.so库。obj文件夹是没有用的,可以删掉了。
(5)加载so文件,运行程序
同方法一.
遇到的问题:
1. Eclipse 中没有NDK 标签
解决:要加入一个jar包到 Eclipse文件夹下的 “plugins”下面
http://jingyan.baidu.com/article/4d58d5413000a09dd4e9c0fe.html
2. 在xx.cpp中加入 jni方面的代码 就报错,到处是红线
- Type 'JNIEnv' could not be resolved
- Type 'JNICALL' could not be resolved
解决:是由于没有将jni.h 导入的缘故,而这个文件在ndk的目录下面。所以,参照以下步骤:
Project Properties -> C/C++ General -> Path and Symbols
选择include标签,Add -> $Android_NDK_HOME/platforms/android-14/arch-arm/usr/include
且选中All languages.最后Apply -> OK
这样错误就解决了。
3. uint16 uint8 Type 'uint16' could not be resolved
解决: http://bbs.csdn.net/topics/330246620
- Android NDK JNI之HelloWorld两种方法汇总
- Android JNI NDK HelloWorld
- JNI开发之HelloWorld(Android Studio+ndk-bundle)
- JNI开发之HelloWorld(Android Studio+ndk-bundle)
- Android Jni之Helloworld
- JNI+NDK HELLOWORLD!
- Android NDK开发之HelloWorld
- Windos下Android(ADT Bundle)配置NDK的两种方法------ADT、Cygwin、NDK配置汇总
- Windos下Android(ADT Bundle)配置NDK的两种方法------ADT、Cygwin、NDK配置汇总
- Windos下Android(ADT Bundle)配置NDK的两种方法------ADT、Cygwin、NDK配置汇总
- android JNI开发之 ----HelloWorld
- android NDK开发之NDK与JNI
- Android NDK之JNI陷阱
- Android之JNI和NDK
- Android NDK之JNI陷阱
- android 之 JNI 调用 NDK
- Android NDK之JNI陷阱
- Android NDK之JNI陷阱
- 大范围内素数的求法的效率问题
- UITableView整理
- hdu 1788 Chinese remainder theorem again(最小公倍数)
- pvr/pvr.ccz文件转png,使用ant脚本实现
- weblogic常用调优方法
- Android NDK JNI之HelloWorld两种方法汇总
- IOS跳转到系统界面
- VC++控件实现串口通信
- VC 系统托盘、气泡提示
- 怎样判断一个文件存在(vc)
- 点9图制作教程
- Android如何运行真机在eclipse上调试应用
- android图片加水印,文字
- E1载波