App Inventor编程教程-第12课-广播中心-少儿编程教育网

App Inventor编程教程-目录

想象一下,你像往常一样,正在一条熟悉的路上慢跑,突然被一个念头打动——一款全新的杀手级移动应用!一路上,你甚至忘记了回家…

前线短信(FrontlineSMS)是一款工具软件,用于联络那些无法访问互联网但可以用手机通信的人,通常用于发展中国家或互联网尚未普及地区的选举监督、天气预报广播等。该软件的作者Ken Banks借助于移动通信技术为人们提供帮助,他的贡献大概无人能及。

该软件可以在一个小组内使用,为组内成员提供短信息接收及广播服务。任何人可以发送一个特殊代码来加入小组,随后他们将收到广播中心发来的信息。对于那些无法访问互联网的地区, 广播中心成为其与外界联系的至关重要的手段。

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-1 设计视图中的“广播中心”
本章将要创建的“广播中心”应用,与前线短信软件有相似之处,只是“广播中心”运行在安卓手机上。随身携带一台安装了“广播中心”应用的移动设备,意味着管理者可以在移动中与组员之间保持信息交流,这一点在某些场合下尤其重要,如选举监督和医疗谈判等。

假想有一个“快闪舞蹈团”,他们可以召之即来,随时随地表演即兴舞蹈,然后瞬间解散,消失得无影无踪。他们用你创建的“广播中心”来组织表演活动。人们只要向中心发送短信“参加快闪舞蹈团",即可完成入团注册,每个注册成功的人都可以向舞蹈团中的其他人广播消息。

当“广播中心”接收到短信时,有以下几种处理方式。

  1. 首先判断发信人是否在广播中心的组员名单中,如果不在组员名单中,则回复短信邀请他加入,并告知他申请代码。
  2. 如果收到短信的内容是“参加快闪舞蹈团”,则将发信人接纳为广播中心成员。{![如果组员发送“参加快闪舞蹈团”呢?应用的逻辑上或许存在漏洞,试看后面如何分解。——译者注]}
  3. 如果发信人已经是广播中心的成员,则转发该消息给全体广播中心成员。

比起第4章的“开车不发短信”,这个应用更为复杂,不过我们可以采取循序渐进的方式,每一步只完成一项功能。首先,用自动回复来邀请人们加入广播中心。在整个应用完成之后,你将对于创建这类“以短信为用户界面的应用”有透彻的了解。你是否打算写一个短信投票的应用(就像电视选秀节目中使用的那种),或下一款超棒的群组短信应用?本章的学习将使你如愿以偿。

学习要点

本章包括下列App Inventor概念,其中有些你可能已经熟悉了。

  • 短信收发器组件:发送短信及处理收到的短信。
  • 列表变量及动态数据:在本例中用来记录电话号码清单。
  • 遍历列表:对列表中的数据进行逐项重复操作。在本例子中,使用“针对列表()中的每一(项)”块向电话号码列表中的所有手机广播消息。
  • 本地数据库组件:实现数据的永久存储,以保证当应用关闭并再次打开时,电话号码列表不丢失。

准备开始

你需要一部可以接收和发送短信的手机来测试程序,还需要招呼一些朋友给你发送短信,来充分地测试应用。

登录App Inventor网站,创建名为“广播中心”的新项目,设置Screen1的标题属性为“广播中心”,并连接测试手机或模拟器。

设计组件

“广播中心”有利于手机之间的通信:这些手机不需要安装应用,甚至不必是智能手机。这些手机通过短信与你的应用通信,因此,应用的用户界面只是为群组的管理人员而设计的。

管理员的用户界面包括两个简单的部分,一是显示当前的“广播列表”,即已注册成员的电话号码清单,二是记录所有收到并已经被广播出去的短信。

为了创建这个界面,要添加表11-1中列出的组件。

表11-1 “广播中心”用户界面中的组件

App Inventor编程教程-第12课-广播中心-少儿编程教育网

设置每个标签的宽度属性为“充满”,让组件在水平方向上充满手机;添加组件之后,还要设置以下属性:

  1. 设置标题标签的字号属性(标签1和标签2)为18,并勾选粗体属性;
  2. 设置广播列表标签及广播日志标签的高度为200像素,用于显示多行文本;
  3. 设置广播列表标签的显示文本属性为“广播列表...”;
  4. 设置广播日志标签的显示文本属性设置为空;
  5. 设标签1的显示文本为“已注册的电话号码”;
  6. 设标签2的显示文本为“活动日志”。

图11-1显示了设计视图中应用的布局。

App Inventor编程教程-第12课-广播中心-少儿编程教育网图11-1 设计视图中的“广播中心”

