如何使用适用于 Azure 移动应用的 Apache Cordova 客户端库How to use Apache Cordova client library for Azure Mobile Apps

Note

Visual Studio App Center 正在投资于对移动应用开发至关重要的新集成服务。Visual Studio App Center is investing in new and integrated services central to mobile app development. 开发人员可以使用生成测试分发服务来设置持续集成和交付管道。Developers can use Build, Test and Distribute services to set up Continuous Integration and Delivery pipeline. 部署应用后,开发人员可以使用分析诊断服务监视其应用的状态和使用情况,并使用推送服务与用户互动。Once the app is deployed, developers can monitor the status and usage of their app using the Analytics and Diagnostics services, and engage with users using the Push service. 开发人员还可以利用 Auth 对用户进行身份验证,利用数据服务在云中持久保存和同步应用数据。Developers can also leverage Auth to authenticate their users and Data service to persist and sync app data in the cloud. 立即查看 App CenterCheck out App Center today.

概述Overview

本指南介绍如何使用最新的 适用于 Azure 移动应用的 Apache Cordova 插件执行常见任务。This guide teaches you to perform common scenarios using the latest Apache Cordova Plugin for Azure Mobile Apps. 对于 Azure 移动应用的新手,请先完成 Azure 移动应用快速入门,创建后端、创建表并下载预先生成的 Apache Cordova 项目。If you are new to Azure Mobile Apps, first complete Azure Mobile Apps Quick Start to create a backend, create a table, and download a pre-built Apache Cordova project. 本指南侧重于客户端 Apache Cordova 插件。In this guide, we focus on the client-side Apache Cordova Plugin.

支持的平台Supported platforms

此 SDK 在 iOS、Android 和 Windows 设备上支持 Apache Cordova v6.0.0 和更高版本。This SDK supports Apache Cordova v6.0.0 and later on iOS, Android, and Windows devices. 平台支持如下所示:The platform support is as follows:

  • Android API 19-24(KitKat 到 Nougat)。Android API 19-24 (KitKat through Nougat).
  • iOS 8.0 和更高版本。iOS versions 8.0 and later.
  • Windows Phone 8.1。Windows Phone 8.1.
  • 通用 Windows 平台。Universal Windows Platform.

安装与先决条件Setup and prerequisites

本指南假设已创建了包含表的后端。This guide assumes that you have created a backend with a table. 本指南假设该表的架构与这些教程中的表相同。This guide assumes that the table has the same schema as the tables in those tutorials. 本指南还假设已将 Apache Cordova 插件添加到代码。This guide also assumes that you have added the Apache Cordova Plugin to your code. 如果尚未这样做,可以在命令行中将 Apache Cordova 插件添加到项目:If you have not done so, you may add the Apache Cordova plugin to your project on the command line:

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

有关创建 第一个 Apache Cordova 应用的详细信息,请参阅相关文档。For more information on creating your first Apache Cordova app, see their documentation.

设置 Ionic v2 应用Setting up an Ionic v2 app

若要正确配置 Ionic v2 项目,首先需创建一个基本应用,并添加 Cordova 插件:To properly configure an Ionic v2 project, first create a basic app and add the Cordova plugin:

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

app.component.ts 中添加以下行以创建客户端对象:Add the following lines to app.component.ts to create the client object:

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

现在可以在浏览器中生成并运行项目:You can now build and run the project in the browser:

ionic platform add browser
ionic run browser

Azure 移动应用 Cordova 插件同时支持 Ionic v1 和 v2 应用。The Azure Mobile Apps Cordova plugin supports both Ionic v1 and v2 apps. 只有 Ionic v2 应用需要额外的针对 WindowsAzure 对象的声明。Only the Ionic v2 apps require the additional declaration for the WindowsAzure object.

创建客户端连接Create a client connection

通过创建 WindowsAzure.MobileServiceClient 对象创建客户端连接。Create a client connection by creating a WindowsAzure.MobileServiceClient object. appUrl 替换为到移动应用的 URL。Replace appUrl with the URL to your Mobile App.

var client = WindowsAzure.MobileServiceClient(appUrl);

使用表Work with tables

若要访问或更新数据,请创建到后端表的引用。To access or update data, create a reference to the backend table. tableName 替换为表名称Replace tableName with the name of your table

var table = client.getTable(tableName);

拥有表格引用后,可进一步使用表格:Once you have a table reference, you can work further with your table:

