×

windows7androidjni

windows7androidjni的简单介绍

admin admin 发表于2023-04-01 02:42:11 浏览52 评论0

抢沙发发表评论

本文目录一览:

如何在Android下使用JNI

Android中JNI是编译so库的源代码,编译成功后会生成SO库,android中最终是使用SO库的。

1.android的NDK开发需要在linux下进行: 因为需要把C/C++编写的代码生成能在arm上运行的.so文件,这就需要用到交叉编译环境,而交叉编译需要在linux系统下才能完成。

2.安装android-ndk开发包,这个开发包可以在google android 官网下载: 通过这个开发包的工具才能将android jni 的C/C++的代码编译成库

3.android应用程序开发环境: 包括eclipse、java、 android sdk、 adt等。

NDK编译步骤:

1.选择 ndk 自带的例子 hello-jni ,我的位于E:\android-ndk-r5\samples\hello-jni( 根据具体的安装位置而定 ) 。

2.运行 cygwin ,输入命令 cd /cygdrive/e/android-ndk-r5/samples/hello-jni ,进入到 E:\android-ndk-r5\samples\hello-jni 目录。-windows7androidjni

3.输入 $NDK/ndk-build ,执行成功后,它会自动生成一个 libs 目录,把编译生成的 .so 文件放在里面。 ($NDK是调用我们之前配置好的环境变量, ndk-build 是调用 ndk 的编译程序 )-windows7androidjni

4.此时去 hello-jni 的 libs 目录下看有没有生成的 .so 文件,如果有,ndk 就运行正常啦。

如何在android studio中用JNI调用静态库

Android.mk文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := static_add

LOCAL_SRC_FILES := libstatic_add.a

include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE := share_add

LOCAL_SRC_FILES := hello-jni.c

LOCAL_STATIC_LIBRARIES := static_add

LOCAL_C_INCLUDES := $(LOCAL_PATH)/jni/app/src/main/jni

LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY)

LOCAL_STATIC_LIBRARIES := static_add

这一行换成:

LOCAL_LDLIBS += -lstatic_add

或者

LOCAL_LDFLAGS += $(LOCAL_PATH)/libstatic_add.a(可以任意指定路径)

windows 下开发 android 需要安装 cygwin吗

一、Android NDK环境简介

Android NDK 是运行于Android 平台上的Native Development Kit 的缩写。

Android 应用开发者可以通过NDK 调用C 或C++ 本地代码。

更多介绍参见:

二 、搭建Android NDK环境

安装cygwin

要在Windows 平台上进行NDK的开发,需要安装cygwin(一个在windows平台上模拟linux的软件),NDK 编译需要用到Cygwin 中的make 和gcc, 所以先来下载并安装Cygwin 关于cygwin 安装比较复杂,其下载地址:-windows7androidjni

安装步骤:

1.选择安装方式:

1)Install from Internet:直接从Internet上下载并立即安装(安装完成后,下载好的安装文件并不会被删除,而是仍然被保留,以便下次再安装)。

2)Download Without Installing:只是将安装文件下载到本地,但暂时不安装。

3)Install from Local Directory:不下载安装文件,直接从本地某个含有安装文件的目录进行安装。

2、选择第一项,然后点击下一步:

3、选择要安装的目录,注意,最好不要放到有中文和空格的目录里,似乎会造成安装出问题,其它选项不用变,之后点下一步:

4、上一步是选择安装cygwin的目录,这个是选择你下载的安装包所在的目录,默认是你运行setup.exe的目 录,直接点下一步就可以:

5、此时你共有三种连接方式选择:

1) Direct Connection:直接连接。

2) Use IE5 Settings:使用IE的连接参数设置进行连接。

3) Use HTTP/FTP Proxy:使用HTTP或FTP代理服务器进行连接(需要输入服务器地址、端口号)。

用户可根据自己的网络连接的实情情况进行选择,一般正常情况下,均选择第一种,也就是直接连接方式。然后再点击“下一步”,

6、 这是选择要下载的站点,在提供的下载站点中选择一个,选择后点下一步

