Mac下使用Android的Jni生成动态库so文件,并打包到APK包说明

Android系统的底层库由C/C++编写,上层Android应用程序通过Java虚拟机调用底层接口。衔接底层C/C++库与Java应用程序间的接口正是JNI(Java  Native  Interface)。本文讲解如何在Mac下打包so库,并安装到APK中。

1、环境的安装

Android的环境安装ADT、NDK、SDK、JDK、ANT等一些环境的搭建,http://www.androiddevtools.cn/
在控制台下输入:vim  ~/.bash_profile,点击i,输入环境变量。如果之前没有配置过Android的环境,./bash_profile文件应该不存在。下面我把我的配置文件粘上来。
# Add environment variable COCOS_CONSOLE_ROOT for cocos2d-x
#export COCOS_CONSOLE_ROOT=/Users/chen/Desktop/cocos2d-x-3.0/tools/cocos2d-     console/bin
#export PATH=$COCOS_CONSOLE_ROOT:$PATH 
# Add environment variable NDK_ROOT for cocos2d-x
#export NDK_ROOT=/Users/chen/work_space/Cocos/android-ndk-r9b
#export PATH=$NDK_ROOT:$PATH  //以上#后面的都是注释,读者可忽略上面的内容
export NDK_ROOT=/Users/chen/work_space/Cocos/android-ndk-r9d //NDK
export ANDROID_SDK_ROOT=/Users/chen/work_space/Cocos/adt-bundle-mac-x86_64-20130917/sdk//SDK
export ANDROID_NDK_ROOT=/Users/chen/work_space/Cocos/android-ndk-r9d //NDK
export ANT_ROOT=/Users/chen/work_space/Cocos/apache-ant-1.9.3/bin//ANT
export PATH=$ANT_ROOT/bin:$PATH//添加环境变量
export PATH=$PATH:$ANT_ROOT
export PATH=$PATH:$NDK_ROOT
export PATH=$PATH:$ANDROID_SDK_ROOT
export PATH=$PATH:$ANDROID_NDK_ROOT
# Add environment variable COCOS_CONSOLE_ROOT for cocos2d-x
export COCOS_CONSOLE_ROOT=/Users/chen/Cocos/cocos2d-x-3.3rc0/tools/cocos2d-console/bin  //Cocos2d-x环境
export PATH=$COCOS_CONSOLE_ROOT:$PATH
export PATH=${PATH}:/Users/chen/work_space/Cocos/adt-bundle-mac-x86_64-20130917/sdk/platform-tools//红米手机链接Mac需要此步
# add by quick-cocos2d-x setup, DATE: 2014-11-15 TIME: 14:11:22
export QUICK_V3_ROOT=`cat ~/.QUICK_V3_ROOT`  //Quick环境                            
完成上面的配置,点电脑键盘esc键,在命令行输入":wq"即保存退出。注意环境路径不要有空格。
控制台下执行source   ~/.bash_profile,保存环境变量,关闭Mac的bash终端。重新打开,如果不报错,就环境变量添加成功。

2、验证安装

1)java  -version:检测JDK是否安装成功
2)ndk-build:验证NDK是否安装成功,在编译动态库时会用到该命令
3)ant -version:验证ANT是否安装成功

3、新建Android工程

打开Eclipse或ADT新建Android工程,此时的Android工程并没有jni这个文件夹。我们需要创建这个文件夹。在项目的根目录下添加一个jni文件夹。在文件夹下先添加3个文件,分别是Android.mk、Application.mk、hello-jni.c。下面分别介绍下这三个文件。
1)Android.mk是android编译时的makefile文件,需要将头文件、源文件、和库添加其中。我们打包的库文件即在该文件中添加。
下面是我的mk文件内容:
LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
 
