基于Qt的Android应用程序C/C++开发方法与实践①

2018-07-18 06:06闫锋欣牛子杰杜烁炜潘天丽
计算机系统应用 2018年7期
关键词:跨平台上机调用

闫锋欣, 牛子杰, 杜烁炜, 潘天丽

(西北农林科技大学 机械与电子工程学院, 杨凌 712100)

随着移动互联网技术的飞速发展, 与智能手机应用程序APP开发相关的各类技术得到了不断发展和深入应用, 开发了大量可在智能手机等移动终端运行的第三方应用程序APP, 但存在总体数量丰富而现有基础功能代码重用率低下的矛盾. 因此, 为了能够有效地满足面向移动智能计算复杂APP对低性能硬件资源、实时信息交互服务的需求, 将广域分布的Java、C/C++、Python等源码和脚本进行按需组织和管理, 以实现移动智能计算平台(Windows Phone、iOS、Android等)和桌面操作系统(Windows、Mac OS、Linux/X11等)之间动态、跨自治域的资源共享与协同, 提高代码资源的综合利用率, 降低APP开发的技术难度和成本, 已成为一个重要的科学问题[1].

为解决这一问题, 需要围绕移动智能计算平台APP开发模式建立能够支持代码资源共享和集成的技术方法. 近年来, 国内外学术界和工业界的研发工作取得了大量积极成果: (1) 从APP开发模式看, 主要有Native原生型、Web网络型和Hybrid混合型三种[2].其中, 原生开发是通过使用移动智能计算平台操作系统的API来实现方便、快捷、高性能调用终端的软硬件资源, 但存在学习难度大、移植性差等不足[3]; 网络开发是依靠实时通信移动网络来实现APP的全部功能, 具有开发简单、速度快等优点, 但存在断网无法工作、硬件资源调用不便等缺点; 混合开发是借助第三方跨平台开发框架来实现APP的各项功能. (2) 从APP开发使用的语言看, 原生开发在Windows Phone、Android和iOS平台上会分别使用C#[4]、Java[5]和Objective-C[6], 网络开发主要借助CSS3、HTML5、JavaScript等脚本与网络服务器的通信[7,8], 而混合开发则会同时使用原生API的专用编程语言和网络脚本[9].

Android在移动智能计算领域中占有绝对的优势,Java是其官方开发语言工具. Java采用进程虚拟机的形式为Android APP提供虚拟运行环境, 并通过对APP屏蔽底层硬件平台异构性的方式实现“一次编译随处运行”的跨平台特性[10]. Norris等[11]利用Java和Python开发了可对大体量核磁共振数据进行并行化快速处理的 NMRFx; Radivoje等[12]借助 Java、JavaScript和HTML5等开发了具有高级功能和强大表现力的车载信息娱乐系统; Gao等[13]采用Java + SQL Server开发了Android在线考试系统, 可实现制卷、判分、数据处理等考试环节的全过程自动化处理; 刘伟等[14]利用Android智能手机和移动互联网设计开发了一种便携式角度测量仪, 具有良好的可操作性及便携性. 然而, 基于Java的APP运行时需依赖于底层Dalvik虚拟机环境, 需要较好的计算性能和硬件资源[15,16]. 移动智能计算和物联网的迅猛发展使这些问题在各类极端应用中得到了逐级放大, 已成为Java难以逾越的障碍.

基于第三方跨平台框架的APP混合开发模式是上述问题的有效解决方案之一[17]. PhoneGap、Titanium、jQuery等现有的第三方框架多基于CSS、HTML5、JavaScript等脚本, 虽然解决了APP的跨平台问题, 但性能方面的提升并不明显. 而Qt跨平台编程框架的所有类都采用C/C++开发, 底层类库封装了各平台的本地化实现, 因而具有极高运行效率, 并可广泛运行于Windows、Mac OS、Android、Raspberry Pi等桌面和移动智能计算设备平台[18–20]. 此外, Qt还支持HTML5、Python等解释型脚本和多种编程语言[21].

1 Android APP开发技术分析和框架设计

1.1 APP开发技术分析

Android移动智能计算平台上APP开发模式主要有Native原生型、Web网络型和Hybrid混合型三种:

