更新记录

1.1.0(2026-09-14) 下载此版本

  • RN Android 的模块调用与 Activity 生命周期统一在主线程管理;关闭中的控制器保留真实忙碌状态。
  • iOS 自动读取的 NDEF 查询与读取回调核对实际会话,忽略旧会话的迟到回调。
  • Android 将连接关闭移到独立线程,等待 I/O 退出及最终关闭后释放占用,并处理过期标签引起的关闭异常。
  • Android 深度读取在切换标签技术前完成 NDEF 关闭;切换期间取消或关闭失败时不进入后续探测。
  • Android 读取与初始化判断仅使用实时 NDEF 消息,空消息不再回退到发现时缓存。
  • 会话关闭异常迟延时,有界交付待处理结果;实际资源释放前仍保持忙碌,不自动重放写入。
  • RN、UNI legacy、UTS 和 x 提供 waitForIdle(),等待上限为 5 秒(可配置),查询失败或超时不会伪装为空闲。
  • 增加关闭阻塞、迟到结果、取消/超时、写后移开标签和 Android 平台 NDEF 编码交叉验证。
  • 补充标签技术互斥、iOS 生产读取链路的迟到回调,以及 RN 主队列与宿主生命周期交错的运行测试。

平台兼容性

uni-app(5.24)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Safari app-vue app-vue插件版本 app-nvue Android Android插件版本 iOS iOS插件版本 鸿蒙
1.1.0 1.1.0 × × 1.1.0 × 6.0 1.1.0 15 1.1.0 ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

uni-app x(5.24)

Chrome Safari Android Android插件版本 iOS iOS插件版本 鸿蒙 微信小程序
× × 6.0 1.1.0 15 1.1.0 × ×

其他

多语言 暗黑模式 宽屏模式
× ×

Sfiora 通用 NFC 读写

Sfiora 为经典 uni-app 和 uni-app x 的 Android/iOS App 提供 NFC 标签读取、NDEF 消息写入与回读验证,以及按标记保留或初始化。读写内容由应用决定,可使用文本、URI、MIME 或 NFC Forum External Type 记录。

兼容范围与版本选择

接入方式 页面与运行环境 最低系统
经典 uni-app legacy Vue 2 / Vue 3 的 App Vue 页面,原生插件 Android API 21 / iOS 13
经典 uni-app UTS Vue 2 / Vue 3 的 App Vue 页面,uni_modules Android API 21 / iOS 13
uni-app x Vapor,uni_modules Android API 23 / iOS 15

使用 HBuilderX 5.24 或更新版本,并满足所用 HBuilderX、宿主框架和打包工具的系统要求。UTS 市场兼容表对 classic/x 使用共同最低声明 Android API 23 / iOS 15;经典 uni-app 的插件原生配置最低为 API 21 / iOS 13。

NFC 操作需要支持 NFC 的真机。本文的 uni-app x 示例面向 Vapor;Android VDOM 的直接 UTS 入口见下方单独说明。不支持 H5、小程序、nvue 或 HarmonyOS,也不能仅靠标准基座或热更新添加原生 NFC 能力。

各渠道已上架的版本以渠道页面为准;离线包和版本历史见 GitHub Releases。同一个 App 只安装一种 Sfiora 插件形态。

安装与导入

UTS:经典 uni-app 与 uni-app x

通过 DCloud 插件市场导入 Sandrox-Sfiora,或者下载对应发行版的 UTS ZIP。将 ZIP 内的文件解压到 uni_modules/Sandrox-Sfiora,确认 package.json 直接位于该目录中,避免再嵌套一层同名目录。

两种宿主都使用下面的公共 JavaScript SDK:

import * as sfiora from '@/uni_modules/Sandrox-Sfiora/js_sdk/index.js';

它提供 Promise 返回值和带字符串错误码的 SfioraError。经典 uni-app 和 x Vapor 使用此入口即可,无须自行处理原生回调或 JSON。

Android VDOM 使用直接 UTS 导入:

import * as sfiora from '@/uni_modules/Sandrox-Sfiora'

直接 UTS 方法返回 Promise<UTSJSONObject> 等 UTS 类型;错误对象保留 codemessagerecoverablenativeError。这是独立的接入路径,不能把本文的 Vapor JavaScript 导入方式照搬到 VDOM,也不据此推定 iOS VDOM 兼容性。

Legacy:经典 uni-app 原生插件

下载发行版的 legacy ZIP,将其中的 Sandrox-Sfiora 目录放入项目的 nativeplugins,然后在 manifest.json 的 App 原生插件配置中选择这个本地插件。

import * as sfiora from '@/nativeplugins/Sandrox-Sfiora/js_sdk/index.js';