为组件添加行为

在这个应用中,促使程序运行的事件是其他手机发来的短信,而不是用户在界面上的输入或点击,因此应用的任务是处理这些短信,并将发信人手机号码保存到列表中。具体操作如下。

  • 如果短信发送者不在广播列表中,则回复一个邀请加入的短信。
  • 如果收到短信“参加快闪舞蹈团”,则将发送者注册为广播列表的一员。
  • 如果短信发送者已经在广播列表中,则将该短信广播到列表中的所有手机。

回应收到的短信

现在开始创建第一个行为:收到短信时,回复发送者,邀请他注册。方法是向你发送短信“参加快闪舞蹈团”。表11-2中列出了需要的块。

表11-2 邀请人们通过发短信来加入群组,需要下面的块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

如果你已经学完第4章的“开车不发短信”应用,应该很熟悉这些块。当手机收到短信时会触发短信收发器1的收到消息事件。如图11-2所示,在事件处理程序中设置短信收发器1的电话号码及短信属性,然后发送短信。块的作用

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-2 收到短信后发送邀请短信
App Inventor编程教程-第12课-广播中心-少儿编程教育网测试:需要用第二部手机来测试这一功能;你不能给自己发短信,否则会永远循环下去!如果没有其他手机,可以注册Google Voice或类似的服务,从这些服务中给自己的手机发短信。用第二部手机发送“你好”到测试手机,则第二部手机会收到一个邀请加入群组的短信。

接纳申请人加入广播列表

现在创建第二个行为所需要的块:收到“参加快闪舞蹈团”的短信后,将发信人的电话号码添加到广播列表中。首先,定义列表变量“广播列表”来保存已注册的电话号码。从变量抽屉中拖出一个声明变量块,将“我的变量”改为“广播列表”,并从列表抽屉中拖出“空列表”块,为变量设置初始值。如图11-3所示(稍后将实现向列表中添加列表项的功能)。

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-3 收到短信后发送邀请短信
下面修改短信收发器1收到消息事件的处理程序,如果收到短信“参加快闪舞蹈团”,则将发信人手机号码添加到广播列表中。判断短信内容需要使用“如果...则...否则”块(在第10章“出题”应用中使用过),将新号码添加到列表中需要使用“向列表()添加项()”块。整个设置所需的块见表11-3。在电话号码添加完毕之后,用广播列表标签来显示新列表。

表11-3 检查来信内容,并将发信人添加到广播列表中,需要如下代码块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

如图11-4所示,要对刚收到的短信进行回复,因此,第一行代码将发信人手机号码设置为接收人手机号码,即设置短信收发器1的电话号码属性为收到消息事件中的电话号码参数。然后,判断事件中携带的消息内容参数是否为特殊代码“参加快闪舞蹈团”。如果是,则将发送者手机号添加到广播列表,并回复短信祝贺;如果不是,则回复邀请短信。在“如果...则...否则”块之后,回复短信被发出(最后一行)。块的作用

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-4 如果收到短信“参加快闪舞蹈团”,将来信电话号码添加到广播列表
App Inventor编程教程-第12课-广播中心-少儿编程教育网测试:用第二部手机发送短信“参加快闪舞蹈团”到测试手机,在测试手机收到短信的同时,第二部手机的号码出现在“已注册的电话号码”下面,第二部手机会收到祝贺短信。尝试发一个其他内容的短信,检查邀请短信是否能正常发送。

广播消息

下面来添加广播消息功能:当广播列表中的成员向广播中心发来短信时,将此信息转发给列表中的所有手机。这一功能略微有些复杂,需要更多的控制块:增加一个“如果...则...否则”块和一个遍历列表块。新增的“如果...则...否则”块用于检查发送短信的手机号是否在广播列表中,而遍历列表块用于向列表中的所有手机广播这条短信。另外还要将之前的“如果...则...否则”块移动到新的“如果...则...否则”块的“否则”分支中。表11-4列出了需要新增的块。

表11-4 向广播列表中的成员群发短信需要新增的块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

这里使用了嵌套的“如果...则...否则”块,使得程序变得更加复杂,如图11-5所示。嵌套的“如果...则...否则”块指的是在一个“如果...则...否则”块的“则”或“否则”分支中又嵌入了另一个“如果...则...否则”块。在本例中,外层的“如果...则...否则”块负责检查发信人的手机号是否已在广播列表中。如果在,则将该短信转发给列表中的所有人;如果不在,则执行内层“如果...则...否则”判断:消息内容是否为“参加快闪舞蹈团”,并依据判断结果,执行不同的分支操作。块的作用

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-5 检查发信人是否已在广播列表中,如果是,则广播此短信
从理论上,“如果...则”块和“如果...则...否则”块可以做任意层级的嵌套,来实现更加复杂的逻辑(更多关于条件语句块的内容,请参见第18章)。