(1) Native型APP的开发主要是借助运行平台自己的开发框架和API. 例如, 在Android平台上, APP是通过Activity来调用平台的底层API来执行各项功能,而用户执行操作产生的交互结果、APP运行时需要的各类参数等都会以XML形式存储起来.

(2) Web型APP的开发主要体现在服务器端的环境配置. 在Android平台上, 每个APP都可简单地认为是由APP的用户界面(GUI)外加一个Java Web构成的, 全部功能的实现都依赖于实时网络.

(3) Hybrid型APP的开发则主要是借助诸如Apache Cordova等的第三方框架进行开发. 这种开发形式的优点在于运行平台与硬件资源调用API无关,缺点则包括调用性能差等.

图1 Cordova APP开发模式

这里以图1所示的Cordova第三方框架为例来进一步说明Android平台下APP开发的技术特点.Cordova开发APP有跨平台和面向平台两种开发方法,前者使用Cordova CLI (Command Line Interface)工具中的各类shell脚本集来管理APP所欲部署平台的配置内容, 后者使用基于Web的Cordova组件集、Shell脚本和Plugman工具等对底层Android平台的SDK进行整合开发. 可以看出, 这种开发方法仍需借助CSS、JS和Shell脚本等才能够完成APP的开发.

1.2 基于C/C++的APP开发框架设计

针对重新学习Java等编程语言所带来的较高学习成本和技术风险问题, 极有必要开展Android平台下基于C/C++的APP开发方法研究. 这里给出基于C/C++的APP开发框架, 如图2所示.

图2 基于C/C++的APP预期开发方法

图2中, 采用C/C++开发APP的底层技术是解决C/C++和Java两类语言之间的相互调用问题, 特别是针对Android平台的Java和C/C++类库之间相互调用的问题. 从APP功能开发和实现的角度看, 它的各种运算、控制等各功能模块的开发实现都用的是C/C++代码, 就为重用其他项目的既有代码提供了直接入口, 也为C/C++开发人员专注于新功能代码的编写提供了接口. 同时, 与用户交互的图形用户接口(GUI)、对Android底层API的调用、移动计算设备的硬件资源通信等衔接工作, 则可以通过第三方的C/C++类库全权负责.

上述类库应具有的基本特点是: (1) 全部采用C/C++编程语言; (2) 具有与平台无关的跨平台能力;(3) 能够满足移动移动智能计算平台硬件资源较低的苛刻要求. 为此, 本文选用已在桌面和嵌入式平台领域内广泛应用的跨平台开发框架Qt. 下面探讨Qt开发Android APP的技术机制和实施方案.

2 Qt开发Android APP的工作机制

Qt是C/C++类库开发框架, 因而必须先构建起与Java之间的相互调用通道. 从Android APP的底层来看, 只能利用Google的NDK(Native Development Kit)来为基于C/C++的Android APP提供必要的编译工具和基础文件. 同时, 还要利用NDK来将C/C++程序封装嵌入到Android包文件(.apk)中, 以及对Android SDK升级后的头文件和库文件进行调用. 然而, 由于Android APP独自运行于各自的Dalvik虚拟机中, 且NDK只对外开放了虚拟机的部分接口, 造成C/C++程序调试难度大、兼容性差等问题, 需先开展其封装性研究.

2.1 基于Qt的Android APP封装模型的建立

利用Qt C/C++类库直接开发Android APP, 需要分别考虑APP开发的两个部分:

(1) 基于Qt类库的C/C++程序部分. 这一部分主要是指APP实现数学计算、图像处理等的那些功能;

(2) 基于Java的Android底层资源调用API部分.这一部分主要是指与Android底层硬件通讯和调用等的功能.

对于(1)来说, 该部分的代码均是Qt C/C++的程序, 在Qt内部会先经Qt元对象编译器(meta object compiler, moc) 将含有 emit、signals、slots、Q_OBJECT等关键字的Qt源代码处理为面向对象的标准C++类, 然后再在不同平台下分别利用g++、gcc、msvc等编译器进行源代码的(交叉)编译, 最后通过对Qt等各依赖库文件的链接, 生成可在不同平台下运行的可执行APP程序.

