Android JNI programming demo with Eclipse

來源:互聯網
上載者:User

標籤:android   blog   http   os   java   使用   io   strong   for   

用Eclipse 建立 JNI 的專案, 示範怎樣在 JAVA 調用 cpp 的函數.

我們將建立一個名稱為 jnidemo的專案, 在主Activity 將調用一個名為libHello.so 的 cpp 函數庫的 getVersion() 的函數, 將其返回字串寫在主Activity 的TextView 上.


首先用Eclipse建立一個新的 Android Activity 專案.  其它選項都用預設值就能夠.

1. 略微改動主活動配置 layout/activity_main.xml,  的在TextView 添?名為 title 的id(行12)以便稍候引用

<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/title"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/hello_world" /></RelativeLayout>



2. 在MainActivity.java添?載入函式庫的動作並添加?一個native 函數名稱為 getVersion.

    改寫例如以下:

package com.example.jnidemo;import android.os.Bundle;import android.app.Activity;import android.widget.TextView;public class MainActivity extends Activity {static {System.loadLibrary("Hello"); // Hello.dll (Windows) or libHello.so (Unixes)}private native String getVersion();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = (TextView) findViewById(R.id.title);tv.setText( getVersion()); }}

3. 新增一個 jni 的目錄. 在jni 底下添?一個名為 HelloJni.cpp 的檔案.

/jni/HelloJni.cpp 內容例如以下

#include <jni.h>#include <stdio.h>#define JNIREG_CLASS "com/example/jnidemo/MainActivity"//指定要注冊的類extern "C" JNIEXPORT jstring JNICALL native_getVersion(JNIEnv *env, jobject thisObj) {   jstring szRet;   szRet = env->NewStringUTF("V1.0");   return szRet;}/**********************************************************************************/static JNINativeMethod gMethods[] = {{ "getVersion", "()Ljava/lang/String;", (void*)native_getVersion },};/** Register several native methods for one class.*/static int registerNativeMethods(JNIEnv* env, const char* className,        JNINativeMethod* gMethods, int numMethods){jclass clazz;clazz = env->FindClass( className);if (clazz == NULL) {return JNI_FALSE;}if (env->RegisterNatives( clazz, gMethods, numMethods) < 0) {return JNI_FALSE;}return JNI_TRUE;}/** Register native methods for all classes we know about.*/static int registerNatives(JNIEnv* env){if (!registerNativeMethods(env, JNIREG_CLASS, gMethods,                                 sizeof(gMethods) / sizeof(gMethods[0])))return JNI_FALSE;return JNI_TRUE;}extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){JNIEnv* env = NULL;jint result = -1;if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {return -1;}if (!registerNatives(env)) {//注冊return -1;}/* success -- return valid version number */result = JNI_VERSION_1_4;return result;}//onUnLoad方法,在JNI組件被釋放時調用extern "C" void JNI_OnUnload(JavaVM* vm, void* reserved){}
4. 在jni 底下添?一個名為 Android.mk 的檔案.

/jni/Android.mk 內容例如以下

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := libHelloLOCAL_SRC_FILES := HelloJni.cppinclude $(BUILD_SHARED_LIBRARY)

5.  專案的檔案結構例如以下:


6. 執行結果


Note:

編譯過程, 若發生例如以下錯誤

Cannot run program "ndk-build": Unknown reasonError: Program "ndk-build" is not found in PATHPATH=[/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/lib/jvm/jdk1.6.0_38/bin]

請到Window->Preferences->Android->NDK->NDL Location 填入ndk 安裝路徑


若出現例如以下錯誤

/opt/android/android-ndk-r9b/ndk-build cleanAndroid NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 17 in /{project_folder}/AndroidManifest.xml   

請改動AndroidManifest.xml 的minSdkVersion 或是到File->Properties->Android 改選 SDK 的版本號碼


其它可能影響編譯結果的設定:

C/C++ Build Toolchain 必須選 Android GCC Compiler


 

確認C/C++ Build command 是 ndk-build



延伸話題:

在cpp中怎樣把log 列印到logcat 的輸出呢? 在 cpp 檔及 Android.mk 要改動幾個地方

1. 在cpp 檔添? ALOGD, ALOGE 等函數的定義

#include <android/log.h>#define LOG_TAG "JniDemo"#define ALOGE(...)     __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__);#define ALOGW(...)     __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__);#define ALOGD(...)     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__);#define ALOGV(...)     __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__);

使用 debug level 的log輸出函數 ALOGD 範比例如以下

extern "C" JNIEXPORT jstring JNICALL native_getVersion(JNIEnv *env, jobject thisObj) {   jstring szRet;   szRet = env->NewStringUTF("V1.0");   ALOGD("native_getVersion");   return szRet;}

2. 在 Android.mk 指定載入liblog.so 函數庫

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := libHelloLOCAL_SRC_FILES := HelloJni.cppLOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)




Android JNI programming demo with Eclipse

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.