在外层“如果...则...否则”块的“则”分支中,使用遍历列表块来广播短信。通过遍历广播列表中的每一个电话号码,来设置接收短信的电话号码,并将短信发送给该号码。在遍历广播列表的过程中,列表中的每个电话号码依次被保存在占位符变量“电话”中(“电话”是一个变量,代表了遍历过程中当前正在处理的项)。在遍历列表块内,设置短信收发器1的电话号码为当前项“电话”,并向其发送短信。有关遍历列表的更多信息,请参见第20章。

App Inventor编程教程-第12课-广播中心-少儿编程教育网测试:除了测试手机之外,还需要另外两部手机向测试手机发送“参加快闪舞蹈团”,以便注册成为广播列表成员。然后,从一部手机向广播中心发送一条短信,这时两部手机都应该收到这条短信(包括发送短信的那一个)。

美化列表的显示

广播短信的功能已经实现,但管理员的用户界面尚需改进。首先,电话号码列表显得很混乱。用标签显示列表时,列表项之间用空格分隔,并且尽可能占满一行,像下面这样:

(+861303318989 +861581235590 +8618902018909 +8613301103355 +8613801237890)

为了改善这种局面,使用表11-5列出的块创建一个名为“显示广播列表”的过程,来实现每行只显示一个号码。请务必在添加列表项块的下面调用该过程,以便显示更新后的列表。

表11-5 改进电话号码列表显示所需的块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

“显示广播列表”过程里的遍历列表块逐项地将每个手机号码添加到标签的末尾,如图11-6所示,用换行符(\n)来分隔每个号码,使得每个号码各占一行。块的作用

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-6 分行显示电话号码
不过,“显示广播列表”过程不会主动做任何事情,除非调用它。在短信收发器1的收到消息事件中,在添加列表项块之后调用它。过程的调用取代了对广播列表的直接显示。在过程抽屉中,可以找到“调用显示广播列表”块。

图11-7显示了对收到消息事件的处理。

App Inventor编程教程-第12课-广播中心-少儿编程教育网
图11-7 调用显示广播列表过程
关于用遍历列表项的方法来显示列表内容的详细信息,请参见第20章;关于创建和调用过程的详细信息,请参见第21章。

App Inventor编程教程-第12课-广播中心-少儿编程教育网测试:重新启动应用来清除列表,然后用至少两部不同的手机重新进行注册。手机号码是否分行显示了?

记录广播过的短信

在收到短信并向其他手机发出广播之后,程序应该记录此类事件,以便管理员可以对活动进行监督。已经在设计视图中添加的“活动日志标签”就是用于这一目的。下面编写程序,每当收到并广播新的短信时,改变活动日志标签的显示内容。

要创建像这样的一段文本:“来自+8613901231234的短信已经广播。”字符“+8613901231234”不是固定数据,而是收到消息事件中携带的参数。因此,要创建的文本包括三个部分:①“来自”;②手机号码,为事件携带的手机号码参数;③“的短信已经广播”。

正如在前几章中所做的一样,用拼字串块将三个部分连接起来,表11-6中列出了所需要的块。

表11-6 构建活动日志所需要的块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

在收到短信后,向广播列表中的所有号码广播此短信,再修改活动日志标签,记录刚才的广播操作,如图11-8所示。需要注意的是,我们将消息添加到列表的开始,而不是结尾,因此最后发出的消息将显示在最顶端。块的作用

App Inventor编程教程-第12课-广播中心-少儿编程教育网图11-8 向活动日志中添加新内容
拼字串块创建了一条新记录:来自+8613901231234的短信已经广播。

每次短信广播之后,这样的一条记录就被添加到活动日志标签的第一行,使最新的记录一直出现在顶部。拼字串块中各个文本片段的顺序决定了日志中记录的顺序。在本例子中,新消息被编排在前三个插槽中,而活动日志标签的显示文本,即已经保存的现有记录,则放在最后一个插槽中。

字符串“的短信已经广播。\n”中的“\n”称为换行符,它让每条记录单独占一行,像这样:

来自+8613030123668的短信已经广播。 来自+8613901231234的短信已经广播。

关于使用遍历列表块来显示列表内容的详细信息,请参见第20章。

将广播列表保存到数据库中

现在应用算是大功告成了,但通过前几章的学习,你可能已经猜到,这里存在一个问题:如果管理人员将应用关闭再重新打开时,广播列表中的数据将全部消失,每个人都必须重新注册。为了解决这个问题,需要使用本地数据库组件,来保存并提取广播列表中的数据。

