Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之——JNI初探

Android之——JNI初探

編輯:關於Android編程

 

這裡,我將用一個小例子的形式來幫助大家初探JNI的用法,首先,大家要先搭建好NDK環境,請大家先閱讀《Android之——NDK環境搭建》一文。

一、實現

這個小例子實現的功能就是,通過Android中的java代碼來調用C代碼實現java代碼與C代碼之間的交互。

1、布局文件

我們首先在布局文件activity_main.xml中,添加一個按鈕控件,並給按鈕控件設置一個點擊事件,具體代碼如下:

 

 

2、完善類MainActivity

1)定義本地方法

要實現JNI方法的調用,首先要在MainActivity中定義一個本地方法,java中本地方法是以native關鍵字定義的。

具體代碼如下:

 

public native String helloFromC()

 

2)用javah命令生成,h頭文件

用javah命令生成,h頭文件,前提是要配置好java環境變量,這裡我就不說怎麼配置環境變量了,相信稍微了解java的同學都知道。我們通過cmd命令行進入到MainActivity包所在的目錄。

如下圖:

height=357

然後輸入命令

 

javah -encoding UTF-8 包名.類名
其中,-encoding UTF-8是指定生成的.h頭文件的編碼為UTF-8,包名是類所在的包,類名就是包含本地方法的類名,類名不帶有.java後綴。

 

如下圖:

height=334

此時,在當前目錄下會生成一個.h頭文件。

如下圖:

height=248

3)實現C代碼

com_lyz_hdk_helloworld_MainActivity.h中生成的代碼如下:

 

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_lyz_hdk_helloworld_MainActivity */

#ifndef _Included_com_lyz_hdk_helloworld_MainActivity
#define _Included_com_lyz_hdk_helloworld_MainActivity
#ifdef __cplusplus
extern C {
#endif
/*
 * Class:     com_lyz_hdk_helloworld_MainActivity
 * Method:    helloFromC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_lyz_hdk_helloworld_MainActivity_helloFromC
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

 

在Android項目的根目錄新建JNI目錄,將com_lyz_hdk_helloworld_MainActivity.h文件拷貝到jni目錄下,然後新建hello.c文件,引入所需要的庫,

如下所示:

 

#include 
#include 
#include com_lyz_hdk_helloworld_MainActivity.h
在hello.c中實現Java_com_lyz_hdk_helloworld_MainActivity_helloFromC方法,返回相應的字符串

 

具體代碼如下:

 

JNIEXPORT jstring JNICALL Java_com_lyz_hdk_helloworld_MainActivity_helloFromC(JNIEnv *env , jobject obj){
	char *str = hello from c;
	jstring jstr = (**env).NewStringUTF(env, str);
	return jstr;
}
hello.c完整代碼如下:

 

 

#include 
#include 
#include com_lyz_hdk_helloworld_MainActivity.h

JNIEXPORT jstring JNICALL Java_com_lyz_hdk_helloworld_MainActivity_helloFromC(JNIEnv *env , jobject obj){
	char *str = hello from c;
	jstring jstr = (**env).NewStringUTF(env, str);
	return jstr;
}

 

4)在jni目錄下創建Android.mk

這個文件是Android實現JNI所必須的文件,而且文件名稱固定為Android.mk不能更改。這個文件裡的內容我們可以到ndk的docs目錄下找到ANDROID-MK.html文件,打開這個文件,找到以下代碼片段,拷貝到Android.mk文件中,注意要每一行不要有空格。

 

   LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := hello-jni
   LOCAL_SRC_FILES := hello-jni.c

   include $(BUILD_SHARED_LIBRARY)
其在文件中的位置如下圖:

 

\

其中:

LOCAL_PATH := $(call my-dir):當前文件所存在的目錄
call my-dir 得到當前我的文件的目錄
include $(CLEAR_VARS):配置信息初始化
LOCAL_MODULE := hello-jni:指定編譯完成後的2進制值可執行文件的名稱
LOCAL_SRC_FILES := hello-jni.c:指定你要編譯哪些C的源文件

include $(BUILD_SHARED_LIBRARY):編譯成動態的鏈接庫文件
include $(BUILD_STATIC_LIBRARY):編譯成靜態的鏈接庫文件

我要編譯的文件是hello.c,要生成的so為libhello.so所以我將上面的配置修改為以下代碼:

 

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c

include $(BUILD_SHARED_LIBRARY)
以上配置也就是Android.mk中的內容了。

 

如下圖:

\

這時,我們項目的jni目錄下的文件如下圖所示:

\

5)編譯生成so動態鏈接庫

我們打開cygwin,進入到項目的jni目錄下。

如下圖:

\

執行命令ndk-build

如下圖:

\

刷新項目工程,會在libs目錄下自動生成一個.so動態鏈接庫,

如下圖:

height=311

6)完善MainActivity

在MainActivity類中,寫一個靜態代碼塊,用於加載.so動態鏈接庫,注意,這裡我們生成的.so文件是libhello.so,我們在加載這個.so文件的時候,只需要傳入hello即可。

具體代碼實現如下:

 

//加載靜態代碼塊
static{
	System.loadLibrary(hello);
}
在按鈕的點擊事件中調動本地方法,同時將結果Toast出來。

 

具體代碼如下:

 

public void click(View v){
	Toast.makeText(this, c代碼的內容是:+helloFromC(), Toast.LENGTH_SHORT).show();
}
MainActivity整體代碼如下:

 

 

package com.lyz.hdk.helloworld;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

/**
 * 主程入口
 * @author liuyazhuang
 *
 */
public class MainActivity extends Activity {
	
	public native String helloFromC();
	//加載靜態代碼塊
	static{
		System.loadLibrary(hello);
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	@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;
	}
	
	public void click(View v){
		Toast.makeText(this, c代碼的內容是:+helloFromC(), Toast.LENGTH_SHORT).show();
	}
}

 

二、運行效果

height=369

三、溫馨提示:

 

本實例中,為了方面,我把一些文字直接寫在了布局文件中和相關的類中,大家在真實的項目中要把這些文字寫在string.xml文件中,在外部引用這些資源,切記,這是作為一個Android程序員最基本的開發常識和規范,我在這裡只是為了方便直接寫在了類和布局文件中。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved