如何使用适用于 Azure 移动应用的 Apache Cordova 客户端库

概述

本指南介绍了如何使用最新的适用于 Azure 移动应用的 Apache Cordova 插件执行常见任务。 对于 Azure 移动应用的新手,请先完成 Azure 移动应用快速入门,创建后端、创建表并下载预先生成的 Apache Cordova 项目。 本指南侧重于客户端 Apache Cordova 插件。

受支持的平台

此 SDK 在 iOS、Android 和 Windows 设备上支持 Apache Cordova v6.0.0 及更高版本。 支持的平台如下:

  • Android API 19-24(KitKat 到 Nougat)。
  • iOS 8.0 及更高版本。
  • Windows Phone 8.1。
  • 通用 Windows 平台。

安装与先决条件

本指南假设已创建了包含表的后端。 本指南假设该表的架构与这些教程中的表相同。 本指南还假设已将 Apache Cordova 插件添加到代码。 如果尚未这样做,可以在命令行中将 Apache Cordova 插件添加到项目:

cordova plugin add cordova-plugin-ms-azure-mobile-apps

有关创建第一个 Apache Cordova 应用的详细信息,请参阅相关文档。

设置 Ionic v2 应用

要正确配置 Ionic v2 项目,请先创建基本应用,然后添加 Cordova 插件:

ionic start projectName --v2
cd projectName
ionic plugin add cordova-plugin-ms-azure-mobile-apps

将以下行添加到 app.component.ts 以创建客户端对象:

declare var WindowsAzure: any;
var client = new WindowsAzure.MobileServiceClient("https://yoursite.azurewebsites.net");

现在可以生成项目并在浏览器中运行项目:

ionic platform add browser
ionic run browser

Azure 移动应用 Cordova 插件同时支持 Ionic v1 和 Ionic v2 应用。 仅 Ionic v2 应用需要添加 WindowsAzure 对象的声明。

创建客户端连接

通过创建 WindowsAzure.MobileServiceClient 对象创建客户端连接。 将 appUrl 替换为到移动应用的 URL。

var client = WindowsAzure.MobileServiceClient(appUrl);

使用表

若要访问或更新数据,请创建到后端表的引用。 将 tableName 替换为表名称

var table = client.getTable(tableName);

拥有表格引用后,可进一步使用表格:

如何:查询表格引用

拥有表格引用后,可用其查询服务器上的数据。 查询使用了“类 LINQ”语言。 若要返回表中的所有数据,请使用以下代码:

/**
 * Process the results that are received by a call to table.read()
 *
 * @param {Object} results the results as a pseudo-array
 * @param {int} results.length the length of the results array
 * @param {Object} results[] the individual results
 */
function success(results) {
   var numItemsRead = results.length;

   for (var i = 0 ; i < results.length ; i++) {
       var row = results[i];
       // Each row is an object - the properties are the columns
   }
}

function failure(error) {
    throw new Error('Error loading data: ', error);
}

table
    .read()
    .then(success, failure);

随结果调用 success 函数。 请勿在 success 函数中使用 for (var i in results),因为这会在使用其他查询函数(如 .includeTotalCount())时迭代结果中所含的信息。

有关查询语法的详细信息,请参阅 [查询对象文档]。

在服务器上筛选数据

可在表格引用上使用 where 子句:

table
    .where({ userId: user.userId, complete: false })
    .read()
    .then(success, failure);

也可使用筛选对象的函数。 在这种情况下,this 变量将分配到正在筛选的当前对象。 以下代码在功能上等效于上述示例:

function filterByUserId(currentUserId) {
    return this.userId === currentUserId && this.complete === false;
}

table
    .where(filterByUserId, user.userId)
    .read()
    .then(success, failure);

分页浏览数据

利用 take()skip() 方法。 例如,如想要将表拆分为 100 行记录:

var totalCount = 0, pages = 0;

// Step 1 - get the total number of records
table.includeTotalCount().take(0).read(function (results) {
    totalCount = results.totalCount;
    pages = Math.floor(totalCount/100) + 1;
    loadPage(0);
}, failure);

