使用在 IBM 云上托管的 Twilio 服务构建一个移动应用程序。这个由多个部分组成的文章系列将逐步构建一个应用程序,每个部分都将向您介绍一些新的服务。本文包括一个演示、样例代码,以及创建 BlueList Android 或 iOS 应用程序的完整说明。您可以应用所学到的知识,将 MobileData 和 Twilio 集成到自己的应用程序中。
您可能已经了解 Bluemix 的一些优势,Bluemix 是 IBM 用于开发和部署移动应用程序和 Web 应用程序的开放式平台。BlueMix 中的许多预构建服务使得构建和增强应用程序变得很简单。
在本文中,我们将使用 Bluemix 服务,利用 Twilio 服务扩展一个名称为 BlueList 的 Android 或 iOS 应用程序。本系列中的其他文章 向您展示如何将更多基于云的服务添加到应用程序。该 BlueList 应用程序是一个使用 Bluemix 服务的简单移动应用程序。利用 Bluemix 上的免费服务,您可以立刻开始编写并扩展自己的应用程序。
在以前的文章 "使用 MobileData 云服务构建一个 Android 应用程序" 和 "使用 MobileData 云服务构建一个 iOS 应用" 中,我们添加了 MobileData 服务,列表中的项将会持久保存。在本文中,我们将向 BlueList 应用程序添加 Twilio 服务,因此,当其中一台设备以某种方式更新列表时,会发送通知,然后所有设备上的列表都被更新。
“利用 Bluemix 上的免费服务,您可以立刻开始编写并扩展自己的应用程序。”
获取代码
如果您跳过了本系列 前面的文章,那么您可以从 bluelist-mobiledata 代码开始,但需要先执行下面的 追赶进度 任务,然后再添加 Twilio 服务。如果已经完成了前面文章的阅读,那么您可以从现有的代码开始,按照下面的步骤添加 Twilio 服务。
为了加快进度,您可以下载 bluelist-twilio(TW)代码,您需要执行一些步骤来让具有 MobileData 和 Twilio 服务的 BlueList 应用程序正常工作。bluelist-twilio(TW)代码包含本文中对 bluelist-mobiledata 代码所做的更改。
应用程序的先决条件
- 熟悉上面提到的本系列的前面的文章,在这些文章中,我们已将 MobileData 服务添加到移动应用程序。该应用程序是本文的起点。
- 对于 Android:应当熟悉 Android 开发和一种 Android 开发环境。我们使用了 Eclipse with ADT,但您可以随意使用自己的首选环境。
- 对于 iOS:应当熟悉 iOS 开发 和一种 iOS 开发环境。
- 熟悉 git,以便下载 bluelist-mobiledata 和 bluelist-twilio Mobile Cloud 样本。
- bluelist-mobiledata 代码(上面的)或来自本系列中 前面的文章 中的现有代码。
- 需要用于 Twilio Node.js 应用程序服务器端代码的 bluelist-twilio 代码(上面的)与 Twilio 服务接口
- 一个 Twilio 帐户,包括与之有关联的 Account SID、Auth 令牌、Twilio 电话号码,以及一个语音/文本验证的电话号码。了解如何在 Twilio.com 获得该帐户,或者如何按照我们的指示进行操作。
- 熟悉 cf 命令行工具,该工具用于推送您的 Bluemix 应用程序的 Twilio Node.js 服务器端代码。
限制
本文基于 Twilio 的免费试用版 安装和 REST API。对于该试用版,有一些限制:
- SMS 消息会被加上前缀字符串 "Sent from a Twilio trial account"。
- SMS 消息必须发送到一个经过验证的电话号码,如以下消息所示:
追赶进度的任务(Android)
如果您跳过了本系列中以前的文章,请尽量追赶上进度:
- 如果还没有这样做,请下载 bluelist-mobiledata code 将 bluelist-mobiledata-android 项目导入您的 Android 开发环境。一旦完成剩下的追赶步骤,就可以将导入项目后看到的所有编译错误都纠正过来。
- 转到本系列前面的文章中的 步骤 1. 在 Bluemix 上创建一个 Mobile Cloud 应用程序,并执行步骤 1.1-1.10。这些步骤将指导您完成:
- 在 Bluemix 上登录并创建名为 BlueList 的应用程序
- 下载 Android SDK
- 用您的 BlueList 应用程序值更新
bluelist.properties
文件 - 将 JAR 文件添加到您的
libs
目录
- 保存您的 Bluemix 应用程序名称。您稍后需要使用此应用程序名称。
- 一旦完成这些步骤,您就可以在自己的模拟器或设备上运行该代码,以便验证您的 Android 开发环境已得到正确设置,然后再添加 Twilio 服务。现在,您应该可以执行前面文章中的步骤 7 和步骤 8。
如果应用程序能够成功运行,那么您已经追上了进度,并准备好添加 Twilio 和服务器端的云服务。
追赶进度的任务(iOS)
如果您跳过了本系列中以前的文章,请尽量追赶上进度:
- 如果还没有这样做,那么请下载 bluelist-mobiledata 将 bluelist-mobiledata-iOS 项目导入您的 iOS 开发环境。
- 转到本系列前面的文章中的 步骤 1. 在 Bluemix 上创建一个 Mobile Cloud 应用程序,并执行步骤 1.1–1.6 和步骤 2.1-2.7。这些步骤将指导您完成:
- 在 Bluemix 上登录并创建名为 BlueList 的应用程序
- 下载 iOS SDK
- 用您的 BlueList 应用程序值更新
bluelist.plist
文件 - 将 JAR 文件添加到您的
libs
目录
- 保存您的 Bluemix 应用程序名称。您稍后需要使用此应用程序名称。
- 一旦完成这些步骤,您就可以在自己的模拟器或设备上运行该代码,以便验证您的 Android 开发环境已得到正确设置,然后再添加 Twilio 服务。现在,您就可以执行前面文章中的步骤 6 和步骤 7 了。
如果应用程序能够成功运行,那么您就已经追赶上了进度,并准备好添加 Twilio 和服务器端的云服务。
建立您的 Twilio 帐户
在开始之前,先建立您的 Twilio 帐户:
- 转到 Twilio 并注册一个免费的试用帐户。
- 输入所需信息(姓名、电子邮件和密码),然后单击 Get Started。
- 输入有效的(真实的)电话号码,让 Twilio 可以验证您是人类,并完成验证。
备注:该号码也将是您的 BlueList 购物清单应用程序发送短信的号码。
- 一旦完成验证,您就会分配到一个 Twilio 电话号码。您可以选择接受所分配的电话号码,或选择自己的电话号码。保存您的 Twilio 电话号码,因为您很快就会再次用到它。
- 完成帐户的设置。单击 DASHBOARD 页面,您会看到自己的 ACCOUNT SID 和 AUTH TOKEN。保存这些值;稍后需要使用它们。复制/粘贴 TOKEN, 单击锁图标,如下图所示。
利用 Twilio 扩展您的 BlueList 应用程序
步骤 1. 在 Bluemix 中将 Twilio 服务添加到您的应用程序
- 登录到 Bluemix。
- 假设您已经完成了 前面的文章 中的步骤,或上述 追赶进度的 步骤,在 DASHBOARD 视图中单击您的应用程序。
- 单击 ADD A SERVICE 并将 Twilio 服务添加到您的应用程序。
- 您会看到系统提示,要求您输入 Twilio 的 Account SID 和 Auth Token。从 Select an application 下拉菜单中选择您的应用程序,然后(复制/粘贴)之前保存的 Twilio 值,单击 CREATE。备注:新的 Twilio 服务将被分配一个名称(比如,Twilio-XX),但您可以把它改成自己喜欢的任何名称。在本例中,Twilio 服务名称是 “Twilio”。
- 保存 Twilio 服务名称;在编辑 Node.js 应用程序代码时会用到它。
- 您的应用程序需要重新启动。单击 OK 重新启动您的 BlueList 应用程序。
- 现在,当查看 Bluemix 仪表盘时,应该可以看到新的 Twilio 服务已被添加到您的 BlueList 应用程序。
- 单击 BlueList 应用程序,访问其概述页面。
- 单击 Runtime 链接查看 BlueList Node.js 运行时的详细信息。
- 滚动到 Environment Variables 部分和 VCAP_SERVICES 选项卡。
- 检查 JSON 代码的
"user-provided"
部分。这一部分是在将 Twilio 服务添加到应用程序时创建的。我们能够使用 VCAP_SERVICES 变量在我们的 Node.js 运行时代码中动态检索 TwilioaccountSID
和authToken
值。利用我们的服务器端代码中的ibmconfig
模块,我们能够访问这些 Bluemix 应用程序的环境变量。
步骤 2. 让自己熟悉服务器端 Node.js Twilio 代码
- 如果不熟悉这些代码的话,请使用 git 从 IBM DevOps Services 下载 Twilio 的 Node.js 应用程序代码。Node.js 代码在 bluelist-twilio-node 子文件夹中。
- 仔细查看
<gitRepository>/bluelist-twilio/bluelist-twilio-node
目录中的代码(其是 app.js 文件)并让自己熟悉代码。 - 该 app.js 文件需要执行一些更新,我们现在将介绍相关的步骤。在编辑器中打开 app.js,并进行以下更新:
- 用应用程序的值替换
applicationId
和applicationRoute
值占位符。在您的应用程序的 Bluemix 概述页面上可以找到这些值。 - 更新
toPhone
和fromPhone
值占位符。用短信发送的目标电话号码替换toPhone
号码,并使用所分配的 Twilio 电话号码替换fromPhone
号码。//change these to your Bluemix application values var appConfig = { applicationId:"<INSERT_APPLICATION_ID_HERE>", applicationRoute:"<INSERT_APPLICATION_ROUTE_HERE>" }; //change these to your Twilio values var twilioConfig = { twilioServiceName:"<INSERT_TWILIO_SERVICE_NAME>", toPhone:"+15551234567", fromPhone:"+15557654321" };
- 用应用程序的值替换
- 编辑 manifest.yml 文件。更新
host:
和name:
值,使之与您的 Bluemix 应用程序名称相匹配。host: my_bluemix_app_name disk:1024M name: my_bluemix_app_name command: node app.js path:. domain: mybluemix.net mem:128M instances:1
- 保存更改并准备使用 Cloud Foundry 命令行界面 (cf) 将您的代码向上推送到 Bluemix。
- 打开命令提示符并导航到您的 Twilio Node.js 应用程序所在的位置。例如:
cd <gitRepository>/bluelist-twilio-node/bluelist_twilio
。 列出目录内容,确保能够看到您的 app.js,manifest.yml 和 package.json 文件(以及其他文件)。 - 发出以下命令,验证已正确安装 cf:
cf –version
- 此命令的结果应该显示已经在您的计算机上安装的 cf 版本。例如:
cf version 6.0.1-9df4861
- 使用下面的命令登录 Bluemix:
cf login -a https://api.ng.bluemix.net
- 将新的应用程序代码向上推送(上传)到 Bluemix Node.js 运行时,运行以下命令,用您的应用程序的名称替换
${yourBlueList}
:cf push ${yourBlueList} -p .-m 512M
- 确认
push
命令是成功的,而且新的 Twilio Node.js 应用程序正在 Bluemix 上运行。
步骤 3 (Android). 修改客户端代码
假设您已经完成了 前面文章 中的步骤或上述 追赶进度的 步骤,我们将开始修改客户端 Android 项目的代码,使之达到 TW 的水平,并能够与您刚刚设置的 Twilio Node.js 运行时进行交互。
- 打开您的 Android 开发环境来执行必要的代码更改。
- 要使用服务器端的云代码,则需要使用另一个 Android SDK JAR 文件。导航到 Android SDK,在前面的文章中,或在 追赶进度的 步骤中进行解压缩,并将 ibmcloudcode.jar 复制到您的 libs 文件夹。您的 libs 目录现在看起来应该如下图所示。
- 编辑您的 assets 文件夹中的 bluelist.properties 文件。如果尚未完成此任务,请使用您的 Bluemix 应用程序 ID 更新
applicationID
值。将两个新的属性值添加到文件:applicationNAME
和twilioTextMessage
。applicationNAME
应该与您的 Bluemix 应用程序名称相匹配;twilioTextMessage
是 Twilio 将向您的手机发送的消息文本。applicationID=<INSERT_APPLICATION_ID_HERE> applicationSecret=<INSERT_APPLICATION_SECRET_HERE> applicationRoute=<INSERT_APPLICATION_ROUTE_HERE> # Text preceding grocery list (keep < 30 chars to allow room for list items) twilioTextMessage=Pick up groceries:
- 编辑 BlueListApplication.java 文件,并准备执行一些修改。
- 创建一个新的
Activity
变量来追踪购物清单活动状态。publicfinalclass BlueListApplication extends Application { private Activity mActivity; publicstaticfinalintEDIT_ACTIVITY_RC = 1; privatestaticfinal String CLASS_NAME = BlueListApplication.class.getSimpleName(); privatestaticfinal String APP_ID = "applicationID"; privatestaticfinal String PROPS_FILE = "bluelist.properties"; List<Item> itemList;
- 在四个
ActivityLifecycleCallbacks
中跟踪活动状态(创建、已启动、已恢复和暂停)。 - 修改 Bluemix 初始化调用。
// initialize the IBM core backend-as-a-service IBMBluemix.initialize(this, props.getProperty(APP_ID), props.getProperty(APP_SECRET), props.getProperty(APP_ROUTE));
- 将您的修改保存到 BlueListApplication.java。您此时可能仍会看到一些告警,在您继续执行代码更新之前,应该解决这些告警。
- 编辑 MainActivity.java 文件,并准备执行一些修改。
- 定义一些新的变量来检索 bluelist.properties 文件中的信息。
/* Define values found in properties file */ private static final String TWILIO_TEXT_MSG = "twilioTextMessage"; private static final String PROPS_FILE = "bluelist.properties"; private static String twilioTextMessage;
- 在执行
/* refresh the list */
命令(在onCreate
中)之后,添加一些代码,以便读取 bluelist.properties 文件。/* refresh the list */ listItems(); /* get text message from properties file */ Properties props = new java.util.Properties(); Context context = getApplicationContext(); try { AssetManager assetManager = context.getAssets(); props.load(assetManager.open(PROPS_FILE)); Log.i(CLASS_NAME, "Found configuration file:" + PROPS_FILE); } catch (FileNotFoundException e) { Log.e(CLASS_NAME, "The bluelist.properties file was not found.", e); } catch (IOException e) { Log.e(CLASS_NAME, "The bluelist.properties file could not be read properly.", e); } Log.i(CLASS_NAME, "Twilio Text Message to send is:" + props.getProperty(TWILIO_TEXT_MSG)); twilioTextMessage = props.getProperty(TWILIO_TEXT_MSG);
- 添加一个新的方法,
updateOtherDevices()
,以便调用我们的服务器端云模块。请注意,在 bluelist.properties 文件中定义的twilioTextMessage
是通过POST
请求上的JSONObject
进行传递的。private void updateOtherDevices() { // initialize and retrieve an instance of the IBM CloudCode service IBMCloudCode.initializeService(); IBMCloudCode myCloudCodeService = IBMCloudCode.getService(); JSONObject jsonObj = new JSONObject(); try { jsonObj.put("text", twilioTextMessage); } catch (JSONException e) { e.printStackTrace(); } // Call the node.js application hosted in the IBM Cloud Code service // with a POST call, passing in a non-essential JSONObject // The URI is relative to, appended to, the Bluemix context root myCloudCodeService.post("notifyOtherDevices", jsonObj); }
- 现在,我们只需将调用添加到
updateOtherDevices
。在编辑、创建新的项目,或者删除现有项目时添加调用。- 编辑代码
public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (resultCode) { /* if an edit has been made, notify that the data set has changed.*/ case BlueListApplication.EDIT_ACTIVITY_RC: updateOtherDevices(); sortItems(itemList); lvArrayAdapter.notifyDataSetChanged(); break; } }
- 创建代码
- 删除代码
- 编辑代码
- 将您的修改保存到
MainActivity
。 - 现在所有的代码修改都已完成。不要忘记使用 Eclipse 来组织导入 (Ctrl+Shift+O)。这会自动从之前复制到项目中的 SDK JAR 文件导入所有必需的元素。如果由于缺少导入语句而仍然有一些编译错误,请确保已将下面的导入内容添加到 MainActivity.java。
import java.util.Properties; import org.json.JSONException; import org.json.JSONObject; import bolts.Continuation; import bolts.Task; import com.ibm.mobile.services.cloudcode.IBMCloudCode; import com.ibm.mobile.services.data.IBMDataException; import com.ibm.mobile.services.data.IBMDataObject; import com.ibm.mobile.services.data.IBMQuery;
步骤 3 (iOS). 修改客户端代码
假设您已经完成了 前面文章 中的步骤或上述 追赶进度的 步骤,我们将开始修改客户端 Android 项目的代码,使之达到 TW 的水平,并能够与您刚刚设置的 Twilio Node.js 运行时进行交互。
- 打开您的 iOS 开发环境,执行必要的代码更改。
- 要使用服务器端的云代码,则需要使用另一个 iOS SDK JAR 文件。在 Finder 中,找到 iOS SDK,在前面的文章中,或在 追赶进度的 步骤中进行解压缩,并将 IBMCloudCode 框架拖动到 Frameworks 文件夹下的 BlueList Xcode 项目中。
- 编辑您的 Supporting Files 文件夹中的 bluelist.plist 文件。如果尚未完成此任务,请使用您的 Bluemix 应用程序值来更新
applicationId
、applicationSecret
和applicationRoute
值。将一个新的属性值添加到文件:twilioTextMessage
。twilioTextMessage
是 Twilio 将要发送到您的手机的消息文本。 - 打开 IBM_AppDelegate.m 并添加对使用 Cloud 代码的支持。添加一个新的
#import
语句和IBM_AppDelegate()
接口,并初始化 IBMCloudCode 服务。在完成现有 IBMData 初始化后立即添加 IBMCloudCode 初始化。#import "IBM_AppDelegate.h" #import <IBMBluemix/IBMBluemix.h> #import <IBMData/IBMData.h> #import <IBMCloudCode/IBMCloudCode.h> @interface IBM_AppDelegate () @end @implementation IBM_AppDelegate ... if(hasValidConfiguration){ // Initialize the SDK and BlueMix services [IBMBluemix initializeWithApplicationId:applicationId andApplicationSecret:applicationSecret andApplicationRoute:applicationRoute]; [IBMData initializeService]; [IBMCloudCode initializeService]; }else{ [NSException raise:@"InvalidApplicationConfiguration" format:@"%@", errorMessage] }
- 将您的修改保存到 IBM_AppDelegate.m。
- 打开 IBM_ListViewController.m 进行多项代码修改。为 IBMCloudCode 添加一个新的
#import
语句,并添加一些新的属性来引用 IBMCloudCode 服务和 Twilio 文本消息。#import "IBM_ListViewController.h" #import "IBM_CreateEditItemViewController.h" #import "IBM_Item.h" #import <IBMCloudCode/IBMCloudCode.h> ... // If edit was triggered, the cell being edited. @property UITableViewCell *editedCell; @property IBMCloudCode *cloudCodeService; @property NSDictionary *jsonDict; @property NSString *twilioText; @property NSData *jsonData;
- 添加代码来初始化 IBMCloudCode 服务,然后从 bluelist.plist 文件中读取 Twilio 文本消息。
- 更新
createItem
、updateItem
和deleteItem
方法,以便调用我们的服务器端的云模块。请注意,在 bluelist.plist 文件中定义的twilioTextMessage
是通过POST
请求上的 JSON 对象进行传递的。还要注意的是,我们正在利用 Bolts 链来调用云代码。- (void) createItem:(IBM_Item*) item { [self.itemList addObject: item]; [self reloadLocalTableData]; //save the new item and then notify other devices via cloud code for twilio notifications [[[item save] continueWithSuccessBlock:^id(BFTask *task) { return [self.cloudCodeService post:@"notifyOtherDevices" withJsonPayload: self.jsonDict]; }] continueWithBlock:^id(BFTask *task) { if(task.error) { NSLog(@"createItem failed with error:%@", task.error); } return nil; }]; } - (void) updateItem:(IBM_Item*) item { self.editedCell.textLabel.text = item.name; //save the updated item and then notify other devices via cloud code for twilio notifications [[[item save] continueWithSuccessBlock:^id(BFTask *task) { NSLog(@"in continueWithSuccessBlock"); return [self.cloudCodeService post:@"notifyOtherDevices" withJsonPayload: self.jsonDict]; }] continueWithBlock:^id(BFTask *task) { NSLog(@"in continueWithBlock"); if(task.error) { NSLog(@"updateItem failed with error:%@", task.error); } return nil; }]; } -(void) deleteItem:(IBM_Item*) item { [self.itemList removeObject: item]; [self reloadLocalTableData]; //delete the item and then notify other devices via cloud code for twilio notifications [[[item delete] continueWithSuccessBlock:^id(BFTask *task) { return [self.cloudCodeService post:@"notifyOtherDevices" withJsonPayload: self.jsonDict]; }] continueWithBlock:^id(BFTask *task) { if(task.error) { NSLog(@"deleteItem failed with error:%@", task.error); } return nil; }]; // Exit edit mode to avoid need to click Done button [self.tableView setEditing:NO animated:YES]; }
- 将您的修改保存到 IBM_ListViewController.m。
- 现在所有的代码修改都已完成。
步骤 4. 运行应用程序
现在我们已经完成了代码更改,您的代码应该相当于 bluelist-twilio 版本。为了验证一切都正常:
- 在您的模拟器中运行更新后的代码。
- 添加一些其他列表项。
- 在更新购物清单时,检查您的手机(在
app.js
代码中输入为toPhone:
号码的那台手机)上的 Twilio 文本消息。
结束语
到此为止,您已经完成了所有操作。通过使用 Bluemix 中提供的 Twilio 服务来扩展这个移动应用程序,您应该了解到使用移动云服务来使用和集成移动数据功能是多么容易。