7、 此时会下载加载安装包列表

8、Search是可以输入你要下载的包的名称,能够快速筛选出你要下载的包。那四个单选按钮是选择下边树的样式,默认就行,不用动。View默认是Category,建议改成full显示全部包再查,省的一些包被隐藏掉。左下角那个复选框是是否隐藏过期包,默认打钩,不用管它就行,下边开始下载我们要安装的包吧,为了避免全部下载,这里列出了后面开发NDK用得着的包:autoconf2.1、automake1.10、binutils、gcc-core、gcc- g++、gcc4-core、gcc4-g++、gdb、pcre、pcre-devel、gawk、make共12个包 -windows7androidjni

9、 然后开始选择安装这些包吧,点skip,把它变成数字版本格式,要确保Bin项变成叉号,而Src项是源码,这个 就没必要选了。

10、 下面测试一下cygwin是不是已经安装好了。

运行cygwin,在弹出的命令行窗口输入:cygcheck -c cygwin命令,会打印出当前cygwin的版本和运行状 态,如果status是ok的话,则cygwin运行正常。

然后依次输入gcc –version,g++ --version,make –version,gdb –version进行测试,如果都打印出版本信息和一些描述信息,非常高兴的告诉你,你的cygwin安装完成了!-windows7androidjni

安装 Android NDK

可到Android官网下载:

注意选择相应的版本下载,下载后将其解压就可以了。

配置cygwin,用UtriaEdit打开cygwin安装目录下的home/你的用户名/.bach-profile文件,在后面加上

NDK=/cygdrive/NDK安装路径

export NDK

两行,也可以在windows 下添加 环境变量 $NDK=NDK安装路径。

注意:这里如果是中文OS 使用记事本或者写字板打开编辑后,重新启动Cygwin 会报错(编码不同)。

(这部有可能不成功 需要用一个dos2unix.exe把bash_profile这个文件转下编码,具体下载地址大家自己找找) 我直接用的 notepad++ 修改的没有问题。

至此,我们就可以用安装好的NDK来编译一个简单的程序吧,我们选择ndk自带的例子hello-jni,我的位于d/android-ndk-r7c/samples/hello-jni (根据你具体的安装位置而定),-windows7androidjni

运行cygwin,输入命令cd /cygdrive/d/android-ndk-r7c/samples/hello-jni,进入到d/android-ndk-r7c/samples/hello-jni目录。-windows7androidjni

输入$NDK/ndk-build,执行成功后,它会自动生成一个libs目录,把编译生成的.so文件放在里面。($NDK是调用我们之前配置好的环境变量,ndk-build是调用ndk的编译程序)

如图:

现在我们终于可以用NDK来编译完成 jni 例子了 。 以上的需要命令来编译,下就用Eclipse CDT 插件来完成

安装CDT插件

CDT是一个使Eclipse支持C/C++的插件。这是下载地址:

可以通过在Eclipse 中 help Install New Software 中安装, 现在,进入Help – Install New Software菜单项,增加一项:CDT - , 等待更新项目树加载,然后选中Programming Languages分支下的Eclipse C/C++ Development Tools,然后点击Next按钮。按照后续的提示,接受缺省的选项,最后必须接受许可,以便让Eclipse完成更新。完成后,你将会看到要求重启Eclipse的提示,点击Yes按钮,等待Eclipse重启。现在你的Eclipse就支持C/C++了。-windows7androidjni

也可以下载插件到本地 ,从本地安装插件。(网络有时候比较。。。)

注意,下载对应 Eclipse 版本的插件 附正版本图

配置C/C++的编译器

1、 打开eclipse,导入ndk自带的hello-jni例子,右键单击项目名称,点击Properties,弹出配置界面,之后再点击Builders,弹出项目的编译工具列表,之后点击New,新添加一个编译器,点击后出现添加界面,选择Program,点 击OK-windows7androidjni

2、出现了添加界面,首先给编译配置起个名字,如:C_Builder