function loadPage(pageNum) {
    let skip = pageNum * 100;
    table.skip(skip).take(100).read(function (results) {
        for (var i = 0 ; i < results.length ; i++) {
            var row = results[i];
            // Process each row
        }
    }
}

.includeTotalCount() 方法用于将 totalCount 字段添加到结果对象。 如果不分页,totalCount 字段会填充要返回的记录总数。

然后,可使用页变量和某些 UI 按钮提供页列表;使用 loadPage() 为每页加载新记录。 实施缓存,加快已加载的记录的访问速度。

如何:返回排序后的数据

使用 .orderBy().orderByDescending() 查询方法:

table
    .orderBy('name')
    .read()
    .then(success, failure);

有关查询对象的详细信息,请参阅 [查询对象文档]。

如何:插入数据

使用相应日期创建 JavaScript 对象并异步调用 table.insert()

var newItem = {
    name: 'My Name',
    signupDate: new Date()
};

table
    .insert(newItem)
    .done(function (insertedItem) {
        var id = insertedItem.id;
    }, failure);

成功插入后,插入项随同步操作所需的其他字段一并返回。 使用此信息更新自己的缓存,便于后续更新。

Azure 移动应用 Node.js Server SDK 支持用于开发的动态架构。 使用动态架构可将列添加到表中,在插入或更新操作中指定这些列即可。 建议先关闭动态架构,再将应用程序迁移到生产。

如何:修改数据

类似于 .insert() 方法,应创建 Update 对象,并调用 .update()。 update 对象必须包含要更新的记录的 ID,此 ID 在读取记录或调用 .insert() 时获取。

var updateItem = {
    id: '7163bc7a-70b2-4dde-98e9-8818969611bd',
    name: 'My New Name'
};

table
    .update(updateItem)
    .done(function (updatedItem) {
        // You can now update your cached copy
    }, failure);

如何:删除数据

若要删除记录,请调用 .del() 方法。 在对象引用中传递 ID:

table
    .del({ id: '7163bc7a-70b2-4dde-98e9-8818969611bd' })
    .done(function () {
        // Record is now deleted - update your cache
    }, failure);

如何对用户进行身份验证

Azure 应用服务支持使用各种外部标识提供者(例如 Facebook、Google、Microsoft 帐户和 Twitter)对应用的用户进行身份验证和授权。 可以在表中设置权限,以便将特定操作的访问权限限制给已经过身份验证的用户。 还可以在服务器脚本中使用已经过身份验证的用户的标识来实施授权规则。 有关详细信息,请参阅身份验证入门教程。

在 Apache Cordova 应用中使用身份验证时,以下 Cordova 插件必须可用:

支持两种身份验证流:服务器流和客户端流。 服务器流依赖于提供者的 Web 身份验证界面,因此可提供最简便的身份验证体验。 客户端流依赖于提供者和设备特定的 SDK,因此允许与设备特定的功能(例如单一登录)进行更深入的集成。

如何:使用提供程序(服务器流)进行身份验证

要让移动应用管理应用中的身份验证过程,必须将应用注册到标识提供者。 然后,需要在 Azure App Service 中配置提供者提供的应用程序 ID 和机密。 有关详细信息,请参阅向应用添加身份验证教程。

注册标识提供者后,请结合提供者的名称调用 .login() 方法。 例如,若要使用 Facebook 登录,请使用以下代码:

client.login("facebook").done(function (results) {
     alert("You are now signed in as: " + results.userId);
}, function (err) {
     alert("Error: " + err);
});

提供者的有效值为“aad”、“facebook”、“google”、“microsoftaccount”和“twitter”。

注意

目前无法通过服务器流执行 Google 身份验证。 若要使用 Google 进行身份验证,必须使用客户端流方法

在这种情况下,Azure 应用服务将管理 OAuth 2.0 身份验证流。 它显示所选提供者的登录页,并在使用标识提供者成功登录后生成应用服务身份验证令牌。 login 函数在完成时会返回一个 JSON 对象,该对象分别在 userId 和 authenticationToken 字段中公开用户 ID 和应用服务身份验证令牌。 可以缓存此令牌,并在它过期之前重复使用。

如何:使用提供程序(客户端流)进行身份验证

你的应用还能够独立联系标识提供者,并将返回的令牌提供给应用服务以进行身份验证。 使用此客户端流可为用户提供单一登录体验,或者从标识提供者中检索其他用户数据。

社交身份验证基本示例

此示例使用 Facebook 客户端 SDK 进行身份验证:

client.login(
     "facebook",
     {"access_token": token})
.done(function (results) {
     alert("You are now signed in as: " + results.userId);
}, function (err) {
     alert("Error: " + err);
});

此示例假定由相应的提供程序 SDK 提供的令牌存储在令牌变量中。

如何:获取已经过身份验证的用户相关信息

可以结合任何 AJAX 库使用 HTTP 调用,从 /.auth/me 终结点检索身份验证信息。 确保将 X-ZUMO-AUTH 标头设置为身份验证令牌。 身份验证令牌存储在 client.currentUser.mobileServiceAuthenticationToken 中。 例如,若要使用提取 API:

var url = client.applicationUrl + '/.auth/me';
var headers = new Headers();
headers.append('X-ZUMO-AUTH', client.currentUser.mobileServiceAuthenticationToken);
fetch(url, { headers: headers })
    .then(function (data) {
        return data.json()
    }).then(function (user) {
        // The user object contains the claims for the authenticated user
    });

提取的内容以 npm 包的形式提供,或者可以通过浏览器从 CDNJS 下载。 也可以使用 jQuery 或其他 AJAX API 提取信息。 数据作为 JSON 对象接收。

如何为外部重定向 URL 配置移动应用服务。

有多种类型的 Apache Cordova 应用程序使用环回功能来处理 OAuth UI 流。 localhost 上的 OAuth UI 流会造成问题,因为身份验证服务默认只知道如何利用服务。 有问题的 OAuth UI 流示例包括:

  • Ripple 模拟器。
  • 使用 Ionic 实时重新加载。
  • 在本地运行移动后端
  • 使用不同的 Azure 应用服务(不是提供身份验证的那一个)运行移动后端。

请遵循以下说明将本地设置添加到配置中:

  1. 登录到 Azure 门户

  2. 选择“所有资源”或“应用服务”,并单击移动应用的名称。

  3. 单击“工具”

  4. 在“观察”菜单中单击“资源浏览器”,并单击“转到”。 此时会打开一个新窗口或选项卡。

  5. 在左侧导航栏中,展开站点的“config”、“authsettings”节点。

  6. 单击“编辑”

  7. 查找“allowedExternalRedirectUrls”元素。 该元素可能已设置为 null 或值数组。 将该值更改为以下值:

      "allowedExternalRedirectUrls": [
          "https://localhost:3000",
          "https://localhost:3000"
      ],
    

    将 URL 替换为自己服务的 URL。 示例包括 https://localhost:3000(适用于 Node.js 示例服务)或 https://localhost:4400(适用于 Ripple 服务)。 但这是一些 URL 示例 - 根据不同的情况(包括示例中提到的服务)可能会有差异。

  8. 单击屏幕右上角的“读/写”按钮。

  9. 单击绿色的“PUT”按钮。

此时会保存设置。 在保存完设置之前,请不要关闭浏览器窗口。 还需要将以下环回 URL 添加到应用服务的 CORS 设置:

  1. 登录到 Azure 门户
  2. 选择“所有资源”或“应用服务”,并单击移动应用的名称。
  3. “设置”边栏选项卡随即自动打开。 如果没有打开,请单击“所有设置”
  4. 在“API”菜单下单击“CORS”
  5. 在提供的框中输入想要添加的 URL,并按 Enter。
  6. 根据需要输入其他 URL。
  7. 单击“保存” 保存这些设置。

大约需要 10-15 秒时间才能使新设置生效。

如何:注册推送通知

安装 phonegap-plugin-push 即可处理推送通知。 在命令行中使用 cordova plugin add 命令,或者在 Visual Studio 内通过 Git 插件安装程序,即可轻松添加此插件。 Apache Cordova 应用中的以下代码将为设备注册推送通知:

var pushOptions = {
    android: {
        senderId: '<from-gcm-console>'
    },
    ios: {
        alert: true,
        badge: true,
        sound: true
    },
    windows: {
    }
};
pushHandler = PushNotification.init(pushOptions);

pushHandler.on('registration', function (data) {
    registrationId = data.registrationId;
    // For cross-platform, you can use the device plugin to determine the device
    // Best is to use device.platform
    var name = 'gcm'; // For android - default
    if (device.platform.toLowerCase() === 'ios')
        name = 'apns';
    if (device.platform.toLowerCase().substring(0, 3) === 'win')
        name = 'wns';
    client.push.register(name, registrationId);
});

pushHandler.on('notification', function (data) {
    // data is an object and is whatever is sent by the PNS - check the format
    // for your particular PNS
});

pushHandler.on('error', function (error) {
    // Handle errors
});

使用通知中心 SDK 从服务器发送推送通知。 请勿直接从客户端发送推送通知。 否则可能会触发拒绝对通知中心或 PNS 的服务攻击。 遇到此类攻击时,PNS 会禁止流量。

更多信息

可以在 API 文档中找到详细的 API 详细信息。