用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" ><TextViewandroid: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    := libHello
LOCAL_SRC_FILES := HelloJni.cppinclude $(BUILD_SHARED_LIBRARY)

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

6. 執行結果

Note:

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

Cannot run program "ndk-build": Unknown reason
Error: 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 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 的版本号

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

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

转载于:https://www.cnblogs.com/hrhguanli/p/3940172.html

Android JNI programming demo with Eclipse相关推荐

  1. ubuntu下的android JNI入门DEMO

    在网上找的jni demo在对着练习的时候,总是多多少少报错. 所以把自己的摸索记录下来 环境: Ubuntu 10.04 LTS eclipse: http://developer.android. ...

  2. android项目模块导入eclipse编译报错,android环信demo导入eclipse编译出错

    官网最新下载的android环信sdk,导入编译出错:java.lang.RuntimeException: Unable to instantiate application com.hyphena ...

  3. Android :JNI 回调demo

    Android :JNI 回调demo 一.AndroidStudioProjects\jnicallbackdemo\app\src\main\java\com\example\jnicallbac ...

  4. Android Jni 调用

    Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap5:j ...

  5. Android JNI --函数调用大全

    Chap1:JNI完全手册 最近在公司里做了一个手机的项目,需要JAVA程序在发送短信的时候和第三方的短信服务器连接.短信接口是用C++ 写的.琢磨了三天,大致搞懂了JNI的主体部分.先将心得整理,希 ...

  6. [转]Android JNI使用方法

    本文转自:http://www.open-open.com/lib/view/open1324909652374.html 经过几天的努力终于搞定了android JNI部分,下面将我的这个小程序和大 ...

  7. Android JNI初试之环境搭建,最新方式的HelloWorld

    前言 最近有个图片识别的需求.需要使用OpenCV,于是研究起了JNI,发现很多资料过旧.绕了大圈.踩了几个坑.总结一下. 什么是JNI Java Native Interface , 实现Java和 ...

  8. Android JNI开发入门之一

    JNI在Android系统中有着广泛的应用.Android系统底层都是C/C++实现的,上层提供的API都是Java的,Java通过JNI调用底 层的实现.比如:Android API多媒体接口Med ...

  9. Android JNI简单实例(android 调用C/C++代码)

    转载自 xiechengfa 最终编辑 xiechengfa Android JNI简单实例关键字: android.jni Android的jni实例 android 的应用程序(Dalvik VM ...

最新文章

  1. itmz文件如何打开_如何使用proteus8打开低版本proteus7的仿真文件?
  2. postman可以测试websocket吗_小海塔罗娱乐测试2021年可以脱单吗?
  3. Vue—基础概念—组建化
  4. asp.net core 3.0 中使用 swagger
  5. Spring JDBC和JdbcTemplate CRUD与DataSource示例
  6. 蓝牙技术联盟宣布开放蓝牙网关架构 IoT设备无须Wi-Fi即可联网
  7. 搭建Harbor docker镜像仓库
  8. Java10的新特性
  9. linux Boot目录满了之后的解决方法
  10. JS If...Else
  11. 网页编码utf8 gb2312 gbk的区别
  12. Linux下模拟多线程的并发并发shell脚本
  13. Java 拦截器自定义(添加响应头)
  14. 人工智能真的具有创造力?
  15. 【WeNews】三胞债务重组方案出炉 650亿元金融债务如何化解
  16. Fractions (水)
  17. 相关矩阵 Correlation matrix
  18. 零数科技成功通过CMMI3级认证,软件研发能力获国际认可
  19. 解决中文乱码问题:使用编码转换工具
  20. 什么是ui设计师:ui设计学什么内容

热门文章

  1. Oracle 11g 数据恢复 数据误删除后的恢复 0、执行 select log_mode from v$database;查看是否为归档模式 1、确定删除时间和被删除的表 04-23,GR
  2. 评《货币战争》:问苍茫大地谁主沉浮? 第一次转这样的帖子
  3. JAVA程序员代表大众车,C++程序员代表捷豹,看看各类程序员们代表着什么车
  4. Chalubo僵尸网络来袭 IOT设备或将受到DDoS攻击
  5. 20165334 《java程序设计》第5周学习总结
  6. MongoDB联合查询 -摘自网络
  7. Erlang编程语言的一些痛点
  8. cacti+nagios整合(未成)
  9. postgresql 执行计划理解
  10. document.all用法