安卓工程接第三方SDK遇到回调函数字符串参数乱码的问题

时间:2024-04-09 22:13:32

安卓工程接第三方SDK遇到回调函数字符串参数乱码的问题

在做《老王麻将》的时候,安卓工程接第三方语音SDK,出现了一个字符串乱码问题,现在总结一下。


出现的问题:
在对方发送语音的时候,SDK会通过一个接口提醒客户端有语音要去下载,这个时候客户端会传一个存语音的地址给SDK然后开始下载。下载成功之后呢,SDK会回调一个函数,把一些语音文件的具体信息还有之前客户端传入的地址一起回调回来。但是,收到的回调里面,路径字符串是乱码。

SDK接口如下:

//下载语音
virtual YIMErrorcode DownloadFile(XUINT64 messageID, const XCHAR* savePath) = 0;
//下载语音回调
void OnDownload(YIMErrorcode errorcode, std::shared_ptr message, const XString& savePath)override;

排除了编码方式,代码逻辑等问题,对方的技术小哥哥指出,问题在于安卓工程中application.mkAPP_STL配置。
下图是我们安卓项目的application.mk

安卓工程接第三方SDK遇到回调函数字符串参数乱码的问题

技术小哥哥说:“cocos 默认是gnustl_static,gnustl_static 是gcc编译器 ,c++_static 是llvm” 。
╭(°A°`)╮大写的懵逼!哈哈哈哈哈哈哈哈哈哈哈~好吧,get到新知识,就好好学习一下。
(づ ̄3 ̄)づ (づ ̄3 ̄)づ (づ ̄3 ̄)づ

首先是Application.mk:

Application.mk是用来描述你的应用程序需要哪些模块,以及这些模块所要具有的一些特性。
而相对的Android.mk是用来描述要编译某个具体的模块,所需要的一些资源,包括要编译的源码、要链接的库等等。
Application.mk所要描述的内容主要包括:

  1. 你程序正常运行,所需要到模块的具体列表;
  2. 程序要编译成什么机器指令集的;
  3. 所有模块要被编译成Release版本还是Debug版本的;
  4. 传递给C或者C++编译器的编译参数。

当然,Application.mk文件其实是可选的。默认情况下,如果ndk-build命令找不到Application.mk文件的话,就会使用如下规则进行编译:

  1. 会编译全部在Android.mk文件中列出的模块;
  2. 对于所有模块,NDK编译系统会根据“armeabi” ABI来生成机器代码,即指令集是ARMv5TE。

具体来说,Application.mk文件中,可以包含对下面几个变量的定义:

  • APP_PROJECT_PATH
  • APP_MODULES
  • APP_OPTIM
  • APP_CFLAGS
  • APP_CPPFLAGS
  • APP_BUILD_SCRIPT
  • APP_ABI
  • APP_STL
  • APP_GNUSTL_FORCE_CPP_FEATURES

那么再来说说这个APP_STL是神马东东:

默认情况下,Android 平台提供很小的 C++ 运行时支持库 (libstdc++)。这种很小的支持不包含如下支持:

  • 标准 C++ 库支持(几个无关紧要的标头除外)。
  • C++ 异常支持
  • RTTI 支持

然而,NDK还带有其它一些可选的C++运行库的实现,你可以选择在你自己的应用程序中,通过在Application.mk中定义APP_STL变量,来使用或链接其中某一个。

安卓工程接第三方SDK遇到回调函数字符串参数乱码的问题

上面这个表是在官网上找到的,但是在百度搜到的资料里面,普遍说的是下面这个规则:

安卓工程接第三方SDK遇到回调函数字符串参数乱码的问题

对此我表示很疑惑,不知道是不是官方有修改。(对于上面有出入的地方,cocos项目没有用到,也没有进一步实际验证。)

(๑• . •๑)好哒,看到这里,知道这个配置项是用来干嘛的了,但是心里还是有很多疑惑的地方,继续学习~

神马是GNU:

简单的说就是个操作系统。
按照技术小哥哥的说法,选择gnustl的时候,使用的是GCC编译器。
而选择c++static的时候,使用的是LLVM编译器。所以说两种链接库的编译器是不一样的。

根据官网上面的解释:
GNU STL 运行时:
运行的是 GNU 标准 C++ 库 (libstdc++)。其共享库文件名为 libgnustl_shared.so。
libc++ 运行时:
运行的是 LLVM libc++ 的 Android 端口。其共享库文件名为 libc++_shared.so。

那么现在,问题又来了,libstdc++libc++是什么,区别是什么。
libc说起。libc是Linux下原来的标准C库,也就是当初写hello world时包含的头文件#include < stdio.h> 定义的地方。
写C++的时候,还有两个重要的库,libc++/libstdc++。
libc++ 为 LLVM 项目重新编写,包含 C++ 11 标准库。
libstdc++ 是 GNU 项目的标准库。

知识学习到这里,大概也能get到为什么我在回调函数里面拿到的字符串是乱码了。
在下载函数里面,我传入的是char,但是在回调的时候传出来的却是string。
我的安卓工程使用的是libc++的库和LLVM的编译器,但是他们SDK却使用的是libstdc++的库和GCC的编译器。这样一来, string的实现方式不一样,我的客户端和他们的SDK读写同一内存,最后拿到的string值就不一样了。

p.s. 在接SDK的时候,一遇到这个问题我就联系了群里的技术人员,但是打印了各种参数值,猜想了各种可能出现的问题,甚至最后对方技术远程了我的电脑看了我的代码也找不到原因,还说是我c++代码逻辑的问题ヾ(༎ຶД༎ຶ)ノ” 然后,我找了公司的几个大牛看了这个问题,也都没找到原因。最后对方换了个技术小哥哥,问了几句之后,就让我截图Application.mk。这个真的是,不懂这一块的人再怎么看也看不出问题吧。遇到这种坑,也算是一个经验的积累。最后,对于我一个换UI的懒程序,这次为神马会有动力学习,那肯定是为了以后跟帅气的技术小哥哥沟通的时候不懵逼啊!٩(ˊvˋ*)و