Android调用so库(c语言编写) Codeblocks+adt-win-x86+ndk-r9c
2014-01-23 10:19
507 查看
Android调用so库, so库是c语言编写, 在linux 64位系统+ndk(32位)生成 lib*.so (32位)
编译软件:Code::Blocks
Android native开发库:android-ndk-r9c-linux-x86.tar.bz2
测试环境: Android手机(系统4.0及以上)
开发工具和SDK包: adt-bundle-windows-x86-20131030.zip(里面含有Eclipse)
本文所需软件如下:
android-ndk-r9c-linux-x86.tar.bz2 http://developer.android.com/intl/zh-cn/tools/sdk/ndk/index.html
adt-bundle-windows-x86-20131030.zip http://developer.android.com/intl/zh-cn/sdk/index.html
Code::Blocks http://www.codeblocks.org/downloads/binaries
然后启动Code::Blocks, 进行系统环境配置
1.1) 配置全局环境
S1: 打开 Settings-> Compiler and debugger...
S2: 选择编译器Selected complier -> GNU ARM GCC Complier,或自己新建一个
S3: 选择 Toolchain executables
S4: 设置android-ndk路径( Complier's installation directory ) ,如 /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86
S5: 设置Program Files各个编译程序
C complier: arm-linux-androideabi-gcc
C++ compiler: arm-linux-androideabi-g++
Linker for dynamic libs: arm-linux-androideabi-g++
Linker for static libs: arm-linux-androideabi-ar
Debugger: arm-linux-androideabi-gdb
Resource compiler:
S6: 设置Additional Paths, 增加(Add) : /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/arm-linux-androideabi/bin
S7: 设置 Search directories -> Compiler, 增加(Add) : /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/include
S8: 设置 Search directories -> Linker,
S9: 设置完成,点击确定
1.2) 配置项目的环境
S1: 右击项目,选择Build options, Selected Complier选择刚才设置的那个 GUN ARM GCC Compiler
S2: Compler settings -> Other options , 写入 -fPIC
S3: 设置 Search directories -> Linker, Add :
S4: Search directories->Complier , Add
2)Android 开发环境搭建
直接解压 adt-bundle-windows-x86-20131030.zip , 如解压到 E:\Program Files\adt\adt-bundle-windows-x86-20131030
就可以看到里面以及放好了eclipse, 此处的eclipse默认已经配置好了 adt, 启动 eclipse.exe 配置android虚拟机
菜单 Window -> Android Virtual Device Manager 管理虚拟机, Android SDK Manager 可以更新 SDK,由于此adt所带android系统是4.4, 建议再 更新 4.0.3 (
手动更新详见:
手动下载Android开发SDK
sdk:platform -> https://dl-ssl.google.com/android/repository/android-14_r03.zip
sdk:system-image -> https://dl-ssl.google.com/android/repository/sysimg_armv7a-14_r02.zip
)
如下图所示
新建一个虚拟机
新建Android项目JniTestAndroid ,建立包 com.lpr, 建类 JniTestAndroid
JniTestAndroid.java
用 Javac 编译成 class文件
现在将com_lpr_JniTestAndroid.h拷贝到 Redhat 下面
并将 $java_home/include/jni.h 和 ./linux/jni_md.h 拷贝到 redhat 下面
在此特给出 jni_md.h 源码
添加 com_lpr_JniTestAndroid.h, jni.h, jni_md.h 到项目(不添加也可以,只要放到项目的更目录即可)
main.cpp
几点注意:
1. 如果传入参数或传出参数有汉字或比较复杂的结构,建议都化为 jbyteArray, 特别是有关的汉字问题
activity_karl.xml //
拷贝 com.lpr.JniTestAndroid 到项目 src 下面
karlActivity.java
运行结果
原因是ld找不到 crtbegin_so.o 和 crteng_so.o, 解决方法是,在项目源码下面建立软连接
5.3) 使用STL
直接使用STL或用Opencv间接调用STL, 提示找不到 #include <algorithm> 等, 在工程的 Build Options -> Search directories -> Complier添加如下包含目录即可
点此处下载源码
QQ: 1505974441
[2014.2.18 14:26:00]
1. 所需软件环境:
1)so库开发环境
操作系统: Redhat Server 6.3 x86_64编译软件:Code::Blocks
Android native开发库:android-ndk-r9c-linux-x86.tar.bz2
[xxx@www ~]$ uname -a Linux www.teleframe.cn 2.6.32-279.el6.x86_64 #1 SMP Wed Jun 13 18:24:36 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux [xxx@www ~]$ cat /proc/version Linux version 2.6.32-279.el6.x86_64 (mockbuild@x86-008.build.bos.redhat.com) (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) ) #1 SMP Wed Jun 13 18:24:36 EDT 2012 [xxx@www ~]$ cat /etc/issue Red Hat Enterprise Linux Server release 6.3 (Santiago) Kernel \r on an \m
2) Android客户端开发
操作系统:Windows 7 x86测试环境: Android手机(系统4.0及以上)
开发工具和SDK包: adt-bundle-windows-x86-20131030.zip(里面含有Eclipse)
本文所需软件如下:
android-ndk-r9c-linux-x86.tar.bz2 http://developer.android.com/intl/zh-cn/tools/sdk/ndk/index.html
adt-bundle-windows-x86-20131030.zip http://developer.android.com/intl/zh-cn/sdk/index.html
Code::Blocks http://www.codeblocks.org/downloads/binaries
2. 环境搭建
1)Code::Blocks环境搭建
首先安装Code::Blocks, 然后解压 android-ndk-r9c-linux-x86.tar.bz2 , 如解压到桌面 /home/UserName/Desktop/android-ndk-r9c/然后启动Code::Blocks, 进行系统环境配置
1.1) 配置全局环境
S1: 打开 Settings-> Compiler and debugger...
S2: 选择编译器Selected complier -> GNU ARM GCC Complier,或自己新建一个
S3: 选择 Toolchain executables
S4: 设置android-ndk路径( Complier's installation directory ) ,如 /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86
S5: 设置Program Files各个编译程序
C complier: arm-linux-androideabi-gcc
C++ compiler: arm-linux-androideabi-g++
Linker for dynamic libs: arm-linux-androideabi-g++
Linker for static libs: arm-linux-androideabi-ar
Debugger: arm-linux-androideabi-gdb
Resource compiler:
S6: 设置Additional Paths, 增加(Add) : /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/arm-linux-androideabi/bin
S7: 设置 Search directories -> Compiler, 增加(Add) : /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/include
S8: 设置 Search directories -> Linker,
/home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6 /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6/armv7-a
S9: 设置完成,点击确定
1.2) 配置项目的环境
S1: 右击项目,选择Build options, Selected Complier选择刚才设置的那个 GUN ARM GCC Compiler
S2: Compler settings -> Other options , 写入 -fPIC
S3: 设置 Search directories -> Linker, Add :
/home/xxx/Desktop/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib
S4: Search directories->Complier , Add
/home/xxx/Desktop/android-ndk-r9c/platforms/android-14/arch-arm/usr/include
2)Android 开发环境搭建
直接解压 adt-bundle-windows-x86-20131030.zip , 如解压到 E:\Program Files\adt\adt-bundle-windows-x86-20131030
就可以看到里面以及放好了eclipse, 此处的eclipse默认已经配置好了 adt, 启动 eclipse.exe 配置android虚拟机
菜单 Window -> Android Virtual Device Manager 管理虚拟机, Android SDK Manager 可以更新 SDK,由于此adt所带android系统是4.4, 建议再 更新 4.0.3 (
手动更新详见:
手动下载Android开发SDK
sdk:platform -> https://dl-ssl.google.com/android/repository/android-14_r03.zip
sdk:system-image -> https://dl-ssl.google.com/android/repository/sysimg_armv7a-14_r02.zip
)
如下图所示
新建一个虚拟机
3. SO库编写
3.1)生成头文件
打开adt-bundle-windows里面的Eclipse新建Android项目JniTestAndroid ,建立包 com.lpr, 建类 JniTestAndroid
JniTestAndroid.java
package com.lpr; class JniTestAndroid { public native byte[] recognition(byte arr[]); static { System.loadLibrary("AndroidCallsoDemo");//Load AndroidCallsoDemo.so produce by code::blocks // System.out.println(System.getProperty("java.library.path")); // System.setProperty("java.library.path", "."); } }
用 Javac 编译成 class文件
>cd E:\JniTestAndroid >javac com/lpr/JniTestAndroid.java >javah com.lpr.JniTestAndroid现在生成了 com_lpr_JniTestAndroid.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_lpr_JniTestAndroid */ #ifndef _Included_com_lpr_JniTestAndroid #define _Included_com_lpr_JniTestAndroid #ifdef __cplusplus extern "C" { #endif /* * Class: com_lpr_JniTestAndroid * Method: recognition * Signature: ([S)[B */ JNIEXPORT jbyteArray JNICALL Java_com_lpr_JniTestAndroid_recognition (JNIEnv *, jobject, jbyteArray); #ifdef __cplusplus } #endif #endif
现在将com_lpr_JniTestAndroid.h拷贝到 Redhat 下面
并将 $java_home/include/jni.h 和 ./linux/jni_md.h 拷贝到 redhat 下面
在此特给出 jni_md.h 源码
#ifndef _JAVASOFT_JNI_MD_H_ #define _JAVASOFT_JNI_MD_H_ #define JNIEXPORT #define JNIIMPORT #define JNICALL typedef long jint; typedef __int64 jlong; typedef signed char jbyte; #endif /* !_JAVASOFT_JNI_MD_H_ */
3.2)编写SO库
打开Code::Block新建(动态库)项目 AndroidCallsoDemo, 设置项目属性 参考上面的【 1.2 配置项目的环境】添加 com_lpr_JniTestAndroid.h, jni.h, jni_md.h 到项目(不添加也可以,只要放到项目的更目录即可)
main.cpp
#include "stdio.h" #include "com_lpr_JniTestAndroid.h" JNIEXPORT jbyteArray JNICALL Java_com_lpr_JniTestAndroid_recognition (JNIEnv *jnienv, jobject jobj, jbyteArray byteArray) { /* short* iArray ; //=new short[maxSize]; jboolean jbool = true; //转换数组 iArray = jnienv->GetShortArrayElements(shortArray, &jbool); //... // jnienv->ReleaseShortArrayElements(shortArray,iArray,0); // do something with iArray ... // carnumber; */ char carnumber[64]= {"你输入的是:"}; jbyteArray returnLPRArray = jnienv->NewByteArray( 64 ); jbyte *retbytes = jnienv->GetByteArrayElements( returnLPRArray, 0); jbyte *bytes2 = jnienv->GetByteArrayElements(byteArray, 0); sprintf(carnumber, "%s %s",carnumber, bytes2); int nLPRLen = strlen(carnumber); //返回值最好是 byte,以免utf8造成汉字的影响 for ( int i = 0; i < nLPRLen; i++ ) { retbytes[ i ] = carnumber[ i ]; } jnienv->SetByteArrayRegion(returnLPRArray, 0, nLPRLen, retbytes ); return returnLPRArray ; }
几点注意:
1. 如果传入参数或传出参数有汉字或比较复杂的结构,建议都化为 jbyteArray, 特别是有关的汉字问题
4. Android编写
建立android项目 JniTestAndroidactivity_karl.xml //
<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:background="#F5F6F2" 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=".KarlActivity" > <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="result" android:textSize="20sp" /> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="40dp" android:layout_below="@+id/textView" android:gravity="center_horizontal" android:text="Button" /> </RelativeLayout>
拷贝 com.lpr.JniTestAndroid 到项目 src 下面
karlActivity.java
package com.karl.jnitestandroid; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import com.lpr.JniTestAndroid; public class KarlActivity extends Activity { private JniTestAndroid jni = new JniTestAndroid(); private Button bt; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_karl); textView = (TextView)findViewById(R.id.textView); bt = (Button) findViewById(R.id.button1); bt.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { String str="中国北京123ABC"; byte data[] = jni.recognition(str.getBytes()); String text = new String(data); //new String(data, "GB2312"); textView.setText(text); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.karl, menu); return true; } }
运行结果
5. 常见错误
5.1) ld: error: cannot open crtbegin_so.o: No such file or directory
arm-linux-androideabi-g++ -Wall -fexceptions -O2 -fPIC -I../android-ndk-r9c/platforms/android-14/arch-arm/usr/include -c main.cpp -o obj/Release/main.o /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/as: /lib/libz.so.1: no version information available (required by /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/as) arm-linux-androideabi-g++ -shared -L../android-ndk-r9c/platforms/android-14/arch-arm/usr/lib -L/home/haifeng/android/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib obj/Release/main.o -o bin/Release/libAndroidCallsoDemo.so -s /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtbegin_so.o: No such file or directory /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtend_so.o: No such file or directory collect2: ld returned 1 exit status
原因是ld找不到 crtbegin_so.o 和 crteng_so.o, 解决方法是,在项目源码下面建立软连接
cd /home/xxx/android/AndroidCallsoDemo/ ln -s /home/xxx/android/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib/crtend_so.o ./ ln -s /home/xxx/android/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib/crtbegin_so.o ./
5.2) 查看SO库的依赖库
查看PC linux 平台是用 ldd, 查看嵌入式的用 arm-linx-*-readelf/home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-readelf -a AndroidCallsoDemo.so或者
/home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-readelf -a AndroidCallsoDemo.so | grep "Shared"
5.3) 使用STL
直接使用STL或用Opencv间接调用STL, 提示找不到 #include <algorithm> 等, 在工程的 Build Options -> Search directories -> Complier添加如下包含目录即可
/home/xxx/Desktop/android-ndk-r9c/sources/cxx-stl/gnu-libstdc++/4.6/include
/home/xxx/Desktop/android-ndk-r9c/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include
点此处下载源码
QQ: 1505974441
[2014.2.18 14:26:00]
相关文章推荐
- 03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写
- 03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写
- QT, THE BETTER ANDROID NDK:Android Studio调用Qt编写的so库
- C语言 编写程序实现字符串拷贝,不允许调用strcpy函数。
- Android HDecoration项目so库导出和调用
- android如何调用dotnet编写的webservice
- 关于Android 添加系统级(java)服务和调用的编写实现说明
- android调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so
- C语言连接MySql数据库(CodeBlocks)
- C语言学习1:Windows搭建C语言开发环境,Code::Blocks安装,配置gcc编译器
- android开发ndk调用第三方so库
- linux中使用code::blocks编译c语言,出现g++ not found
- android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so
- android开发调用getresponsecode() 时会抛出 IOException
- 编写android对google地图的调用
- Android之项目中调用已有.so库
- php调用c语言编写的so动态库
- android使用C/C++调用SO库
- android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so
- android开发ndk调用第三方so库