这里将使用与“出题”应用(第10章)中相似的方案:

  • 每次添加新项时,将列表保存到数据库中;
  • 应用启动时,从数据库中加载列表,并保存到一个变量中。

用表11-7中所列出的块,将列表存储到数据库中。本地数据库组件中的参数数据标记作为数据的标识,将保存在数据库中的不同数据区分开来。在本例中,你可以将数据标记设为“广播列表”。在短信收发器1的收到消息事件中,将这些块放在添加列表项块之下。

表11-7 用本地数据库来存储广播列表所需要的块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

当应用收到短信“参加快闪舞蹈团”,并将新成员的手机号码添加到列表时,调用本地数据库1的保存数据功能,将广播列表保存到数据库中。标记(“广播列表”)的使用是数据存储的需要,也是之后从数据库提取数据的需要。如图11-9所示,保存数据块的另一个参数“数值”则是广播列表变量。

App Inventor编程教程-第12课-广播中心-少儿编程教育网图11-9 将广播列表保存到本地数据库中
从数据库中加载广播列表

每次应用启动时,从数据库中加载广播列表,表11-8中列出了实现这一功能需要的块。

表11-8 应用启动时加载广播列表所需要的块

App Inventor编程教程-第12课-广播中心-少儿编程教育网

应用的启动将触发Screen1的初始化事件,因此数据的加载要在该事件的处理程序中实现。

应用启动时,将触发Screen1的初始化事件。如图11-10所示,使用“让本地数据库1请求数据”块向数据库请求数据。

App Inventor编程教程-第12课-广播中心-少儿编程教育网图11-10 从数据库中加载广播列表
在使用本地数据库组件向数据库请求数据时,使用的标记参数与保存数据时的标记(广播列表)相同。一般情况下,将返回此前保存的电话号码列表,并将列表保存到全局变量广播列表中。不过,请求数据块还提供了另外一个参数插槽:“无标记返回”,用来定义当请求的标记不存在时的返回值。例如,当第一次启动应用时,在这种情况下,则返回一个空列表。

App Inventor编程教程-第12课-广播中心-少儿编程教育网测试:你可以使用实时测试功能,来测试那些涉及数据库更新的应用{![较早前的App Inventor版本,凡是涉及本地数据库更新的应用,都无法进行实时测试。因为每次连接测试设备时,都会清空数据库。——译者注]},但要小心操作。在这个例子中,使用其他手机向测试手机发送短信,将手机号码添加到广播列表中,然后重新启动应用。这里告诉你一个重新启动应用的方法:在设计视图中,随便修改某个组件的属性,如改变标签的字体等属性。不过要全面测试数据库应用,还需要将应用打包,下载并安装到手机上(点击“编译→显示二维码或下载到本地“)。在手机上启动应用,用其他手机发送短信加入群组,再退出应用。当重启应用时,如果那些电话号码还在,说明数据库部分工作正常。

完整的“广播中心”应用

图11-11中列出了“广播中心”应用中的全部代码块。

App Inventor编程教程-第12课-广播中心-少儿编程教育网图11-11 完整的“广播中心”应用

改进

在庆祝完成一个如此复杂的应用时,你也许还想做进一步的完善。举例如下。

  • 在广播短信环节,广播中心向所有人发出短信,也包括发送这条短信的列表成员。修改此功能,将短信群发给除了发送者之外的所有成员。
  • 允许列表成员退出群组,用手机发送短信“退出”给广播中心,请求从列表中删除自己。这项功能需要使用列表的删除指定项功能。
  • 管理人员可以在操作界面上添加或删除广播列表中的成员(手机号)。
  • 管理人员可以指定某些不允许加入列表的手机号。
  • 细化应用的功能,让任何人都可以加入列表并接收广播,但只有管理员可以广播消息。
  • 进一步细化应用,让任何人都可以加入列表并接收广播,但只有一个固定列表中的电话号码可以向全体成员广播消息。

小结

以下是本章涵盖的内容。

  • 应用不仅可以响应用户发起的事件,也可以响应非用户发起的事件,比如收到短信这样的事件。这意味着你可以开发这样的应用,应用的用户是其他手机的使用者。
  • 使用嵌套的“如果...则...否则”块以及遍历列表块,可以构造出复杂的逻辑。有关条件语句和循环语句的详细信息,请分别参见第18章及第20章。
  • 使用拼字串块可以创建一个由多项内容组成的文本对象。
  • 本地数据库组件可以用于数据库操作:存储及提取数据。最常用的方法是,在数据发生变化时,调用保存数据功能更新数据库;在应用启动时,调用请求数据功能从数据库中读取数据。