include $(BUILD_SHARED_LIBRARY)
注意:":="是赋值的意思,"+="是追加的意思,"$"表示引用某变量的值。
1)LOCAL_PATH:当前文件的路径,即android.mk文件的路径。第一句话的意思就是将当前文件的路径返回给LOCAL_PATH
2)LOCAL_MODEL:表示模块的名字,唯一,且不含空格。必须在包含任一的$(BUILD_XXXX)的脚本之前定义它。模块的名字决定了生成库文件的名字。
3)LOCAL_SRC_FILE:表示将要编译的源代码。源码文件都是相对于当前文件路径的
4)LOCAL_STATIC_LIBRARIES:表示该模块需要使用哪些静态库,一边在编译时进行连接。
5)LOCAL_SHARED_LIBRARIES:表示模块在运行时依赖的动态库。
6)LOCAL_JNI_SHARED_LIBRARIES := libxxx这样在编译时NDK自动会把libxxx打包进apk,放在lib目录下
#编译静态库  
LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_MODULE = libhellos  
LOCAL_CFLAGS = $(L_CFLAGS)  
LOCAL_SRC_FILES = hellos.c  
LOCAL_C_INCLUDES = $(INCLUDES)  
LOCAL_SHARED_LIBRARIES := libcutils  
LOCAL_COPY_HEADERS_TO := libhellos  
LOCAL_COPY_HEADERS := hellos.h  
include $(BUILD_STATIC_LIBRARY)  
  
#编译动态库  
LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_MODULE = libhellod  
LOCAL_CFLAGS = $(L_CFLAGS)  
LOCAL_SRC_FILES = hellod.c  
LOCAL_C_INCLUDES = $(INCLUDES)  
LOCAL_SHARED_LIBRARIES := libcutils  
LOCAL_COPY_HEADERS_TO := libhellod  
LOCAL_COPY_HEADERS := hellod.h  
include $(BUILD_SHARED_LIBRARY)  
  
#使用静态库  
LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_MODULE := hellos  
LOCAL_STATIC_LIBRARIES := libhellos  
LOCAL_SHARED_LIBRARIES :=  
LOCAL_LDLIBS += -ldl  
LOCAL_CFLAGS := $(L_CFLAGS)  
LOCAL_SRC_FILES := mains.c  
LOCAL_C_INCLUDES := $(INCLUDES)  
include $(BUILD_EXECUTABLE)  
  
#使用动态库  
LOCAL_PATH := $(call my-dir)  
include $(CLEAR_VARS)  
LOCAL_MODULE := hellod  
LOCAL_MODULE_TAGS := debug  
LOCAL_SHARED_LIBRARIES := libc libcutils libhellod  
LOCAL_LDLIBS += -ldl  
LOCAL_CFLAGS := $(L_CFLAGS)  
LOCAL_SRC_FILES := maind.c  
LOCAL_C_INCLUDES := $(INCLUDES)  
include $(BUILD_EXECUTABLE)  

4、我的代码

1)修改src文件
package com.example.myhello;

import com.example.myhello.R;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		TextView tv = (TextView) findViewById(R.id.textView1);
//		tv.setText("Test");
		tv.setText(stringFromJNI());
		
	}
	
	public native String stringFromJNI();
	public native void printString(String info);
	
	static{
		System.loadLibrary("hello-jni");
	}
	
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}
2)添加jni文件夹
文件夹下添加Android.mk、Application.mk和hello-jni.c
(1)hello-jni.c
#include <string.h>
#include <jni.h>
#include <android/log.h>

JNIEXPORT jstring JNICALL
Java_com_example_myhello_MainActivity_stringFromJNI( JNIEnv* env,
                                                                  jobject thiz )
{
            return (*env)->NewStringUTF(env, "Hello from JNI !");
}

JNIEXPORT void JNICALL
Java_com_example_myhello_MainActivity_printString( JNIEnv* env,jobject thiz,jstring info)
{
            const jchar* strDest;
                strDest = (*env)->GetStringUTFChars(env,info,NULL);
                    if(strDest == NULL)
                                {
                                                return NULL;
                                                    }
                        __android_log_print(ANDROID_LOG_INFO, "printString", strDest);
                            (*env)->ReleaseStringUTFChars(env,info,strDest);
}
(2)Android.mk
LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_LDLIBS := -llog
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
 
include $(BUILD_SHARED_LIBRARY)
(3)Application.mk
由于我的ADT版本与NDK版本不符,所有会有一些警告当成了错误,所以,我的Application需添加如下代码
APP_CFLAGS += -Wno-error=format-security

5、编译动态库

1)cd到工程目录
2)ndk-build,编译生成so库
3)在src的文件中调用,即 MainActivity调用库中的文件,注意,一定要先加载库文件

6、编译运行





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值