对于(2)而言, 该部分主要是指通过Java、XML等描述的与Android平台交互的各类资源, 包括manifest、assets/strings/images、Ministro service 和Java类等, 用来实现APP在Android平台上的调用、权限获取、通信部署等工作.

为在(1)和(2)之间, 即基于Qt的“纯”C/C++类源代码和不对第三方开放的Android平台之间, 需以JNI(Java Native Interface)为桥梁来实现两者的协同工作. 当Qt调用Android系统中的部分已有功能时, 就可借助JNI访问它们. 同时, Qt作为专注于跨平台的C++开发框架, 也不可能全部实现Android的所有功能. 某种程度上, JNI成为Android APP和C++程序之间相互调用的唯一通道.

为此, 本文给出如图3所示的基于Qt的Android APP封装模型. 其中, 在“模块①”中, Qt会利用抽象层QPA (Qt Platform Abstraction)对全部操作系统平台进行统一化支持, 确保采用Qt类库的所有程序均可直接运行于所有操作系统平台上, 且不限于Android平台;在“模块③”中, APP仍旧采用类似Java APP的形式,依靠独自的Dalvik虚拟机无缝运行于Android平台,这样就可以通过所处的Dalvik虚拟机对第三方程序开放部分接口并支持外部的JNI调用; 当两者需要交互通信时, 可分别利用Qt事件循环和Android事件循环,借助“模块②”中的类THREAD线程交换信息.

图3 基于Qt的Android APP封装模型

此外, 通过Qt对Java代码的支持, 可进一步拓展Qt APP的功能和应用范围, 把Qt C/C++程序封装成.apk包文件并平稳运行于Android平台上.

2.2 Qt C/C++与Android Java间的调用机制

要基于Qt C/C++开发可运行于Android平台的APP, 就必须先实现从Qt C/C++程序调用Java的Android线程. 这是因为, Android的部分API设计机理不允许对外完全开放且必须在Android的UI线程中进行调用[22]. 然而, 因Qt不可能实现Android的全部功能而又要在Qt中调用这些功能时, 就需采用一定的方式来将其运行于Android UI线程中.

定义1. 正向调用. 从Qt C/C++事件循环线程到Android Java UI线程的调用称为正向调用.

定义2. 逆向调用. 从Android Java UI线程到Qt C/C++事件循环线程的调用称为逆向调用.

这里给出在Qt C/C++与Android Java两者之间进行双向调用的多线程机制, 如图4所示.

该机制的正向调用主要过程如下:

三是建立健全农村供水项目资金管理制度,提高资金使用效益。建立健全覆盖项目立项、设计、实施、验收、管理等环节在内的整个资金运行全过程的管理制度体系,确保每项水利资金都有相应的资金管理制度,严格使用管理。对农村饮水安全项目的中央投资和省、市配套资金,在市农村饮水安全项目办公室设专户管理,实行市级报账制;县级自筹资金在县农村饮水安全项目办公室设专户管理,实行县级报账制。对妇基会的专项百事慈善资金加强管理,属于工程部分全部用于项目,采取水务局到妇联报账的管理办法。

步骤1. 在Qt C/C++事件循环线程中调用自定义的Java方法并在Qt线程中执行, 设该方法的名称为cppCallJava(), 为在Android Java线程中访问Android的API做好准备.

步骤2. 在cppCallJava()方法中, 借助Android的Activity.runOnUiThread, 向Android的UI线程事件队列中添加一个public型Runnable动作并在Android的UI线程中执行这个Runnable动作.

步骤3. 因处于执行状态的Runnable对象本已在Android的UI线程中, 因而就可以直接访问所需的Android API.

若Android平台中的原生Java APP需调用基于Qt的C/C++ APP, 就形成了逆向调用过程. 此时, 与正向调用类似, 同样可在Android UI线程中调用Qt的C/C++函数.

图4 Qt与Android之间的技术关联

逆向调用的主要过程包括:

步骤1. 在Android UI线程中调用相应的Qt C/C++方法, 令其名称为javaCallCpp().

步骤 2. 在 javaCallCpp()方法中, 使用 Qt的QMetaObject: : invokeMethod方法向Qt事件队列中添加一个异步或同步调用.

