Android调用so库, so库是c语言编写, 在linux 64位系统+ndk(32位)生成 lib*.so (32位)

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)

本文所需软件如下:

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,

  1. /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib
  2. /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6
  3. /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 :

  1. /home/xxx/Desktop/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib

S4: Search directories->Complier , Add

  1. /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

  1. package com.lpr;
  2. class JniTestAndroid {
  3. public native byte[]  recognition(byte arr[]);
  4. static {
  5. System.loadLibrary("AndroidCallsoDemo");//Load  AndroidCallsoDemo.so produce by code::blocks
  6. //  System.out.println(System.getProperty("java.library.path"));
  7. //  System.setProperty("java.library.path", ".");
  8. }
  9. }

用 Javac 编译成 class文件

>cd E:\JniTestAndroid
>javac com/lpr/JniTestAndroid.java
>javah com.lpr.JniTestAndroid

现在生成了 com_lpr_JniTestAndroid.h

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_lpr_JniTestAndroid */
  4. #ifndef _Included_com_lpr_JniTestAndroid
  5. #define _Included_com_lpr_JniTestAndroid
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class:     com_lpr_JniTestAndroid
  11. * Method:    recognition
  12. * Signature: ([S)[B
  13. */
  14. JNIEXPORT jbyteArray JNICALL Java_com_lpr_JniTestAndroid_recognition
  15. (JNIEnv *, jobject, jbyteArray);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif

现在将com_lpr_JniTestAndroid.h拷贝到 Redhat 下面

并将 $java_home/include/jni.h 和 ./linux/jni_md.h 拷贝到 redhat 下面

在此特给出 jni_md.h 源码

  1. #ifndef _JAVASOFT_JNI_MD_H_
  2. #define _JAVASOFT_JNI_MD_H_
  3. #define JNIEXPORT
  4. #define JNIIMPORT
  5. #define JNICALL
  6. typedef long jint;
  7. typedef __int64 jlong;
  8. typedef signed char jbyte;
  9. #endif /* !_JAVASOFT_JNI_MD_H_ */

3.2)编写SO库

打开Code::Block新建(动态库)项目 AndroidCallsoDemo, 设置项目属性  参考上面的【 1.2  配置项目的环境】

添加 com_lpr_JniTestAndroid.h, jni.h,  jni_md.h 到项目(不添加也可以,只要放到项目的更目录即可)

main.cpp

  1. #include "stdio.h"
  2. #include "com_lpr_JniTestAndroid.h"
  3. JNIEXPORT jbyteArray JNICALL Java_com_lpr_JniTestAndroid_recognition
  4. (JNIEnv *jnienv, jobject jobj, jbyteArray byteArray)
  5. {
  6. /*    short*  iArray ; //=new short[maxSize];
  7. jboolean jbool = true;
  8. //转换数组
  9. iArray = jnienv->GetShortArrayElements(shortArray, &jbool);
  10. //...
  11. //
  12. jnienv->ReleaseShortArrayElements(shortArray,iArray,0);
  13. // do something with iArray ...
  14. // carnumber;
  15. */
  16. char carnumber[64]= {"你输入的是:"};
  17. jbyteArray  returnLPRArray = jnienv->NewByteArray( 64 );
  18. jbyte *retbytes = jnienv->GetByteArrayElements( returnLPRArray, 0);
  19. jbyte *bytes2 = jnienv->GetByteArrayElements(byteArray, 0);
  20. sprintf(carnumber, "%s %s",carnumber, bytes2);
  21. int nLPRLen = strlen(carnumber);
  22. //返回值最好是 byte,以免utf8造成汉字的影响
  23. for ( int i = 0; i < nLPRLen;  i++ )
  24. {
  25. retbytes[ i ] = carnumber[ i ];
  26. }
  27. jnienv->SetByteArrayRegion(returnLPRArray, 0, nLPRLen, retbytes );
  28. return   returnLPRArray ;
  29. }

几点注意:

1. 如果传入参数或传出参数有汉字或比较复杂的结构,建议都化为 jbyteArray, 特别是有关的汉字问题

4. Android编写

建立android项目 JniTestAndroid

activity_karl.xml //

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#F5F6F2"
  6. android:paddingBottom="@dimen/activity_vertical_margin"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. tools:context=".KarlActivity" >
  11. <TextView
  12. android:id="@+id/textView"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:gravity="center_horizontal"
  16. android:text="result"
  17. android:textSize="20sp" />
  18. <Button
  19. android:id="@+id/button1"
  20. android:layout_width="match_parent"
  21. android:layout_height="40dp"
  22. android:layout_below="@+id/textView"
  23. android:gravity="center_horizontal"
  24. android:text="Button" />
  25. </RelativeLayout>

拷贝  com.lpr.JniTestAndroid  到项目 src 下面

karlActivity.java

  1. package com.karl.jnitestandroid;
  2. import android.os.Bundle;
  3. import android.app.Activity;
  4. import android.view.Menu;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.TextView;
  9. import com.lpr.JniTestAndroid;
  10. public class KarlActivity extends Activity {
  11. private JniTestAndroid jni = new JniTestAndroid();
  12. private Button bt;
  13. private TextView textView;
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_karl);
  18. textView = (TextView)findViewById(R.id.textView);
  19. bt = (Button) findViewById(R.id.button1);
  20. bt.setOnClickListener(new OnClickListener(){
  21. @Override
  22. public void onClick(View arg0) {
  23. String str="中国北京123ABC";
  24. byte data[] =  jni.recognition(str.getBytes());
  25. String text = new String(data); //new String(data, "GB2312");
  26. textView.setText(text);
  27. }
  28. });
  29. }
  30. @Override
  31. public boolean onCreateOptionsMenu(Menu menu) {
  32. // Inflate the menu; this adds items to the action bar if it is present.
  33. getMenuInflater().inflate(R.menu.karl, menu);
  34. return true;
  35. }
  36. }

