linux android ndk
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)
本文所需软件如下:
- 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项目 JniTestAndroid
activity_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
linux android ndk的更多相关文章
- Android NDK开发及调用标准linux动态库.so文件
源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...
- Linux环境下使用Android NDK编译c/c++生成可执行文件
1.安装Android NDK至Linux(Lubuntu 16) 从网上下载 android-ndk-r13b-linux-x86_64.zip,本人将其解压至/home/guanglun/work ...
- 在eclipse里配置Android ndk环境 适用于windows mac 和linux(转)
在eclipse里配置Android ndk环境 适用于windows mac 和linux(转) 2012-02-27 13:02:16| 分类: android | 标签:java prog ...
- Linux命令行下编译Android NDK的示例代码
这几天琢磨写一个Android的Runtime用来加速HTML5 Canvas,让GameBuilder+CanTK 不但开发速度快,运行速度也能接近原生应用.所以花了点时间研究 Android ND ...
- Linux Ubuntu下用Android NDK 生成独立交叉编译链
本文主要介绍使用Android NDK生成独立交叉编译链,然后使用独立交叉编译链编译Android程序 下载NDK 下载与自己操作系统相吻合的版本 下载地址 解压到安装目录(如~/myndk): ta ...
- linux下搭建android NDK开发环境
1)下载android-ndk-r4 下载地址 http://www.ideasandroid.com/android/sdk/android-ndk-r4-linux-x86.zip http: ...
- 使用android ndk编译x86 so在linux下使用的问题
一直以为android ndk编译x86 so库可以在linxu下运行,结果我试了几次都行不通.后来想了一下,android ndk编译的库应该只能在android设备或模拟器上运行才有效,后来改用 ...
- Android NDK开发Hello Word!
在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...
- Android NDK开发初识
神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...
随机推荐
- 编译Boost 详细步骤
vs2008编译boost [一.Boost库的介绍] Boost库是一个经过千锤百炼.可移植.提供源代码的C++库,作为标准库的后备,是C++标准化进程的发动机之一. Boost库由C++标准委员会 ...
- PAT 65. A+B and C (64bit) (20)
题目链接:http://pat.zju.edu.cn/contests/pat-a-practise/1065 思路分析: 1)对a+b造成的long long 类型的数据溢出进行特殊处理: a> ...
- Mvc htmlhelper that generates a menu from a controller
Simple menu system that grabs a list of actions from a single controller and creates an unordered li ...
- WordPress插件制作教程(三): 添加菜单的方法
上一篇编写了一个简单的插件,让大家对插件的简单制作有个了解,这一篇我们在更深一步,当我们激活插件后后台会显示菜单出来,然后通过单击菜单显示自己定义好的信息.激活之后会在WordPress后台显示一个菜 ...
- 必须弄懂的495个C语言问题
1.1 我如何决定使用那种整数类型? 如果需要大数 值(大于32, 767 或小于¡32, 767), 使用long 型.否则, 如果空间很重要(如有大数组或很多结构), 使用short 型.除此之外 ...
- centos 6.4 更新源地址
执行如下命令: mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.old vim /etc/yum.repo ...
- 程序减肥,strip,eu-strip 及其符号表
程序减肥,strip,eu-strip 及其符号表 我们要给我们生成的可执行文件和DSO瘦身,因为这样可以节省更多的磁盘空间,所以我们移除了debug信息,移除了符号表信息,同时我们还希望万一出事了, ...
- ThreadPoolExecutor参数解析
ThreadPoolExecutor是一个非常重要的类,用来构建带有线程池的任务执行器,通过配置不同的参数来构造具有不同规格线程池的任务执行器. 写在前面的是: 线程池和任务执行器,线程池的定义比较直 ...
- unix c 11
多线程(thread) 操作系统支持多进程,进程内部使用多线程. 进程是 重量级的,拥有自己 独立的内存空间. 线程是 轻量级的,不需要拥有自己 独立的内存空间,线程的内存空间:1 ...
- /proc/uptime
在Linux中,我们常常会使用到uptime命令去看看系统的运行时间,它与一个文件有关,就是/proc/uptime.这个文件里的两个参数所代表的意义如下. [root@app ~]#cat /pro ...