分享

艰辛的Delphi 11.1 Android项目升级之路(成功升级的注意事项)

 和谐世界 2022-08-27 发布于福建

我使用了洪荒之力,终于把项目成功升级到Delphi 11.1了,可能因为项目里面用到的三方SDK比较多,像推送、支付、扫码、相册选择等,所以遇到的问题也比较多吧。

1.将工程Android 32位目标平台下的Libraries恢复为默认

如果用D11打开工程,10.4下很多自带的jar都已经被去除了

Image

如果立即编译的话,会报错:

Image

这个时候,你只要右键Libraries,在弹出的菜单中点击“Revert System Files to Default”

Image

点击之后,会清除不存在的jar,把D11中自带的jar添加进去:

Image

再清一下工程的临时生成目录

2.由于Delphi 10.4.2编译jar用的是dx,D11.1编译jar用的是d8,我复制一个工程出来专门用于D11.1下编译,配置下工程的生成目录,与D10.4的生成目录区分开

比如TestAndroidBGAQRCodeSDK_FMX_D10_4.dproj是给D10.4编译的,

再复制一个工程出来,命名为TestAndroidBGAQRCodeSDK_FMX_D11.dproj,表示是给D11编译的,

然后再修改工程的生成目录,

比如原来为:.\$(Platform)\$(Config)

更改为:.\$(Platform)\D11\$(Config)

Image

3.修改权限申请方法的参数类型

如下10.4下面申请权限的代码已经编译不过了

Image

Image

RequestPermissions的声明为:

    procedure RequestPermissions(const APermissions: TArray;

      const AOnRequestPermissionsResult: TRequestPermissionsResultEvent; AOnDisplayRationale: TDisplayRationaleEvent = nil);

      overload; virtual;

其中,D10.4下TRequestPermissionsResultEvent的声明为:

  TRequestPermissionsResultEvent = procedure(Sender: TObject; const APermissions: TArray;

    const AGrantResults: TArray) of object;

D11下TRequestPermissionsResultEvent的声明为:

  TRequestPermissionsResultEvent = procedure(Sender: TObject; const APermissions: TClassicStringDynArray;

    const AGrantResults: TClassicPermissionStatusDynArray) of object;

  TClassicStringDynArray= array of string;

所以改成如下,这样这段代码10.4和11都能使用了:

Image

  //申请权限

  {$IFDEF ANDROID}

  PermissionsService.RequestPermissions

      ([JStringToString(TJManifest_permission.JavaClass.CAMERA),

      //要有震动的权限

      JStringToString(TJManifest_permission.JavaClass.VIBRATE)

        ],

    procedure(const APermissions: {$IF CompilerVersion >= 35.0}TClassicStringDynArray{$ELSE}TArray{$IFEND};

    const AGrantResults: {$IF CompilerVersion >= 35.0}TClassicPermissionStatusDynArray{$ELSE}TArray{$IFEND})

    begin

    end);

  {$ENDIF}

4.一些三方SDK的jar在编译成dex.jar时会卡住,

比如编译支付宝支付SDK的时候卡住了

Image

编译华为二维码扫描SDK的时候也是:

Image

一动不动,初步估计是将jar编译为dex的时候卡住了,

这个时候该怎么办呢?

编译dex用的是java,所以我们只需要找到java.exe相关的进程当前在执行什么,即找到启动该进程的参数:

Image

在cmd下执行如下命令:

wmic process where caption='java.exe' get caption,commandline /value

Image

然后把CommandLine后面的命令复制下来,在cmd中运行,看看它会报什么:

Image

Expected stack map table for method with non-linear control flow.

这些是警告,并非是报错(Error),可以忽略,并且实际上jar对应的dex.jar已经生成了,

再把java.exe进程杀掉,

Image

杀掉之后,在Delphi的Messages窗口也能看到上面那些警告,

再继续编译即可,重复以上步骤,直到将所有的jar都编译成dex.jar。

5.由于Delphi 11.1添加了许多系统自带的jar,导致不能用太多第三方的jar,需要打Patch1补丁修复这个问题

D11.1添加了AndroidX支持库相关的jar,现在很多SDK都需要这个包

Image

如果你的项目使用了很多三方SDK,会导致原来在Delphi 10.4以下编译正常的项目到D11下编译不了,报:

Error: E7688 Error: Cannot fit requested classes in a single dex file (# methods: 68541 > 65536). Try supplying a main-dex list,

如下图所示:

Image

这个问题是因为一个dex文件中不能包含大于65536个方法所导致的,你可以禁用掉firebase和googleplay相关的jar来临时解决,

Image

下面是我所使用的一堆三方SDK包:

Image

StackOverflow上有人说在编译classes.dex时加--min-api 21就能通过,

Image

试了一下,果然成功,并生成了两个dex

Image

不过,Delphi每次Build的时候都会编译classes.dex并报错,所以解决不了问题,

我在Facebook,Telegram,Whatsapp上都问了一圈,多亏有人在Slack上指点:

Image

原来早就有人提出了这个问题,

https://quality./browse/RSP-37667

并且Embarcadero也发了补丁来修复,

https://blogs./rad-studio-11-1-alexandria-patch-1-available/

Image

Image

那就下载安装这个补下吧,

Image

Image

Image

补丁就安装好了,

再编译,还是报错,可以看出--min-api参数的值为19,不是21,

Image

那就需要改AndroidManifest.template.xml中的minSdkVersion为21,

Image

再次编译,成功!!!

Image

同时生成了两个dex,

Image

6.D11.1将旧的Android支持库升级为了AndroidX库

D11.1去除了android-support-v4.jar,使用了新的AndroidX支持库,但是就我所用到的SDK中,还是有用到这个android-support-v4库的,所以我还得把它加上去。但是加上去也不是这么简单的,和Delphi自带的jar之间会有冲突,编译的时候会报类重复定义多次:

Image

[PAClient Error] Error: E7688 Type android.support.v4.app.INotificationSideChannel is defined multiple times: c:\program files (x86)\embarcadero\studio\22.0\lib\android\Release\core-1.5.0-rc02.dex.jar:classes.dex, C:\MyFiles\ThirdPartySDK\Android图片视频选择器dmcBig_mediapicker\Android\D11\Release\android-support-v4_For_D11-dexed.jar:classes.dex

因此需要用WinRAR将jar打开,把重复的类删除掉,再清缓存编译,直至编译成功。

7.布署也恢复一下默认

以上编译没有问题了,本以为皆大欢喜了,但是运行闪退,令人头大,

手机插电脑上,在cmd下运行adb logcat > C:\a.log命令,

我是将这个命令放在批处理,然后运行这个批处理的:

Image

cd C:\Windows\system32

chcp 936

cd C:\PlatformSDKs_10_2_3\android_sdk_windows\platform-tools

C:

adb logcat >C:\alog.txt

在手机上点击APP,闪退后,关闭这个命令,打开C:\a.log查看闪退日志,

Image

06-16 21:58:29.330 20573 20573 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class 'androidx.core.content.FileProvider'

说是没有这个类,可是这个类在core-1.5.0-rc02.jar中,并且也是Delphi自带的jar,

这就有点纳闷了,

难道是multidex分包了之后,只有将classes.dex布署进去了,但是其他包比如classes2.dex这些没有布署进去,说到这里,我打开布署,

可以看到,旧项目里面是有布署一个classes.dex的,

Image

点击“Revert to Default”之后 ,

Image

这个classes.dex的布署就被删除了,说明D11是不需要这个布署项的,

Image

再编译,运行,

我的APP终于可以正常打开了。真是太难了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多