65.9K
CodeProject 正在变化。 阅读更多。
Home

移动应用程序开发经验教训

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2012年8月13日

CPOL

7分钟阅读

viewsIcon

39893

downloadIcon

478

本文讨论了在移动应用程序开发过程中吸取的两点经验。

引言

本文讨论了在移动应用程序开发过程中吸取的两点经验。总体而言,除了在项目中期进行的规格变更,需要添加背景图片并更改连接到移动设备的打印机之外,开发过程均未受到严重影响。

背景

应用程序

该移动应用程序是一款工作流程应用程序,旨在指导街头小贩完成剧院门票销售过程。它供经过培训的操作员使用。顾客若想购买剧院门票,可以通过该应用程序查询可用的演出场次和座位。当特定演出场次和座位数量确定后,设备会查询剧院服务器以获取具体座位信息。当顾客同意演出场次和座位(这两者组合决定了票价)后,顾客可以使用信用卡或现金支付。经卡发行方接受后,门票即被预订,并将打印门票和收据。

执行环境

该移动应用程序运行在 Motorola MC65 设备上。该设备通过蓝牙连接到 Intermec PB31 打印机,并通过虚拟专用网络 (VPN) 连接到剧院服务器。后者除了提供连接性外,还提供了设备与其服务器之间的安全通道。Web 服务用于与剧院服务器之间传递数据。该设备运行 Microsoft Windows 6.5 操作系统。VPN API 和刷卡 API 由 Motorola 在 Symbol 库中提供。

开发环境

该项目使用 Visual Studio 2008 IDE 和 .NET 3.5 框架在笔记本电脑上作为 Windows 应用程序开发。目标平台是 Windows Mobile 6.5.3 Professional DTK。在部署软件之前,使用了 Windows Mobile 6.5.3 Professional VGA 模拟器来测试该软件。

屏幕显示是通过将 Microsoft Mobile Device Emulator 作为 Visual Studio 2008 的插件来实现的。当屏幕实现完成后,会交给内部质量保证人员进行审查,然后才提供给客户。如果发现错误,则在提供给客户审查之前进行修复。尽早收集客户的反馈意见对于确保开发能够贴近客户最初的设想非常重要。

学到的教训

背景图像

在移动应用程序开发过程中,直到项目中期才指定背景图片。这造成了中断,因为需要修改所有需要背景图片的窗体。我建议为项目包含背景图片,无论是否需要背景图片。该图片不必是最终的(如果需要的话)背景图片,而应该是一个占位符。

为了方便讨论,我将使用以下 Visual Studio 目录结构

Solution Tree

