/* http://my.oschina.net/lifj/blog/177087 */
上一篇讲了怎么配置NDK的开发环境。此次记录一下写一个Hello Jni的最简单的Android程序。java
这里,咱们须要作一下几步:
1.Layout中添加TextView的id。
2.MainActivity中声明native方法。
3.MainActivity中调用native方法。 android
咱们这里先不loadLibrary。先load总感受个人库尚未呢,先load作什么?有点莫名其妙。固然,你也能够先loadLibrary。看我的习惯了。shell
下面详细说明:
1.新建Android,名字,包名什么的随便取。一路下一步,生成以后,在默认生成的Activity的layout的TextView上加一个id。(这个都会吧)android:id="@+id/hello_jni"。此时的layout文件内容以下:app
<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" > <TextView android:id="@+id/hello_jni" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
2.在MainActivity.java中声明native方法。
public native String getHelloJniString();
3.在OnCreate()方法中获取TextView,并设置text。
((TextView)findViewById(R.id.hello_jni)).setText(getHelloJniString());
通过二、3两步以后的MainActivity.java文件内容以下:
ide
package com.example.hellojni; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { public native String getHelloJniString(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.hello_jni)).setText(getHelloJniString()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
这一步,你须要C/C++的语言基础。(这个简单的例子只须要简单的。)
按照大多数博客,会告诉你:编译工程以后,进入工程目录文件夹下,在控制台运行
javah -classpath bin/classes -d jni com.example.hellojni.MainAcitivity
,而后就会在工程目录下生成一个jni文件夹,里面就会有.h的头文件了。ui
实际上,你会遇到一个错误:
错误: 没法访问android.app.Activity
找不到android.app.Activity的类文件
是的,大多数人都会遇到这个问题,我对此表示疑问:那些写博客的人都本身试过没有?编码
怎么办呢?
1. 有人提出方法,在工程目录下运行命令:
javah -classpath src -d jni com.example.hellojni.MainAcitivity
就OK了。是的,这个是OK的。(这个命令和上面一个命令的区别就是 -classpath 不一样了。)
spa
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类了。
以上两种可行的获得.h头文件的方法,生成的.h文件的内容是不同的,你能够试试看。至于哪种比较好,我目前还不清楚。由于看谷歌NDK的samples里面(samples这个文件夹,就是NDK的示例程序目录,对咱们来讲,就是教程了)的头文件,彷佛是第一种方式。第二种方式却是没有见到过。
我我的仍是倾向于用第二种方式,虽然命令比较烦。。.net
头文件生成好了,刷新一下工程,就会看到以下的目录结构:
code
多了一个jni文件夹和里面的一长串名字的头文件。名字太长,咱们改短一点,改为HelloJni.h吧。省的麻烦。
接下来编写.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!"); }
下面开始编写mk文件。在jni目录下建立一个Android.mk的文件(A要大写哦!!否则编译会出错:
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk /home/aditya/android-ndk-r9/build/core/add-application.mk:176: *** Android NDK: Aborting... .
)。加入以下代码并保存(里面的一些命令先不了解也是能够的。):
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := HelloJni LOCAL_SRC_FILES := HelloJni.c include $(BUILD_SHARED_LIBRARY)
这里,主要注意两个地方:
LOCAL_MODULE := HelloJni 。这里的HelloJni就是你的库的名字,也就是你loadLibrary的字符串。生成出来的库是libHelloJni.so。
LOCAL_SRC_FILES := HelloJni.c 。这里的HelloJni.c就是c文件的名字。
下面打开Cygwin,进入到工程目录下,输入以下命令,并回车:
$NDK/ndk-build
出现以下画面,就说明ok了。
而后咱们刷新工程,会发现,多了一个obj文件夹,和libs文件夹里面多了armeabi文件夹和里面的libHelloJni.so库。obj文件夹是没有用的,能够删掉了。
最后一步,咱们再次进入MainActivity,加载库文件。加入后的代码以下:
package com.example.hellojni; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { static { System.loadLibrary("HelloJni"); } public native String getHelloJniString(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((TextView)findViewById(R.id.hello_jni)).setText(getHelloJniString()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } }
System.loadLibrary("HelloJni"); 这个字符串就是咱们在mk文件中写的LOCAL_MODULE的值。
好了,至此,咱们编码ok了。运行起来吧。