运行结果

5.  常见错误

5.1)  ld: error: cannot open crtbegin_so.o: No such file or directory

  1. 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
  2. /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)
  3. 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
  4. /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
  5. /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
  6. 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

  1. /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-readelf -a AndroidCallsoDemo.so

或者

  1. /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添加如下包含目录即可

  1. /home/xxx/Desktop/android-ndk-r9c/sources/cxx-stl/gnu-libstdc++/4.6/include
  1. /home/xxx/Desktop/android-ndk-r9c/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include

linux android ndk的更多相关文章

  1. Android NDK开发及调用标准linux动态库.so文件

    源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...

  2. Linux环境下使用Android NDK编译c/c++生成可执行文件

    1.安装Android NDK至Linux(Lubuntu 16) 从网上下载 android-ndk-r13b-linux-x86_64.zip,本人将其解压至/home/guanglun/work ...

  3. 在eclipse里配置Android ndk环境 适用于windows mac 和linux(转)

    在eclipse里配置Android ndk环境 适用于windows mac 和linux(转) 2012-02-27 13:02:16|  分类: android |  标签:java  prog ...

  4. Linux命令行下编译Android NDK的示例代码

    这几天琢磨写一个Android的Runtime用来加速HTML5 Canvas,让GameBuilder+CanTK 不但开发速度快,运行速度也能接近原生应用.所以花了点时间研究 Android ND ...

  5. Linux Ubuntu下用Android NDK 生成独立交叉编译链

    本文主要介绍使用Android NDK生成独立交叉编译链,然后使用独立交叉编译链编译Android程序 下载NDK 下载与自己操作系统相吻合的版本 下载地址 解压到安装目录(如~/myndk): ta ...

  6. linux下搭建android NDK开发环境

      1)下载android-ndk-r4 下载地址 http://www.ideasandroid.com/android/sdk/android-ndk-r4-linux-x86.zip http: ...

  7. 使用android ndk编译x86 so在linux下使用的问题

    一直以为android ndk编译x86 so库可以在linxu下运行,结果我试了几次都行不通.后来想了一下,android ndk编译的库应该只能在android设备或模拟器上运行才有效,后来改用 ...

  8. Android NDK开发Hello Word!

    在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...

  9. Android NDK开发初识

    神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...

随机推荐

  1. OpenGL ES 2.0 混合

    混合技术 混合技术就是将俩个片元调和,主要用于将通过各项测试准备进入帧缓冲的片元(源片元)与原有片元按照设定的比例加权计算出最终片元的颜色值. OpenGL ES 2.0中是通过设置混合因子来指定两个 ...

  2. Oracle11.2.0.4 RAC安装文档

    1 环境配置 参考官方文档<Grid Infrastructure Installation Guide for Linux> 1.1 软件环境 操作系统: [root@howe1 ~]# ...

  3. js delete 用法

    1,对象属性删除   function fun(){ this.name = 'mm'; } var obj = new fun(); console.log(obj.name);//mm delet ...

  4. canvas-js贝塞尔曲代码在线生成工具

    canvas贝塞尔曲代码在线生成工具 可以快速生成二次.三次贝塞尔曲线的源码生成器,方便经常使用到canvas画图的同学使用,可以直接预览效果随意画出自己想要的图像. 生成源码效果预览: canvas ...

  5. js学习(一)

    在javascript中,哪些值能作为if的条件呢? 1.布尔变量true/false 2.数字 非0数值为true, 0 或NaN为false. 3.对象 对象为null或undefined为fal ...

  6. CSS Hacks 总结

    CSS hack由于不同的浏览器,对CSS的解析认识不一样,因此会导致生成的页面效果不一样,我们就需要针对不同的浏览器去写不同的CSS,让他能在不同的浏览器中也能得到我们想要的页面效果. CSS ha ...

  7. mac qq截图功能失效后,如何重启截图功能?

    在finder中打开应用程序目录,找到QQ,右键单击QQ,选择显示包内容,此时会打开一个文件夹. 进入以下路径Library/LoginItems然后双击ScreenCapture这个进程,截图功能即 ...

  8. 文件:一个任务 - 零基础入门学习Python029

    文件:一个任务 让编程改变世界 Change the world by program 一个任务 这节课,我们需要一起来完成一个任务:将文件(record.txt)中的数据进行分割并按照以下规律保存起 ...

  9. 为什么1Byte=8bit

    Byte是字节的意思,而字节在早期计算机内部是用标准ASCII码来表示的根据当时情况确定至多有128种需要表示的字符(当时是IBM的标准,现在普遍是255),也就是2的7次方用二进制的0和1来表示就需 ...

  10. 25045操作标准子程序集41.C

    /* ;程 序 最 后 修 改 时 间 0-4-3 23:43 ;软 件 标 题:25045操作标准子程序集41 ;软 件 说 明:25045 I2C 串行EEPROM 驱动 ;___________ ...