• Android JNI programming demo with Eclipse


    用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();
    		
    	@Override
    	protected 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    := libHello
    LOCAL_SRC_FILES := HelloJni.cpp
    
    include $(BUILD_SHARED_LIBRARY)
    

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

    檔案結構


    6. 執行結果

    執行結果


    Note:

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

    Cannot run program "ndk-build": Unknown reason
    Error: Program "ndk-build" is not found in PATH
    
    PATH=[/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 clean
    Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 17 in /{project_folder}/AndroidManifest.xml   
    

    請改动AndroidManifest.xml 的minSdkVersion 或是到File->Properties->Android 改選 SDK 的版本号

    property_android_sdk

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

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

    toolchain

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

    build command


    延伸話題:

    在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    := libHello
    LOCAL_SRC_FILES := HelloJni.cpp
    
    LOCAL_LDLIBS := -llog 
    
    include $(BUILD_SHARED_LIBRARY)
    




  • 相关阅读:
    每日日报
    每日日报
    每日日报
    线上问题定位---jstack
    8.18Java入门--->第二十二节(ObjectOutputStream、ObjectInputStream)
    8.17Java入门--->第二十一节(IO流)
    Mybatis--->第六节一对多和多对一
    8.14Java入门--->第二十节
    8.13Java入门--->第十九节(Map嵌套)
    Java学习
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3940172.html
Copyright © 2020-2023  润新知