设置Location为你cygwin安装路径\bin\bash.exe程序,例如:E:\cygwin\bin\bash.exe,设置Working Directory为你cygwin安装路径\bin目录,例如:E:\cygwin\bin-windows7androidjni

设置Arguments为

--login -c "cd /cygdrive/d/android-ndk-r7c/samples/hello-jni $NDK/ndk-build"

上面的配置中 d/android-ndk-r7c/samples/hello-jni 是你当前要编译的程序的目录,$NDK是之前配置 的ndk的环境变量,这两个根据你具体的安装目录进行配置,其他的不用变,Arguments这串参数实际是 给bash.exe命令行程序传参数,进入要编译的程序目录,然后运行ndk-build编译程序-windows7androidjni

3、接着切换到Refresh选项卡,给Refresh resources upon completion打上钩

4、然后切换到Build Options选项卡,勾选上最后三项

5、之后点击Specify Resources按钮,选择资源目录,勾选你的项目目录即可

6、 最后点击Finish,点击OK一路把刚才的配置都保存下来,注意:如果你配置的编译器在其它编译器下边,记得一定要点Up按钮,把它排到第一位,否则C代码的编译晚于Java代码的编译,会造成你的C代码要编译两次才能看到最新的修改-windows7androidjni

7、 编译配置也配置完成啦,现在来测试一下是否可以自动编译呢,当你点击 ok 完成之后 其实在console 就可以看到 自动编译信息

如图:

打开项目jni目录里的hello-jni.c文件把提示Hello from JNI!改成其他的文字:如:Hello,My name is 。。。。,然后再模拟器中运行你的程序,模拟器中应该就显示了你最新修改的文字! 如果以上的步骤都没错的话。-windows7androidjni

如何在android的jni线程中实现回调

在Android系统的解决方案是:

把c/c++中所有线程的创建,由pthread_create函数替换为由Java层的创建线程的函数AndroidRuntime::createJavaThread。

假设有c++函数:

[cpp] view plaincopy

void *thread_entry(void *args)

{

while(1)

{

printf("thread running...\n");

sleep(1);

}

}

void init()

{

pthread_t thread;

pthread_create(thread,NULL,thread_entry,(void *)NULL);

}

init()函数创建一个线程,需要在该线程中调用java类Test的回调函数Receive:

[cpp] view plaincopy

public void Receive(char buffer[],int length){

String msg = new String(buffer);

msg = "received from jni callback:" + msg;

Log.d("Test", msg);

}

首先在c++中定义回调函数指针:

[cpp] view plaincopy

//test.h

#include pthread.h

//function type for receiving data from native

typedef void (*ReceiveCallback)(unsigned char *buf, int len);

/** Callback for creating a thread that can call into the Java framework code.

* This must be used to create any threads that report events up to the framework.

*/

typedef pthread_t (* CreateThreadCallback)(const char* name, void (*start)(void *), void* arg);

typedef struct{

ReceiveCallback recv_cb;

CreateThreadCallback create_thread_cb;

}Callback;

再修改c++中的init和thread_entry函数:

[cpp] view plaincopy

//test.c

#include stdio.h

#include stdlib.h

#include pthread.h

#include sys/wait.h

#include unistd.h

#include "test.h"

void *thread_entry(void *args)

{

char *str = "i'm happy now";

Callback cb = NULL;

int len;

if(args != NULL){

cb = (Callback *)args;

}

len = strlen(str);

while(1)

{

printf("thread running...\n");

//invoke callback method to java

if(cb != NULL cb-recv_cb != NULL){

cb-recv_cb((unsigned char*)str, len);

}

sleep(1);

}

}

void init(Callback *cb)

{

pthread_t thread;

//pthread_create(thread,NULL,thread_entry,(void *)NULL);

if(cb != NULL cb-create_thread_cb != NULL)

{

cb-create_thread_cb("thread",thread_entry,(void *)cb);

}

}

然后在jni中实现回调函数,以及其他实现:

[cpp] view plaincopy

//jni_test.c

#include stdlib.h

#include malloc.h

#include jni.h

