ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Delphi XE7安卓开发实战:从环境配置到APK发布的关键经验

Delphi XE7安卓开发实战:从环境配置到APK发布的关键经验 简介DELPHI XE7安卓手机开发框架是一份面向跨平台开发者的资源包覆盖安卓端业务系统的常用功能适合有一定Delphi基础、希望快速搭建移动端界面与数据交互的开发者参考复用。压缩包共23个文件含PNG界面示例、JPG运行截图、可安装APK演示程序、SQL脚本与SQLite数据库文件以及电脑端测试EXE程序整体仅18MB。功能层面涉及主菜单切换、StyleBook设计、编辑界面键盘处理、WSDL/PHP接口调用、DataSet与JSON互转、报表查询框架、SQLite本地数据库及图片操作、百度定位、二维码扫码、通讯录拼音码滑动、版本升级、通知提醒、选择文件对话框、图片上传下载、多图片切换、手机截屏等31项功能模块。另提供DATASNAP与HTTP Server电脑测试端方便对照联调接口与数据同步。已有777人学习下载适合需要系统获取Delphi XE7安卓端完整功能范例的开发者。 第一次用 Delphi XE7 写出一个能跑在安卓手机上的 App 时我的感觉是复杂的代码还是那个熟悉的 Object Pascal但程序的行为、交互方式、甚至文件读写的思路都彻底变了。Delphi XE7 作为 Embarcadero 在移动开发上真正站住脚的一个版本让一大群从 Delphi 6/7 时代过来的桌面程序员看到了“用同一套代码做安卓应用”的可能但说实话围绕这套安卓开发框架的坑也比想象中多得多。这篇文章我不打算写成官方文档式的教程而是把我在 XE7 上实际跑安卓项目时的选型思路、环境配置、代码写法、发布流程以及那些社区里反复有人问的细节问题一起捋一遍。适合正在用或准备用 DELPHI XE7 做安卓开发的朋友也适合还在评估“老 Delphi 程序员要不要进入移动端”的人做参考。1. XE7 在安卓开发里的真实定位不止是“能用”更是跨平台思路的转折点1.1 FireMonkey 与 VCL 的本质差异很多从 Delphi 7 时代过来的人第一次打开 XE7会下意识找 VCL 窗体、找 TButton、TEdit然后发现界面设计器完全变了。XE7 主推的 FireMonkeyFMX框架和 VCL 是两套不同的东西VCL 封装的是 Windows 原生控件而 FMX 是一套自绘的跨平台 UI 层通过 GPU 渲染在 Windows、macOS、iOS、安卓上跑同一套代码。这一点对安卓开发极其关键。因为在 XE7 时代安卓原生开发的主流语言是 Java而 FireMonkey 让你可以用 Object Pascal 直接写安卓界面逻辑不需要经过 Java 桥接。虽然底层还是通过 JNI 调用安卓 API但你的业务代码可以完全用 Delphi 的语法习惯来写这对老 Delphi 程序员来说学习成本曲线一下子就平缓了。1.2 与后续版本相比XE7 缺了哪些“新世界的通行证”用今天的眼光看XE7 当然不是最强的 Delphi 版本它只代表 2014 年前后对安卓支持的成熟度。我整理过一份和后续版本的对比方便你判断手里的项目该不该升版能力维度Delphi XE7Delphi 10.3 RioDelphi 10.4 SydneyAndroid API 支持API 21 左右旧设备友好API 26面向现代安卓API 30兼容新机型运行时权限服务不完善需手动 JNI 调用TPermissionsService 成熟权限处理完善安卓模拟器支持差必须真机有改善可配合现代模拟器高分辨率适配基础支持需手调自动适配更好多屏适配成熟从表格能看出XE7 的优势在于它的“老”对 Android 5.0 时代的设备兼容性反而比新版更好很多工控平板、老旧定制设备就是 Android 4.4 到 5.1新版本 Delphi 编译出来的 APK 在这些设备上反而可能出现问题。但如果你想上架新的安卓应用市场targetSdkVersion 要求越来越高XE7 会有心无力。1.3 现在选 XE7 的三种合理场景这几年实体项目中还在坚持用 XE7 的基本就三种情况维护存量代码公司内部有一套用 XE7 开发的分发系统跑在定制安卓平板上老板不会为换框架出预算你只能继续用 XE7。老旧工业设备定制仓库扫码、生产看板、医疗手持终端这类场景设备系统版本锁定在 Android 5.1 以下对新版本 Delphi 编译的程序未必友好XE7 反而稳。学习 FireMonkey 的架构原理XE7 的源码结构比新版本简单适合想彻底搞懂 FMX 控件渲染、跨平台抽象层的人做学习材料。当然如果是新项目且面向普通消费者我的建议很直接优先考虑 10.3 以上版本或者干脆走安卓原生/Flutter 路线。XE7 适合特定场景不代表它是万能解。2. 环境搭建中最容易让人放弃的环节JDK、SDK、NDK 的三角匹配2.1 版本不是越新越好匹配才是真的Delphi XE7 的安卓环境配置最难的不是安装而是把 JDK、Android SDK、Android NDK 三个东西的版本凑齐。很多新手卡在这里几天出不来就是因为用了最新版的 JDK 或 SDK结果 XE7 编译时报各种奇怪错误。我实测过一组能稳定编译的组合JDK 8u19132 位或 64 位都行主要看你的 XE7 版本Android SDK Tools 25.x不要用 26 以上Android SDK Platform 23NDK r10e。这个组合在 Windows 7/10 上都验证过配合 XE7 的 Android 编译链最顺畅。为什么不能用新版 SDK因为 XE7 编译时会调用 SDK 里的 aapt、dx 等工具新版 SDK Tools 改了目录结构和参数格式老编译器不认识。NDK 也同理r10e 之后 GCC 工具链有调整FMX 的底层链接脚本可能对不上。提示安装 Android SDK 时把“Android SDK Build-Tools”固定到 23.0.1 附近太高版本会在打包阶段报 Unexpected exception 之类的错。2.2 模拟器效率太差真机调试才是正路XE7 时代的安卓模拟器打开一个应用要几分钟调试体验非常痛苦。我的实际操作是直接找一台安卓 5.0 左右的旧手机开启开发者选项和 USB 调试然后在 Delphi IDE 里选择安卓设备作为 Target点击运行就能自动部署。这个流程虽然简单但也有个容易踩的坑USB 驱动没装好时IDE 会提示找不到设备而 Windows 经常悄悄把手机识别成便携设备而不是 ADB 接口需要手动安装厂商 ADB 驱动。更省事的方法是用 WiFi 调试先用 USB 连接并执行 adb tcpip 5555然后拔线用 adb connect 局域网 IP 连接。这样测试时不用一直挂着数据线对做扫码枪、移动终端这类项目特别实用。2.3 部署时的常见错误与排查链路如果你部署时遇到“Unable to install ... Failure [INSTALL_FAILED_OLDER_SDK]”说明 APK 编译的 minSdkVersion 高于设备系统版本。而 XE7 默认的 minSdkVersion 较低一般不会出这个问题反而是在新系统上遇到 INSTALL_FAILED_UPDATE_INCOMPATIBLE多半是签名不一致卸载旧应用重装即可。另一类高频错误是编译时找不到 android.jar。打开 Project Options SDK Manager确认已经下载了对应 Platform 的 android.jar并且 Project Options 里的 SDK 版本和 Tools Options SDK 里设置一致。我见过不少人同时配置了两套 SDK 路径IDE 编译时取了旧的那套结果怎么改都报错。3. 从桌面程序员的思维惯性切换到安卓系统的运行规则3.1 返回键、生命周期与窗体退出逻辑桌面程序的 Form 关闭通常就是销毁窗口但在安卓上按返回键默认行为是关闭当前 Activity。Delphi XE7 里你可以重写 Form 的 OnKeyDown 事件判断 Key 等于 vkHardwareBack然后决定是退出程序、最小化到后台还是弹确认框。很多老程序员第一次写完安卓 App 后发现自己按返回键直接退出了连保存数据的机会都没有就是因为没处理这个事件。另一个桌面思维带过来的坑是生命周期。安卓系统在内存紧张时会回收后台 Activity而 FMX 在 XE7 中恢复状态的能力比较弱。最稳妥的做法是在 Form 的 OnSaveState 里保存关键业务数据在 OnRestoreState 里恢复。这个机制很多人忽略但做扫码、表单录入类应用时特别重要——用户录了一半数据切到微信回个消息再切回来发现界面重来这是致命体验。3.2 运行时权限不能在 FormCreate 里赌运气安卓 6.0API 23开始引入运行时权限机制跟老系统安装时一次性授权完全不同。XE7 刚出的时候安卓 5.0 还没有这个要求所以早期 Delphi 代码基本都是写进 AndroidManifest.xml 就完事但系统一升级权限在安装时不弹窗程序运行到读取存储卡时就崩溃。XE7 的问题在于没有成熟的 TPermissionsService你需要通过 JNI 调用安卓 API 手动申请权限。我的处理方式是封装一个公共函数利用 JavaClasses 和 JNIEnv 调用 Activity.requestPermissions再在 JavaCallback 里接收回调结果。代码比较繁琐但这也是熟悉 JNI 的好机会。如果嫌麻烦优先把 targetSdkVersion 降回 22 以下系统就会退回到安装时授权模式能绕开运行时权限问题代价是无法上架新版应用市场。这里还顺带提一个热词场景有人问“delphi 如何禁用 u 盘”。在安卓上做 USB 存储控制本质上就是监听存储设备的挂载广播并在业务层拦截文件读写路径。XE7 可以通过 JNI 注册广播接收器实现基础拦截真要做得彻底需要 DevicePolicyManager 级别的设备管控这对老框架来说工程量不小建议用原生模块配合。3.3 多分辨率与屏幕方向别再用像素思维定布局FMX 的布局系统采用 Align 和 Margin 组合思路是“控件跟随父容器对齐”这对安卓碎片化的屏幕尺寸非常重要。我在 XE7 项目里最常用的布局结构是底层放一个 TLayout 做背景容器里面用 TGridLayout 或 TVertScrollBox 划分区域按钮和输入框全部用 Align 属性定位避免用绝对坐标。屏幕方向也是容易忽略的点。工控项目里经常要求锁横屏可以在 Project Options 里设置 Orientation 为 Landscape或者在 Form 的 OnCreate 里调用 Screen.ActiveOrientation 属性。但注意 XE7 在横竖屏切换时对 FMX 布局的重新计算比较机械如果业务界面复杂建议直接锁屏省得测试时出现控件错位的尴尬。4. 把 XE7 玩出花Excel 读取、CAN 通信与局域网消息传递4.1 安卓上读取 Excel 的正确思路Delphi 在 Windows 上读取 Excel 最常用 OLE 创建 Excel.Application但安卓上根本没有 Office 组件这条路直接堵死。正确的做法是绕开“读取 Excel 文件”这个想法转成两种更可行的方案。第一种把 Excel 转换成 CSV 再读取。用 TStringList 加载 CSV 文件按逗号或制表符切分字段代码量很小。缺点是无法保留公式和格式但绝大多数查询类业务根本用不到。第二种解析 XLSX 文件。XLSX 本质是个 zip 压缩包里面是多个 XML 文件。Delphi XE7 自带 TZipFile 类可以先解压再用 TXMLDocument 解析 sheet 里的单元格数据。这个方案适合对数据准确性要求高的场景比如读取设备点检表、固定资产清单原字段和数据类型不会丢。我自己做过一个生产领料 App就是用这个思路读取模板 Excel把字段映射到 ClientDataSet 里效果稳定且不依赖任何第三方商业库。注意TZipFile 解压中文文件名时在部分安卓设备上会有编码问题建议把 Excel 模板的 sheet 名和列名都设置成 ASCII 字符避免解析时找不到节点。4.2 USB 转 CAN 通信工业场景的接入办法热词里有“delphi can口编程例子”这正好是 XE7 在工业端的典型用途。安卓设备本身没有 CAN 口常见做法是通过 USB 转 CAN 适配器比如 USBCAN、CANable连接总线。XE7 要操作 USB 外设技术上走的是安卓的 USB Host API而 Delphi 封装比较薄需要自己做 JNI 调用。整体思路是先用 Java2OP 工具把 android.hardware.usb 相关的 jar 包转换成 Pascal 单元然后在代码里调用 UsbManager 获取设备列表请求权限找到 CAN 适配器的接口和端点最后通过 bulkTransfer 收发数据。这个链路我第一次跑通花了差不多两个晚上主要时间耗在权限申请和端点匹配上——有些适配器有多个接口写死接口序号会出问题。如果你的现场条件允许更省心的方法是改用串口转 CAN 模块或者直接用 WiFi 数传模块。比如用有人或者 USR 的 TCP 转 CAN 盒子安卓端只需要走 Socket 发送十六进制命令Delphi 自带 TIdTCPClient 就能搞定开发速度快得多。这套方案我在产线看板项目里用过稳定性足够维护成本低。4.3 局域网消息传递从 Win32 消息到 UDP 广播桌面 Delphi 程序之间传消息用 SendMessage这套在安卓上行不通。安卓设备之间最简单的消息方案是 UDP 广播。比如一号设备在局域网内广播“开机”其他设备监听同一个端口收到消息后做联动。用 Indy 组件实现很直接发送端用 TIdUDPClient设置 BroadcastEnabled 为 True发送到 255.255.255.255接收端用 TIdUDPServer绑定端口在 OnUDPRead 事件里解析消息。XE7 自带了对应版本的 Indy不需要额外安装依赖。这个方案我常用于工位呼叫、看板数据同步这类场景。要注意的是部分路由器隔离了广播域AP 隔离设备之间收不到广播稳妥做法是做成“广播 直连”双模式先广播发现拿到设备 IP 后改用 TCP 点对点通信。5. 打包、签名与上架实测比想象中多走三步5.1 正式签名配置与 Keystore 管理XE7 打包安卓 APK有 Debug 签名和 Release 签名两套。Debug 签名 IDE 会自动生成但发布时必须自己生成正式签名文件。很多人在这一步栽跟头随便生成一个 keystore签名密码不记录结果第一次上架测试通过第二次要升级时发现密码忘了只能卸载旧包重装用户数据全丢。我的建议是项目一开始就用独立工具生成正式 keystore并把密码保存在公司密码管理库里。生成方式用 JDK 自带的 keytool 即可keytool -genkey -alias myapp -keyalg RSA -validity 3650 -keystore myapp.keystore。然后在 Project Options Provisioning 里选择 Release 配置填入 keystore 路径和密码。实测下来XE7 对这步的支持还算稳定只要路径里不带中文基本一路顺畅。5.2 APK 体积和启动速度XE7 打包的 APK 基础体积通常在 20MB 以上其中包含完整的 FMX 运行时和原生库。想压缩体积我用过两个相对有效的方案一是把用不到的 FMX 控件从 uses 里去掉让链接器裁剪掉对应单元二是用 RTTI 削减选项只给需要反射的类生成 RTTI 信息。对大多数内部工具类 App能把体积控制在 20MB 出头。启动速度是另一个体验点。老设备上 FMX App 启动时会有 1-2 秒的白屏期这是运行时初始化的开销很难完全消除。缓解办法是在 AndroidManifest 里配置一个自定义启动主题设置 windowBackground 为深色或品牌色让首屏看起来不突兀。这个方案在很多商用 App 里也用原理和 Delphi 无关纯粹是安卓层的技巧。5.3 上架安卓市场 vs 企业内部部署如果你打算把 XE7 打包的 APK 上架到公开应用市场要有心理准备。当前国内主流市场对 targetSdkVersion 有明确要求普遍要求 30 以上而 XE7 默认的 target 版本远达不到。虽然可以通过修改编译配置强行提高 target 值但底层的旧 API 行为会导致系统兼容性问题比如权限、文件路径访问受限等治标不治本。所以我的经验是XE7 的安卓程序主要适合企业内部部署和行业定制分发。给设备装 APK 用 adb install、U 盘安装或者企业 MDM 下发不需要经过应用市场审核。如果你的需求是做一个面向大众的应用商店产品还是老老实实切到新版 Delphi或者直接用原生/跨平台方案别在 XE7 上硬扛。6. 社区高频问题手记几个小问题背后的常见误区6.1 判断周六日时别踩 DayOfWeek 的坑“delphi如何判断是周六日”是社区常问的问题。核心坑在于 Delphi 的 DateUtils.DayOfWeek 返回 1 到 7其中 1 代表周日而习惯上我们默认一周从周一开始。如果你写 if DayOfWeek(Now) 6 来判断周五逻辑完全错误。更清晰的做法是用 DayOfTheWeek 函数它返回 1 代表周一、7 代表周日更符合中文业务习惯。还有一个小细节DayOfWeek 相关的编译条件在某些老版本里会受 System.SysUtils 和 DateUtils 的引用顺序影响建议显式 uses DateUtils避免无意中调用了 System.SysUtils 里的旧版本重载。6.2 WebBrowser 的放大缩小控制XE7 的 TWebBrowser 在安卓上封装自 WebView默认支持手势缩放但很多开发者发现页面缩放时布局错乱或者想禁掉缩放却发现没有直接属性。实际上需要通过 JNI 修改 WebView 的 Settings。调用思路是拿到 WebView 的 Java 实例然后调用 setSupportZoom 和 setBuiltInZoomControls 方法传入布尔参数。如果只是控制网页内容的显示比例更简单的方法是在 HTML 里设置 viewport 标签或者通过 EvaluateJavaScript 执行 document.body.style.zoom。我在一个数据看板项目里就是用 JS 方式控制图表缩放稳定且不用写 JNI 代码。注意 XE7 的 EvaluateJavaScript 方法在某些版本有返回值类型差异尽量只调用不接收返回值避免类型转换异常。6.3 ClientDataSet.CloneCursor 的正确打开方式“tclientdataset的clonecursor函数是干什么的”也是一个高频问题。CloneCursor 的作用是让两个 ClientDataSet 共享同一个数据游标也就是底层共用一份数据但上层可以各自维护不同的过滤条件、排序字段和当前记录指针。这个功能非常适合做“同一张表在不同页面用不同视图展示”的场景比如列表页只显示未完成订单详情页需要显示全部订单。好处是省内存不用复制数据坑在于两个 CDS 是共享游标的一个关闭、清空或修改数据另一个也会受影响。我在实际项目里的使用原则是只读场景放心用写场景老老实实复制数据或用主从表结构。6.4 顺带聊几句老代码里的其他小毛病社区里还有人问“delphi goto”和旧版第三方控件兼容问题。goto 在 Delphi 里存在了很多年但它很容易打乱结构化逻辑老项目里 goto 满天飞的代码维护起来非常痛苦新代码我的建议是坚决不用用 while/break 或封装函数替代。至于第三方控件XE7 能直接兼容的控件库有限很多老 Delphi 7 时代的 DCU 在 XE7 里因为字符串类型、RTTI 机制的变化无法直接使用需要找对应版本源码重新编译这点在项目选型时就该确认清楚。我在 XE7 上折腾安卓开发这几年最大的体会是老框架不是不能用而是要清楚它的边界。很多问题——比如权限、打包、新系统兼容——不是 Delphi 本身写不了而是工具链和时代错位导致的“系统级约束”。如果只是给特定型号的安卓设备做内部工具XE7 的开发效率甚至比原生还高但如果要做长期维护、面向大众市场的东西趁早迁移到新版本。最后再分享一个实操小技巧所有涉及设备路径、IP 地址、适配器参数的配置一定不要写死在代码里用 INI 文件或 SQLite 存起来因为工控现场改参数是常态每次重新编译部署真的会让人崩溃。本文还有配套的精品资源点击获取
返回列表