Android调用so库(c语言编写) Codeblocks+adt-win-x86+ndk-r9c

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,

/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

点此处下载源码

QQ: 1505974441

[2014.2.18 14:26:00]


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值