下面经典 uni-app 示例只需替换这一行导入,API 与 UTS 版本一致。原生模块名是 Sfiora,但业务代码使用公共 SDK,不需要直接调用 uni.requireNativePlugin

权限、签名与自定义基座

Android 插件声明 android.permission.NFC,并将 NFC 硬件声明为可选,因此无 NFC 的设备也可以安装应用。NFC 没有运行时权限弹框;使用前通过 getCapabilities() 检查设备支持和系统 NFC 开关。

iOS 应用需要 NFC 用途说明、TAG entitlement,以及包含 Near Field Communication Tag Reading 能力的 App ID 和签名描述文件。用途说明应描述实际应用用途。

经典 uni-app 在 manifest.json 中合并以下配置,保留已有的其他权限:

{
  "app-plus": {
    "distribute": {
      "ios": {
        "privacyDescription": {
          "NFCReaderUsageDescription": "读取和写入您选择的 NFC 标签。"
        },
        "capabilities": {
          "entitlements": {
            "com.apple.developer.nfc.readersession.formats": ["TAG"]
          }
        }
      }
    }
  }
}

uni-app x 在项目根目录的 Info.plist 中添加用途说明:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NFCReaderUsageDescription</key>
    <string>读取和写入您选择的 NFC 标签。</string>
</dict>
</plist>

nativeResources/ios/UniApp.entitlements 中添加:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.nfc.readersession.formats</key>
    <array>
        <string>TAG</string>
    </array>
</dict>
</plist>

已有这两个文件时合并键值,不要覆盖其他插件的配置。原生资源目录规则见 DCloud iOS 原生配置。使用 FeliCa 轮询时,还需在 Info.plistcom.apple.developer.nfc.readersession.felica.systemcodes 中填写应用支持的真实系统码;ISO 7816 AID 配置也由宿主按目标标签提供。

安装插件、修改原生权限或升级插件后,制作包含当前插件的自定义基座,或重新打包完整 App,再选择该基座运行到真机。基座需要匹配 HBuilderX、平台和插件版本。只修改页面布局或调用参数时,可以在同一匹配基座上重新运行页面;原生模块、权限和签名变化需要重新打包。

开始读取

先由用户启动操作,再靠近标签;读写期间保持应用前台并稳定贴住标签。每次 startScan 只完成一次读取,不是持续事件订阅。

经典 uni-app 可在页面的方法中调用:

import * as sfiora from '@/uni_modules/Sandrox-Sfiora/js_sdk/index.js';

export async function readTag() {
  const capability = await sfiora.getCapabilities();
  if (!capability.supported || !capability.enabled) {
    throw new Error('当前设备不支持 NFC,或 NFC 尚未开启。');
  }
  try {
    return await sfiora.startScan({ mode: 'automatic', timeoutMilliseconds: 30000 });
  } catch (error) {
    if (error instanceof sfiora.SfioraError && error.code === 'USER_CANCELLED') {
      return null;
    }
    throw error;
  }
}

uni-app x Vapor 的 .uvue 页面可使用下面的 UTS 方法。调用方将返回值绑定到自己的页面,并处理失败结果:

import * as sfiora from '@/uni_modules/Sandrox-Sfiora/js_sdk/index.js'

async function readTag(): Promise<UTSJSONObject> {
  const capability: UTSJSONObject = await sfiora.getCapabilities()
  const supported = capability['supported'] as boolean | null
  const enabled = capability['enabled'] as boolean | null
  if (supported != true || enabled != true) {
    throw new Error('当前设备不支持 NFC,或 NFC 尚未开启。')
  }
  return await sfiora.startScan({ mode: 'automatic', timeoutMilliseconds: 30000 })
}

三种读取模式:

mode 行为
automatic 默认模式;发现标签,并在可用时读取 NDEF
ndef 要求 NDEF;iOS 使用系统 NDEF 兼容读取会话,结果可能没有标签 ID
discover 只获取标签信息,不主动读取 NDEF

结果包含 idtechnologiesndefwarnings。读取文本用 tag.ndef.records 中的 text,URI 用 uri,二进制内容用 payloadBase64。经典 uni-app 可用可选链访问;UTS 使用 UTSJSONObject 的访问方法或明确的类型转换。

发现标签成功并不代表 NDEF 读取成功,需检查 ndef.statusndef.readErrorwarnings。无值或读取错误不能被当成业务上的“空标签”。两端可读的技术信息和 ID 可能不同,不能假设每种模式都会返回 ID。

替换 NDEF 消息并验证

下面的方法沿用前面的 sfiora 导入,从用户点击事件调用,并在调用处处理 Promise 失败:

export async function replaceTag() {
  return await sfiora.writeNdef({
    records: [{ kind: 'text', text: 'Hello from Sfiora', languageCode: 'en' }],
  }, { timeoutMilliseconds: 30000 });
}

这是替换整条 NDEF 消息,旧记录会被覆盖。标签必须已经支持 NDEF、可写且容量足够。成功结果包含 verified: truebytesWrittenrecordCount 和回读的 tag;验证比较完整 NDEF 消息的序列化字节。

写入没有事务回滚保证。写入开始后失去接触、取消或验证失败,标签可能保留旧内容,也可能变成新内容、部分内容或空内容。失败后重新读取,才能判断标签实际状态;不能把“报错”理解成“原内容一定没变”。

NDEF 记录格式

records 必须非空,可包含多条记录。下面四种记录既可单独使用,也可组合成一条消息:

const records = [
  { kind: 'text', text: '你好', languageCode: 'zh-Hans', encoding: 'UTF-8' },
  { kind: 'uri', uri: 'https://example.com' },
  { kind: 'mime', mediaType: 'application/octet-stream', payloadBase64: 'AQID' },
  { kind: 'external', domain: 'example.com', type: 'initialized', payloadBase64: 'AQID' },
];

Text 需要 languageCode,默认 UTF-8,也支持 UTF-16。语言码属于 NDEF 格式,不是正文;某些工具的原始值会把语言码和正文一起显示,业务应读取解析后的 text。网址建议使用带 https:// 等协议的 URI 记录。

MIME 和 External Type 的 payloadBase64 表达原始字节。例如 AQID 写入三个字节 01 02 03,不是写入四个字符。若要写入一段字符串,先按应用选择的编码转成字节,再转 Base64。各类记录都支持可选的 identifierBase64

保留或初始化

export async function initializeTag() {
  const marker = { domain: 'example.com', type: 'initialized' };
  return await sfiora.initializeNdef({
    records: [{
      kind: 'external',
      domain: marker.domain,
      type: marker.type,
      payloadBase64: 'AQID',
    }],
  }, marker, { timeoutMilliseconds: 30000 });
}

example.com 换成应用自己的小写域名和类型约定。待写入消息必须包含恰好一条匹配 marker 的 External Type 记录,插件不会自动补标记。

  • 已有消息包含相同 domain/type:返回 action: 'preserved',不写入,返回已有的 tag;没有 verified 和写入字节数字段。标记记录的 payload 不参与匹配,也不会因传入新 payload 而更新。
  • 没有匹配标记:替换整条消息并回读验证,返回 action: 'initialized'verified: true。已有其他内容但没有这个标记的标签也会被覆盖。
  • 无法检查现有消息时返回错误,不把读取失败当成空白。未格式化的出厂标签不会由此自动格式化。

这是一种应用约定的保留机制,不会把标签设为只读,也不是密码保护或身份认证。其他写入工具仍然可以覆盖标记;身份校验、授权、加密和业务格式由宿主负责。

在 x Vapor 中,写入和初始化使用相同消息对象,方法返回 Promise<UTSJSONObject>。例如将方法声明为 async function replaceTag(): Promise<UTSJSONObject>,读取 action 时用 result['action'] as string | null

取消、页面生命周期与按钮状态

所有平台提供:

方法 返回值
getCapabilities() 设备 NFC 支持、启用情况和能力
startScan(options?) 单次标签快照
writeNdef(message, options?) 已写入并验证的结果
initializeNdef(message, marker, options?) preservedinitialized 结果
cancelScan() Promise<void>
cancelWrite() Promise<void>,也取消初始化
isScanning() Promise<boolean>
isWriting() Promise<boolean>
waitForIdle(options?) Promise<void>,有上限地等待本桥接实例空闲

取消没有进行中的操作不会报错。取消方法完成只代表请求已送达,原始读写 Promise 的失败仍需处理,也不代表系统 NFC 面板已经收起。

页面应同时禁用读取和写入入口,条件是“本地有未完成调用,或 isScanning() / isWriting() 任一为 true”。iOS 成功结果可能在系统面板收起前返回,因此不能在 finally 中直接恢复按钮;继续查询状态,确认两项都为 false 后再恢复。状态查询失败应显示错误,不按 idle 处理。

await sfiora.waitForIdle({ timeoutMilliseconds: 5000 }) 可统一完成等待,legacy 的 JS SDK、UTS JS SDK 和直接 UTS API 均支持。超时参数为 1–60000 的整数,默认 5000;查询失败原样返回错误,超时返回 SESSION_CLOSE_TIMEOUT,即使查询没有回调也会结束等待。它不取消当前操作、不预留下一次会话,也不会在超时后释放原生占用;用户可刷新真实状态后再试。