步骤3. 在Qt线程中, 处理javaCallCpp()方法所添加的调用事件.

经过上述双向调用后, 就可以实现Qt C/C++功能程序和Android Java API之间的相互调用了.

3 实验结果及展示

3.1 基于Qt的学生导教APP设计

图5给出的是机械CAD技术基础课程上机实践的基本流程. 学生在实验室机房按照授课内容完成对应的上机编程练习, 用U盘等保存自己的代码. 因各章内容相对独立, 上机实践完成的习题源代码也相对分散, 仅有30%左右的学生能够在最后一次的综合实践课中重用这些代码; 同时, 由于机房内台式机完成的程序无法移植到学生的智能手机、平板等可移动智能计算设备上, 导致每次上机实验中学生主动编程的积极性不高, 相互复制抄袭的比例较高, 上机训练效果一般.此外, 因课程内容与实际的学习生活关联性不强, 学生缺少成就感.

图5 传统机械CAD上机训练流程

针对上述问题, 将学生每次上机实践训练时完成的C/C++程序代码作为APP的各项功能, 通过使用Qt构建的APP UI界面和QPA类屏蔽与Android平台相关的硬件资源具体差异, 再利用Qt的多线程机制在C/C++事件和Android Java事件之间建立通信联系, 就可以开发出Android版的机械CAD导教APP. 整个APP的体系架构和各模块间的逻辑关系如图6所示.

图6 Android版机械CAD导教APP的体系架构

APP可实现的基本功能包括: (1) 在APP中查看不同章节的上机实验安排, 了解实验原理、算法步骤、注意事项等; (2) 点选单项实验后可通过完善模板空白或借助对话框、单(复)选框等进行人机交互; (3)根据教师发布的新消息或内容更新, 由系统自动提示给相应的学生群组; (4) 点击“运行”等按钮后执行内置的单项实验程序样例, 为上机实验提供参考和指导; (5)阅读、编辑、保存或另存修改后的核心程序代码.

3.2 导教APP的开发过程

本文以Win7为开发平台, 利用Qt C/C++来完成APP的全部开发工作. 基于Qt C/C++开发框架中的Qt Designer、uic、moc等辅助开发工具, 可以把开发的用户界面翻译为XML中间文件, 再通过内部编译连接工具翻译为可在Android平台下运行的二进制文件. 同时, 为了能够方便地“一键”实现从C/C++源代码开发环境直接到Android平台上APP的自动运行, 还可以使用Ant、Gradle等自助打包开源软件. 为此, 将完成各部分辅助开发功能的(开源)软件整理后列示在表1中.

表1 Win7平台APP开发所需的辅助工具

具体来说, 各软件的主要作用是: (1) Android SDK,即Software Development Kit(Android软件开发工具包), 采用Java开发完成, 是Android APP运行所需的底层基础组件和Android平台开发的专属工具包; (2)JDK, 即Java Development Kit(Java开发工具包), 包括Java运行环境(Java虚拟机与Java系统类库)和Java基本组件工具; (3) Apache Ant或者Gradle可生成APP的. apk包文件, 可自动完成编译、测试和部署等步骤; (4) ADB, 即Android Debug Bridge(Android调试桥), 可在电脑上调试Android手机设备或模拟器;(5) Google NDK, 即Native Develop Kit(原生开发工具包), 支持Android平台调用C/C++程序.

基于Qt C/C++的Android APP开发步骤主要包括:

步骤1. 安装所需开发工具软件并对其进行配置.各辅助开发工具软件的安装配置要遵循先安装再配置的方式来有效解决相互之间的依赖关系, 如表1中的各软件工具可在依次安装Qt、JDK、Apache Ant、Gradle、Android NDK、SDK和Google ADB后, 在对它们的运行环境变量进行相应的设置.

步骤2. 利用QtCreator中内嵌的Qt Designer开发APP的用户界面, 在相应的功能模块区域中填充相应的按钮、输入框等窗口部件, 设计过程中随时可以使用Alt+Shift+R快捷键等方式预览设计效果, 如图7所示.