步骤如下

  1. 定义一个纯色 JPG 图片。使用任何熟悉的工具(例如 Paint)创建临时背景图片。选择一种颜色,使其接近将在窗体上显示的控件的颜色。在此示例中,纯色为 RGB (213, 229, 245)。将图像大小设置为足够覆盖目标设备的大小。生成的图像是

    Unspecified Background Image

  2. 在启动项目(以下简称“LessonsLearned”)下创建一个名为“Images”的文件夹,并将 JPG 文件保存在该文件夹中,命名为“BackgroundImage.JPG”之类的名称。

  3. 选择 LessonsLearned;点击“刷新”,然后点击“显示所有文件”;右键单击“Images”文件夹;然后点击“包含到项目”。文件夹将打开,显示 BackgroundImage.JPG 文件。

  4. 左键单击 BackgroundImage.JPG 文件。在“属性”窗口中,将“生成操作”更改为“嵌入的资源”。

  5. 右键单击 LessonsLearned 并选择“属性”。打开“资源”选项卡。从下拉菜单中选择“图像”。左键单击 LessonsLearned 文件夹“Images”下的 BackgroundImage.JPG 文件名,并将其拖到“资源图像”区域。确保图像资源名称为 BackgroundImage。

  6. 向 LessonsLearned 中添加一个接口(C# 类),其中包含
    using System.Drawing;
    
    // http://blogs.commentor.dk/post/Transparent-Controls-in-NETCF.aspx
    
    namespace LessonsLearned
        {
    
        // ********************************** interface IControlBackground
    
        public interface IControlBackground
            {
    
            Image BackgroundImage { get; }
    
            } // interface IControlBackground
    
        } // namespace LessonsLearned
    该接口以及随后的基类,均源自 Christian R. Helle 的文章 .NETCF 中的透明控件

  7. 向 LessonsLearned 中添加基类(C# 类)FormBase
    using System.Drawing;
    using System.Windows.Forms;
    
    // http://blogs.commentor.dk/post/Transparent-Controls-in-NETCF.aspx
    
    namespace LessonsLearned
        {
    
        // ************************************************ class FormBase
    
        public class FormBase : Form, IControlBackground
            {
            private Bitmap background = null;
    
            // ************************************************** FormBase
    
            public FormBase ( )
                {
    
                if ( background == null )
                    {
                    background = new Bitmap ( LessonsLearned.
                                              Properties.
                                              Resources.
                                              BackgroundImage );
                    }
                }
    
            // *************************************************** OnPaint
    
            protected override void OnPaint ( PaintEventArgs e )
                {
    
                e.Graphics.DrawImage ( background, 0, 0 );
                }
    
            // ******************************************* BackgroundImage
    
            public Image BackgroundImage
                {
    
                get
                    {
                    return ( background );
                    }
                }
    
            } // class FormBase
    
        } // namespace LessonsLearned

现在我们可以使用新的背景图片了。在移动应用程序中所有可能具有背景图片的窗体中,只需继承自基类 FormBase,如下所示:

namespace LessonsLearned
    {

    // ***************************************** class Lessons_Learned

    public partial class Lessons_Learned : FormBase
        {
        public Lessons_Learned ( )
            {

            InitializeComponent ( );
            }

        } // class Lessons_Learned

    } // namespace LessonsLearned

执行此项目时,将显示如下

Background Image Placeholder

现在假设指定了背景图片。例如,它看起来像

Specified Background Image

要实现此新背景图片,只需将新的背景图片 JPG 复制到 \Images\BackgroundImage.jpg。当执行此修改后的项目时,将显示如下

Background Image Specified

Intermec 打印机

移动应用程序打印机用于打印门票和收据。两者都包含文本和图形,这些内容需要战略性地放置在打印的门票或收据上。客户的营销组织负责指定项目的位置。

在开发之初,指定了 Intermec PB21 移动收据打印机(以下简称“PB21”)。PB21 的最大打印宽度为 1.8 英寸。开发团队选择了 Intermec Printer Language (IPL) 来定义收据和门票模板。这个选择并非最佳:IPL 是一种难以学习的语言;其维护成本巨大。例如,要指定一个带边框的文本字符串,需要以下命令:

IPL 命令 含义
<STX>R<ETX> 退出程序模式
<STX><ESC>C0<ETX> 选择高级模式(0.005 英寸点大小)
<STX><SI>W1591<ETX> 将标签宽度设置为 1591 个点
<STX><SI>h<ETX> 设置正常打印(黑底白字)
<STX><SI>o1<ETX> 开机时联机
<STX><ESC>P<ETX> 进入程序模式
<STX>E1<ETX> 擦除格式 1
<STX>F1<ETX> 定义格式 1
<STX>W1;f0;o0,0;l1200;w1;h550;<ETX> 创建框 1;水平方向;原点在 0,0;长度 200;粗细 1;高度 550
<STX>H2;f0;o75,200;c40;d3,THIS IS A PRINTER TEST;<ETX> 创建可读文本;水平方向;原点 75,200;30 点粗体等宽字体;后跟数据
<STX>D0<ETX> 删除字段 0
<STX>R<ETX> 退出程序模式
<STX><ESC>E1,1<ETX> 选择格式 1;仅重新绘制
<STX><CAN><ETX> 清除所有数据
<STX><RS>1<ETX> 设置数量计数为 1
<STX><US>1<ETX> 设置批次计数为 1
<STX><ETB><ETX> 打印
<STX><FF><ETX> 换页

项目中期,Intermec PB31 移动收据打印机(以下简称“PB31”)取代了 PB21。PB31 的最大打印宽度为 2.8 英寸。幸运的是,更换时,可以重新考虑用于定义标签的语言选择。新选择的语言是 Intermec Fingerprint。摘自 程序员参考手册

Intermec Fingerprint 是一种类似 BASIC 的、驻留在打印机中的编程语言……Fingerprint 是一种**易于使用**的智能编程工具,用于标签格式设置和打印机定制……由于新需求的**改进或更改**可以**快速且以最低的成本**实现。

IPL 的缺点通过选择 Fingerprint 得到了解决。使用与上面相同的示例,需要以下命令(请注意坐标不相同):

Fingerprint 命令 含义
CLEAR 清除字符串、变量和数组
CLL 清除打印图像缓冲区
CLIP ON 即使在打印窗口之外也进行打印
FONT Swiss 721 Bold BT,16 设置字体和字号
DIR 4 沿进给方向打印
ALIGN 7 将锚点设置为左上角
PRPOS 75,0 指定框插入点
PRBOX 550,1050,1 绘制框 550 x 1050
PRPOS 150,75 指定文本插入点
PRTEXT "THIS IS A PRINTER TEST" 绘制文本
PRINTFEED 打印框和文本并换页

使用 Intermec IPL 似乎没有任何优势;而使用 Intermec Fingerprint 则具有易于使用(学习曲线浅)和可读性强(即易于维护)等主要优点。

经验总结:谨慎选择第三方语言;选择最容易学习和维护的。

摘要

我敢肯定,我的许多读者可能已经意识到了移动应用程序开发中的这两个潜在陷阱。我在此提出它们,仅仅是因为它们导致了中断和项目延期。

历史

  • 2012年8月13日 - 原始文章
© . All rights reserved.