#include JNIHelp.h

#include "android_runtime/AndroidRuntime.h"

#include "test.h"

#define RADIO_PROVIDER_CLASS_NAME "com/tonny/Test"

using namespace android;

static jobject mCallbacksObj = NULL;

static jmethodID method_receive;

static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {

if (env-ExceptionCheck()) {

LOGE("An exception was thrown by callback '%s'.", methodName);

LOGE_EX(env);

env-ExceptionClear();

}

}

static void receive_callback(unsigned char *buf, int len)

{

int i;

JNIEnv* env = AndroidRuntime::getJNIEnv();

jcharArray array = env-NewCharArray(len);

jchar *pArray ;

if(array == NULL){

LOGE("receive_callback: NewCharArray error.");

return;

}

pArray = (jchar*)calloc(len, sizeof(jchar));

if(pArray == NULL){

LOGE("receive_callback: calloc error.");

return;

}

//copy buffer to jchar array

for(i = 0; i len; i++)

{

*(pArray + i) = *(buf + i);

}

//copy buffer to jcharArray

env-SetCharArrayRegion(array,0,len,pArray);

//invoke java callback method

env-CallVoidMethod(mCallbacksObj, method_receive,array,len);

//release resource

env-DeleteLocalRef(array);

free(pArray);

pArray = NULL;

checkAndClearExceptionFromCallback(env, __FUNCTION__);

}

static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)

{

return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);

}

static Callback mCallbacks = {

receive_callback,

create_thread_callback

};

static void jni_class_init_native

(JNIEnv* env, jclass clazz)

{

method_receive = env-GetMethodID(clazz, "Receive", "([CI)V");

}

static int jni_init

(JNIEnv *env, jobject obj)

{

if (!mCallbacksObj)

mCallbacksObj = env-NewGlobalRef(obj);

return init(mCallbacks);

}

static const JNINativeMethod gMethods[] = {

{ "class_init_native", "()V", (void *)jni_class_init_native },

{ "native_init", "()I", (void *)jni_init },

};

static int registerMethods(JNIEnv* env) {

const char* const kClassName = RADIO_PROVIDER_CLASS_NAME;

jclass clazz;

/* look up the class */

clazz = env-FindClass(kClassName);

if (clazz == NULL) {

LOGE("Can't find class %s/n", kClassName);

return -1;

}

/* register all the methods */

if (env-RegisterNatives(clazz,gMethods,sizeof(gMethods)/sizeof(gMethods[0])) != JNI_OK)

{

LOGE("Failed registering methods for %s/n", kClassName);

return -1;

}

/* fill out the rest of the ID cache */

return 0;

}

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

JNIEnv* env = NULL;

jint result = -1;

LOGI("Radio JNI_OnLoad");

if (vm-GetEnv((void**) env, JNI_VERSION_1_4) != JNI_OK) {

LOGE("ERROR: GetEnv failed/n");

goto fail;

}

if(env == NULL){

goto fail;

}

if (registerMethods(env) != 0) {

LOGE("ERROR: PlatformLibrary native registration failed/n");

goto fail;

}

/* success -- return valid version number */

result = JNI_VERSION_1_4;

fail:

return result;

}

jni的Android.mk文件中共享库设置为:

[cpp] view plaincopy

LOCAL_SHARED_LIBRARIES := liblog libcutils libandroid_runtime libnativehelper

最后再实现Java中的Test类:

[java] view plaincopy

//com.tonny.Test.java

public class Test {

static{

try {

System.loadLibrary("test");

class_init_native();

} catch(UnsatisfiedLinkError ule){

System.err.println("WARNING: Could not load library libtest.so!");

}

}

public int initialize() {

return native_radio_init();

}

public void Receive(char buffer[],int length){

String msg = new String(buffer);

msg = "received from jni callback" + msg;

Log.d("Test", msg);

}

protected static native void class_init_native();

protected native int native_init();

}

android jni怎么使用

Android JNI开发需要so动态库、再把相应的so文件放在对应的文件夹下才可以使用。so文件需要c语言编程。