步骤3. 通过添加不同的信号-槽连接, 设置所需的JNI静态函数, 将界面元素和相应的功能实现源程序代码关联起来, 达到点击按钮产生相应动作响应的效果; 同时, 为加速开发过程和减少功能优化时的复杂性, 可先采用Desktop桌面形式进行开发调试, 并综合利用QtCreator集成开发环境中的编译、连接功能对APP系统进行优化、测试和调试.

步骤4. 达到APP设计的满意效果后, 将QtCreator中运行模式调整为Android for armeabi-v7a, 然后进行编译、连接和. apk包在Android操作平台上的自动安装. 生成的. apk安装包文件既可以通过手动方式在Android手机上安装, 也可通过配置QtCreator开发环境后自动安装.

图7 APP软件系统在桌面环境下的开发效果

3.3 结果展示与评价

图8(a)是Android版机械CAD课程导教APP在手机(型号HUAWEI MT7-CL00)横放时的显示效果,用户此时选定了计算“V带尺寸”实验. 在APP界面的左侧, 给出了各章上机实践所需完成的任务, 还包括“平键尺寸”、“一元插值”、“V带功率”等实验项目; 界面中间是每个实验的说明, 未显示完全的文字可通过边侧的滑动条进行翻页; 界面右侧是该项实验所需的核心代码.

图8中的黑色区域是手机屏幕的上方和右侧, 用来显示Android手机的系统菜单栏. 值得注意的是, 只有当如图8(a)所示的形式, 对APP中的叙述性文字或者代码进行了修改时, 按钮“保存”和“另存为…”才会变为可用状态. 图8(b)给出的是在点击了图8(a)中的按钮“运行”后, 查询出的Z型V带(其代号为1)的截面尺寸值; 图8(c)是同一计算过程在Win7操作系统下的显示效果. 可以看出, 同一对话框因运行平台所能够支持的默认参数不同而具有一定的显示效果差异.

图8 Android 6.0下APP运行效果及查询结果对比

在 2016–2017学年第 1学期 (2016年 10月17日~12月25日)的机械CAD课上机实践训练过程中, 由机制专业的122名本科生首次使用Android版机械CAD导教APP进行了性能测试和实验评估. 图9给出了全体学生使用频率的时间分布, 可以看出, 从第8周课程开始到第17周课程结束, 10周期间共收到学生提交更新建议19项、疏漏补正76个, APP打开使用6025次(网络连接状态). 以10周共50个工作日为例,每天人均使用0.988次, 说明在日常教学活动中得到了较好应用. 从第二周的周五开始, 每周五都有较高的使用次数, 这也与周五是上机实践训练课的实际情况相符. 在周一至周四的日常学习期间使用量并不多, 可见本科生并不愿意在专业课上投入过多的学习时间和精力.

图9 APP的每周使用数分布

可以看出, 利用C/C++编程开发语言并借助Qt开发框架, 通过使用相关开源软件能够开发出满足实际需要的Android APP应用程序, 既降低了重新学习Java和JavaScript等开发环境所带来的负担, 又为重用已有的C/C++程序提供了新途径.

4 结论与展望

本文在分析了Google的NDK不能为C/C++程序提供全部Android功能调用的基础下, 给出了基于Qt C/C++框架开发Android APP的方法和原理, 深入阐释了Qt C/C++与Android Java两者之间的调用方法, 给出了Win7平台下开发Android APP过程的主要步骤.同时, 通过Android版机械CAD导教APP的开发和该APP的实际使用结果的展示和评价, 说明了基于Qt C/C++开发Android APP方法的有效性和可行性. 在未来的研究工作中, 将进一步对复杂需求环境(如图形快速渲染等)下基于Qt和Java开发的Android APP综合运算性能做出分析和评测.

猜你喜欢
跨平台上机调用
周金应
跨层级网络、跨架构、跨平台的数据共享交换关键技术研究与系统建设
一款游戏怎么挣到全平台的钱?
潜力双跨平台:进阶:谁将跨入下一个“十大”?
核电项目物项调用管理的应用研究
系统虚拟化环境下客户机系统调用信息捕获与分析①
上机数控“可疑”的高毛利率
高中信息技术教学实效探究
高中信息技术教学实效探究
基于C++语言的跨平台软件开发的设计