Fsu0413 / QtCompile

Personal build of Qt5 onwards, with SSL builtin. Multiple configuration available.
https://build-qt.fsu0413.me/
88 stars 11 forks source link

5.15.8 for android库的两个问题。。 #12

Closed leamus closed 1 year ago

leamus commented 1 year ago

首先很感谢你的分享,这个真的方便了很多人,也包括我,很感谢~ 昨天我用你的5.15.8 for android库,编译了我的一个项目,我发现有2个问题: 1、libqt5purchasing.xxx.so 这个库,v7a和v8a,只要携带就会报错(报错原因具体我忘了,翻译过来就是库不适合); 2、编译并安装后,app无法创建文件夹和写文件(读好像可以),哪怕给了读写外部存储空间权限也不行。 上面两个问题我用官方的qt5.15.2的安卓编译均正常,不知哪里有问题,所以想请教一下~

Fsu0413 commented 1 year ago

qt5 purchasing我不用不太清楚

创建文件和文件夹使用下面的解决方案

AndroidManifests.xml 里面加上 android:requestLegacyExternalStorage

<application android:requestLegacyExternalStorage="true" >
...
</application>

cpp 里申请权限(分安卓10及以下和安卓11及以上),参考我的 RMEssentials 工程

https://github.com/Fsu0413/RMEssentials/blob/master/src/rmessentials/src/main.cpp Line 20 ~ 28、247 ~ 387

https://github.com/Fsu0413/RMEssentials/blob/master/src/rmessentials/src/main.h Line 30 ~ 48

pro里加

android {
    equals(QT_MAJOR_VERSION, 6): QT += core-private
    else: QT += androidextras
}
Fsu0413 commented 1 year ago

还有 官方Qt 5.15.2可能是API 29(Android 10)以下的,而我编译的是使用新SDK的。 API 30(Android 11)以上的话创建文件夹和写文件申请的权限不同,如果APP要兼容安卓10以下和11以上需要两套权限都写

leamus commented 1 year ago

谢谢回答,你给我的那些我都有用到(所以5.15.2运行是没问题的),我用的是 java11+ndk23+gradle7.5.1+AndroidSDKBuildTool30.0.3+compileSdkVersion33(这个应该是API) 编译的,貌似更新一点^^,不知是不是和这些版本有关系?

Fsu0413 commented 1 year ago

build tool和gradle不清楚,ndk应该用和Qt构建时相同的版本,java应该是8

leamus commented 1 year ago

回头我试试和你一样的构建环境,看看有没有什么问题,按理说更新的编译结果应该兼容旧环境才对。。。

Fsu0413 commented 1 year ago

NDK没有二进制兼容保证,NDK开发者自己说的。我也不知道他们为什么不保证二进制兼容。 我本地也是NDK 21和25混用,只要有一个环节版本不对,编译出来的程序就闪退。。。。。

很久之前 Qt 有个服务叫做ministro,用在安卓版本的Qt上。使用ministro发布的程序会在运行时下载最新版本的Qt库来运行。而ministro依赖标准库之间的二进制兼容性。 后来NDK开发者在issue里直接说NDK没有二进制兼容保证,直接导致Qt从5.7开始弃用了ministro。。。。

leamus commented 1 year ago

嗯,了解了,安卓开发真是恶心啊。。一堆环境,版本还得对应。。 不过奇怪的是我的app倒是用哪个版本的NDK倒是都能编译和运行,可能也是巧合吧。。

leamus commented 1 year ago

SDK构建工具版本应该兼容吧?

leamus commented 1 year ago

哦对了,那个libqt5purchasing.xxx.so的错误是: java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad in "/data/app/。。。/libqt5purchasing.xxx.so

Fsu0413 commented 1 year ago

SDK应该是兼容的,不懂purchasing,帮不上忙了。。。 看了一下purchasing的代码库,里面有两个预编译的jar,会不会是这两个jar打包的问题呢。。。

leamus commented 1 year ago

应该不是,它的报错是so文件不合适无法链接(UnsatisfiedLinkError),估计和你说的一样可能是NDK版本不兼容吧。。 我的项目是游戏引擎,所以几乎把所有Qt的库都包进去了,正好能整体测试一下,哈哈 再次感谢你哈~

leamus commented 1 year ago

来反馈一下,我用NDK21.4编译,purchasing报错变成了:JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.ClassNotFoundException: org.qtproject.qt5.android.purchasing.QtInAppPurchase 估计确实有个jar文件没引入进来。。 另外,编译的仍然没有写权限。。 放弃5.15.8了,期待你的5.15.9~

Fsu0413 commented 1 year ago

没写权限的话确认下 AndroidManifests.xml 是否编进去了,pro要加点东西来着,加啥来着我忘了。。。 purchasing的问题估计我也得看看,如果真的是什么东西没引入的话,估计也不用5.15.9修,最近出一版就行

Fsu0413 commented 1 year ago

看了一下QtPurchasing,从5.15.7开始里面新增加了两个jar,在pro里没写install 我这边的解决方案是手工部署这两个jar,但是不知道部署到哪里。。。

真的难受。。。。

Fsu0413 commented 1 year ago

读写文件的问题,能让我看看代码吗? 因为我这边读写文件都正常,所以想看看你的实现问题在哪里

leamus commented 1 year ago

写文件的问题应该不是权限的问题,我用5.15.2编译完全没问题的,用5.15.8就很奇怪,能创建文件夹,但就是无法写文件,各种报错,android:requestLegacyExternalStorage="true" 也加在androidmanifest文件里了,uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE也加进去了,pro文件好像不需要额外加什么,代码类似:

QFile file(QString("log_%1.txt").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd"))); file.open(QIODevice::WriteOnly | QIODevice::Append); QTextStream text_stream(&file);

if (QT_VERSION < QT_VERSION_CHECK(6,0,0))

text_stream.setCodec("UTF-8");

endif

text_stream << message << "\r\n";
file.flush();
//text_stream.setDevice(nullptr);
file.close();

另外QtPurchasing这个,我在pro文件里引入了 Qt+=purchasing 好像也没有把jar打包进去,我估计所有的jar最后都打包到了classes.dex里,回头我编译的时候看看编译过程有没有相关的命令。。

Fsu0413 commented 1 year ago

看你的描述就是权限问题没跑了。。

我的5.15是用新SDK构建的。 对于SDK 30以后构建的程序,在安卓11之后系统不再读取android:requestLegacyExternalStorage属性和WRITE_EXTERNAL_STORAGE权限,而是需要一个“完全文件访问权限”需要用户自己去设置。 而对于使用SDK29以及以前版本构建的程序,系统只会读取android:requestLegacyExternalStorage。

SDK 30及以后的实现类似这样:程序检测安卓版本大于等于11的话,可以用一个叫做android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION的indent打开activity 需要让用户在这个activity中找到你做的程序,然后选择授予权限,然后等这个activity返回之后,再尝试读取写入文件试试,应该就可以了

Purchasing 的问题原谅我不懂,除了部署jar之外我也没有啥别的解决方案了

leamus commented 1 year ago

了解,我有空再去测一下,我的项目是用最新的sdk33做的,看来光项目用最新的还不行。。。等我测试好了来反馈~ Purchasing 我不知道如何部署jar到class。。。对安卓不是很懂,所以才用了qt。。 多谢拉~

Fsu0413 commented 1 year ago

没啥问题这issue我关了哈