升级到Delphi11.3后遇到的Android问题
问题1:Delphi11.3生成的apk安装到手机的时候,提示安装包解析失败。
查看build出来的AndroidManifest.xml(生成apk的路径里能找到),关键的一行:
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="32" />
targetSdkVersion = 32,我的手机是荣耀的Android 13,按道理是支持32的,但不知为什么会提示这个错误,没办法,只好强行设置targetSdkVersion = 29,之所以是29,跟问题2有关。具体怎么设置?在你的代码目录里有个文件AndroidManifest.template.xml,打开会找到一行:
<uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
然后把%targetSdkVersion%直接改为29,保存后重新build,生成apk,再打开AndroidManifest.xml就会发现已经变为targetSdkVersion = “29”,再安装到手机就没有这个提示了。
具体原因没时间去研究,只能先改到能用吧。
问题2:apk安装到手机后没有读写文件的权限。
因为我的数据库文件不是放在app的私有目录,主要是担心卸载app会把我的数据库也一起删掉,所以我放在了外部存储。但是29版本后(Android 10),实行分区存储,app只能访问私有存储和共享存储,不能访问外部存储(具体说明可以百度一下targetSdkVersion 29/30相关的内容,这里不做阐述)。即使我给了Read external storage,Write external storage,Manage external storage权限,也不起作用。经过一番的网上查资料,说是targetSdkVersion = 29应用中,设置android:requestLegacyExternalStorage=“true”,就可以不启动分区存储,和以前一样正常访问外部存储,所以我把targetSdkVersion 设为29,然后查看AndroidManifest.xml,发现requestLegacyExternalStorage已经是true,以为没问题了,结果安装后还是没有读写文件的权限。在手机设置里,查看app的权限,根本就没有读写文件的权限可以让你选择。
没办法,继续查资料。看到有一篇文章提到,需要在代码里动态申请权限才行。然后我也试试在代码上加这段内容:
uses
...
{$IFDEF ANDROID}
Androidapi.Jni.Os, androidapi.Helpers, System.Permissions,
{$ENDIF}
...
{$IFDEF ANDROID}
procedure TfrmMain.RequestPermissions;
var
LPermissionReadExternalStorage, LPermissionWriteExternalStorage: string;
begin
//先获取读写外部存储权限
LPermissionReadExternalStorage := JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE);
LPermissionWriteExternalStorage := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
PermissionsService.RequestPermissions([LPermissionReadExternalStorage, LPermissionWriteExternalStorage], nil, nil);
end;
{$ENDIF}
然后在form的create里调用RequestPermissions即可,调用的时候记得用{$IFDEF ANDROID}包住。
安装完后,第一次打开app会提示是否给它读写文件的权限,选择允许。在手机设置里,查看app的权限,也能看到已经获得的权限。
后来发现只给了Read external storage,Write external storage权限也可以,不需要Manage external storage权限,以前三个都要有的。
Delphi的资料越来越稀缺了,遇到问题真的是找不到解决办法,只能自己去摸索,能解决一个是一个,痛苦啊!好不容易盼来了一份代码可以支持多平台,却就此退出舞台了。