Android引用c语言so库
思路1.在linux环境编译交叉编译so库2.在Android Studio创建包含C++的工程3.在Android工程中引用so库,在C++中利用JNI编写java可以调用的API编译so库编译之前先了解以下Android系统的运行环境,从CPU分为以下几类:1.armeabiv-v7a: 第7代及以上的 ARM 处理器2.arm64-v8a: 第8代、64位ARM处...
思路
1.在linux环境编译交叉编译so库
2.在Android Studio创建包含C++的工程
3.在Android工程中引用so库,在C++中利用JNI编写java可以调用的API
编译so库
编译之前先了解以下Android系统的运行环境,从CPU分为以下几类:
1.armeabiv-v7a: 第7代及以上的 ARM 处理器
2.arm64-v8a: 第8代、64位ARM处理器
3.armeabi: 第5代、第6代的ARM处理器
4.x86: 平板、模拟器用得比较多(android studio模拟器用的就是x86)
5.x86_64: 64位的平板
将手机与电脑adb连接,输入cat /proc/cpuinfo查看手机cpu架构,一般arm64-v8a向下兼容armeabiv-v7a、armeabi,现在的手机大多都是arm64-v8a架构。
NDK下载:https://developer.android.google.cn/ndk/downloads/
libuv的交叉编译比较方便,下载安装gyp即可,参考https://github.com/libuv/libuv/blob/master/README.md
NDK里有对应不同CPU架构的编译器, 用build/tools/make-standalone-toolchain.sh安装NDK编译器,也可用绝对路径直接使用NDK包里的工具,下面是脚本参数
安装后将安装的路径添加到PATH里就可以使用了。
编译过程中提示arm-linux-androideabi/bin/ld: fatal error: test: Input/output error,原因:虚拟机共享文件中编译所致。
编译时切换成root权限会少很多问题。
加载so库
使用Android Studio创建包含C++工程(版本3.3.0)
cpp就是java要调用的api文件,CMakeLists.txt是编译cpp的配置文件:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
set(CURRENT_DIR ${CMAKE_SOURCE_DIR})
message("CURRENT_DIR" ${CMAKE_SOURCE_DIR})
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${CURRENT_DIR}/native-lib.cpp )
add_library( uv
SHARED
IMPORTED)
set_target_properties( uv
PROPERTIES IMPORTED_LOCATION
${CURRENT_DIR}/../../../libs/armeabi-v7a/libuv.a )
add_library( net
SHARED
IMPORTED)
set_target_properties( net
PROPERTIES IMPORTED_LOCATION
${CURRENT_DIR}/../../../libs/armeabi-v7a/libnet.so )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
include_directories(${CURRENT_DIR}/../../../libs/include)
target_link_libraries( # Specifies the target library.
native-lib
net
uv
# Links the target library to the log library
# included in the NDK.
${log-lib} )
cpp文件:
#include <jni.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include "CommunicationFunction.h"
#include "CommunicationInterface.h"
#include "uv.h"
extern "C"
{
void *ghander = NULL;
void link_state_cb(void* hander, CmciLinkConfigStruct stCmciLinkConfig, CmciLinkStateEnum enCmciLinkState)
{
if(enCmciLinkState == CMCI_LINK_STATE_SUCCESS)
{
ghander = hander;
__android_log_print(ANDROID_LOG_DEBUG,"libuv","hander = %d \n",hander);
}
else
{
hander = NULL;
}
}
void tcp_read_cb(void* hander, SYS_PBUFFER pBuffer, SYS_U32 u32BufferSize)
{
for(int i = 0; i < u32BufferSize; i++)
{
__android_log_print(ANDROID_LOG_DEBUG,"libuv","%02x \n",pBuffer[i]);
}
}
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */)
{
//std::string hello = "Hello from C++";
const char *ver = uv_version_string();
//return env->NewStringUTF(hello.c_str());
return env->NewStringUTF(ver);
}
void* net_server(void *)
{
while(1)
{
usleep(1000);
Cmci_PocessMsg();
}
}
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_netInit(JNIEnv* env, jobject /* this */, jstring ip, jint port)
{
int flag = 0;
char buf[5] = "1234";
const char *tmp_ip = env->GetStringUTFChars(ip,0);
if (tmp_ip == NULL)
{
return;
}
int len = strlen(tmp_ip);
CmciLinkConfigStruct client;
memset(&client,0, sizeof(client));
client.enProtocal = CMCI_PRTL_TYPE_TCP;
client.enLinkType = CMCI_LINK_TYPE_CLIENT;
client.stTcpConfigClient.enProtocal = CMCI_PRTL_TYPE_IPV4;
client.stTcpConfigClient.i32Port = port;
pthread_t net_id;
pthread_create(&net_id, NULL, net_server, NULL);
for(int i = 0; i < len; i++)
{
client.stTcpConfigClient.ui8ServiceIP[i] = tmp_ip[i];
}
Cmci_Init();
Cmci_RegisterLinkStateCB(link_state_cb);
Cmci_RegisterReadCB(tcp_read_cb);
Cmci_StartLink(client);
sleep(1);
Cmci_Write(ghander,buf,4);
return;
}
}
创建tcp连接时失败,调查发现是因为工程中未添加相关权限,AndroidManifest.xml添加:
<uses-permission android:name="android.permission.INTERNET"/>
更多推荐
所有评论(0)