android里面有mk文件去使用原生代码,但还没试过,
如果要复制代码,务必删掉注释。代码里的注释格式都是c风格的 “//注释”,但下面基本没有c代码,因为是随手写的,所以并不正确,会导致错误。
概述就是如下三步
1.编写jni,提供java可调用的原生方法
2.编译c++代码为安卓可用的so库
3.使用原生方法
1:使用swig,是c++自动生成jni文件以及接口,省去大量人力。
----下载swigwin,给swig.exe配置path环境变量
----编写脚本:只写了一点点自己用到的,更详细的去swig官网看文档吧。3.0版本链接http://www.swig.org/Doc3.0/SWIGDocumentation.html#CONTENTS
swig是脚本语言,务必注意顺序,举个顺序错误的例子:
%include "VTManager.h"
%include <std_string.i>
因为先处理VTManager.h,再添加std_string的操作,所以VTManager.h里的string就不会被识别,会变成SWIGTYPE_p_std_string这个错误类型。
%module(directors="1") ChcVtCore_swig //“ChcVtCore_swig”是生成文件名,可修改,其他不改
//%{ %} 里面是引用的头文件,注意是#开头
%{
#include "ParseDef.h"
#include "ObjectPool.h"
#include "ParseDataList.h"
#include "VTManager.h"
%}
//%include 注意是%开头 外面是要暴露给java的头文件,而*.i是swig自己脚本头文件,仅仅是添加一些操作
//添加<std_string.i> 可以转换string,不然string会变成SWIGTYPE_p_std_string类型
%include <std_vector.i>
%include <stdint.i>
%include <windows.i>
%include <std_string.i>
//重命名命令。%(firstuppercase)s 是首字母大写。%$isclass是仅修改类名,""是默认参数。
%rename("%(firstuppercase)s", %$isclass) "";
//要暴露给java的头文件
%include "ParseDef.h"
%include "ObjectPool.h"
%include "ParseDataList.h"
%include "VTManager.h"
//使用vector必须使用 %include <std_vector.i>
//在搭配%template(类名)std::vector<列表对象名>;
%template(ObjectDataVector) std::vector<chcVT::SubObject>;
%template(CharDataVector) std::vector<uint8_t>;
%template(LanguagesDataVector) std::vector<uint16_t>;
%template(SubPointVector) std::vector<chcVT::SubPoint>;
%template(ActGraphicDataVector) std::vector<chcVT::ActGraphic>;
%template(ObjectIndexVector) std::vector<chcVT::ObjectIndex>;
得到一堆java文件,和一个cxx,这个cxx就是java中使用的c接口,也就是编写好的jni文件,
2.使用cmake + 交叉工具链 编译,这些ndk都提供了。CmakeLists要自己写。
CmakeLists.txt是组织和编译cpp和h的文件,名字不要错,cmake是要找这个文件的
cmake是跨平台编译器,如果目标是vs,会生成sln。我们的目标是android。
切记放入上面生成的cxx,jni是通道,不然java到不到c函数入口。
project(CGALhellworld) //项目名称,如果目标是vs,会是sln的名称
cmake_minimum_required(VERSION 3.1) //版本申明
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_options(-fPIC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic") //cmake.exe的环境变量。具体百度cmake配置
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpic")
include_directories(./3rdParty/windows/include)//include路径
aux_source_directory(./AreaCaculate Allcpp )//添加AreaCaculate这个文件夹下的所有cpp,并命名为allcpp
link_directories(./3rdParty/android/lib/32) //添加静态库路径
//add_library是生成库的意思,生成exe是add_execute
add_library(
AreaCaculate //库名/程序名
SHARED //共享库
${Allcpp})//放入cpp,可以使用绝对路径一个一个写
set_property(TARGET AreaCaculate PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(AreaCaculate liblog.so)//添加所需静态库(目标名 库名),这个是log库。可以在c++里直接写loge打印日志
bat脚本:camke编译 省得每次都输入了。
//ndk路径储存为一个变量
SET ANDROID_NDK=D:\mysdk\android-ndk-r14b
//新建一个文件夹,作为编译的场所,可以删掉
rmdir /S /Q build_android
mkdir build_android && cd build_android
//使用cmake编译,具体参数如下
//DCMAKE_TOOLCHAIN_FILE 是交叉工具链,使用相对路径指向ndk
//DANDROID_ABI :目标abi ,armeabi-v7a就是32位arm
//DANDROID_NATIVE_API_LEVEL :安卓版本
//DANDROID_TOOLCHAIN_NAME
//DCMAKE_MAKE_PROGRAM:编译器路径,使用相对路径指向ndk
D:\mysdk\cmake-3.12.0-rc1-win64-x64\bin\cmake.exe -G"MinGW Makefiles" -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK%\build\cmake\android.toolchain.cmake -DANDROID_STL=gnustl_static -DANDROID_ABI="armeabi-v7a" -DANDROID_NDK=%ANDROID_NDK% -DANDROID_NATIVE_API_LEVEL=android-21 -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows-x86_64\bin\make.exe" ..
D:\mysdk\cmake-3.12.0-rc1-win64-x64\bin\cmake.exe --build .
在bat脚本所在文件夹,按住shift然后右键,打开shell,输入./bat文件名.bat。即可开始编译,可以看是否有报错。
3.java项目里可以放入java,开始使用c的方法。
PS:使用log调试:
在c中添加jni和log头文件,arm处理器的在 ndk\platforms\android-14\arch-arm\usr\include
然后添加一个方便的宏
#ifndef __CLOG_H__
#define __CLOG_H__
#ifdef ANDROID
#ifndef _NO_LOG
#include <android/log.h>
#include <jni.h>
#define LOGI(tag, fmt, args...) __android_log_print(ANDROID_LOG_INFO, tag, fmt, ##args)
#define LOGD(tag, fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, tag, fmt, ##args)
#define LOGE(tag, fmt, args...) __android_log_print(ANDROID_LOG_ERROR, tag, fmt, ##args)
#else
#define LOGI(tag, fmt, args...)
#define LOGD(tag, fmt, args...)
#define LOGE(tag, fmt, args...)
#endif
#else
#define LOGI(tag,fmt,args,...)
#define LOGD(tag,fmt,args,...)
#define LOGE(tag,fmt,args,...)
#endif
#endif//__CLOG_H__
还有cmake里面,链接上log库,这个只是头文件。完成之后就可以c里面直接写 日志了
LOGE("this is tag","this is log cintext");