Android NDK開發起步Hello Jni

/*

http://my.oschina.net/lifj/blog/177087

*/


上一篇講了怎麼配置NDK的開發環境。此次記錄一下寫一個Hello Jni的最簡單的Android程序。java

一。新建Android程序工程。

這裏,咱們須要作一下幾步:
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;
	}

}


二。生成.h頭文件,編寫.c文件。

這一步,你須要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文件,使用Cygwin編譯出so文件。

下面開始編寫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文件夾是沒有用的,能夠刪掉了。

四。加載so文件,運行程序。

最後一步,咱們再次進入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了。運行起來吧。

相關文章
相關標籤/搜索