如何:查询表格引用How to: Query a table reference

拥有表格引用后,可用其查询服务器上的数据。Once you have a table reference, you can use it to query for data on the server. 查询使用了“类 LINQ”语言。Queries are made in a "LINQ-like" language. 若要返回表中的所有数据,请使用以下代码:To return all data from the table, use the following code:

/**
 * 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 函数。The success function is called with the results. 请勿在 success 函数中使用 for (var i in results),因为这会在使用其他查询函数(如 .includeTotalCount())时循环访问结果中所含的信息。Do not use for (var i in results) in the success function as that will iterate over information that is included in the results when other query functions (such as .includeTotalCount()) are used.

有关查询语法的详细信息,请参阅 [查询对象文档]。For more information on the Query syntax, see the [Query object documentation].

在服务器上筛选数据Filtering data on the server

可在表格引用上使用 where 子句:You can use a where clause on the table reference:

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

也可使用筛选对象的函数。You can also use a function that filters the object. 该情况下, this 变量被分配给经过筛选的当前对象。In this case, the this variable is assigned to the current object being filtered. 以下代码在功能上等效于上个示例:The following code is functionally equivalent to the prior example:

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

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

分页浏览数据Paging through data

利用 take()skip() 方法。Utilize the take() and skip() methods. 例如,如想要将表拆分为 100 行记录:For example, if you wish to split the table into 100-row records:

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 字段添加到结果对象。The .includeTotalCount() method is used to add a totalCount field to the results object. 如果不分页,totalCount 字段会填充要返回的记录总数。The totalCount field is filled with the total number of records that would be returned if no paging is used.

然后可使用页变量和某些 UI 按钮提供页列表;使用 loadPage() 为每页加载新记录。You can then use the pages variable and some UI buttons to provide a page list; use loadPage() to load the new records for each page. 实现缓存以加快对已加载记录的访问速度。Implement caching to speed access to records that have already been loaded.

如何:返回排序后的数据How to: Return sorted data

使用 .orderBy().orderByDescending() 查询方法:Use the .orderBy() or .orderByDescending() query methods:

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

有关查询对象的详细信息,请参阅 [查询对象文档]。For more information on the Query object, see the [Query object documentation].

如何:插入数据How to: Insert data

使用相应日期创建 JavaScript 对象并异步调用 table.insert()Create a JavaScript object with the appropriate date and call table.insert() asynchronously:

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

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

成功插入后,插入项随同步操作所需的其他字段一并返回。On successful insertion, the inserted item is returned with the additional fields that are required for sync operations. 使用此信息更新自己的缓存,便于后续更新。Update your own cache with this information for later updates.

Azure 移动应用 Node.js Server SDK 支持用于开发的动态架构。The Azure Mobile Apps Node.js Server SDK supports dynamic schema for development purposes. 在动态架构中,可通过在插入或更新操作中指定列,以将这些列添加到表中。Dynamic Schema allows you to add columns to the table by specifying them in an insert or update operation. 建议先关闭动态架构,再将应用程序迁移到生产。We recommend that you turn off dynamic schema before moving your application to production.

如何:修改数据How to: Modify data

类似于 .insert() 方法,应创建 Update 对象,然后调用 .update()Similar to the .insert() method, you should create an Update object and then call .update(). Update 对象必须包含要更新的记录的 ID,此 ID 在读取记录或调用 .insert()时获取。The update object must contain the ID of the record to be updated - the ID is obtained when reading the record or when calling .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);

如何:删除数据How to: Delete data

若要删除记录,请调用 .del() 方法。To delete a record, call the .del() method. 在对象引用中传递 ID:Pass the ID in an object reference:

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

如何:对用户进行身份验证How to: Authenticate users

Azure 应用服务支持使用标识提供者对应用用户进行身份验证和授权:Microsoft 帐户。Azure App Service supports authenticating and authorizing app users using identity provider: Microsoft Account. 可以在表中设置权限,以便将特定操作的访问权限限制给已经过身份验证的用户。You can set permissions on tables to restrict access for specific operations to only authenticated users. 还可以在服务器脚本中使用已经过身份验证的用户的标识来实施授权规则。You can also use the identity of authenticated users to implement authorization rules in server scripts. 有关详细信息,请参阅身份验证入门教程。For more information, see the Get started with authentication tutorial.

在 Apache Cordova 应用中使用身份验证时,以下 Cordova 插件必须可用:When using authentication in an Apache Cordova app, the following Cordova plugins must be available:

支持两种身份验证流:服务器流和客户端流。Two authentication flows are supported: a server flow and a client flow. 服务器流依赖于提供者的 Web 身份验证界面,因此可提供最简便的身份验证体验。The server flow provides the simplest authentication experience, as it relies on the provider's web authentication interface. 客户端流依赖于提供者和设备特定的 SDK,因此允许与设备特定的功能(例如单一登录)进行更深入的集成。The client flow allows for deeper integration with device-specific capabilities such as single-sign-on as it relies on provider-specific device-specific SDKs.

如何:使用提供程序(服务器流)进行身份验证How to: Authenticate with a provider (Server Flow)

若要让移动应用管理应用中的身份验证过程,必须向标识提供者注册应用。To have Mobile Apps manage the authentication process in your app, you must register your app with your identity provider. 然后,需要在 Azure 应用服务中配置提供者提供的应用程序 ID 和机密。Then in your Azure App Service, you need to configure the application ID and secret provided by your provider. 有关详细信息,请参阅 向应用程序添加身份验证教程。For more information, see the tutorial Add authentication to your app.

注册标识提供者后,使用提供者的名称调用 .login() 方法。Once you have registered your identity provider, call the .login() method with the name of your provider. 例如,若要使用 Facebook 登录,请使用以下代码:For example, to sign in with Facebook use the following code:

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

提供者的有效值为“aad”和“microsoftaccount”。The valid values for the provider are 'aad' and 'microsoftaccount'.

在这种情况下,由 Azure 应用服务管理 OAuth 2.0 身份验证流程。In this case, Azure App Service manages the OAuth 2.0 authentication flow. 它显示所选提供者的登录页,并在使用标识提供者成功登录后生成应用服务身份验证令牌。It displays the sign-in page of the selected provider and generates an App Service authentication token after successful sign-in with the identity provider. login 函数在完成时返回一个 JSON 对象,该对象分别在 userId 和 authenticationToken 字段中公开用户 ID 和应用服务身份验证令牌。The login function, when complete, returns a JSON object that exposes both the user ID and App Service authentication token in the userId and authenticationToken fields, respectively. 可以缓存此令牌,并在它过期之前重复使用。This token can be cached and reused until it expires.

如何:使用提供程序(客户端流)进行身份验证How to: Authenticate with a provider (Client Flow)

用户的应用还能够独立联系标识提供者,并将返回的令牌提供给应用服务以进行身份验证。Your app can also independently contact the identity provider and then provide the returned token to your App Service for authentication. 使用此客户端流可为用户提供单一登录体验,或者从标识提供者中检索其他用户数据。This client flow enables you to provide a single sign-in experience for users or to retrieve additional user data from the identity provider.

社交身份验证基本示例Social Authentication basic example

此示例使用 Facebook 客户端 SDK 进行身份验证:This example uses Facebook client SDK for authentication:

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

此示例假定由相应的提供程序 SDK 提供的令牌存储在令牌变量中。This example assumes that the token provided by the respective provider SDK is stored in the token variable.

如何:获取已经过身份验证的用户的相关信息How to: Obtain information about the authenticated user

可以结合任何 AJAX 库使用 HTTP 调用,从 /.auth/me 终结点检索身份验证信息。The authentication information can be retrieved from the /.auth/me endpoint using an HTTP call with any AJAX library. 确保将 X-ZUMO-AUTH 标头设置为身份验证令牌。Ensure you set the X-ZUMO-AUTH header to your authentication token. 身份验证令牌存储在 client.currentUser.mobileServiceAuthenticationToken中。The authentication token is stored in client.currentUser.mobileServiceAuthenticationToken. 例如,若要使用提取 API:For example, to use the fetch 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 下载。Fetch is available as an npm package or for browser download from CDNJS. 也可以使用 jQuery 或其他 AJAX API 提取信息。You could also use jQuery or another AJAX API to fetch the information. 数据作为 JSON 对象接收。Data is received as a JSON object.

如何:为外部重定向 URL 配置移动应用服务。How to: Configure your Mobile App Service for external redirect URLs.

有多种类型的 Apache Cordova 应用程序使用环回功能来处理 OAuth UI 流。Several types of Apache Cordova applications use a loopback capability to handle OAuth UI flows. Localhost 上的 OAuth UI 流会导致问题,因为默认情况下,身份验证服务只知道如何利用服务。OAuth UI flows on localhost cause problems since the authentication service only knows how to utilize your service by default. 有问题的 OAuth UI 流的示例包括:Examples of problematic OAuth UI flows include:

  • Ripple 模拟器。The Ripple emulator.
  • 使用 Ionic 的实时重新加载。Live Reload with Ionic.
  • 在本地运行移动后端Running the mobile backend locally
  • 在提供身份验证服务以外的其他 Azure 应用服务中运行移动后端。Running the mobile backend in a different Azure App Service than the one providing authentication.

请遵循以下说明将本地设置添加到配置中:Follow these instructions to add your local settings to the configuration:

  1. 登录到 Azure 门户Log in to the Azure portal

  2. 选择“所有资源” 或“应用服务” ,然后单击移动应用的名称。Select All resources or App Services then click the name of your Mobile App.

  3. 单击“工具” Click Tools

  4. 在“观察”菜单中单击“资源浏览器” ,然后单击“转到” 。Click Resource explorer in the OBSERVE menu, then click Go. 会打开新窗口或选项卡。A new window or tab opens.

  5. 在左侧导航栏中,展开站点的“config” 、“authsettings” 节点。Expand the config, authsettings nodes for your site in the left-hand navigation.

  6. 单击“编辑” Click Edit

  7. 查找“allowedExternalRedirectUrls”元素。Look for the "allowedExternalRedirectUrls" element. 该元素可能已设置为 null 或值数组。It may be set to null or an array of values. 将该值更改为以下值:Change the value to the following value:

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

    将 URL 替换为自己服务的 URL。Replace the URLs with the URLs of your service. 示例包括 http://localhost:3000(适用于 Node.js 示例服务)或 http://localhost:4400(适用于 Ripple 服务)。Examples include http://localhost:3000 (for the Node.js sample service), or http://localhost:4400 (for the Ripple service). 但是,这些 URL 是示例,根据不同的情况(包括示例中提到的服务)可能会有差异。However, these URLs are examples - your situation, including for the services mentioned in the examples, may be different.

  8. 单击屏幕右上角的“读/写” 按钮。Click the Read/Write button in the top-right corner of the screen.

  9. 单击绿色的“PUT” 按钮。Click the green PUT button.

此时会保存设置。The settings are saved at this point. 在保存完设置之前,请不要关闭浏览器窗口。Do not close the browser window until the settings have finished saving. 同时将以下环回 URL 添加到应用服务的 CORS 设置:Also add these loopback URLs to the CORS settings for your App Service:

  1. 登录到 Azure 门户Log in to the Azure portal
  2. 选择“所有资源” 或“应用服务” ,然后单击移动应用的名称。Select All resources or App Services then click the name of your Mobile App.
  3. “设置”边栏选项卡随即自动打开。The Settings blade opens automatically. 如果没有打开,请单击“所有设置” 。If it doesn't, click All Settings.
  4. 在“API”菜单下面单击“CORS” 。Click CORS under the API menu.
  5. 在提供的框中输入想要添加的 URL,并按 Enter。Enter the URL that you wish to add in the box provided and press Enter.
  6. 根据需要输入其他 URL。Enter additional URLs as needed.
  7. 单击“保存” 保存这些设置。Click Save to save the settings.

大约需要 10-15 秒时间才能使新设置生效。It takes approximately 10-15 seconds for the new settings to take effect.

如何:注册推送通知How to: Register for push notifications

安装 phonegap-plugin-push 即可处理推送通知。Install the phonegap-plugin-push to handle push notifications. 在命令行中使用 cordova plugin add 命令,或者在 Visual Studio 内通过 Git 插件安装程序,即可轻松添加此插件。This plugin can be easily added using the cordova plugin add command on the command line, or via the Git plugin installer within Visual Studio. Apache Cordova 应用中的以下代码为设备注册推送通知:The following code in your Apache Cordova app registers your device for push notifications:

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 从服务器发送推送通知。Use the Notification Hubs SDK to send push notifications from the server. 永远不要直接从客户端发送推送通知。Never send push notifications directly from clients. 此做法可能会被用于触发针对通知中心或 PNS 的拒绝服务攻击。Doing so could be used to trigger a denial of service attack against Notification Hubs or the PNS. PNS 可能会因此类攻击而禁止相关流量。The PNS could ban your traffic as a result of such attacks.

详细信息More information

可在 API 文档中找到有关 API 的详细信息。You can find detailed API details in our API documentation.