原生关闭超过 5 秒时可先交付待处理结果,实际关闭前仍保持忙碌。Android 的读取和初始化判断均使用实时 NDEF 内容,当前空消息不回退到发现时缓存。

拥有当前操作的页面在 onHide / onUnload 中取消操作,并忽略页面离开后的迟到结果。不要让没有发起操作的页面随意取消另一个页面的会话。原生读写在进程内互斥,重复启动会返回忙错误。

参数与错误处理

读取参数 默认值 说明
timeoutMilliseconds 30000 100060000 的整数,单位毫秒
android.presentation managed none 关闭 Android 读取面板
android.deepReadEnabled false 对支持的标签启用额外只读协议探测
android.presenceCheckDelayMilliseconds 250 505000 的整数
ios.pollingTechnologies ['iso14443', 'iso15693'] 非空数组;添加 iso18092 需配置 FeliCa 系统码
messages 内置提示语 自定义时提供完整的 NfcScanMessages

写入选项只有 timeoutMilliseconds(范围和默认值同上)及完整的 NfcWriteMessages,不接受读取专用选项。Android 桥接写入使用操作面板,iOS 使用系统 NFC 面板。未知参数、错误类型或不完整的自定义提示语会返回 INVALID_OPTIONS。完整字段见包内 js_sdk/index.d.tscontract/types.d.ts

错误包含 codemessagerecoverable 和可选 nativeError。按字符串 code 分支,不依赖设备原生错误文案:

错误码 处理方向
NFC_UNSUPPORTED / NFC_DISABLED 检查硬件支持或引导开启 NFC
SCAN_BUSY / WRITE_BUSY 等当前会话释放,避免连续自动重试
USER_CANCELLED 正常结束这次交互
SESSION_CLOSE_TIMEOUT 保留原生状态门控,允许刷新,不能假定会话已关闭
SCAN_TIMEOUT / WRITE_TIMEOUT / TAG_LOST 调整贴合位置后由用户重试
UNSUPPORTED_TAG / TAG_READ_ONLY / NDEF_CAPACITY_EXCEEDED 更换合适的可写 NDEF 标签或缩小消息
READ_FAILED 检查读取错误,不能按空标签继续处理
WRITE_FAILED / WRITE_VERIFICATION_FAILED 重新读取确认标签现状
INVALID_OPTIONS 修正参数
INTERNAL_ERROR 检查基座、模块加载、页面生命周期及原生错误

recoverable 只是重试提示,不保证标签未改变;写入期间的取消、超时和丢失标签也遵循前面的写入不确定性说明。

常见接入问题

  • 提示模块不存在:核对安装目录、legacy 原生插件勾选、导入路径,以及运行时选择的自定义基座。只更新 JS 不能补入缺失的原生模块。
  • iOS 会话无法开始:核对用途说明、最终签名中的 TAG entitlement、App ID 与描述文件;修改后重打基座或 App。
  • 手机打开了系统标签页面:先启动 Sfiora 操作再贴标签。空闲时的系统 NFC 分发属于宿主和系统行为;应用若需要处理相关 Intent,应在宿主层处理。
  • 取消后按钮暂时不可点:确认正在等待真实会话释放;按钮状态应与原生状态一致。
  • 读到技术信息却不能写:能发现某种技术不等于能写该标签;写入只面向已支持 NDEF 的可写标签。

隐私、能力边界与许可

插件无广告、统计或推广 SDK,不向作者服务器上传标签内容,也不替应用持久化业务数据;写入到标签的数据和宿主后续保存的数据由调用方决定。

Sfiora 不提供标签格式化、永久锁定、密码修改、门禁卡复制、卡模拟或任意 APDU/私有区写入。标记与读取出的 ID 不构成身份真实性证明。

源码与问题反馈 · 版本记录 · Apache License 2.0

反馈时提供插件版本、HBuilderX 版本、宿主模式、系统与设备、操作和结构化错误;标签私密内容请先去除。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android NFC 权限;iOS NFCReaderUsageDescription 和 TAG entitlement。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集、存储或上传标签数据;读写内容由调用方决定。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

  1. Definitions.

    "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.

    "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.

    "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.

    "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.

    "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.

    "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.

    "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).

    "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.

    "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."

    "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.

  2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.

  3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.

  4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:

    (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and

    (b) You must cause any modified files to carry prominent notices stating that You changed the files; and

    (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and

    (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.

    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.

  5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.

  6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.

  7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.

  8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.

  9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.

    END OF TERMS AND CONDITIONS

    APPENDIX: How to apply the Apache License to your work.

    To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.

    Copyright [yyyy] [name of copyright owner]

    Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.